1f857971dSopenharmony_ci/* 2f857971dSopenharmony_ci * Copyright (c) 2021-2023 Huawei Device Co., Ltd. 3f857971dSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4f857971dSopenharmony_ci * you may not use this file except in compliance with the License. 5f857971dSopenharmony_ci * You may obtain a copy of the License at 6f857971dSopenharmony_ci * 7f857971dSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8f857971dSopenharmony_ci * 9f857971dSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10f857971dSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11f857971dSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12f857971dSopenharmony_ci * See the License for the specific language governing permissions and 13f857971dSopenharmony_ci * limitations under the License. 14f857971dSopenharmony_ci */ 15f857971dSopenharmony_ci 16f857971dSopenharmony_ci#include "client.h" 17f857971dSopenharmony_ci 18f857971dSopenharmony_ci#include <cinttypes> 19f857971dSopenharmony_ci#include <condition_variable> 20f857971dSopenharmony_ci 21f857971dSopenharmony_ci#include "devicestatus_client.h" 22f857971dSopenharmony_ci#include "fd_listener.h" 23f857971dSopenharmony_ci#include "fi_log.h" 24f857971dSopenharmony_ci#include "proto.h" 25f857971dSopenharmony_ci#include "time_cost_chk.h" 26f857971dSopenharmony_ci#include "include/util.h" 27f857971dSopenharmony_ci 28f857971dSopenharmony_ci#undef LOG_TAG 29f857971dSopenharmony_ci#define LOG_TAG "Client" 30f857971dSopenharmony_ci 31f857971dSopenharmony_cinamespace OHOS { 32f857971dSopenharmony_cinamespace Msdp { 33f857971dSopenharmony_cinamespace DeviceStatus { 34f857971dSopenharmony_cinamespace { 35f857971dSopenharmony_ciconst std::string THREAD_NAME { "os_ClientEventHandler" }; 36f857971dSopenharmony_ci} // namespace 37f857971dSopenharmony_ci 38f857971dSopenharmony_ciusing namespace AppExecFwk; 39f857971dSopenharmony_ciClient::~Client() 40f857971dSopenharmony_ci{ 41f857971dSopenharmony_ci CALL_DEBUG_ENTER; 42f857971dSopenharmony_ci Stop(); 43f857971dSopenharmony_ci} 44f857971dSopenharmony_ci 45f857971dSopenharmony_civoid Client::SetEventHandler(EventHandlerPtr eventHandler) 46f857971dSopenharmony_ci{ 47f857971dSopenharmony_ci CHKPV(eventHandler); 48f857971dSopenharmony_ci eventHandler_ = eventHandler; 49f857971dSopenharmony_ci} 50f857971dSopenharmony_ci 51f857971dSopenharmony_civoid Client::MarkIsEventHandlerChanged(EventHandlerPtr eventHandler) 52f857971dSopenharmony_ci{ 53f857971dSopenharmony_ci CHKPV(eventHandler); 54f857971dSopenharmony_ci CHKPV(eventHandler_); 55f857971dSopenharmony_ci auto currentRunner = eventHandler_->GetEventRunner(); 56f857971dSopenharmony_ci CHKPV(currentRunner); 57f857971dSopenharmony_ci auto newEventRunner = eventHandler->GetEventRunner(); 58f857971dSopenharmony_ci CHKPV(newEventRunner); 59f857971dSopenharmony_ci isEventHandlerChanged_ = false; 60f857971dSopenharmony_ci if (currentRunner->GetRunnerThreadName() != newEventRunner->GetRunnerThreadName()) { 61f857971dSopenharmony_ci isEventHandlerChanged_ = true; 62f857971dSopenharmony_ci FI_HILOGD("Event handler changed"); 63f857971dSopenharmony_ci } 64f857971dSopenharmony_ci FI_HILOGD("Current handler name:%{public}s, New handler name:%{public}s", 65f857971dSopenharmony_ci currentRunner->GetRunnerThreadName().c_str(), newEventRunner->GetRunnerThreadName().c_str()); 66f857971dSopenharmony_ci} 67f857971dSopenharmony_ci 68f857971dSopenharmony_cibool Client::SendMessage(const NetPacket &pkt) const 69f857971dSopenharmony_ci{ 70f857971dSopenharmony_ci return SendMsg(pkt); 71f857971dSopenharmony_ci} 72f857971dSopenharmony_ci 73f857971dSopenharmony_cibool Client::GetCurrentConnectedStatus() const 74f857971dSopenharmony_ci{ 75f857971dSopenharmony_ci return GetConnectedStatus(); 76f857971dSopenharmony_ci} 77f857971dSopenharmony_ci 78f857971dSopenharmony_ciIClientPtr Client::GetSharedPtr() 79f857971dSopenharmony_ci{ 80f857971dSopenharmony_ci return shared_from_this(); 81f857971dSopenharmony_ci} 82f857971dSopenharmony_ci 83f857971dSopenharmony_cibool Client::Start() 84f857971dSopenharmony_ci{ 85f857971dSopenharmony_ci CALL_DEBUG_ENTER; 86f857971dSopenharmony_ci auto callback = [this](const StreamClient &client, NetPacket &pkt) { 87f857971dSopenharmony_ci this->OnMsgHandler(client, pkt); 88f857971dSopenharmony_ci }; 89f857971dSopenharmony_ci if (!StartClient(callback)) { 90f857971dSopenharmony_ci FI_HILOGE("Client startup failed"); 91f857971dSopenharmony_ci Stop(); 92f857971dSopenharmony_ci return false; 93f857971dSopenharmony_ci } 94f857971dSopenharmony_ci if (!StartEventRunner()) { 95f857971dSopenharmony_ci FI_HILOGE("Start runner failed"); 96f857971dSopenharmony_ci Stop(); 97f857971dSopenharmony_ci return false; 98f857971dSopenharmony_ci } 99f857971dSopenharmony_ci FI_HILOGD("Client started successfully"); 100f857971dSopenharmony_ci return true; 101f857971dSopenharmony_ci} 102f857971dSopenharmony_ci 103f857971dSopenharmony_cibool Client::StartEventRunner() 104f857971dSopenharmony_ci{ 105f857971dSopenharmony_ci CALL_DEBUG_ENTER; 106f857971dSopenharmony_ci CHK_PID_AND_TID(); 107f857971dSopenharmony_ci auto runner = AppExecFwk::EventRunner::Create(THREAD_NAME); 108f857971dSopenharmony_ci CHKPF(runner); 109f857971dSopenharmony_ci eventHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner); 110f857971dSopenharmony_ci 111f857971dSopenharmony_ci FI_HILOGI("Create event handler, thread name:%{public}s", runner->GetRunnerThreadName().c_str()); 112f857971dSopenharmony_ci 113f857971dSopenharmony_ci if (hasConnected_ && fd_ >= 0) { 114f857971dSopenharmony_ci if (isListening_) { 115f857971dSopenharmony_ci FI_HILOGI("File fd is in listening"); 116f857971dSopenharmony_ci return true; 117f857971dSopenharmony_ci } 118f857971dSopenharmony_ci if (!AddFdListener(fd_)) { 119f857971dSopenharmony_ci FI_HILOGE("Add fd listener failed"); 120f857971dSopenharmony_ci return false; 121f857971dSopenharmony_ci } 122f857971dSopenharmony_ci } else { 123f857971dSopenharmony_ci if (!eventHandler_->PostTask([this] { this->OnReconnect(); }, CLIENT_RECONNECT_COOLING_TIME)) { 124f857971dSopenharmony_ci FI_HILOGE("Send reconnect event failed"); 125f857971dSopenharmony_ci return false; 126f857971dSopenharmony_ci } 127f857971dSopenharmony_ci } 128f857971dSopenharmony_ci return true; 129f857971dSopenharmony_ci} 130f857971dSopenharmony_ci 131f857971dSopenharmony_cibool Client::AddFdListener(int32_t fd) 132f857971dSopenharmony_ci{ 133f857971dSopenharmony_ci CALL_DEBUG_ENTER; 134f857971dSopenharmony_ci if (fd < 0) { 135f857971dSopenharmony_ci FI_HILOGE("Invalid fd:%{public}d", fd); 136f857971dSopenharmony_ci return false; 137f857971dSopenharmony_ci } 138f857971dSopenharmony_ci CHKPF(eventHandler_); 139f857971dSopenharmony_ci auto fdListener = std::make_shared<FdListener>(GetSharedPtr()); 140f857971dSopenharmony_ci auto errCode = eventHandler_->AddFileDescriptorListener(fd, FILE_DESCRIPTOR_INPUT_EVENT, fdListener, 141f857971dSopenharmony_ci "DeviceStatusTask"); 142f857971dSopenharmony_ci if (errCode != ERR_OK) { 143f857971dSopenharmony_ci FI_HILOGE("Add fd listener failed, fd:%{public}d, code:%{public}u, str:%{public}s", fd, errCode, 144f857971dSopenharmony_ci GetErrorStr(errCode).c_str()); 145f857971dSopenharmony_ci return false; 146f857971dSopenharmony_ci } 147f857971dSopenharmony_ci isRunning_ = true; 148f857971dSopenharmony_ci FI_HILOGI("serverFd:%{public}d was listening, mask:%{public}u," PRIu64, fd, FILE_DESCRIPTOR_INPUT_EVENT); 149f857971dSopenharmony_ci return true; 150f857971dSopenharmony_ci} 151f857971dSopenharmony_ci 152f857971dSopenharmony_cibool Client::DelFdListener(int32_t fd) 153f857971dSopenharmony_ci{ 154f857971dSopenharmony_ci CALL_DEBUG_ENTER; 155f857971dSopenharmony_ci CHKPF(eventHandler_); 156f857971dSopenharmony_ci if (fd >= 0) { 157f857971dSopenharmony_ci eventHandler_->RemoveFileDescriptorListener(fd); 158f857971dSopenharmony_ci FI_HILOGI("Remove file descriptor listener success"); 159f857971dSopenharmony_ci } else { 160f857971dSopenharmony_ci FI_HILOGE("Invalid fd:%{public}d", fd); 161f857971dSopenharmony_ci } 162f857971dSopenharmony_ci auto runner = eventHandler_->GetEventRunner(); 163f857971dSopenharmony_ci CHKPF(runner); 164f857971dSopenharmony_ci if (runner->GetRunnerThreadName() == THREAD_NAME) { 165f857971dSopenharmony_ci eventHandler_->RemoveAllEvents(); 166f857971dSopenharmony_ci FI_HILOGI("Remove all events success"); 167f857971dSopenharmony_ci } 168f857971dSopenharmony_ci isRunning_ = false; 169f857971dSopenharmony_ci return true; 170f857971dSopenharmony_ci} 171f857971dSopenharmony_ci 172f857971dSopenharmony_civoid Client::OnPacket(NetPacket &pkt) 173f857971dSopenharmony_ci{ 174f857971dSopenharmony_ci recvFun_(*this, pkt); 175f857971dSopenharmony_ci} 176f857971dSopenharmony_ci 177f857971dSopenharmony_civoid Client::OnRecvMsg(const char *buf, size_t size) 178f857971dSopenharmony_ci{ 179f857971dSopenharmony_ci CHKPV(buf); 180f857971dSopenharmony_ci if (size == 0 || size > MAX_PACKET_BUF_SIZE) { 181f857971dSopenharmony_ci FI_HILOGE("Invalid input param size, size:%{public}zu", size); 182f857971dSopenharmony_ci return; 183f857971dSopenharmony_ci } 184f857971dSopenharmony_ci if (!circBuf_.Write(buf, size)) { 185f857971dSopenharmony_ci FI_HILOGW("Write data failed, size:%{public}zu", size); 186f857971dSopenharmony_ci } 187f857971dSopenharmony_ci OnReadPackets(circBuf_, [this](NetPacket &pkt) { this->OnPacket(pkt); }); 188f857971dSopenharmony_ci} 189f857971dSopenharmony_ci 190f857971dSopenharmony_ciint32_t Client::Reconnect() 191f857971dSopenharmony_ci{ 192f857971dSopenharmony_ci return StartConnect(); 193f857971dSopenharmony_ci} 194f857971dSopenharmony_ci 195f857971dSopenharmony_civoid Client::OnReconnect() 196f857971dSopenharmony_ci{ 197f857971dSopenharmony_ci if (Reconnect() == RET_OK) { 198f857971dSopenharmony_ci FI_HILOGI("Reconnect ok"); 199f857971dSopenharmony_ci return; 200f857971dSopenharmony_ci } 201f857971dSopenharmony_ci CHKPV(eventHandler_); 202f857971dSopenharmony_ci if (!eventHandler_->PostTask([this] { this->OnReconnect(); }, CLIENT_RECONNECT_COOLING_TIME)) { 203f857971dSopenharmony_ci FI_HILOGE("Post reconnect event failed"); 204f857971dSopenharmony_ci } 205f857971dSopenharmony_ci} 206f857971dSopenharmony_ci 207f857971dSopenharmony_civoid Client::OnDisconnect() 208f857971dSopenharmony_ci{ 209f857971dSopenharmony_ci OnDisconnected(); 210f857971dSopenharmony_ci} 211f857971dSopenharmony_ci 212f857971dSopenharmony_civoid Client::RegisterConnectedFunction(ConnectCallback function) 213f857971dSopenharmony_ci{ 214f857971dSopenharmony_ci funConnected_ = function; 215f857971dSopenharmony_ci} 216f857971dSopenharmony_ci 217f857971dSopenharmony_civoid Client::RegisterDisconnectedFunction(ConnectCallback fun) 218f857971dSopenharmony_ci{ 219f857971dSopenharmony_ci funDisconnected_ = fun; 220f857971dSopenharmony_ci} 221f857971dSopenharmony_ci 222f857971dSopenharmony_civoid Client::OnDisconnected() 223f857971dSopenharmony_ci{ 224f857971dSopenharmony_ci CALL_DEBUG_ENTER; 225f857971dSopenharmony_ci FI_HILOGI("Disconnected from server, fd:%{public}d", fd_); 226f857971dSopenharmony_ci hasConnected_ = false; 227f857971dSopenharmony_ci isListening_ = false; 228f857971dSopenharmony_ci if (funDisconnected_ != nullptr) { 229f857971dSopenharmony_ci FI_HILOGI("Execute funDisconnected"); 230f857971dSopenharmony_ci funDisconnected_(); 231f857971dSopenharmony_ci } 232f857971dSopenharmony_ci if (!DelFdListener(fd_)) { 233f857971dSopenharmony_ci FI_HILOGW("Delete fd listener failed"); 234f857971dSopenharmony_ci } 235f857971dSopenharmony_ci StreamClient::Stop(); 236f857971dSopenharmony_ci if (hasClient_ && eventHandler_ != nullptr) { 237f857971dSopenharmony_ci if (!eventHandler_->PostTask([this] { this->OnReconnect(); }, CLIENT_RECONNECT_COOLING_TIME)) { 238f857971dSopenharmony_ci FI_HILOGE("Send reconnect event task failed"); 239f857971dSopenharmony_ci } 240f857971dSopenharmony_ci } 241f857971dSopenharmony_ci} 242f857971dSopenharmony_ci 243f857971dSopenharmony_civoid Client::OnConnected() 244f857971dSopenharmony_ci{ 245f857971dSopenharmony_ci CALL_DEBUG_ENTER; 246f857971dSopenharmony_ci FI_HILOGI("Connection to server succeeded, fd:%{public}d", GetFd()); 247f857971dSopenharmony_ci hasConnected_ = true; 248f857971dSopenharmony_ci if (funConnected_ != nullptr) { 249f857971dSopenharmony_ci FI_HILOGI("Execute funConnected"); 250f857971dSopenharmony_ci funConnected_(); 251f857971dSopenharmony_ci } 252f857971dSopenharmony_ci if (hasClient_ && !isRunning_ && fd_ >= 0 && eventHandler_ != nullptr) { 253f857971dSopenharmony_ci if (!AddFdListener(fd_)) { 254f857971dSopenharmony_ci FI_HILOGE("Add fd listener failed"); 255f857971dSopenharmony_ci return; 256f857971dSopenharmony_ci } 257f857971dSopenharmony_ci isListening_ = true; 258f857971dSopenharmony_ci } 259f857971dSopenharmony_ci} 260f857971dSopenharmony_ci 261f857971dSopenharmony_ciint32_t Client::Socket() 262f857971dSopenharmony_ci{ 263f857971dSopenharmony_ci CALL_DEBUG_ENTER; 264f857971dSopenharmony_ci return -1; 265f857971dSopenharmony_ci} 266f857971dSopenharmony_ci 267f857971dSopenharmony_civoid Client::Stop() 268f857971dSopenharmony_ci{ 269f857971dSopenharmony_ci CALL_DEBUG_ENTER; 270f857971dSopenharmony_ci StreamClient::Stop(); 271f857971dSopenharmony_ci isRunning_ = false; 272f857971dSopenharmony_ci if (eventHandler_ != nullptr) { 273f857971dSopenharmony_ci auto runner = eventHandler_->GetEventRunner(); 274f857971dSopenharmony_ci CHKPV(runner); 275f857971dSopenharmony_ci if (runner->GetRunnerThreadName() == THREAD_NAME) { 276f857971dSopenharmony_ci runner->Stop(); 277f857971dSopenharmony_ci eventHandler_->RemoveAllEvents(); 278f857971dSopenharmony_ci eventHandler_->RemoveAllFileDescriptorListeners(); 279f857971dSopenharmony_ci FI_HILOGI("Remove all file descriptor listeners success"); 280f857971dSopenharmony_ci } 281f857971dSopenharmony_ci } 282f857971dSopenharmony_ci} 283f857971dSopenharmony_ci 284f857971dSopenharmony_civoid Client::OnMsgHandler(const StreamClient &client, NetPacket &pkt) 285f857971dSopenharmony_ci{ 286f857971dSopenharmony_ci CALL_DEBUG_ENTER; 287f857971dSopenharmony_ci auto id = pkt.GetMsgId(); 288f857971dSopenharmony_ci TimeCostChk chk("Client::OnMsgHandler", "overtime 300(us)", MAX_OVER_TIME, id); 289f857971dSopenharmony_ci auto callback = GetMsgCallback(id); 290f857971dSopenharmony_ci if (callback == nullptr) { 291f857971dSopenharmony_ci FI_HILOGE("Unknown msg id:%{public}d", id); 292f857971dSopenharmony_ci return; 293f857971dSopenharmony_ci } 294f857971dSopenharmony_ci int32_t ret = (*callback)(client, pkt); 295f857971dSopenharmony_ci if (ret < 0) { 296f857971dSopenharmony_ci FI_HILOGE("Msg handling failed, id:%{public}d, ret:%{public}d", id, ret); 297f857971dSopenharmony_ci return; 298f857971dSopenharmony_ci } 299f857971dSopenharmony_ci} 300f857971dSopenharmony_ci 301f857971dSopenharmony_ciconst std::string& Client::GetErrorStr(ErrCode code) const 302f857971dSopenharmony_ci{ 303f857971dSopenharmony_ci const static std::string defErrString = "Unknown event handler error!"; 304f857971dSopenharmony_ci const static std::map<ErrCode, std::string> mapStrings = { 305f857971dSopenharmony_ci { ERR_OK, "ERR_OK" }, 306f857971dSopenharmony_ci { EVENT_HANDLER_ERR_INVALID_PARAM, "Invalid parameters" }, 307f857971dSopenharmony_ci { EVENT_HANDLER_ERR_NO_EVENT_RUNNER, "Have not set event runner yet" }, 308f857971dSopenharmony_ci { EVENT_HANDLER_ERR_FD_NOT_SUPPORT, "Not support to listen file descriptors" }, 309f857971dSopenharmony_ci { EVENT_HANDLER_ERR_FD_ALREADY, "File descriptor is already in listening" }, 310f857971dSopenharmony_ci { EVENT_HANDLER_ERR_FD_FAILED, "Failed to listen file descriptor" }, 311f857971dSopenharmony_ci { EVENT_HANDLER_ERR_RUNNER_NO_PERMIT, "No permit to start or stop deposited event runner" }, 312f857971dSopenharmony_ci { EVENT_HANDLER_ERR_RUNNER_ALREADY, "Event runner is already running" } 313f857971dSopenharmony_ci }; 314f857971dSopenharmony_ci auto it = mapStrings.find(code); 315f857971dSopenharmony_ci if (it != mapStrings.end()) { 316f857971dSopenharmony_ci return it->second; 317f857971dSopenharmony_ci } 318f857971dSopenharmony_ci return defErrString; 319f857971dSopenharmony_ci} 320f857971dSopenharmony_ci} // namespace DeviceStatus 321f857971dSopenharmony_ci} // namespace Msdp 322f857971dSopenharmony_ci} // namespace OHOS 323