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