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