• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 #include "server_for_client.h"
16 #ifndef TEST_HASH
17 #include "hdc_hash_gen.h"
18 #endif
19 #include "server.h"
20 #ifdef __OHOS__
21 #include <sys/un.h>
22 #endif
23 #include "host_shell_option.h"
24 namespace Hdc {
25 static const int MAX_RETRY_COUNT = 500;
26 static const int MAX_CONNECT_DEVICE_RETRY_COUNT = 100;
27 #ifdef __OHOS__
28 static const int MAX_CONNECTIONS_COUNT = 16;
29 #endif
30 
HdcServerForClient(const bool serverOrClient,const string & addrString,void * pClsServer,uv_loop_t * loopMainIn)31 HdcServerForClient::HdcServerForClient(const bool serverOrClient, const string &addrString, void *pClsServer,
32                                        uv_loop_t *loopMainIn)
33     : HdcChannelBase(serverOrClient, addrString, loopMainIn)
34 {
35     clsServer = pClsServer;
36 }
37 
~HdcServerForClient()38 HdcServerForClient::~HdcServerForClient()
39 {
40     WRITE_LOG(LOG_DEBUG, "~HdcServerForClient");
41 }
42 
Stop()43 void HdcServerForClient::Stop()
44 {
45     Base::TryCloseHandle((uv_handle_t *)&tcpListen);
46 #ifdef __OHOS__
47     Base::TryCloseHandle((uv_handle_t *)&udsListen);
48 #endif
49 }
50 
GetTCPListenPort()51 uint16_t HdcServerForClient::GetTCPListenPort()
52 {
53     return channelPort;
54 }
55 
56 #ifdef __OHOS__
AcceptUdsClient(uv_stream_t * server,int status)57 void HdcServerForClient::AcceptUdsClient(uv_stream_t *server, int status)
58 {
59     StartTraceScope("HdcServerForClient::AcceptUdsClient");
60     HdcServerForClient *thisClass = (HdcServerForClient *)(((uv_pipe_t *)server)->data);
61     CALLSTAT_GUARD(thisClass->loopMainStatus, server->loop, "HdcServerForClient::AcceptUdsClient");
62     HChannel hChannel = new HdcChannel();
63     if (hChannel == nullptr) {
64         WRITE_LOG(LOG_FATAL, "AcceptUdsClient new channel fail");
65         return;
66     }
67     hChannel->isUds = true;
68     uint32_t uid = thisClass->MallocChannel(&hChannel);
69     hChannel->startTime = Base::GetRuntimeMSec();
70     int rc = 0;
71     if ((rc = uv_accept(server, (uv_stream_t *)&hChannel->hWorkUds)) < 0) {
72         WRITE_LOG(LOG_FATAL, "AcceptUdsClient uv_accept error rc:%d uid:%u", rc, uid);
73         thisClass->FreeChannel(uid);
74         return;
75     }
76     WRITE_LOG(LOG_DEBUG, "AcceptUdsClient uid:%u", uid);
77     // limit first recv
78     int bufMaxSize = 0;
79     uv_recv_buffer_size((uv_handle_t *)&hChannel->hWorkUds, &bufMaxSize);
80     auto funcChannelHeaderAlloc = [](uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf) -> void {
81         HChannel context = (HChannel)handle->data;
82         Base::ReallocBuf(&context->ioBuf, &context->bufSize, Base::GetMaxBufSize() * BUF_EXTEND_SIZE);
83         buf->base = (char *)context->ioBuf + context->availTailIndex;
84 #ifdef HDC_VERSION_CHECK
85         buf->len = sizeof(struct ChannelHandShake) + DWORD_SERIALIZE_SIZE;  // only recv static size
86 #else
87         buf->len = offsetof(struct ChannelHandShake, version) + DWORD_SERIALIZE_SIZE;
88 #endif
89     };
90     // first packet static size, after this packet will be dup for normal recv
91     uv_read_start((uv_stream_t *)&hChannel->hWorkUds, funcChannelHeaderAlloc, ReadStream);
92     // channel handshake step1
93     struct ChannelHandShake handShake = {};
94     if (EOK == strcpy_s(handShake.banner, sizeof(handShake.banner), HANDSHAKE_MESSAGE.c_str())) {
95         handShake.banner[BANNER_FEATURE_TAG_OFFSET] = HUGE_BUF_TAG; // set feature tag for huge buf size
96         handShake.banner[SERVICE_KILL_OFFSET] = SERVICE_KILL_TAG;
97         handShake.channelId = htonl(hChannel->channelId);
98         string ver = Base::GetVersion() + HDC_MSG_HASH;
99         WRITE_LOG(LOG_DEBUG, "Server ver:%s", ver.c_str());
100         if (EOK != strcpy_s(handShake.version, sizeof(handShake.version), ver.c_str())) {
101             WRITE_LOG(LOG_FATAL, "strcpy_s failed");
102             return;
103         }
104 #ifdef HDC_VERSION_CHECK
105     thisClass->Send(hChannel->channelId, (uint8_t *)&handShake, sizeof(struct ChannelHandShake));
106 #else
107     // do not send version message if check feature disable
108     thisClass->Send(hChannel->channelId, reinterpret_cast<uint8_t *>(&handShake),
109                     offsetof(struct ChannelHandShake, version));
110 #endif
111     }
112 }
113 #endif
114 
AcceptClient(uv_stream_t * server,int status)115 void HdcServerForClient::AcceptClient(uv_stream_t *server, int status)
116 {
117     StartTraceScope("HdcServerForClient::AcceptClient");
118     uv_tcp_t *pServTCP = (uv_tcp_t *)server;
119     HdcServerForClient *thisClass = (HdcServerForClient *)pServTCP->data;
120     CALLSTAT_GUARD(thisClass->loopMainStatus, server->loop, "HdcServerForClient::AcceptClient");
121 #ifdef HOST_OHOS
122     HChannel hChannel = new HdcChannel();
123     if (hChannel == nullptr) {
124         WRITE_LOG(LOG_FATAL, "AcceptClient new channel fail");
125         return;
126     }
127 #else
128     HChannel hChannel = nullptr;
129 #endif
130     uint32_t uid = thisClass->MallocChannel(&hChannel);
131     if (!hChannel) {
132         WRITE_LOG(LOG_FATAL, "AcceptClient hChannel is nullptr");
133         return;
134     }
135     hChannel->startTime = Base::GetRuntimeMSec();
136     int rc = uv_accept(server, (uv_stream_t *)&hChannel->hWorkTCP);
137     if (rc < 0) {
138         WRITE_LOG(LOG_FATAL, "AcceptClient uv_accept error rc:%d uid:%u", rc, uid);
139         thisClass->FreeChannel(uid);
140         return;
141     }
142     WRITE_LOG(LOG_DEBUG, "AcceptClient uid:%u", uid);
143     // limit first recv
144     int bufMaxSize = 0;
145     uv_recv_buffer_size((uv_handle_t *)&hChannel->hWorkTCP, &bufMaxSize);
146     auto funcChannelHeaderAlloc = [](uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf) -> void {
147         HChannel context = (HChannel)handle->data;
148         Base::ReallocBuf(&context->ioBuf, &context->bufSize, Base::GetMaxBufSize() * BUF_EXTEND_SIZE);
149         buf->base = (char *)context->ioBuf + context->availTailIndex;
150 #ifdef HDC_VERSION_CHECK
151         buf->len = sizeof(struct ChannelHandShake) + DWORD_SERIALIZE_SIZE;  // only recv static size
152 #else
153         buf->len = offsetof(struct ChannelHandShake, version) + DWORD_SERIALIZE_SIZE;
154 #endif
155     };
156     // first packet static size, after this packet will be dup for normal recv
157     uv_read_start((uv_stream_t *)&hChannel->hWorkTCP, funcChannelHeaderAlloc, ReadStream);
158     // channel handshake step1
159     struct ChannelHandShake handShake = {};
160     if (EOK == strcpy_s(handShake.banner, sizeof(handShake.banner), HANDSHAKE_MESSAGE.c_str())) {
161         handShake.banner[BANNER_FEATURE_TAG_OFFSET] = HUGE_BUF_TAG; // set feature tag for huge buf size
162 #ifdef HOST_OHOS
163         handShake.banner[SERVICE_KILL_OFFSET] = SERVICE_KILL_TAG;
164 #endif
165         handShake.channelId = htonl(hChannel->channelId);
166         string ver = Base::GetVersion() + HDC_MSG_HASH;
167         WRITE_LOG(LOG_DEBUG, "Server ver:%s", ver.c_str());
168         if (EOK != strcpy_s(handShake.version, sizeof(handShake.version), ver.c_str())) {
169             WRITE_LOG(LOG_FATAL, "strcpy_s failed");
170             return;
171         }
172 #ifdef HDC_VERSION_CHECK
173     thisClass->Send(hChannel->channelId, (uint8_t *)&handShake, sizeof(struct ChannelHandShake));
174 #else
175     // do not send version message if check feature disable
176     thisClass->Send(hChannel->channelId, reinterpret_cast<uint8_t *>(&handShake),
177                     offsetof(struct ChannelHandShake, version));
178 #endif
179     }
180 }
181 
182 #ifdef __OHOS__
SetUdsListen()183 bool HdcServerForClient::SetUdsListen()
184 {
185     udsListen.data = this;
186     int ret = -1;
187     ret = uv_pipe_init(loopMain, &udsListen, 0);
188 
189     unlink(UDS_PATH.c_str());
190 
191     if ((ret = uv_pipe_bind(&udsListen, UDS_PATH.c_str())) != 0) {
192         WRITE_LOG(LOG_WARN, "bind uds addr fail! ret:%d", ret);
193         return false;
194     }
195 
196     uv_fs_t req = {};
197     ret = uv_fs_chmod(nullptr, &req, UDS_PATH.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
198         nullptr);
199     if (ret < 0) {
200         char buffer[BUF_SIZE_DEFAULT] = { 0 };
201         uv_strerror_r(ret, buffer, BUF_SIZE_DEFAULT);
202         WRITE_LOG(LOG_WARN, "uv_fs_chmod uds failed %s", buffer);
203         uv_fs_req_cleanup(&req);
204         return false;
205     }
206     uv_fs_req_cleanup(&req);
207 
208     if ((ret = uv_listen((uv_stream_t *)&udsListen, MAX_CONNECTIONS_COUNT, AcceptUdsClient)) != 0) {
209         WRITE_LOG(LOG_WARN, "uds listen fail! ret:%d", ret);
210         return false;
211     }
212     return true;
213 }
214 #endif
215 
SetTCPListen()216 bool HdcServerForClient::SetTCPListen()
217 {
218     char buffer[BUF_SIZE_DEFAULT] = { 0 };
219     tcpListen.data = this;
220     struct sockaddr_in6 addr;
221     uv_tcp_init(loopMain, &tcpListen);
222 
223     WRITE_LOG(LOG_DEBUG, "channelHost %s, port: %d", channelHost.c_str(), channelPort);
224     int rc = uv_ip6_addr(channelHost.c_str(), channelPort, &addr);
225     if (rc != 0) {
226         uv_strerror_r(rc, buffer, BUF_SIZE_DEFAULT);
227         WRITE_LOG(LOG_FATAL, "uv_ip6_addr %d %s", rc, buffer);
228         return false;
229     }
230     rc = uv_tcp_bind(&tcpListen, (const struct sockaddr *)&addr, 0);
231     if (rc != 0) {
232         WRITE_LOG(LOG_WARN, "uv_tcp_bind ipv6 %d", rc);
233         if (rc == -EAFNOSUPPORT) {
234             size_t index = channelHost.find(IPV4_MAPPING_PREFIX);
235             size_t size = IPV4_MAPPING_PREFIX.size();
236             if (index != std::string::npos) {
237                 struct sockaddr_in addr4v;
238                 std::string ipv4 = channelHost.substr(index + size);
239                 uv_ip4_addr(ipv4.c_str(), channelPort, &addr4v);
240                 rc = uv_tcp_bind(&tcpListen, (const struct sockaddr *)&addr4v, 0);
241                 if (rc != 0) {
242                     uv_strerror_r(rc, buffer, BUF_SIZE_DEFAULT);
243                     WRITE_LOG(LOG_FATAL, "uv_tcp_bind ipv4 %s failed %d %s",
244                         ipv4.c_str(), rc, buffer);
245                     return false;
246                 }
247             }
248         } else {
249             uv_strerror_r(rc, buffer, BUF_SIZE_DEFAULT);
250             WRITE_LOG(LOG_FATAL, "uv_tcp_bind %d %s", rc, buffer);
251             return false;
252         }
253     }
254     int backLog = 128;
255     rc = uv_listen((uv_stream_t *)&tcpListen, backLog, (uv_connection_cb)AcceptClient);
256     if (rc != 0) {
257         uv_strerror_r(rc, buffer, BUF_SIZE_DEFAULT);
258         WRITE_LOG(LOG_FATAL, "uv_listen %d %s", rc, buffer);
259         return false;
260     }
261     return true;
262 }
263 
Initial()264 int HdcServerForClient::Initial()
265 {
266     if (!clsServer) {
267         WRITE_LOG(LOG_FATAL, "Module client initial failed");
268         return -1;
269     }
270 #ifndef __OHOS__
271     if (!channelHostPort.size() || !channelHost.size() || !channelPort) {
272         WRITE_LOG(LOG_FATAL, "Listen string initial failed");
273         return -2;  // -2:err for Listen initial failed
274     }
275     if (!SetTCPListen()) {
276         WRITE_LOG(LOG_FATAL, "SetTCPListen failed");
277         int listenError = -3;  // -3:error for SetTCPListen failed
278         return listenError;
279     }
280 #else
281     if (!channelHostPort.size() || !channelHost.size() || !channelPort) {
282         WRITE_LOG(LOG_FATAL, "Listen string initial failed");
283     } else {
284         if (!SetTCPListen()) {
285             WRITE_LOG(LOG_FATAL, "SetTCPListen failed");
286         }
287     }
288     if (!SetUdsListen()) {
289         WRITE_LOG(LOG_FATAL, "SetUdsListen failed");
290         int listenError = -3; // -3:error for SetUdsListen failed
291         return listenError;
292     }
293 #endif
294 
295     return 0;
296 }
297 
EchoClient(HChannel hChannel,MessageLevel level,const char * msg,...)298 void HdcServerForClient::EchoClient(HChannel hChannel, MessageLevel level, const char *msg, ...)
299 {
300     StartTraceScope("HdcServerForClient::EchoClient");
301     string logInfo = "";
302     switch (level) {
303         case MSG_FAIL:
304             logInfo = MESSAGE_FAIL;
305             break;
306         case MSG_INFO:
307             logInfo = MESSAGE_INFO;
308             break;
309         default:  // successful, not append extra info
310             break;
311     }
312     va_list vaArgs;
313     va_start(vaArgs, msg);
314     string log = logInfo + Base::StringFormat(msg, vaArgs);
315     va_end(vaArgs);
316     if (log.back() != '\n') {
317         log += "\r\n";
318     }
319     SendChannel(hChannel, const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(log.c_str())), log.size());
320 }
321 
EchoClientRaw(const HChannel hChannel,uint8_t * payload,const int payloadSize)322 void HdcServerForClient::EchoClientRaw(const HChannel hChannel, uint8_t *payload, const int payloadSize)
323 {
324     SendChannel(hChannel, payload, payloadSize);
325 }
326 
327 // HdcServerForClient passthrough file command to client
SendCommandToClient(const HChannel hChannel,const uint16_t commandFlag,uint8_t * payload,const int payloadSize)328 void HdcServerForClient::SendCommandToClient(const HChannel hChannel, const uint16_t commandFlag,
329                                              uint8_t *payload, const int payloadSize)
330 {
331     if (Base::CanPrintCmd(commandFlag)) {
332         WRITE_LOG(LOG_INFO, "SendCommandToClient cid:%u sid:%u commandID:%u payloadSize:%d",
333             hChannel->channelId, hChannel->targetSessionId, commandFlag, payloadSize);
334     }
335     SendChannelWithCmd(hChannel, commandFlag, payload, payloadSize);
336 }
337 
SendToDaemon(HChannel hChannel,const uint16_t commandFlag,uint8_t * bufPtr,const int bufSize)338 bool HdcServerForClient::SendToDaemon(HChannel hChannel, const uint16_t commandFlag, uint8_t *bufPtr, const int bufSize)
339 {
340     StartTraceScope("HdcServerForClient::SendToDaemon");
341     HDaemonInfo hdi = nullptr;
342     bool ret = false;
343     HdcServer *ptrServer = (HdcServer *)clsServer;
344     if (Base::CanPrintCmd(commandFlag)) {
345         WRITE_LOG(LOG_INFO, "SendToDaemon cid:%u sid:%u key:%s commandID:%u sizeSend:%d", hChannel->channelId,
346             hChannel->targetSessionId, Hdc::MaskString(hChannel->connectKey).c_str(), commandFlag, bufSize);
347     }
348     while (true) {
349         ptrServer->AdminDaemonMap(OP_QUERY, hChannel->connectKey, hdi);
350         if (hdi == nullptr) {
351             WRITE_LOG(LOG_FATAL, "SendToDaemon hdi nullptr");
352             break;
353         }
354         if (hdi->connStatus != STATUS_CONNECTED) {
355             WRITE_LOG(LOG_FATAL, "SendToDaemon not connected");
356             break;
357         }
358         if (!hdi->hSession) {
359             WRITE_LOG(LOG_FATAL, "SendToDaemon hdi->hSession nullptr");
360             break;
361         }
362         if (ptrServer->Send(hdi->hSession->sessionId, hChannel->channelId, commandFlag, bufPtr, bufSize) < 0) {
363             WRITE_LOG(LOG_FATAL, "SendToDaemon Send failed channelId:%u", hChannel->channelId);
364             break;
365         }
366         ret = true;
367         break;
368     }
369     return ret;
370 }
371 
OrderFindTargets(HChannel hChannel)372 void HdcServerForClient::OrderFindTargets(HChannel hChannel)
373 {
374     int count = 0;
375     EchoClient(hChannel, MSG_INFO, "Please add HDC server's firewall ruler to allow udp incoming, udpport:%d",
376                DEFAULT_PORT);
377     HdcServer *ptrServer = (HdcServer *)clsServer;
378     ptrServer->clsTCPClt->FindLanDaemon();
379     list<string> &lst = ptrServer->clsTCPClt->lstDaemonResult;
380     // refresh main list
381     HdcDaemonInformation di;
382     while (!lst.empty()) {
383         di = {};
384         ++count;
385         di.connectKey = lst.front();
386         di.connType = CONN_TCP;
387         di.connStatus = STATUS_READY;
388         di.inited = false;
389         HDaemonInfo pDi = reinterpret_cast<HDaemonInfo>(&di);
390         ptrServer->AdminDaemonMap(OP_ADD, STRING_EMPTY, pDi);
391         lst.pop_front();
392     }
393     EchoClient(hChannel, MSG_INFO, "Broadcast find daemon, total:%d", count);
394 #ifdef UNIT_TEST
395     string bufString = std::to_string(count);
396     Base::WriteBinFile((UT_TMP_PATH + "/base-discover.result").c_str(), (uint8_t *)bufString.c_str(), bufString.size(),
397                        true);
398 #endif
399 }
400 
OrderConnecTargetResult(uv_timer_t * req)401 void HdcServerForClient::OrderConnecTargetResult(uv_timer_t *req)
402 {
403     HChannel hChannel = (HChannel)req->data;
404     HdcServerForClient *thisClass = (HdcServerForClient *)hChannel->clsChannel;
405     HdcServer *ptrServer = (HdcServer *)thisClass->clsServer;
406     bool bConnectOK = false;
407     bool bExitRepet = false;
408     HDaemonInfo hdi = nullptr;
409     string sRet;
410     string target = std::string(hChannel->bufStd + 2);
411     if (target == "any") {
412         ptrServer->AdminDaemonMap(OP_GET_ANY, target, hdi);
413     } else {
414         ptrServer->AdminDaemonMap(OP_QUERY, target, hdi);
415     }
416     if (hdi && hdi->connStatus == STATUS_CONNECTED) {
417         bConnectOK = true;
418     }
419     while (true) {
420         if (bConnectOK) {
421             bExitRepet = true;
422             if (hChannel->isCheck) {
423                 WRITE_LOG(LOG_INFO, "%s check device success and remove %s", __FUNCTION__, hChannel->key.c_str());
424                 thisClass->CommandRemoveSession(hChannel, hChannel->key.c_str());
425                 thisClass->EchoClient(hChannel, MSG_OK, const_cast<char *>(hdi->version.c_str()));
426             } else {
427                 sRet = "Connect OK";
428                 thisClass->EchoClient(hChannel, MSG_OK, const_cast<char *>(sRet.c_str()));
429             }
430             break;
431         } else {
432             uint16_t *bRetryCount = reinterpret_cast<uint16_t *>(hChannel->bufStd);
433             ++(*bRetryCount);
434             if (*bRetryCount > MAX_RETRY_COUNT ||
435                 (hChannel->connectLocalDevice && *bRetryCount > MAX_CONNECT_DEVICE_RETRY_COUNT)) {
436                 // 5s or localDevice 1s
437                 bExitRepet = true;
438                 sRet = "Connect failed";
439                 thisClass->EchoClient(hChannel, MSG_FAIL, const_cast<char *>(sRet.c_str()));
440                 hdi->inited = false;
441                 hdi->connStatus = STATUS_OFFLINE;
442                 ptrServer->AdminDaemonMap(OP_UPDATE, target, hdi);
443                 break;
444             }
445         }
446         break;
447     }
448     if (bExitRepet) {
449         thisClass->FreeChannel(hChannel->channelId);
450         Base::TryCloseHandle((const uv_handle_t *)req, Base::CloseTimerCallback);
451     }
452 }
453 
NewConnectTry(void * ptrServer,HChannel hChannel,const string & connectKey,bool isCheck)454 bool HdcServerForClient::NewConnectTry(void *ptrServer, HChannel hChannel, const string &connectKey, bool isCheck)
455 {
456 #ifdef HDC_DEBUG
457     WRITE_LOG(LOG_ALL, "%s %s", __FUNCTION__, Hdc::MaskString(connectKey).c_str());
458 #endif
459     int childRet = ((HdcServer *)ptrServer)->CreateConnect(connectKey, isCheck);
460     bool ret = false;
461     int connectError = -2;
462     constexpr uint8_t bufOffsetTwo = 2;
463     constexpr uint8_t bufOffsetThree = 3;
464     if (childRet == -1) {
465         EchoClient(hChannel, MSG_INFO, "Target is connected, repeat operation");
466     } else if (childRet == connectError) {
467         EchoClient(hChannel, MSG_FAIL, "CreateConnect failed");
468         WRITE_LOG(LOG_FATAL, "CreateConnect failed");
469     } else {
470         size_t pos = connectKey.find(":");
471         if (pos != std::string::npos) {
472             string ip = connectKey.substr(0, pos);
473             if (ip == "127.0.0.1") {
474                 hChannel->connectLocalDevice = true;
475             }
476         }
477         Base::ZeroBuf(hChannel->bufStd, bufOffsetTwo);
478         childRet = snprintf_s(hChannel->bufStd + bufOffsetTwo, sizeof(hChannel->bufStd) - bufOffsetTwo,
479                               sizeof(hChannel->bufStd) - bufOffsetThree, "%s",
480                               const_cast<char *>(connectKey.c_str()));
481         if (childRet > 0) {
482             Base::TimerUvTask(loopMain, hChannel, OrderConnecTargetResult, UV_START_REPEAT);
483             ret = true;
484         }
485     }
486     return ret;
487 }
488 
CommandRemoveSession(HChannel hChannel,const char * connectKey)489 bool HdcServerForClient::CommandRemoveSession(HChannel hChannel, const char *connectKey)
490 {
491     HdcServer *ptrServer = (HdcServer *)clsServer;
492     HDaemonInfo hdiOld = nullptr;
493     (reinterpret_cast<HdcServer *>(ptrServer))->AdminDaemonMap(OP_QUERY, connectKey, hdiOld);
494     if (hdiOld == nullptr || hdiOld->hSession == nullptr) {
495         EchoClient(hChannel, MSG_FAIL, "No target available");
496         WRITE_LOG(LOG_FATAL, "CommandRemoveSession No target available");
497         return false;
498     }
499     (reinterpret_cast<HdcServer *>(ptrServer))->FreeSession(hdiOld->hSession->sessionId);
500     return true;
501 }
502 
CommandRemoveForward(const string & forwardKey)503 bool HdcServerForClient::CommandRemoveForward(const string &forwardKey)
504 {
505     StartTraceScope("HdcServerForClient::CommandRemoveForward");
506     bool ret = RemoveFportkey("0|" + forwardKey);
507     ret |= RemoveFportkey("1|" + forwardKey);
508     return ret;
509 }
510 
RemoveFportkey(const string & forwardKey)511 bool HdcServerForClient::RemoveFportkey(const string &forwardKey)
512 {
513     StartTraceScope("HdcServerForClient::RemoveFportkey");
514     HdcServer *ptrServer = (HdcServer *)clsServer;
515     HForwardInfo hfi = nullptr;
516     ptrServer->AdminForwardMap(OP_QUERY, forwardKey, hfi);
517     if (!hfi) {
518         WRITE_LOG(LOG_FATAL, "CommandRemoveForward hfi nullptr forwardKey:%s", forwardKey.c_str());
519         return false;
520     }
521     HSession hSession = ptrServer->AdminSession(OP_QUERY, hfi->sessionId, nullptr);
522     if (!hSession) {
523         WRITE_LOG(LOG_FATAL, "CommandRemoveForward hSession nullptr sessionId:%u", hfi->sessionId);
524         ptrServer->AdminForwardMap(OP_REMOVE, forwardKey, hfi);
525         return true;
526     }
527     hSession->commandCount++;
528     ptrServer->ClearOwnTasks(hSession, hfi->channelId);
529     FreeChannel(hfi->channelId);
530     hfi = nullptr;
531     ptrServer->AdminForwardMap(OP_REMOVE, forwardKey, hfi);
532     return true;
533 }
534 
GetTargetList(HChannel hChannel,void * formatCommandInput)535 void HdcServerForClient::GetTargetList(HChannel hChannel, void *formatCommandInput)
536 {
537     TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput;
538     HdcServer *ptrServer = (HdcServer *)clsServer;
539     uint16_t cmd = OP_GET_STRLIST;
540     if (formatCommand->parameters == "v") {
541         cmd = OP_GET_STRLIST_FULL;
542     }
543     HDaemonInfo hdi = nullptr;
544     string sRet = ptrServer->AdminDaemonMap(cmd, STRING_EMPTY, hdi);
545     if (!sRet.length()) {
546         sRet = EMPTY_ECHO;
547     }
548     EchoClient(hChannel, MSG_OK, const_cast<char *>(sRet.c_str()));
549 #ifdef UNIT_TEST
550     Base::WriteBinFile((UT_TMP_PATH + "/base-list.result").c_str(), (uint8_t *)MESSAGE_SUCCESS.c_str(),
551                        MESSAGE_SUCCESS.size(), true);
552 #endif
553 }
554 
GetAnyTarget(HChannel hChannel)555 bool HdcServerForClient::GetAnyTarget(HChannel hChannel)
556 {
557     HdcServer *ptrServer = (HdcServer *)clsServer;
558     HDaemonInfo hdi = nullptr;
559     ptrServer->AdminDaemonMap(OP_GET_ANY, STRING_EMPTY, hdi);
560     if (!hdi) {
561         EchoClient(hChannel, MSG_FAIL, "No target available");
562         return false;
563     }
564     // can not use hdi->connectKey.This memory may be released to re-Malloc
565     string connectKey = hdi->connectKey;
566     bool ret = NewConnectTry(ptrServer, hChannel, connectKey);
567 #ifdef UNIT_TEST
568     Base::WriteBinFile((UT_TMP_PATH + "/base-any.result").c_str(), (uint8_t *)MESSAGE_SUCCESS.c_str(),
569                        MESSAGE_SUCCESS.size(), true);
570 #endif
571     return ret;
572 }
573 
WaitForAny(HChannel hChannel)574 bool HdcServerForClient::WaitForAny(HChannel hChannel)
575 {
576     HdcServer *ptrServer = (HdcServer *)clsServer;
577     HDaemonInfo hdi = nullptr;
578     if (!hChannel->connectKey.empty()) {
579         ptrServer->AdminDaemonMap(OP_WAIT_FOR_ANY, hChannel->connectKey, hdi);
580     } else {
581         ptrServer->AdminDaemonMap(OP_WAIT_FOR_ANY, STRING_EMPTY, hdi);
582     }
583     if (!hdi) {
584         EchoClient(hChannel, MSG_FAIL, "No any connected target");
585         return false;
586     }
587     string key = hdi->connectKey;
588     EchoClient(hChannel, MSG_OK, "Wait for connected target is %s", key.c_str());
589     return true;
590 }
591 
RemoveForward(HChannel hChannel,const char * parameterString)592 bool HdcServerForClient::RemoveForward(HChannel hChannel, const char *parameterString)
593 {
594     StartTraceScope("HdcServerForClient::RemoveForward");
595     HdcServer *ptrServer = (HdcServer *)clsServer;
596     if (parameterString == nullptr) {  // remove all
597         HForwardInfo hfi = nullptr;    // dummy
598         string echo = ptrServer->AdminForwardMap(OP_GET_STRLIST, "", hfi);
599         if (!echo.length()) {
600             return false;
601         }
602         vector<string> filterStrings;
603         Base::SplitString(echo, string("\n"), filterStrings);
604         for (auto &&s : filterStrings) {
605             if (CommandRemoveForward(s.c_str())) {
606                 EchoClient(hChannel, MSG_OK, "Remove forward ruler success, ruler:%s", s.c_str());
607             } else {
608                 EchoClient(hChannel, MSG_FAIL, "Remove forward ruler failed, ruler is not exist %s", s.c_str());
609             }
610         }
611     } else {  // remove single
612         if (CommandRemoveForward(parameterString)) {
613             EchoClient(hChannel, MSG_OK, "Remove forward ruler success, ruler:%s", parameterString);
614         } else {
615             EchoClient(hChannel, MSG_FAIL, "Remove forward ruler failed, ruler is not exist %s", parameterString);
616         }
617     }
618     return true;
619 }
620 
DoCommandLocal(HChannel hChannel,void * formatCommandInput)621 bool HdcServerForClient::DoCommandLocal(HChannel hChannel, void *formatCommandInput)
622 {
623     StartTraceScope("HdcServerForClient::DoCommandLocal");
624     TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput;
625     HdcServer *ptrServer = (HdcServer *)clsServer;
626     bool ret = false;
627     // Main thread command, direct Listen main thread
628     switch (formatCommand->cmdFlag) {
629         case CMD_KERNEL_TARGET_DISCOVER: {
630             OrderFindTargets(hChannel);
631             hChannel->isSuccess = true;
632             ret = false;
633             break;
634         }
635         case CMD_KERNEL_TARGET_LIST: {
636             GetTargetList(hChannel, formatCommandInput);
637             hChannel->isSuccess = true;
638             ret = false;
639             break;
640         }
641         case CMD_SERVICE_START: {
642             PrintLastError(hChannel);
643             hChannel->isSuccess = true;
644             ret = false;
645             break;
646         }
647 #ifdef HOST_OHOS
648         case CMD_SERVER_KILL: {
649             WRITE_LOG(LOG_FATAL, "CMD_SERVER_KILL command");
650             ptrServer->SessionSoftReset();
651             hChannel->isSuccess  = true;
652             EchoClient(hChannel, MSG_OK, "Kill server finish");
653             _exit(0);
654         }
655 #endif
656         case CMD_CHECK_SERVER: {
657             WRITE_LOG(LOG_DEBUG, "CMD_CHECK_SERVER command");
658             ReportServerVersion(hChannel);
659             hChannel->isSuccess = true;
660             ret = false;
661             break;
662         }
663         case CMD_WAIT_FOR: {
664             WRITE_LOG(LOG_DEBUG, "CMD_WAIT_FOR command");
665             ret = !WaitForAny(hChannel);
666             hChannel->isSuccess = ret;
667             break;
668         }
669         case CMD_KERNEL_TARGET_ANY: {
670 #ifdef HDC_DEBUG
671             WRITE_LOG(LOG_DEBUG, "%s CMD_KERNEL_TARGET_ANY %s", __FUNCTION__, formatCommand->parameters.c_str());
672 #endif
673             ret = GetAnyTarget(hChannel);
674             hChannel->isSuccess = ret;
675             break;
676         }
677         case CMD_KERNEL_TARGET_CONNECT: {
678 #ifdef HDC_DEBUG
679             WRITE_LOG(LOG_DEBUG, "%s CMD_KERNEL_TARGET_CONNECT %s", __FUNCTION__, formatCommand->parameters.c_str());
680 #endif
681             ret = NewConnectTry(ptrServer, hChannel, formatCommand->parameters.c_str());
682             hChannel->isSuccess = ret;
683             break;
684         }
685         case CMD_CHECK_DEVICE: {
686             WRITE_LOG(LOG_INFO, "%s CMD_CHECK_DEVICE %s", __FUNCTION__, formatCommand->parameters.c_str());
687             hChannel->isCheck = true;
688             hChannel->key = formatCommand->parameters.c_str();
689             ret = NewConnectTry(ptrServer, hChannel, formatCommand->parameters.c_str(), true);
690             hChannel->isSuccess = ret;
691             break;
692         }
693         case CMD_KERNEL_TARGET_DISCONNECT: {
694             CommandRemoveSession(hChannel, formatCommand->parameters.c_str());
695             hChannel->isSuccess = true;
696             break;
697         }
698         // task will be global task,Therefore, it can only be controlled in the global session.
699         case CMD_FORWARD_LIST: {
700             HForwardInfo hfi = nullptr;  // dummy
701             string echo = ptrServer->AdminForwardMap(OP_GET_STRLIST_FULL, "", hfi);
702             if (!echo.length()) {
703                 echo = EMPTY_ECHO;
704             }
705             EchoClient(hChannel, MSG_OK, const_cast<char *>(echo.c_str()));
706             hChannel->isSuccess = true;
707             break;
708         }
709         case CMD_FORWARD_REMOVE: {
710             RemoveForward(hChannel, formatCommand->parameters.c_str());
711             hChannel->isSuccess = true;
712             break;
713         }
714         case CMD_KERNEL_ENABLE_KEEPALIVE: {
715             // just use for 'list targets' now
716             hChannel->keepAlive = true;
717             ret = true;
718             hChannel->isSuccess = true;
719             break;
720         }
721         default: {
722             EchoClient(hChannel, MSG_FAIL, "ExecuteCommand need connect-key? please confirm a device by help info");
723             FillChannelResult(hChannel, false, "found no devices");
724             break;
725         }
726     }
727     return ret;
728 }
729 
TaskCommand(HChannel hChannel,void * formatCommandInput)730 bool HdcServerForClient::TaskCommand(HChannel hChannel, void *formatCommandInput)
731 {
732     StartTraceScope("HdcServerForClient::TaskCommand");
733     TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput;
734     HdcServer *ptrServer = (HdcServer *)clsServer;
735     string cmdFlag;
736     uint8_t sizeCmdFlag = 0;
737     if (formatCommand->cmdFlag == CMD_FILE_INIT) {
738         cmdFlag = "send ";
739         sizeCmdFlag = 5;  // 5: cmdFlag send size
740         HandleRemote(hChannel, formatCommand->parameters, RemoteType::REMOTE_FILE);
741     } else if (formatCommand->cmdFlag == CMD_FORWARD_INIT) {
742         cmdFlag = "fport ";
743         sizeCmdFlag = 6;  // 6: cmdFlag fport size
744     } else if (formatCommand->cmdFlag == CMD_APP_INIT) {
745         cmdFlag = "install ";
746         sizeCmdFlag = 8;  // 8: cmdFlag install size
747         HandleRemote(hChannel, formatCommand->parameters, RemoteType::REMOTE_APP);
748     } else if (formatCommand->cmdFlag == CMD_APP_UNINSTALL) {
749         cmdFlag = "uninstall ";
750         sizeCmdFlag = 10;  // 10: cmdFlag uninstall size
751     } else if (formatCommand->cmdFlag == CMD_UNITY_BUGREPORT_INIT) {
752         cmdFlag = "bugreport ";
753         sizeCmdFlag = 10;  // 10: cmdFlag bugreport size
754     } else if (formatCommand->cmdFlag == CMD_APP_SIDELOAD) {
755         cmdFlag = "sideload ";
756         sizeCmdFlag = 9; // 9: cmdFlag sideload size
757     } else if (formatCommand->cmdFlag == CMD_FLASHD_UPDATE_INIT) {
758         cmdFlag = "update ";
759         sizeCmdFlag = 7; // 7: cmdFlag update size
760     } else if (formatCommand->cmdFlag == CMD_FLASHD_FLASH_INIT) {
761         cmdFlag = "flash ";
762         sizeCmdFlag = 6; // 6: cmdFlag flash size
763     }
764     int sizeSend = formatCommand->parameters.size();
765     if (!strncmp(formatCommand->parameters.c_str(), cmdFlag.c_str(), sizeCmdFlag)) {  // local do
766         HSession hSession = FindAliveSession(hChannel->targetSessionId);
767         if (!hSession) {
768             return false;
769         }
770         if ((formatCommand->cmdFlag == CMD_FILE_INIT || formatCommand->cmdFlag == CMD_APP_INIT) &&
771             hChannel->fromClient) {
772             // remote client mode, CMD_FILE_INIT and CMD_APP_INIT command send back to client
773             WRITE_LOG(LOG_INFO, "CMD_FILE_INIT|CMD_APP_INIT command send back to remote client, cid:%u",
774                 hChannel->channelId);
775             SendChannelWithCmd(hChannel, formatCommand->cmdFlag,
776                 reinterpret_cast<uint8_t *>(const_cast<char *>(formatCommand->parameters.c_str())) + sizeCmdFlag,
777                 sizeSend - sizeCmdFlag);
778             return false;
779         }
780         ptrServer->DispatchTaskData(hSession, hChannel->channelId, formatCommand->cmdFlag,
781             reinterpret_cast<uint8_t *>(const_cast<char *>(formatCommand->parameters.c_str())) + sizeCmdFlag,
782             sizeSend - sizeCmdFlag);
783     } else {  // Send to Daemon-side to do
784         SendToDaemon(hChannel, formatCommand->cmdFlag,
785             reinterpret_cast<uint8_t *>(const_cast<char *>(formatCommand->parameters.c_str())) + sizeCmdFlag,
786             sizeSend - sizeCmdFlag);
787     }
788     return true;
789 }
790 
HandleRemote(HChannel hChannel,string & parameters,RemoteType flag)791 void HdcServerForClient::HandleRemote(HChannel hChannel, string &parameters, RemoteType flag)
792 {
793     StartTraceScope("HdcServerForClient::HandleRemote");
794     hChannel->remote = flag;
795     int argc = 0;
796     char **argv = Base::SplitCommandToArgs(parameters.c_str(), &argc);
797     for (int i = 0; i < argc; i++) {
798         if (argv[i] == CMDSTR_REMOTE_PARAMETER) {
799             hChannel->fromClient = true;
800             WRITE_LOG(LOG_DEBUG, "remote client mode channelId:%u", hChannel->channelId);
801             break;
802         }
803     }
804     if (hChannel->fromClient) {
805         string remote = CMDSTR_REMOTE_PARAMETER + " ";
806         if (parameters.find(remote) != std::string::npos) {
807             parameters.replace(parameters.find(remote), remote.size(), "");
808             WRITE_LOG(LOG_DEBUG, "parameters: %s", Hdc::MaskString(parameters).c_str());
809         }
810     }
811     delete[](reinterpret_cast<char *>(argv));
812 }
813 
814 #ifdef __OHOS__
IsServerTransfer(HChannel hChannel,uint16_t cmdFlag,string & parameters)815 bool HdcServerForClient::IsServerTransfer(HChannel hChannel, uint16_t cmdFlag, string &parameters)
816 {
817     if (cmdFlag == CMD_FILE_INIT || cmdFlag== CMD_APP_INIT) {
818         HandleRemote(hChannel, parameters, RemoteType::REMOTE_FILE);
819         if (!hChannel->fromClient) {
820             EchoClient(hChannel, MSG_FAIL, "[E005200] Unsupport file command");
821             return false;
822         }
823     }
824     return true;
825 }
826 #endif
827 
DoCommandRemote(HChannel hChannel,void * formatCommandInput)828 bool HdcServerForClient::DoCommandRemote(HChannel hChannel, void *formatCommandInput)
829 {
830     StartTraceScope("HdcServerForClient::DoCommandRemote");
831     TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput;
832     bool ret = false;
833     int sizeSend = formatCommand->parameters.size();
834     switch (formatCommand->cmdFlag) {
835         // Some simple commands only need to forward the instruction, no need to start Task
836         case CMD_SHELL_INIT:
837         case CMD_SHELL_DATA:
838         case CMD_UNITY_EXECUTE:
839         case CMD_UNITY_EXECUTE_EX:
840         case CMD_UNITY_REMOUNT:
841         case CMD_UNITY_REBOOT:
842         case CMD_UNITY_RUNMODE:
843         case CMD_UNITY_HILOG:
844         case CMD_UNITY_ROOTRUN:
845         case CMD_JDWP_TRACK:
846         case CMD_JDWP_LIST: {
847             if (!SendToDaemon(hChannel, formatCommand->cmdFlag,
848                 reinterpret_cast<uint8_t *>(const_cast<char *>(formatCommand->parameters.c_str())), sizeSend)) {
849                 break;
850             }
851             ret = true;
852             if (formatCommand->cmdFlag == CMD_SHELL_INIT) {
853                 hChannel->interactiveShellMode = true;
854             }
855             break;
856         }
857         case CMD_FILE_INIT:
858         case CMD_FORWARD_INIT:
859         case CMD_APP_INIT: {
860 #ifdef __OHOS__
861             if (!IsServerTransfer(hChannel, formatCommand->cmdFlag, formatCommand->parameters)) {
862                 return false;
863             }
864 #endif
865         }
866         case CMD_APP_UNINSTALL:
867         case CMD_UNITY_BUGREPORT_INIT:
868         case CMD_APP_SIDELOAD:
869         case CMD_FLASHD_UPDATE_INIT:
870         case CMD_FLASHD_FLASH_INIT:
871         case CMD_FLASHD_ERASE:
872         case CMD_FLASHD_FORMAT: {
873             TaskCommand(hChannel, formatCommandInput);
874             ret = true;
875             break;
876         }
877         default:
878             break;
879     }
880     if (!ret) {
881         EchoClient(hChannel, MSG_FAIL, "[E002106] Failed to communicate with daemon");
882     }
883     return ret;
884 }
885 // Do not specify Target's operations no longer need to put it in the thread.
DoCommand(HChannel hChannel,void * formatCommandInput,HDaemonInfo & hdi)886 bool HdcServerForClient::DoCommand(HChannel hChannel, void *formatCommandInput, HDaemonInfo &hdi)
887 {
888     StartTraceScope("HdcServerForClient::DoCommand");
889     bool ret = false;
890     TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput;
891 #ifdef __OHOS__
892     if ((!hChannel->hChildWorkTCP.loop && !hChannel->hChildWorkUds.loop) ||
893 #else
894     if (!hChannel->hChildWorkTCP.loop ||
895 #endif
896         formatCommand->cmdFlag == CMD_FORWARD_REMOVE ||
897 #ifdef HOST_OHOS
898         formatCommand->cmdFlag == CMD_SERVER_KILL ||
899 #endif
900         formatCommand->cmdFlag == CMD_SERVICE_START) {
901         hChannel->commandFlag = formatCommand->cmdFlag;
902         hChannel->commandParameters = formatCommand->parameters;
903         // Main thread command, direct Listen main thread
904         ret = DoCommandLocal(hChannel, formatCommandInput);
905     } else {  // CONNECT DAEMON's work thread command, non-primary thread
906         if (!CommandMatchDaemonFeature(formatCommand->cmdFlag, hdi)) {
907             // only the cmdFlag in the FEATURE_VERSION_MATCH_MAP needs to be checked, others to permissive.
908             WRITE_LOG(LOG_WARN, "unsupport cmdFlag: %d, due to daemon feature dismatch", formatCommand->cmdFlag);
909             EchoClient(hChannel, MSG_FAIL, "[E002105] Unsupport command");
910             return false;
911         }
912         if (formatCommand->cmdFlag != CMD_SHELL_DATA) {
913             hChannel->commandFlag = formatCommand->cmdFlag;
914             hChannel->commandParameters = formatCommand->parameters;
915         }
916         ret = DoCommandRemote(hChannel, formatCommandInput);
917     }
918     return ret;
919 }
920 
921 // just call from BindChannelToSession
FindAliveSessionFromDaemonMap(const HChannel hChannel)922 HSession HdcServerForClient::FindAliveSessionFromDaemonMap(const HChannel hChannel)
923 {
924     StartTraceScope("HdcServerForClient::FindAliveSessionFromDaemonMap");
925     HSession hSession = nullptr;
926     HDaemonInfo hdi = nullptr;
927     HdcServer *ptrServer = (HdcServer *)clsServer;
928     ptrServer->AdminDaemonMap(OP_QUERY, hChannel->connectKey, hdi);
929     if (!hdi) {
930         WRITE_LOG(LOG_WARN, "Not match target founded cid:%u", hChannel->channelId);
931         FillChannelResult(hChannel, false, "no match targets found");
932         EchoClient(hChannel, MSG_FAIL, "Not match target founded, check connect-key please");
933         return nullptr;
934     }
935     if (hdi->connStatus != STATUS_CONNECTED) {
936         WRITE_LOG(LOG_WARN, "Device not found or connected cid:%u", hChannel->channelId);
937         FillChannelResult(hChannel, false, "device not found or connected");
938         EchoClient(hChannel, MSG_FAIL, "[E001005] Device not found or connected");
939         return nullptr;
940     }
941     if (hdi->hSession == nullptr || hdi->hSession->isDead) {
942         WRITE_LOG(LOG_WARN, "Bind tartget session is null or dead cid:%u", hChannel->channelId);
943         FillChannelResult(hChannel, false, "bind tartget session is null or dead");
944         EchoClient(hChannel, MSG_FAIL, "Bind tartget session is dead");
945         return nullptr;
946     }
947     if (!hdi->hSession->handshakeOK) {
948         WRITE_LOG(LOG_WARN, "hSession handShake is false sid:%u cid:%u",
949             hdi->hSession->sessionId, hChannel->channelId);
950         FillChannelResult(hChannel, false, "handshake is not ready");
951         const string errMsg = "[E000004]:The communication channel is being established.\r\n"\
952             "Please wait for several seconds and try again.";
953         EchoClient(hChannel, MSG_FAIL, errMsg.c_str());
954         return nullptr;
955     }
956     hSession = reinterpret_cast<HSession>(hdi->hSession);
957     return hSession;
958 }
959 
960 #ifdef __OHOS__
BindChannelToSession(HChannel hChannel,uint8_t * bufPtr,const int bytesIO)961 int HdcServerForClient::BindChannelToSession(HChannel hChannel, uint8_t *bufPtr, const int bytesIO)
962 {
963     StartTraceScope("HdcServerForClient::BindChannelToSession");
964     if (FindAliveSessionFromDaemonMap(hChannel) == nullptr) {
965         WRITE_LOG(LOG_FATAL, "Find no alive session channelId:%u", hChannel->channelId);
966         return ERR_SESSION_NOFOUND;
967     }
968     bool isClosing = false;
969     if (!hChannel->isUds) {
970         isClosing = uv_is_closing((const uv_handle_t *)&hChannel->hWorkTCP);
971         if (!isClosing && (hChannel->fdChildWorkTCP = Base::DuplicateUvSocket(&hChannel->hWorkTCP)) < 0) {
972             WRITE_LOG(LOG_FATAL, "Duplicate socket failed channelId:%u", hChannel->channelId);
973             return ERR_SOCKET_DUPLICATE;
974         }
975     } else {
976         isClosing = uv_is_closing((const uv_handle_t *)&hChannel->hWorkUds);
977         if (!isClosing && (hChannel->fdChildWorkTCP = Base::DuplicateUvPipe(&hChannel->hWorkUds)) < 0) {
978             WRITE_LOG(LOG_FATAL, "Duplicate pipe failed channelId:%u", hChannel->channelId);
979             return ERR_SOCKET_DUPLICATE;
980         }
981     }
982 
983     uv_close_cb funcWorkTcpClose = [](uv_handle_t *handle) -> void {
984         HChannel hChannel = (HChannel)handle->data;
985         --hChannel->ref;
986     };
987     ++hChannel->ref;
988     if (!isClosing) {
989         if (!hChannel->isUds) {
990             uv_close((uv_handle_t *)&hChannel->hWorkTCP, funcWorkTcpClose);
991         } else {
992             uv_close((uv_handle_t *)&hChannel->hWorkUds, funcWorkTcpClose);
993         }
994     }
995     Base::DoNextLoop(loopMain, hChannel, [](const uint8_t flag, string &msg, const void *data) {
996         // Thread message can avoid using thread lock and improve program efficiency
997         // If not next loop call, ReadStream will thread conflict
998         HChannel hChannel = (HChannel)data;
999         auto thisClass = (HdcServerForClient *)hChannel->clsChannel;
1000         HSession hSession = nullptr;
1001         if ((hSession = thisClass->FindAliveSessionFromDaemonMap(hChannel)) == nullptr) {
1002             WRITE_LOG(LOG_FATAL, "hSession nullptr channelId:%u", hChannel->channelId);
1003             return;
1004         }
1005         auto ctrl = HdcSessionBase::BuildCtrlString(SP_ATTACH_CHANNEL, hChannel->channelId, nullptr, 0);
1006         Base::SendToPollFd(hSession->ctrlFd[STREAM_MAIN], ctrl.data(), ctrl.size());
1007     });
1008     return RET_SUCCESS;
1009 }
1010 #else
BindChannelToSession(HChannel hChannel,uint8_t * bufPtr,const int bytesIO)1011 int HdcServerForClient::BindChannelToSession(HChannel hChannel, uint8_t *bufPtr, const int bytesIO)
1012 {
1013     StartTraceScope("HdcServerForClient::BindChannelToSession");
1014     if (FindAliveSessionFromDaemonMap(hChannel) == nullptr) {
1015         WRITE_LOG(LOG_FATAL, "Find no alive session channelId:%u", hChannel->channelId);
1016         return ERR_SESSION_NOFOUND;
1017     }
1018     bool isClosing = uv_is_closing((const uv_handle_t *)&hChannel->hWorkTCP);
1019     if (!isClosing && (hChannel->fdChildWorkTCP = Base::DuplicateUvSocket(&hChannel->hWorkTCP)) < 0) {
1020         WRITE_LOG(LOG_FATAL, "Duplicate socket failed channelId:%u", hChannel->channelId);
1021         return ERR_SOCKET_DUPLICATE;
1022     }
1023 
1024     uv_close_cb funcWorkTcpClose = [](uv_handle_t *handle) -> void {
1025         HChannel hChannel = (HChannel)handle->data;
1026         --hChannel->ref;
1027     };
1028     ++hChannel->ref;
1029     if (!isClosing) {
1030         uv_close((uv_handle_t *)&hChannel->hWorkTCP, funcWorkTcpClose);
1031     }
1032     Base::DoNextLoop(loopMain, hChannel, [](const uint8_t flag, string &msg, const void *data) {
1033         // Thread message can avoid using thread lock and improve program efficiency
1034         // If not next loop call, ReadStream will thread conflict
1035         HChannel hChannel = (HChannel)data;
1036         auto thisClass = (HdcServerForClient *)hChannel->clsChannel;
1037         HSession hSession = nullptr;
1038         if ((hSession = thisClass->FindAliveSessionFromDaemonMap(hChannel)) == nullptr) {
1039             WRITE_LOG(LOG_FATAL, "hSession nullptr channelId:%u", hChannel->channelId);
1040             return;
1041         }
1042         auto ctrl = HdcSessionBase::BuildCtrlString(SP_ATTACH_CHANNEL, hChannel->channelId, nullptr, 0);
1043         Base::SendToPollFd(hSession->ctrlFd[STREAM_MAIN], ctrl.data(), ctrl.size());
1044     });
1045     return RET_SUCCESS;
1046 }
1047 #endif
1048 
CheckAutoFillTarget(HChannel hChannel)1049 bool HdcServerForClient::CheckAutoFillTarget(HChannel hChannel)
1050 {
1051     HdcServer *ptrServer = (HdcServer *)clsServer;
1052     if (!hChannel->connectKey.size()) {
1053         WRITE_LOG(LOG_FATAL, "connectKey.size 0 channelId:%u", hChannel->channelId);
1054         return false;  // Operation of non-bound destination of scanning
1055     }
1056     if (hChannel->connectKey == CMDSTR_CONNECT_ANY) {
1057         HDaemonInfo hdiOld = nullptr;
1058         ptrServer->AdminDaemonMap(OP_GET_ONLY, "", hdiOld);
1059         if (!hdiOld) {
1060             WRITE_LOG(LOG_WARN, "No any key found channelId:%u", hChannel->channelId);
1061             return false;
1062         }
1063         if (!hdiOld->hSession) {
1064             WRITE_LOG(LOG_WARN, "hSession is null. channelId:%u", hChannel->channelId);
1065             return false;
1066         }
1067         if (!hdiOld->hSession->handshakeOK) {
1068             WRITE_LOG(LOG_WARN, "hSession handShake is false SessionId:%u", hdiOld->hSession->sessionId);
1069             return false;
1070         }
1071         hChannel->connectKey = hdiOld->connectKey;
1072         return true;
1073     }
1074     return true;
1075 }
1076 
ChannelHandShake(HChannel hChannel,uint8_t * bufPtr,const int bytesIO)1077 int HdcServerForClient::ChannelHandShake(HChannel hChannel, uint8_t *bufPtr, const int bytesIO)
1078 {
1079     StartTraceScope("HdcServerForClient::ChannelHandShake");
1080     vector<uint8_t> rebuildHandshake;
1081     rebuildHandshake.insert(rebuildHandshake.end(), bufPtr, bufPtr + bytesIO);
1082     rebuildHandshake.push_back(0x00);
1083     struct ChannelHandShake *handShake = reinterpret_cast<struct ChannelHandShake *>(rebuildHandshake.data());
1084     if (strncmp(handShake->banner, HANDSHAKE_MESSAGE.c_str(), HANDSHAKE_MESSAGE.size())) {
1085         hChannel->availTailIndex = 0;
1086         WRITE_LOG(LOG_DEBUG, "Channel Hello failed");
1087         return ERR_HANDSHAKE_NOTMATCH;
1088     }
1089     if (strlen(handShake->connectKey) > sizeof(handShake->connectKey)) {
1090         hChannel->availTailIndex = 0;
1091         WRITE_LOG(LOG_DEBUG, "Connectkey's size incorrect");
1092         return ERR_HANDSHAKE_CONNECTKEY_FAILED;
1093     }
1094     // channel handshake step3
1095     WRITE_LOG(LOG_DEBUG, "ServerForClient cid:%u sid:%u handshake finished",
1096         hChannel->channelId, hChannel->targetSessionId);
1097     hChannel->connectKey = handShake->connectKey;
1098     hChannel->handshakeOK = true;
1099     if (handShake->banner[WAIT_TAG_OFFSET] == WAIT_DEVICE_TAG || !CheckAutoFillTarget(hChannel)) {
1100         WRITE_LOG(LOG_WARN, "No target channelId:%u", hChannel->channelId);
1101         return 0;
1102     }
1103     // channel handshake stBindChannelToSession
1104     if (BindChannelToSession(hChannel, nullptr, 0)) {
1105         hChannel->availTailIndex = 0;
1106         WRITE_LOG(LOG_FATAL, "BindChannelToSession failed channelId:%u sid:%u",
1107             hChannel->channelId, hChannel->targetSessionId);
1108         return ERR_GENERIC;
1109     }
1110     return 0;
1111 }
1112 
ReportServerVersion(HChannel hChannel)1113 void HdcServerForClient::ReportServerVersion(HChannel hChannel)
1114 {
1115     string version = Base::GetVersion();
1116     SendChannelWithCmd(hChannel, CMD_CHECK_SERVER,
1117                        const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(version.c_str())),
1118                        version.size());
1119 }
1120 
1121 // Here is Server to get data, the source is the SERVER's ChildWork to send data
ReadChannel(HChannel hChannel,uint8_t * bufPtr,const int bytesIO)1122 int HdcServerForClient::ReadChannel(HChannel hChannel, uint8_t *bufPtr, const int bytesIO)
1123 {
1124     StartTraceScope("HdcServerForClient::ReadChannel");
1125     if (!hChannel->handshakeOK) {
1126         return ChannelHandShake(hChannel, bufPtr, bytesIO);
1127     }
1128     HDaemonInfo hdi = nullptr;
1129     HdcServer *ptrServer = (HdcServer *)clsServer;
1130     ptrServer->AdminDaemonMap(OP_QUERY, hChannel->connectKey, hdi);
1131     if (hdi && !hdi->emgmsg.empty()) {
1132         EchoClient(hChannel, MSG_FAIL, hdi->emgmsg.c_str());
1133         return ERR_GENERIC;
1134     }
1135     uint16_t command = *reinterpret_cast<uint16_t *>(bufPtr);
1136     if (command != 0 && (hChannel->remote > RemoteType::REMOTE_NONE)) {
1137         // server directly passthrough file command to daemon
1138         if (!SendToDaemon(hChannel, command, bufPtr + sizeof(uint16_t), bytesIO - sizeof(uint16_t))) {
1139             WRITE_LOG(LOG_FATAL, "Client ReadChannel : direct send to daemon failed");
1140         }
1141         return 0;
1142     }
1143     struct TranslateCommand::FormatCommand formatCommand = { 0 };
1144     if (!hChannel->interactiveShellMode) {
1145         string retEcho = String2FormatCommand(reinterpret_cast<char *>(bufPtr), bytesIO, &formatCommand);
1146         if (retEcho.length()) {
1147             if (!strncmp(reinterpret_cast<char *>(bufPtr), CMDSTR_SOFTWARE_HELP.c_str(),
1148                 CMDSTR_SOFTWARE_HELP.size()) ||
1149                 !strcmp(reinterpret_cast<char *>(bufPtr), CMDSTR_SOFTWARE_VERSION.c_str()) ||
1150                 !strcmp(reinterpret_cast<char *>(bufPtr), "flash")) {
1151                 EchoClient(hChannel, MSG_OK, retEcho.c_str());
1152             } else {
1153                 EchoClient(hChannel, MSG_FAIL, retEcho.c_str());
1154             }
1155         }
1156 
1157         WRITE_LOG(LOG_INFO, "ReadChannel cid:%u sid:%u key:%s", hChannel->channelId,
1158             hChannel->targetSessionId, Hdc::MaskString(hChannel->connectKey).c_str());
1159         if (Hdc::Base::GetCmdLogSwitch()) {
1160             string logBuf = Base::CmdLogStringFormat(hChannel->targetSessionId, (reinterpret_cast<char *>(bufPtr)));
1161             ptrServer->PrintCmdLogEx(logBuf);
1162         }
1163         if (formatCommand.bJumpDo) {
1164             WRITE_LOG(LOG_FATAL, "ReadChannel bJumpDo true");
1165             return -10;  //  -10 error formatCommand
1166         }
1167     } else {
1168         formatCommand.parameters = string(reinterpret_cast<char *>(bufPtr), bytesIO);
1169         formatCommand.cmdFlag = CMD_SHELL_DATA;
1170     }
1171     if (!DoCommand(hChannel, &formatCommand, hdi)) {
1172         return -3;  // -3: error or want close
1173     }
1174     return bytesIO;
1175 };
1176 
1177 // avoid session dead
FindAliveSession(uint32_t sessionId)1178 HSession HdcServerForClient::FindAliveSession(uint32_t sessionId)
1179 {
1180     StartTraceScope("HdcServerForClient::FindAliveSession");
1181     HdcServer *ptrServer = (HdcServer *)clsServer;
1182     HSession hSession = ptrServer->AdminSession(OP_QUERY, sessionId, nullptr);
1183     if (!hSession || hSession->isDead) {
1184         WRITE_LOG(LOG_FATAL, "FindAliveSession hSession nullptr or isDead sessionId:%u", sessionId);
1185         return nullptr;
1186     } else {
1187         return hSession;
1188     }
1189 }
1190 
ChannelSendSessionCtrlMsg(vector<uint8_t> & ctrlMsg,uint32_t sessionId)1191 bool HdcServerForClient::ChannelSendSessionCtrlMsg(vector<uint8_t> &ctrlMsg, uint32_t sessionId)
1192 {
1193     HSession hSession = FindAliveSession(sessionId);
1194     if (!hSession) {
1195         WRITE_LOG(LOG_FATAL, "ChannelSendSessionCtrlMsg hSession nullptr sessionId:%u", sessionId);
1196         return false;
1197     }
1198     int rc = Base::SendToPollFd(hSession->ctrlFd[STREAM_MAIN], ctrlMsg.data(), ctrlMsg.size());
1199     if (rc <= 0) {
1200         WRITE_LOG(LOG_FATAL, "send ctrlmsg failed sessionId:%u rc:%d", sessionId, rc);
1201     }
1202     return rc > 0;
1203 }
1204 
PrintLastError(HChannel HChannel)1205 void HdcServerForClient::PrintLastError(HChannel HChannel)
1206 {
1207     HdcServer *ptrServer = (HdcServer *)clsServer;
1208     uint32_t errorCode = ptrServer->lastErrorNum;
1209     if (errorCode > 0) {
1210         string errorString = GetErrorString(errorCode);
1211         EchoClient(HChannel, MSG_FAIL, "[E%06x]%s", errorCode, errorString.c_str());
1212         ptrServer->lastErrorNum = 0;
1213     }
1214 }
1215 
GetErrorString(uint32_t errorCode)1216 string HdcServerForClient::GetErrorString(uint32_t errorCode)
1217 {
1218     auto map = ErrorStringEnglish.find(errorCode);
1219     if (map != ErrorStringEnglish.end()) {
1220         return map->second;
1221     }
1222     return ErrorStringEnglish.at(0xFFFFFF); // 0xFFFFFF:  Unknown error
1223 }
1224 
CommandMatchDaemonFeature(uint16_t cmdFlag,const HDaemonInfo & hdi)1225 bool HdcServerForClient::CommandMatchDaemonFeature(uint16_t cmdFlag, const HDaemonInfo &hdi)
1226 {
1227     StartTraceScope("HdcServerForClient::CommandMatchDaemonFeature");
1228     string cmdFlagStr = std::to_string(cmdFlag);
1229     if (FEATURE_CHECK_SET.find(cmdFlag) == FEATURE_CHECK_SET.end()) { // not need check
1230         return true;
1231     }
1232     auto tagMatch = hdi->daemonFeature.find(cmdFlagStr);
1233     if (tagMatch == hdi->daemonFeature.end()) { // unsupport command
1234         return false;
1235     }
1236     return (tagMatch->second == STR_FEATURE_ENABLE);
1237 }
1238 }  // namespace Hdc
1239