• 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 #include "host_updater.h"
17 #include "server_cmd_log.h"
18 
19 
20 namespace Hdc {
HdcServer(bool serverOrDaemonIn)21 HdcServer::HdcServer(bool serverOrDaemonIn)
22     : HdcSessionBase(serverOrDaemonIn)
23 {
24     clsTCPClt = nullptr;
25     clsUSBClt = nullptr;
26 #ifdef HDC_SUPPORT_UART
27     clsUARTClt = nullptr;
28 #endif
29     clsServerForClient = nullptr;
30     lastErrorNum = 0;
31     uv_rwlock_init(&daemonAdmin);
32     uv_rwlock_init(&forwardAdmin);
33 }
34 
~HdcServer()35 HdcServer::~HdcServer()
36 {
37     WRITE_LOG(LOG_DEBUG, "~HdcServer");
38     uv_rwlock_destroy(&daemonAdmin);
39     uv_rwlock_destroy(&forwardAdmin);
40 }
41 
ClearInstanceResource()42 void HdcServer::ClearInstanceResource()
43 {
44     TryStopInstance();
45     Base::TryCloseLoop(&loopMain, "HdcServer::~HdcServer");
46     if (clsTCPClt) {
47         delete clsTCPClt;
48         clsTCPClt = nullptr;
49     }
50     if (clsUSBClt) {
51         delete clsUSBClt;
52         clsUSBClt = nullptr;
53     }
54 #ifdef HDC_SUPPORT_UART
55     if (clsUARTClt) {
56         delete clsUARTClt;
57         clsUARTClt = nullptr;
58     }
59 #endif
60     if (clsServerForClient) {
61         delete (static_cast<HdcServerForClient *>(clsServerForClient));
62     }
63 }
64 
TryStopInstance()65 void HdcServer::TryStopInstance()
66 {
67     ClearSessions();
68     if (clsTCPClt) {
69         clsTCPClt->Stop();
70     }
71     if (clsUSBClt) {
72         clsUSBClt->Stop();
73     }
74 #ifdef HDC_SUPPORT_UART
75     if (clsUARTClt) {
76         clsUARTClt->Stop();
77     }
78 #endif
79     if (clsServerForClient) {
80         ((HdcServerForClient *)clsServerForClient)->Stop();
81     }
82     ReMainLoopForInstanceClear();
83     ClearMapDaemonInfo();
84 }
85 
Initial(const char * listenString)86 bool HdcServer::Initial(const char *listenString)
87 {
88     bool ret = false;
89     if (Base::ProgramMutex(SERVER_NAME.c_str(), false) != 0) {
90         WRITE_LOG(LOG_FATAL, "Other instance already running, program mutex failed");
91         return false;
92     }
93     Base::RemoveLogFile();
94 #ifdef HDC_SUPPORT_ENCRYPT_PRIVATE_KEY
95     if (!HdcAuth::CheckPrivateKeyFile()) {
96         WRITE_LOG(LOG_FATAL, "Private key file not found, please check your installation.");
97         return false;
98     }
99 #endif
100     do {
101         clsServerForClient = new HdcServerForClient(true, listenString, this, &loopMain);
102         int rc = (static_cast<HdcServerForClient *>(clsServerForClient))->Initial();
103         if (rc != RET_SUCCESS) {
104             WRITE_LOG(LOG_FATAL, "clsServerForClient Initial failed");
105             break;
106         }
107         clsUSBClt->InitLogging(ctxUSB);
108         clsTCPClt = new HdcHostTCP(true, this);
109         clsUSBClt = new HdcHostUSB(true, this, ctxUSB);
110         if (clsUSBClt->Initial() != RET_SUCCESS) {
111             WRITE_LOG(LOG_FATAL, "clsUSBClt Initial failed");
112             break;
113         }
114         if (!clsServerForClient || !clsTCPClt || !clsUSBClt) {
115             WRITE_LOG(LOG_FATAL, "Class init failed");
116             break;
117         }
118 #ifdef HDC_SUPPORT_UART
119         clsUARTClt = new HdcHostUART(*this);
120         if (!clsUARTClt) {
121             WRITE_LOG(LOG_FATAL, "Class init failed");
122             break;
123         }
124         if (clsUARTClt->Initial() != RET_SUCCESS) {
125             WRITE_LOG(LOG_FATAL, "clsUARTClt Class init failed.");
126             break;
127         }
128 #endif
129         Base::ProcessCmdLogs();
130         ret = true;
131     } while (0);
132     if (!ret) {
133         ClearInstanceResource();
134     }
135     return ret;
136 }
137 
PullupServerWin32(const char * path,const char * listenString)138 bool HdcServer::PullupServerWin32(const char *path, const char *listenString)
139 {
140     bool retVal = false;
141 #ifdef _WIN32
142     char buf[BUF_SIZE_SMALL] = "";
143     char shortPath[MAX_PATH] = "";
144     std::string strPath = Base::UnicodeToUtf8(path, true);
145     int ret = GetShortPathName(strPath.c_str(), shortPath, MAX_PATH);
146     std::string runPath = shortPath;
147     if (ret == 0) {
148         int err = GetLastError();
149         constexpr int bufSize = 1024;
150         char buffer[bufSize] = { 0 };
151         strerror_s(buffer, bufSize, err);
152         WRITE_LOG(LOG_WARN, "GetShortPath path:[%s] errmsg:%s", path, buffer);
153         string uvPath = path;
154         runPath = uvPath.substr(uvPath.find_last_of("/\\") + 1);
155     }
156     WRITE_LOG(LOG_DEBUG, "server shortpath:[%s] runPath:[%s]", shortPath, runPath.c_str());
157     // here we give a dummy option first, because getopt will assume the first option is command. it
158     // begin from 2nd args.
159     if (sprintf_s(buf, sizeof(buf), "dummy -l %d -s %s -m", Base::GetLogLevelByEnv(), listenString) < 0) {
160         return retVal;
161     }
162     WRITE_LOG(LOG_DEBUG, "Run server in debug-forground, cmd:%s, args:%s", runPath.c_str(), buf);
163     STARTUPINFO si = {};
164     si.cb = sizeof(STARTUPINFO);
165     PROCESS_INFORMATION pi = {};
166 #ifndef HDC_DEBUG
167     si.dwFlags = STARTF_USESHOWWINDOW;
168     si.wShowWindow = SW_HIDE;
169 #endif
170     if (!CreateProcess(runPath.c_str(), buf, nullptr, nullptr, false, CREATE_NEW_CONSOLE, nullptr, nullptr, &si, &pi)) {
171         WRITE_LOG(LOG_WARN, "CreateProcess failed with cmd:%s, args:%s, Error Code %d", runPath.c_str(), buf,
172                   GetLastError());
173         retVal = false;
174     } else {
175         retVal = true;
176     }
177     CloseHandle(pi.hThread);
178     CloseHandle(pi.hProcess);
179 #endif
180     return retVal;
181 }
182 
183 // Only detects that the default call is in the loop address, the other tubes are not
PullupServer(const char * listenString)184 bool HdcServer::PullupServer(const char *listenString)
185 {
186     char path[BUF_SIZE_SMALL] = "";
187     size_t nPathSize = sizeof(path);
188     int ret = uv_exepath(path, &nPathSize);
189     if (ret < 0) {
190         constexpr int bufSize = 1024;
191         char buf[bufSize] = { 0 };
192         uv_err_name_r(ret, buf, bufSize);
193         WRITE_LOG(LOG_WARN, "uvexepath ret:%d error:%s", ret, buf);
194         return false;
195     }
196 #ifdef FEATURE_HOST_LOG_COMPRESS
197     Base::CreateLogDir();
198 #endif
199 
200 #ifdef _WIN32
201     if (!PullupServerWin32(path, listenString)) {
202         return false;
203     }
204 #else
205     pid_t pc = fork();  // create process as daemon process
206     if (pc < 0) {
207         return false;
208     } else if (!pc) {
209         Base::CloseOpenFd();
210         Base::g_isBackgroundServer = true;
211         execl(path, "hdc", "-m", "-s", listenString, nullptr);
212         exit(0);
213         return true;
214     }
215     // orig process
216 #endif
217     // wait little time, util backend-server work ready
218     uv_sleep(TIME_BASE);
219     return true;
220 }
221 
ClearMapDaemonInfo()222 void HdcServer::ClearMapDaemonInfo()
223 {
224     map<string, HDaemonInfo>::iterator iter;
225     uv_rwlock_rdlock(&daemonAdmin);
226     for (iter = mapDaemon.begin(); iter != mapDaemon.end();) {
227         string sKey = iter->first;
228         HDaemonInfo hDi = iter->second;
229         delete hDi;
230         ++iter;
231     }
232     uv_rwlock_rdunlock(&daemonAdmin);
233     uv_rwlock_wrlock(&daemonAdmin);
234     mapDaemon.clear();
235     uv_rwlock_wrunlock(&daemonAdmin);
236 }
237 
BuildDaemonVisableLine(HDaemonInfo hdi,bool fullDisplay,string & out)238 void HdcServer::BuildDaemonVisableLine(HDaemonInfo hdi, bool fullDisplay, string &out)
239 {
240     if (fullDisplay) {
241         string sConn = conTypeDetail[CONN_UNKNOWN];
242         if (hdi->connType < CONN_UNKNOWN) {
243             sConn = conTypeDetail[hdi->connType];
244         }
245 
246         string sStatus = conStatusDetail[STATUS_UNKNOW];
247         if (hdi->connStatus < STATUS_UNAUTH) {
248             if (hdi->connStatus == STATUS_CONNECTED && hdi->daemonAuthStatus == DAEOMN_UNAUTHORIZED) {
249                 sStatus = conStatusDetail[STATUS_UNAUTH];
250             } else {
251                 sStatus = conStatusDetail[hdi->connStatus];
252             }
253         }
254 
255         string devname = hdi->devName;
256         if (devname.empty()) {
257             devname = "unknown...";
258         }
259         out = Base::StringFormat("%s\t\t%s\t%s\t%s\n", hdi->connectKey.c_str(), sConn.c_str(), sStatus.c_str(),
260                                  devname.c_str());
261     } else {
262         if (hdi->connStatus == STATUS_CONNECTED) {
263             out = Base::StringFormat("%s", hdi->connectKey.c_str());
264             if (hdi->daemonAuthStatus == DAEOMN_UNAUTHORIZED) {
265                 out.append("\tUnauthorized");
266             }
267             out.append("\n");
268         }
269     }
270 }
271 
GetDaemonMapList(uint8_t opType)272 string HdcServer::GetDaemonMapList(uint8_t opType)
273 {
274     string ret;
275     bool fullDisplay = false;
276     if (opType == OP_GET_STRLIST_FULL) {
277         fullDisplay = true;
278     }
279     uv_rwlock_rdlock(&daemonAdmin);
280     map<string, HDaemonInfo>::iterator iter;
281     string echoLine;
282     for (iter = mapDaemon.begin(); iter != mapDaemon.end(); ++iter) {
283         HDaemonInfo di = iter->second;
284         if (!di) {
285             continue;
286         }
287         echoLine = "";
288         BuildDaemonVisableLine(di, fullDisplay, echoLine);
289         ret += echoLine;
290     }
291     uv_rwlock_rdunlock(&daemonAdmin);
292     return ret;
293 }
294 
GetDaemonMapOnlyOne(HDaemonInfo & hDaemonInfoInOut)295 void HdcServer::GetDaemonMapOnlyOne(HDaemonInfo &hDaemonInfoInOut)
296 {
297     uv_rwlock_rdlock(&daemonAdmin);
298     string key;
299     for (auto &i : mapDaemon) {
300         if (i.second->connStatus == STATUS_CONNECTED) {
301             if (key == STRING_EMPTY) {
302                 key = i.first;
303             } else {
304                 key = STRING_EMPTY;
305                 break;
306             }
307         }
308     }
309     if (key.size() > 0) {
310         hDaemonInfoInOut = mapDaemon[key];
311     }
312     uv_rwlock_rdunlock(&daemonAdmin);
313 }
314 
AdminDaemonMapForWait(const string & connectKey,HDaemonInfo & hDaemonInfoInOut)315 void HdcServer::AdminDaemonMapForWait(const string &connectKey, HDaemonInfo &hDaemonInfoInOut)
316 {
317     map<string, HDaemonInfo>::iterator iter;
318     for (iter = mapDaemon.begin(); iter != mapDaemon.end(); ++iter) {
319         HDaemonInfo di = iter->second;
320         if (di->connStatus == STATUS_CONNECTED) {
321             if (!connectKey.empty() && connectKey != di->connectKey) {
322                 continue;
323             }
324             hDaemonInfoInOut = di;
325             return;
326         }
327     }
328     return;
329 }
330 
AdminDaemonMap(uint8_t opType,const string & connectKey,HDaemonInfo & hDaemonInfoInOut)331 string HdcServer::AdminDaemonMap(uint8_t opType, const string &connectKey, HDaemonInfo &hDaemonInfoInOut)
332 {
333     StartTraceScope("HdcServer::AdminDaemonMap");
334     string sRet;
335     switch (opType) {
336         case OP_ADD: {
337             HDaemonInfo pdiNew = new(std::nothrow) HdcDaemonInformation();
338             if (pdiNew == nullptr) {
339                 WRITE_LOG(LOG_FATAL, "AdminDaemonMap new pdiNew failed");
340                 break;
341             }
342             *pdiNew = *hDaemonInfoInOut;
343             uv_rwlock_wrlock(&daemonAdmin);
344             if (!mapDaemon[hDaemonInfoInOut->connectKey]) {
345                 mapDaemon[hDaemonInfoInOut->connectKey] = pdiNew;
346             }
347             uv_rwlock_wrunlock(&daemonAdmin);
348             break;
349         }
350         case OP_GET_STRLIST:
351         case OP_GET_STRLIST_FULL: {
352             sRet = GetDaemonMapList(opType);
353             break;
354         }
355         case OP_QUERY: {
356             uv_rwlock_rdlock(&daemonAdmin);
357             if (mapDaemon.count(connectKey)) {
358                 hDaemonInfoInOut = mapDaemon[connectKey];
359             }
360             uv_rwlock_rdunlock(&daemonAdmin);
361             break;
362         }
363         case OP_REMOVE: {
364             uv_rwlock_wrlock(&daemonAdmin);
365             if (mapDaemon.count(connectKey)) {
366                 HDaemonInfo hDaemonInfo = mapDaemon[connectKey];
367                 mapDaemon.erase(connectKey);
368                 if (hDaemonInfo != nullptr) {
369                     delete hDaemonInfo;
370                 }
371             }
372             uv_rwlock_wrunlock(&daemonAdmin);
373             break;
374         }
375         case OP_GET_ANY: {
376             uv_rwlock_rdlock(&daemonAdmin);
377             map<string, HDaemonInfo>::iterator iter;
378             for (iter = mapDaemon.begin(); iter != mapDaemon.end(); ++iter) {
379                 HDaemonInfo di = iter->second;
380                 // usb will be auto connected
381                 if (di->connStatus == STATUS_READY || di->connStatus == STATUS_CONNECTED) {
382                     hDaemonInfoInOut = di;
383                     break;
384                 }
385             }
386             uv_rwlock_rdunlock(&daemonAdmin);
387             break;
388         }
389         case OP_WAIT_FOR_ANY: {
390             uv_rwlock_rdlock(&daemonAdmin);
391             AdminDaemonMapForWait(connectKey, hDaemonInfoInOut);
392             uv_rwlock_rdunlock(&daemonAdmin);
393             break;
394         }
395         case OP_GET_ONLY: {
396             GetDaemonMapOnlyOne(hDaemonInfoInOut);
397             break;
398         }
399         case OP_UPDATE: {  // Cannot update the Object HDi lower key value by direct value
400             uv_rwlock_wrlock(&daemonAdmin);
401             HDaemonInfo hdi = mapDaemon[hDaemonInfoInOut->connectKey];
402             if (hdi) {
403                 *mapDaemon[hDaemonInfoInOut->connectKey] = *hDaemonInfoInOut;
404             }
405             uv_rwlock_wrunlock(&daemonAdmin);
406             break;
407         }
408         default:
409             break;
410     }
411     return sRet;
412 }
413 
NotifyInstanceSessionFree(HSession hSession,bool freeOrClear)414 void HdcServer::NotifyInstanceSessionFree(HSession hSession, bool freeOrClear)
415 {
416     HDaemonInfo hdiOld = nullptr;
417     AdminDaemonMap(OP_QUERY, hSession->connectKey, hdiOld);
418     if (hdiOld == nullptr) {
419         WRITE_LOG(LOG_FATAL, "NotifyInstanceSessionFree hdiOld nullptr");
420         return;
421     }
422     if (!freeOrClear) {  // step1
423         // update
424         HdcDaemonInformation diNew = *hdiOld;
425         diNew.inited = false;
426         diNew.connStatus = STATUS_OFFLINE;
427         diNew.hSession = nullptr;
428         HDaemonInfo hdiNew = &diNew;
429         AdminDaemonMap(OP_UPDATE, hSession->connectKey, hdiNew);
430         CleanForwardMap(hSession->sessionId);
431     } else {  // step2
432         string usbMountPoint = hdiOld->usbMountPoint;
433         // The waiting time must be longer than DEVICE_CHECK_INTERVAL. Wait the method WatchUsbNodeChange
434         // to finish execution. Otherwise, the main thread and the session worker thread will conflict
435         constexpr int waitDaemonReconnect = DEVICE_CHECK_INTERVAL + DEVICE_CHECK_INTERVAL;
436         auto funcDelayUsbNotify = [this, usbMountPoint](const uint8_t flag, string &msg, const void *) -> void {
437             string s = usbMountPoint;
438             clsUSBClt->RemoveIgnoreDevice(s);
439         };
440         if (usbMountPoint.size() > 0) {
441             // wait time for daemon reconnect
442             // If removed from maplist, the USB module will be reconnected, so it needs to wait for a while
443             Base::DelayDoSimple(&loopMain, waitDaemonReconnect, funcDelayUsbNotify);
444         }
445     }
446 }
447 
GetDaemonAuthType(HSession hSession,SessionHandShake & handshake)448 void HdcServer::GetDaemonAuthType(HSession hSession, SessionHandShake &handshake)
449 {
450     /*
451      * check if daemon support RSA_3072_SHA512 for auth
452      * it the value is not RSA_3072_SHA512, we use old auth algorithm
453      * Notice, If deamon is old version 'handshake.buf' will be 'hSession->tokenRSA',
454      * the length of hSession->tokenRSA less than min len(TLV_MIN_LEN), so there no
455      * problem
456     */
457     std::map<string, string> tlvmap;
458     hSession->verifyType = AuthVerifyType::RSA_ENCRYPT;
459     if (!Base::TlvToStringMap(handshake.buf, tlvmap)) {
460         WRITE_LOG(LOG_INFO, "the deamon maybe old version for %u session, so use rsa encrypt", hSession->sessionId);
461         return;
462     }
463     if (tlvmap.find(TAG_AUTH_TYPE) == tlvmap.end() ||
464         tlvmap[TAG_AUTH_TYPE] != std::to_string(AuthVerifyType::RSA_3072_SHA512)) {
465         WRITE_LOG(LOG_FATAL, "the buf is invalid for %u session, so use rsa encrypt", hSession->sessionId);
466         return;
467     }
468     hSession->verifyType = AuthVerifyType::RSA_3072_SHA512;
469     WRITE_LOG(LOG_INFO, "daemon auth type is rsa_3072_sha512 for %u session", hSession->sessionId);
470 }
471 
HandServerAuth(HSession hSession,SessionHandShake & handshake)472 bool HdcServer::HandServerAuth(HSession hSession, SessionHandShake &handshake)
473 {
474     string bufString;
475     switch (handshake.authType) {
476         case AUTH_PUBLICKEY: {
477             WRITE_LOG(LOG_INFO, "recive get publickey cmd");
478             GetDaemonAuthType(hSession, handshake);
479             if (!HdcAuth::GetPublicKeyinfo(handshake.buf)) {
480                 WRITE_LOG(LOG_FATAL, "load public key failed");
481                 lastErrorNum = 0x000005; // E000005: load public key failed
482                 return false;
483             }
484             handshake.authType = AUTH_PUBLICKEY;
485             bufString = SerialStruct::SerializeToString(handshake);
486             Send(hSession->sessionId, 0, CMD_KERNEL_HANDSHAKE,
487                  reinterpret_cast<uint8_t *>(const_cast<char *>(bufString.c_str())), bufString.size());
488 
489             WRITE_LOG(LOG_INFO, "send pubkey over");
490             return true;
491         }
492         case AUTH_SIGNATURE: {
493             WRITE_LOG(LOG_INFO, "recive auth signture cmd");
494             if (!HdcAuth::RsaSignAndBase64(handshake.buf, hSession->verifyType)) {
495                 WRITE_LOG(LOG_FATAL, "sign failed");
496                 return false;
497             }
498             handshake.authType = AUTH_SIGNATURE;
499             bufString = SerialStruct::SerializeToString(handshake);
500             Send(hSession->sessionId, 0, CMD_KERNEL_HANDSHAKE,
501                  reinterpret_cast<uint8_t *>(const_cast<char *>(bufString.c_str())), bufString.size());
502             WRITE_LOG(LOG_INFO, "response auth signture success");
503             return true;
504         }
505 #ifdef HDC_SUPPORT_ENCRYPT_TCP
506         case AUTH_SSL_TLS_PSK: {
507             if (hSession->classSSL == nullptr && !ServerSessionSSLInit(hSession, handshake)) {
508                 WRITE_LOG(LOG_FATAL, "SSL init failed");
509                 return false;
510             }
511             return ServerSSLHandshake(hSession, handshake);
512         }
513 #endif
514         default:
515             WRITE_LOG(LOG_FATAL, "invalid auth type %d", handshake.authType);
516             return false;
517     }
518 }
519 
UpdateHdiInfo(Hdc::HdcSessionBase::SessionHandShake & handshake,HSession & hSession)520 void HdcServer::UpdateHdiInfo(Hdc::HdcSessionBase::SessionHandShake &handshake, HSession &hSession)
521 {
522     HDaemonInfo hdiOld = nullptr;
523     if (hSession == nullptr) {
524         WRITE_LOG(LOG_FATAL, "Invalid paramter, hSession is null");
525         return;
526     }
527     AdminDaemonMap(OP_QUERY, hSession->connectKey, hdiOld);
528     if (!hdiOld) {
529         return;
530     }
531     HdcDaemonInformation diNew = *hdiOld;
532     HDaemonInfo hdiNew = &diNew;
533     // update
534     hdiNew->inited = false;
535     hdiNew->connStatus = STATUS_CONNECTED;
536     WRITE_LOG(LOG_INFO, "handshake info is : %s", handshake.ToDebugString().c_str());
537     WRITE_LOG(LOG_INFO, "handshake.buf = %s", handshake.buf.c_str());
538     if (handshake.version < "Ver: 3.0.0b") {
539         if (!handshake.buf.empty()) {
540             hdiNew->devName = handshake.buf;
541         }
542     } else {
543         std::map<string, string> tlvmap;
544         if (Base::TlvToStringMap(handshake.buf, tlvmap)) {
545             if (tlvmap.find(TAG_DEVNAME) != tlvmap.end()) {
546                 hdiNew->devName = tlvmap[TAG_DEVNAME];
547                 WRITE_LOG(LOG_INFO, "devname = %s", hdiNew->devName.c_str());
548             }
549             if (tlvmap.find(TAG_EMGMSG) != tlvmap.end()) {
550                 hdiNew->emgmsg = tlvmap[TAG_EMGMSG];
551                 WRITE_LOG(LOG_INFO, "emgmsg = %s", hdiNew->emgmsg.c_str());
552             }
553             if (tlvmap.find(TAG_DAEOMN_AUTHSTATUS) != tlvmap.end()) {
554                 hdiNew->daemonAuthStatus = tlvmap[TAG_DAEOMN_AUTHSTATUS];
555                 WRITE_LOG(LOG_INFO, "daemonauthstatus = %s", hdiNew->daemonAuthStatus.c_str());
556             }
557             if (tlvmap.find(TAG_FEATURE_SHELL_OPT) != tlvmap.end()) {
558                 hdiNew->daemonFeature[TAG_FEATURE_SHELL_OPT] = tlvmap[TAG_FEATURE_SHELL_OPT];
559                 WRITE_LOG(LOG_INFO, "shellOpt = %s", hdiNew->daemonFeature[TAG_FEATURE_SHELL_OPT].c_str());
560             }
561             ParsePeerSupportFeatures(hSession, tlvmap);
562         } else {
563             WRITE_LOG(LOG_FATAL, "TlvToStringMap failed");
564         }
565     }
566     hdiNew->version = handshake.version;
567     AdminDaemonMap(OP_UPDATE, hSession->connectKey, hdiNew);
568 }
569 
570 #ifdef HDC_SUPPORT_ENCRYPT_TCP
571 // host(  ) ---(TLS handshake client hello )--> hdcd(  ) step 1
572 // host(  ) <--(TLS handshake server hello )--- hdcd(  ) step 2
573 // host(ok) ---(TLS handshake change cipher)--> hdcd(  ) step 3
574 // host(ok) <--(TLS handshake change cipher)--- hdcd(ok) step 4
ServerSSLHandshake(HSession hSession,SessionHandShake & handshake)575 bool HdcServer::ServerSSLHandshake(HSession hSession, SessionHandShake &handshake)
576 {
577     if (hSession->classSSL == nullptr) {
578         WRITE_LOG(LOG_DEBUG, "ssl is nullptr");
579         return false;
580     }
581     HdcSSLBase *hssl = static_cast<HdcSSLBase *>(hSession->classSSL);
582     if (hssl == nullptr) {
583         WRITE_LOG(LOG_WARN, "hssl is null");
584         return false;
585     }
586     if (handshake.buf.size() != 0) {
587         uint8_t *payload = reinterpret_cast<uint8_t*>(handshake.buf.data());
588         int payloadSize = handshake.buf.size();
589         int retw = hssl->DoBIOWrite(payload, payloadSize);
590         if (retw != payloadSize) {
591             WRITE_LOG(LOG_DEBUG, "BIO_write failed");
592             return false;
593         }
594     }
595     vector<uint8_t> buf;
596     int ret = hssl->PerformHandshake(buf);
597     if (ret == RET_SUCCESS) { // SSL handshake step 1 and step 3
598         if (buf.size() == 0) { // no handshake data
599             WRITE_LOG(LOG_WARN, "SSL PerformHandshake failed, buffer data size is 0");
600             return false;
601         }
602         handshake.buf.assign(buf.begin(), buf.end());
603         string bufString = SerialStruct::SerializeToString(handshake);
604         Send(hSession->sessionId, 0, CMD_KERNEL_HANDSHAKE,
605              reinterpret_cast<uint8_t *>(const_cast<char *>(bufString.c_str())), bufString.size());
606     }
607     if (ret == RET_SSL_HANDSHAKE_FINISHED) {
608         hssl->SetHandshakeLabel(hSession);
609         WRITE_LOG(LOG_DEBUG, "ssl handshake finished, SetHandshakeLabel");
610         if (!hssl->ClearPsk()) {
611             WRITE_LOG(LOG_WARN, "clear Pre Shared Key failed");
612             ret = ERR_GENERIC;
613         }
614     }
615     fill(buf.begin(), buf.end(), 0);
616     return ret >= RET_SUCCESS;
617 }
618 
ServerSessionSSLInit(HSession hSession,SessionHandShake & handshake)619 bool HdcServer::ServerSessionSSLInit(HSession hSession, SessionHandShake &handshake)
620 {
621     WRITE_LOG(LOG_INFO, "ServerSession SSL Init");
622     int payloadSize = handshake.buf.size();
623     uint8_t *payload = reinterpret_cast<uint8_t*>(handshake.buf.data());
624     if (payloadSize < BUF_SIZE_PSK) {
625         WRITE_LOG(LOG_WARN, "Encrypted Pre-Shared-Key payloadSize is %d", payloadSize);
626         return false;
627     }
628     std::unique_ptr<unsigned char[]> out(std::make_unique<unsigned char[]>(BUF_SIZE_DEFAULT2));
629     if (!out) {
630         WRITE_LOG(LOG_WARN, "new buffer failed");
631         return false;
632     }
633     if (memset_s(out.get(), BUF_SIZE_DEFAULT2, 0, BUF_SIZE_DEFAULT2) != EOK) {
634         WRITE_LOG(LOG_WARN, "ServerSessionSSLInit memset_s failed");
635         return false;
636     }
637     SSLInfoPtr hSSLInfo = new (std::nothrow) HdcSSLInfo();
638     if (!hSSLInfo) {
639         WRITE_LOG(LOG_WARN, "new SSLInfoPtr failed");
640         return false;
641     }
642     HdcSSLBase::SetSSLInfo(hSSLInfo, hSession);
643     hSession->classSSL = new (std::nothrow) HdcHostSSL(hSSLInfo);
644     delete hSSLInfo;
645     HdcSSLBase *hssl = static_cast<HdcSSLBase *>(hSession->classSSL);
646     if (!hssl) {
647         WRITE_LOG(LOG_WARN, "new HdcHostSSL failed");
648         return false;
649     }
650     int outLen = hssl->RsaPrikeyDecrypt(reinterpret_cast<const unsigned char*>(payload),
651         payloadSize, out.get(), BUF_SIZE_DEFAULT2);
652     if (outLen <= 0) {
653         WRITE_LOG(LOG_WARN, "RsaPrivatekeyDecrypt failed, sid:%d", hSession->sessionId);
654         return false;
655     }
656     if (!hssl->InputPsk(out.get(), outLen)) {
657         WRITE_LOG(LOG_WARN, "InputPsk failed, sid:%d", hSession->sessionId);
658         return false;
659     }
660     int initRet = hssl->InitSSL();
661     if (initRet != RET_SUCCESS) {
662         WRITE_LOG(LOG_WARN, "InitSSL failed");
663         return false;
664     }
665     handshake.buf.clear();
666     return true;
667 }
668 #endif
669 
ServerSessionHandshake(HSession hSession,uint8_t * payload,int payloadSize)670 bool HdcServer::ServerSessionHandshake(HSession hSession, uint8_t *payload, int payloadSize)
671 {
672     // session handshake step3
673     string s = string(reinterpret_cast<char *>(payload), payloadSize);
674     Hdc::HdcSessionBase::SessionHandShake handshake;
675     SerialStruct::ParseFromString(handshake, s);
676 #ifdef HDC_DEBUG
677     WRITE_LOG(LOG_DEBUG, "handshake.banner:%s, payload:%s(%d)", handshake.banner.c_str(), s.c_str(), payloadSize);
678 #endif
679 
680     if (handshake.banner == HANDSHAKE_FAILED.c_str()) {
681         WRITE_LOG(LOG_FATAL, "Handshake failed");
682         return false;
683     }
684 
685     if (handshake.banner != HANDSHAKE_MESSAGE.c_str()) {
686         WRITE_LOG(LOG_DEBUG, "Hello failed");
687         return false;
688     }
689     if (handshake.authType != AUTH_OK) {
690         if (!HandServerAuth(hSession, handshake)) {
691             WRITE_LOG(LOG_WARN, "Auth failed");
692             return false;
693         }
694         return true;
695     }
696     // handshake auth OK
697     UpdateHdiInfo(handshake, hSession);
698     hSession->handshakeOK = true;
699     return true;
700 }
701 
702 // call in child thread
FetchCommand(HSession hSession,const uint32_t channelId,const uint16_t command,uint8_t * payload,const int payloadSize)703 bool HdcServer::FetchCommand(HSession hSession, const uint32_t channelId, const uint16_t command, uint8_t *payload,
704                              const int payloadSize)
705 {
706     bool ret = true;
707     HdcServerForClient *sfc = static_cast<HdcServerForClient *>(clsServerForClient);
708     if (command == CMD_KERNEL_HANDSHAKE) {
709         ret = ServerSessionHandshake(hSession, payload, payloadSize);
710         WRITE_LOG(LOG_INFO, "Session handshake %s connType:%d sid:%u", ret ? "successful" : "failed",
711                   hSession->connType, hSession->sessionId);
712         return ret;
713     }
714     if (command == CMD_HEARTBEAT_MSG) {
715         // heartbeat msg
716         std::string str = hSession->heartbeat.HandleRecvHeartbeatMsg(payload, payloadSize);
717         WRITE_LOG(LOG_INFO, "recv %s for session %u", str.c_str(), hSession->sessionId);
718         return ret;
719     }
720     // When you first initialize, ChannelID may be 0
721     HChannel hChannel = sfc->AdminChannel(OP_QUERY_REF, channelId, nullptr);
722     if (!hChannel) {
723         if (command == CMD_KERNEL_CHANNEL_CLOSE) {
724             // Daemon close channel and want to notify server close channel also, but it may has been
725             // closed by herself
726             WRITE_LOG(LOG_WARN, "Die channelId :%lu recv CMD_KERNEL_CHANNEL_CLOSE", channelId);
727         } else {
728             // Client may be ctrl+c and Server remove channel. notify server async
729             WRITE_LOG(LOG_DEBUG, "channelId :%lu die", channelId);
730         }
731         uint8_t flag = 0;
732         Send(hSession->sessionId, channelId, CMD_KERNEL_CHANNEL_CLOSE, &flag, 1);
733         return ret;
734     }
735     if (hChannel->isDead) {
736         WRITE_LOG(LOG_FATAL, "FetchCommand channelId:%u isDead", channelId);
737         uint8_t flag = 0;
738         Send(hSession->sessionId, channelId, CMD_KERNEL_CHANNEL_CLOSE, &flag, 1);
739         --hChannel->ref;
740         return ret;
741     }
742     switch (command) {
743         case CMD_KERNEL_ECHO_RAW: {  // Native shell data output
744             sfc->EchoClientRaw(hChannel, payload, payloadSize);
745             break;
746         }
747         case CMD_KERNEL_ECHO: {
748             MessageLevel level = static_cast<MessageLevel>(*payload);
749             string s(reinterpret_cast<char *>(payload + 1), payloadSize - 1);
750             sfc->EchoClient(hChannel, level, s.c_str());
751             WRITE_LOG(LOG_INFO, "CMD_KERNEL_ECHO size:%d cid:%u sid:%u", payloadSize - 1, channelId,
752                 hSession->sessionId);
753             break;
754         }
755         case CMD_KERNEL_CHANNEL_CLOSE: {
756             WRITE_LOG(LOG_INFO, "CMD_KERNEL_CHANNEL_CLOSE cid:%u sid:%u", channelId, hSession->sessionId);
757             // Forcibly closing the tcp handle here may result in incomplete data reception on the client side
758             ClearOwnTasks(hSession, channelId);
759             // crossthread free
760             sfc->PushAsyncMessage(channelId, ASYNC_FREE_CHANNEL, nullptr, 0);
761             if (*payload != 0) {
762                 --(*payload);
763                 Send(hSession->sessionId, channelId, CMD_KERNEL_CHANNEL_CLOSE, payload, 1);
764             }
765             break;
766         }
767         case CMD_FORWARD_SUCCESS: {
768             // add to local
769             HdcForwardInformation di;
770             HForwardInfo pdiNew = &di;
771             pdiNew->channelId = channelId;
772             pdiNew->sessionId = hSession->sessionId;
773             pdiNew->connectKey = hSession->connectKey;
774             pdiNew->forwardDirection = (reinterpret_cast<char *>(payload))[0] == '1';
775             pdiNew->taskString = reinterpret_cast<char *>(payload);
776             AdminForwardMap(OP_ADD, STRING_EMPTY, pdiNew);
777 #ifdef __OHOS__
778             if (hChannel->isUds) {
779                 Base::TryCloseHandle((uv_handle_t *)&hChannel->hChildWorkUds);
780             } else {
781                 Base::TryCloseHandle((uv_handle_t *)&hChannel->hChildWorkTCP);
782             }
783 #else
784             Base::TryCloseHandle((uv_handle_t *)&hChannel->hChildWorkTCP);  // detch client channel
785 #endif
786             break;
787         }
788         case CMD_FILE_INIT:
789         case CMD_FILE_CHECK:
790         case CMD_FILE_BEGIN:
791         case CMD_FILE_DATA:
792         case CMD_FILE_FINISH:
793         case CMD_FILE_MODE:
794         case CMD_DIR_MODE:
795         case CMD_APP_INIT:
796         case CMD_APP_CHECK:
797         case CMD_APP_BEGIN:
798         case CMD_APP_DATA:
799         case CMD_APP_FINISH:
800             if (hChannel->fromClient) {
801                 // server directly passthrough app command to client if remote file mode, else go default
802                 sfc->SendCommandToClient(hChannel, command, payload, payloadSize);
803                 break;
804             }
805         default: {
806             HSession hSessionByQuery = AdminSession(OP_QUERY, hChannel->targetSessionId, nullptr);
807             if (!hSessionByQuery) {
808                 ret = false;
809                 break;
810             }
811             ret = DispatchTaskData(hSessionByQuery, channelId, command, payload, payloadSize);
812             break;
813         }
814     }
815     --hChannel->ref;
816     return ret;
817 }
818 
BuildForwardVisableLine(bool fullOrSimble,HForwardInfo hfi,string & echo)819 void HdcServer::BuildForwardVisableLine(bool fullOrSimble, HForwardInfo hfi, string &echo)
820 {
821     string buf;
822     if (fullOrSimble) {
823         buf = Base::StringFormat("%s    %s    %s\n", hfi->connectKey.c_str(), hfi->taskString.substr(OFFSET).c_str(),
824                                  hfi->forwardDirection ? "[Forward]" : "[Reverse]");
825     } else {
826         buf = Base::StringFormat("%s\n", hfi->taskString.c_str());
827     }
828     echo += buf;
829 }
830 
AdminForwardMap(uint8_t opType,const string & taskString,HForwardInfo & hForwardInfoInOut)831 string HdcServer::AdminForwardMap(uint8_t opType, const string &taskString, HForwardInfo &hForwardInfoInOut)
832 {
833     string sRet;
834     switch (opType) {
835         case OP_ADD: {
836             HForwardInfo pfiNew = new(std::nothrow) HdcForwardInformation();
837             if (pfiNew == nullptr) {
838                 WRITE_LOG(LOG_FATAL, "AdminForwardMap new pfiNew failed");
839                 break;
840             }
841             *pfiNew = *hForwardInfoInOut;
842             uv_rwlock_wrlock(&forwardAdmin);
843             if (!mapForward[hForwardInfoInOut->taskString]) {
844                 mapForward[hForwardInfoInOut->taskString] = pfiNew;
845             }
846             uv_rwlock_wrunlock(&forwardAdmin);
847             break;
848         }
849         case OP_GET_STRLIST:
850         case OP_GET_STRLIST_FULL: {
851             uv_rwlock_rdlock(&forwardAdmin);
852             map<string, HForwardInfo>::iterator iter;
853             for (iter = mapForward.begin(); iter != mapForward.end(); ++iter) {
854                 HForwardInfo di = iter->second;
855                 if (!di) {
856                     continue;
857                 }
858                 BuildForwardVisableLine(opType == OP_GET_STRLIST_FULL, di, sRet);
859             }
860             uv_rwlock_rdunlock(&forwardAdmin);
861             break;
862         }
863         case OP_QUERY: {
864             uv_rwlock_rdlock(&forwardAdmin);
865             if (mapForward.count(taskString)) {
866                 hForwardInfoInOut = mapForward[taskString];
867             }
868             uv_rwlock_rdunlock(&forwardAdmin);
869             break;
870         }
871         case OP_REMOVE: {
872             uv_rwlock_wrlock(&forwardAdmin);
873             if (mapForward.count(taskString)) {
874                 HForwardInfo hForwardInfo = mapForward[taskString];
875                 mapForward.erase(taskString);
876                 if (hForwardInfo != nullptr) {
877                     delete hForwardInfo;
878                 }
879             }
880             uv_rwlock_wrunlock(&forwardAdmin);
881             break;
882         }
883         default:
884             break;
885     }
886     return sRet;
887 }
888 
CleanForwardMap(uint32_t sessionId)889 void HdcServer::CleanForwardMap(uint32_t sessionId)
890 {
891     uv_rwlock_rdlock(&forwardAdmin);
892     map<string, HForwardInfo>::iterator iter;
893     for (iter = mapForward.begin(); iter != mapForward.end();) {
894         HForwardInfo di = iter->second;
895         if (!di) {
896             continue;
897         }
898         if (sessionId == 0 || sessionId == di->sessionId) {
899             iter = mapForward.erase(iter);
900         } else {
901             iter++;
902         }
903     }
904     uv_rwlock_rdunlock(&forwardAdmin);
905 }
906 
UsbPreConnect(uv_timer_t * handle)907 void HdcServer::UsbPreConnect(uv_timer_t *handle)
908 {
909     HSession hSession = (HSession)handle->data;
910     bool stopLoop = false;
911     HdcServer *hdcServer = (HdcServer *)hSession->classInstance;
912     CALLSTAT_GUARD(hdcServer->loopMainStatus, handle->loop, "HdcServer::UsbPreConnect");
913     while (true) {
914         WRITE_LOG(LOG_DEBUG, "HdcServer::UsbPreConnect");
915         HDaemonInfo pDi = nullptr;
916         if (hSession->connectKey == "any") {
917             hdcServer->AdminDaemonMap(OP_GET_ANY, hSession->connectKey, pDi);
918         } else {
919             hdcServer->AdminDaemonMap(OP_QUERY, hSession->connectKey, pDi);
920         }
921         if (!pDi || !pDi->usbMountPoint.size()) {
922             break;
923         }
924         HdcHostUSB *hdcHostUSB = (HdcHostUSB *)hSession->classModule;
925         hdcHostUSB->ConnectDetectDaemon(hSession, pDi);
926         stopLoop = true;
927         break;
928     }
929     if (stopLoop && !uv_is_closing((const uv_handle_t *)handle)) {
930         uv_close((uv_handle_t *)handle, Base::CloseTimerCallback);
931     }
932 }
933 #ifdef HDC_SUPPORT_UART
UartPreConnect(uv_timer_t * handle)934 void HdcServer::UartPreConnect(uv_timer_t *handle)
935 {
936     WRITE_LOG(LOG_DEBUG, "%s", __FUNCTION__);
937     HSession hSession = (HSession)handle->data;
938     bool stopLoop = false;
939     HdcServer *hdcServer = (HdcServer *)hSession->classInstance;
940     const int uartConnectRetryMax = 100; // max 6s
941     while (true) {
942         if (hSession->hUART->retryCount > uartConnectRetryMax) {
943             WRITE_LOG(LOG_DEBUG, "%s failed because max retry limit %d", __FUNCTION__,
944                       hSession->hUART->retryCount);
945             hdcServer->FreeSession(hSession->sessionId);
946             stopLoop = true;
947             break;
948         }
949         hSession->hUART->retryCount++;
950         HDaemonInfo pDi = nullptr;
951 
952         WRITE_LOG(LOG_DEBUG, "%s query %s", __FUNCTION__, hSession->ToDebugString().c_str());
953         hdcServer->AdminDaemonMap(OP_QUERY, hSession->connectKey, pDi);
954         if (!pDi) {
955             WRITE_LOG(LOG_DEBUG, "%s not found", __FUNCTION__);
956             break;
957         }
958         HdcHostUART *hdcHostUART = (HdcHostUART *)hSession->classModule;
959         hdcHostUART->ConnectDaemonByUart(hSession, pDi);
960         WRITE_LOG(LOG_DEBUG, "%s ConnectDaemonByUart done", __FUNCTION__);
961 
962         stopLoop = true;
963         break;
964     }
965     if (stopLoop) {
966         uv_close((uv_handle_t *)handle, Base::CloseTimerCallback);
967     }
968 }
969 
CreatConnectUart(HSession hSession)970 void HdcServer::CreatConnectUart(HSession hSession)
971 {
972     uv_timer_t *waitTimeDoCmd = new(std::nothrow) uv_timer_t;
973     if (waitTimeDoCmd == nullptr) {
974         WRITE_LOG(LOG_FATAL, "CreatConnectUart new waitTimeDoCmd failed");
975         return;
976     }
977     uv_timer_init(&loopMain, waitTimeDoCmd);
978     waitTimeDoCmd->data = hSession;
979     uv_timer_start(waitTimeDoCmd, UartPreConnect, UV_TIMEOUT, UV_REPEAT);
980 }
981 #endif
982 // -1,has old,-2 error
CreateConnect(const string & connectKey,bool isCheck)983 int HdcServer::CreateConnect(const string &connectKey, bool isCheck)
984 {
985     uint8_t connType = 0;
986     if (connectKey.find(":") != std::string::npos) { // TCP
987         connType = CONN_TCP;
988     }
989 #ifdef HDC_SUPPORT_UART
990     else if (connectKey.find("COM") == 0 ||
991              connectKey.find("/dev/ttyUSB") == 0 ||
992              connectKey.find("/dev/cu.") == 0) { // UART
993         connType = CONN_SERIAL;
994     }
995 #endif
996     else { // Not support
997         return ERR_NO_SUPPORT;
998     }
999     HDaemonInfo hdi = nullptr;
1000     if (connectKey == "any") {
1001         return RET_SUCCESS;
1002     }
1003     AdminDaemonMap(OP_QUERY, connectKey, hdi);
1004     if (hdi == nullptr) {
1005         HdcDaemonInformation di = {};
1006         di.connectKey = connectKey;
1007         di.connType = connType;
1008         di.connStatus = STATUS_UNKNOW;
1009         di.inited = false;
1010         HDaemonInfo pDi = reinterpret_cast<HDaemonInfo>(&di);
1011         AdminDaemonMap(OP_ADD, "", pDi);
1012         AdminDaemonMap(OP_QUERY, connectKey, hdi);
1013     }
1014     if (!hdi || hdi->connStatus == STATUS_CONNECTED) {
1015         WRITE_LOG(LOG_FATAL, "Connected return");
1016         return ERR_GENERIC;
1017     }
1018     if (hdi->inited == true) {
1019         WRITE_LOG(LOG_FATAL, "Connection is inited");
1020         return ERR_GENERIC;
1021     }
1022     HSession hSession = nullptr;
1023     if (connType == CONN_TCP) {
1024         hSession = clsTCPClt->ConnectDaemon(connectKey, isCheck);
1025     } else if (connType == CONN_SERIAL) {
1026 #ifdef HDC_SUPPORT_UART
1027         clsUARTClt->SetCheckFlag(isCheck);
1028         hSession = clsUARTClt->ConnectDaemon(connectKey);
1029 #endif
1030     } else {
1031         hSession = MallocSession(true, CONN_USB, clsUSBClt);
1032         if (!hSession) {
1033             WRITE_LOG(LOG_FATAL, "CreateConnect malloc usb session failed %s", Hdc::MaskString(connectKey).c_str());
1034             return ERR_BUF_ALLOC;
1035         }
1036         hSession->connectKey = connectKey;
1037         uv_timer_t *waitTimeDoCmd = new(std::nothrow) uv_timer_t;
1038         if (waitTimeDoCmd == nullptr) {
1039             WRITE_LOG(LOG_FATAL, "CreateConnect new waitTimeDoCmd failed");
1040             FreeSession(hSession->sessionId);
1041             return ERR_GENERIC;
1042         }
1043         uv_timer_init(&loopMain, waitTimeDoCmd);
1044         waitTimeDoCmd->data = hSession;
1045         uv_timer_start(waitTimeDoCmd, UsbPreConnect, UV_TIMEOUT, UV_REPEAT);
1046     }
1047     if (!hSession) {
1048         WRITE_LOG(LOG_FATAL, "CreateConnect hSession nullptr");
1049         return ERR_BUF_ALLOC;
1050     }
1051     HDaemonInfo hdiQuery = nullptr;
1052     AdminDaemonMap(OP_QUERY, connectKey, hdiQuery);
1053     if (hdiQuery) {
1054         HdcDaemonInformation diNew = *hdiQuery;
1055         diNew.hSession = hSession;
1056         diNew.inited = true;
1057         HDaemonInfo hdiNew = &diNew;
1058         AdminDaemonMap(OP_UPDATE, hdiQuery->connectKey, hdiNew);
1059     }
1060     return RET_SUCCESS;
1061 }
1062 
1063 #ifdef HOST_OHOS
AttachChannelInnerForUds(HSession hSession,const uint32_t channelId)1064 void HdcServer::AttachChannelInnerForUds(HSession hSession, const uint32_t channelId)
1065 {
1066     int ret = 0;
1067     HdcServerForClient *hSfc = static_cast<HdcServerForClient *>(clsServerForClient);
1068     HChannel hChannel = hSfc->AdminChannel(OP_QUERY_REF, channelId, nullptr);
1069     if (!hChannel) {
1070         WRITE_LOG(LOG_DEBUG, "AttachChannelInnerForUds hChannel null channelId:%u", channelId);
1071         return;
1072     }
1073     uv_pipe_init(&hSession->childLoop, &hChannel->hChildWorkUds, 0);
1074     hChannel->hChildWorkUds.data = hChannel;
1075     hChannel->loopStatus = &hSession->childLoopStatus;
1076     hChannel->targetSessionId = hSession->sessionId;
1077     hSession->commandCount++;
1078     if ((ret = uv_pipe_open((uv_pipe_t *)&hChannel->hChildWorkUds, hChannel->fdChildWorkTCP)) < 0) {
1079         constexpr int bufSize = 1024;
1080         char buf[bufSize] = { 0 };
1081         uv_err_name_r(ret, buf, bufSize);
1082         WRITE_LOG(LOG_WARN, "Hdcserver AttachChannel uv_tcp_open failed %s, channelid:%d fdChildWorkTCP:%d",
1083                   buf, hChannel->channelId, hChannel->fdChildWorkTCP);
1084         Base::TryCloseHandle((uv_handle_t *)&hChannel->hChildWorkUds);
1085         --hChannel->ref;
1086         return;
1087     }
1088     Base::SetUdsOptions((uv_pipe_t *)&hChannel->hChildWorkUds);
1089     uv_read_start((uv_stream_t *)&hChannel->hChildWorkUds, hSfc->AllocCallback, hSfc->ReadStream);
1090     --hChannel->ref;
1091     WRITE_LOG(LOG_INFO, "AttachChannelInnerForUds");
1092 };
1093 
DeatchChannelInnerForUds(HSession hSession,const uint32_t channelId)1094 void HdcServer::DeatchChannelInnerForUds(HSession hSession, const uint32_t channelId)
1095 {
1096     HdcServerForClient *hSfc = static_cast<HdcServerForClient *>(clsServerForClient);
1097     // childCleared has not set, no need OP_QUERY_REF
1098     HChannel hChannel = hSfc->AdminChannel(OP_QUERY, channelId, nullptr);
1099     if (!hChannel) {
1100         ClearOwnTasks(hSession, channelId);
1101         uint8_t count = 0;
1102         Send(hSession->sessionId, channelId, CMD_KERNEL_CHANNEL_CLOSE, &count, 1);
1103         WRITE_LOG(LOG_WARN, "DeatchChannelInnerForUds hChannel null channelId:%u", channelId);
1104         return;
1105     }
1106     if (hChannel->childCleared) {
1107         WRITE_LOG(LOG_DEBUG, "Childchannel has already freed, cid:%u", channelId);
1108         return;
1109     }
1110     // The own task for this channel must be clear before free channel
1111     ClearOwnTasks(hSession, channelId);
1112     uint8_t count = 0;
1113     Send(hSession->sessionId, hChannel->channelId, CMD_KERNEL_CHANNEL_CLOSE, &count, 1);
1114     WRITE_LOG(LOG_DEBUG, "Childchannel begin close, cid:%u, sid:%u", hChannel->channelId, hSession->sessionId);
1115     if (uv_is_closing((const uv_handle_t *)&hChannel->hChildWorkUds)) {
1116         Base::DoNextLoop(&hSession->childLoop, hChannel, [](const uint8_t flag, string &msg, const void *data) {
1117             HChannel hChannel = (HChannel)data;
1118             hChannel->childCleared = true;
1119             WRITE_LOG(LOG_DEBUG, "Childchannel free direct, cid:%u", hChannel->channelId);
1120         });
1121     } else {
1122         if (hChannel->hChildWorkUds.loop == NULL) {
1123             WRITE_LOG(LOG_DEBUG, "Childchannel loop is null, cid:%u", hChannel->channelId);
1124         }
1125         Base::TryCloseHandle((uv_handle_t *)&hChannel->hChildWorkUds, [](uv_handle_t *handle) -> void {
1126             HChannel hChannel = (HChannel)handle->data;
1127             hChannel->childCleared = true;
1128             WRITE_LOG(LOG_DEBUG, "Childchannel free callback, cid:%u", hChannel->channelId);
1129         });
1130     }
1131 };
1132 
AttachChannel(HSession hSession,const uint32_t channelId)1133 void HdcServer::AttachChannel(HSession hSession, const uint32_t channelId)
1134 {
1135     HdcServerForClient *hSfc = static_cast<HdcServerForClient *>(clsServerForClient);
1136     HChannel hChannel = hSfc->AdminChannel(OP_QUERY, channelId, nullptr);
1137     if (!hChannel) {
1138         WRITE_LOG(LOG_DEBUG, "AttachChannel hChannel null channelId:%u", channelId);
1139         return;
1140     }
1141     if (hChannel->isUds) {
1142         AttachChannelInnerForUds(hSession, channelId);
1143     } else {
1144         AttachChannelInnerForTcp(hSession, channelId);
1145     }
1146 }
1147 
DeatchChannel(HSession hSession,const uint32_t channelId)1148 void HdcServer::DeatchChannel(HSession hSession, const uint32_t channelId)
1149 {
1150     HdcServerForClient *hSfc = static_cast<HdcServerForClient *>(clsServerForClient);
1151     // childCleared has not set, no need OP_QUERY_REF
1152     HChannel hChannel = hSfc->AdminChannel(OP_QUERY, channelId, nullptr);
1153     if (!hChannel) {
1154         ClearOwnTasks(hSession, channelId);
1155         uint8_t count = 0;
1156         Send(hSession->sessionId, channelId, CMD_KERNEL_CHANNEL_CLOSE, &count, 1);
1157         WRITE_LOG(LOG_WARN, "DeatchChannel hChannel null channelId:%u", channelId);
1158         return;
1159     }
1160     if (hChannel->childCleared) {
1161         WRITE_LOG(LOG_DEBUG, "Childchannel has already freed, cid:%u", channelId);
1162         return;
1163     }
1164     if (hChannel->isUds) {
1165         DeatchChannelInnerForUds(hSession, channelId);
1166     } else {
1167         DeatchChannelInnerForTcp(hSession, channelId);
1168     }
1169 }
1170 #else
AttachChannel(HSession hSession,const uint32_t channelId)1171 void HdcServer::AttachChannel(HSession hSession, const uint32_t channelId)
1172 {
1173     AttachChannelInnerForTcp(hSession, channelId);
1174 }
1175 
DeatchChannel(HSession hSession,const uint32_t channelId)1176 void HdcServer::DeatchChannel(HSession hSession, const uint32_t channelId)
1177 {
1178     DeatchChannelInnerForTcp(hSession, channelId);
1179 }
1180 #endif
1181 
AttachChannelInnerForTcp(HSession hSession,const uint32_t channelId)1182 void HdcServer::AttachChannelInnerForTcp(HSession hSession, const uint32_t channelId)
1183 {
1184     int ret = 0;
1185     HdcServerForClient *hSfc = static_cast<HdcServerForClient *>(clsServerForClient);
1186     HChannel hChannel = hSfc->AdminChannel(OP_QUERY_REF, channelId, nullptr);
1187     if (!hChannel) {
1188         WRITE_LOG(LOG_DEBUG, "AttachChannel hChannel null channelId:%u", channelId);
1189         return;
1190     }
1191     uv_tcp_init(&hSession->childLoop, &hChannel->hChildWorkTCP);
1192     hChannel->hChildWorkTCP.data = hChannel;
1193     hChannel->loopStatus = &hSession->childLoopStatus;
1194     hChannel->targetSessionId = hSession->sessionId;
1195     hSession->commandCount++;
1196     if ((ret = uv_tcp_open((uv_tcp_t *)&hChannel->hChildWorkTCP, hChannel->fdChildWorkTCP)) < 0) {
1197         constexpr int bufSize = 1024;
1198         char buf[bufSize] = { 0 };
1199         uv_err_name_r(ret, buf, bufSize);
1200         WRITE_LOG(LOG_WARN, "Hdcserver AttachChannel uv_tcp_open failed %s, channelid:%d fdChildWorkTCP:%d",
1201                   buf, hChannel->channelId, hChannel->fdChildWorkTCP);
1202         Base::TryCloseHandle((uv_handle_t *)&hChannel->hChildWorkTCP);
1203         --hChannel->ref;
1204         return;
1205     }
1206     Base::SetTcpOptions((uv_tcp_t *)&hChannel->hChildWorkTCP);
1207     uv_read_start((uv_stream_t *)&hChannel->hChildWorkTCP, hSfc->AllocCallback, hSfc->ReadStream);
1208     --hChannel->ref;
1209 };
1210 
DeatchChannelInnerForTcp(HSession hSession,const uint32_t channelId)1211 void HdcServer::DeatchChannelInnerForTcp(HSession hSession, const uint32_t channelId)
1212 {
1213     HdcServerForClient *hSfc = static_cast<HdcServerForClient *>(clsServerForClient);
1214     // childCleared has not set, no need OP_QUERY_REF
1215     HChannel hChannel = hSfc->AdminChannel(OP_QUERY, channelId, nullptr);
1216     if (!hChannel) {
1217         ClearOwnTasks(hSession, channelId);
1218         uint8_t count = 0;
1219         Send(hSession->sessionId, channelId, CMD_KERNEL_CHANNEL_CLOSE, &count, 1);
1220         WRITE_LOG(LOG_WARN, "DeatchChannel hChannel null channelId:%u", channelId);
1221         return;
1222     }
1223     if (hChannel->childCleared) {
1224         WRITE_LOG(LOG_DEBUG, "Childchannel has already freed, cid:%u", channelId);
1225         return;
1226     }
1227     // The own task for this channel must be clear before free channel
1228     ClearOwnTasks(hSession, channelId);
1229     uint8_t count = 0;
1230     Send(hSession->sessionId, hChannel->channelId, CMD_KERNEL_CHANNEL_CLOSE, &count, 1);
1231     WRITE_LOG(LOG_DEBUG, "Childchannel begin close, cid:%u, sid:%u", hChannel->channelId, hSession->sessionId);
1232     if (uv_is_closing((const uv_handle_t *)&hChannel->hChildWorkTCP)) {
1233         Base::DoNextLoop(&hSession->childLoop, hChannel, [](const uint8_t flag, string &msg, const void *data) {
1234             HChannel hChannel = (HChannel)data;
1235             hChannel->childCleared = true;
1236             WRITE_LOG(LOG_DEBUG, "Childchannel free direct, cid:%u", hChannel->channelId);
1237         });
1238     } else {
1239         if (hChannel->hChildWorkTCP.loop == NULL) {
1240             WRITE_LOG(LOG_DEBUG, "Childchannel loop is null, cid:%u", hChannel->channelId);
1241         }
1242         Base::TryCloseHandle((uv_handle_t *)&hChannel->hChildWorkTCP, [](uv_handle_t *handle) -> void {
1243             HChannel hChannel = (HChannel)handle->data;
1244             hChannel->childCleared = true;
1245             WRITE_LOG(LOG_DEBUG, "Childchannel free callback, cid:%u", hChannel->channelId);
1246         });
1247     }
1248 };
1249 
ServerCommand(const uint32_t sessionId,const uint32_t channelId,const uint16_t command,uint8_t * bufPtr,const int size)1250 bool HdcServer::ServerCommand(const uint32_t sessionId, const uint32_t channelId, const uint16_t command,
1251                               uint8_t *bufPtr, const int size)
1252 {
1253     HdcServerForClient *hSfc = static_cast<HdcServerForClient *>(clsServerForClient);
1254     HChannel hChannel = hSfc->AdminChannel(OP_QUERY, channelId, nullptr);
1255     HSession hSession = AdminSession(OP_QUERY, sessionId, nullptr);
1256     if (!hChannel || !hSession) {
1257         return false;
1258     }
1259     return FetchCommand(hSession, channelId, command, bufPtr, size);
1260 }
1261 
1262 // clang-format off
RedirectToTask(HTaskInfo hTaskInfo,HSession hSession,const uint32_t channelId,const uint16_t command,uint8_t * payload,const int payloadSize)1263 bool HdcServer::RedirectToTask(HTaskInfo hTaskInfo, HSession hSession, const uint32_t channelId,
1264                                const uint16_t command, uint8_t *payload, const int payloadSize)
1265 // clang-format on
1266 {
1267     bool ret = true;
1268     hTaskInfo->ownerSessionClass = this;
1269     switch (command) {
1270         case CMD_UNITY_BUGREPORT_INIT:
1271         case CMD_UNITY_BUGREPORT_DATA:
1272             ret = TaskCommandDispatch<HdcHostUnity>(hTaskInfo, TYPE_UNITY, command, payload, payloadSize);
1273             break;
1274         case CMD_FILE_INIT:
1275         case CMD_FILE_BEGIN:
1276         case CMD_FILE_CHECK:
1277         case CMD_FILE_DATA:
1278         case CMD_FILE_FINISH:
1279         case CMD_FILE_MODE:
1280         case CMD_DIR_MODE:
1281             ret = TaskCommandDispatch<HdcFile>(hTaskInfo, TASK_FILE, command, payload, payloadSize);
1282             break;
1283         case CMD_FORWARD_INIT:
1284         case CMD_FORWARD_CHECK:
1285         case CMD_FORWARD_CHECK_RESULT:
1286         case CMD_FORWARD_ACTIVE_MASTER:
1287         case CMD_FORWARD_ACTIVE_SLAVE:
1288         case CMD_FORWARD_DATA:
1289         case CMD_FORWARD_FREE_CONTEXT:
1290             ret = TaskCommandDispatch<HdcHostForward>(hTaskInfo, TASK_FORWARD, command, payload, payloadSize);
1291             break;
1292         case CMD_APP_INIT:
1293         case CMD_APP_SIDELOAD:
1294         case CMD_APP_BEGIN:
1295         case CMD_APP_FINISH:
1296         case CMD_APP_UNINSTALL:
1297             ret = TaskCommandDispatch<HdcHostApp>(hTaskInfo, TASK_APP, command, payload, payloadSize);
1298             break;
1299         case CMD_FLASHD_UPDATE_INIT:
1300         case CMD_FLASHD_FLASH_INIT:
1301         case CMD_FLASHD_CHECK:
1302         case CMD_FLASHD_BEGIN:
1303         case CMD_FLASHD_DATA:
1304         case CMD_FLASHD_FINISH:
1305         case CMD_FLASHD_ERASE:
1306         case CMD_FLASHD_FORMAT:
1307         case CMD_FLASHD_PROGRESS:
1308             ret = TaskCommandDispatch<HostUpdater>(hTaskInfo, TASK_FLASHD, command, payload, payloadSize);
1309             break;
1310         default:
1311             // ignore unknown command
1312             break;
1313     }
1314     return ret;
1315 }
1316 
RemoveInstanceTask(const uint8_t op,HTaskInfo hTask)1317 bool HdcServer::RemoveInstanceTask(const uint8_t op, HTaskInfo hTask)
1318 {
1319     bool ret = true;
1320     switch (hTask->taskType) {
1321         case TYPE_SHELL:
1322             WRITE_LOG(LOG_DEBUG, "Server not enable unity/shell");
1323             break;
1324         case TYPE_UNITY:
1325             ret = DoTaskRemove<HdcHostUnity>(hTask, op);
1326             break;
1327         case TASK_FILE:
1328             ret = DoTaskRemove<HdcFile>(hTask, op);
1329             break;
1330         case TASK_FORWARD:
1331             ret = DoTaskRemove<HdcHostForward>(hTask, op);
1332             break;
1333         case TASK_APP:
1334             ret = DoTaskRemove<HdcHostApp>(hTask, op);
1335             break;
1336         case TASK_FLASHD:
1337             ret = DoTaskRemove<HostUpdater>(hTask, op);
1338             break;
1339         default:
1340             ret = false;
1341             break;
1342     }
1343     return ret;
1344 }
1345 
EchoToClientsForSession(uint32_t targetSessionId,const string & echo)1346 void HdcServer::EchoToClientsForSession(uint32_t targetSessionId, const string &echo)
1347 {
1348     HdcServerForClient *hSfc = static_cast<HdcServerForClient *>(clsServerForClient);
1349     WRITE_LOG(LOG_INFO, "%s:%u %s", __FUNCTION__, targetSessionId, echo.c_str());
1350     hSfc->EchoToAllChannelsViaSessionId(targetSessionId, echo);
1351 }
1352 
PrintCmdLogEx(const string & cmdStr)1353 void HdcServer::PrintCmdLogEx(const string& cmdStr)
1354 {
1355     if (cmdStr.empty()) {
1356         return;
1357     }
1358     Hdc::ServerCmdLog::GetInstance().PushCmdLogStr(cmdStr);
1359 }
1360 
1361 #ifdef HOST_OHOS
SessionSoftReset()1362 void HdcServer::SessionSoftReset()
1363 {
1364     uv_rwlock_rdlock(&daemonAdmin);
1365     map<string, HDaemonInfo>::iterator iter;
1366     for (iter = mapDaemon.begin(); iter != mapDaemon.end(); ++iter) {
1367         HDaemonInfo di = iter->second;
1368         if (di == nullptr) {
1369             continue;
1370         }
1371         string devname = di->devName;
1372         if (devname.empty()) {
1373             continue;
1374         }
1375         if (di->connType == CONN_USB) {
1376             HSession hSession = di->hSession;
1377             if (hSession == nullptr) {
1378                 continue;
1379             }
1380             clsUSBClt->SendSoftResetToDaemon(hSession, 0);
1381         }
1382     }
1383     uv_rwlock_rdunlock(&daemonAdmin);
1384 }
1385 #endif
1386 }  // namespace Hdc
1387