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