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