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