• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "flash_define.h"
16 #include "server.h"
17 #include "server_for_client.h"
18 
19 using namespace Hdc;
20 
21 static bool g_isServerMode = false;
22 static bool g_isPullServer = true;
23 static bool g_isPcDebugRun = false;
24 static bool g_isTCPorUSB = false;
25 static auto g_logLevel = LOG_LEVEL_FULL;
26 static int g_isTestMethod = 0;
27 static string g_connectKey = "";
28 static string g_serverListenString = DEFAULT_SERVER_ADDR;
29 
30 namespace Hdc {
31 // return value: 0 == not command, 1 == one command, 2 == double command
IsRegisterCommand(string & outCommand,const char * cmd,const char * cmdnext)32 int IsRegisterCommand(string &outCommand, const char *cmd, const char *cmdnext)
33 {
34     string sCmdNext = (cmdnext == nullptr) ? string("") : string(cmdnext);
35     string doubleCommand = cmd + string(" ") + sCmdNext;
36     vector<string> registerCommand;
37     registerCommand.push_back(CMDSTR_SOFTWARE_VERSION);
38     registerCommand.push_back(CMDSTR_SOFTWARE_HELP);
39     registerCommand.push_back(CMDSTR_TARGET_DISCOVER);
40     registerCommand.push_back(CMDSTR_LIST_TARGETS);
41     registerCommand.push_back(CMDSTR_CONNECT_ANY);
42     registerCommand.push_back(CMDSTR_CONNECT_TARGET);
43     registerCommand.push_back(CMDSTR_TARGET_REBOOT);
44     registerCommand.push_back(CMDSTR_SERVICE_KILL);
45     registerCommand.push_back(CMDSTR_SERVICE_START);
46     registerCommand.push_back(CMDSTR_TARGET_MODE);
47 
48     // flashd
49     registerCommand.push_back(CMDSTR_UPDATE_SYSTEM);
50     registerCommand.push_back(CMDSTR_FLASH_PARTITION);
51     registerCommand.push_back(CMDSTR_ERASE_PARTITION);
52     registerCommand.push_back(CMDSTR_FORMAT_PARTITION);
53     for (string v : registerCommand) {
54         if (doubleCommand == v) {
55             outCommand = doubleCommand;
56             return 2; // 2 error code
57         }
58         if (cmd == v) {
59             outCommand = cmd;
60             return 1;
61         }
62     }
63     return 0;
64 }
65 
AppendCwdWhenTransfer(string & outCommand)66 void AppendCwdWhenTransfer(string &outCommand)
67 {
68     if (outCommand != CMDSTR_FILE_SEND && outCommand != CMDSTR_FILE_RECV && outCommand != CMDSTR_APP_INSTALL
69         && outCommand != CMDSTR_APP_SIDELOAD) {
70         return;
71     }
72     char path[PATH_MAX] = "";
73     size_t size = sizeof(path);
74     if (uv_cwd(path, &size) < 0)
75         return;
76     if (path[strlen(path) - 1] != Base::GetPathSep()) {
77         path[strlen(path)] = Base::GetPathSep();
78     }
79     outCommand = outCommand + (outCommand.size() ? " -cwd " : "-cwd ");
80     outCommand += path;
81 }
82 
SplitOptionAndCommand(int argc,const char ** argv,string & outOption,string & outCommand)83 int SplitOptionAndCommand(int argc, const char **argv, string &outOption, string &outCommand)
84 {
85     bool foundCommand = false;
86     int resultChild = 0;
87     // we want to start from 1, ignore argv[0], but it has issue
88     for (int i = 0; i < argc; ++i) {
89         if (!foundCommand) {
90             resultChild = IsRegisterCommand(outCommand, argv[i], (i == argc - 1) ? nullptr : argv[i + 1]);
91             if (resultChild > 0) {
92                 foundCommand = true;
93                 if (resultChild == 2) { // 2 error code
94                     ++i;
95                 }
96                 AppendCwdWhenTransfer(outCommand);
97                 continue;
98             }
99         }
100         if (foundCommand) {
101             outCommand += outCommand.size() ? " " : "";
102             string rawCmd = argv[i];
103             string packageCmd = Base::StringFormat("\"%s\"", argv[i]);
104             outCommand += rawCmd.find(" ") == string::npos ? rawCmd : packageCmd;
105         } else {
106             outOption += outOption.size() ? " " : "";
107             outOption += argv[i];
108         }
109     }
110     return 0;
111 }
112 
RunServerMode(string & serverListenString)113 int RunServerMode(string &serverListenString)
114 {
115     HdcServer server(true);
116     if (!server.Initial(serverListenString.c_str())) {
117         Base::PrintMessage("Initial failed");
118         return -1;
119     }
120     server.WorkerPendding();
121     return 0;
122 }
123 
RunClientMode(string & commands,string & serverListenString,string & connectKey,bool isPullServer)124 int RunClientMode(string &commands, string &serverListenString, string &connectKey, bool isPullServer)
125 {
126     uv_loop_t loopMain;
127     uv_loop_init(&loopMain);
128     HdcClient client(false, serverListenString, &loopMain);
129     if (!commands.size()) {
130         Base::PrintMessage("Unknow operation command...");
131         TranslateCommand::Usage();
132         return 0;
133     }
134     if (!strncmp(commands.c_str(), CMDSTR_SERVICE_START.c_str(), CMDSTR_SERVICE_START.size())
135         || !strncmp(commands.c_str(), CMDSTR_SERVICE_KILL.c_str(), CMDSTR_SERVICE_KILL.size())
136         || !strncmp(commands.c_str(), CMDSTR_GENERATE_KEY.c_str(), CMDSTR_GENERATE_KEY.size())) {
137         client.CtrlServiceWork(commands.c_str());
138         return 0;
139     }
140     if (isPullServer && serverListenString == DEFAULT_SERVER_ADDR
141         && Base::ProgramMutex(SERVER_NAME.c_str(), true) == 0) {
142         // default pullup, just default listenstr.If want to customer listen-string, please use 'hdc -m -s lanip:port'
143         HdcServer::PullupServer(DEFAULT_SERVER_ADDR.c_str());
144         uv_sleep(300);  // give time to start serverForClient,at least 300ms
145     }
146     client.Initial(connectKey);
147     client.ExecuteCommand(commands.c_str());
148     return 0;
149 }
150 
ParseServerListenString(string & serverListenString,char * optarg)151 bool ParseServerListenString(string &serverListenString, char *optarg)
152 {
153     if (strlen(optarg) > 24) { // 24 min len
154         Base::PrintMessage("Unknow content of parament '-s'");
155         return false;
156     }
157     char buf[BUF_SIZE_TINY] = "";
158     if (strcpy_s(buf, sizeof(buf), optarg) < 0) {
159         return false;
160     }
161     char *p = strchr(buf, ':');
162     if (!p) {  // Only port
163         if (strlen(buf) > 5) { // 5 port len
164             Base::PrintMessage("The port-string's length must < 5");
165             return false;
166         }
167         int port = atoi(buf);
168         if (port <= 0 || port > MAX_IP_PORT) {
169             Base::PrintMessage("Port range incorrect");
170             return false;
171         }
172         snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "127.0.0.1:%d", port);
173         serverListenString = buf;
174     } else {
175         *p = '\0';
176         int port = atoi(p + 1);
177         sockaddr_in addr;
178         if ((port <= 0 || port > MAX_IP_PORT) || uv_ip4_addr(buf, port, &addr) < 0) {
179             Base::PrintMessage("-s content incorrect.");
180             return false;
181         }
182         serverListenString = optarg;
183     }
184     return true;
185 }
186 
GetCommandlineOptions(int optArgc,const char * optArgv[])187 bool GetCommandlineOptions(int optArgc, const char *optArgv[])
188 {
189     int ch = 0;
190     bool needExit = false;
191     opterr = 0;
192     // get option parameters first
193     while ((ch = getopt(optArgc, (char * const *)optArgv, "hvpfms:d:t:l:")) != -1) {
194         switch (ch) {
195             case 'h': {
196                 string usage = Hdc::TranslateCommand::Usage();
197                 fprintf(stderr, "%s", usage.c_str());
198                 needExit = true;
199                 return needExit;
200             }
201             case 'v': {
202                 string ver = Base::GetVersion();
203                 fprintf(stdout, "%s\n", ver.c_str());
204                 needExit = true;
205                 return needExit;
206             }
207             case 'f': {  // [not-publish]
208                 break;
209             }
210             case 'l': {
211                 int logLevel = atoi(optarg);
212                 if (logLevel < 0 || logLevel > LOG_LAST) {
213                     Base::PrintMessage("Loglevel error!");
214                     needExit = true;
215                     return needExit;
216                 }
217                 g_logLevel = logLevel;
218                 Base::SetLogLevel(logLevel);
219                 break;
220             }
221             case 'm': {  // [not-publish] is server modeļ¼Œor client mode
222                 g_isServerMode = true;
223                 break;
224             }
225             case 'p': {  // [not-publish]  not pullup server
226                 g_isPullServer = false;
227                 break;
228             }
229             case 't': {  // key
230                 if (strlen(optarg) > MAX_CONNECTKEY_SIZE) {
231                     Base::PrintMessage("Sizeo of of parament '-t' %d is too long", strlen(optarg));
232                     needExit = true;
233                     return needExit;
234                 }
235                 g_connectKey = optarg;
236                 break;
237             }
238             case 's': {
239                 if (!Hdc::ParseServerListenString(g_serverListenString, optarg)) {
240                     needExit = true;
241                     return needExit;
242                 }
243                 break;
244             }
245             case 'd':  // [Undisclosed parameters] debug mode
246                 g_isPcDebugRun = true;
247                 if (optarg[0] == 't') {
248                     g_isTCPorUSB = true;
249                 } else if (optarg[0] == 'u') {
250                     g_isTCPorUSB = false;
251                 } else {
252                     Base::PrintMessage("Unknown debug parameters");
253                     needExit = true;
254                     return needExit;
255                 }
256                 g_isTestMethod = atoi(optarg + 1);
257                 break;
258             case '?':
259                 break;
260             default: {
261                 Base::PrintMessage("Unknown parameters");
262                 needExit = true;
263                 return needExit;
264             }
265         }
266     }
267     return needExit;
268 }
269 }
270 
271 #ifndef UNIT_TEST
272 // hdc -l4 -m -s ip:port|hdc -l4 -m
273 // hdc -l4 - s ip:port list targets
main(int argc,const char * argv[])274 int main(int argc, const char *argv[])
275 {
276     string options;
277     string commands;
278     Hdc::SplitOptionAndCommand(argc, argv, options, commands);
279     int optArgc = 0;
280     char **optArgv = Base::SplitCommandToArgs(options.c_str(), &optArgc);
281     bool cmdOptionResult = GetCommandlineOptions(optArgc, (const char **)optArgv);
282     delete[]((char *)optArgv);
283     if (cmdOptionResult) {
284         return 0;
285     }
286     if (g_isServerMode) {
287         // -m server.Run alone in the background, no -s will be listen loopback address,
288         Base::SetLogLevel(g_logLevel); // default level LOG_LEVEL_FULL
289         Hdc::RunServerMode(g_serverListenString);
290     } else if (!g_isPcDebugRun) {
291         Hdc::RunClientMode(commands, g_serverListenString, g_connectKey, g_isPullServer);
292     }
293     WRITE_LOG(LOG_DEBUG, "!!!!!!!!!Main finish main");
294     return 0;
295 }
296 #endif  // no UNIT_TEST
297