1cc290419Sopenharmony_ci/* 2cc290419Sopenharmony_ci * Copyright (C) 2021 Huawei Device Co., Ltd. 3cc290419Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4cc290419Sopenharmony_ci * you may not use this file except in compliance with the License. 5cc290419Sopenharmony_ci * You may obtain a copy of the License at 6cc290419Sopenharmony_ci * 7cc290419Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8cc290419Sopenharmony_ci * 9cc290419Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10cc290419Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11cc290419Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12cc290419Sopenharmony_ci * See the License for the specific language governing permissions and 13cc290419Sopenharmony_ci * limitations under the License. 14cc290419Sopenharmony_ci */ 15cc290419Sopenharmony_ci#include "server_for_client.h" 16cc290419Sopenharmony_ci#ifndef TEST_HASH 17cc290419Sopenharmony_ci#include "hdc_hash_gen.h" 18cc290419Sopenharmony_ci#endif 19cc290419Sopenharmony_ci#include "server.h" 20cc290419Sopenharmony_ci 21cc290419Sopenharmony_cinamespace Hdc { 22cc290419Sopenharmony_cistatic const int MAX_RETRY_COUNT = 500; 23cc290419Sopenharmony_cistatic const int MAX_CONNECT_DEVICE_RETRY_COUNT = 100; 24cc290419Sopenharmony_ci 25cc290419Sopenharmony_ciHdcServerForClient::HdcServerForClient(const bool serverOrClient, const string &addrString, void *pClsServer, 26cc290419Sopenharmony_ci uv_loop_t *loopMainIn) 27cc290419Sopenharmony_ci : HdcChannelBase(serverOrClient, addrString, loopMainIn) 28cc290419Sopenharmony_ci{ 29cc290419Sopenharmony_ci clsServer = pClsServer; 30cc290419Sopenharmony_ci} 31cc290419Sopenharmony_ci 32cc290419Sopenharmony_ciHdcServerForClient::~HdcServerForClient() 33cc290419Sopenharmony_ci{ 34cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "~HdcServerForClient"); 35cc290419Sopenharmony_ci} 36cc290419Sopenharmony_ci 37cc290419Sopenharmony_civoid HdcServerForClient::Stop() 38cc290419Sopenharmony_ci{ 39cc290419Sopenharmony_ci Base::TryCloseHandle((uv_handle_t *)&tcpListen); 40cc290419Sopenharmony_ci} 41cc290419Sopenharmony_ci 42cc290419Sopenharmony_ciuint16_t HdcServerForClient::GetTCPListenPort() 43cc290419Sopenharmony_ci{ 44cc290419Sopenharmony_ci return channelPort; 45cc290419Sopenharmony_ci} 46cc290419Sopenharmony_ci 47cc290419Sopenharmony_civoid HdcServerForClient::AcceptClient(uv_stream_t *server, int status) 48cc290419Sopenharmony_ci{ 49cc290419Sopenharmony_ci uv_tcp_t *pServTCP = (uv_tcp_t *)server; 50cc290419Sopenharmony_ci HdcServerForClient *thisClass = (HdcServerForClient *)pServTCP->data; 51cc290419Sopenharmony_ci HChannel hChannel = nullptr; 52cc290419Sopenharmony_ci uint32_t uid = thisClass->MallocChannel(&hChannel); 53cc290419Sopenharmony_ci if (!hChannel) { 54cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "AcceptClient hChannel is nullptr"); 55cc290419Sopenharmony_ci return; 56cc290419Sopenharmony_ci } 57cc290419Sopenharmony_ci int rc = uv_accept(server, (uv_stream_t *)&hChannel->hWorkTCP); 58cc290419Sopenharmony_ci if (rc < 0) { 59cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "AcceptClient uv_accept error rc:%d uid:%u", rc, uid); 60cc290419Sopenharmony_ci thisClass->FreeChannel(uid); 61cc290419Sopenharmony_ci return; 62cc290419Sopenharmony_ci } 63cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "AcceptClient uid:%u", uid); 64cc290419Sopenharmony_ci // limit first recv 65cc290419Sopenharmony_ci int bufMaxSize = 0; 66cc290419Sopenharmony_ci uv_recv_buffer_size((uv_handle_t *)&hChannel->hWorkTCP, &bufMaxSize); 67cc290419Sopenharmony_ci auto funcChannelHeaderAlloc = [](uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf) -> void { 68cc290419Sopenharmony_ci HChannel context = (HChannel)handle->data; 69cc290419Sopenharmony_ci Base::ReallocBuf(&context->ioBuf, &context->bufSize, Base::GetMaxBufSize() * BUF_EXTEND_SIZE); 70cc290419Sopenharmony_ci buf->base = (char *)context->ioBuf + context->availTailIndex; 71cc290419Sopenharmony_ci#ifdef HDC_VERSION_CHECK 72cc290419Sopenharmony_ci buf->len = sizeof(struct ChannelHandShake) + DWORD_SERIALIZE_SIZE; // only recv static size 73cc290419Sopenharmony_ci#else 74cc290419Sopenharmony_ci buf->len = offsetof(struct ChannelHandShake, version) + DWORD_SERIALIZE_SIZE; 75cc290419Sopenharmony_ci#endif 76cc290419Sopenharmony_ci }; 77cc290419Sopenharmony_ci // first packet static size, after this packet will be dup for normal recv 78cc290419Sopenharmony_ci uv_read_start((uv_stream_t *)&hChannel->hWorkTCP, funcChannelHeaderAlloc, ReadStream); 79cc290419Sopenharmony_ci // channel handshake step1 80cc290419Sopenharmony_ci struct ChannelHandShake handShake = {}; 81cc290419Sopenharmony_ci if (EOK == strcpy_s(handShake.banner, sizeof(handShake.banner), HANDSHAKE_MESSAGE.c_str())) { 82cc290419Sopenharmony_ci handShake.banner[BANNER_FEATURE_TAG_OFFSET] = HUGE_BUF_TAG; // set feature tag for huge buf size 83cc290419Sopenharmony_ci handShake.channelId = htonl(hChannel->channelId); 84cc290419Sopenharmony_ci string ver = Base::GetVersion() + HDC_MSG_HASH; 85cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "Server ver:%s", ver.c_str()); 86cc290419Sopenharmony_ci if (EOK != strcpy_s(handShake.version, sizeof(handShake.version), ver.c_str())) { 87cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "strcpy_s failed"); 88cc290419Sopenharmony_ci return; 89cc290419Sopenharmony_ci } 90cc290419Sopenharmony_ci#ifdef HDC_VERSION_CHECK 91cc290419Sopenharmony_ci thisClass->Send(hChannel->channelId, (uint8_t *)&handShake, sizeof(struct ChannelHandShake)); 92cc290419Sopenharmony_ci#else 93cc290419Sopenharmony_ci // do not send version message if check feature disable 94cc290419Sopenharmony_ci thisClass->Send(hChannel->channelId, reinterpret_cast<uint8_t *>(&handShake), 95cc290419Sopenharmony_ci offsetof(struct ChannelHandShake, version)); 96cc290419Sopenharmony_ci#endif 97cc290419Sopenharmony_ci } 98cc290419Sopenharmony_ci} 99cc290419Sopenharmony_ci 100cc290419Sopenharmony_cibool HdcServerForClient::SetTCPListen() 101cc290419Sopenharmony_ci{ 102cc290419Sopenharmony_ci char buffer[BUF_SIZE_DEFAULT] = { 0 }; 103cc290419Sopenharmony_ci tcpListen.data = this; 104cc290419Sopenharmony_ci struct sockaddr_in6 addr; 105cc290419Sopenharmony_ci uv_tcp_init(loopMain, &tcpListen); 106cc290419Sopenharmony_ci 107cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "channelHost %s, port: %d", channelHost.c_str(), channelPort); 108cc290419Sopenharmony_ci int rc = uv_ip6_addr(channelHost.c_str(), channelPort, &addr); 109cc290419Sopenharmony_ci if (rc != 0) { 110cc290419Sopenharmony_ci uv_strerror_r(rc, buffer, BUF_SIZE_DEFAULT); 111cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "uv_ip6_addr %d %s", rc, buffer); 112cc290419Sopenharmony_ci return false; 113cc290419Sopenharmony_ci } 114cc290419Sopenharmony_ci rc = uv_tcp_bind(&tcpListen, (const struct sockaddr *)&addr, 0); 115cc290419Sopenharmony_ci if (rc != 0) { 116cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "uv_tcp_bind ipv6 %d", rc); 117cc290419Sopenharmony_ci if (rc == -EAFNOSUPPORT) { 118cc290419Sopenharmony_ci size_t index = channelHost.find(IPV4_MAPPING_PREFIX); 119cc290419Sopenharmony_ci size_t size = IPV4_MAPPING_PREFIX.size(); 120cc290419Sopenharmony_ci if (index != std::string::npos) { 121cc290419Sopenharmony_ci struct sockaddr_in addr4v; 122cc290419Sopenharmony_ci std::string ipv4 = channelHost.substr(index + size); 123cc290419Sopenharmony_ci uv_ip4_addr(ipv4.c_str(), channelPort, &addr4v); 124cc290419Sopenharmony_ci rc = uv_tcp_bind(&tcpListen, (const struct sockaddr *)&addr4v, 0); 125cc290419Sopenharmony_ci if (rc != 0) { 126cc290419Sopenharmony_ci uv_strerror_r(rc, buffer, BUF_SIZE_DEFAULT); 127cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "uv_tcp_bind ipv4 %s failed %d %s", 128cc290419Sopenharmony_ci ipv4.c_str(), rc, buffer); 129cc290419Sopenharmony_ci return false; 130cc290419Sopenharmony_ci } 131cc290419Sopenharmony_ci } 132cc290419Sopenharmony_ci } else { 133cc290419Sopenharmony_ci uv_strerror_r(rc, buffer, BUF_SIZE_DEFAULT); 134cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "uv_tcp_bind %d %s", rc, buffer); 135cc290419Sopenharmony_ci return false; 136cc290419Sopenharmony_ci } 137cc290419Sopenharmony_ci } 138cc290419Sopenharmony_ci int backLog = 128; 139cc290419Sopenharmony_ci rc = uv_listen((uv_stream_t *)&tcpListen, backLog, (uv_connection_cb)AcceptClient); 140cc290419Sopenharmony_ci if (rc != 0) { 141cc290419Sopenharmony_ci uv_strerror_r(rc, buffer, BUF_SIZE_DEFAULT); 142cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "uv_listen %d %s", rc, buffer); 143cc290419Sopenharmony_ci return false; 144cc290419Sopenharmony_ci } 145cc290419Sopenharmony_ci return true; 146cc290419Sopenharmony_ci} 147cc290419Sopenharmony_ci 148cc290419Sopenharmony_ciint HdcServerForClient::Initial() 149cc290419Sopenharmony_ci{ 150cc290419Sopenharmony_ci if (!clsServer) { 151cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "Module client initial failed"); 152cc290419Sopenharmony_ci return -1; 153cc290419Sopenharmony_ci } 154cc290419Sopenharmony_ci if (!channelHostPort.size() || !channelHost.size() || !channelPort) { 155cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "Listen string initial failed"); 156cc290419Sopenharmony_ci return -2; // -2:err for Listen initial failed 157cc290419Sopenharmony_ci } 158cc290419Sopenharmony_ci bool b = SetTCPListen(); 159cc290419Sopenharmony_ci if (!b) { 160cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "SetTCPListen failed"); 161cc290419Sopenharmony_ci int listenError = -3; // -3:error for SetTCPListen failed 162cc290419Sopenharmony_ci return listenError; 163cc290419Sopenharmony_ci } 164cc290419Sopenharmony_ci return 0; 165cc290419Sopenharmony_ci} 166cc290419Sopenharmony_ci 167cc290419Sopenharmony_civoid HdcServerForClient::EchoClient(HChannel hChannel, MessageLevel level, const char *msg, ...) 168cc290419Sopenharmony_ci{ 169cc290419Sopenharmony_ci string logInfo = ""; 170cc290419Sopenharmony_ci switch (level) { 171cc290419Sopenharmony_ci case MSG_FAIL: 172cc290419Sopenharmony_ci logInfo = MESSAGE_FAIL; 173cc290419Sopenharmony_ci break; 174cc290419Sopenharmony_ci case MSG_INFO: 175cc290419Sopenharmony_ci logInfo = MESSAGE_INFO; 176cc290419Sopenharmony_ci break; 177cc290419Sopenharmony_ci default: // successful, not append extra info 178cc290419Sopenharmony_ci break; 179cc290419Sopenharmony_ci } 180cc290419Sopenharmony_ci va_list vaArgs; 181cc290419Sopenharmony_ci va_start(vaArgs, msg); 182cc290419Sopenharmony_ci string log = logInfo + Base::StringFormat(msg, vaArgs); 183cc290419Sopenharmony_ci va_end(vaArgs); 184cc290419Sopenharmony_ci if (log.back() != '\n') { 185cc290419Sopenharmony_ci log += "\r\n"; 186cc290419Sopenharmony_ci } 187cc290419Sopenharmony_ci SendChannel(hChannel, const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(log.c_str())), log.size()); 188cc290419Sopenharmony_ci} 189cc290419Sopenharmony_ci 190cc290419Sopenharmony_civoid HdcServerForClient::EchoClientRaw(const HChannel hChannel, uint8_t *payload, const int payloadSize) 191cc290419Sopenharmony_ci{ 192cc290419Sopenharmony_ci SendChannel(hChannel, payload, payloadSize); 193cc290419Sopenharmony_ci} 194cc290419Sopenharmony_ci 195cc290419Sopenharmony_ci// HdcServerForClient passthrough file command to client 196cc290419Sopenharmony_civoid HdcServerForClient::SendCommandToClient(const HChannel hChannel, const uint16_t commandFlag, 197cc290419Sopenharmony_ci uint8_t *payload, const int payloadSize) 198cc290419Sopenharmony_ci{ 199cc290419Sopenharmony_ci SendChannelWithCmd(hChannel, commandFlag, payload, payloadSize); 200cc290419Sopenharmony_ci} 201cc290419Sopenharmony_ci 202cc290419Sopenharmony_cibool HdcServerForClient::SendToDaemon(HChannel hChannel, const uint16_t commandFlag, uint8_t *bufPtr, const int bufSize) 203cc290419Sopenharmony_ci{ 204cc290419Sopenharmony_ci HDaemonInfo hdi = nullptr; 205cc290419Sopenharmony_ci bool ret = false; 206cc290419Sopenharmony_ci HdcServer *ptrServer = (HdcServer *)clsServer; 207cc290419Sopenharmony_ci while (true) { 208cc290419Sopenharmony_ci ptrServer->AdminDaemonMap(OP_QUERY, hChannel->connectKey, hdi); 209cc290419Sopenharmony_ci if (hdi == nullptr) { 210cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "SendToDaemon hdi nullptr"); 211cc290419Sopenharmony_ci break; 212cc290419Sopenharmony_ci } 213cc290419Sopenharmony_ci if (hdi->connStatus != STATUS_CONNECTED) { 214cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "SendToDaemon not connected"); 215cc290419Sopenharmony_ci break; 216cc290419Sopenharmony_ci } 217cc290419Sopenharmony_ci if (!hdi->hSession) { 218cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "SendToDaemon hdi->hSession nullptr"); 219cc290419Sopenharmony_ci break; 220cc290419Sopenharmony_ci } 221cc290419Sopenharmony_ci if (ptrServer->Send(hdi->hSession->sessionId, hChannel->channelId, commandFlag, bufPtr, bufSize) < 0) { 222cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "SendToDaemon Send failed channelId:%u", hChannel->channelId); 223cc290419Sopenharmony_ci break; 224cc290419Sopenharmony_ci } 225cc290419Sopenharmony_ci ret = true; 226cc290419Sopenharmony_ci break; 227cc290419Sopenharmony_ci } 228cc290419Sopenharmony_ci return ret; 229cc290419Sopenharmony_ci} 230cc290419Sopenharmony_ci 231cc290419Sopenharmony_civoid HdcServerForClient::OrderFindTargets(HChannel hChannel) 232cc290419Sopenharmony_ci{ 233cc290419Sopenharmony_ci int count = 0; 234cc290419Sopenharmony_ci EchoClient(hChannel, MSG_INFO, "Please add HDC server's firewall ruler to allow udp incoming, udpport:%d", 235cc290419Sopenharmony_ci DEFAULT_PORT); 236cc290419Sopenharmony_ci HdcServer *ptrServer = (HdcServer *)clsServer; 237cc290419Sopenharmony_ci ptrServer->clsTCPClt->FindLanDaemon(); 238cc290419Sopenharmony_ci list<string> &lst = ptrServer->clsTCPClt->lstDaemonResult; 239cc290419Sopenharmony_ci // refresh main list 240cc290419Sopenharmony_ci HdcDaemonInformation di; 241cc290419Sopenharmony_ci while (!lst.empty()) { 242cc290419Sopenharmony_ci di = {}; 243cc290419Sopenharmony_ci ++count; 244cc290419Sopenharmony_ci di.connectKey = lst.front(); 245cc290419Sopenharmony_ci di.connType = CONN_TCP; 246cc290419Sopenharmony_ci di.connStatus = STATUS_READY; 247cc290419Sopenharmony_ci HDaemonInfo pDi = reinterpret_cast<HDaemonInfo>(&di); 248cc290419Sopenharmony_ci ptrServer->AdminDaemonMap(OP_ADD, STRING_EMPTY, pDi); 249cc290419Sopenharmony_ci lst.pop_front(); 250cc290419Sopenharmony_ci } 251cc290419Sopenharmony_ci EchoClient(hChannel, MSG_INFO, "Broadcast find daemon, total:%d", count); 252cc290419Sopenharmony_ci#ifdef UNIT_TEST 253cc290419Sopenharmony_ci string bufString = std::to_string(count); 254cc290419Sopenharmony_ci Base::WriteBinFile((UT_TMP_PATH + "/base-discover.result").c_str(), (uint8_t *)bufString.c_str(), bufString.size(), 255cc290419Sopenharmony_ci true); 256cc290419Sopenharmony_ci#endif 257cc290419Sopenharmony_ci} 258cc290419Sopenharmony_ci 259cc290419Sopenharmony_civoid HdcServerForClient::OrderConnecTargetResult(uv_timer_t *req) 260cc290419Sopenharmony_ci{ 261cc290419Sopenharmony_ci HChannel hChannel = (HChannel)req->data; 262cc290419Sopenharmony_ci HdcServerForClient *thisClass = (HdcServerForClient *)hChannel->clsChannel; 263cc290419Sopenharmony_ci HdcServer *ptrServer = (HdcServer *)thisClass->clsServer; 264cc290419Sopenharmony_ci bool bConnectOK = false; 265cc290419Sopenharmony_ci bool bExitRepet = false; 266cc290419Sopenharmony_ci HDaemonInfo hdi = nullptr; 267cc290419Sopenharmony_ci string sRet; 268cc290419Sopenharmony_ci string target = std::string(hChannel->bufStd + 2); 269cc290419Sopenharmony_ci if (target == "any") { 270cc290419Sopenharmony_ci ptrServer->AdminDaemonMap(OP_GET_ANY, target, hdi); 271cc290419Sopenharmony_ci } else { 272cc290419Sopenharmony_ci ptrServer->AdminDaemonMap(OP_QUERY, target, hdi); 273cc290419Sopenharmony_ci } 274cc290419Sopenharmony_ci if (hdi && hdi->connStatus == STATUS_CONNECTED) { 275cc290419Sopenharmony_ci bConnectOK = true; 276cc290419Sopenharmony_ci } 277cc290419Sopenharmony_ci while (true) { 278cc290419Sopenharmony_ci if (bConnectOK) { 279cc290419Sopenharmony_ci bExitRepet = true; 280cc290419Sopenharmony_ci if (hChannel->isCheck) { 281cc290419Sopenharmony_ci WRITE_LOG(LOG_INFO, "%s check device success and remove %s", __FUNCTION__, hChannel->key.c_str()); 282cc290419Sopenharmony_ci thisClass->CommandRemoveSession(hChannel, hChannel->key.c_str()); 283cc290419Sopenharmony_ci thisClass->EchoClient(hChannel, MSG_OK, const_cast<char *>(hdi->version.c_str())); 284cc290419Sopenharmony_ci } else { 285cc290419Sopenharmony_ci sRet = "Connect OK"; 286cc290419Sopenharmony_ci thisClass->EchoClient(hChannel, MSG_OK, const_cast<char *>(sRet.c_str())); 287cc290419Sopenharmony_ci } 288cc290419Sopenharmony_ci break; 289cc290419Sopenharmony_ci } else { 290cc290419Sopenharmony_ci uint16_t *bRetryCount = reinterpret_cast<uint16_t *>(hChannel->bufStd); 291cc290419Sopenharmony_ci ++(*bRetryCount); 292cc290419Sopenharmony_ci if (*bRetryCount > MAX_RETRY_COUNT || 293cc290419Sopenharmony_ci (hChannel->connectLocalDevice && *bRetryCount > MAX_CONNECT_DEVICE_RETRY_COUNT)) { 294cc290419Sopenharmony_ci // 5s or localDevice 1s 295cc290419Sopenharmony_ci bExitRepet = true; 296cc290419Sopenharmony_ci sRet = "Connect failed"; 297cc290419Sopenharmony_ci thisClass->EchoClient(hChannel, MSG_FAIL, const_cast<char *>(sRet.c_str())); 298cc290419Sopenharmony_ci break; 299cc290419Sopenharmony_ci } 300cc290419Sopenharmony_ci } 301cc290419Sopenharmony_ci break; 302cc290419Sopenharmony_ci } 303cc290419Sopenharmony_ci if (bExitRepet) { 304cc290419Sopenharmony_ci thisClass->FreeChannel(hChannel->channelId); 305cc290419Sopenharmony_ci Base::TryCloseHandle((const uv_handle_t *)req, Base::CloseTimerCallback); 306cc290419Sopenharmony_ci } 307cc290419Sopenharmony_ci} 308cc290419Sopenharmony_ci 309cc290419Sopenharmony_cibool HdcServerForClient::NewConnectTry(void *ptrServer, HChannel hChannel, const string &connectKey, bool isCheck) 310cc290419Sopenharmony_ci{ 311cc290419Sopenharmony_ci#ifdef HDC_DEBUG 312cc290419Sopenharmony_ci WRITE_LOG(LOG_ALL, "%s %s", __FUNCTION__, Hdc::MaskString(connectKey).c_str()); 313cc290419Sopenharmony_ci#endif 314cc290419Sopenharmony_ci int childRet = ((HdcServer *)ptrServer)->CreateConnect(connectKey, isCheck); 315cc290419Sopenharmony_ci bool ret = false; 316cc290419Sopenharmony_ci int connectError = -2; 317cc290419Sopenharmony_ci constexpr uint8_t bufOffsetTwo = 2; 318cc290419Sopenharmony_ci constexpr uint8_t bufOffsetThree = 3; 319cc290419Sopenharmony_ci if (childRet == -1) { 320cc290419Sopenharmony_ci EchoClient(hChannel, MSG_INFO, "Target is connected, repeat operation"); 321cc290419Sopenharmony_ci } else if (childRet == connectError) { 322cc290419Sopenharmony_ci EchoClient(hChannel, MSG_FAIL, "CreateConnect failed"); 323cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "CreateConnect failed"); 324cc290419Sopenharmony_ci } else { 325cc290419Sopenharmony_ci size_t pos = connectKey.find(":"); 326cc290419Sopenharmony_ci if (pos != std::string::npos) { 327cc290419Sopenharmony_ci string ip = connectKey.substr(0, pos); 328cc290419Sopenharmony_ci if (ip == "127.0.0.1") { 329cc290419Sopenharmony_ci hChannel->connectLocalDevice = true; 330cc290419Sopenharmony_ci } 331cc290419Sopenharmony_ci } 332cc290419Sopenharmony_ci Base::ZeroBuf(hChannel->bufStd, bufOffsetTwo); 333cc290419Sopenharmony_ci childRet = snprintf_s(hChannel->bufStd + bufOffsetTwo, sizeof(hChannel->bufStd) - bufOffsetTwo, 334cc290419Sopenharmony_ci sizeof(hChannel->bufStd) - bufOffsetThree, "%s", 335cc290419Sopenharmony_ci const_cast<char *>(connectKey.c_str())); 336cc290419Sopenharmony_ci if (childRet > 0) { 337cc290419Sopenharmony_ci Base::TimerUvTask(loopMain, hChannel, OrderConnecTargetResult, UV_START_REPEAT); 338cc290419Sopenharmony_ci ret = true; 339cc290419Sopenharmony_ci } 340cc290419Sopenharmony_ci } 341cc290419Sopenharmony_ci return ret; 342cc290419Sopenharmony_ci} 343cc290419Sopenharmony_ci 344cc290419Sopenharmony_cibool HdcServerForClient::CommandRemoveSession(HChannel hChannel, const char *connectKey) 345cc290419Sopenharmony_ci{ 346cc290419Sopenharmony_ci HdcServer *ptrServer = (HdcServer *)clsServer; 347cc290419Sopenharmony_ci HDaemonInfo hdiOld = nullptr; 348cc290419Sopenharmony_ci (reinterpret_cast<HdcServer *>(ptrServer))->AdminDaemonMap(OP_QUERY, connectKey, hdiOld); 349cc290419Sopenharmony_ci if (!hdiOld) { 350cc290419Sopenharmony_ci EchoClient(hChannel, MSG_FAIL, "No target available"); 351cc290419Sopenharmony_ci return false; 352cc290419Sopenharmony_ci } 353cc290419Sopenharmony_ci (reinterpret_cast<HdcServer *>(ptrServer))->FreeSession(hdiOld->hSession->sessionId); 354cc290419Sopenharmony_ci return true; 355cc290419Sopenharmony_ci} 356cc290419Sopenharmony_ci 357cc290419Sopenharmony_cibool HdcServerForClient::CommandRemoveForward(const string &forwardKey) 358cc290419Sopenharmony_ci{ 359cc290419Sopenharmony_ci bool ret = RemoveFportkey("0|" + forwardKey); 360cc290419Sopenharmony_ci ret |= RemoveFportkey("1|" + forwardKey); 361cc290419Sopenharmony_ci return ret; 362cc290419Sopenharmony_ci} 363cc290419Sopenharmony_ci 364cc290419Sopenharmony_cibool HdcServerForClient::RemoveFportkey(const string &forwardKey) 365cc290419Sopenharmony_ci{ 366cc290419Sopenharmony_ci HdcServer *ptrServer = (HdcServer *)clsServer; 367cc290419Sopenharmony_ci HForwardInfo hfi = nullptr; 368cc290419Sopenharmony_ci ptrServer->AdminForwardMap(OP_QUERY, forwardKey, hfi); 369cc290419Sopenharmony_ci if (!hfi) { 370cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "CommandRemoveForward hfi nullptr forwardKey:%s", forwardKey.c_str()); 371cc290419Sopenharmony_ci return false; 372cc290419Sopenharmony_ci } 373cc290419Sopenharmony_ci HSession hSession = ptrServer->AdminSession(OP_QUERY, hfi->sessionId, nullptr); 374cc290419Sopenharmony_ci if (!hSession) { 375cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "CommandRemoveForward hSession nullptr sessionId:%u", hfi->sessionId); 376cc290419Sopenharmony_ci ptrServer->AdminForwardMap(OP_REMOVE, forwardKey, hfi); 377cc290419Sopenharmony_ci return true; 378cc290419Sopenharmony_ci } 379cc290419Sopenharmony_ci ptrServer->ClearOwnTasks(hSession, hfi->channelId); 380cc290419Sopenharmony_ci FreeChannel(hfi->channelId); 381cc290419Sopenharmony_ci hfi = nullptr; 382cc290419Sopenharmony_ci ptrServer->AdminForwardMap(OP_REMOVE, forwardKey, hfi); 383cc290419Sopenharmony_ci return true; 384cc290419Sopenharmony_ci} 385cc290419Sopenharmony_ci 386cc290419Sopenharmony_civoid HdcServerForClient::GetTargetList(HChannel hChannel, void *formatCommandInput) 387cc290419Sopenharmony_ci{ 388cc290419Sopenharmony_ci TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput; 389cc290419Sopenharmony_ci HdcServer *ptrServer = (HdcServer *)clsServer; 390cc290419Sopenharmony_ci uint16_t cmd = OP_GET_STRLIST; 391cc290419Sopenharmony_ci if (formatCommand->parameters == "v") { 392cc290419Sopenharmony_ci cmd = OP_GET_STRLIST_FULL; 393cc290419Sopenharmony_ci } 394cc290419Sopenharmony_ci HDaemonInfo hdi = nullptr; 395cc290419Sopenharmony_ci string sRet = ptrServer->AdminDaemonMap(cmd, STRING_EMPTY, hdi); 396cc290419Sopenharmony_ci if (!sRet.length()) { 397cc290419Sopenharmony_ci sRet = EMPTY_ECHO; 398cc290419Sopenharmony_ci } 399cc290419Sopenharmony_ci EchoClient(hChannel, MSG_OK, const_cast<char *>(sRet.c_str())); 400cc290419Sopenharmony_ci#ifdef UNIT_TEST 401cc290419Sopenharmony_ci Base::WriteBinFile((UT_TMP_PATH + "/base-list.result").c_str(), (uint8_t *)MESSAGE_SUCCESS.c_str(), 402cc290419Sopenharmony_ci MESSAGE_SUCCESS.size(), true); 403cc290419Sopenharmony_ci#endif 404cc290419Sopenharmony_ci} 405cc290419Sopenharmony_ci 406cc290419Sopenharmony_cibool HdcServerForClient::GetAnyTarget(HChannel hChannel) 407cc290419Sopenharmony_ci{ 408cc290419Sopenharmony_ci HdcServer *ptrServer = (HdcServer *)clsServer; 409cc290419Sopenharmony_ci HDaemonInfo hdi = nullptr; 410cc290419Sopenharmony_ci ptrServer->AdminDaemonMap(OP_GET_ANY, STRING_EMPTY, hdi); 411cc290419Sopenharmony_ci if (!hdi) { 412cc290419Sopenharmony_ci EchoClient(hChannel, MSG_FAIL, "No target available"); 413cc290419Sopenharmony_ci return false; 414cc290419Sopenharmony_ci } 415cc290419Sopenharmony_ci // can not use hdi->connectKey.This memory may be released to re-Malloc 416cc290419Sopenharmony_ci string connectKey = hdi->connectKey; 417cc290419Sopenharmony_ci bool ret = NewConnectTry(ptrServer, hChannel, connectKey); 418cc290419Sopenharmony_ci#ifdef UNIT_TEST 419cc290419Sopenharmony_ci Base::WriteBinFile((UT_TMP_PATH + "/base-any.result").c_str(), (uint8_t *)MESSAGE_SUCCESS.c_str(), 420cc290419Sopenharmony_ci MESSAGE_SUCCESS.size(), true); 421cc290419Sopenharmony_ci#endif 422cc290419Sopenharmony_ci return ret; 423cc290419Sopenharmony_ci} 424cc290419Sopenharmony_ci 425cc290419Sopenharmony_cibool HdcServerForClient::WaitForAny(HChannel hChannel) 426cc290419Sopenharmony_ci{ 427cc290419Sopenharmony_ci HdcServer *ptrServer = (HdcServer *)clsServer; 428cc290419Sopenharmony_ci HDaemonInfo hdi = nullptr; 429cc290419Sopenharmony_ci if (!hChannel->connectKey.empty()) { 430cc290419Sopenharmony_ci ptrServer->AdminDaemonMap(OP_WAIT_FOR_ANY, hChannel->connectKey, hdi); 431cc290419Sopenharmony_ci } else { 432cc290419Sopenharmony_ci ptrServer->AdminDaemonMap(OP_WAIT_FOR_ANY, STRING_EMPTY, hdi); 433cc290419Sopenharmony_ci } 434cc290419Sopenharmony_ci if (!hdi) { 435cc290419Sopenharmony_ci EchoClient(hChannel, MSG_FAIL, "No any connected target"); 436cc290419Sopenharmony_ci return false; 437cc290419Sopenharmony_ci } 438cc290419Sopenharmony_ci string key = hdi->connectKey; 439cc290419Sopenharmony_ci EchoClient(hChannel, MSG_OK, "Wait for connected target is %s", key.c_str()); 440cc290419Sopenharmony_ci return true; 441cc290419Sopenharmony_ci} 442cc290419Sopenharmony_ci 443cc290419Sopenharmony_cibool HdcServerForClient::RemoveForward(HChannel hChannel, const char *parameterString) 444cc290419Sopenharmony_ci{ 445cc290419Sopenharmony_ci HdcServer *ptrServer = (HdcServer *)clsServer; 446cc290419Sopenharmony_ci if (parameterString == nullptr) { // remove all 447cc290419Sopenharmony_ci HForwardInfo hfi = nullptr; // dummy 448cc290419Sopenharmony_ci string echo = ptrServer->AdminForwardMap(OP_GET_STRLIST, "", hfi); 449cc290419Sopenharmony_ci if (!echo.length()) { 450cc290419Sopenharmony_ci return false; 451cc290419Sopenharmony_ci } 452cc290419Sopenharmony_ci vector<string> filterStrings; 453cc290419Sopenharmony_ci Base::SplitString(echo, string("\n"), filterStrings); 454cc290419Sopenharmony_ci for (auto &&s : filterStrings) { 455cc290419Sopenharmony_ci if (CommandRemoveForward(s.c_str())) { 456cc290419Sopenharmony_ci EchoClient(hChannel, MSG_OK, "Remove forward ruler success, ruler:%s", s.c_str()); 457cc290419Sopenharmony_ci } else { 458cc290419Sopenharmony_ci EchoClient(hChannel, MSG_FAIL, "Remove forward ruler failed, ruler is not exist %s", s.c_str()); 459cc290419Sopenharmony_ci } 460cc290419Sopenharmony_ci } 461cc290419Sopenharmony_ci } else { // remove single 462cc290419Sopenharmony_ci if (CommandRemoveForward(parameterString)) { 463cc290419Sopenharmony_ci EchoClient(hChannel, MSG_OK, "Remove forward ruler success, ruler:%s", parameterString); 464cc290419Sopenharmony_ci } else { 465cc290419Sopenharmony_ci EchoClient(hChannel, MSG_FAIL, "Remove forward ruler failed, ruler is not exist %s", parameterString); 466cc290419Sopenharmony_ci } 467cc290419Sopenharmony_ci } 468cc290419Sopenharmony_ci return true; 469cc290419Sopenharmony_ci} 470cc290419Sopenharmony_ci 471cc290419Sopenharmony_cibool HdcServerForClient::DoCommandLocal(HChannel hChannel, void *formatCommandInput) 472cc290419Sopenharmony_ci{ 473cc290419Sopenharmony_ci TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput; 474cc290419Sopenharmony_ci HdcServer *ptrServer = (HdcServer *)clsServer; 475cc290419Sopenharmony_ci bool ret = false; 476cc290419Sopenharmony_ci // Main thread command, direct Listen main thread 477cc290419Sopenharmony_ci switch (formatCommand->cmdFlag) { 478cc290419Sopenharmony_ci case CMD_KERNEL_TARGET_DISCOVER: { 479cc290419Sopenharmony_ci OrderFindTargets(hChannel); 480cc290419Sopenharmony_ci ret = false; 481cc290419Sopenharmony_ci break; 482cc290419Sopenharmony_ci } 483cc290419Sopenharmony_ci case CMD_KERNEL_TARGET_LIST: { 484cc290419Sopenharmony_ci GetTargetList(hChannel, formatCommandInput); 485cc290419Sopenharmony_ci ret = false; 486cc290419Sopenharmony_ci break; 487cc290419Sopenharmony_ci } 488cc290419Sopenharmony_ci case CMD_CHECK_SERVER: { 489cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "CMD_CHECK_SERVER command"); 490cc290419Sopenharmony_ci ReportServerVersion(hChannel); 491cc290419Sopenharmony_ci ret = false; 492cc290419Sopenharmony_ci break; 493cc290419Sopenharmony_ci } 494cc290419Sopenharmony_ci case CMD_WAIT_FOR: { 495cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "CMD_WAIT_FOR command"); 496cc290419Sopenharmony_ci ret = !WaitForAny(hChannel); 497cc290419Sopenharmony_ci break; 498cc290419Sopenharmony_ci } 499cc290419Sopenharmony_ci case CMD_KERNEL_TARGET_ANY: { 500cc290419Sopenharmony_ci#ifdef HDC_DEBUG 501cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "%s CMD_KERNEL_TARGET_ANY %s", __FUNCTION__, formatCommand->parameters.c_str()); 502cc290419Sopenharmony_ci#endif 503cc290419Sopenharmony_ci ret = GetAnyTarget(hChannel); 504cc290419Sopenharmony_ci break; 505cc290419Sopenharmony_ci } 506cc290419Sopenharmony_ci case CMD_KERNEL_TARGET_CONNECT: { 507cc290419Sopenharmony_ci#ifdef HDC_DEBUG 508cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "%s CMD_KERNEL_TARGET_CONNECT %s", __FUNCTION__, formatCommand->parameters.c_str()); 509cc290419Sopenharmony_ci#endif 510cc290419Sopenharmony_ci ret = NewConnectTry(ptrServer, hChannel, formatCommand->parameters.c_str()); 511cc290419Sopenharmony_ci break; 512cc290419Sopenharmony_ci } 513cc290419Sopenharmony_ci case CMD_CHECK_DEVICE: { 514cc290419Sopenharmony_ci WRITE_LOG(LOG_INFO, "%s CMD_CHECK_DEVICE %s", __FUNCTION__, formatCommand->parameters.c_str()); 515cc290419Sopenharmony_ci hChannel->isCheck = true; 516cc290419Sopenharmony_ci hChannel->key = formatCommand->parameters.c_str(); 517cc290419Sopenharmony_ci ret = NewConnectTry(ptrServer, hChannel, formatCommand->parameters.c_str(), true); 518cc290419Sopenharmony_ci break; 519cc290419Sopenharmony_ci } 520cc290419Sopenharmony_ci case CMD_KERNEL_TARGET_DISCONNECT: { 521cc290419Sopenharmony_ci CommandRemoveSession(hChannel, formatCommand->parameters.c_str()); 522cc290419Sopenharmony_ci break; 523cc290419Sopenharmony_ci } 524cc290419Sopenharmony_ci // task will be global task,Therefore, it can only be controlled in the global session. 525cc290419Sopenharmony_ci case CMD_FORWARD_LIST: { 526cc290419Sopenharmony_ci HForwardInfo hfi = nullptr; // dummy 527cc290419Sopenharmony_ci string echo = ptrServer->AdminForwardMap(OP_GET_STRLIST_FULL, "", hfi); 528cc290419Sopenharmony_ci if (!echo.length()) { 529cc290419Sopenharmony_ci echo = EMPTY_ECHO; 530cc290419Sopenharmony_ci } 531cc290419Sopenharmony_ci EchoClient(hChannel, MSG_OK, const_cast<char *>(echo.c_str())); 532cc290419Sopenharmony_ci break; 533cc290419Sopenharmony_ci } 534cc290419Sopenharmony_ci case CMD_FORWARD_REMOVE: { 535cc290419Sopenharmony_ci RemoveForward(hChannel, formatCommand->parameters.c_str()); 536cc290419Sopenharmony_ci break; 537cc290419Sopenharmony_ci } 538cc290419Sopenharmony_ci case CMD_KERNEL_ENABLE_KEEPALIVE: { 539cc290419Sopenharmony_ci // just use for 'list targets' now 540cc290419Sopenharmony_ci hChannel->keepAlive = true; 541cc290419Sopenharmony_ci ret = true; 542cc290419Sopenharmony_ci break; 543cc290419Sopenharmony_ci } 544cc290419Sopenharmony_ci default: { 545cc290419Sopenharmony_ci EchoClient(hChannel, MSG_FAIL, "ExecuteCommand need connect-key? please confirm a device by help info"); 546cc290419Sopenharmony_ci break; 547cc290419Sopenharmony_ci } 548cc290419Sopenharmony_ci } 549cc290419Sopenharmony_ci return ret; 550cc290419Sopenharmony_ci} 551cc290419Sopenharmony_ci 552cc290419Sopenharmony_cibool HdcServerForClient::TaskCommand(HChannel hChannel, void *formatCommandInput) 553cc290419Sopenharmony_ci{ 554cc290419Sopenharmony_ci TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput; 555cc290419Sopenharmony_ci HdcServer *ptrServer = (HdcServer *)clsServer; 556cc290419Sopenharmony_ci string cmdFlag; 557cc290419Sopenharmony_ci uint8_t sizeCmdFlag = 0; 558cc290419Sopenharmony_ci if (formatCommand->cmdFlag == CMD_FILE_INIT) { 559cc290419Sopenharmony_ci cmdFlag = "send "; 560cc290419Sopenharmony_ci sizeCmdFlag = 5; // 5: cmdFlag send size 561cc290419Sopenharmony_ci HandleRemote(hChannel, formatCommand->parameters, RemoteType::REMOTE_FILE); 562cc290419Sopenharmony_ci } else if (formatCommand->cmdFlag == CMD_FORWARD_INIT) { 563cc290419Sopenharmony_ci cmdFlag = "fport "; 564cc290419Sopenharmony_ci sizeCmdFlag = 6; // 6: cmdFlag fport size 565cc290419Sopenharmony_ci } else if (formatCommand->cmdFlag == CMD_APP_INIT) { 566cc290419Sopenharmony_ci cmdFlag = "install "; 567cc290419Sopenharmony_ci sizeCmdFlag = 8; // 8: cmdFlag install size 568cc290419Sopenharmony_ci HandleRemote(hChannel, formatCommand->parameters, RemoteType::REMOTE_APP); 569cc290419Sopenharmony_ci } else if (formatCommand->cmdFlag == CMD_APP_UNINSTALL) { 570cc290419Sopenharmony_ci cmdFlag = "uninstall "; 571cc290419Sopenharmony_ci sizeCmdFlag = 10; // 10: cmdFlag uninstall size 572cc290419Sopenharmony_ci } else if (formatCommand->cmdFlag == CMD_UNITY_BUGREPORT_INIT) { 573cc290419Sopenharmony_ci cmdFlag = "bugreport "; 574cc290419Sopenharmony_ci sizeCmdFlag = 10; // 10: cmdFlag bugreport size 575cc290419Sopenharmony_ci } else if (formatCommand->cmdFlag == CMD_APP_SIDELOAD) { 576cc290419Sopenharmony_ci cmdFlag = "sideload "; 577cc290419Sopenharmony_ci sizeCmdFlag = 9; // 9: cmdFlag sideload size 578cc290419Sopenharmony_ci } else if (formatCommand->cmdFlag == CMD_FLASHD_UPDATE_INIT) { 579cc290419Sopenharmony_ci cmdFlag = "update "; 580cc290419Sopenharmony_ci sizeCmdFlag = 7; // 7: cmdFlag update size 581cc290419Sopenharmony_ci } else if (formatCommand->cmdFlag == CMD_FLASHD_FLASH_INIT) { 582cc290419Sopenharmony_ci cmdFlag = "flash "; 583cc290419Sopenharmony_ci sizeCmdFlag = 6; // 6: cmdFlag flash size 584cc290419Sopenharmony_ci } 585cc290419Sopenharmony_ci int sizeSend = formatCommand->parameters.size(); 586cc290419Sopenharmony_ci if (!strncmp(formatCommand->parameters.c_str(), cmdFlag.c_str(), sizeCmdFlag)) { // local do 587cc290419Sopenharmony_ci HSession hSession = FindAliveSession(hChannel->targetSessionId); 588cc290419Sopenharmony_ci if (!hSession) { 589cc290419Sopenharmony_ci return false; 590cc290419Sopenharmony_ci } 591cc290419Sopenharmony_ci if ((formatCommand->cmdFlag == CMD_FILE_INIT || formatCommand->cmdFlag == CMD_APP_INIT) && 592cc290419Sopenharmony_ci hChannel->fromClient) { 593cc290419Sopenharmony_ci // remote client mode, CMD_FILE_INIT and CMD_APP_INIT command send back to client 594cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "command send back to remote client channelId:%u", hChannel->channelId); 595cc290419Sopenharmony_ci SendChannelWithCmd(hChannel, formatCommand->cmdFlag, 596cc290419Sopenharmony_ci reinterpret_cast<uint8_t *>(const_cast<char *>(formatCommand->parameters.c_str())) + sizeCmdFlag, 597cc290419Sopenharmony_ci sizeSend - sizeCmdFlag); 598cc290419Sopenharmony_ci return false; 599cc290419Sopenharmony_ci } 600cc290419Sopenharmony_ci ptrServer->DispatchTaskData(hSession, hChannel->channelId, formatCommand->cmdFlag, 601cc290419Sopenharmony_ci reinterpret_cast<uint8_t *>(const_cast<char *>(formatCommand->parameters.c_str())) + sizeCmdFlag, 602cc290419Sopenharmony_ci sizeSend - sizeCmdFlag); 603cc290419Sopenharmony_ci } else { // Send to Daemon-side to do 604cc290419Sopenharmony_ci SendToDaemon(hChannel, formatCommand->cmdFlag, 605cc290419Sopenharmony_ci reinterpret_cast<uint8_t *>(const_cast<char *>(formatCommand->parameters.c_str())) + sizeCmdFlag, 606cc290419Sopenharmony_ci sizeSend - sizeCmdFlag); 607cc290419Sopenharmony_ci } 608cc290419Sopenharmony_ci return true; 609cc290419Sopenharmony_ci} 610cc290419Sopenharmony_ci 611cc290419Sopenharmony_civoid HdcServerForClient::HandleRemote(HChannel hChannel, string ¶meters, RemoteType flag) 612cc290419Sopenharmony_ci{ 613cc290419Sopenharmony_ci hChannel->remote = flag; 614cc290419Sopenharmony_ci int argc = 0; 615cc290419Sopenharmony_ci char **argv = Base::SplitCommandToArgs(parameters.c_str(), &argc); 616cc290419Sopenharmony_ci for (int i = 0; i < argc; i++) { 617cc290419Sopenharmony_ci if (argv[i] == CMDSTR_REMOTE_PARAMETER) { 618cc290419Sopenharmony_ci hChannel->fromClient = true; 619cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "remote client mode channelId:%u", hChannel->channelId); 620cc290419Sopenharmony_ci break; 621cc290419Sopenharmony_ci } 622cc290419Sopenharmony_ci } 623cc290419Sopenharmony_ci if (hChannel->fromClient) { 624cc290419Sopenharmony_ci string remote = CMDSTR_REMOTE_PARAMETER + " "; 625cc290419Sopenharmony_ci if (parameters.find(remote) != std::string::npos) { 626cc290419Sopenharmony_ci parameters.replace(parameters.find(remote), remote.size(), ""); 627cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "parameters: %s", parameters.c_str()); 628cc290419Sopenharmony_ci } 629cc290419Sopenharmony_ci } 630cc290419Sopenharmony_ci} 631cc290419Sopenharmony_ci 632cc290419Sopenharmony_cibool HdcServerForClient::DoCommandRemote(HChannel hChannel, void *formatCommandInput) 633cc290419Sopenharmony_ci{ 634cc290419Sopenharmony_ci TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput; 635cc290419Sopenharmony_ci bool ret = false; 636cc290419Sopenharmony_ci int sizeSend = formatCommand->parameters.size(); 637cc290419Sopenharmony_ci string cmdFlag; 638cc290419Sopenharmony_ci switch (formatCommand->cmdFlag) { 639cc290419Sopenharmony_ci // Some simple commands only need to forward the instruction, no need to start Task 640cc290419Sopenharmony_ci case CMD_SHELL_INIT: 641cc290419Sopenharmony_ci case CMD_SHELL_DATA: 642cc290419Sopenharmony_ci case CMD_UNITY_EXECUTE: 643cc290419Sopenharmony_ci case CMD_UNITY_REMOUNT: 644cc290419Sopenharmony_ci case CMD_UNITY_REBOOT: 645cc290419Sopenharmony_ci case CMD_UNITY_RUNMODE: 646cc290419Sopenharmony_ci case CMD_UNITY_HILOG: 647cc290419Sopenharmony_ci case CMD_UNITY_ROOTRUN: 648cc290419Sopenharmony_ci case CMD_JDWP_TRACK: 649cc290419Sopenharmony_ci case CMD_JDWP_LIST: { 650cc290419Sopenharmony_ci if (!SendToDaemon(hChannel, formatCommand->cmdFlag, 651cc290419Sopenharmony_ci reinterpret_cast<uint8_t *>(const_cast<char *>(formatCommand->parameters.c_str())), 652cc290419Sopenharmony_ci sizeSend)) { 653cc290419Sopenharmony_ci break; 654cc290419Sopenharmony_ci } 655cc290419Sopenharmony_ci ret = true; 656cc290419Sopenharmony_ci if (formatCommand->cmdFlag == CMD_SHELL_INIT) { 657cc290419Sopenharmony_ci hChannel->interactiveShellMode = true; 658cc290419Sopenharmony_ci } 659cc290419Sopenharmony_ci break; 660cc290419Sopenharmony_ci } 661cc290419Sopenharmony_ci case CMD_FILE_INIT: 662cc290419Sopenharmony_ci case CMD_FORWARD_INIT: 663cc290419Sopenharmony_ci case CMD_APP_INIT: 664cc290419Sopenharmony_ci case CMD_APP_UNINSTALL: 665cc290419Sopenharmony_ci case CMD_UNITY_BUGREPORT_INIT: 666cc290419Sopenharmony_ci case CMD_APP_SIDELOAD: 667cc290419Sopenharmony_ci case CMD_FLASHD_UPDATE_INIT: 668cc290419Sopenharmony_ci case CMD_FLASHD_FLASH_INIT: 669cc290419Sopenharmony_ci case CMD_FLASHD_ERASE: 670cc290419Sopenharmony_ci case CMD_FLASHD_FORMAT: { 671cc290419Sopenharmony_ci TaskCommand(hChannel, formatCommandInput); 672cc290419Sopenharmony_ci ret = true; 673cc290419Sopenharmony_ci break; 674cc290419Sopenharmony_ci } 675cc290419Sopenharmony_ci default: 676cc290419Sopenharmony_ci break; 677cc290419Sopenharmony_ci } 678cc290419Sopenharmony_ci if (!ret) { 679cc290419Sopenharmony_ci EchoClient(hChannel, MSG_FAIL, "Failed to communicate with daemon"); 680cc290419Sopenharmony_ci } 681cc290419Sopenharmony_ci return ret; 682cc290419Sopenharmony_ci} 683cc290419Sopenharmony_ci// Do not specify Target's operations no longer need to put it in the thread. 684cc290419Sopenharmony_cibool HdcServerForClient::DoCommand(HChannel hChannel, void *formatCommandInput) 685cc290419Sopenharmony_ci{ 686cc290419Sopenharmony_ci bool ret = false; 687cc290419Sopenharmony_ci TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput; 688cc290419Sopenharmony_ci if (!hChannel->hChildWorkTCP.loop || formatCommand->cmdFlag == CMD_FORWARD_REMOVE) { 689cc290419Sopenharmony_ci // Main thread command, direct Listen main thread 690cc290419Sopenharmony_ci ret = DoCommandLocal(hChannel, formatCommandInput); 691cc290419Sopenharmony_ci } else { // CONNECT DAEMON's work thread command, non-primary thread 692cc290419Sopenharmony_ci ret = DoCommandRemote(hChannel, formatCommandInput); 693cc290419Sopenharmony_ci } 694cc290419Sopenharmony_ci return ret; 695cc290419Sopenharmony_ci} 696cc290419Sopenharmony_ci 697cc290419Sopenharmony_ci// just call from BindChannelToSession 698cc290419Sopenharmony_ciHSession HdcServerForClient::FindAliveSessionFromDaemonMap(const HChannel hChannel) 699cc290419Sopenharmony_ci{ 700cc290419Sopenharmony_ci HSession hSession = nullptr; 701cc290419Sopenharmony_ci HDaemonInfo hdi = nullptr; 702cc290419Sopenharmony_ci HdcServer *ptrServer = (HdcServer *)clsServer; 703cc290419Sopenharmony_ci ptrServer->AdminDaemonMap(OP_QUERY, hChannel->connectKey, hdi); 704cc290419Sopenharmony_ci if (!hdi) { 705cc290419Sopenharmony_ci EchoClient(hChannel, MSG_FAIL, "Not match target founded, check connect-key please"); 706cc290419Sopenharmony_ci return nullptr; 707cc290419Sopenharmony_ci } 708cc290419Sopenharmony_ci if (hdi->connStatus != STATUS_CONNECTED) { 709cc290419Sopenharmony_ci EchoClient(hChannel, MSG_FAIL, "Device not founded or connected"); 710cc290419Sopenharmony_ci return nullptr; 711cc290419Sopenharmony_ci } 712cc290419Sopenharmony_ci if (hdi->hSession->isDead) { 713cc290419Sopenharmony_ci EchoClient(hChannel, MSG_FAIL, "Bind tartget session is dead"); 714cc290419Sopenharmony_ci return nullptr; 715cc290419Sopenharmony_ci } 716cc290419Sopenharmony_ci if (!hdi->hSession->handshakeOK) { 717cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "hSession handShake is false sid:%u cid:%u", 718cc290419Sopenharmony_ci hdi->hSession->sessionId, hChannel->channelId); 719cc290419Sopenharmony_ci const string errMsg = "[E000004]:The communication channel is being established.\r\n"\ 720cc290419Sopenharmony_ci "Please wait for several seconds and try again."; 721cc290419Sopenharmony_ci EchoClient(hChannel, MSG_FAIL, errMsg.c_str()); 722cc290419Sopenharmony_ci return nullptr; 723cc290419Sopenharmony_ci } 724cc290419Sopenharmony_ci hSession = reinterpret_cast<HSession>(hdi->hSession); 725cc290419Sopenharmony_ci return hSession; 726cc290419Sopenharmony_ci} 727cc290419Sopenharmony_ci 728cc290419Sopenharmony_ciint HdcServerForClient::BindChannelToSession(HChannel hChannel, uint8_t *bufPtr, const int bytesIO) 729cc290419Sopenharmony_ci{ 730cc290419Sopenharmony_ci if (FindAliveSessionFromDaemonMap(hChannel) == nullptr) { 731cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "Find no alive session channelId:%u", hChannel->channelId); 732cc290419Sopenharmony_ci return ERR_SESSION_NOFOUND; 733cc290419Sopenharmony_ci } 734cc290419Sopenharmony_ci bool isClosing = uv_is_closing((const uv_handle_t *)&hChannel->hWorkTCP); 735cc290419Sopenharmony_ci if (!isClosing && (hChannel->fdChildWorkTCP = Base::DuplicateUvSocket(&hChannel->hWorkTCP)) < 0) { 736cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "Duplicate socket failed channelId:%u", hChannel->channelId); 737cc290419Sopenharmony_ci return ERR_SOCKET_DUPLICATE; 738cc290419Sopenharmony_ci } 739cc290419Sopenharmony_ci uv_close_cb funcWorkTcpClose = [](uv_handle_t *handle) -> void { 740cc290419Sopenharmony_ci HChannel hChannel = (HChannel)handle->data; 741cc290419Sopenharmony_ci --hChannel->ref; 742cc290419Sopenharmony_ci }; 743cc290419Sopenharmony_ci ++hChannel->ref; 744cc290419Sopenharmony_ci if (!isClosing) { 745cc290419Sopenharmony_ci uv_close((uv_handle_t *)&hChannel->hWorkTCP, funcWorkTcpClose); 746cc290419Sopenharmony_ci } 747cc290419Sopenharmony_ci Base::DoNextLoop(loopMain, hChannel, [](const uint8_t flag, string &msg, const void *data) { 748cc290419Sopenharmony_ci // Thread message can avoid using thread lock and improve program efficiency 749cc290419Sopenharmony_ci // If not next loop call, ReadStream will thread conflict 750cc290419Sopenharmony_ci HChannel hChannel = (HChannel)data; 751cc290419Sopenharmony_ci auto thisClass = (HdcServerForClient *)hChannel->clsChannel; 752cc290419Sopenharmony_ci HSession hSession = nullptr; 753cc290419Sopenharmony_ci if ((hSession = thisClass->FindAliveSessionFromDaemonMap(hChannel)) == nullptr) { 754cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "hSession nullptr channelId:%u", hChannel->channelId); 755cc290419Sopenharmony_ci return; 756cc290419Sopenharmony_ci } 757cc290419Sopenharmony_ci auto ctrl = HdcSessionBase::BuildCtrlString(SP_ATTACH_CHANNEL, hChannel->channelId, nullptr, 0); 758cc290419Sopenharmony_ci Base::SendToPollFd(hSession->ctrlFd[STREAM_MAIN], ctrl.data(), ctrl.size()); 759cc290419Sopenharmony_ci }); 760cc290419Sopenharmony_ci return RET_SUCCESS; 761cc290419Sopenharmony_ci} 762cc290419Sopenharmony_ci 763cc290419Sopenharmony_cibool HdcServerForClient::CheckAutoFillTarget(HChannel hChannel) 764cc290419Sopenharmony_ci{ 765cc290419Sopenharmony_ci HdcServer *ptrServer = (HdcServer *)clsServer; 766cc290419Sopenharmony_ci if (!hChannel->connectKey.size()) { 767cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "connectKey.size 0 channelId:%u", hChannel->channelId); 768cc290419Sopenharmony_ci return false; // Operation of non-bound destination of scanning 769cc290419Sopenharmony_ci } 770cc290419Sopenharmony_ci if (hChannel->connectKey == CMDSTR_CONNECT_ANY) { 771cc290419Sopenharmony_ci HDaemonInfo hdiOld = nullptr; 772cc290419Sopenharmony_ci ptrServer->AdminDaemonMap(OP_GET_ONLY, "", hdiOld); 773cc290419Sopenharmony_ci if (!hdiOld) { 774cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "No any key found channelId:%u", hChannel->channelId); 775cc290419Sopenharmony_ci return false; 776cc290419Sopenharmony_ci } 777cc290419Sopenharmony_ci if (!hdiOld->hSession) { 778cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "hSession is null. channelId:%u", hChannel->channelId); 779cc290419Sopenharmony_ci return false; 780cc290419Sopenharmony_ci } 781cc290419Sopenharmony_ci if (!hdiOld->hSession->handshakeOK) { 782cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "hSession handShake is false SessionId:%u", hdiOld->hSession->sessionId); 783cc290419Sopenharmony_ci return false; 784cc290419Sopenharmony_ci } 785cc290419Sopenharmony_ci hChannel->connectKey = hdiOld->connectKey; 786cc290419Sopenharmony_ci return true; 787cc290419Sopenharmony_ci } 788cc290419Sopenharmony_ci return true; 789cc290419Sopenharmony_ci} 790cc290419Sopenharmony_ci 791cc290419Sopenharmony_ciint HdcServerForClient::ChannelHandShake(HChannel hChannel, uint8_t *bufPtr, const int bytesIO) 792cc290419Sopenharmony_ci{ 793cc290419Sopenharmony_ci vector<uint8_t> rebuildHandshake; 794cc290419Sopenharmony_ci rebuildHandshake.insert(rebuildHandshake.end(), bufPtr, bufPtr + bytesIO); 795cc290419Sopenharmony_ci rebuildHandshake.push_back(0x00); 796cc290419Sopenharmony_ci struct ChannelHandShake *handShake = reinterpret_cast<struct ChannelHandShake *>(rebuildHandshake.data()); 797cc290419Sopenharmony_ci if (strncmp(handShake->banner, HANDSHAKE_MESSAGE.c_str(), HANDSHAKE_MESSAGE.size())) { 798cc290419Sopenharmony_ci hChannel->availTailIndex = 0; 799cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "Channel Hello failed"); 800cc290419Sopenharmony_ci return ERR_HANDSHAKE_NOTMATCH; 801cc290419Sopenharmony_ci } 802cc290419Sopenharmony_ci if (strlen(handShake->connectKey) > sizeof(handShake->connectKey)) { 803cc290419Sopenharmony_ci hChannel->availTailIndex = 0; 804cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "Connectkey's size incorrect"); 805cc290419Sopenharmony_ci return ERR_HANDSHAKE_CONNECTKEY_FAILED; 806cc290419Sopenharmony_ci } 807cc290419Sopenharmony_ci // channel handshake step3 808cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "ServerForClient cid:%u sid:%u handshake finished", 809cc290419Sopenharmony_ci hChannel->channelId, hChannel->targetSessionId); 810cc290419Sopenharmony_ci hChannel->connectKey = handShake->connectKey; 811cc290419Sopenharmony_ci hChannel->handshakeOK = true; 812cc290419Sopenharmony_ci if (handShake->banner[WAIT_TAG_OFFSET] == WAIT_DEVICE_TAG || !CheckAutoFillTarget(hChannel)) { 813cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "No target channelId:%u", hChannel->channelId); 814cc290419Sopenharmony_ci return 0; 815cc290419Sopenharmony_ci } 816cc290419Sopenharmony_ci // channel handshake stBindChannelToSession 817cc290419Sopenharmony_ci if (BindChannelToSession(hChannel, nullptr, 0)) { 818cc290419Sopenharmony_ci hChannel->availTailIndex = 0; 819cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "BindChannelToSession failed channelId:%u sid:%u", 820cc290419Sopenharmony_ci hChannel->channelId, hChannel->targetSessionId); 821cc290419Sopenharmony_ci return ERR_GENERIC; 822cc290419Sopenharmony_ci } 823cc290419Sopenharmony_ci return 0; 824cc290419Sopenharmony_ci} 825cc290419Sopenharmony_ci 826cc290419Sopenharmony_civoid HdcServerForClient::ReportServerVersion(HChannel hChannel) 827cc290419Sopenharmony_ci{ 828cc290419Sopenharmony_ci string version = Base::GetVersion(); 829cc290419Sopenharmony_ci SendChannelWithCmd(hChannel, CMD_CHECK_SERVER, 830cc290419Sopenharmony_ci const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(version.c_str())), 831cc290419Sopenharmony_ci version.size()); 832cc290419Sopenharmony_ci} 833cc290419Sopenharmony_ci 834cc290419Sopenharmony_ci// Here is Server to get data, the source is the SERVER's ChildWork to send data 835cc290419Sopenharmony_ciint HdcServerForClient::ReadChannel(HChannel hChannel, uint8_t *bufPtr, const int bytesIO) 836cc290419Sopenharmony_ci{ 837cc290419Sopenharmony_ci int ret = 0; 838cc290419Sopenharmony_ci if (!hChannel->handshakeOK) { 839cc290419Sopenharmony_ci return ChannelHandShake(hChannel, bufPtr, bytesIO); 840cc290419Sopenharmony_ci } 841cc290419Sopenharmony_ci HDaemonInfo hdi = nullptr; 842cc290419Sopenharmony_ci HdcServer *ptrServer = (HdcServer *)clsServer; 843cc290419Sopenharmony_ci ptrServer->AdminDaemonMap(OP_QUERY, hChannel->connectKey, hdi); 844cc290419Sopenharmony_ci if (hdi && !hdi->emgmsg.empty()) { 845cc290419Sopenharmony_ci EchoClient(hChannel, MSG_FAIL, hdi->emgmsg.c_str()); 846cc290419Sopenharmony_ci return ERR_GENERIC; 847cc290419Sopenharmony_ci } 848cc290419Sopenharmony_ci uint16_t command = *reinterpret_cast<uint16_t *>(bufPtr); 849cc290419Sopenharmony_ci if (command != 0 && (hChannel->remote > RemoteType::REMOTE_NONE)) { 850cc290419Sopenharmony_ci // server directly passthrough file command to daemon 851cc290419Sopenharmony_ci if (!SendToDaemon(hChannel, command, bufPtr + sizeof(uint16_t), bytesIO - sizeof(uint16_t))) { 852cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "Client ReadChannel : direct send to daemon failed"); 853cc290419Sopenharmony_ci } 854cc290419Sopenharmony_ci return ret; 855cc290419Sopenharmony_ci } 856cc290419Sopenharmony_ci struct TranslateCommand::FormatCommand formatCommand = { 0 }; 857cc290419Sopenharmony_ci if (!hChannel->interactiveShellMode) { 858cc290419Sopenharmony_ci string retEcho = String2FormatCommand(reinterpret_cast<char *>(bufPtr), bytesIO, &formatCommand); 859cc290419Sopenharmony_ci if (retEcho.length()) { 860cc290419Sopenharmony_ci if (!strncmp(reinterpret_cast<char *>(bufPtr), CMDSTR_SOFTWARE_HELP.c_str(), 861cc290419Sopenharmony_ci CMDSTR_SOFTWARE_HELP.size()) || 862cc290419Sopenharmony_ci !strcmp(reinterpret_cast<char *>(bufPtr), CMDSTR_SOFTWARE_VERSION.c_str()) || 863cc290419Sopenharmony_ci !strcmp(reinterpret_cast<char *>(bufPtr), "flash")) { 864cc290419Sopenharmony_ci EchoClient(hChannel, MSG_OK, retEcho.c_str()); 865cc290419Sopenharmony_ci } else { 866cc290419Sopenharmony_ci EchoClient(hChannel, MSG_FAIL, retEcho.c_str()); 867cc290419Sopenharmony_ci } 868cc290419Sopenharmony_ci } 869cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "ReadChannel cid:%u sid:%u key:%s command: %s", 870cc290419Sopenharmony_ci hChannel->channelId, hChannel->targetSessionId, Hdc::MaskString(hChannel->connectKey).c_str(), bufPtr); 871cc290419Sopenharmony_ci if (formatCommand.bJumpDo) { 872cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "ReadChannel bJumpDo true"); 873cc290419Sopenharmony_ci return -10; // -10 error formatCommand 874cc290419Sopenharmony_ci } 875cc290419Sopenharmony_ci } else { 876cc290419Sopenharmony_ci formatCommand.parameters = string(reinterpret_cast<char *>(bufPtr), bytesIO); 877cc290419Sopenharmony_ci formatCommand.cmdFlag = CMD_SHELL_DATA; 878cc290419Sopenharmony_ci } 879cc290419Sopenharmony_ci 880cc290419Sopenharmony_ci if (!DoCommand(hChannel, &formatCommand)) { 881cc290419Sopenharmony_ci return -3; // -3: error or want close 882cc290419Sopenharmony_ci } 883cc290419Sopenharmony_ci ret = bytesIO; 884cc290419Sopenharmony_ci return ret; 885cc290419Sopenharmony_ci}; 886cc290419Sopenharmony_ci 887cc290419Sopenharmony_ci// avoid session dead 888cc290419Sopenharmony_ciHSession HdcServerForClient::FindAliveSession(uint32_t sessionId) 889cc290419Sopenharmony_ci{ 890cc290419Sopenharmony_ci HdcServer *ptrServer = (HdcServer *)clsServer; 891cc290419Sopenharmony_ci HSession hSession = ptrServer->AdminSession(OP_QUERY, sessionId, nullptr); 892cc290419Sopenharmony_ci if (!hSession || hSession->isDead) { 893cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "FindAliveSession hSession nullptr or isDead sessionId:%u", sessionId); 894cc290419Sopenharmony_ci return nullptr; 895cc290419Sopenharmony_ci } else { 896cc290419Sopenharmony_ci return hSession; 897cc290419Sopenharmony_ci } 898cc290419Sopenharmony_ci} 899cc290419Sopenharmony_ci 900cc290419Sopenharmony_cibool HdcServerForClient::ChannelSendSessionCtrlMsg(vector<uint8_t> &ctrlMsg, uint32_t sessionId) 901cc290419Sopenharmony_ci{ 902cc290419Sopenharmony_ci HSession hSession = FindAliveSession(sessionId); 903cc290419Sopenharmony_ci if (!hSession) { 904cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "ChannelSendSessionCtrlMsg hSession nullptr sessionId:%u", sessionId); 905cc290419Sopenharmony_ci return false; 906cc290419Sopenharmony_ci } 907cc290419Sopenharmony_ci int rc = Base::SendToPollFd(hSession->ctrlFd[STREAM_MAIN], ctrlMsg.data(), ctrlMsg.size()); 908cc290419Sopenharmony_ci if (rc <= 0) { 909cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "send ctrlmsg failed sessionId:%u rc:%d", sessionId, rc); 910cc290419Sopenharmony_ci } 911cc290419Sopenharmony_ci return rc > 0; 912cc290419Sopenharmony_ci} 913cc290419Sopenharmony_ci} // namespace Hdc 914