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 "client.h" 16cc290419Sopenharmony_ci#ifndef TEST_HASH 17cc290419Sopenharmony_ci#include "hdc_hash_gen.h" 18cc290419Sopenharmony_ci#endif 19cc290419Sopenharmony_ci#include "host_updater.h" 20cc290419Sopenharmony_ci#include "server.h" 21cc290419Sopenharmony_ci#include "file.h" 22cc290419Sopenharmony_ci 23cc290419Sopenharmony_cistd::map<std::string, std::string> g_lists; 24cc290419Sopenharmony_cibool g_show = true; 25cc290419Sopenharmony_ci 26cc290419Sopenharmony_cinamespace Hdc { 27cc290419Sopenharmony_cibool g_terminalStateChange = false; 28cc290419Sopenharmony_ciHdcClient::HdcClient(const bool serverOrClient, const string &addrString, uv_loop_t *loopMainIn, bool checkVersion) 29cc290419Sopenharmony_ci : HdcChannelBase(serverOrClient, addrString, loopMainIn) 30cc290419Sopenharmony_ci{ 31cc290419Sopenharmony_ci MallocChannel(&channel); // free by logic 32cc290419Sopenharmony_ci debugRetryCount = 0; 33cc290419Sopenharmony_ci#ifndef _WIN32 34cc290419Sopenharmony_ci Base::ZeroStruct(terminalState); 35cc290419Sopenharmony_ci#endif 36cc290419Sopenharmony_ci isCheckVersionCmd = checkVersion; 37cc290419Sopenharmony_ci} 38cc290419Sopenharmony_ci 39cc290419Sopenharmony_ciHdcClient::~HdcClient() 40cc290419Sopenharmony_ci{ 41cc290419Sopenharmony_ci#ifndef _WIN32 42cc290419Sopenharmony_ci if (g_terminalStateChange) { 43cc290419Sopenharmony_ci tcsetattr(STDIN_FILENO, TCSAFLUSH, &terminalState); 44cc290419Sopenharmony_ci } 45cc290419Sopenharmony_ci#endif 46cc290419Sopenharmony_ci Base::TryCloseLoop(loopMain, "ExecuteCommand finish"); 47cc290419Sopenharmony_ci} 48cc290419Sopenharmony_ci 49cc290419Sopenharmony_civoid HdcClient::NotifyInstanceChannelFree(HChannel hChannel) 50cc290419Sopenharmony_ci{ 51cc290419Sopenharmony_ci if (bShellInteractive) { 52cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "Restore tty"); 53cc290419Sopenharmony_ci ModifyTty(false, &hChannel->stdinTty); 54cc290419Sopenharmony_ci } 55cc290419Sopenharmony_ci} 56cc290419Sopenharmony_ci 57cc290419Sopenharmony_ciuint32_t HdcClient::GetLastPID() 58cc290419Sopenharmony_ci{ 59cc290419Sopenharmony_ci char bufPath[BUF_SIZE_MEDIUM] = ""; 60cc290419Sopenharmony_ci size_t size = BUF_SIZE_MEDIUM; 61cc290419Sopenharmony_ci char pidBuf[BUF_SIZE_TINY] = ""; 62cc290419Sopenharmony_ci // get running pid to kill it 63cc290419Sopenharmony_ci if (uv_os_tmpdir(bufPath, &size) < 0) { 64cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "Tmppath failed"); 65cc290419Sopenharmony_ci return 0; 66cc290419Sopenharmony_ci } 67cc290419Sopenharmony_ci string path = Base::StringFormat("%s%c.%s.pid", bufPath, Base::GetPathSep(), SERVER_NAME.c_str()); 68cc290419Sopenharmony_ci Base::ReadBinFile(path.c_str(), reinterpret_cast<void **>(&pidBuf), BUF_SIZE_TINY); 69cc290419Sopenharmony_ci int pid = atoi(pidBuf); // pid maybe 0 70cc290419Sopenharmony_ci return pid; 71cc290419Sopenharmony_ci} 72cc290419Sopenharmony_ci 73cc290419Sopenharmony_cibool HdcClient::StartServer(const string &cmd) 74cc290419Sopenharmony_ci{ 75cc290419Sopenharmony_ci int serverStatus = Base::ProgramMutex(SERVER_NAME.c_str(), true); 76cc290419Sopenharmony_ci if (serverStatus < 0) { 77cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "get server status failed, serverStatus:%d", serverStatus); 78cc290419Sopenharmony_ci return false; 79cc290419Sopenharmony_ci } 80cc290419Sopenharmony_ci 81cc290419Sopenharmony_ci // server is not running 82cc290419Sopenharmony_ci if (serverStatus == 0) { 83cc290419Sopenharmony_ci HdcServer::PullupServer(channelHostPort.c_str()); 84cc290419Sopenharmony_ci return true; 85cc290419Sopenharmony_ci } 86cc290419Sopenharmony_ci 87cc290419Sopenharmony_ci // server is running 88cc290419Sopenharmony_ci if (cmd.find(" -r") == std::string::npos) { 89cc290419Sopenharmony_ci return true; 90cc290419Sopenharmony_ci } 91cc290419Sopenharmony_ci 92cc290419Sopenharmony_ci // restart server 93cc290419Sopenharmony_ci uint32_t pid = GetLastPID(); 94cc290419Sopenharmony_ci if (pid == 0) { 95cc290419Sopenharmony_ci Base::PrintMessage(TERMINAL_HDC_PROCESS_FAILED.c_str()); 96cc290419Sopenharmony_ci return false; 97cc290419Sopenharmony_ci } 98cc290419Sopenharmony_ci int rc = uv_kill(pid, SIGKILL); 99cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "uv_kill rc:%d", rc); 100cc290419Sopenharmony_ci HdcServer::PullupServer(channelHostPort.c_str()); 101cc290419Sopenharmony_ci return true; 102cc290419Sopenharmony_ci} 103cc290419Sopenharmony_ci 104cc290419Sopenharmony_cibool HdcClient::KillServer(const string &cmd) 105cc290419Sopenharmony_ci{ 106cc290419Sopenharmony_ci int serverStatus = Base::ProgramMutex(SERVER_NAME.c_str(), true); 107cc290419Sopenharmony_ci if (serverStatus < 0) { 108cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "get server status failed, serverStatus:%d", serverStatus); 109cc290419Sopenharmony_ci return false; 110cc290419Sopenharmony_ci } 111cc290419Sopenharmony_ci 112cc290419Sopenharmony_ci // server is not running 113cc290419Sopenharmony_ci if (serverStatus == 0) { 114cc290419Sopenharmony_ci if (cmd.find(" -r") != std::string::npos) { 115cc290419Sopenharmony_ci HdcServer::PullupServer(channelHostPort.c_str()); 116cc290419Sopenharmony_ci } 117cc290419Sopenharmony_ci return true; 118cc290419Sopenharmony_ci } 119cc290419Sopenharmony_ci 120cc290419Sopenharmony_ci // server is running 121cc290419Sopenharmony_ci uint32_t pid = GetLastPID(); 122cc290419Sopenharmony_ci if (pid == 0) { 123cc290419Sopenharmony_ci Base::PrintMessage(TERMINAL_HDC_PROCESS_FAILED.c_str()); 124cc290419Sopenharmony_ci return false; 125cc290419Sopenharmony_ci } 126cc290419Sopenharmony_ci int rc = uv_kill(pid, SIGKILL); 127cc290419Sopenharmony_ci if (rc == 0) { 128cc290419Sopenharmony_ci Base::PrintMessage("Kill server finish"); 129cc290419Sopenharmony_ci } else { 130cc290419Sopenharmony_ci constexpr int size = 1024; 131cc290419Sopenharmony_ci char buf[size] = { 0 }; 132cc290419Sopenharmony_ci uv_strerror_r(rc, buf, size); 133cc290419Sopenharmony_ci Base::PrintMessage("Kill server failed %s", buf); 134cc290419Sopenharmony_ci } 135cc290419Sopenharmony_ci if (cmd.find(" -r") != std::string::npos) { 136cc290419Sopenharmony_ci HdcServer::PullupServer(channelHostPort.c_str()); 137cc290419Sopenharmony_ci } 138cc290419Sopenharmony_ci return true; 139cc290419Sopenharmony_ci} 140cc290419Sopenharmony_ci 141cc290419Sopenharmony_civoid HdcClient::DoCtrlServiceWork(uv_check_t *handle) 142cc290419Sopenharmony_ci{ 143cc290419Sopenharmony_ci HdcClient *thisClass = (HdcClient *)handle->data; 144cc290419Sopenharmony_ci string &strCmd = thisClass->command; 145cc290419Sopenharmony_ci if (!strncmp(thisClass->command.c_str(), CMDSTR_SERVICE_START.c_str(), CMDSTR_SERVICE_START.size())) { 146cc290419Sopenharmony_ci thisClass->StartServer(strCmd); 147cc290419Sopenharmony_ci } else if (!strncmp(thisClass->command.c_str(), CMDSTR_SERVICE_KILL.c_str(), CMDSTR_SERVICE_KILL.size())) { 148cc290419Sopenharmony_ci thisClass->KillServer(strCmd); 149cc290419Sopenharmony_ci // clang-format off 150cc290419Sopenharmony_ci } else if (!strncmp(thisClass->command.c_str(), CMDSTR_GENERATE_KEY.c_str(), CMDSTR_GENERATE_KEY.size()) && 151cc290419Sopenharmony_ci strCmd.find(" ") != std::string::npos) { 152cc290419Sopenharmony_ci // clang-format on 153cc290419Sopenharmony_ci string keyPath = strCmd.substr(CMDSTR_GENERATE_KEY.size() + 1, strCmd.size()); 154cc290419Sopenharmony_ci HdcAuth::GenerateKey(keyPath.c_str()); 155cc290419Sopenharmony_ci } else { 156cc290419Sopenharmony_ci Base::PrintMessage("Unknown command"); 157cc290419Sopenharmony_ci } 158cc290419Sopenharmony_ci Base::TryCloseHandle((const uv_handle_t *)handle); 159cc290419Sopenharmony_ci} 160cc290419Sopenharmony_ci 161cc290419Sopenharmony_ciint HdcClient::CtrlServiceWork(const char *commandIn) 162cc290419Sopenharmony_ci{ 163cc290419Sopenharmony_ci command = commandIn; 164cc290419Sopenharmony_ci ctrlServerWork.data = this; 165cc290419Sopenharmony_ci uv_check_init(loopMain, &ctrlServerWork); 166cc290419Sopenharmony_ci uv_check_start(&ctrlServerWork, DoCtrlServiceWork); 167cc290419Sopenharmony_ci uv_run(loopMain, UV_RUN_NOWAIT); 168cc290419Sopenharmony_ci return 0; 169cc290419Sopenharmony_ci} 170cc290419Sopenharmony_ci 171cc290419Sopenharmony_cistring HdcClient::AutoConnectKey(string &doCommand, const string &preConnectKey) const 172cc290419Sopenharmony_ci{ 173cc290419Sopenharmony_ci string key = preConnectKey; 174cc290419Sopenharmony_ci bool isNoTargetCommand = false; 175cc290419Sopenharmony_ci vector<string> vecNoConnectKeyCommand; 176cc290419Sopenharmony_ci vecNoConnectKeyCommand.push_back(CMDSTR_SOFTWARE_VERSION); 177cc290419Sopenharmony_ci vecNoConnectKeyCommand.push_back(CMDSTR_SOFTWARE_HELP); 178cc290419Sopenharmony_ci vecNoConnectKeyCommand.push_back(CMDSTR_TARGET_DISCOVER); 179cc290419Sopenharmony_ci vecNoConnectKeyCommand.push_back(CMDSTR_LIST_TARGETS); 180cc290419Sopenharmony_ci vecNoConnectKeyCommand.push_back(CMDSTR_CHECK_SERVER); 181cc290419Sopenharmony_ci vecNoConnectKeyCommand.push_back(CMDSTR_CONNECT_TARGET); 182cc290419Sopenharmony_ci vecNoConnectKeyCommand.push_back(CMDSTR_CHECK_DEVICE); 183cc290419Sopenharmony_ci vecNoConnectKeyCommand.push_back(CMDSTR_WAIT_FOR); 184cc290419Sopenharmony_ci vecNoConnectKeyCommand.push_back(CMDSTR_FORWARD_FPORT + " ls"); 185cc290419Sopenharmony_ci vecNoConnectKeyCommand.push_back(CMDSTR_FORWARD_FPORT + " rm"); 186cc290419Sopenharmony_ci for (string v : vecNoConnectKeyCommand) { 187cc290419Sopenharmony_ci if (!doCommand.compare(0, v.size(), v)) { 188cc290419Sopenharmony_ci isNoTargetCommand = true; 189cc290419Sopenharmony_ci break; 190cc290419Sopenharmony_ci } 191cc290419Sopenharmony_ci } 192cc290419Sopenharmony_ci if (isNoTargetCommand) { 193cc290419Sopenharmony_ci if (this->command != CMDSTR_WAIT_FOR) { 194cc290419Sopenharmony_ci key = ""; 195cc290419Sopenharmony_ci } 196cc290419Sopenharmony_ci } else { 197cc290419Sopenharmony_ci if (!preConnectKey.size()) { 198cc290419Sopenharmony_ci key = CMDSTR_CONNECT_ANY; 199cc290419Sopenharmony_ci } 200cc290419Sopenharmony_ci } 201cc290419Sopenharmony_ci return key; 202cc290419Sopenharmony_ci} 203cc290419Sopenharmony_ci 204cc290419Sopenharmony_ci#ifdef _WIN32 205cc290419Sopenharmony_cistatic void ReadFileThreadFunc(void* arg) 206cc290419Sopenharmony_ci{ 207cc290419Sopenharmony_ci char buffer[BUF_SIZE_DEFAULT] = { 0 }; 208cc290419Sopenharmony_ci DWORD bytesRead = 0; 209cc290419Sopenharmony_ci 210cc290419Sopenharmony_ci HANDLE* read = reinterpret_cast<HANDLE*>(arg); 211cc290419Sopenharmony_ci while (true) { 212cc290419Sopenharmony_ci if (!ReadFile(*read, buffer, BUF_SIZE_DEFAULT - 1, &bytesRead, NULL)) { 213cc290419Sopenharmony_ci break; 214cc290419Sopenharmony_ci } 215cc290419Sopenharmony_ci string str = std::to_string(bytesRead); 216cc290419Sopenharmony_ci const char* zero = "0"; 217cc290419Sopenharmony_ci if (!strncmp(zero, str.c_str(), strlen(zero))) { 218cc290419Sopenharmony_ci return; 219cc290419Sopenharmony_ci } 220cc290419Sopenharmony_ci printf("%s", buffer); 221cc290419Sopenharmony_ci if (memset_s(buffer, sizeof(buffer), 0, sizeof(buffer)) != EOK) { 222cc290419Sopenharmony_ci return; 223cc290419Sopenharmony_ci } 224cc290419Sopenharmony_ci } 225cc290419Sopenharmony_ci} 226cc290419Sopenharmony_ci 227cc290419Sopenharmony_cistring HdcClient::GetHilogPath() 228cc290419Sopenharmony_ci{ 229cc290419Sopenharmony_ci string hdcPath = Base::GetHdcAbsolutePath(); 230cc290419Sopenharmony_ci int index = hdcPath.find_last_of(Base::GetPathSep()); 231cc290419Sopenharmony_ci string exePath = hdcPath.substr(0, index) + Base::GetPathSep() + HILOG_NAME; 232cc290419Sopenharmony_ci 233cc290419Sopenharmony_ci return exePath; 234cc290419Sopenharmony_ci} 235cc290419Sopenharmony_ci 236cc290419Sopenharmony_civoid HdcClient::RunCommandWin32(const string& cmd) 237cc290419Sopenharmony_ci{ 238cc290419Sopenharmony_ci HANDLE hSubWrite; 239cc290419Sopenharmony_ci HANDLE hParentRead; 240cc290419Sopenharmony_ci HANDLE hParentWrite; 241cc290419Sopenharmony_ci HANDLE hSubRead; 242cc290419Sopenharmony_ci STARTUPINFO si; 243cc290419Sopenharmony_ci PROCESS_INFORMATION pi; 244cc290419Sopenharmony_ci SECURITY_ATTRIBUTES sa; 245cc290419Sopenharmony_ci sa.nLength = sizeof(SECURITY_ATTRIBUTES); 246cc290419Sopenharmony_ci sa.lpSecurityDescriptor = NULL; 247cc290419Sopenharmony_ci sa.bInheritHandle = true; 248cc290419Sopenharmony_ci 249cc290419Sopenharmony_ci if (!CreatePipe(&hParentRead, &hSubWrite, &sa, 0) || 250cc290419Sopenharmony_ci !CreatePipe(&hSubRead, &hParentWrite, &sa, 0) || 251cc290419Sopenharmony_ci !SetHandleInformation(hParentRead, HANDLE_FLAG_INHERIT, 0) || 252cc290419Sopenharmony_ci !SetHandleInformation(hParentWrite, HANDLE_FLAG_INHERIT, 0)) { 253cc290419Sopenharmony_ci return; 254cc290419Sopenharmony_ci } 255cc290419Sopenharmony_ci 256cc290419Sopenharmony_ci ZeroMemory(&si, sizeof(STARTUPINFO)); 257cc290419Sopenharmony_ci si.cb = sizeof(STARTUPINFO); 258cc290419Sopenharmony_ci GetStartupInfo(&si); 259cc290419Sopenharmony_ci si.hStdError = hSubWrite; 260cc290419Sopenharmony_ci si.hStdOutput = hSubWrite; 261cc290419Sopenharmony_ci si.hStdInput = hSubRead; 262cc290419Sopenharmony_ci si.wShowWindow = SW_HIDE; 263cc290419Sopenharmony_ci si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; 264cc290419Sopenharmony_ci 265cc290419Sopenharmony_ci const char *msg = cmd.c_str(); 266cc290419Sopenharmony_ci char buffer[BUF_SIZE_SMALL] = {0}; 267cc290419Sopenharmony_ci if (strcpy_s(buffer, sizeof(buffer), msg) != EOK) { 268cc290419Sopenharmony_ci return; 269cc290419Sopenharmony_ci } 270cc290419Sopenharmony_ci const string exePath = GetHilogPath(); 271cc290419Sopenharmony_ci if (!CreateProcess(_T(exePath.c_str()), _T(buffer), NULL, NULL, true, NULL, NULL, NULL, &si, &pi)) { 272cc290419Sopenharmony_ci WRITE_LOG(LOG_INFO, "create process failed, error:%d", GetLastError()); 273cc290419Sopenharmony_ci return; 274cc290419Sopenharmony_ci } 275cc290419Sopenharmony_ci auto thread = std::thread([&hParentRead]() { 276cc290419Sopenharmony_ci ReadFileThreadFunc(&hParentRead); 277cc290419Sopenharmony_ci }); 278cc290419Sopenharmony_ci WaitForSingleObject(pi.hProcess, INFINITE); 279cc290419Sopenharmony_ci CloseHandle(hSubWrite); 280cc290419Sopenharmony_ci CloseHandle(pi.hProcess); 281cc290419Sopenharmony_ci CloseHandle(pi.hThread); 282cc290419Sopenharmony_ci thread.join(); 283cc290419Sopenharmony_ci CloseHandle(hParentRead); 284cc290419Sopenharmony_ci CloseHandle(hParentWrite); 285cc290419Sopenharmony_ci CloseHandle(hSubRead); 286cc290419Sopenharmony_ci} 287cc290419Sopenharmony_ci#else 288cc290419Sopenharmony_civoid HdcClient::RunCommand(const string& cmd) 289cc290419Sopenharmony_ci{ 290cc290419Sopenharmony_ci FILE *procFileInfo = nullptr; 291cc290419Sopenharmony_ci procFileInfo = popen(cmd.c_str(), "r"); 292cc290419Sopenharmony_ci if (procFileInfo == nullptr) { 293cc290419Sopenharmony_ci perror("popen execute failed"); 294cc290419Sopenharmony_ci return; 295cc290419Sopenharmony_ci } 296cc290419Sopenharmony_ci char resultBufShell[BUF_SIZE_DEFAULT] = {0}; 297cc290419Sopenharmony_ci while (fgets(resultBufShell, sizeof(resultBufShell), procFileInfo) != nullptr) { 298cc290419Sopenharmony_ci printf("%s", resultBufShell); 299cc290419Sopenharmony_ci if (memset_s(resultBufShell, sizeof(resultBufShell), 0, sizeof(resultBufShell)) != EOK) { 300cc290419Sopenharmony_ci break; 301cc290419Sopenharmony_ci } 302cc290419Sopenharmony_ci } 303cc290419Sopenharmony_ci pclose(procFileInfo); 304cc290419Sopenharmony_ci} 305cc290419Sopenharmony_ci#endif 306cc290419Sopenharmony_ci 307cc290419Sopenharmony_civoid HdcClient::RunExecuteCommand(const string& cmd) 308cc290419Sopenharmony_ci{ 309cc290419Sopenharmony_ci#ifdef _WIN32 310cc290419Sopenharmony_ci RunCommandWin32(cmd); 311cc290419Sopenharmony_ci#else 312cc290419Sopenharmony_ci RunCommand(cmd); 313cc290419Sopenharmony_ci#endif 314cc290419Sopenharmony_ci} 315cc290419Sopenharmony_ci 316cc290419Sopenharmony_cibool IsCaptureCommand(const string& cmd) 317cc290419Sopenharmony_ci{ 318cc290419Sopenharmony_ci int index = string(CMDSTR_HILOG).length(); 319cc290419Sopenharmony_ci int length = cmd.length(); 320cc290419Sopenharmony_ci const string captureOption = "parse"; 321cc290419Sopenharmony_ci while (index < length) { 322cc290419Sopenharmony_ci if (cmd[index] == ' ') { 323cc290419Sopenharmony_ci index++; 324cc290419Sopenharmony_ci continue; 325cc290419Sopenharmony_ci } 326cc290419Sopenharmony_ci if (!strncmp(cmd.c_str() + index, captureOption.c_str(), captureOption.size())) { 327cc290419Sopenharmony_ci return true; 328cc290419Sopenharmony_ci } else { 329cc290419Sopenharmony_ci return false; 330cc290419Sopenharmony_ci } 331cc290419Sopenharmony_ci } 332cc290419Sopenharmony_ci return false; 333cc290419Sopenharmony_ci} 334cc290419Sopenharmony_ci 335cc290419Sopenharmony_ciint HdcClient::ExecuteCommand(const string &commandIn) 336cc290419Sopenharmony_ci{ 337cc290419Sopenharmony_ci char ip[BUF_SIZE_TINY] = ""; 338cc290419Sopenharmony_ci uint16_t port = 0; 339cc290419Sopenharmony_ci int ret = Base::ConnectKey2IPPort(channelHostPort.c_str(), ip, &port, sizeof(ip)); 340cc290419Sopenharmony_ci if (ret < 0) { 341cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "ConnectKey2IPPort %s failed with %d", 342cc290419Sopenharmony_ci channelHostPort.c_str(), ret); 343cc290419Sopenharmony_ci return -1; 344cc290419Sopenharmony_ci } 345cc290419Sopenharmony_ci 346cc290419Sopenharmony_ci if (!strncmp(commandIn.c_str(), CMDSTR_HILOG.c_str(), CMDSTR_HILOG.size()) && 347cc290419Sopenharmony_ci IsCaptureCommand(commandIn)) { 348cc290419Sopenharmony_ci RunExecuteCommand(commandIn); 349cc290419Sopenharmony_ci return 0; 350cc290419Sopenharmony_ci } 351cc290419Sopenharmony_ci 352cc290419Sopenharmony_ci if (!strncmp(commandIn.c_str(), CMDSTR_FILE_SEND.c_str(), CMDSTR_FILE_SEND.size()) || 353cc290419Sopenharmony_ci !strncmp(commandIn.c_str(), CMDSTR_FILE_RECV.c_str(), CMDSTR_FILE_RECV.size())) { 354cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "Set file send mode"); 355cc290419Sopenharmony_ci channel->remote = RemoteType::REMOTE_FILE; 356cc290419Sopenharmony_ci } 357cc290419Sopenharmony_ci if (!strncmp(commandIn.c_str(), CMDSTR_APP_INSTALL.c_str(), CMDSTR_APP_INSTALL.size())) { 358cc290419Sopenharmony_ci channel->remote = RemoteType::REMOTE_APP; 359cc290419Sopenharmony_ci } 360cc290419Sopenharmony_ci command = commandIn; 361cc290419Sopenharmony_ci connectKey = AutoConnectKey(command, connectKey); 362cc290419Sopenharmony_ci ConnectServerForClient(ip, port); 363cc290419Sopenharmony_ci uv_timer_init(loopMain, &waitTimeDoCmd); 364cc290419Sopenharmony_ci waitTimeDoCmd.data = this; 365cc290419Sopenharmony_ci uv_timer_start(&waitTimeDoCmd, CommandWorker, UV_START_TIMEOUT, UV_START_REPEAT); 366cc290419Sopenharmony_ci WorkerPendding(); 367cc290419Sopenharmony_ci return 0; 368cc290419Sopenharmony_ci} 369cc290419Sopenharmony_ci 370cc290419Sopenharmony_ciint HdcClient::Initial(const string &connectKeyIn) 371cc290419Sopenharmony_ci{ 372cc290419Sopenharmony_ci connectKey = connectKeyIn; 373cc290419Sopenharmony_ci if (!channelHostPort.size() || !channelHost.size() || !channelPort) { 374cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "Listen string initial failed"); 375cc290419Sopenharmony_ci return ERR_PARM_FAIL; 376cc290419Sopenharmony_ci } 377cc290419Sopenharmony_ci return 0; 378cc290419Sopenharmony_ci} 379cc290419Sopenharmony_ci 380cc290419Sopenharmony_ciint HdcClient::ConnectServerForClient(const char *ip, uint16_t port) 381cc290419Sopenharmony_ci{ 382cc290419Sopenharmony_ci if (uv_is_closing((const uv_handle_t *)&channel->hWorkTCP)) { 383cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "ConnectServerForClient uv_is_closing"); 384cc290419Sopenharmony_ci return ERR_SOCKET_FAIL; 385cc290419Sopenharmony_ci } 386cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "Try to connect %s:%d", ip, port); 387cc290419Sopenharmony_ci uv_connect_t *conn = new(std::nothrow) uv_connect_t(); 388cc290419Sopenharmony_ci if (conn == nullptr) { 389cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "ConnectServerForClient new conn failed"); 390cc290419Sopenharmony_ci return ERR_GENERIC; 391cc290419Sopenharmony_ci } 392cc290419Sopenharmony_ci conn->data = this; 393cc290419Sopenharmony_ci tcpConnectRetryCount = 0; 394cc290419Sopenharmony_ci uv_timer_init(loopMain, &retryTcpConnTimer); 395cc290419Sopenharmony_ci retryTcpConnTimer.data = this; 396cc290419Sopenharmony_ci if (strchr(ip, '.')) { 397cc290419Sopenharmony_ci isIpV4 = true; 398cc290419Sopenharmony_ci std::string s = ip; 399cc290419Sopenharmony_ci size_t index = s.find(IPV4_MAPPING_PREFIX); 400cc290419Sopenharmony_ci size_t size = IPV4_MAPPING_PREFIX.size(); 401cc290419Sopenharmony_ci if (index != std::string::npos) { 402cc290419Sopenharmony_ci s = s.substr(index + size); 403cc290419Sopenharmony_ci } 404cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "ConnectServerForClient ipv4 %s:%d", s.c_str(), port); 405cc290419Sopenharmony_ci uv_ip4_addr(s.c_str(), port, &destv4); 406cc290419Sopenharmony_ci uv_tcp_connect(conn, (uv_tcp_t *)&channel->hWorkTCP, (const struct sockaddr *)&destv4, Connect); 407cc290419Sopenharmony_ci } else { 408cc290419Sopenharmony_ci isIpV4 = false; 409cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "ConnectServerForClient ipv6 %s:%d", ip, port); 410cc290419Sopenharmony_ci uv_ip6_addr(ip, port, &dest); 411cc290419Sopenharmony_ci uv_tcp_connect(conn, (uv_tcp_t *)&channel->hWorkTCP, (const struct sockaddr *)&dest, Connect); 412cc290419Sopenharmony_ci } 413cc290419Sopenharmony_ci return 0; 414cc290419Sopenharmony_ci} 415cc290419Sopenharmony_ci 416cc290419Sopenharmony_civoid HdcClient::CommandWorker(uv_timer_t *handle) 417cc290419Sopenharmony_ci{ 418cc290419Sopenharmony_ci const uint16_t maxWaitRetry = 1200; // client socket try 12s 419cc290419Sopenharmony_ci HdcClient *thisClass = (HdcClient *)handle->data; 420cc290419Sopenharmony_ci if (++thisClass->debugRetryCount > maxWaitRetry) { 421cc290419Sopenharmony_ci uv_timer_stop(handle); 422cc290419Sopenharmony_ci uv_stop(thisClass->loopMain); 423cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "Connect server failed"); 424cc290419Sopenharmony_ci fprintf(stderr, "Connect server failed\n"); 425cc290419Sopenharmony_ci return; 426cc290419Sopenharmony_ci } 427cc290419Sopenharmony_ci if (!thisClass->channel->handshakeOK) { 428cc290419Sopenharmony_ci return; 429cc290419Sopenharmony_ci } 430cc290419Sopenharmony_ci uv_timer_stop(handle); 431cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "Connect server successful"); 432cc290419Sopenharmony_ci bool closeInput = false; 433cc290419Sopenharmony_ci if (!HostUpdater::ConfirmCommand(thisClass->command, closeInput)) { 434cc290419Sopenharmony_ci uv_timer_stop(handle); 435cc290419Sopenharmony_ci uv_stop(thisClass->loopMain); 436cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "Cmd \'%s\' has been canceld", thisClass->command.c_str()); 437cc290419Sopenharmony_ci return; 438cc290419Sopenharmony_ci } 439cc290419Sopenharmony_ci while (closeInput) { 440cc290419Sopenharmony_ci#ifndef _WIN32 441cc290419Sopenharmony_ci if (tcgetattr(STDIN_FILENO, &thisClass->terminalState)) { 442cc290419Sopenharmony_ci break; 443cc290419Sopenharmony_ci } 444cc290419Sopenharmony_ci termios tio; 445cc290419Sopenharmony_ci if (tcgetattr(STDIN_FILENO, &tio)) { 446cc290419Sopenharmony_ci break; 447cc290419Sopenharmony_ci } 448cc290419Sopenharmony_ci cfmakeraw(&tio); 449cc290419Sopenharmony_ci tio.c_cc[VTIME] = 0; 450cc290419Sopenharmony_ci tio.c_cc[VMIN] = 1; 451cc290419Sopenharmony_ci tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio); 452cc290419Sopenharmony_ci g_terminalStateChange = true; 453cc290419Sopenharmony_ci#endif 454cc290419Sopenharmony_ci break; 455cc290419Sopenharmony_ci } 456cc290419Sopenharmony_ci thisClass->Send(thisClass->channel->channelId, 457cc290419Sopenharmony_ci const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(thisClass->command.c_str())), 458cc290419Sopenharmony_ci thisClass->command.size() + 1); 459cc290419Sopenharmony_ci} 460cc290419Sopenharmony_ci 461cc290419Sopenharmony_civoid HdcClient::AllocStdbuf(uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf) 462cc290419Sopenharmony_ci{ 463cc290419Sopenharmony_ci if (sizeWanted <= 0) { 464cc290419Sopenharmony_ci return; 465cc290419Sopenharmony_ci } 466cc290419Sopenharmony_ci HChannel context = (HChannel)handle->data; 467cc290419Sopenharmony_ci int availSize = strlen(context->bufStd); 468cc290419Sopenharmony_ci buf->base = (char *)context->bufStd + availSize; 469cc290419Sopenharmony_ci buf->len = sizeof(context->bufStd) - availSize - 2; // reserve 2bytes 470cc290419Sopenharmony_ci} 471cc290419Sopenharmony_ci 472cc290419Sopenharmony_civoid HdcClient::ReadStd(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) 473cc290419Sopenharmony_ci{ 474cc290419Sopenharmony_ci HChannel hChannel = (HChannel)stream->data; 475cc290419Sopenharmony_ci HdcClient *thisClass = (HdcClient *)hChannel->clsChannel; 476cc290419Sopenharmony_ci char *cmd = hChannel->bufStd; 477cc290419Sopenharmony_ci if (nread <= 0) { 478cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "ReadStd error nread:%zd", nread); 479cc290419Sopenharmony_ci return; // error 480cc290419Sopenharmony_ci } 481cc290419Sopenharmony_ci thisClass->Send(hChannel->channelId, reinterpret_cast<uint8_t *>(cmd), strlen(cmd)); 482cc290419Sopenharmony_ci Base::ZeroArray(hChannel->bufStd); 483cc290419Sopenharmony_ci} 484cc290419Sopenharmony_ci 485cc290419Sopenharmony_civoid HdcClient::ModifyTty(bool setOrRestore, uv_tty_t *tty) 486cc290419Sopenharmony_ci{ 487cc290419Sopenharmony_ci if (setOrRestore) { 488cc290419Sopenharmony_ci#ifdef _WIN32 489cc290419Sopenharmony_ci uv_tty_set_mode(tty, UV_TTY_MODE_RAW); 490cc290419Sopenharmony_ci#else 491cc290419Sopenharmony_ci if (tcgetattr(STDIN_FILENO, &terminalState)) { 492cc290419Sopenharmony_ci return; 493cc290419Sopenharmony_ci } 494cc290419Sopenharmony_ci termios tio; 495cc290419Sopenharmony_ci if (tcgetattr(STDIN_FILENO, &tio)) { 496cc290419Sopenharmony_ci return; 497cc290419Sopenharmony_ci } 498cc290419Sopenharmony_ci cfmakeraw(&tio); 499cc290419Sopenharmony_ci tio.c_cc[VTIME] = 0; 500cc290419Sopenharmony_ci tio.c_cc[VMIN] = 1; 501cc290419Sopenharmony_ci tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio); 502cc290419Sopenharmony_ci#endif 503cc290419Sopenharmony_ci } else { 504cc290419Sopenharmony_ci#ifndef _WIN32 505cc290419Sopenharmony_ci tcsetattr(STDIN_FILENO, TCSAFLUSH, &terminalState); 506cc290419Sopenharmony_ci#endif 507cc290419Sopenharmony_ci } 508cc290419Sopenharmony_ci} 509cc290419Sopenharmony_ci 510cc290419Sopenharmony_civoid HdcClient::BindLocalStd(HChannel hChannel) 511cc290419Sopenharmony_ci{ 512cc290419Sopenharmony_ci if (command == CMDSTR_SHELL) { 513cc290419Sopenharmony_ci bShellInteractive = true; 514cc290419Sopenharmony_ci } 515cc290419Sopenharmony_ci if (bShellInteractive && uv_guess_handle(STDIN_FILENO) != UV_TTY) { 516cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "Not support stdio TTY mode"); 517cc290419Sopenharmony_ci return; 518cc290419Sopenharmony_ci } 519cc290419Sopenharmony_ci 520cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "setup stdio TTY mode"); 521cc290419Sopenharmony_ci if (uv_tty_init(loopMain, &hChannel->stdoutTty, STDOUT_FILENO, 0) 522cc290419Sopenharmony_ci || uv_tty_init(loopMain, &hChannel->stdinTty, STDIN_FILENO, 1)) { 523cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "uv_tty_init failed"); 524cc290419Sopenharmony_ci return; 525cc290419Sopenharmony_ci } 526cc290419Sopenharmony_ci hChannel->stdoutTty.data = hChannel; 527cc290419Sopenharmony_ci ++hChannel->uvHandleRef; 528cc290419Sopenharmony_ci hChannel->stdinTty.data = hChannel; 529cc290419Sopenharmony_ci ++hChannel->uvHandleRef; 530cc290419Sopenharmony_ci if (bShellInteractive) { 531cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "uv_tty_init uv_tty_set_mode"); 532cc290419Sopenharmony_ci ModifyTty(true, &hChannel->stdinTty); 533cc290419Sopenharmony_ci uv_read_start((uv_stream_t *)&hChannel->stdinTty, AllocStdbuf, ReadStd); 534cc290419Sopenharmony_ci } 535cc290419Sopenharmony_ci} 536cc290419Sopenharmony_ci 537cc290419Sopenharmony_civoid HdcClient::Connect(uv_connect_t *connection, int status) 538cc290419Sopenharmony_ci{ 539cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "Enter Connect, status:%d", status); 540cc290419Sopenharmony_ci HdcClient *thisClass = (HdcClient *)connection->data; 541cc290419Sopenharmony_ci delete connection; 542cc290419Sopenharmony_ci HChannel hChannel = reinterpret_cast<HChannel>(thisClass->channel); 543cc290419Sopenharmony_ci if (uv_is_closing((const uv_handle_t *)&hChannel->hWorkTCP)) { 544cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "uv_is_closing..."); 545cc290419Sopenharmony_ci thisClass->FreeChannel(hChannel->channelId); 546cc290419Sopenharmony_ci return; 547cc290419Sopenharmony_ci } 548cc290419Sopenharmony_ci 549cc290419Sopenharmony_ci // connect success 550cc290419Sopenharmony_ci if (status == 0) { 551cc290419Sopenharmony_ci thisClass->BindLocalStd(hChannel); 552cc290419Sopenharmony_ci Base::SetTcpOptions((uv_tcp_t *)&hChannel->hWorkTCP); 553cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "uv_read_start"); 554cc290419Sopenharmony_ci uv_read_start((uv_stream_t *)&hChannel->hWorkTCP, AllocCallback, ReadStream); 555cc290419Sopenharmony_ci return; 556cc290419Sopenharmony_ci } 557cc290419Sopenharmony_ci 558cc290419Sopenharmony_ci // connect failed, start timer and retry 559cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "retry count:%d", thisClass->tcpConnectRetryCount); 560cc290419Sopenharmony_ci if (thisClass->tcpConnectRetryCount >= TCP_CONNECT_MAX_RETRY_COUNT) { 561cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "stop retry for connect"); 562cc290419Sopenharmony_ci thisClass->FreeChannel(hChannel->channelId); 563cc290419Sopenharmony_ci return; 564cc290419Sopenharmony_ci } 565cc290419Sopenharmony_ci thisClass->tcpConnectRetryCount++; 566cc290419Sopenharmony_ci uv_timer_start(&(thisClass->retryTcpConnTimer), thisClass->RetryTcpConnectWorker, TCP_CONNECT_RETRY_TIME_MS, 0); 567cc290419Sopenharmony_ci} 568cc290419Sopenharmony_ci 569cc290419Sopenharmony_civoid HdcClient::RetryTcpConnectWorker(uv_timer_t *handle) 570cc290419Sopenharmony_ci{ 571cc290419Sopenharmony_ci HdcClient *thisClass = (HdcClient *)handle->data; 572cc290419Sopenharmony_ci HChannel hChannel = reinterpret_cast<HChannel>(thisClass->channel); 573cc290419Sopenharmony_ci uv_connect_t *connection = new(std::nothrow) uv_connect_t(); 574cc290419Sopenharmony_ci if (connection == nullptr) { 575cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "RetryTcpConnectWorker new conn failed"); 576cc290419Sopenharmony_ci thisClass->FreeChannel(hChannel->channelId); 577cc290419Sopenharmony_ci return; 578cc290419Sopenharmony_ci } 579cc290419Sopenharmony_ci connection->data = thisClass; 580cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "RetryTcpConnectWorker start tcp connect"); 581cc290419Sopenharmony_ci if (thisClass->isIpV4) { 582cc290419Sopenharmony_ci uv_tcp_connect(connection, &(thisClass->channel->hWorkTCP), 583cc290419Sopenharmony_ci (const struct sockaddr *)&(thisClass->destv4), thisClass->Connect); 584cc290419Sopenharmony_ci } else { 585cc290419Sopenharmony_ci uv_tcp_connect(connection, &(thisClass->channel->hWorkTCP), 586cc290419Sopenharmony_ci (const struct sockaddr *)&(thisClass->dest), thisClass->Connect); 587cc290419Sopenharmony_ci } 588cc290419Sopenharmony_ci} 589cc290419Sopenharmony_ci 590cc290419Sopenharmony_ciint HdcClient::PreHandshake(HChannel hChannel, const uint8_t *buf) 591cc290419Sopenharmony_ci{ 592cc290419Sopenharmony_ci ChannelHandShake *hShake = reinterpret_cast<ChannelHandShake *>(const_cast<uint8_t *>(buf)); 593cc290419Sopenharmony_ci if (strncmp(hShake->banner, HANDSHAKE_MESSAGE.c_str(), HANDSHAKE_MESSAGE.size())) { 594cc290419Sopenharmony_ci hChannel->availTailIndex = 0; 595cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "Channel Hello failed"); 596cc290419Sopenharmony_ci return ERR_BUF_CHECK; 597cc290419Sopenharmony_ci } 598cc290419Sopenharmony_ci hChannel->isStableBuf = (hShake->banner[BANNER_FEATURE_TAG_OFFSET] != HUGE_BUF_TAG); 599cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "Channel PreHandshake isStableBuf:%d", hChannel->isStableBuf); 600cc290419Sopenharmony_ci if (this->command == CMDSTR_WAIT_FOR && !connectKey.empty()) { 601cc290419Sopenharmony_ci hShake->banner[WAIT_TAG_OFFSET] = WAIT_DEVICE_TAG; 602cc290419Sopenharmony_ci } 603cc290419Sopenharmony_ci // sync remote session id to local 604cc290419Sopenharmony_ci uint32_t unOld = hChannel->channelId; 605cc290419Sopenharmony_ci hChannel->channelId = ntohl(hShake->channelId); 606cc290419Sopenharmony_ci AdminChannel(OP_UPDATE, unOld, hChannel); 607cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "Client channel handshake finished, use connectkey:%s", 608cc290419Sopenharmony_ci Hdc::MaskString(connectKey).c_str()); 609cc290419Sopenharmony_ci // send config 610cc290419Sopenharmony_ci // channel handshake step2 611cc290419Sopenharmony_ci if (memset_s(hShake->connectKey, sizeof(hShake->connectKey), 0, sizeof(hShake->connectKey)) != EOK 612cc290419Sopenharmony_ci || memcpy_s(hShake->connectKey, sizeof(hShake->connectKey), connectKey.c_str(), connectKey.size()) != EOK) { 613cc290419Sopenharmony_ci hChannel->availTailIndex = 0; 614cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "Channel Hello failed"); 615cc290419Sopenharmony_ci return ERR_BUF_COPY; 616cc290419Sopenharmony_ci } 617cc290419Sopenharmony_ci 618cc290419Sopenharmony_ci#ifdef HDC_VERSION_CHECK 619cc290419Sopenharmony_ci // add check version 620cc290419Sopenharmony_ci if (!isCheckVersionCmd) { // do not check version cause user want to get server version 621cc290419Sopenharmony_ci string clientVer = Base::GetVersion() + HDC_MSG_HASH; 622cc290419Sopenharmony_ci string serverVer(hShake->version); 623cc290419Sopenharmony_ci 624cc290419Sopenharmony_ci if (clientVer != serverVer) { 625cc290419Sopenharmony_ci serverVer = serverVer.substr(0, Base::GetVersion().size()); 626cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "Client version:%s, server version:%s", clientVer.c_str(), serverVer.c_str()); 627cc290419Sopenharmony_ci hChannel->availTailIndex = 0; 628cc290419Sopenharmony_ci return ERR_CHECK_VERSION; 629cc290419Sopenharmony_ci } 630cc290419Sopenharmony_ci } 631cc290419Sopenharmony_ci Send(hChannel->channelId, reinterpret_cast<uint8_t *>(hShake), sizeof(ChannelHandShake)); 632cc290419Sopenharmony_ci#else 633cc290419Sopenharmony_ci // do not send version message if check feature disable 634cc290419Sopenharmony_ci Send(hChannel->channelId, reinterpret_cast<uint8_t *>(hShake), offsetof(struct ChannelHandShake, version)); 635cc290419Sopenharmony_ci#endif 636cc290419Sopenharmony_ci hChannel->handshakeOK = true; 637cc290419Sopenharmony_ci#ifdef HDC_CHANNEL_KEEP_ALIVE 638cc290419Sopenharmony_ci // Evaluation method, non long-term support 639cc290419Sopenharmony_ci Send(hChannel->channelId, 640cc290419Sopenharmony_ci reinterpret_cast<uint8_t *>(const_cast<char*>(CMDSTR_INNER_ENABLE_KEEPALIVE.c_str())), 641cc290419Sopenharmony_ci CMDSTR_INNER_ENABLE_KEEPALIVE.size()); 642cc290419Sopenharmony_ci#endif 643cc290419Sopenharmony_ci return RET_SUCCESS; 644cc290419Sopenharmony_ci} 645cc290419Sopenharmony_ci 646cc290419Sopenharmony_ci// read serverForClient(server)TCP data 647cc290419Sopenharmony_ciint HdcClient::ReadChannel(HChannel hChannel, uint8_t *buf, const int bytesIO) 648cc290419Sopenharmony_ci{ 649cc290419Sopenharmony_ci if (!hChannel->handshakeOK) { 650cc290419Sopenharmony_ci return PreHandshake(hChannel, buf); 651cc290419Sopenharmony_ci } 652cc290419Sopenharmony_ci#ifdef UNIT_TEST 653cc290419Sopenharmony_ci // Do not output to console when the unit test 654cc290419Sopenharmony_ci return 0; 655cc290419Sopenharmony_ci#endif 656cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "Client ReadChannel :%d", bytesIO); 657cc290419Sopenharmony_ci 658cc290419Sopenharmony_ci uint16_t cmd = 0; 659cc290419Sopenharmony_ci bool bOffset = false; 660cc290419Sopenharmony_ci if (bytesIO >= static_cast<int>(sizeof(uint16_t))) { 661cc290419Sopenharmony_ci cmd = *reinterpret_cast<uint16_t *>(buf); 662cc290419Sopenharmony_ci bOffset = IsOffset(cmd); 663cc290419Sopenharmony_ci } 664cc290419Sopenharmony_ci if (cmd == CMD_CHECK_SERVER && isCheckVersionCmd) { 665cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "recieve CMD_CHECK_VERSION command"); 666cc290419Sopenharmony_ci string version(reinterpret_cast<char *>(buf + sizeof(uint16_t)), bytesIO - sizeof(uint16_t)); 667cc290419Sopenharmony_ci fprintf(stdout, "Client version:%s, server version:%s\n", Base::GetVersion().c_str(), version.c_str()); 668cc290419Sopenharmony_ci fflush(stdout); 669cc290419Sopenharmony_ci return 0; 670cc290419Sopenharmony_ci } 671cc290419Sopenharmony_ci if (hChannel->remote > RemoteType::REMOTE_NONE && bOffset) { 672cc290419Sopenharmony_ci // file command 673cc290419Sopenharmony_ci if (hChannel->remote == RemoteType::REMOTE_FILE) { 674cc290419Sopenharmony_ci if (fileTask == nullptr) { 675cc290419Sopenharmony_ci HTaskInfo hTaskInfo = GetRemoteTaskInfo(hChannel); 676cc290419Sopenharmony_ci hTaskInfo->masterSlave = (cmd == CMD_FILE_INIT); 677cc290419Sopenharmony_ci fileTask = std::make_unique<HdcFile>(hTaskInfo); 678cc290419Sopenharmony_ci } 679cc290419Sopenharmony_ci if (!fileTask->CommandDispatch(cmd, buf + sizeof(uint16_t), bytesIO - sizeof(uint16_t))) { 680cc290419Sopenharmony_ci fileTask->TaskFinish(); 681cc290419Sopenharmony_ci } 682cc290419Sopenharmony_ci } 683cc290419Sopenharmony_ci // app command 684cc290419Sopenharmony_ci if (hChannel->remote == RemoteType::REMOTE_APP) { 685cc290419Sopenharmony_ci if (appTask == nullptr) { 686cc290419Sopenharmony_ci HTaskInfo hTaskInfo = GetRemoteTaskInfo(hChannel); 687cc290419Sopenharmony_ci hTaskInfo->masterSlave = (cmd == CMD_APP_INIT); 688cc290419Sopenharmony_ci appTask = std::make_unique<HdcHostApp>(hTaskInfo); 689cc290419Sopenharmony_ci } 690cc290419Sopenharmony_ci if (!appTask->CommandDispatch(cmd, buf + sizeof(uint16_t), bytesIO - sizeof(uint16_t))) { 691cc290419Sopenharmony_ci appTask->TaskFinish(); 692cc290419Sopenharmony_ci } 693cc290419Sopenharmony_ci } 694cc290419Sopenharmony_ci return 0; 695cc290419Sopenharmony_ci } 696cc290419Sopenharmony_ci 697cc290419Sopenharmony_ci string s(reinterpret_cast<char *>(buf), bytesIO); 698cc290419Sopenharmony_ci if (WaitFor(s)) { 699cc290419Sopenharmony_ci return 0; 700cc290419Sopenharmony_ci } 701cc290419Sopenharmony_ci s = ListTargetsAll(s); 702cc290419Sopenharmony_ci if (g_show) { 703cc290419Sopenharmony_ci#ifdef _WIN32 704cc290419Sopenharmony_ci fprintf(stdout, "%s", s.c_str()); 705cc290419Sopenharmony_ci fflush(stdout); 706cc290419Sopenharmony_ci#else 707cc290419Sopenharmony_ci constexpr int len = 512; 708cc290419Sopenharmony_ci int size = s.size() / len; 709cc290419Sopenharmony_ci int left = s.size() % len; 710cc290419Sopenharmony_ci for (int i = 0; i <= size; i++) { 711cc290419Sopenharmony_ci int cnt = len; 712cc290419Sopenharmony_ci const char *p = reinterpret_cast<char *>(buf) + i * cnt; 713cc290419Sopenharmony_ci if (i == size) { 714cc290419Sopenharmony_ci cnt = left; 715cc290419Sopenharmony_ci } 716cc290419Sopenharmony_ci fprintf(stdout, "%.*s", cnt, p); 717cc290419Sopenharmony_ci fflush(stdout); 718cc290419Sopenharmony_ci std::this_thread::sleep_for(std::chrono::milliseconds(1)); 719cc290419Sopenharmony_ci } 720cc290419Sopenharmony_ci#endif 721cc290419Sopenharmony_ci } 722cc290419Sopenharmony_ci return 0; 723cc290419Sopenharmony_ci} 724cc290419Sopenharmony_ci 725cc290419Sopenharmony_cibool HdcClient::WaitFor(const string &str) 726cc290419Sopenharmony_ci{ 727cc290419Sopenharmony_ci bool wait = false; 728cc290419Sopenharmony_ci if (!strncmp(this->command.c_str(), CMDSTR_WAIT_FOR.c_str(), CMDSTR_WAIT_FOR.size())) { 729cc290419Sopenharmony_ci const string waitFor = "[Fail]No any connected target"; 730cc290419Sopenharmony_ci if (!strncmp(str.c_str(), waitFor.c_str(), waitFor.size())) { 731cc290419Sopenharmony_ci Send(this->channel->channelId, reinterpret_cast<uint8_t *>(const_cast<char *>(this->command.c_str())), 732cc290419Sopenharmony_ci this->command.size() + 1); 733cc290419Sopenharmony_ci constexpr int timeout = 1; 734cc290419Sopenharmony_ci std::this_thread::sleep_for(std::chrono::seconds(timeout)); 735cc290419Sopenharmony_ci wait = true; 736cc290419Sopenharmony_ci } else { 737cc290419Sopenharmony_ci _exit(0); 738cc290419Sopenharmony_ci } 739cc290419Sopenharmony_ci } 740cc290419Sopenharmony_ci return wait; 741cc290419Sopenharmony_ci} 742cc290419Sopenharmony_ci 743cc290419Sopenharmony_cistring HdcClient::ListTargetsAll(const string &str) 744cc290419Sopenharmony_ci{ 745cc290419Sopenharmony_ci string all = str; 746cc290419Sopenharmony_ci const string lists = "list targets -v"; 747cc290419Sopenharmony_ci if (!strncmp(this->command.c_str(), lists.c_str(), lists.size())) { 748cc290419Sopenharmony_ci UpdateList(str); 749cc290419Sopenharmony_ci all = Base::ReplaceAll(all, "\n", "\thdc\n"); 750cc290419Sopenharmony_ci } else if (!strncmp(this->command.c_str(), CMDSTR_LIST_TARGETS.c_str(), CMDSTR_LIST_TARGETS.size())) { 751cc290419Sopenharmony_ci UpdateList(str); 752cc290419Sopenharmony_ci } 753cc290419Sopenharmony_ci if (!strncmp(this->command.c_str(), CMDSTR_LIST_TARGETS.c_str(), CMDSTR_LIST_TARGETS.size())) { 754cc290419Sopenharmony_ci if (g_lists.size() > 0 && !strncmp(str.c_str(), EMPTY_ECHO.c_str(), EMPTY_ECHO.size())) { 755cc290419Sopenharmony_ci all = ""; 756cc290419Sopenharmony_ci } 757cc290419Sopenharmony_ci } 758cc290419Sopenharmony_ci return all; 759cc290419Sopenharmony_ci} 760cc290419Sopenharmony_ci 761cc290419Sopenharmony_civoid HdcClient::UpdateList(const string &str) 762cc290419Sopenharmony_ci{ 763cc290419Sopenharmony_ci if (!strncmp(str.c_str(), EMPTY_ECHO.c_str(), EMPTY_ECHO.size())) { 764cc290419Sopenharmony_ci return; 765cc290419Sopenharmony_ci } 766cc290419Sopenharmony_ci vector<string> devs; 767cc290419Sopenharmony_ci Base::SplitString(str, "\n", devs); 768cc290419Sopenharmony_ci for (size_t i = 0; i < devs.size(); i++) { 769cc290419Sopenharmony_ci string::size_type pos = devs[i].find("\t"); 770cc290419Sopenharmony_ci if (pos != string::npos) { 771cc290419Sopenharmony_ci string key = devs[i].substr(0, pos); 772cc290419Sopenharmony_ci g_lists[key] = "hdc"; 773cc290419Sopenharmony_ci } else { 774cc290419Sopenharmony_ci string key = devs[i]; 775cc290419Sopenharmony_ci g_lists[key] = "hdc"; 776cc290419Sopenharmony_ci } 777cc290419Sopenharmony_ci } 778cc290419Sopenharmony_ci} 779cc290419Sopenharmony_ci 780cc290419Sopenharmony_cibool HdcClient::IsOffset(uint16_t cmd) 781cc290419Sopenharmony_ci{ 782cc290419Sopenharmony_ci return (cmd == CMD_CHECK_SERVER) || 783cc290419Sopenharmony_ci (cmd == CMD_FILE_INIT) || 784cc290419Sopenharmony_ci (cmd == CMD_FILE_CHECK) || 785cc290419Sopenharmony_ci (cmd == CMD_FILE_BEGIN) || 786cc290419Sopenharmony_ci (cmd == CMD_FILE_DATA) || 787cc290419Sopenharmony_ci (cmd == CMD_FILE_FINISH) || 788cc290419Sopenharmony_ci (cmd == CMD_FILE_MODE) || 789cc290419Sopenharmony_ci (cmd == CMD_DIR_MODE) || 790cc290419Sopenharmony_ci (cmd == CMD_APP_INIT) || 791cc290419Sopenharmony_ci (cmd == CMD_APP_CHECK) || 792cc290419Sopenharmony_ci (cmd == CMD_APP_BEGIN) || 793cc290419Sopenharmony_ci (cmd == CMD_APP_DATA) || 794cc290419Sopenharmony_ci (cmd == CMD_APP_FINISH); 795cc290419Sopenharmony_ci} 796cc290419Sopenharmony_ci 797cc290419Sopenharmony_ciHTaskInfo HdcClient::GetRemoteTaskInfo(HChannel hChannel) 798cc290419Sopenharmony_ci{ 799cc290419Sopenharmony_ci HTaskInfo hTaskInfo = new TaskInformation(); 800cc290419Sopenharmony_ci hTaskInfo->channelId = hChannel->channelId; 801cc290419Sopenharmony_ci hTaskInfo->runLoop = loopMain; 802cc290419Sopenharmony_ci hTaskInfo->serverOrDaemon = true; 803cc290419Sopenharmony_ci hTaskInfo->channelTask = true; 804cc290419Sopenharmony_ci hTaskInfo->channelClass = this; 805cc290419Sopenharmony_ci hTaskInfo->isStableBuf = hChannel->isStableBuf; 806cc290419Sopenharmony_ci hTaskInfo->isCleared = false; 807cc290419Sopenharmony_ci return hTaskInfo; 808cc290419Sopenharmony_ci}; 809cc290419Sopenharmony_ci} // namespace Hdc 810