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