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