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