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