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
16cc290419Sopenharmony_ci#include <iostream>
17cc290419Sopenharmony_ci#include "ext_client.h"
18cc290419Sopenharmony_ci#include "server.h"
19cc290419Sopenharmony_ci#include "server_for_client.h"
20cc290419Sopenharmony_ci
21cc290419Sopenharmony_ci#ifdef _WIN32
22cc290419Sopenharmony_ci#include <windows.h>
23cc290419Sopenharmony_ci#endif
24cc290419Sopenharmony_ci
25cc290419Sopenharmony_ci#ifndef HARMONY_PROJECT
26cc290419Sopenharmony_ci#include "ut_command.h"
27cc290419Sopenharmony_ciusing namespace HdcTest;
28cc290419Sopenharmony_ci#endif
29cc290419Sopenharmony_ci
30cc290419Sopenharmony_ciusing namespace Hdc;
31cc290419Sopenharmony_ci
32cc290419Sopenharmony_cinamespace {
33cc290419Sopenharmony_ci    bool g_isServerMode = false;
34cc290419Sopenharmony_ci    bool g_isPullServer = true;
35cc290419Sopenharmony_ci    bool g_isPcDebugRun = false;
36cc290419Sopenharmony_ci    bool g_isTCPorUSB = false;
37cc290419Sopenharmony_ci    bool g_isCustomLoglevel = false;
38cc290419Sopenharmony_ci    bool g_externalCmd = false;
39cc290419Sopenharmony_ci    int g_isTestMethod = 0;
40cc290419Sopenharmony_ci    string g_connectKey = "";
41cc290419Sopenharmony_ci    string g_serverListenString = "";
42cc290419Sopenharmony_ci    string g_containerInOut = "";
43cc290419Sopenharmony_ci}
44cc290419Sopenharmony_ci
45cc290419Sopenharmony_cinamespace Hdc {
46cc290419Sopenharmony_ci// return value: 0 == not command, 1 == one command, 2 == double command
47cc290419Sopenharmony_ciint IsRegisterCommand(string &outCommand, const char *cmd, const char *cmdnext)
48cc290419Sopenharmony_ci{
49cc290419Sopenharmony_ci    string sCmdNext = cmdnext == nullptr ? string("") : string(cmdnext);
50cc290419Sopenharmony_ci    string doubleCommand = cmd + string(" ") + sCmdNext;
51cc290419Sopenharmony_ci    vector<string> registerCommand;
52cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_SOFTWARE_VERSION);
53cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_SOFTWARE_HELP);
54cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_TARGET_DISCOVER);
55cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_LIST_TARGETS);
56cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_CHECK_SERVER);
57cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_CHECK_DEVICE);
58cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_WAIT_FOR);
59cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_CONNECT_ANY);
60cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_CONNECT_TARGET);
61cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_SHELL);
62cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_FILE_SEND);
63cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_FILE_RECV);
64cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_FORWARD_FPORT);
65cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_FORWARD_RPORT);
66cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_SERVICE_KILL);
67cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_SERVICE_START);
68cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_GENERATE_KEY);
69cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_APP_INSTALL);
70cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_APP_UNINSTALL);
71cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_TARGET_MOUNT);
72cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_HILOG);
73cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_STARTUP_MODE);
74cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_BUGREPORT);
75cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_TARGET_MODE);
76cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_APP_SIDELOAD);
77cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_TARGET_REBOOT);
78cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_LIST_JDWP);
79cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_TRACK_JDWP);
80cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_FLASHD_UPDATE);
81cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_FLASHD_FLASH);
82cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_FLASHD_ERASE);
83cc290419Sopenharmony_ci    registerCommand.push_back(CMDSTR_FLASHD_FORMAT);
84cc290419Sopenharmony_ci
85cc290419Sopenharmony_ci    for (string v : registerCommand) {
86cc290419Sopenharmony_ci        if (doubleCommand == v) {
87cc290419Sopenharmony_ci            outCommand = doubleCommand;
88cc290419Sopenharmony_ci            return CMD_ARG1_COUNT;
89cc290419Sopenharmony_ci        }
90cc290419Sopenharmony_ci        if (cmd == v || !strncmp(cmd, CMDSTR_WAIT_FOR.c_str(), CMDSTR_WAIT_FOR.size())) {
91cc290419Sopenharmony_ci            outCommand = cmd;
92cc290419Sopenharmony_ci            return 1;
93cc290419Sopenharmony_ci        }
94cc290419Sopenharmony_ci    }
95cc290419Sopenharmony_ci    return 0;
96cc290419Sopenharmony_ci}
97cc290419Sopenharmony_ci
98cc290419Sopenharmony_civoid AppendCwdWhenTransfer(string &outCommand)
99cc290419Sopenharmony_ci{
100cc290419Sopenharmony_ci    if (outCommand != CMDSTR_FILE_SEND && outCommand != CMDSTR_FILE_RECV && outCommand != CMDSTR_APP_INSTALL &&
101cc290419Sopenharmony_ci        outCommand != CMDSTR_APP_SIDELOAD) {
102cc290419Sopenharmony_ci        return;
103cc290419Sopenharmony_ci    }
104cc290419Sopenharmony_ci    int value = -1;
105cc290419Sopenharmony_ci    char path[PATH_MAX] = "";
106cc290419Sopenharmony_ci    size_t size = sizeof(path);
107cc290419Sopenharmony_ci    value = uv_cwd(path, &size);
108cc290419Sopenharmony_ci    if (value < 0) {
109cc290419Sopenharmony_ci        constexpr int bufSize = 1024;
110cc290419Sopenharmony_ci        char buf[bufSize] = { 0 };
111cc290419Sopenharmony_ci        uv_strerror_r(value, buf, bufSize);
112cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "append cwd path failed: %s", buf);
113cc290419Sopenharmony_ci        return;
114cc290419Sopenharmony_ci    }
115cc290419Sopenharmony_ci    if (strlen(path) >= PATH_MAX - 1) {
116cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "append cwd path failed: buffer space max");
117cc290419Sopenharmony_ci        return;
118cc290419Sopenharmony_ci    }
119cc290419Sopenharmony_ci    if (path[strlen(path) - 1] != Base::GetPathSep()) {
120cc290419Sopenharmony_ci        path[strlen(path)] = Base::GetPathSep();
121cc290419Sopenharmony_ci    }
122cc290419Sopenharmony_ci    outCommand += outCommand.size() ? " " : "";
123cc290419Sopenharmony_ci    outCommand += CMDSTR_REMOTE_PARAMETER;
124cc290419Sopenharmony_ci    outCommand += outCommand.size() ? " -cwd " : "-cwd ";
125cc290419Sopenharmony_ci    outCommand += Base::StringFormat("\"%s\"", path);
126cc290419Sopenharmony_ci}
127cc290419Sopenharmony_ci
128cc290419Sopenharmony_ciint SplitOptionAndCommand(int argc, const char **argv, string &outOption, string &outCommand)
129cc290419Sopenharmony_ci{
130cc290419Sopenharmony_ci    bool foundCommand = false;
131cc290419Sopenharmony_ci    int resultChild = 0;
132cc290419Sopenharmony_ci    // we want to start from 1, ignore argv[0], but it has issue
133cc290419Sopenharmony_ci    for (int i = 0; i < argc; ++i) {
134cc290419Sopenharmony_ci        if (!foundCommand) {
135cc290419Sopenharmony_ci            resultChild = IsRegisterCommand(outCommand, argv[i], (i == argc - 1) ? nullptr : argv[i + 1]);
136cc290419Sopenharmony_ci            if (resultChild > 0) {
137cc290419Sopenharmony_ci                foundCommand = true;
138cc290419Sopenharmony_ci                if (resultChild == 2) {
139cc290419Sopenharmony_ci                    ++i;
140cc290419Sopenharmony_ci                }
141cc290419Sopenharmony_ci                AppendCwdWhenTransfer(outCommand);
142cc290419Sopenharmony_ci                continue;
143cc290419Sopenharmony_ci            }
144cc290419Sopenharmony_ci        }
145cc290419Sopenharmony_ci        if (foundCommand) {
146cc290419Sopenharmony_ci            outCommand += outCommand.size() ? " " : "";
147cc290419Sopenharmony_ci            string rawCmd = Base::UnicodeToUtf8(argv[i]);
148cc290419Sopenharmony_ci            outCommand += rawCmd.find(" ") == string::npos ? rawCmd : Base::StringFormat("\"%s\"", rawCmd.c_str());
149cc290419Sopenharmony_ci        } else {
150cc290419Sopenharmony_ci            outOption += outOption.size() ? " " : "";
151cc290419Sopenharmony_ci            string rawOption = Base::UnicodeToUtf8(argv[i]);
152cc290419Sopenharmony_ci            outOption += (i == 0) ? Base::StringFormat("\"%s\"", rawOption.c_str()) : rawOption;
153cc290419Sopenharmony_ci        }
154cc290419Sopenharmony_ci    }
155cc290419Sopenharmony_ci    return 0;
156cc290419Sopenharmony_ci}
157cc290419Sopenharmony_ci
158cc290419Sopenharmony_ciint RunServerMode(string &serverListenString)
159cc290419Sopenharmony_ci{
160cc290419Sopenharmony_ci    if (serverListenString.empty()) {
161cc290419Sopenharmony_ci        return -1;
162cc290419Sopenharmony_ci    }
163cc290419Sopenharmony_ci    HdcServer server(true);
164cc290419Sopenharmony_ci    if (!server.Initial(serverListenString.c_str())) {
165cc290419Sopenharmony_ci        Base::PrintMessage("Initial failed");
166cc290419Sopenharmony_ci        return -1;
167cc290419Sopenharmony_ci    }
168cc290419Sopenharmony_ci    server.WorkerPendding();
169cc290419Sopenharmony_ci    return 0;
170cc290419Sopenharmony_ci}
171cc290419Sopenharmony_ci
172cc290419Sopenharmony_ciint RunPcDebugMode(bool isPullServer, bool isTCPorUSB, int isTestMethod)
173cc290419Sopenharmony_ci{
174cc290419Sopenharmony_ci#ifdef HARMONY_PROJECT
175cc290419Sopenharmony_ci    Base::PrintMessage("Not support command...");
176cc290419Sopenharmony_ci#else
177cc290419Sopenharmony_ci    pthread_t pt;
178cc290419Sopenharmony_ci    if (isPullServer) {
179cc290419Sopenharmony_ci        pthread_create(&pt, nullptr, TestBackgroundServerForClient, nullptr);
180cc290419Sopenharmony_ci        uv_sleep(200);  // give time to start serverForClient,at least 200ms
181cc290419Sopenharmony_ci    }
182cc290419Sopenharmony_ci    TestRuntimeCommandSimple(isTCPorUSB, isTestMethod, true);
183cc290419Sopenharmony_ci    if (isPullServer) {
184cc290419Sopenharmony_ci        pthread_join(pt, nullptr);
185cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "!!!!!!!!!Server finish");
186cc290419Sopenharmony_ci    }
187cc290419Sopenharmony_ci#endif
188cc290419Sopenharmony_ci    return 0;
189cc290419Sopenharmony_ci}
190cc290419Sopenharmony_ci
191cc290419Sopenharmony_ciint RunClientMode(string &commands, string &serverListenString, string &connectKey, bool isPullServer)
192cc290419Sopenharmony_ci{
193cc290419Sopenharmony_ci    if (serverListenString.empty()) {
194cc290419Sopenharmony_ci        return -1;
195cc290419Sopenharmony_ci    }
196cc290419Sopenharmony_ci    uv_loop_t loopMain;
197cc290419Sopenharmony_ci    uv_loop_init(&loopMain);
198cc290419Sopenharmony_ci    HdcClient client(false, serverListenString, &loopMain, commands == CMDSTR_CHECK_SERVER);
199cc290419Sopenharmony_ci    if (!commands.size()) {
200cc290419Sopenharmony_ci        Base::PrintMessage("Unknown operation command...");
201cc290419Sopenharmony_ci        std::cerr << TranslateCommand::Usage();
202cc290419Sopenharmony_ci        return 0;
203cc290419Sopenharmony_ci    }
204cc290419Sopenharmony_ci    if (!strncmp(commands.c_str(), CMDSTR_SERVICE_START.c_str(), CMDSTR_SERVICE_START.size()) ||
205cc290419Sopenharmony_ci        !strncmp(commands.c_str(), CMDSTR_SERVICE_KILL.c_str(), CMDSTR_SERVICE_KILL.size()) ||
206cc290419Sopenharmony_ci        !strncmp(commands.c_str(), CMDSTR_GENERATE_KEY.c_str(), CMDSTR_GENERATE_KEY.size())) {
207cc290419Sopenharmony_ci        client.CtrlServiceWork(commands.c_str());
208cc290419Sopenharmony_ci        return 0;
209cc290419Sopenharmony_ci    }
210cc290419Sopenharmony_ci    if (isPullServer && Base::ProgramMutex(SERVER_NAME.c_str(), true) == 0) {
211cc290419Sopenharmony_ci        // default pullup, just default listenstr.If want to customer listen-string, please use 'hdc -m -s lanip:port'
212cc290419Sopenharmony_ci        HdcServer::PullupServer(serverListenString.c_str());
213cc290419Sopenharmony_ci        uv_sleep(START_SERVER_FOR_CLIENT_TIME);  // give time to start serverForClient,at least 200ms
214cc290419Sopenharmony_ci    }
215cc290419Sopenharmony_ci    client.Initial(connectKey);
216cc290419Sopenharmony_ci    client.ExecuteCommand(commands.c_str());
217cc290419Sopenharmony_ci    return 0;
218cc290419Sopenharmony_ci}
219cc290419Sopenharmony_ci
220cc290419Sopenharmony_cibool ParseServerListenString(string &serverListenString, char *optarg)
221cc290419Sopenharmony_ci{
222cc290419Sopenharmony_ci    if (strlen(optarg) > strlen("0000::0000:0000:0000:0000%interfacename:65535")) {
223cc290419Sopenharmony_ci        Base::PrintMessage("Unknown content of parament '-s'");
224cc290419Sopenharmony_ci        return false;
225cc290419Sopenharmony_ci    }
226cc290419Sopenharmony_ci    char buf[BUF_SIZE_TINY] = "";
227cc290419Sopenharmony_ci    if (strcpy_s(buf, sizeof(buf), optarg) != 0) {
228cc290419Sopenharmony_ci        Base::PrintMessage("strcpy_s error %d", errno);
229cc290419Sopenharmony_ci        return false;
230cc290419Sopenharmony_ci    }
231cc290419Sopenharmony_ci    char *p = strrchr(buf, ':');
232cc290419Sopenharmony_ci    if (!p) {  // Only port
233cc290419Sopenharmony_ci        if (strlen(buf) > PORT_MAX_LEN) {
234cc290419Sopenharmony_ci            Base::PrintMessage("The port-string's length must < 5");
235cc290419Sopenharmony_ci            return false;
236cc290419Sopenharmony_ci        }
237cc290419Sopenharmony_ci        size_t len = strlen(buf);
238cc290419Sopenharmony_ci        for (size_t i = 0; i < len; i++) {
239cc290419Sopenharmony_ci            if (isdigit(buf[i]) == 0) {
240cc290419Sopenharmony_ci                Base::PrintMessage("The port must be digit buf:%s", buf);
241cc290419Sopenharmony_ci                return false;
242cc290419Sopenharmony_ci            }
243cc290419Sopenharmony_ci        }
244cc290419Sopenharmony_ci        int port = atoi(buf);
245cc290419Sopenharmony_ci        if (port <= 0 || port > MAX_IP_PORT) {
246cc290419Sopenharmony_ci            Base::PrintMessage("Port range incorrect");
247cc290419Sopenharmony_ci            return false;
248cc290419Sopenharmony_ci        }
249cc290419Sopenharmony_ci        (void)snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "::ffff:127.0.0.1:%d", port);
250cc290419Sopenharmony_ci        serverListenString = buf;
251cc290419Sopenharmony_ci    } else {
252cc290419Sopenharmony_ci        *p = '\0';
253cc290419Sopenharmony_ci        char *str = p + 1;
254cc290419Sopenharmony_ci        size_t len = strlen(str);
255cc290419Sopenharmony_ci        for (size_t i = 0; i < len; i++) {
256cc290419Sopenharmony_ci            if (isdigit(str[i]) == 0) {
257cc290419Sopenharmony_ci                Base::PrintMessage("The port must be digit str:%s", str);
258cc290419Sopenharmony_ci                return false;
259cc290419Sopenharmony_ci            }
260cc290419Sopenharmony_ci        }
261cc290419Sopenharmony_ci        int port = atoi(p + 1);
262cc290419Sopenharmony_ci        sockaddr_in addrv4;
263cc290419Sopenharmony_ci        sockaddr_in6 addrv6;
264cc290419Sopenharmony_ci
265cc290419Sopenharmony_ci        if ((port <= 0 || port > MAX_IP_PORT)) {
266cc290419Sopenharmony_ci            Base::PrintMessage("-s content port incorrect.");
267cc290419Sopenharmony_ci            return false;
268cc290419Sopenharmony_ci        }
269cc290419Sopenharmony_ci
270cc290419Sopenharmony_ci        if (uv_ip4_addr(buf, port, &addrv4) == 0) {
271cc290419Sopenharmony_ci            serverListenString = IPV4_MAPPING_PREFIX;
272cc290419Sopenharmony_ci            serverListenString += optarg;
273cc290419Sopenharmony_ci        } else if (uv_ip6_addr(buf, port, &addrv6) == 0) {
274cc290419Sopenharmony_ci            serverListenString = optarg;
275cc290419Sopenharmony_ci        } else {
276cc290419Sopenharmony_ci            Base::PrintMessage("-s content IP incorrect.");
277cc290419Sopenharmony_ci            return false;
278cc290419Sopenharmony_ci        }
279cc290419Sopenharmony_ci    }
280cc290419Sopenharmony_ci    return true;
281cc290419Sopenharmony_ci}
282cc290419Sopenharmony_ci
283cc290419Sopenharmony_cibool GetCommandlineOptions(int optArgc, const char *optArgv[])
284cc290419Sopenharmony_ci{
285cc290419Sopenharmony_ci    int ch = 0;
286cc290419Sopenharmony_ci    bool needExit = false;
287cc290419Sopenharmony_ci    opterr = 0;
288cc290419Sopenharmony_ci    // get option parameters first
289cc290419Sopenharmony_ci    while ((ch = getopt(optArgc, const_cast<char *const*>(optArgv), "hvpfmncs:Sd:t:l:")) != -1) {
290cc290419Sopenharmony_ci        switch (ch) {
291cc290419Sopenharmony_ci            case 'h': {
292cc290419Sopenharmony_ci                string usage = Hdc::TranslateCommand::Usage();
293cc290419Sopenharmony_ci                if (optind < optArgc && optind >= 0 && string(optArgv[optind]) == "verbose") {
294cc290419Sopenharmony_ci                    usage = Hdc::TranslateCommand::Verbose();
295cc290419Sopenharmony_ci                }
296cc290419Sopenharmony_ci                fprintf(stderr, "%s", usage.c_str());
297cc290419Sopenharmony_ci                needExit = true;
298cc290419Sopenharmony_ci                return needExit;
299cc290419Sopenharmony_ci            }
300cc290419Sopenharmony_ci            case 'v': {
301cc290419Sopenharmony_ci                string ver = Base::GetVersion();
302cc290419Sopenharmony_ci                fprintf(stdout, "%s\n", ver.c_str());
303cc290419Sopenharmony_ci                needExit = true;
304cc290419Sopenharmony_ci                return needExit;
305cc290419Sopenharmony_ci            }
306cc290419Sopenharmony_ci            case 'f': {  // [not-publish]
307cc290419Sopenharmony_ci                break;
308cc290419Sopenharmony_ci            }
309cc290419Sopenharmony_ci            case 'l': {
310cc290419Sopenharmony_ci                int logLevel = atoi(optarg);
311cc290419Sopenharmony_ci                if (logLevel < 0 || logLevel > LOG_LAST) {
312cc290419Sopenharmony_ci                    Base::PrintMessage("Loglevel error!");
313cc290419Sopenharmony_ci                    needExit = true;
314cc290419Sopenharmony_ci                    return needExit;
315cc290419Sopenharmony_ci                }
316cc290419Sopenharmony_ci                g_isCustomLoglevel = true;
317cc290419Sopenharmony_ci                Base::SetLogLevel(logLevel);
318cc290419Sopenharmony_ci                break;
319cc290419Sopenharmony_ci            }
320cc290419Sopenharmony_ci            case 'm': {  // [not-publish] is server mode,or client mode
321cc290419Sopenharmony_ci                g_isServerMode = true;
322cc290419Sopenharmony_ci                break;
323cc290419Sopenharmony_ci            }
324cc290419Sopenharmony_ci            case 'n': {
325cc290419Sopenharmony_ci                g_containerInOut = "-n";
326cc290419Sopenharmony_ci                break;
327cc290419Sopenharmony_ci            }
328cc290419Sopenharmony_ci            case 'c': {
329cc290419Sopenharmony_ci                g_containerInOut = "-c";
330cc290419Sopenharmony_ci                break;
331cc290419Sopenharmony_ci            }
332cc290419Sopenharmony_ci            case 'p': {  // [not-publish]  not pullup server
333cc290419Sopenharmony_ci                g_isPullServer = false;
334cc290419Sopenharmony_ci                break;
335cc290419Sopenharmony_ci            }
336cc290419Sopenharmony_ci            case 't': {  // key
337cc290419Sopenharmony_ci                if (strlen(optarg) > MAX_CONNECTKEY_SIZE) {
338cc290419Sopenharmony_ci                    Base::PrintMessage("Sizeo of of parament '-t' %d is too long", strlen(optarg));
339cc290419Sopenharmony_ci                    needExit = true;
340cc290419Sopenharmony_ci                    return needExit;
341cc290419Sopenharmony_ci                }
342cc290419Sopenharmony_ci                g_connectKey = optarg;
343cc290419Sopenharmony_ci                break;
344cc290419Sopenharmony_ci            }
345cc290419Sopenharmony_ci            case 's': {
346cc290419Sopenharmony_ci                if (!Hdc::ParseServerListenString(g_serverListenString, optarg)) {
347cc290419Sopenharmony_ci                    needExit = true;
348cc290419Sopenharmony_ci                    return needExit;
349cc290419Sopenharmony_ci                }
350cc290419Sopenharmony_ci                break;
351cc290419Sopenharmony_ci            }
352cc290419Sopenharmony_ci            case 'S': {
353cc290419Sopenharmony_ci                g_externalCmd = true;
354cc290419Sopenharmony_ci                break;
355cc290419Sopenharmony_ci            }
356cc290419Sopenharmony_ci            case 'd':  // [Undisclosed parameters] debug mode
357cc290419Sopenharmony_ci                g_isPcDebugRun = true;
358cc290419Sopenharmony_ci                if (optarg[0] == 't') {
359cc290419Sopenharmony_ci                    g_isTCPorUSB = true;
360cc290419Sopenharmony_ci                } else if (optarg[0] == 'u') {
361cc290419Sopenharmony_ci                    g_isTCPorUSB = false;
362cc290419Sopenharmony_ci                } else {
363cc290419Sopenharmony_ci                    Base::PrintMessage("Unknown debug parameters");
364cc290419Sopenharmony_ci                    needExit = true;
365cc290419Sopenharmony_ci                    return needExit;
366cc290419Sopenharmony_ci                }
367cc290419Sopenharmony_ci                g_isTestMethod = atoi(optarg + 1);
368cc290419Sopenharmony_ci                break;
369cc290419Sopenharmony_ci            case '?':
370cc290419Sopenharmony_ci                break;
371cc290419Sopenharmony_ci            default: {
372cc290419Sopenharmony_ci                Base::PrintMessage("Unknown parameters");
373cc290419Sopenharmony_ci                needExit = true;
374cc290419Sopenharmony_ci                return needExit;
375cc290419Sopenharmony_ci            }
376cc290419Sopenharmony_ci        }
377cc290419Sopenharmony_ci    }
378cc290419Sopenharmony_ci    return needExit;
379cc290419Sopenharmony_ci}
380cc290419Sopenharmony_ci
381cc290419Sopenharmony_civoid InitServerAddr(void)
382cc290419Sopenharmony_ci{
383cc290419Sopenharmony_ci    int port;
384cc290419Sopenharmony_ci    do {
385cc290419Sopenharmony_ci        char *env = getenv(ENV_SERVER_PORT.c_str());
386cc290419Sopenharmony_ci        if (!env) {
387cc290419Sopenharmony_ci            port = DEFAULT_PORT;
388cc290419Sopenharmony_ci            break;
389cc290419Sopenharmony_ci        }
390cc290419Sopenharmony_ci
391cc290419Sopenharmony_ci        size_t len = strlen(env);
392cc290419Sopenharmony_ci        size_t maxLen = 5;
393cc290419Sopenharmony_ci        if (len > maxLen) {
394cc290419Sopenharmony_ci            fprintf(stderr, "OHOS_HDC_SERVER_PORT %s is not in (0, 65535] range\n", env);
395cc290419Sopenharmony_ci            return;
396cc290419Sopenharmony_ci        }
397cc290419Sopenharmony_ci
398cc290419Sopenharmony_ci        for (size_t i = 0; i < len; i++) {
399cc290419Sopenharmony_ci            if (isdigit(env[i]) == 0) {
400cc290419Sopenharmony_ci                fprintf(stderr, "OHOS_HDC_SERVER_PORT %s is not digit\n", env);
401cc290419Sopenharmony_ci                return;
402cc290419Sopenharmony_ci            }
403cc290419Sopenharmony_ci        }
404cc290419Sopenharmony_ci
405cc290419Sopenharmony_ci        port = atoi(env);
406cc290419Sopenharmony_ci        if (port > MAX_IP_PORT || port <= 0) {
407cc290419Sopenharmony_ci            fprintf(stderr, "OHOS_HDC_SERVER_PORT %s is not in (0, 65535] range\n", env);
408cc290419Sopenharmony_ci            return;
409cc290419Sopenharmony_ci        }
410cc290419Sopenharmony_ci    } while (0);
411cc290419Sopenharmony_ci    g_serverListenString = DEFAULT_SERVER_ADDR_IP;
412cc290419Sopenharmony_ci    g_serverListenString += ":";
413cc290419Sopenharmony_ci    g_serverListenString += std::to_string(port);
414cc290419Sopenharmony_ci}
415cc290419Sopenharmony_ci
416cc290419Sopenharmony_civoid RunExternalClient(string &str, string &connectKey, string &containerInOut)
417cc290419Sopenharmony_ci{
418cc290419Sopenharmony_ci    ExtClient extClient;
419cc290419Sopenharmony_ci    extClient.connectKey = connectKey;
420cc290419Sopenharmony_ci    extClient.containerInOut = containerInOut;
421cc290419Sopenharmony_ci    extClient.Init();
422cc290419Sopenharmony_ci    extClient.ExecuteCommand(str);
423cc290419Sopenharmony_ci}
424cc290419Sopenharmony_ci}
425cc290419Sopenharmony_ci
426cc290419Sopenharmony_ci#ifndef UNIT_TEST
427cc290419Sopenharmony_ci
428cc290419Sopenharmony_ci// hdc -l4 -m -s ip:port|hdc -l4 -m
429cc290419Sopenharmony_ci// hdc -l4 - s ip:port list targets
430cc290419Sopenharmony_ciint main(int argc, const char *argv[])
431cc290419Sopenharmony_ci{
432cc290419Sopenharmony_ci#ifdef _WIN32
433cc290419Sopenharmony_ci    SetConsoleOutputCP(CP_UTF8);
434cc290419Sopenharmony_ci#endif
435cc290419Sopenharmony_ci    string options;
436cc290419Sopenharmony_ci    string commands;
437cc290419Sopenharmony_ci    Hdc::SplitOptionAndCommand(argc, argv, options, commands);
438cc290419Sopenharmony_ci    uv_setup_args(argc, const_cast<char **>(argv));
439cc290419Sopenharmony_ci    int optArgc = 0;
440cc290419Sopenharmony_ci    char **optArgv = Base::SplitCommandToArgs(options.c_str(), &optArgc);
441cc290419Sopenharmony_ci    bool cmdOptionResult;
442cc290419Sopenharmony_ci
443cc290419Sopenharmony_ci    InitServerAddr();
444cc290419Sopenharmony_ci    cmdOptionResult = GetCommandlineOptions(optArgc, const_cast<const char **>(optArgv));
445cc290419Sopenharmony_ci    delete[](reinterpret_cast<char*>(optArgv));
446cc290419Sopenharmony_ci    if (cmdOptionResult) {
447cc290419Sopenharmony_ci        return 0;
448cc290419Sopenharmony_ci    }
449cc290419Sopenharmony_ci    Base::InitProcess();
450cc290419Sopenharmony_ci    if (g_isServerMode) {
451cc290419Sopenharmony_ci        Base::CreateLogDir();
452cc290419Sopenharmony_ci        // -m server.Run alone in the background, no -s will be listen loopback address
453cc290419Sopenharmony_ci        Hdc::RunServerMode(g_serverListenString);
454cc290419Sopenharmony_ci    } else if (g_isPcDebugRun) {
455cc290419Sopenharmony_ci        Hdc::RunPcDebugMode(g_isPullServer, g_isTCPorUSB, g_isTestMethod);
456cc290419Sopenharmony_ci    } else {
457cc290419Sopenharmony_ci        if (!g_isCustomLoglevel) {
458cc290419Sopenharmony_ci            Base::SetLogLevel(LOG_INFO);
459cc290419Sopenharmony_ci        }
460cc290419Sopenharmony_ci
461cc290419Sopenharmony_ci        if (!ExtClient::SharedLibraryExist()) {
462cc290419Sopenharmony_ci            Hdc::RunClientMode(commands, g_serverListenString, g_connectKey, g_isPullServer);
463cc290419Sopenharmony_ci            Hdc::Base::RemoveLogCache();
464cc290419Sopenharmony_ci            _exit(0);
465cc290419Sopenharmony_ci        }
466cc290419Sopenharmony_ci        string str = "list targets";
467cc290419Sopenharmony_ci        if (!strncmp(commands.c_str(), CMDSTR_LIST_TARGETS.c_str(), CMDSTR_LIST_TARGETS.size())) {
468cc290419Sopenharmony_ci            string lista = "list targets -a";
469cc290419Sopenharmony_ci            if (!strncmp(commands.c_str(), lista.c_str(), lista.size())) {
470cc290419Sopenharmony_ci                str = "list targets -v";
471cc290419Sopenharmony_ci            } else {
472cc290419Sopenharmony_ci                str = commands;
473cc290419Sopenharmony_ci            }
474cc290419Sopenharmony_ci            Hdc::RunExternalClient(str, g_connectKey, g_containerInOut);
475cc290419Sopenharmony_ci            Hdc::RunClientMode(str, g_serverListenString, g_connectKey, g_isPullServer);
476cc290419Sopenharmony_ci        } else if (!strncmp(commands.c_str(), CMDSTR_SOFTWARE_VERSION.c_str(), CMDSTR_SOFTWARE_VERSION.size()) ||
477cc290419Sopenharmony_ci                   !strncmp(commands.c_str(), CMDSTR_SOFTWARE_HELP.c_str(), CMDSTR_SOFTWARE_HELP.size()) ||
478cc290419Sopenharmony_ci                   !strncmp(commands.c_str(), CMDSTR_TARGET_DISCOVER.c_str(), CMDSTR_TARGET_DISCOVER.size()) ||
479cc290419Sopenharmony_ci                   !strncmp(commands.c_str(), CMDSTR_SERVICE_START.c_str(), CMDSTR_SERVICE_START.size()) ||
480cc290419Sopenharmony_ci                   !strncmp(commands.c_str(), CMDSTR_SERVICE_KILL.c_str(), CMDSTR_SERVICE_KILL.size()) ||
481cc290419Sopenharmony_ci                   !strncmp(commands.c_str(), CMDSTR_WAIT_FOR.c_str(), CMDSTR_WAIT_FOR.size())) {
482cc290419Sopenharmony_ci            Hdc::RunExternalClient(commands, g_connectKey, g_containerInOut);
483cc290419Sopenharmony_ci            Hdc::RunClientMode(commands, g_serverListenString, g_connectKey, g_isPullServer);
484cc290419Sopenharmony_ci        } else if (!strncmp(commands.c_str(), CMDSTR_CONNECT_TARGET.c_str(), CMDSTR_CONNECT_TARGET.size()) ||
485cc290419Sopenharmony_ci                   !strncmp(commands.c_str(), CMDSTR_TARGET_MODE.c_str(), CMDSTR_TARGET_MODE.size()) || g_externalCmd) {
486cc290419Sopenharmony_ci            Hdc::RunExternalClient(commands, g_connectKey, g_containerInOut);
487cc290419Sopenharmony_ci        } else {
488cc290419Sopenharmony_ci            g_show = false;
489cc290419Sopenharmony_ci            Hdc::RunExternalClient(str, g_connectKey, g_containerInOut);
490cc290419Sopenharmony_ci            Hdc::RunClientMode(str, g_serverListenString, g_connectKey, g_isPullServer);
491cc290419Sopenharmony_ci            g_show = true;
492cc290419Sopenharmony_ci            if (g_connectKey.empty()) {
493cc290419Sopenharmony_ci                if (g_lists.size() == 0) {
494cc290419Sopenharmony_ci                    Base::PrintMessage("No any target");
495cc290419Sopenharmony_ci                } else if (g_lists.size() == 1) {
496cc290419Sopenharmony_ci                    auto iter = g_lists.begin();
497cc290419Sopenharmony_ci                    g_connectKey = iter->first;
498cc290419Sopenharmony_ci                } else {
499cc290419Sopenharmony_ci                    Base::PrintMessage("Specify one target");
500cc290419Sopenharmony_ci                }
501cc290419Sopenharmony_ci            }
502cc290419Sopenharmony_ci            if (g_lists[g_connectKey] == "external") {
503cc290419Sopenharmony_ci                Hdc::RunExternalClient(commands, g_connectKey, g_containerInOut);
504cc290419Sopenharmony_ci            } else if (g_lists[g_connectKey] == "hdc") {
505cc290419Sopenharmony_ci                Hdc::RunClientMode(commands, g_serverListenString, g_connectKey, g_isPullServer);
506cc290419Sopenharmony_ci            }
507cc290419Sopenharmony_ci        }
508cc290419Sopenharmony_ci    }
509cc290419Sopenharmony_ci    WRITE_LOG(LOG_DEBUG, "!!!!!!!!!Main finish main");
510cc290419Sopenharmony_ci    Hdc::Base::RemoveLogCache();
511cc290419Sopenharmony_ci    return 0;
512cc290419Sopenharmony_ci}
513cc290419Sopenharmony_ci#endif  // no UNIT_TEST
514