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