• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "session.h"
16 #ifndef TEST_HASH
17 #include "hdc_hash_gen.h"
18 #endif
19 #include "serial_struct.h"
20 
21 namespace Hdc {
HdcSessionBase(bool serverOrDaemonIn,size_t uvThreadSize)22 HdcSessionBase::HdcSessionBase(bool serverOrDaemonIn, size_t uvThreadSize) : loopMainStatus(&loopMain, "MainLoop")
23 {
24     // print version pid
25     WRITE_LOG(LOG_INFO, "Program running. %s Pid:%u", Base::GetVersion().c_str(), getpid());
26     // server/daemon common initialization code
27     if (uvThreadSize < SIZE_THREAD_POOL_MIN) {
28         uvThreadSize = SIZE_THREAD_POOL_MIN;
29     } else if (uvThreadSize > SIZE_THREAD_POOL_MAX) {
30         uvThreadSize = SIZE_THREAD_POOL_MAX;
31     }
32     threadPoolCount = uvThreadSize;
33     WRITE_LOG(LOG_INFO, "set UV_THREADPOOL_SIZE:%zu", threadPoolCount);
34     string uvThreadEnv("UV_THREADPOOL_SIZE");
35     string uvThreadVal = std::to_string(threadPoolCount);
36 #ifdef _WIN32
37     uvThreadEnv += "=";
38     uvThreadEnv += uvThreadVal;
39     _putenv(uvThreadEnv.c_str());
40 #else
41     setenv(uvThreadEnv.c_str(), uvThreadVal.c_str(), 1);
42 #endif
43     uv_loop_init(&loopMain);
44     WRITE_LOG(LOG_DEBUG, "loopMain init");
45     uv_rwlock_init(&mainAsync);
46 #ifndef FUZZ_TEST
47     loopMainStatus.StartReportTimer();
48     uv_async_init(&loopMain, &asyncMainLoop, MainAsyncCallback);
49 #endif
50     uv_rwlock_init(&lockMapSession);
51     serverOrDaemon = serverOrDaemonIn;
52     ctxUSB = nullptr;
53     wantRestart = false;
54     threadSessionMain = uv_thread_self();
55 
56 #ifdef HDC_HOST
57     if (serverOrDaemon) {
58         if (libusb_init((libusb_context **)&ctxUSB) != 0) {
59             ctxUSB = nullptr;
60             WRITE_LOG(LOG_FATAL, "libusb_init failed ctxUSB is nullptr");
61         }
62     }
63 #endif
64 }
65 
~HdcSessionBase()66 HdcSessionBase::~HdcSessionBase()
67 {
68 #ifndef FUZZ_TEST
69     Base::TryCloseHandle((uv_handle_t *)&asyncMainLoop);
70 #endif
71     uv_loop_close(&loopMain);
72     // clear base
73     uv_rwlock_destroy(&mainAsync);
74     uv_rwlock_destroy(&lockMapSession);
75 #ifdef HDC_HOST
76     if (serverOrDaemon and ctxUSB != nullptr) {
77         libusb_exit((libusb_context *)ctxUSB);
78     }
79 #endif
80     WRITE_LOG(LOG_WARN, "~HdcSessionBase free sessionRef:%u instance:%s", uint32_t(sessionRef),
81               serverOrDaemon ? "server" : "daemon");
82 }
83 
84 // remove step2
TryRemoveTask(HTaskInfo hTask)85 bool HdcSessionBase::TryRemoveTask(HTaskInfo hTask)
86 {
87     if (hTask->taskFree) {
88         WRITE_LOG(LOG_WARN, "TryRemoveTask channelId:%u", hTask->channelId);
89         return true;
90     }
91     bool ret = RemoveInstanceTask(OP_REMOVE, hTask);
92     if (ret) {
93         hTask->taskFree = true;
94     } else {
95         // This is used to check that the memory cannot be cleaned up. If the memory cannot be released, break point
96         // here to see which task has not been released
97         // print task clear
98     }
99     return ret;
100 }
101 
102 // remove step1
BeginRemoveTask(HTaskInfo hTask)103 void HdcSessionBase::BeginRemoveTask(HTaskInfo hTask)
104 {
105     StartTraceScope("HdcSessionBase::BeginRemoveTask");
106     if (hTask->taskStop || hTask->taskFree) {
107         WRITE_LOG(LOG_WARN, "BeginRemoveTask channelId:%u taskStop:%d taskFree:%d",
108             hTask->channelId, hTask->taskStop, hTask->taskFree);
109         return;
110     }
111 
112     WRITE_LOG(LOG_WARN, "BeginRemoveTask taskType:%d channelId:%u", hTask->taskType, hTask->channelId);
113     auto taskClassDeleteRetry = [](uv_timer_t *handle) -> void {
114         StartTraceScope("HdcSessionBase::BeginRemoveTask taskClassDeleteRetry");
115         HTaskInfo hTask = (HTaskInfo)handle->data;
116         HdcSessionBase *thisClass = (HdcSessionBase *)hTask->ownerSessionClass;
117         if (hTask->isCleared == false) {
118             hTask->isCleared = true;
119             WRITE_LOG(LOG_WARN, "taskClassDeleteRetry start clear task, taskType:%d cid:%u sid:%u",
120                 hTask->taskType, hTask->channelId, hTask->sessionId);
121             bool ret = thisClass->RemoveInstanceTask(OP_CLEAR, hTask);
122             if (!ret) {
123                 WRITE_LOG(LOG_WARN, "taskClassDeleteRetry RemoveInstanceTask return false taskType:%d cid:%u sid:%u",
124                     hTask->taskType, hTask->channelId, hTask->sessionId);
125             }
126         }
127 
128         constexpr uint32_t count = 1000;
129         if (hTask->closeRetryCount == 0 || hTask->closeRetryCount > count) {
130             WRITE_LOG(LOG_DEBUG, "TaskDelay task remove retry count %d/%d, taskType:%d channelId:%u, sessionId:%u",
131                 hTask->closeRetryCount, GLOBAL_TIMEOUT, hTask->taskType, hTask->channelId, hTask->sessionId);
132             hTask->closeRetryCount = 1;
133         }
134         hTask->closeRetryCount++;
135         if (!thisClass->TryRemoveTask(hTask)) {
136             WRITE_LOG(LOG_WARN, "TaskDelay TryRemoveTask false channelId:%u", hTask->channelId);
137             return;
138         }
139         WRITE_LOG(LOG_WARN, "TaskDelay task remove finish, channelId:%u", hTask->channelId);
140         if (hTask != nullptr) {
141             delete hTask;
142             hTask = nullptr;
143         }
144         thisClass->taskCount--;
145         Base::TryCloseHandle((uv_handle_t *)handle, Base::CloseTimerCallback);
146     };
147     Base::TimerUvTask(hTask->runLoop, hTask, taskClassDeleteRetry, (GLOBAL_TIMEOUT * TIME_BASE) / UV_DEFAULT_INTERVAL);
148 
149     hTask->taskStop = true;
150 }
151 
152 // Clear all Task or a single Task, the regular situation is stopped first, and the specific class memory is cleaned up
153 // after the end of the LOOP.
154 // When ChannelIdinput == 0, at this time, all of the LOOP ends, all runs in the class end, so directly skip STOP,
155 // physical memory deletion class trimming
ClearOwnTasks(HSession hSession,const uint32_t channelIDInput)156 void HdcSessionBase::ClearOwnTasks(HSession hSession, const uint32_t channelIDInput)
157 {
158     // First case: normal task cleanup process (STOP Remove)
159     // Second: The task is cleaned up, the session ends
160     // Third: The task is cleaned up, and the session is directly over the session.
161     StartTraceScope("HdcSessionBase::ClearOwnTasks");
162     hSession->mapTaskMutex.lock();
163     map<uint32_t, HTaskInfo>::iterator iter;
164     taskCount = hSession->mapTask->size();
165     for (iter = hSession->mapTask->begin(); iter != hSession->mapTask->end();) {
166         uint32_t channelId = iter->first;
167         HTaskInfo hTask = iter->second;
168         if (channelIDInput != 0) {  // single
169             if (channelIDInput != channelId) {
170                 ++iter;
171                 continue;
172             }
173             BeginRemoveTask(hTask);
174             WRITE_LOG(LOG_WARN, "ClearOwnTasks OP_CLEAR finish, sessionId:%u channelIDInput:%u",
175                 hSession->sessionId, channelIDInput);
176             iter = hSession->mapTask->erase(iter);
177             break;
178         }
179         // multi
180         BeginRemoveTask(hTask);
181         iter = hSession->mapTask->erase(iter);
182     }
183     hSession->mapTaskMutex.unlock();
184 }
185 
ClearSessions()186 void HdcSessionBase::ClearSessions()
187 {
188     // no need to lock mapSession
189     // broadcast free signal
190     for (auto v : mapSession) {
191         HSession hSession = (HSession)v.second;
192         if (!hSession->isDead) {
193             FreeSession(hSession->sessionId);
194         }
195     }
196 }
197 
ReMainLoopForInstanceClear()198 void HdcSessionBase::ReMainLoopForInstanceClear()
199 {  // reloop
200     StartTraceScope("HdcSessionBase::ReMainLoopForInstanceClear");
201     auto clearSessionsForFinish = [](uv_idle_t *handle) -> void {
202         HdcSessionBase *thisClass = (HdcSessionBase *)handle->data;
203         if (thisClass->sessionRef > 0) {
204             return;
205         }
206         // all task has been free
207         uv_close((uv_handle_t *)handle, Base::CloseIdleCallback);
208         uv_stop(&thisClass->loopMain);
209     };
210     Base::IdleUvTask(&loopMain, this, clearSessionsForFinish);
211     uv_run(&loopMain, UV_RUN_DEFAULT);
212 };
213 
214 #ifdef HDC_SUPPORT_UART
EnumUARTDeviceRegister(UartKickoutZombie kickOut)215 void HdcSessionBase::EnumUARTDeviceRegister(UartKickoutZombie kickOut)
216 {
217     uv_rwlock_rdlock(&lockMapSession);
218     map<uint32_t, HSession>::iterator i;
219     for (i = mapSession.begin(); i != mapSession.end(); ++i) {
220         HSession hs = i->second;
221         if ((hs->connType != CONN_SERIAL) or (hs->hUART == nullptr)) {
222             continue;
223         }
224         kickOut(hs);
225         break;
226     }
227     uv_rwlock_rdunlock(&lockMapSession);
228 }
229 #endif
230 
EnumUSBDeviceRegister(void (* pCallBack)(HSession hSession))231 void HdcSessionBase::EnumUSBDeviceRegister(void (*pCallBack)(HSession hSession))
232 {
233     if (!pCallBack) {
234         return;
235     }
236     uv_rwlock_rdlock(&lockMapSession);
237     map<uint32_t, HSession>::iterator i;
238     for (i = mapSession.begin(); i != mapSession.end(); ++i) {
239         HSession hs = i->second;
240         if (hs->connType != CONN_USB) {
241             continue;
242         }
243         if (hs->hUSB == nullptr) {
244             continue;
245         }
246         if (pCallBack) {
247             pCallBack(hs);
248         }
249         break;
250     }
251     uv_rwlock_rdunlock(&lockMapSession);
252 }
253 
254 // The PC side gives the device information, determines if the USB device is registered
255 // PDEV and Busid Devid two choices
QueryUSBDeviceRegister(void * pDev,uint8_t busIDIn,uint8_t devIDIn)256 HSession HdcSessionBase::QueryUSBDeviceRegister(void *pDev, uint8_t busIDIn, uint8_t devIDIn)
257 {
258 #ifdef HDC_HOST
259     libusb_device *dev = (libusb_device *)pDev;
260     HSession hResult = nullptr;
261     if (!mapSession.size()) {
262         return nullptr;
263     }
264     uint8_t busId = 0;
265     uint8_t devId = 0;
266     if (pDev) {
267         busId = libusb_get_bus_number(dev);
268         devId = libusb_get_device_address(dev);
269     } else {
270         busId = busIDIn;
271         devId = devIDIn;
272     }
273     uv_rwlock_rdlock(&lockMapSession);
274     map<uint32_t, HSession>::iterator i;
275     for (i = mapSession.begin(); i != mapSession.end(); ++i) {
276         HSession hs = i->second;
277         if (hs->connType == CONN_USB) {
278             continue;
279         }
280         if (hs->hUSB == nullptr) {
281             continue;
282         }
283         if (hs->hUSB->devId != devId || hs->hUSB->busId != busId) {
284             continue;
285         }
286         hResult = hs;
287         break;
288     }
289     uv_rwlock_rdunlock(&lockMapSession);
290     return hResult;
291 #else
292     return nullptr;
293 #endif
294 }
295 
AsyncMainLoopTask(uv_idle_t * handle)296 void HdcSessionBase::AsyncMainLoopTask(uv_idle_t *handle)
297 {
298     AsyncParam *param = (AsyncParam *)handle->data;
299     HdcSessionBase *thisClass = (HdcSessionBase *)param->thisClass;
300     CALLSTAT_GUARD(thisClass->loopMainStatus, handle->loop, "HdcSessionBase::AsyncMainLoopTask");
301     switch (param->method) {
302         case ASYNC_FREE_SESSION:
303             // Destruction is unified in the main thread
304             thisClass->FreeSession(param->sid);
305             break;
306         case ASYNC_STOP_MAINLOOP:
307             uv_stop(&thisClass->loopMain);
308             break;
309         default:
310             break;
311     }
312     if (param->data) {
313         delete[]((uint8_t *)param->data);
314     }
315     delete param;
316     param = nullptr;
317     Base::TryCloseHandle((uv_handle_t *)handle, Base::CloseIdleCallback);
318 }
319 
MainAsyncCallback(uv_async_t * handle)320 void HdcSessionBase::MainAsyncCallback(uv_async_t *handle)
321 {
322     HdcSessionBase *thisClass = (HdcSessionBase *)handle->data;
323     CALLSTAT_GUARD(thisClass->loopMainStatus, handle->loop, "HdcSessionBase::MainAsyncCallback");
324     list<void *>::iterator i;
325     list<void *> &lst = thisClass->lstMainThreadOP;
326     uv_rwlock_wrlock(&thisClass->mainAsync);
327     for (i = lst.begin(); i != lst.end();) {
328         AsyncParam *param = (AsyncParam *)*i;
329         Base::IdleUvTask(&thisClass->loopMain, param, AsyncMainLoopTask);
330         i = lst.erase(i);
331     }
332     uv_rwlock_wrunlock(&thisClass->mainAsync);
333 }
334 
PushAsyncMessage(const uint32_t sessionId,const uint8_t method,const void * data,const int dataSize)335 void HdcSessionBase::PushAsyncMessage(const uint32_t sessionId, const uint8_t method, const void *data,
336                                       const int dataSize)
337 {
338     AsyncParam *param = new AsyncParam();
339     if (!param) {
340         return;
341     }
342     param->sid = sessionId;
343     param->thisClass = this;
344     param->method = method;
345     if (dataSize > 0) {
346         param->dataSize = dataSize;
347         param->data = new uint8_t[param->dataSize]();
348         if (!param->data) {
349             delete param;
350             return;
351         }
352         if (memcpy_s((uint8_t *)param->data, param->dataSize, data, dataSize)) {
353             delete[]((uint8_t *)param->data);
354             delete param;
355             return;
356         }
357     }
358 
359     asyncMainLoop.data = this;
360     uv_rwlock_wrlock(&mainAsync);
361     lstMainThreadOP.push_back(param);
362     uv_rwlock_wrunlock(&mainAsync);
363     uv_async_send(&asyncMainLoop);
364 }
365 
WorkerPendding()366 void HdcSessionBase::WorkerPendding()
367 {
368     StartLoopMonitor();
369     uv_run(&loopMain, UV_RUN_DEFAULT);
370     ClearInstanceResource();
371 }
372 
MallocSessionByConnectType(HSession hSession)373 int HdcSessionBase::MallocSessionByConnectType(HSession hSession)
374 {
375     int ret = 0;
376     switch (hSession->connType) {
377         case CONN_TCP: {
378             uv_tcp_init(&loopMain, &hSession->hWorkTCP);
379             WRITE_LOG(LOG_INFO, "MallocSessionByConnectType init hWorkTCP sid:%u", hSession->sessionId);
380             ++hSession->uvHandleRef;
381             hSession->hWorkTCP.data = hSession;
382             break;
383         }
384         case CONN_USB: {
385             // Some members need to be placed at the primary thread
386             HUSB hUSB = new HdcUSB();
387             if (!hUSB) {
388                 ret = -1;
389                 break;
390             }
391             hSession->hUSB = hUSB;
392             hSession->hUSB->wMaxPacketSizeSend = MAX_PACKET_SIZE_HISPEED;
393             break;
394         }
395 #ifdef HDC_SUPPORT_UART
396         case CONN_SERIAL: {
397             HUART hUART = new HdcUART();
398             if (!hUART) {
399                 ret = -1;
400                 break;
401             }
402             hSession->hUART = hUART;
403             break;
404         }
405 #endif // HDC_SUPPORT_UART
406         default:
407             ret = -1;
408             break;
409     }
410     return ret;
411 }
412 
413 // Avoid unit test when client\server\daemon on the same host, maybe get the same ID value
GetSessionPseudoUid()414 uint32_t HdcSessionBase::GetSessionPseudoUid()
415 {
416     uint32_t uid = 0;
417     do {
418         uid = Base::GetSecureRandom();
419     } while (AdminSession(OP_QUERY, uid, nullptr) != nullptr);
420     return uid;
421 }
422 
423 // when client 0 to automatic generated,when daemon First place 1 followed by
MallocSession(bool serverOrDaemon,const ConnType connType,void * classModule,uint32_t sessionId)424 HSession HdcSessionBase::MallocSession(bool serverOrDaemon, const ConnType connType, void *classModule,
425                                        uint32_t sessionId)
426 {
427 #ifdef CONFIG_USE_JEMALLOC_DFX_INIF
428     mallopt(M_DELAYED_FREE, M_DELAYED_FREE_DISABLE);
429     mallopt(M_SET_THREAD_CACHE, M_THREAD_CACHE_DISABLE);
430 #endif
431     HSession hSession = new(std::nothrow) HdcSession();
432     if (!hSession) {
433         WRITE_LOG(LOG_FATAL, "MallocSession new hSession failed");
434         return nullptr;
435     }
436     int ret = 0;
437     ++sessionRef;
438     hSession->classInstance = this;
439     hSession->connType = connType;
440     hSession->classModule = classModule;
441     hSession->isDead = false;
442     hSession->sessionId = ((sessionId == 0) ? GetSessionPseudoUid() : sessionId);
443     hSession->serverOrDaemon = serverOrDaemon;
444     hSession->hWorkThread = uv_thread_self();
445     hSession->mapTask = new(std::nothrow) map<uint32_t, HTaskInfo>();
446     if (hSession->mapTask == nullptr) {
447         WRITE_LOG(LOG_FATAL, "MallocSession new hSession->mapTask failed");
448         delete hSession;
449         hSession = nullptr;
450         return nullptr;
451     }
452     hSession->listKey = new(std::nothrow) list<void *>;
453     if (hSession->listKey == nullptr) {
454         WRITE_LOG(LOG_FATAL, "MallocSession new hSession->listKey failed");
455         delete hSession;
456         hSession = nullptr;
457         return nullptr;
458     }
459     uv_loop_init(&hSession->childLoop);
460     hSession->childLoopStatus.StartReportTimer();
461     hSession->uvHandleRef = 0;
462     // pullup child
463     WRITE_LOG(LOG_INFO, "HdcSessionBase NewSession, sessionId:%u, connType:%d.",
464               hSession->sessionId, hSession->connType);
465     ++hSession->uvHandleRef;
466     Base::CreateSocketPair(hSession->ctrlFd);
467     size_t handleSize = sizeof(uv_poll_t);
468     hSession->pollHandle[STREAM_WORK] = (uv_poll_t *)malloc(handleSize);
469     hSession->pollHandle[STREAM_MAIN] = (uv_poll_t *)malloc(handleSize);
470     uv_poll_t *pollHandleMain = hSession->pollHandle[STREAM_MAIN];
471     if (pollHandleMain == nullptr || hSession->pollHandle[STREAM_WORK] == nullptr) {
472         WRITE_LOG(LOG_FATAL, "MallocSession malloc hSession->pollHandle failed");
473         delete hSession;
474         hSession = nullptr;
475         return nullptr;
476     }
477     (void)memset_s(hSession->pollHandle[STREAM_WORK], handleSize, 0, handleSize);
478     (void)memset_s(hSession->pollHandle[STREAM_MAIN], handleSize, 0, handleSize);
479     int initResult = uv_poll_init_socket(&loopMain, pollHandleMain, hSession->ctrlFd[STREAM_MAIN]);
480     if (initResult != 0) {
481         WRITE_LOG(LOG_FATAL, "MallocSession init pollHandleMain->loop failed");
482         _exit(0);
483     }
484     uv_poll_start(pollHandleMain, UV_READABLE, ReadCtrlFromSession);
485     hSession->pollHandle[STREAM_MAIN]->data = hSession;
486     hSession->pollHandle[STREAM_WORK]->data = hSession;
487     // Activate USB DAEMON's data channel, may not for use
488     uv_tcp_init(&loopMain, &hSession->dataPipe[STREAM_MAIN]);
489     (void)memset_s(&hSession->dataPipe[STREAM_WORK], sizeof(hSession->dataPipe[STREAM_WORK]),
490                    0, sizeof(uv_tcp_t));
491     ++hSession->uvHandleRef;
492     int createResult = Base::CreateSocketPair(hSession->dataFd);
493     if (createResult < 0) {
494         WRITE_LOG(LOG_FATAL, "MallocSession init dataFd failed");
495         _exit(0);
496     }
497     uv_tcp_open(&hSession->dataPipe[STREAM_MAIN], hSession->dataFd[STREAM_MAIN]);
498     hSession->dataPipe[STREAM_MAIN].data = hSession;
499     hSession->dataPipe[STREAM_WORK].data = hSession;
500 #ifdef HDC_HOST
501     Base::SetTcpOptions(&hSession->dataPipe[STREAM_MAIN], HOST_SOCKETPAIR_SIZE);
502 #else
503     Base::SetTcpOptions(&hSession->dataPipe[STREAM_MAIN]);
504 #endif
505     ret = MallocSessionByConnectType(hSession);
506     if (ret) {
507         delete hSession;
508         hSession = nullptr;
509     } else {
510         AdminSession(OP_ADD, hSession->sessionId, hSession);
511     }
512     return hSession;
513 }
514 
515 #ifdef HDC_HOST
PrintAllSessionConnection(const uint32_t sessionId)516 void HdcSessionBase::PrintAllSessionConnection(const uint32_t sessionId)
517 {
518     AdminSession(OP_PRINT, sessionId, nullptr);
519 }
520 #endif
521 
FreeSessionByConnectType(HSession hSession)522 void HdcSessionBase::FreeSessionByConnectType(HSession hSession)
523 {
524     WRITE_LOG(LOG_INFO, "FreeSessionByConnectType %s", hSession->ToDebugString().c_str());
525 
526     if (hSession->connType == CONN_USB) {
527         // ibusb All context is applied for sub-threaded, so it needs to be destroyed in the subline
528         if (!hSession->hUSB) {
529             return;
530         }
531         HUSB hUSB = hSession->hUSB;
532         if (!hUSB) {
533             return;
534         }
535 #ifdef HDC_HOST
536         if (hUSB->devHandle) {
537             libusb_release_interface(hUSB->devHandle, hUSB->interfaceNumber);
538             libusb_close(hUSB->devHandle);
539             hUSB->devHandle = nullptr;
540         }
541 #else
542         Base::CloseFd(hUSB->bulkIn);
543         Base::CloseFd(hUSB->bulkOut);
544 #endif
545         delete hSession->hUSB;
546         hSession->hUSB = nullptr;
547     }
548 #ifdef HDC_SUPPORT_UART
549     if (CONN_SERIAL == hSession->connType) {
550         if (!hSession->hUART) {
551             return;
552         }
553         HUART hUART = hSession->hUART;
554         if (!hUART) {
555             return;
556         }
557         HdcUARTBase *uartBase = (HdcUARTBase *)hSession->classModule;
558         // tell uart session will be free
559         uartBase->StopSession(hSession);
560 #ifdef HDC_HOST
561 #ifdef HOST_MINGW
562         if (hUART->devUartHandle != INVALID_HANDLE_VALUE) {
563             CloseHandle(hUART->devUartHandle);
564             hUART->devUartHandle = INVALID_HANDLE_VALUE;
565         }
566 #elif defined(HOST_LINUX)
567         Base::CloseFd(hUART->devUartHandle);
568 #endif // _WIN32
569 #endif
570         delete hSession->hUART;
571         hSession->hUART = nullptr;
572     }
573 #endif
574 }
575 
576 // work when libuv-handle at struct of HdcSession has all callback finished
FreeSessionFinally(uv_idle_t * handle)577 void HdcSessionBase::FreeSessionFinally(uv_idle_t *handle)
578 {
579     HSession hSession = (HSession)handle->data;
580     HdcSessionBase *thisClass = (HdcSessionBase *)hSession->classInstance;
581     if (hSession->uvHandleRef > 0) {
582         WRITE_LOG(LOG_INFO, "FreeSessionFinally uvHandleRef:%d sessionId:%u",
583             hSession->uvHandleRef, hSession->sessionId);
584         return;
585     }
586     // Notify Server or Daemon, just UI or display commandline
587     thisClass->NotifyInstanceSessionFree(hSession, true);
588 #ifdef HDC_HOST
589     thisClass->AdminSession(OP_PRINT, hSession->sessionId, nullptr);
590 #endif
591 #ifdef HDC_SUPPORT_ENCRYPT_TCP
592     if (hSession->classSSL != nullptr) {
593         HdcSSLBase *hssl = static_cast<HdcSSLBase *>(hSession->classSSL);
594         delete hssl;
595         hSession->classSSL = nullptr;
596     }
597 #endif
598     // all hsession uv handle has been clear
599     thisClass->AdminSession(OP_REMOVE, hSession->sessionId, nullptr);
600     WRITE_LOG(LOG_INFO, "!!!FreeSessionFinally sessionId:%u finish", hSession->sessionId);
601     HdcAuth::FreeKey(!hSession->serverOrDaemon, hSession->listKey);
602     delete hSession;
603     hSession = nullptr;  // fix CodeMars SetNullAfterFree issue
604     Base::TryCloseHandle((const uv_handle_t *)handle, Base::CloseIdleCallback);
605     --thisClass->sessionRef;
606 }
607 
608 // work when child-work thread finish
FreeSessionContinue(HSession hSession)609 void HdcSessionBase::FreeSessionContinue(HSession hSession)
610 {
611     auto closeSessionTCPHandle = [](uv_handle_t *handle) -> void {
612         HSession hSession = (HSession)handle->data;
613         --hSession->uvHandleRef;
614         Base::TryCloseHandle((uv_handle_t *)handle);
615         if (handle == reinterpret_cast<uv_handle_t *>(hSession->pollHandle[STREAM_MAIN])) {
616             WRITE_LOG(LOG_INFO, "closeSessionTCPHandle CloseSocketPair ctrlFd, sid:%u", hSession->sessionId);
617             Base::CloseSocketPair(hSession->ctrlFd);
618             free(hSession->pollHandle[STREAM_MAIN]);
619         }
620     };
621     if (hSession->connType == CONN_TCP) {
622         // Turn off TCP to prevent continuing writing
623         WRITE_LOG(LOG_INFO, "FreeSessionContinue start close hWorkTCP, sid:%u", hSession->sessionId);
624         Base::TryCloseHandle((uv_handle_t *)&hSession->hWorkTCP, true, closeSessionTCPHandle);
625 #ifdef _WIN32
626         closesocket(hSession->dataFd[STREAM_WORK]);
627 #else
628         Base::CloseFd(hSession->dataFd[STREAM_WORK]);
629 #endif
630     }
631     hSession->availTailIndex = 0;
632     if (hSession->ioBuf) {
633         delete[] hSession->ioBuf;
634         hSession->ioBuf = nullptr;
635     }
636     Base::TryCloseHandle((uv_handle_t *)hSession->pollHandle[STREAM_MAIN], true, closeSessionTCPHandle);
637     Base::TryCloseHandle((uv_handle_t *)&hSession->dataPipe[STREAM_MAIN], true, closeSessionTCPHandle);
638     FreeSessionByConnectType(hSession);
639     // finish
640     Base::IdleUvTask(&loopMain, hSession, FreeSessionFinally);
641 }
642 
FreeSessionOpeate(uv_timer_t * handle)643 void HdcSessionBase::FreeSessionOpeate(uv_timer_t *handle)
644 {
645     StartTraceScope("HdcSessionBase::FreeSessionOpeate");
646     HSession hSession = (HSession)handle->data;
647 #ifdef HDC_HOST
648     if (hSession->hUSB != nullptr
649         && (!hSession->hUSB->hostBulkIn.isShutdown || !hSession->hUSB->hostBulkOut.isShutdown)) {
650         HdcUSBBase *pUSB = ((HdcUSBBase *)hSession->classModule);
651         pUSB->CancelUsbIo(hSession);
652         return;
653     }
654 #endif
655     HdcSessionBase *thisClass = (HdcSessionBase *)hSession->classInstance;
656     if (hSession->ref > 0) {
657         WRITE_LOG(LOG_WARN, "FreeSessionOpeate sid:%u ref:%u > 0", hSession->sessionId, uint32_t(hSession->ref));
658         return;
659     }
660     WRITE_LOG(LOG_INFO, "FreeSessionOpeate sid:%u ref:%u", hSession->sessionId, uint32_t(hSession->ref));
661     // wait workthread to free
662     if (hSession->pollHandle[STREAM_WORK]->loop) {
663         auto ctrl = BuildCtrlString(SP_STOP_SESSION, 0, nullptr, 0);
664         Base::SendToPollFd(hSession->ctrlFd[STREAM_MAIN], ctrl.data(), ctrl.size());
665         WRITE_LOG(LOG_INFO, "FreeSessionOpeate, send workthread for free. sessionId:%u", hSession->sessionId);
666         auto callbackCheckFreeSessionContinue = [](uv_timer_t *handle) -> void {
667             HSession hSession = (HSession)handle->data;
668             HdcSessionBase *thisClass = (HdcSessionBase *)hSession->classInstance;
669             if (!hSession->childCleared) {
670                 WRITE_LOG(LOG_INFO, "FreeSessionOpeate childCleared:%d sessionId:%u",
671                     hSession->childCleared, hSession->sessionId);
672                 return;
673             }
674             Base::TryCloseHandle((uv_handle_t *)handle, Base::CloseTimerCallback);
675             thisClass->FreeSessionContinue(hSession);
676         };
677         Base::TimerUvTask(&thisClass->loopMain, hSession, callbackCheckFreeSessionContinue);
678     } else {
679         thisClass->FreeSessionContinue(hSession);
680     }
681     Base::TryCloseHandle((uv_handle_t *)handle, Base::CloseTimerCallback);
682 }
683 
FreeSession(const uint32_t sessionId)684 void HdcSessionBase::FreeSession(const uint32_t sessionId)
685 {
686     StartTraceScope("HdcSessionBase::FreeSession");
687     DispAllLoopStatus("FreeSession-" + std::to_string(sessionId));
688     Base::AddDeletedSessionId(sessionId);
689     if (threadSessionMain != uv_thread_self()) {
690         PushAsyncMessage(sessionId, ASYNC_FREE_SESSION, nullptr, 0);
691         return;
692     }
693     HSession hSession = AdminSession(OP_QUERY, sessionId, nullptr);
694     WRITE_LOG(LOG_INFO, "Begin to free session, sessionid:%u", sessionId);
695     do {
696         if (!hSession || hSession->isDead) {
697             WRITE_LOG(LOG_WARN, "FreeSession hSession nullptr or isDead sessionId:%u", sessionId);
698             break;
699         }
700         WRITE_LOG(LOG_INFO, "dataFdSend:%llu, dataFdRecv:%llu",
701             uint64_t(hSession->stat.dataSendBytes),
702             uint64_t(hSession->stat.dataRecvBytes));
703         hSession->isDead = true;
704         Base::TimerUvTask(&loopMain, hSession, FreeSessionOpeate);
705         NotifyInstanceSessionFree(hSession, false);
706         WRITE_LOG(LOG_INFO, "FreeSession sessionId:%u ref:%u", hSession->sessionId, uint32_t(hSession->ref));
707     } while (false);
708 }
709 
710 #ifdef HDC_HOST
PrintSession(const uint32_t sessionId)711 void HdcSessionBase::PrintSession(const uint32_t sessionId)
712 {
713     uv_rwlock_rdlock(&lockMapSession);
714     int count = 0;
715     for (auto v : mapSession) {
716         HSession hSession = (HSession)v.second;
717         auto str = hSession->ToDisplayConnectionStr();
718         if (hSession->sessionId == sessionId) {
719             str = str + " (Current)";
720             WRITE_LOG(LOG_INFO, "%s", str.c_str());
721         } else {
722             WRITE_LOG(LOG_DEBUG, "%s", str.c_str());
723         }
724         if (hSession->isRunningOk) {
725             count++;
726         }
727     }
728     WRITE_LOG(LOG_INFO, "alive session count:%d", count);
729     uv_rwlock_rdunlock(&lockMapSession);
730 }
731 #endif
732 
VoteReset(const uint32_t sessionId)733 HSession HdcSessionBase::VoteReset(const uint32_t sessionId)
734 {
735     HSession hRet = nullptr;
736     bool needReset = true;
737     if (serverOrDaemon) {
738         uv_rwlock_wrlock(&lockMapSession);
739         hRet = mapSession[sessionId];
740         hRet->voteReset = true;
741         for (auto &kv : mapSession) {
742             if (sessionId == kv.first) {
743                 continue;
744             }
745             WRITE_LOG(LOG_DEBUG, "session:%u vote reset, session %u is %s",
746                 sessionId, kv.first, kv.second->voteReset ? "YES" : "NO");
747             if (!kv.second->voteReset) {
748                 needReset = false;
749             }
750         }
751         uv_rwlock_wrunlock(&lockMapSession);
752     }
753     if (needReset) {
754         WRITE_LOG(LOG_FATAL, "!! session:%u vote reset, passed unanimously !!", sessionId);
755         abort();
756     }
757     return hRet;
758 }
759 
AdminSession(const uint8_t op,const uint32_t sessionId,HSession hInput)760 HSession HdcSessionBase::AdminSession(const uint8_t op, const uint32_t sessionId, HSession hInput)
761 {
762     StartTraceScope("HdcSessionBase::AdminSession");
763     HSession hRet = nullptr;
764     switch (op) {
765         case OP_ADD:
766             uv_rwlock_wrlock(&lockMapSession);
767             mapSession[sessionId] = hInput;
768             uv_rwlock_wrunlock(&lockMapSession);
769             break;
770         case OP_REMOVE:
771             uv_rwlock_wrlock(&lockMapSession);
772             mapSession.erase(sessionId);
773             uv_rwlock_wrunlock(&lockMapSession);
774             break;
775         case OP_QUERY:
776             uv_rwlock_rdlock(&lockMapSession);
777             if (mapSession.count(sessionId)) {
778                 hRet = mapSession[sessionId];
779             }
780             uv_rwlock_rdunlock(&lockMapSession);
781             break;
782         case OP_PRINT:
783 #ifdef HDC_HOST
784             PrintSession(sessionId);
785 #endif
786             break;
787         case OP_QUERY_REF:
788             uv_rwlock_wrlock(&lockMapSession);
789             if (mapSession.count(sessionId)) {
790                 hRet = mapSession[sessionId];
791                 ++hRet->ref;
792             }
793             uv_rwlock_wrunlock(&lockMapSession);
794             break;
795         case OP_UPDATE:
796             uv_rwlock_wrlock(&lockMapSession);
797             // remove old
798             mapSession.erase(sessionId);
799             mapSession[hInput->sessionId] = hInput;
800             uv_rwlock_wrunlock(&lockMapSession);
801             break;
802         case OP_VOTE_RESET:
803             if (mapSession.count(sessionId) == 0) {
804                 break;
805             }
806             hRet = VoteReset(sessionId);
807             break;
808         default:
809             break;
810     }
811     return hRet;
812 }
813 
DumpTasksInfo(map<uint32_t,HTaskInfo> & mapTask)814 void HdcSessionBase::DumpTasksInfo(map<uint32_t, HTaskInfo> &mapTask)
815 {
816     int idx = 1;
817     for (auto t : mapTask) {
818         HTaskInfo ti = t.second;
819         WRITE_LOG(LOG_WARN, "%d: channelId: %lu, type: %d, closeRetry: %d\n",
820                   idx++, ti->channelId, ti->taskType, ti->closeRetryCount);
821     }
822 }
823 
824 // All in the corresponding sub-thread, no need locks
AdminTask(const uint8_t op,HSession hSession,const uint32_t channelId,HTaskInfo hInput)825 HTaskInfo HdcSessionBase::AdminTask(const uint8_t op, HSession hSession, const uint32_t channelId, HTaskInfo hInput)
826 {
827     HTaskInfo hRet = nullptr;
828     map<uint32_t, HTaskInfo> &mapTask = *hSession->mapTask;
829 
830     switch (op) {
831         case OP_ADD:
832             hRet = mapTask[channelId];
833             if (hRet != nullptr) {
834                 delete hRet;
835             }
836             mapTask[channelId] = hInput;
837             hRet = hInput;
838 
839             WRITE_LOG(LOG_INFO, "AdminTask add task type:%u cid:%u sid:%u mapsize:%zu",
840                       hInput->taskType, channelId, hSession->sessionId, mapTask.size());
841 
842             break;
843         case OP_REMOVE:
844             mapTask.erase(channelId);
845             WRITE_LOG(LOG_INFO, "AdminTask rm cid:%u sid:%u mapsize:%zu",
846                       channelId, hSession->sessionId, mapTask.size());
847             break;
848         case OP_QUERY:
849             if (mapTask.count(channelId)) {
850                 hRet = mapTask[channelId];
851             }
852             break;
853         case OP_VOTE_RESET:
854             AdminSession(op, hSession->sessionId, nullptr);
855             break;
856         default:
857             break;
858     }
859     return hRet;
860 }
861 
SendByProtocol(HSession hSession,uint8_t * bufPtr,const int bufLen,bool echo)862 int HdcSessionBase::SendByProtocol(HSession hSession, uint8_t *bufPtr, const int bufLen, bool echo)
863 {
864     StartTraceScope("HdcSessionBase::SendByProtocol");
865     if (hSession->isDead) {
866         delete[] bufPtr;
867         WRITE_LOG(LOG_WARN, "SendByProtocol session dead error");
868         return ERR_SESSION_NOFOUND;
869     }
870     int ret = 0;
871     switch (hSession->connType) {
872         case CONN_TCP: {
873             HdcTCPBase *pTCP = ((HdcTCPBase *)hSession->classModule);
874             if (echo && !hSession->serverOrDaemon) {
875                 ret = pTCP->WriteUvTcpFd(&hSession->hChildWorkTCP, bufPtr, bufLen);
876             } else {
877                 if (hSession->hWorkThread == uv_thread_self()) {
878                     ret = pTCP->WriteUvTcpFd(&hSession->hWorkTCP, bufPtr, bufLen);
879                 } else {
880                     ret = pTCP->WriteUvTcpFd(&hSession->hChildWorkTCP, bufPtr, bufLen);
881                 }
882             }
883             break;
884         }
885         case CONN_USB: {
886             HdcUSBBase *pUSB = ((HdcUSBBase *)hSession->classModule);
887             ret = pUSB->SendUSBBlock(hSession, bufPtr, bufLen);
888             delete[] bufPtr;
889             break;
890         }
891 #ifdef HDC_SUPPORT_UART
892         case CONN_SERIAL: {
893             HdcUARTBase *pUART = ((HdcUARTBase *)hSession->classModule);
894             ret = pUART->SendUARTData(hSession, bufPtr, bufLen);
895             delete[] bufPtr;
896             break;
897         }
898 #endif
899         default:
900             delete[] bufPtr;
901             break;
902     }
903     return ret;
904 }
905 
Send(const uint32_t sessionId,const uint32_t channelId,const uint16_t commandFlag,const uint8_t * data,const int dataSize)906 int HdcSessionBase::Send(const uint32_t sessionId, const uint32_t channelId, const uint16_t commandFlag,
907                          const uint8_t *data, const int dataSize)
908 {
909     StartTraceScope("HdcSessionBase::Send");
910     HSession hSession = AdminSession(OP_QUERY_REF, sessionId, nullptr);
911     if (!hSession) {
912         WRITE_LOG(LOG_WARN, "Send to offline device, drop it, sessionId:%u", sessionId);
913         return ERR_SESSION_NOFOUND;
914     }
915     PayloadProtect protectBuf;  // noneed convert to big-endian
916     protectBuf.channelId = channelId;
917     protectBuf.commandFlag = commandFlag;
918     protectBuf.checkSum = (ENABLE_IO_CHECKSUM && dataSize > 0) ? Base::CalcCheckSum(data, dataSize) : 0;
919     protectBuf.vCode = payloadProtectStaticVcode;
920     string s = SerialStruct::SerializeToString(protectBuf);
921     // reserve for encrypt here
922     // xx-encrypt
923 
924     PayloadHead payloadHead = {};  // need convert to big-endian
925     payloadHead.flag[0] = PACKET_FLAG.at(0);
926     payloadHead.flag[1] = PACKET_FLAG.at(1);
927     payloadHead.protocolVer = VER_PROTOCOL;
928     payloadHead.headSize = htons(s.size());
929     payloadHead.dataSize = htonl(dataSize);
930     int finalBufSize = sizeof(PayloadHead) + s.size() + dataSize;
931 #ifdef HDC_SUPPORT_ENCRYPT_TCP
932     uint8_t *finayBuf = (hSession->connType == CONN_TCP && hSession->sslHandshake) ?
933         new(std::nothrow) uint8_t[HdcSSLBase::GetSSLBufLen(finalBufSize) + 1]() :
934         new(std::nothrow) uint8_t[finalBufSize]();
935 #else
936     uint8_t *finayBuf = new(std::nothrow) uint8_t[finalBufSize]();
937 #endif
938     if (finayBuf == nullptr) {
939         WRITE_LOG(LOG_WARN, "send allocmem err");
940         --hSession->ref;
941         return ERR_BUF_ALLOC;
942     }
943     bool bufRet = false;
944     do {
945         if (memcpy_s(finayBuf, sizeof(PayloadHead), reinterpret_cast<uint8_t *>(&payloadHead), sizeof(PayloadHead))) {
946             WRITE_LOG(LOG_WARN, "send copyhead err for dataSize:%d", dataSize);
947             break;
948         }
949         if (memcpy_s(finayBuf + sizeof(PayloadHead), s.size(),
950                      reinterpret_cast<uint8_t *>(const_cast<char *>(s.c_str())), s.size())) {
951             WRITE_LOG(LOG_WARN, "send copyProtbuf err for dataSize:%d", dataSize);
952             break;
953         }
954         if (dataSize > 0 && memcpy_s(finayBuf + sizeof(PayloadHead) + s.size(), dataSize, data, dataSize)) {
955             WRITE_LOG(LOG_WARN, "send copyDatabuf err for dataSize:%d", dataSize);
956             break;
957         }
958         bufRet = true;
959     } while (false);
960     if (!bufRet) {
961         delete[] finayBuf;
962         WRITE_LOG(LOG_WARN, "send copywholedata err for dataSize:%d", dataSize);
963         --hSession->ref;
964         return ERR_BUF_COPY;
965     }
966     int ret = -1;
967     if (CMD_KERNEL_ECHO == commandFlag) {
968         ret = SendByProtocol(hSession, finayBuf, finalBufSize, true);
969     } else {
970         ret = SendByProtocol(hSession, finayBuf, finalBufSize);
971     }
972     --hSession->ref;
973     return ret;
974 }
975 
DecryptPayload(HSession hSession,PayloadHead * payloadHeadBe,uint8_t * encBuf)976 int HdcSessionBase::DecryptPayload(HSession hSession, PayloadHead *payloadHeadBe, uint8_t *encBuf)
977 {
978     StartTraceScope("HdcSessionBase::DecryptPayload");
979     PayloadProtect protectBuf = {};
980     uint16_t headSize = ntohs(payloadHeadBe->headSize);
981     int dataSize = ntohl(payloadHeadBe->dataSize);
982     string encString(reinterpret_cast<char *>(encBuf), headSize);
983     SerialStruct::ParseFromString(protectBuf, encString);
984     if (protectBuf.vCode != payloadProtectStaticVcode) {
985         WRITE_LOG(LOG_FATAL, "Session recv static vcode failed");
986         return ERR_BUF_CHECK;
987     }
988     uint8_t *data = encBuf + headSize;
989     if (ENABLE_IO_CHECKSUM && protectBuf.checkSum != 0 && (protectBuf.checkSum != Base::CalcCheckSum(data, dataSize))) {
990         WRITE_LOG(LOG_FATAL, "Session recv CalcCheckSum failed");
991         return ERR_BUF_CHECK;
992     }
993     if (!FetchCommand(hSession, protectBuf.channelId, protectBuf.commandFlag, data, dataSize)) {
994         WRITE_LOG(LOG_WARN, "FetchCommand failed: channelId %x commandFlag %x",
995                   protectBuf.channelId, protectBuf.commandFlag);
996         return ERR_GENERIC;
997     }
998     return RET_SUCCESS;
999 }
1000 
OnRead(HSession hSession,uint8_t * bufPtr,const int bufLen)1001 int HdcSessionBase::OnRead(HSession hSession, uint8_t *bufPtr, const int bufLen)
1002 {
1003     int ret = ERR_GENERIC;
1004     StartTraceScope("HdcSessionBase::OnRead");
1005     if (memcmp(bufPtr, PACKET_FLAG.c_str(), PACKET_FLAG.size())) {
1006         WRITE_LOG(LOG_FATAL, "PACKET_FLAG incorrect %x %x", bufPtr[0], bufPtr[1]);
1007         return ERR_BUF_CHECK;
1008     }
1009     struct PayloadHead *payloadHead = reinterpret_cast<struct PayloadHead *>(bufPtr);
1010     // to prevent integer overflow caused by the add operation of two input num
1011     uint64_t payloadHeadSize = static_cast<uint64_t>(ntohl(payloadHead->dataSize)) +
1012         static_cast<uint64_t>(ntohs(payloadHead->headSize));
1013     int packetHeadSize = sizeof(struct PayloadHead);
1014     if (payloadHeadSize == 0 || payloadHeadSize > static_cast<uint64_t>(HDC_BUF_MAX_BYTES)) {
1015         WRITE_LOG(LOG_FATAL, "Packet size incorrect");
1016         return ERR_BUF_CHECK;
1017     }
1018 
1019     // 0 < payloadHeadSize < HDC_BUF_MAX_BYTES
1020     int tobeReadLen = static_cast<int>(payloadHeadSize);
1021     if (bufLen - packetHeadSize < tobeReadLen) {
1022         return 0;
1023     }
1024     if (DecryptPayload(hSession, payloadHead, bufPtr + packetHeadSize)) {
1025         WRITE_LOG(LOG_WARN, "decrypt plhead error");
1026         return ERR_BUF_CHECK;
1027     }
1028     ret = packetHeadSize + tobeReadLen;
1029     return ret;
1030 }
1031 
1032 // Returns <0 error;> 0 receives the number of bytes; 0 untreated
FetchIOBuf(HSession hSession,uint8_t * ioBuf,int read)1033 int HdcSessionBase::FetchIOBuf(HSession hSession, uint8_t *ioBuf, int read)
1034 {
1035     HdcSessionBase *ptrConnect = (HdcSessionBase *)hSession->classInstance;
1036     int indexBuf = 0;
1037     int childRet = 0;
1038     StartTraceScope("HdcSessionBase::FetchIOBuf");
1039     if (read < 0) {
1040         constexpr int bufSize = 1024;
1041         char buf[bufSize] = { 0 };
1042         uv_strerror_r(read, buf, bufSize);
1043         WRITE_LOG(LOG_FATAL, "FetchIOBuf read io failed,%s", buf);
1044         return ERR_IO_FAIL;
1045     }
1046     if (hSession->heartbeat.GetSupportHeartbeat() && !hSession->heartbeat.HandleMessageCount()) {
1047         WRITE_LOG(LOG_FATAL, "Rehandshake is required because no heartbeat message is received for a long time");
1048         FreeSession(hSession->sessionId);
1049         return ERR_IO_FAIL;
1050     }
1051     hSession->stat.dataRecvBytes += read;
1052     hSession->availTailIndex += read;
1053     while (!hSession->isDead && hSession->availTailIndex > static_cast<int>(sizeof(PayloadHead))) {
1054         childRet = ptrConnect->OnRead(hSession, ioBuf + indexBuf, hSession->availTailIndex);
1055         if (childRet > 0) {
1056             hSession->availTailIndex -= childRet;
1057             indexBuf += childRet;
1058         } else if (childRet == 0) {
1059             // Not enough a IO
1060             break;
1061         } else {                           // <0
1062             WRITE_LOG(LOG_FATAL, "FetchIOBuf error childRet:%d sessionId:%u", childRet, hSession->sessionId);
1063             hSession->availTailIndex = 0;  // Preventing malicious data packages
1064             indexBuf = ERR_BUF_SIZE;
1065             break;
1066         }
1067         // It may be multi-time IO to merge in a BUF, need to loop processing
1068     }
1069     if (indexBuf > 0 && hSession->availTailIndex > 0) {
1070         if (memmove_s(hSession->ioBuf, hSession->bufSize, hSession->ioBuf + indexBuf, hSession->availTailIndex)
1071             != EOK) {
1072             return ERR_BUF_COPY;
1073         };
1074         uint8_t *bufToZero = reinterpret_cast<uint8_t *>(hSession->ioBuf + hSession->availTailIndex);
1075         Base::ZeroBuf(bufToZero, hSession->bufSize - hSession->availTailIndex);
1076     }
1077     return indexBuf;
1078 }
1079 
1080 #ifdef HDC_SUPPORT_ENCRYPT_TCP
FetchIOBuf(HSession hSession,uint8_t * ioBuf,int read,bool isEncrypt)1081 int HdcSessionBase::FetchIOBuf(HSession hSession, uint8_t *ioBuf, int read, bool isEncrypt)
1082 {
1083     if (isEncrypt) {
1084         HdcSSLBase *hssl = static_cast<HdcSSLBase *>(hSession->classSSL);
1085         int ret = (hssl != nullptr) ? hssl->Decrypt(read,
1086             hSession->bufSize, hSession->ioBuf, hSession->availTailIndex) : ERR_GENERIC;
1087         if (ret == ERR_DECRYPT_WANT_READ) {
1088             return RET_SUCCESS;
1089         }
1090         // for the SSL_ERR_WANT_READ branch, do next read.
1091         if (ret == RET_SUCCESS && FetchIOBuf(hSession, hSession->ioBuf, 0) < 0) {
1092             WRITE_LOG(LOG_FATAL, "ReadStream FetchIOBuf error nread:%zd, sid:%u", read, hSession->sessionId);
1093             ret = ERR_GENERIC;
1094         }
1095         return ret;
1096     } else {
1097         return FetchIOBuf(hSession, hSession->ioBuf, read);
1098     }
1099 }
1100 #endif
1101 
AllocCallback(uv_handle_t * handle,size_t sizeWanted,uv_buf_t * buf)1102 void HdcSessionBase::AllocCallback(uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf)
1103 {
1104     HSession context = (HSession)handle->data;
1105     Base::ReallocBuf(&context->ioBuf, &context->bufSize, HDC_SOCKETPAIR_SIZE);
1106     buf->base = (char *)context->ioBuf + context->availTailIndex;
1107     int size = context->bufSize - context->availTailIndex;
1108     buf->len = std::min(size, static_cast<int>(sizeWanted));
1109 }
1110 
FinishWriteSessionTCP(uv_write_t * req,int status)1111 void HdcSessionBase::FinishWriteSessionTCP(uv_write_t *req, int status)
1112 {
1113     HSession hSession = (HSession)req->handle->data;
1114     --hSession->ref;
1115     HdcSessionBase *thisClass = (HdcSessionBase *)hSession->classInstance;
1116     if (status < 0) {
1117         WRITE_LOG(LOG_WARN, "FinishWriteSessionTCP status:%d sessionId:%u isDead:%d ref:%u",
1118             status, hSession->sessionId, hSession->isDead, uint32_t(hSession->ref));
1119         Base::TryCloseHandle((uv_handle_t *)req->handle);
1120         if (!hSession->isDead && !hSession->ref) {
1121             WRITE_LOG(LOG_INFO, "FinishWriteSessionTCP freesession:%u", hSession->sessionId);
1122             thisClass->FreeSession(hSession->sessionId);
1123         }
1124     }
1125     delete[]((uint8_t *)req->data);
1126     delete req;
1127 }
1128 
DispatchSessionThreadCommand(HSession hSession,const uint8_t * baseBuf,const int bytesIO)1129 bool HdcSessionBase::DispatchSessionThreadCommand(HSession hSession, const uint8_t *baseBuf,
1130                                                   const int bytesIO)
1131 {
1132     bool ret = true;
1133     uint8_t flag = *const_cast<uint8_t *>(baseBuf);
1134 
1135     switch (flag) {
1136         case SP_JDWP_NEWFD:
1137         case SP_ARK_NEWFD: {
1138             JdwpNewFileDescriptor(baseBuf, bytesIO);
1139             break;
1140         }
1141         default:
1142             WRITE_LOG(LOG_WARN, "Not support session command");
1143             break;
1144     }
1145     return ret;
1146 }
1147 
ReadCtrlFromSession(uv_poll_t * poll,int status,int events)1148 void HdcSessionBase::ReadCtrlFromSession(uv_poll_t *poll, int status, int events)
1149 {
1150     HSession hSession = (HSession)poll->data;
1151     CALLSTAT_GUARD(hSession->childLoopStatus, poll->loop, "HdcSessionBase::ReadCtrlFromSession");
1152     HdcSessionBase *hSessionBase = (HdcSessionBase *)hSession->classInstance;
1153     const int size = Base::GetMaxBufSizeStable();
1154     char *buf = reinterpret_cast<char *>(new uint8_t[size]());
1155     ssize_t nread = Base::ReadFromFd(hSession->ctrlFd[STREAM_MAIN], buf, size);
1156     while (true) {
1157         if (nread < 0) {
1158             constexpr int bufSize = 1024;
1159             char buffer[bufSize] = { 0 };
1160             uv_strerror_r(static_cast<int>(nread), buffer, bufSize);
1161             WRITE_LOG(LOG_WARN, "ReadCtrlFromSession failed,%s", buffer);
1162             uv_poll_stop(poll);
1163             break;
1164         }
1165         if (nread == 0) {
1166             WRITE_LOG(LOG_FATAL, "ReadCtrlFromSession read data zero byte");
1167             break;
1168         }
1169         // only one command, no need to split command from stream
1170         // if add more commands, consider the format command
1171         hSessionBase->DispatchSessionThreadCommand(hSession, reinterpret_cast<uint8_t *>(buf), nread);
1172         break;
1173     }
1174     delete[] buf;
1175 }
1176 
SetFeature(SessionHandShake & handshake)1177 void HdcSessionBase::SetFeature(SessionHandShake &handshake)
1178 {
1179     Base::HdcFeatureSet feature = {};
1180     if (Base::GetheartbeatSwitch()) {
1181         feature.push_back(FEATURE_HEARTBEAT);
1182     }
1183 #ifdef HDC_SUPPORT_ENCRYPT_TCP
1184     if (Base::GetEncrpytTCPSwitch()) {
1185         feature.push_back(FEATURE_ENCRYPT_TCP);
1186     }
1187 #endif
1188     // told daemon, we support features
1189     if (feature.size() == 0) {
1190         return;
1191     }
1192     Base::TlvAppend(handshake.buf, TAG_SUPPORT_FEATURE, Base::FeatureToString(feature));
1193 }
1194 
WorkThreadInitSession(HSession hSession,SessionHandShake & handshake)1195 void HdcSessionBase::WorkThreadInitSession(HSession hSession, SessionHandShake &handshake)
1196 {
1197     handshake.banner = HANDSHAKE_MESSAGE;
1198     handshake.sessionId = hSession->sessionId;
1199     handshake.connectKey = hSession->connectKey;
1200     if (!hSession->isCheck) {
1201         handshake.version = Base::GetVersion() + HDC_MSG_HASH;
1202         WRITE_LOG(LOG_INFO, "set version = %s", handshake.version.c_str());
1203     }
1204     handshake.authType = AUTH_NONE;
1205     // told daemon, we support RSA_3072_SHA512 auth
1206     Base::TlvAppend(handshake.buf, TAG_AUTH_TYPE, std::to_string(AuthVerifyType::RSA_3072_SHA512));
1207     HdcSessionBase *hSessionBase = (HdcSessionBase *)hSession->classInstance;
1208     hSessionBase->SetFeature(handshake);
1209 }
1210 
WorkThreadStartSession(HSession hSession)1211 bool HdcSessionBase::WorkThreadStartSession(HSession hSession)
1212 {
1213     bool regOK = false;
1214     int childRet = 0;
1215     if (hSession->connType == CONN_TCP) {
1216         HdcTCPBase *pTCPBase = (HdcTCPBase *)hSession->classModule;
1217         hSession->hChildWorkTCP.data = hSession;
1218         if (uv_tcp_init(&hSession->childLoop, &hSession->hChildWorkTCP) < 0) {
1219             WRITE_LOG(LOG_FATAL, "WorkThreadStartSession uv_tcp_init failed sid:%u", hSession->sessionId);
1220             return false;
1221         }
1222         WRITE_LOG(LOG_INFO, "start tcp open fdChildWorkTCP, sid:%u", hSession->sessionId);
1223         if ((childRet = uv_tcp_open(&hSession->hChildWorkTCP, hSession->fdChildWorkTCP)) < 0) {
1224             constexpr int bufSize = 1024;
1225             char buf[bufSize] = { 0 };
1226             uv_strerror_r(childRet, buf, bufSize);
1227             WRITE_LOG(LOG_FATAL, "WorkThreadStartSession uv_tcp_open failed fd:%d str:%s sid:%u",
1228                 hSession->fdChildWorkTCP, buf, hSession->sessionId);
1229             return false;
1230         }
1231         Base::SetTcpOptions((uv_tcp_t *)&hSession->hChildWorkTCP);
1232         uv_read_start((uv_stream_t *)&hSession->hChildWorkTCP, AllocCallback, pTCPBase->ReadStream);
1233         regOK = true;
1234 #ifdef HDC_SUPPORT_UART
1235     } else if (hSession->connType == CONN_SERIAL) { // UART
1236         HdcUARTBase *pUARTBase = (HdcUARTBase *)hSession->classModule;
1237         WRITE_LOG(LOG_INFO, "UART ReadyForWorkThread sid:%u", hSession->sessionId);
1238         regOK = pUARTBase->ReadyForWorkThread(hSession);
1239 #endif
1240     } else {  // USB
1241         HdcUSBBase *pUSBBase = (HdcUSBBase *)hSession->classModule;
1242         WRITE_LOG(LOG_INFO, "USB ReadyForWorkThread sid:%u", hSession->sessionId);
1243         regOK = pUSBBase->ReadyForWorkThread(hSession);
1244     }
1245 
1246     if (regOK && hSession->serverOrDaemon) {
1247         // session handshake step1
1248         SessionHandShake handshake = {};
1249         WorkThreadInitSession(hSession, handshake);
1250         string hs = SerialStruct::SerializeToString(handshake);
1251 #ifdef HDC_SUPPORT_UART
1252         WRITE_LOG(LOG_INFO, "WorkThreadStartSession session %u auth %u send handshake hs: %s",
1253                   hSession->sessionId, handshake.authType, hs.c_str());
1254 #endif
1255         Send(hSession->sessionId, 0, CMD_KERNEL_HANDSHAKE,
1256              reinterpret_cast<uint8_t *>(const_cast<char *>(hs.c_str())), hs.size());
1257     }
1258     return regOK;
1259 }
1260 
BuildCtrlString(InnerCtrlCommand command,uint32_t channelId,uint8_t * data,int dataSize)1261 vector<uint8_t> HdcSessionBase::BuildCtrlString(InnerCtrlCommand command, uint32_t channelId, uint8_t *data,
1262                                                 int dataSize)
1263 {
1264     vector<uint8_t> ret;
1265     while (true) {
1266         if (dataSize > BUF_SIZE_MICRO) {
1267             WRITE_LOG(LOG_WARN, "BuildCtrlString dataSize:%d", dataSize);
1268             break;
1269         }
1270         CtrlStruct ctrl = {};
1271         ctrl.command = command;
1272         ctrl.channelId = channelId;
1273         ctrl.dataSize = dataSize;
1274         if (dataSize > 0 && data != nullptr && memcpy_s(ctrl.data, sizeof(ctrl.data), data, dataSize) != EOK) {
1275             break;
1276         }
1277         uint8_t *buf = reinterpret_cast<uint8_t *>(&ctrl);
1278         ret.insert(ret.end(), buf, buf + sizeof(CtrlStruct));
1279         break;
1280     }
1281     return ret;
1282 }
1283 
DispatchMainThreadCommand(HSession hSession,const CtrlStruct * ctrl)1284 bool HdcSessionBase::DispatchMainThreadCommand(HSession hSession, const CtrlStruct *ctrl)
1285 {
1286     bool ret = true;
1287     uint32_t channelId = ctrl->channelId;  // if send not set, it is zero
1288     switch (ctrl->command) {
1289         case SP_START_SESSION: {
1290             WRITE_LOG(LOG_WARN, "Dispatch MainThreadCommand  START_SESSION sessionId:%u instance:%s",
1291                       hSession->sessionId, hSession->serverOrDaemon ? "server" : "daemon");
1292             ret = WorkThreadStartSession(hSession);
1293             break;
1294         }
1295         case SP_STOP_SESSION: {
1296             WRITE_LOG(LOG_WARN, "Dispatch MainThreadCommand STOP_SESSION sessionId:%u", hSession->sessionId);
1297             HdcSessionBase *hSessionBase = (HdcSessionBase *)hSession->classInstance;
1298             hSessionBase->StopHeartbeatWork(hSession);
1299             auto closeSessionChildThreadTCPHandle = [](uv_handle_t *handle) -> void {
1300                 HSession hSession = (HSession)handle->data;
1301                 Base::TryCloseHandle((uv_handle_t *)handle);
1302                 if (handle == (uv_handle_t *)hSession->pollHandle[STREAM_WORK]) {
1303                     free(hSession->pollHandle[STREAM_WORK]);
1304                 }
1305                 if (--hSession->uvChildRef == 0) {
1306                     WRITE_LOG(LOG_WARN, "Dispatch MainThreadCommand uv stop childLoop sessionId:%u",
1307                         hSession->sessionId);
1308                     uv_stop(&hSession->childLoop);
1309                 };
1310             };
1311             constexpr int uvChildRefOffset = 2;
1312             hSession->uvChildRef += uvChildRefOffset;
1313             if (hSession->connType == CONN_TCP && hSession->hChildWorkTCP.loop) {  // maybe not use it
1314                 ++hSession->uvChildRef;
1315                 WRITE_LOG(LOG_INFO, "Dispatch MainThreadCommand try close hChildWorkTCP, sid:%u", hSession->sessionId);
1316                 Base::TryCloseHandle((uv_handle_t *)&hSession->hChildWorkTCP, true, closeSessionChildThreadTCPHandle);
1317             }
1318             Base::TryCloseHandle((uv_handle_t *)hSession->pollHandle[STREAM_WORK], true,
1319                                  closeSessionChildThreadTCPHandle);
1320             Base::TryCloseHandle((uv_handle_t *)&hSession->dataPipe[STREAM_WORK], true,
1321                                  closeSessionChildThreadTCPHandle);
1322             break;
1323         }
1324         case SP_ATTACH_CHANNEL: {
1325             if (!serverOrDaemon) {
1326                 break;  // Only Server has this feature
1327             }
1328             AttachChannel(hSession, channelId);
1329             break;
1330         }
1331         case SP_DEATCH_CHANNEL: {
1332             if (!serverOrDaemon) {
1333                 break;  // Only Server has this feature
1334             }
1335             DeatchChannel(hSession, channelId);
1336             break;
1337         }
1338         default:
1339             WRITE_LOG(LOG_WARN, "Not support main command");
1340             ret = false;
1341             break;
1342     }
1343     return ret;
1344 }
1345 
1346 // Several bytes of control instructions, generally do not stick
ReadCtrlFromMain(uv_poll_t * poll,int status,int events)1347 void HdcSessionBase::ReadCtrlFromMain(uv_poll_t *poll, int status, int events)
1348 {
1349     HSession hSession = (HSession)poll->data;
1350     CALLSTAT_GUARD(hSession->childLoopStatus, poll->loop, "HdcSessionBase::ReadCtrlFromMain");
1351     HdcSessionBase *hSessionBase = (HdcSessionBase *)hSession->classInstance;
1352     int formatCommandSize = sizeof(CtrlStruct);
1353     int index = 0;
1354     const int size = Base::GetMaxBufSizeStable();
1355     char *buf = reinterpret_cast<char *>(new uint8_t[size]());
1356     ssize_t nread = Base::ReadFromFd(hSession->ctrlFd[STREAM_WORK], buf, size);
1357     while (true) {
1358         if (nread < 0) {
1359             constexpr int bufSize = 1024;
1360             char buffer[bufSize] = { 0 };
1361             uv_strerror_r(static_cast<int>(nread), buffer, bufSize);
1362             WRITE_LOG(LOG_WARN, "SessionCtrl failed,%s", buffer);
1363             break;
1364         }
1365         if (nread % formatCommandSize != 0) {
1366             WRITE_LOG(LOG_FATAL, "ReadCtrlFromMain size failed, nread == %d", nread);
1367             break;
1368         }
1369         CtrlStruct *ctrl = reinterpret_cast<CtrlStruct *>(buf + index);
1370         if (!hSessionBase->DispatchMainThreadCommand(hSession, ctrl)) {
1371             WRITE_LOG(LOG_FATAL, "ReadCtrlFromMain failed sessionId:%u channelId:%u command:%u",
1372                       hSession->sessionId, ctrl->channelId, ctrl->command);
1373             break;
1374         }
1375         index += sizeof(CtrlStruct);
1376         if (index >= nread) {
1377             break;
1378         }
1379     }
1380     delete[] buf;
1381 }
1382 
ReChildLoopForSessionClear(HSession hSession)1383 void HdcSessionBase::ReChildLoopForSessionClear(HSession hSession)
1384 {
1385     // Restart loop close task
1386     ClearOwnTasks(hSession, 0);
1387     WRITE_LOG(LOG_INFO, "ReChildLoopForSessionClear sessionId:%u", hSession->sessionId);
1388     auto clearTaskForSessionFinish = [](uv_timer_t *handle) -> void {
1389         HSession hSession = (HSession)handle->data;
1390         hSession->clearTaskTimes++;
1391         HdcSessionBase *thisClass = (HdcSessionBase *)hSession->classInstance;
1392         if (thisClass->taskCount && (hSession->clearTaskTimes < 50)) {    //50: 50 * 120ms = 6s
1393             return;
1394         }
1395         if (hSession->clearTaskTimes >= 50) {   //50: 50 * 120ms = 6s
1396             WRITE_LOG(LOG_FATAL, "ReChildLoopForSessionClear exited due to timeout of 6s");
1397         }
1398         // all task has been free
1399         uv_close((uv_handle_t *)handle, Base::CloseTimerCallback);
1400         uv_stop(&hSession->childLoop);  // stop ReChildLoopForSessionClear pendding
1401     };
1402     Base::TimerUvTask(
1403         &hSession->childLoop, hSession, clearTaskForSessionFinish, (GLOBAL_TIMEOUT * TIME_BASE) / UV_DEFAULT_INTERVAL);
1404     uv_run(&hSession->childLoop, UV_RUN_DEFAULT);
1405     // clear
1406     Base::TryCloseChildLoop(&hSession->childLoop, "Session childUV");
1407 }
1408 
1409 //stop Heartbeat
StopHeartbeatWork(HSession hSession)1410 void HdcSessionBase::StopHeartbeatWork(HSession hSession)
1411 {
1412     hSession->heartbeat.SetSupportHeartbeat(false);
1413     uv_timer_stop(&hSession->heartbeatTimer);
1414 }
1415 
1416 // send heartbeat msg
SendHeartbeatMsg(uv_timer_t * handle)1417 void HdcSessionBase::SendHeartbeatMsg(uv_timer_t *handle)
1418 {
1419     HSession hSession = (HSession)handle->data;
1420     if (!hSession->heartbeat.GetSupportHeartbeat()) {
1421         WRITE_LOG(LOG_INFO, "session %u not support heatbeat", hSession->sessionId);
1422         if (hSession->handshakeOK) {
1423             uv_timer_stop(&hSession->heartbeatTimer);
1424         }
1425         return;
1426     }
1427 
1428     std::string str = hSession->heartbeat.ToString();
1429     WRITE_LOG(LOG_INFO, "send %s for session %u", str.c_str(), hSession->sessionId);
1430 
1431     HeartbeatMsg heartbeat = {};
1432     heartbeat.heartbeatCount = hSession->heartbeat.GetHeartbeatCount();
1433     hSession->heartbeat.AddHeartbeatCount();
1434     string s = SerialStruct::SerializeToString(heartbeat);
1435     HdcSessionBase *thisClass = (HdcSessionBase *)hSession->classInstance;
1436     thisClass->Send(hSession->sessionId, 0, CMD_HEARTBEAT_MSG,
1437         reinterpret_cast<uint8_t *>(const_cast<char *>(s.c_str())), s.size());
1438 }
1439 
StartHeartbeatWork(HSession hSession)1440 void HdcSessionBase::StartHeartbeatWork(HSession hSession)
1441 {
1442     if (!Base::GetheartbeatSwitch()) {
1443         return;
1444     }
1445     WRITE_LOG(LOG_DEBUG, "StartHeartbeatWork");
1446     hSession->heartbeatTimer.data = hSession;
1447     uv_timer_init(&hSession->childLoop, &hSession->heartbeatTimer);
1448     uv_timer_start(&hSession->heartbeatTimer, SendHeartbeatMsg, 0, HEARTBEAT_INTERVAL);
1449 }
1450 
SessionWorkThread(uv_work_t * arg)1451 void HdcSessionBase::SessionWorkThread(uv_work_t *arg)
1452 {
1453     HSession hSession = (HSession)arg->data;
1454     HdcSessionBase *thisClass = (HdcSessionBase *)hSession->classInstance;
1455     hSession->hWorkChildThread = uv_thread_self();
1456 
1457     uv_poll_t *pollHandle = hSession->pollHandle[STREAM_WORK];
1458     pollHandle->data = hSession;
1459     int initResult = uv_poll_init_socket(&hSession->childLoop, pollHandle, hSession->ctrlFd[STREAM_WORK]);
1460     if (initResult != 0) {
1461         WRITE_LOG(LOG_FATAL, "SessionWorkThread init pollHandle->loop failed");
1462         _exit(0);
1463     }
1464     uv_poll_start(pollHandle, UV_READABLE, ReadCtrlFromMain);
1465     // start heartbeat rimer
1466     HdcSessionBase *hSessionBase = (HdcSessionBase *)hSession->classInstance;
1467     hSessionBase->StartHeartbeatWork(hSession);
1468     WRITE_LOG(LOG_INFO, "!!!Workthread run begin, sid:%u instance:%s", hSession->sessionId,
1469               thisClass->serverOrDaemon ? "server" : "daemon");
1470     uv_run(&hSession->childLoop, UV_RUN_DEFAULT);  // work pendding
1471     WRITE_LOG(LOG_INFO, "!!!Workthread run again, sid:%u", hSession->sessionId);
1472     // main loop has exit
1473     thisClass->ReChildLoopForSessionClear(hSession);  // work pending again
1474     hSession->childCleared = true;
1475     WRITE_LOG(LOG_INFO, "!!!Workthread run finish, sid:%u", hSession->sessionId);
1476 }
1477 
1478 // clang-format off
LogMsg(const uint32_t sessionId,const uint32_t channelId,MessageLevel level,const char * msg,...)1479 void HdcSessionBase::LogMsg(const uint32_t sessionId, const uint32_t channelId,
1480                             MessageLevel level, const char *msg, ...)
1481 // clang-format on
1482 {
1483     va_list vaArgs;
1484     va_start(vaArgs, msg);
1485     string log = Base::StringFormat(msg, vaArgs);
1486     va_end(vaArgs);
1487     vector<uint8_t> buf;
1488     buf.push_back(level);
1489     buf.insert(buf.end(), log.c_str(), log.c_str() + log.size());
1490     ServerCommand(sessionId, channelId, CMD_KERNEL_ECHO, buf.data(), buf.size());
1491 }
1492 
NeedNewTaskInfo(const uint16_t command,bool & masterTask)1493 bool HdcSessionBase::NeedNewTaskInfo(const uint16_t command, bool &masterTask)
1494 {
1495     // referer from HdcServerForClient::DoCommandRemote
1496     bool ret = false;
1497     bool taskMasterInit = false;
1498     masterTask = false;
1499     switch (command) {
1500         case CMD_FILE_INIT:
1501         case CMD_FLASHD_FLASH_INIT:
1502         case CMD_FLASHD_UPDATE_INIT:
1503         case CMD_FLASHD_ERASE:
1504         case CMD_FLASHD_FORMAT:
1505         case CMD_FORWARD_INIT:
1506         case CMD_APP_INIT:
1507         case CMD_APP_UNINSTALL:
1508         case CMD_APP_SIDELOAD:
1509             taskMasterInit = true;
1510             break;
1511         default:
1512             break;
1513     }
1514     if (!serverOrDaemon &&
1515             (command == CMD_SHELL_INIT || command == CMD_UNITY_EXECUTE_EX ||
1516                 (command > CMD_UNITY_COMMAND_HEAD && command < CMD_UNITY_COMMAND_TAIL))) {
1517         // daemon's single side command
1518         ret = true;
1519     } else if (command == CMD_KERNEL_WAKEUP_SLAVETASK) {
1520         // slave tasks
1521         ret = true;
1522     } else if (command == CMD_UNITY_BUGREPORT_INIT) {
1523         ret = true;
1524     } else if (taskMasterInit) {
1525         // task init command
1526         masterTask = true;
1527         ret = true;
1528     }
1529     return ret;
1530 }
1531 // Heavy and time-consuming work was putted in the new thread to do, and does
1532 // not occupy the main thread
DispatchTaskData(HSession hSession,const uint32_t channelId,const uint16_t command,uint8_t * payload,int payloadSize)1533 bool HdcSessionBase::DispatchTaskData(HSession hSession, const uint32_t channelId, const uint16_t command,
1534                                       uint8_t *payload, int payloadSize)
1535 {
1536     StartTraceScope("HdcSessionBase::DispatchTaskData");
1537     bool ret = true;
1538     HTaskInfo hTaskInfo = nullptr;
1539     bool masterTask = false;
1540     while (true) {
1541         // Some basic commands do not have a local task constructor. example: Interactive shell, some uinty commands
1542         if (NeedNewTaskInfo(command, masterTask)) {
1543             WRITE_LOG(LOG_INFO, "New HTaskInfo cid:%u sid:%u command:%u", channelId, hSession->sessionId, command);
1544             hTaskInfo = new(std::nothrow) TaskInformation();
1545             if (hTaskInfo == nullptr) {
1546                 WRITE_LOG(LOG_FATAL, "DispatchTaskData new hTaskInfo failed");
1547                 break;
1548             }
1549             hTaskInfo->channelId = channelId;
1550             hTaskInfo->sessionId = hSession->sessionId;
1551             hTaskInfo->runLoop = &hSession->childLoop;
1552             hTaskInfo->runLoopStatus = &hSession->childLoopStatus;
1553             hTaskInfo->serverOrDaemon = serverOrDaemon;
1554             hTaskInfo->masterSlave = masterTask;
1555             hTaskInfo->closeRetryCount = 0;
1556             hTaskInfo->channelTask = false;
1557             hTaskInfo->isCleared = false;
1558 
1559             int addTaskRetry = 3; // try 3 time
1560             while (addTaskRetry > 0) {
1561                 if (AdminTask(OP_ADD, hSession, channelId, hTaskInfo)) {
1562                     break;
1563                 }
1564                 sleep(1);
1565                 --addTaskRetry;
1566             }
1567 
1568             if (addTaskRetry == 0) {
1569 #ifndef HDC_HOST
1570                 LogMsg(hTaskInfo->sessionId, hTaskInfo->channelId,
1571                        MSG_FAIL, "hdc thread pool busy, may cause reset later");
1572 #endif
1573                 delete hTaskInfo;
1574                 hTaskInfo = nullptr;
1575                 ret = false;
1576                 break;
1577             }
1578         } else {
1579             hTaskInfo = AdminTask(OP_QUERY, hSession, channelId, nullptr);
1580         }
1581         if (!hTaskInfo || hTaskInfo->taskStop || hTaskInfo->taskFree) {
1582             WRITE_LOG(LOG_WARN, "hTaskInfo null cid:%u sid:%u command:%u", channelId, hSession->sessionId, command);
1583             break;
1584         }
1585         ret = RedirectToTask(hTaskInfo, hSession, channelId, command, payload, payloadSize);
1586         break;
1587     }
1588     return ret;
1589 }
1590 
PostStopInstanceMessage(bool restart)1591 void HdcSessionBase::PostStopInstanceMessage(bool restart)
1592 {
1593     PushAsyncMessage(0, ASYNC_STOP_MAINLOOP, nullptr, 0);
1594     WRITE_LOG(LOG_INFO, "StopDaemon has sended restart %d", restart);
1595     wantRestart = restart;
1596 }
1597 
ParsePeerSupportFeatures(HSession & hSession,std::map<std::string,std::string> & tlvMap)1598 void HdcSessionBase::ParsePeerSupportFeatures(HSession &hSession, std::map<std::string, std::string> &tlvMap)
1599 {
1600     if (hSession == nullptr) {
1601         WRITE_LOG(LOG_FATAL, "Invalid paramter, hSession is null");
1602         return;
1603     }
1604 
1605     if (tlvMap.find(TAG_SUPPORT_FEATURE) != tlvMap.end()) {
1606         std::vector<std::string> features;
1607         WRITE_LOG(LOG_INFO, "peer support features are %s for session %u",
1608             tlvMap[TAG_SUPPORT_FEATURE].c_str(), hSession->sessionId);
1609         Base::SplitString(tlvMap[TAG_SUPPORT_FEATURE], ",", features);
1610         hSession->heartbeat.SetSupportHeartbeat(Base::IsSupportFeature(features, FEATURE_HEARTBEAT));
1611 #ifdef HDC_SUPPORT_ENCRYPT_TCP
1612         hSession->supportEncrypt = Base::IsSupportFeature(features, FEATURE_ENCRYPT_TCP);
1613 #endif
1614     }
1615 }
1616 }  // namespace Hdc
1617