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