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 "translate.h" 16#include "host_updater.h" 17 18namespace Hdc { 19namespace TranslateCommand { 20 string Usage() 21 { 22 string ret = ""; 23 ret = "\n OpenHarmony device connector(HDC) ...\n\n" 24 "---------------------------------global commands:----------------------------------\n" 25 " -h/help [verbose] - Print hdc help, 'verbose' for more other cmds\n" 26 " -v/version - Print hdc version\n" 27 " -t connectkey - Use device with given connect key\n" 28 "\n" 29 "---------------------------------component commands:-------------------------------\n" 30 "session commands(on server):\n" 31 " list targets [-v] - List all devices status, -v for detail\n" 32 " start [-r] - Start server. If with '-r', will be restart server\n" 33 " kill [-r] - Kill server. If with '-r', will be restart server\n" 34 "\n" 35 "service commands(on daemon):\n" 36 " target mount - Set /system /vendor partition read-write\n" 37 " wait - Wait for the device to become available\n" 38 " target boot [-bootloader|-recovery] - Reboot the device or boot into bootloader\\recovery.\n" 39 " target boot [MODE] - Reboot the into MODE.\n" 40 " smode [-r] - Restart daemon with root permissions, '-r' to cancel root\n" 41 " permissions\n" 42 " tmode usb - Reboot the device, listening on USB\n" 43 " tmode port [port] - Reboot the device, listening on TCP port\n" 44 "\n" 45 "---------------------------------task commands:-------------------------------------\n" 46 "file commands:\n" 47 " file send [option] local remote - Send file to device\n" 48 " file recv [option] remote local - Recv file from device\n" 49 " option is -a|-s|-z\n" 50 " -a: hold target file timestamp\n" 51 " -sync: just update newer file\n" 52 " -z: compress transfer\n" 53 " -m: mode sync\n" 54 "\n" 55 "forward commands:\n" 56 " fport localnode remotenode - Forward local traffic to remote device\n" 57 " rport remotenode localnode - Reserve remote traffic to local host\n" 58 " node config name format 'schema:content'\n" 59 " examples are below:\n" 60 " tcp:<port>\n" 61 " localfilesystem:<unix domain socket name>\n" 62 " localreserved:<unix domain socket name>\n" 63 " localabstract:<unix domain socket name>\n" 64 " dev:<device name>\n" 65 " jdwp:<pid> (remote only)\n" 66 " fport ls - Display forward/reverse tasks\n" 67 " fport rm taskstr - Remove forward/reverse task by taskstring\n" 68 "\n" 69 "app commands:\n" 70 " install [-r|-s] src - Send package(s) to device and install them\n" 71 " src examples: single or multiple packages and directories\n" 72 " (.hap .hsp)\n" 73 " -r: replace existing application\n" 74 " -s: install shared bundle for multi-apps\n" 75 " uninstall [-k] [-s] package - Remove application package from device\n" 76 " -k: keep the data and cache directories\n" 77 " -s: remove shared bundle\n" 78 "\n" 79 "debug commands:\n" 80 " hilog [-h] - Show device log, -h for detail\n" 81 " shell [COMMAND...] - Run shell command (interactive shell if no command given)\n" 82 " bugreport [FILE] - Return all information from the device, stored in file if " 83 "FILE is specified\n" 84 " jpid - List PIDs of processes hosting a JDWP transport\n" 85 " track-jpid [-a|-p] - Track PIDs of debug processes hosting a JDWP transport\n" 86 " -a: include debug and release processes\n" 87 " -p: don't display debug and release tags\n" 88 "\n" 89 "security commands:\n" 90 " keygen FILE - Generate public/private key; key stored in FILE and FILE.pub\n" 91 "\n"; 92 return ret; 93 } 94 95 string Verbose() 96 { 97 string ret = "\n OpenHarmony device connector(HDC) ...\n\n" 98 "---------------------------------global commands:----------------------------------\n" 99 " -h/help [verbose] - Print hdc help, 'verbose' for more other cmds\n" 100 " -v/version - Print hdc version\n" 101 " -l[0-5] - Set runtime loglevel\n" 102 " -t connectkey - Use device with given connect key\n" 103 " checkserver - check client-server version\n" 104 " checkdevice - check server-daemon version(only uart)\n" 105 "\n" 106 "---------------------------------component commands:-------------------------------\n" 107 "session commands(on server):\n" 108 " discover - Discover devices listening on TCP via LAN broadcast\n" 109 " list targets [-v] - List all devices status, -v for detail\n" 110 " tconn key - Connect device via key, TCP use ip:port\n" 111 " example:192.168.0.100:10178/192.168.0.100\n" 112 " USB connect automatic, TCP need to connect manually\n" 113#ifdef HDC_SUPPORT_UART 114 "\n" 115 " UART connect need connect manually.\n" 116 " Baud Rate can be specified with commas.\n" 117 " key format: <Port Name>[,Baud Rate]\n" 118 " example: tconn COM5,921600\n" 119 " Default Baud Rate is 921600.\n" 120 "\n" 121#endif 122 " start [-r] - Start server. If with '-r', will be restart server\n" 123 " kill [-r] - Kill server. If with '-r', will be restart server\n" 124 " -s [ip:]port - Set hdc server listen config\n" 125 "\n" 126 "service commands(on daemon):\n" 127 " target mount - Set /system /vendor partition read-write\n" 128 " target boot [-bootloader|-recovery] - Reboot the device or boot into bootloader\\recovery.\n" 129 " target boot [MODE] - Reboot the into MODE.\n" 130 " smode [-r] - Restart daemon with root permissions, '-r' to cancel root\n" 131 " permissions\n" 132 " tmode usb - Reboot the device, listening on USB\n" 133 " tmode port [port] - Reboot the device, listening on TCP port\n" 134 "\n" 135 "---------------------------------task commands:-------------------------------------\n" 136 "file commands:\n" 137 " file send [option] local remote - Send file to device\n" 138 " file recv [option] remote local - Recv file from device\n" 139 " option is -a|-s|-z\n" 140 " -a: hold target file timestamp\n" 141 " -sync: just update newer file\n" 142 " -z: compress transfer\n" 143 " -m: mode sync\n" 144 "\n" 145 "forward commands:\n" 146 " fport localnode remotenode - Forward local traffic to remote device\n" 147 " rport remotenode localnode - Reserve remote traffic to local host\n" 148 " node config name format 'schema:content'\n" 149 " examples are below:\n" 150 " tcp:<port>\n" 151 " localfilesystem:<unix domain socket name>\n" 152 " localreserved:<unix domain socket name>\n" 153 " localabstract:<unix domain socket name>\n" 154 " dev:<device name>\n" 155 " jdwp:<pid> (remote only)\n" 156 " fport ls - Display forward/reverse tasks\n" 157 " fport rm taskstr - Remove forward/reverse task by taskstring\n" 158 "\n" 159 "app commands:\n" 160 " install [-r|-s] src - Send package(s) to device and install them\n" 161 " src examples: single or multiple packages and directories\n" 162 " (.hap .hsp)\n" 163 " -r: replace existing application\n" 164 " -s: install shared bundle for multi-apps\n" 165 " uninstall [-k] [-s] package - Remove application package from device\n" 166 " -k: keep the data and cache directories\n" 167 " -s: remove shared bundle\n" 168 "\n" 169 "debug commands:\n" 170 " hilog [-h] - Show device log, -h for detail\n" 171 " shell [COMMAND...] - Run shell command (interactive shell if no command given)\n" 172 " bugreport [FILE] - Return all information from the device, stored in file if FILE " 173 "is specified\n" 174 " jpid - List PIDs of processes hosting a JDWP transport\n" 175 " sideload [PATH] - Sideload the given full OTA package\n" 176 "\n" 177 "security commands:\n" 178 " keygen FILE - Generate public/private key; key stored in FILE and FILE.pub\n" 179 "\n" 180 "---------------------------------flash commands:------------------------------------\n" 181 "flash commands:\n" 182 " update packagename - Update system by package\n" 183 " flash [-f] partition imagename - Flash partition by image\n" 184 " erase [-f] partition - Erase partition\n" 185 " format [-f] partition - Format partition\n" 186 "---------------------------------external commands:------------------------------------\n" 187 "extconn key - Connect external device via key, TCP use ip:port(remian)\n" 188 "-S [ip:]port - Set hdc external server listen config\n" 189 "\n"; 190 return ret; 191 } 192 193 string TargetConnect(FormatCommand *outCmd) 194 { 195 string stringError; 196 if (Base::StringEndsWith(outCmd->parameters, " -remove")) { 197 outCmd->parameters = outCmd->parameters.substr(0, outCmd->parameters.size() - CMD_REMOTE_SIZE); 198 outCmd->cmdFlag = CMD_KERNEL_TARGET_DISCONNECT; 199 } else { 200 outCmd->cmdFlag = CMD_KERNEL_TARGET_CONNECT; 201 constexpr int maxKeyLength = 50; // 50: tcp max=21,USB max=8bytes, serial device name maybe long 202 if (outCmd->parameters.size() > maxKeyLength) { 203 stringError = "Error connect key's size"; 204 outCmd->bJumpDo = true; 205 } 206 } 207 size_t pos = outCmd->parameters.find(":"); 208 if (pos != std::string::npos) { 209 // tcp mode 210 string ip = outCmd->parameters.substr(0, pos); 211 if (!Base::IsValidIpv4(ip)) { 212 stringError = "[E001104]:IP address incorrect"; 213 outCmd->bJumpDo = true; 214 return stringError; 215 } 216 string sport = outCmd->parameters.substr(pos + 1); 217 if (sport.empty() || !Base::IsDigitString(sport)) { 218 stringError = "Port incorrect"; 219 outCmd->bJumpDo = true; 220 return stringError; 221 } 222 if (ip == "localhost") { 223 ip = "127.0.0.1"; 224 outCmd->parameters.replace(0, pos, ip); 225 } 226 int port = std::stoi(sport); 227 sockaddr_in addr; 228 if ((port <= 0 || port > MAX_IP_PORT) || uv_ip4_addr(ip.c_str(), port, &addr) < 0) { 229 stringError = "IP:Port incorrect"; 230 outCmd->bJumpDo = true; 231 } 232 } 233 return stringError; 234 } 235 236 string ForwardPort(const char *input, FormatCommand *outCmd) 237 { 238 string stringError; 239 const char *pExtra = input + 6; // CMDSTR_FORWARD_FPORT CMDSTR_FORWARD_RPORT + " " size 240 if (!strncmp(input, CMDSTR_FORWARD_FPORT.c_str(), CMDSTR_FORWARD_FPORT.size()) && !strcmp(pExtra, "ls")) { 241 outCmd->cmdFlag = CMD_FORWARD_LIST; 242 } else if (!strncmp(input, CMDSTR_FORWARD_FPORT.c_str(), CMDSTR_FORWARD_FPORT.size()) && 243 !strncmp(pExtra, "rm", 2)) { // 2: "rm" size 244 outCmd->cmdFlag = CMD_FORWARD_REMOVE; 245 if (strcmp(pExtra, "rm")) { 246 outCmd->parameters = input + FORWORD_PORT_RM_BUF_SIZE; 247 } 248 } else { 249 const char *p = input + FORWORD_PORT_OTHER_BUF_SIZE; 250 // clang-format off 251 if (strncmp(p, "tcp:", 4) && // 4: "tcp:" size 252 strncmp(p, "localabstract:", 14) && // 14: "localabstract:" size 253 strncmp(p, "localreserved:", 14) && // 14: "localreserved:" size 254 strncmp(p, "localfilesystem:", 16) && // 16: "localfilesystem:" size 255 strncmp(p, "dev:", 4) && // 4: "dev:" size 256 strncmp(p, "jdwp:", 5) && // 5: "jdwp:" size 257 strncmp(p, "ark:", 4)) { // 4: "ark:" size 258 stringError = "Incorrect forward command"; 259 outCmd->bJumpDo = true; 260 } 261 // clang-format on 262 outCmd->cmdFlag = CMD_FORWARD_INIT; 263 outCmd->parameters = input; 264 } 265 return stringError; 266 } 267 268 string RunMode(const char *input, FormatCommand *outCmd) 269 { 270 string stringError; 271 outCmd->cmdFlag = CMD_UNITY_RUNMODE; 272 outCmd->parameters = input + CMDSTR_TARGET_MODE.size() + 1; // with ' ' 273 int portLength = 4; 274 int portSpaceLength = 5; 275 if (!strncmp(outCmd->parameters.c_str(), "port", portLength) && 276 !strcmp(outCmd->parameters.c_str(), CMDSTR_TMODE_USB.c_str())) { 277 stringError = "Error tmode command"; 278 outCmd->bJumpDo = true; 279 } else if (!strncmp(outCmd->parameters.c_str(), "port ", portSpaceLength)) { 280 const char *tmp = input + strlen("tmode port "); 281 // command is tmode port close 282 if (strcmp(tmp, "close") == 0) { 283 return stringError; 284 } 285 int port = atoi(tmp); 286 if (port > MAX_IP_PORT || port <= 0) { 287 stringError = "Incorrect port range"; 288 outCmd->bJumpDo = true; 289 } 290 } 291 return stringError; 292 } 293 294 void TargetReboot(const char *input, FormatCommand *outCmd) 295 { 296 outCmd->cmdFlag = CMD_UNITY_REBOOT; 297 if (strcmp(input, CMDSTR_TARGET_REBOOT.c_str())) { 298 outCmd->parameters = input + CMDSTR_TARGET_REBOOT.size() + 1; // with ' ' 299 if (outCmd->parameters == "-bootloader" || outCmd->parameters == "-recovery" || 300 outCmd->parameters == "-flashd") { 301 outCmd->parameters.erase(outCmd->parameters.begin()); 302 } 303 } 304 } 305 306 // command input 307 // client side:Enter string data formatting conversion to module see internal processing command 308 string String2FormatCommand(const char *inputRaw, int sizeInputRaw, FormatCommand *outCmd) 309 { 310 string stringError; 311 string input = string(inputRaw, sizeInputRaw); 312 if (!strncmp(input.c_str(), CMDSTR_SOFTWARE_HELP.c_str(), CMDSTR_SOFTWARE_HELP.size())) { 313 outCmd->cmdFlag = CMD_KERNEL_HELP; 314 outCmd->bJumpDo = true; 315 if (strstr(input.c_str(), " verbose")) { 316 stringError = Verbose(); 317 } else { 318 stringError = Usage(); 319 } 320 } else if (!strcmp(input.c_str(), CMDSTR_SOFTWARE_VERSION.c_str())) { 321 outCmd->cmdFlag = CMD_KERNEL_HELP; 322 stringError = Base::GetVersion(); 323 outCmd->bJumpDo = true; 324 } else if (!strcmp(input.c_str(), CMDSTR_TARGET_DISCOVER.c_str())) { 325 outCmd->cmdFlag = CMD_KERNEL_TARGET_DISCOVER; 326 } else if (!strncmp(input.c_str(), CMDSTR_LIST_TARGETS.c_str(), CMDSTR_LIST_TARGETS.size())) { 327 outCmd->cmdFlag = CMD_KERNEL_TARGET_LIST; 328 if (strstr(input.c_str(), " -v")) { 329 outCmd->parameters = "v"; 330 } 331 } else if (!strncmp(input.c_str(), CMDSTR_CHECK_SERVER.c_str(), CMDSTR_CHECK_SERVER.size())) { 332 outCmd->cmdFlag = CMD_CHECK_SERVER; 333 } else if (!strncmp(input.c_str(), CMDSTR_CHECK_DEVICE.c_str(), CMDSTR_CHECK_DEVICE.size())) { 334 outCmd->parameters = input.c_str() + CMDSTR_CHECK_DEVICE.size() + 1; // with ' ' 335 outCmd->cmdFlag = CMD_CHECK_DEVICE; 336 } else if (!strncmp(input.c_str(), CMDSTR_WAIT_FOR.c_str(), CMDSTR_WAIT_FOR.size())) { 337 outCmd->cmdFlag = CMD_WAIT_FOR; 338 } else if (!strcmp(input.c_str(), CMDSTR_CONNECT_ANY.c_str())) { 339 outCmd->cmdFlag = CMD_KERNEL_TARGET_ANY; 340 } else if (!strncmp(input.c_str(), CMDSTR_CONNECT_TARGET.c_str(), CMDSTR_CONNECT_TARGET.size())) { 341 outCmd->parameters = input.c_str() + CMDSTR_CONNECT_TARGET.size() + 1; // with ' ' 342 stringError = TargetConnect(outCmd); 343 } else if (!strncmp(input.c_str(), (CMDSTR_SHELL + " ").c_str(), CMDSTR_SHELL.size() + 1)) { 344 outCmd->cmdFlag = CMD_UNITY_EXECUTE; 345 outCmd->parameters = input.c_str() + CMDSTR_SHELL.size() + 1; 346 } else if (!strcmp(input.c_str(), CMDSTR_SHELL.c_str())) { 347 outCmd->cmdFlag = CMD_SHELL_INIT; 348 } else if (!strncmp(input.c_str(), CMDSTR_FILE_SEND.c_str(), CMDSTR_FILE_SEND.size()) || 349 !strncmp(input.c_str(), CMDSTR_FILE_RECV.c_str(), CMDSTR_FILE_RECV.size())) { 350 outCmd->cmdFlag = CMD_FILE_INIT; 351 outCmd->parameters = input.c_str() + strlen("file "); 352 } else if (!strncmp(input.c_str(), string(CMDSTR_FORWARD_FPORT + " ").c_str(), CMDSTR_FORWARD_FPORT.size() + 1) 353 || !strncmp(input.c_str(), string(CMDSTR_FORWARD_RPORT + " ").c_str(), 354 CMDSTR_FORWARD_RPORT.size() + 1)) { 355 stringError = ForwardPort(input.c_str(), outCmd); 356 } else if (!strncmp(input.c_str(), CMDSTR_APP_INSTALL.c_str(), CMDSTR_APP_INSTALL.size())) { 357 outCmd->cmdFlag = CMD_APP_INIT; 358 outCmd->parameters = input; 359 } else if (!strncmp(input.c_str(), CMDSTR_APP_UNINSTALL.c_str(), CMDSTR_APP_UNINSTALL.size())) { 360 outCmd->cmdFlag = CMD_APP_UNINSTALL; 361 outCmd->parameters = input; 362 if (outCmd->parameters.size() > MAX_APP_PARAM_SIZE || outCmd->parameters.size() < MIN_APP_PARAM_SIZE) { 363 stringError = "Package's path incorrect"; 364 outCmd->bJumpDo = true; 365 } 366 } else if (!strcmp(input.c_str(), CMDSTR_TARGET_MOUNT.c_str())) { 367 outCmd->cmdFlag = CMD_UNITY_REMOUNT; 368 } else if (!strcmp(input.c_str(), CMDSTR_LIST_JDWP.c_str())) { 369 outCmd->cmdFlag = CMD_JDWP_LIST; 370 } else if (!strncmp(input.c_str(), CMDSTR_TRACK_JDWP.c_str(), CMDSTR_TRACK_JDWP.size())) { 371 outCmd->cmdFlag = CMD_JDWP_TRACK; 372 if (strstr(input.c_str(), " -p")) { 373 outCmd->parameters = "p"; 374 } else if (strstr(input.c_str(), " -a")) { 375 outCmd->parameters = "a"; 376 } 377 } else if (!strncmp(input.c_str(), CMDSTR_TARGET_REBOOT.c_str(), CMDSTR_TARGET_REBOOT.size())) { 378 TargetReboot(input.c_str(), outCmd); 379 } else if (!strncmp(input.c_str(), CMDSTR_TARGET_MODE.c_str(), CMDSTR_TARGET_MODE.size())) { 380 stringError = RunMode(input.c_str(), outCmd); 381 } else if (!strncmp(input.c_str(), CMDSTR_HILOG.c_str(), CMDSTR_HILOG.size())) { 382 outCmd->cmdFlag = CMD_UNITY_HILOG; 383 if (strstr(input.c_str(), " -h")) { 384 outCmd->parameters = "h"; 385 } 386 } else if (!strncmp(input.c_str(), CMDSTR_STARTUP_MODE.c_str(), CMDSTR_STARTUP_MODE.size())) { 387 outCmd->cmdFlag = CMD_UNITY_ROOTRUN; 388 if (strstr(input.c_str(), " -r")) { 389 outCmd->parameters = "r"; 390 } 391 } else if (!strncmp(input.c_str(), CMDSTR_APP_SIDELOAD.c_str(), CMDSTR_APP_SIDELOAD.size())) { 392 if (strlen(input.c_str()) == CMDSTR_APP_SIDELOAD.size()) { 393 stringError = "Incorrect command, please with local path"; 394 outCmd->bJumpDo = true; 395 } 396 outCmd->cmdFlag = CMD_APP_SIDELOAD; 397 outCmd->parameters = input; 398 } else if (!strncmp(input.c_str(), CMDSTR_BUGREPORT.c_str(), CMDSTR_BUGREPORT.size())) { 399 outCmd->cmdFlag = CMD_UNITY_BUGREPORT_INIT; 400 outCmd->parameters = input; 401 if (outCmd->parameters.size() == CMDSTR_BUGREPORT.size() + 1) { // 1 is sizeInputRaw = input.size() + 1 402 outCmd->parameters = CMDSTR_BUGREPORT + " "; 403 } 404 } 405 // Inner command, protocol uses only 406 else if (!strncmp(input.c_str(), CMDSTR_INNER_ENABLE_KEEPALIVE.c_str(), CMDSTR_INNER_ENABLE_KEEPALIVE.size())) { 407 outCmd->cmdFlag = CMD_KERNEL_ENABLE_KEEPALIVE; 408 } else if (HostUpdater::CheckMatchUpdate(input, *outCmd)) { 409 outCmd->parameters = input; 410 } else { 411 stringError = "Unknown command..."; 412 outCmd->bJumpDo = true; 413 } 414#ifdef HDC_DEBUG 415 WRITE_LOG(LOG_DEBUG, "String2FormatCommand cmdFlag:%d", outCmd->cmdFlag); 416#endif 417 // nl 418 if (stringError.size()) { 419 stringError += "\n"; 420 } 421 return stringError; 422 }; 423} 424} // namespace Hdc 425