1/* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "socket_client.h" 17 18#include "event_handler.h" 19 20#include "devicestatus_define.h" 21#include "intention_identity.h" 22#include "socket_params.h" 23#include "time_cost_chk.h" 24 25#undef LOG_TAG 26#define LOG_TAG "SocketClient" 27 28namespace OHOS { 29namespace Msdp { 30namespace DeviceStatus { 31namespace { 32const std::string THREAD_NAME { "os_ClientEventHandler" }; 33} 34 35SocketClient::SocketClient(std::shared_ptr<ITunnelClient> tunnel) 36 : tunnel_(tunnel) 37{ 38 auto runner = AppExecFwk::EventRunner::Create(THREAD_NAME); 39 eventHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner); 40} 41 42bool SocketClient::RegisterEvent(MessageId id, std::function<int32_t(const StreamClient&, NetPacket&)> callback) 43{ 44 std::lock_guard guard(lock_); 45 auto [_, inserted] = callbacks_.emplace(id, callback); 46 return inserted; 47} 48 49void SocketClient::Start() 50{ 51 CALL_DEBUG_ENTER; 52 Reconnect(); 53} 54 55void SocketClient::Stop() 56{} 57 58bool SocketClient::Connect() 59{ 60 CALL_DEBUG_ENTER; 61 if (socket_ != nullptr) { 62 return true; 63 } 64 auto socket = SocketConnection::Connect( 65 [this] { return this->Socket(); }, 66 [this](NetPacket &pkt) { this->OnPacket(pkt); }, 67 [this] { this->OnDisconnected(); }); 68 CHKPF(socket); 69 CHKPF(eventHandler_); 70 auto errCode = eventHandler_->AddFileDescriptorListener(socket->GetFd(), 71 AppExecFwk::FILE_DESCRIPTOR_INPUT_EVENT, socket, "DeviceStatusTask"); 72 if (errCode != ERR_OK) { 73 FI_HILOGE("AddFileDescriptorListener(%{public}d) failed (%{public}u)", socket->GetFd(), errCode); 74 return false; 75 } 76 socket_ = socket; 77 FI_HILOGD("SocketClient started successfully"); 78 if (funConnected_ != nullptr) { 79 FI_HILOGI("Execute funConnected"); 80 funConnected_(); 81 } 82 return true; 83} 84 85int32_t SocketClient::Socket() 86{ 87 CALL_DEBUG_ENTER; 88 std::shared_ptr<ITunnelClient> tunnel = tunnel_.lock(); 89 CHKPR(tunnel, RET_ERR); 90 AllocSocketPairParam param { GetProgramName(), CONNECT_MODULE_TYPE_FI_CLIENT }; 91 AllocSocketPairReply reply; 92 93 int32_t ret = tunnel->Control(Intention::SOCKET, SocketAction::SOCKET_ACTION_CONNECT, param, reply); 94 if (ret != RET_OK) { 95 FI_HILOGE("ITunnelClient::Control fail"); 96 return -1; 97 } 98 FI_HILOGD("Connected to intention service (%{public}d)", reply.socketFd); 99 return reply.socketFd; 100} 101 102void SocketClient::OnPacket(NetPacket &pkt) 103{ 104 CALL_DEBUG_ENTER; 105 std::lock_guard guard(lock_); 106 OnMsgHandler(*this, pkt); 107} 108 109void SocketClient::OnDisconnected() 110{ 111 CALL_DEBUG_ENTER; 112 std::lock_guard guard(lock_); 113 if (socket_ != nullptr) { 114 eventHandler_->RemoveFileDescriptorListener(socket_->GetFd()); 115 eventHandler_->RemoveAllEvents(); 116 socket_.reset(); 117 } 118 if (funDisconnected_ != nullptr) { 119 FI_HILOGI("Execute funDisconnected"); 120 funDisconnected_(); 121 } 122 if (!eventHandler_->PostTask([this] { this->Reconnect(); }, CLIENT_RECONNECT_COOLING_TIME)) { 123 FI_HILOGE("Failed to post reconnection task"); 124 } 125} 126 127void SocketClient::Reconnect() 128{ 129 std::lock_guard guard(lock_); 130 if (Connect()) { 131 return; 132 } 133 if (!eventHandler_->PostTask([this] { this->Reconnect(); }, CLIENT_RECONNECT_COOLING_TIME)) { 134 FI_HILOGE("Failed to post reconnection task"); 135 } 136} 137 138void SocketClient::OnMsgHandler(const StreamClient &client, NetPacket &pkt) 139{ 140 CALL_DEBUG_ENTER; 141 MessageId id = pkt.GetMsgId(); 142 TimeCostChk chk("SocketClient::OnMsgHandler", "overtime 300(us)", MAX_OVER_TIME, id); 143 auto iter = callbacks_.find(id); 144 if (iter == callbacks_.end()) { 145 FI_HILOGE("Unknown msg id:%{public}d", id); 146 return; 147 } 148 int32_t ret = iter->second(client, pkt); 149 if (ret < 0) { 150 FI_HILOGE("Msg handling failed, id:%{public}d, ret:%{public}d", id, ret); 151 } 152} 153 154void SocketClient::RegisterConnectedFunction(ConnectCallback funConnected) 155{ 156 funConnected_ = funConnected; 157} 158 159void SocketClient::RegisterDisconnectedFunction(ConnectCallback funDisconnected) 160{ 161 funDisconnected_ = funDisconnected; 162} 163} // namespace DeviceStatus 164} // namespace Msdp 165} // namespace OHOS