• 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.h"
16 
17 #include "host_updater.h"
18 #include "flash_define.h"
19 
20 namespace Hdc {
HdcServer(bool serverOrDaemonIn)21 HdcServer::HdcServer(bool serverOrDaemonIn)
22     : HdcSessionBase(serverOrDaemonIn)
23 {
24     clsTCPClt = nullptr;
25     clsUSBClt = nullptr;
26     clsServerForClient = nullptr;
27     uv_rwlock_init(&daemonAdmin);
28     uv_rwlock_init(&forwardAdmin);
29 }
30 
~HdcServer()31 HdcServer::~HdcServer()
32 {
33     WRITE_LOG(LOG_DEBUG, "~HdcServer");
34     uv_rwlock_destroy(&daemonAdmin);
35     uv_rwlock_destroy(&forwardAdmin);
36 }
37 
ClearInstanceResource()38 void HdcServer::ClearInstanceResource()
39 {
40     TryStopInstance();
41     Base::TryCloseLoop(&loopMain, "HdcServer::~HdcServer");
42     if (clsTCPClt) {
43         delete clsTCPClt;
44     }
45     if (clsUSBClt) {
46         delete clsUSBClt;
47     }
48     if (clsServerForClient) {
49         delete (static_cast<HdcServerForClient *>(clsServerForClient));
50     }
51 }
52 
TryStopInstance()53 void HdcServer::TryStopInstance()
54 {
55     ClearSessions();
56     if (clsTCPClt) {
57         clsTCPClt->Stop();
58     }
59     if (clsUSBClt) {
60         clsUSBClt->Stop();
61     }
62     if (clsServerForClient) {
63         ((HdcServerForClient *)clsServerForClient)->Stop();
64     }
65     ReMainLoopForInstanceClear();
66     ClearMapDaemonInfo();
67 }
68 
Initial(const char * listenString)69 bool HdcServer::Initial(const char *listenString)
70 {
71     if (Base::ProgramMutex(SERVER_NAME.c_str(), false) != 0) {
72         WRITE_LOG(LOG_FATAL, "Other instance already running, program mutex failed");
73         return false;
74     }
75     clsServerForClient = new HdcServerForClient(true, listenString, this, &loopMain);
76     clsTCPClt = new HdcHostTCP(true, this);
77     clsUSBClt = new HdcHostUSB(true, this, ctxUSB);
78     if (!clsServerForClient || !clsTCPClt || !clsUSBClt) {
79         WRITE_LOG(LOG_FATAL, "Class init failed");
80         return false;
81     }
82     (static_cast<HdcServerForClient *>(clsServerForClient))->Initial();
83     clsUSBClt->Initial();
84     return true;
85 }
86 
PullupServerWin32(const char * path,const char * listenString)87 bool HdcServer::PullupServerWin32(const char *path, const char *listenString)
88 {
89 #ifdef _WIN32
90     char buf[BUF_SIZE_SMALL] = "";
91     char shortPath[MAX_PATH] = "";
92     int ret = GetShortPathName(path, shortPath, MAX_PATH);
93     std::string runPath = shortPath;
94     if (ret == 0) {
95         int err = GetLastError();
96         WRITE_LOG(LOG_WARN, "GetShortPath path:[%s] err:%d errmsg:%s", path, err, strerror(err));
97         string uvPath = path;
98         runPath = uvPath.substr(uvPath.find_last_of("/\\") + 1);
99     }
100     WRITE_LOG(LOG_DEBUG, "server shortpath:[%s] runPath:[%s]", shortPath, runPath.c_str());
101     if (sprintf_s(buf, sizeof(buf), "%s -l4 -s %s -m", runPath.c_str(), listenString) < 0) {
102         return false;
103     }
104     WRITE_LOG(LOG_DEBUG, "Run server in debug-forground, cmd:%s", buf);
105     STARTUPINFO si;
106     Base::ZeroStruct(si);
107     si.cb = sizeof(STARTUPINFO);
108     PROCESS_INFORMATION pi;
109     Base::ZeroStruct(pi);
110 #ifndef HDC_DEBUG
111     si.dwFlags = STARTF_USESHOWWINDOW;
112     si.wShowWindow = SW_HIDE;
113 #endif
114     CreateProcess(nullptr, buf, nullptr, nullptr, true, CREATE_NEW_CONSOLE, nullptr, nullptr, &si, &pi);
115     CloseHandle(pi.hThread);
116     CloseHandle(pi.hProcess);
117 #endif
118     return true;
119 }
120 
121 // Only detects that the default call is in the loop address, the other tubes are not
PullupServer(const char * listenString)122 bool HdcServer::PullupServer(const char *listenString)
123 {
124     char path[BUF_SIZE_SMALL] = "";
125     size_t nPathSize = sizeof(path);
126     int ret = uv_exepath(path, &nPathSize);
127     if (ret < 0) {
128         WRITE_LOG(LOG_WARN, "uvexepath ret:%d error:%s", ret, uv_err_name(ret));
129         return false;
130     }
131 
132 #ifdef _WIN32
133     if (!PullupServerWin32(path, listenString)) {
134         return false;
135     }
136 #else
137     pid_t pc = fork();  // create process as daemon process
138     if (pc < 0) {
139         return false;
140     } else if (!pc) {
141         int i;
142         const int maxFD = 1024;
143         for (i = 0; i < maxFD; ++i) {
144             // close file pipe
145             close(i);
146         }
147         execl(path, "ohflash", "-m", "-s", listenString, nullptr);
148         exit(0);
149         return true;
150     }
151     // orig process
152 #endif
153     // wait little time, util backend-server work ready
154     uv_sleep(TIME_BASE);
155     return true;
156 }
157 
ClearMapDaemonInfo()158 void HdcServer::ClearMapDaemonInfo()
159 {
160     uv_rwlock_rdlock(&daemonAdmin);
161     for (auto iter = mapDaemon.begin(); iter != mapDaemon.end();) {
162         string sKey = iter->first;
163         HDaemonInfo hDi = iter->second;
164         delete hDi;
165         ++iter;
166     }
167     uv_rwlock_rdunlock(&daemonAdmin);
168     uv_rwlock_wrlock(&daemonAdmin);
169     mapDaemon.clear();
170     uv_rwlock_wrunlock(&daemonAdmin);
171 }
172 
BuildDaemonVisableLine(HDaemonInfo hdi,bool fullDisplay,string & out)173 void HdcServer::BuildDaemonVisableLine(HDaemonInfo hdi, bool fullDisplay, string &out)
174 {
175     if (fullDisplay) {
176         string sConn;
177         string sStatus;
178         switch (hdi->connType) {
179             case CONN_TCP:
180                 sConn = "TCP";
181                 break;
182             case CONN_USB:
183                 sConn = "USB";
184                 break;
185 
186             case CONN_BT:
187                 sConn = "BT";
188                 break;
189             default:
190                 sConn = "UNKNOW";
191                 break;
192         }
193         switch (hdi->connStatus) {
194             case STATUS_READY:
195                 sStatus = "Ready";
196                 break;
197             case STATUS_CONNECTED:
198                 sStatus = "Connected";
199                 break;
200             case STATUS_OFFLINE:
201                 sStatus = "Offline";
202                 break;
203             default:
204                 sStatus = "UNKNOW";
205                 break;
206         }
207         out = Base::StringFormat("%s\t\t%s\t%s\t%s\n", hdi->connectKey.c_str(), sConn.c_str(), sStatus.c_str(),
208                                  hdi->devName.c_str());
209     } else {
210         if (hdi->connStatus == STATUS_CONNECTED) {
211             out = Base::StringFormat("%s\n", hdi->connectKey.c_str());
212         }
213     }
214 }
215 
GetDaemonMapList(uint8_t opType)216 string HdcServer::GetDaemonMapList(uint8_t opType)
217 {
218     string ret;
219     bool fullDisplay = false;
220     if (OP_GET_STRLIST_FULL == opType) {
221         fullDisplay = true;
222     }
223     uv_rwlock_rdlock(&daemonAdmin);
224     map<string, HDaemonInfo>::iterator iter;
225     string echoLine;
226     for (iter = mapDaemon.begin(); iter != mapDaemon.end(); ++iter) {
227         HDaemonInfo di = iter->second;
228         if (!di) {
229             continue;
230         }
231         echoLine = "";
232         BuildDaemonVisableLine(di, fullDisplay, echoLine);
233         ret += echoLine;
234     }
235     uv_rwlock_rdunlock(&daemonAdmin);
236     return ret;
237 }
238 
GetDaemonMapOnlyOne(HDaemonInfo & hDaemonInfoInOut)239 void HdcServer::GetDaemonMapOnlyOne(HDaemonInfo &hDaemonInfoInOut)
240 {
241     uv_rwlock_rdlock(&daemonAdmin);
242     string key;
243     for (auto &i : mapDaemon) {
244         if (i.second->connStatus == STATUS_CONNECTED) {
245             if (key == STRING_EMPTY) {
246                 key = i.first;
247             } else {
248                 key = STRING_EMPTY;
249                 break;
250             }
251         }
252     }
253     if (key.size() > 0) {
254         hDaemonInfoInOut = mapDaemon[key];
255     }
256     uv_rwlock_rdunlock(&daemonAdmin);
257 }
258 
AdminDaemonMap(uint8_t opType,const string & connectKey,HDaemonInfo & hDaemonInfoInOut)259 string HdcServer::AdminDaemonMap(uint8_t opType, const string &connectKey, HDaemonInfo &hDaemonInfoInOut)
260 {
261     string sRet;
262     switch (opType) {
263         case OP_ADD: {
264             HDaemonInfo pdiNew = new HdcDaemonInformation();
265             *pdiNew = *hDaemonInfoInOut;
266             uv_rwlock_wrlock(&daemonAdmin);
267             if (!mapDaemon[hDaemonInfoInOut->connectKey]) {
268                 mapDaemon[hDaemonInfoInOut->connectKey] = pdiNew;
269             }
270             uv_rwlock_wrunlock(&daemonAdmin);
271             break;
272         }
273         case OP_GET_STRLIST:
274         case OP_GET_STRLIST_FULL: {
275             sRet = GetDaemonMapList(opType);
276             break;
277         }
278         case OP_QUERY: {
279             uv_rwlock_rdlock(&daemonAdmin);
280             if (mapDaemon.count(connectKey)) {
281                 hDaemonInfoInOut = mapDaemon[connectKey];
282             }
283             uv_rwlock_rdunlock(&daemonAdmin);
284             break;
285         }
286         case OP_REMOVE: {
287             uv_rwlock_wrlock(&daemonAdmin);
288             if (mapDaemon.count(connectKey)) {
289                 mapDaemon.erase(connectKey);
290             }
291             uv_rwlock_wrunlock(&daemonAdmin);
292             break;
293         }
294         case OP_GET_ANY: {
295             uv_rwlock_rdlock(&daemonAdmin);
296             map<string, HDaemonInfo>::iterator iter;
297             for (iter = mapDaemon.begin(); iter != mapDaemon.end(); ++iter) {
298                 HDaemonInfo di = iter->second;
299                 // usb will be auto connected
300                 if (di->connStatus == STATUS_READY || di->connStatus == STATUS_CONNECTED) {
301                     hDaemonInfoInOut = di;
302                     break;
303                 }
304             }
305             uv_rwlock_rdunlock(&daemonAdmin);
306             break;
307         }
308         case OP_GET_ONLY: {
309             GetDaemonMapOnlyOne(hDaemonInfoInOut);
310             break;
311         }
312         case OP_UPDATE: {  // Cannot update the Object HDi lower key value by direct value
313             uv_rwlock_wrlock(&daemonAdmin);
314             HDaemonInfo hdi = mapDaemon[hDaemonInfoInOut->connectKey];
315             if (hdi) {
316                 *mapDaemon[hDaemonInfoInOut->connectKey] = *hDaemonInfoInOut;
317             }
318             uv_rwlock_wrunlock(&daemonAdmin);
319             break;
320         }
321         default:
322             break;
323     }
324     return sRet;
325 }
326 
NotifyInstanceSessionFree(HSession hSession,bool freeOrClear)327 void HdcServer::NotifyInstanceSessionFree(HSession hSession, bool freeOrClear)
328 {
329     HDaemonInfo hdiOld = nullptr;
330     AdminDaemonMap(OP_QUERY, hSession->connectKey, hdiOld);
331     if (hdiOld == nullptr) {
332         return;
333     }
334     if (!freeOrClear) {  // step1
335         // update
336         HdcDaemonInformation diNew = *hdiOld;
337         diNew.connStatus = STATUS_OFFLINE;
338         HDaemonInfo hdiNew = &diNew;
339         AdminDaemonMap(OP_UPDATE, hSession->connectKey, hdiNew);
340     } else {  // step2
341         string usbMountPoint = hdiOld->usbMountPoint;
342         constexpr int waitDaemonReconnect = UV_DEFAULT_INTERVAL;  // wait little time for daemon reinit
343         auto funcDelayUsbNotify = [this, usbMountPoint](const uint8_t flag, string &msg, const void *) -> void {
344             string s = usbMountPoint;
345             clsUSBClt->RemoveIgnoreDevice(s);
346         };
347         if (usbMountPoint.size() > 0) {
348             // wait time for daemon reconnect
349             // If removed from maplist, the USB module will be reconnected, so it needs to wait for a while
350             Base::DelayDoSimple(&loopMain, waitDaemonReconnect, funcDelayUsbNotify);
351         }
352     }
353 }
354 
HandServerAuth(HSession hSession,SessionHandShake & handshake)355 bool HdcServer::HandServerAuth(HSession hSession, SessionHandShake &handshake)
356 {
357     bool ret = false;
358     int retChild = 0;
359     string bufString;
360     switch (handshake.authType) {
361         case AUTH_TOKEN: {
362             void *ptr = nullptr;
363             bool retChild = HdcAuth::KeylistIncrement(hSession->listKey, hSession->authKeyIndex, &ptr);
364             // HdcAuth::FreeKey will be effect at funciton 'FreeSession'
365             if (!retChild) {
366                 // Iteration call certificate authentication
367                 handshake.authType = AUTH_PUBLICKEY;
368                 ret = HandServerAuth(hSession, handshake);
369                 break;
370             }
371             char sign[BUF_SIZE_DEFAULT2] = { 0 };
372             retChild = HdcAuth::AuthSign(ptr, (const unsigned char *)handshake.buf.c_str(), handshake.buf.size(), sign);
373             if (!retChild) {
374                 break;
375             }
376             handshake.buf = string(sign, retChild);
377             handshake.authType = AUTH_SIGNATURE;
378             bufString = SerialStruct::SerializeToString(handshake);
379             Send(hSession->sessionId, 0, CMD_KERNEL_HANDSHAKE, (uint8_t *)bufString.c_str(), bufString.size());
380             ret = true;
381             break;
382         }
383         case AUTH_PUBLICKEY: {
384             char bufPrivateKey[BUF_SIZE_DEFAULT2] = "";
385             retChild = HdcAuth::GetPublicKeyFileBuf((unsigned char *)bufPrivateKey, sizeof(bufPrivateKey));
386             if (!retChild) {
387                 break;
388             }
389             handshake.buf = string(bufPrivateKey, retChild);
390             handshake.authType = AUTH_PUBLICKEY;
391             bufString = SerialStruct::SerializeToString(handshake);
392             Send(hSession->sessionId, 0, CMD_KERNEL_HANDSHAKE, (uint8_t *)bufString.c_str(), bufString.size());
393             ret = true;
394             break;
395         }
396         default:
397             break;
398     }
399     return ret;
400 }
401 
ServerSessionHandshake(HSession hSession,uint8_t * payload,int payloadSize)402 bool HdcServer::ServerSessionHandshake(HSession hSession, uint8_t *payload, int payloadSize)
403 {
404     // session handshake step3
405     string s = string((char *)payload, payloadSize);
406     Hdc::HdcSessionBase::SessionHandShake handshake;
407     SerialStruct::ParseFromString(handshake, s);
408     if (handshake.banner != HANDSHAKE_MESSAGE.c_str()) {
409         WRITE_LOG(LOG_DEBUG, "Hello failed");
410         return false;
411     }
412     if (handshake.authType != AUTH_OK) {
413         if (!HandServerAuth(hSession, handshake)) {
414             WRITE_LOG(LOG_DEBUG, "Auth failed");
415             return false;
416         }
417         return true;
418     }
419     // handshake auth OK
420     HDaemonInfo hdiOld = nullptr;
421     AdminDaemonMap(OP_QUERY, hSession->connectKey, hdiOld);
422     if (!hdiOld) {
423         return false;
424     }
425     HdcDaemonInformation diNew = *hdiOld;
426     HDaemonInfo hdiNew = &diNew;
427     // update
428     hdiNew->connStatus = STATUS_CONNECTED;
429     if (handshake.buf.size() > sizeof(hdiNew->devName) || !handshake.buf.size()) {
430         hdiNew->devName = "unknow...";
431     } else {
432         hdiNew->devName = handshake.buf;
433     }
434     AdminDaemonMap(OP_UPDATE, hSession->connectKey, hdiNew);
435     hSession->handshakeOK = true;
436     return true;
437 }
438 
FetchCommand(HSession hSession,const uint32_t channelId,const uint16_t command,uint8_t * payload,const int payloadSize)439 bool HdcServer::FetchCommand(HSession hSession, const uint32_t channelId, const uint16_t command, uint8_t *payload,
440                              const int payloadSize)
441 {
442     bool ret = true;
443     HdcServerForClient *pSfc = static_cast<HdcServerForClient *>(clsServerForClient);
444     // When you first initialize, ChannelID may be 0
445     HChannel hChannel = pSfc->AdminChannel(OP_QUERY, channelId, nullptr);
446     if (CMD_KERNEL_HANDSHAKE == command) {
447         ret = ServerSessionHandshake(hSession, payload, payloadSize);
448         WRITE_LOG(LOG_DEBUG, "Session handshake %s", ret ? "successful" : "failed");
449         return ret;
450     }
451     if (!hChannel) {
452         if (command == CMD_KERNEL_CHANNEL_CLOSE) {
453             // Daemon close channel and want to notify server close channel also, but it may has been
454             // closed by herself
455         } else {
456             // Client may be ctrl+c and Server remove channel. notify server async
457         }
458         Send(hSession->sessionId, channelId, CMD_KERNEL_CHANNEL_CLOSE, payload, 1);
459         return true;
460     }
461     switch (command) {
462         case CMD_KERNEL_ECHO_RAW: {  // Native shell data output
463             pSfc->EchoClientRaw(channelId, payload, payloadSize);
464             break;
465         }
466         case CMD_KERNEL_ECHO: {
467             MessageLevel level = (MessageLevel)*payload;
468             string s(reinterpret_cast<char *>(payload + 1), payloadSize - 1);
469             pSfc->EchoClient(hChannel, level, s.c_str());
470             WRITE_LOG(LOG_DEBUG, "CMD_KERNEL_ECHO size:%d", payloadSize - 1);
471             break;
472         }
473         case CMD_KERNEL_CHANNEL_CLOSE: {
474             WRITE_LOG(LOG_DEBUG, "CMD_KERNEL_CHANNEL_CLOSE channelid:%d", channelId);
475             ClearOwnTasks(hSession, channelId);
476             // Forcibly closing the tcp handle here may result in incomplete data reception on the client side
477             HdcServerForClient *sfc = static_cast<HdcServerForClient *>(hChannel->clsChannel);
478             sfc->FreeChannel(hChannel->channelId);
479             if (*payload == 1) {
480                 --(*payload);
481                 Send(hSession->sessionId, channelId, CMD_KERNEL_CHANNEL_CLOSE, payload, 1);
482             }
483             break;
484         }
485         case CMD_FORWARD_SUCCESS: {
486             // add to local
487             HdcForwardInformation di;
488             HForwardInfo pdiNew = &di;
489             pdiNew->channelId = channelId;
490             pdiNew->sessionId = hSession->sessionId;
491             pdiNew->forwardDirection = ((char *)payload)[0] == '1';
492             pdiNew->taskString = (char *)payload + 2; // 2 len
493             AdminForwardMap(OP_ADD, STRING_EMPTY, pdiNew);
494             Base::TryCloseHandle((uv_handle_t *)&hChannel->hChildWorkTCP);  // detch client channel
495             break;
496         }
497         default: {
498             HSession hSession = AdminSession(OP_QUERY, hChannel->targetSessionId, nullptr);
499             if (!hSession) {
500                 return false;
501             }
502             ret = DispatchTaskData(hSession, hChannel->channelId, command, payload, payloadSize);
503             break;
504         }
505     }
506     return ret;
507 }
508 
BuildForwardVisableLine(bool fullOrSimble,HForwardInfo hfi,string & echo)509 void HdcServer::BuildForwardVisableLine(bool fullOrSimble, HForwardInfo hfi, string &echo)
510 {
511     string buf;
512     if (fullOrSimble) {
513         buf = Base::StringFormat("'%s'\t%s\n", hfi->taskString.c_str(),
514                                  hfi->forwardDirection ? "[Forward]" : "[Reverse]");
515     } else {
516         buf = Base::StringFormat("%s\n", hfi->taskString.c_str());
517     }
518     echo += buf;
519 }
520 
AdminForwardMap(uint8_t opType,const string & taskString,HForwardInfo & hForwardInfoInOut)521 string HdcServer::AdminForwardMap(uint8_t opType, const string &taskString, HForwardInfo &hForwardInfoInOut)
522 {
523     string sRet;
524     switch (opType) {
525         case OP_ADD: {
526             HForwardInfo pfiNew = new HdcForwardInformation();
527             *pfiNew = *hForwardInfoInOut;
528             uv_rwlock_wrlock(&forwardAdmin);
529             if (!mapForward[hForwardInfoInOut->taskString]) {
530                 mapForward[hForwardInfoInOut->taskString] = pfiNew;
531             }
532             uv_rwlock_wrunlock(&forwardAdmin);
533             break;
534         }
535         case OP_GET_STRLIST:
536         case OP_GET_STRLIST_FULL: {
537             uv_rwlock_rdlock(&forwardAdmin);
538             map<string, HForwardInfo>::iterator iter;
539             for (iter = mapForward.begin(); iter != mapForward.end(); ++iter) {
540                 HForwardInfo di = iter->second;
541                 if (!di) {
542                     continue;
543                 }
544                 BuildForwardVisableLine(opType == OP_GET_STRLIST_FULL, di, sRet);
545             }
546             uv_rwlock_rdunlock(&forwardAdmin);
547             break;
548         }
549         case OP_QUERY: {
550             uv_rwlock_rdlock(&forwardAdmin);
551             if (mapForward.count(taskString)) {
552                 hForwardInfoInOut = mapForward[taskString];
553             }
554             uv_rwlock_rdunlock(&forwardAdmin);
555             break;
556         }
557         case OP_REMOVE: {
558             uv_rwlock_wrlock(&forwardAdmin);
559             if (mapForward.count(taskString)) {
560                 mapForward.erase(taskString);
561             }
562             uv_rwlock_wrunlock(&forwardAdmin);
563             break;
564         }
565         default:
566             break;
567     }
568     return sRet;
569 }
570 
UsbPreConnect(uv_timer_t * handle)571 void HdcServer::UsbPreConnect(uv_timer_t *handle)
572 {
573     HSession hSession = (HSession)handle->data;
574     bool stopLoop = false;
575     HdcServer *hdcServer = (HdcServer *)hSession->classInstance;
576     const int usbConnectRetryMax = 5;
577     while (true) {
578         WRITE_LOG(LOG_DEBUG, "HdcServer::UsbPreConnect");
579         if (++hSession->hUSB->retryCount > usbConnectRetryMax) {  // max 15s
580             hdcServer->FreeSession(hSession->sessionId);
581             stopLoop = true;
582             break;
583         }
584         HDaemonInfo pDi = nullptr;
585         if (hSession->connectKey == "any") {
586             hdcServer->AdminDaemonMap(OP_GET_ANY, hSession->connectKey, pDi);
587         } else {
588             hdcServer->AdminDaemonMap(OP_QUERY, hSession->connectKey, pDi);
589         }
590         if (!pDi || !pDi->usbMountPoint.size()) {
591             break;
592         }
593         HdcHostUSB *hdcHostUSB = (HdcHostUSB *)hSession->classModule;
594         hdcHostUSB->ConnectDetectDaemon(hSession, pDi);
595         stopLoop = true;
596         break;
597     }
598     if (stopLoop && !uv_is_closing((const uv_handle_t *)handle)) {
599         uv_close((uv_handle_t *)handle, Base::CloseTimerCallback);
600     }
601 }
602 
603 // -1,has old,-2 error
CreateConnect(const string & connectKey)604 int HdcServer::CreateConnect(const string &connectKey)
605 {
606     uint8_t connType = 0;
607     if (connectKey.find(":") != std::string::npos) {  // TCP
608         connType = CONN_TCP;
609     } else {  // USB
610         connType = CONN_USB;
611     }
612     HDaemonInfo hdi = nullptr;
613     if (connectKey == "any") {
614         return RET_SUCCESS;
615     }
616     AdminDaemonMap(OP_QUERY, connectKey, hdi);
617     if (hdi == nullptr) {
618         HdcDaemonInformation di;
619         Base::ZeroStruct(di);
620         di.connectKey = connectKey;
621         di.connType = connType;
622         di.connStatus = STATUS_UNKNOW;
623         HDaemonInfo pDi = (HDaemonInfo)&di;
624         AdminDaemonMap(OP_ADD, "", pDi);
625         AdminDaemonMap(OP_QUERY, connectKey, hdi);
626     }
627     if (!hdi || hdi->connStatus == STATUS_CONNECTED) {
628         return ERR_GENERIC;
629     }
630     HSession hSession = nullptr;
631     if (CONN_TCP == connType) {
632         hSession = clsTCPClt->ConnectDaemon(connectKey);
633     } else {
634         hSession = MallocSession(true, CONN_USB, clsUSBClt);
635         hSession->connectKey = connectKey;
636         uv_timer_t *waitTimeDoCmd = new uv_timer_t;
637         uv_timer_init(&loopMain, waitTimeDoCmd);
638         waitTimeDoCmd->data = hSession;
639         uv_timer_start(waitTimeDoCmd, UsbPreConnect, 10, 100); // 10 100 repeat
640     }
641     if (!hSession) {
642         return ERR_BUF_ALLOC;
643     }
644     HDaemonInfo hdiQuery = nullptr;
645     AdminDaemonMap(OP_QUERY, connectKey, hdiQuery);
646     if (hdiQuery) {
647         HdcDaemonInformation diNew = *hdiQuery;
648         diNew.hSession = hSession;
649         HDaemonInfo hdiNew = &diNew;
650         AdminDaemonMap(OP_UPDATE, hdiQuery->connectKey, hdiNew);
651     }
652     return RET_SUCCESS;
653 }
654 
AttachChannel(HSession hSession,const uint32_t channelId)655 void HdcServer::AttachChannel(HSession hSession, const uint32_t channelId)
656 {
657     HdcServerForClient *hSfc = static_cast<HdcServerForClient *>(clsServerForClient);
658     HChannel hChannel = hSfc->AdminChannel(OP_QUERY, channelId, nullptr);
659     int ret = 0;
660     if (!hChannel) {
661         return;
662     }
663     uv_tcp_init(&hSession->childLoop, &hChannel->hChildWorkTCP);
664     hChannel->hChildWorkTCP.data = hChannel;
665     hChannel->targetSessionId = hSession->sessionId;
666     if ((ret = uv_tcp_open((uv_tcp_t *)&hChannel->hChildWorkTCP, hChannel->fdChildWorkTCP)) < 0) {
667         WRITE_LOG(LOG_DEBUG, "Hdcserver AttachChannel uv_tcp_open failed %s, channelid:%d fdChildWorkTCP:%d",
668                   uv_err_name(ret), hChannel->channelId, hChannel->fdChildWorkTCP);
669         Base::TryCloseHandle((uv_handle_t *)&hChannel->hChildWorkTCP);
670         return;
671     }
672     Base::SetTcpOptions((uv_tcp_t *)&hChannel->hChildWorkTCP);
673     uv_read_start((uv_stream_t *)&hChannel->hChildWorkTCP, hSfc->AllocCallback, hSfc->ReadStream);
674 };
675 
DeatchChannel(HSession hSession,const uint32_t channelId)676 void HdcServer::DeatchChannel(HSession hSession, const uint32_t channelId)
677 {
678     HdcServerForClient *hSfc = static_cast<HdcServerForClient *>(clsServerForClient);
679     HChannel hChannel = hSfc->AdminChannel(OP_QUERY, channelId, nullptr);
680     if (!hChannel) {
681         return;
682     }
683     if (hChannel->childCleared) {
684         WRITE_LOG(LOG_DEBUG, "Childchannel has already freed, cid:%d", channelId);
685         return;
686     }
687     uint8_t count = 1;
688     Send(hSession->sessionId, hChannel->channelId, CMD_KERNEL_CHANNEL_CLOSE, &count, 1);
689     if (uv_is_closing((const uv_handle_t *)&hChannel->hChildWorkTCP)) {
690         Base::DoNextLoop(&hSession->childLoop, hChannel, [](const uint8_t flag, string &msg, const void *data) {
691             HChannel hChannel = (HChannel)data;
692             hChannel->childCleared = true;
693             WRITE_LOG(LOG_DEBUG, "Childchannel free direct, cid:%d", hChannel->channelId);
694         });
695     } else {
696         Base::TryCloseHandle((uv_handle_t *)&hChannel->hChildWorkTCP, [](uv_handle_t *handle) -> void {
697             HChannel hChannel = (HChannel)handle->data;
698             hChannel->childCleared = true;
699             WRITE_LOG(LOG_DEBUG, "Childchannel free callback, cid:%d", hChannel->channelId);
700         });
701     }
702 };
703 
ServerCommand(const uint32_t sessionId,const uint32_t channelId,const uint16_t command,uint8_t * bufPtr,const int size)704 bool HdcServer::ServerCommand(const uint32_t sessionId, const uint32_t channelId, const uint16_t command,
705                               uint8_t *bufPtr, const int size)
706 {
707     HdcServerForClient *hSfc = static_cast<HdcServerForClient *>(clsServerForClient);
708     HChannel hChannel = hSfc->AdminChannel(OP_QUERY, channelId, nullptr);
709     HSession hSession = AdminSession(OP_QUERY, sessionId, nullptr);
710     if (!hChannel || !hSession) {
711         return false;
712     }
713     return FetchCommand(hSession, channelId, command, bufPtr, size);
714 }
715 
716 // clang-format off
RedirectToTask(HTaskInfo hTaskInfo,HSession hSession,const uint32_t channelId,const uint16_t command,uint8_t * payload,const int payloadSize)717 bool HdcServer::RedirectToTask(HTaskInfo hTaskInfo, HSession hSession, const uint32_t channelId,
718                                const uint16_t command, uint8_t *payload, const int payloadSize)
719 // clang-format on
720 {
721     bool ret = true;
722     hTaskInfo->ownerSessionClass = this;
723     switch (command) {
724         case CMD_UNITY_BUGREPORT_INIT:
725         case CMD_UNITY_BUGREPORT_DATA:
726             ret = TaskCommandDispatch<HdcHostUnity>(hTaskInfo, TYPE_UNITY, command, payload, payloadSize);
727             break;
728         case CMD_FILE_INIT:
729         case CMD_FILE_BEGIN:
730         case CMD_FILE_CHECK:
731         case CMD_FILE_DATA:
732         case CMD_FILE_FINISH:
733             ret = TaskCommandDispatch<HdcFile>(hTaskInfo, TASK_FILE, command, payload, payloadSize);
734             break;
735         case CMD_FORWARD_INIT:
736         case CMD_FORWARD_CHECK:
737         case CMD_FORWARD_CHECK_RESULT:
738         case CMD_FORWARD_ACTIVE_MASTER:
739         case CMD_FORWARD_DATA:
740         case CMD_FORWARD_FREE_CONTEXT:
741             ret = TaskCommandDispatch<HdcHostForward>(hTaskInfo, TASK_FORWARD, command, payload, payloadSize);
742             break;
743         case CMD_APP_INIT:
744         case CMD_APP_SIDELOAD:
745         case CMD_APP_BEGIN:
746         case CMD_APP_FINISH:
747         case CMD_APP_UNINSTALL:
748             ret = TaskCommandDispatch<HdcHostApp>(hTaskInfo, TASK_APP, command, payload, payloadSize);
749             break;
750         case CMD_UPDATER_UPDATE_INIT:
751         case CMD_UPDATER_FLASH_INIT:
752         case CMD_UPDATER_CHECK:
753         case CMD_UPDATER_BEGIN:
754         case CMD_UPDATER_DATA:
755         case CMD_UPDATER_FINISH:
756         case CMD_UPDATER_ERASE:
757         case CMD_UPDATER_FORMAT:
758         case CMD_UPDATER_PROGRESS:
759             ret = TaskCommandDispatch<HostUpdater>(hTaskInfo, TASK_UPDATER, command, payload, payloadSize);
760             break;
761         default:
762             WRITE_LOG(LOG_WARN, "RedirectToTask error command:%d ", command);
763             ret = false;
764             break;
765     }
766     return ret;
767 }
768 
RemoveInstanceTask(const uint8_t op,HTaskInfo hTask)769 bool HdcServer::RemoveInstanceTask(const uint8_t op, HTaskInfo hTask)
770 {
771     bool ret = true;
772     switch (hTask->taskType) {
773         case TYPE_SHELL:
774             WRITE_LOG(LOG_DEBUG, "Server not enable unity/shell");
775             break;
776         case TYPE_UNITY:
777             ret = DoTaskRemove<HdcHostUnity>(hTask, op);
778             break;
779         case TASK_FILE:
780             ret = DoTaskRemove<HdcFile>(hTask, op);
781             break;
782         case TASK_FORWARD:
783             ret = DoTaskRemove<HdcHostForward>(hTask, op);
784             break;
785         case TASK_APP:
786             ret = DoTaskRemove<HdcHostApp>(hTask, op);
787             break;
788         case TASK_UPDATER:
789             ret = DoTaskRemove<HostUpdater>(hTask, op);
790             break;
791         default:
792             ret = false;
793             break;
794     }
795     return ret;
796 }
797 }  // namespace Hdc