• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 "ext_client.h"
16 #include "libgen.h"
17 #include "common.h"
18 
19 namespace Hdc {
ExtClient()20 ExtClient::ExtClient()
21 {
22 #ifdef _WIN32
23     const char *path = "libexternal_hdc.dll";
24 #elif HOST_MAC
25     const char *path = "libexternal_hdc.dylib";
26 #else
27     const char *path = "libexternal_hdc.z.so";
28 #endif
29     int rc = uv_dlopen(path, &lib);
30     if (rc != 0) {
31         WRITE_LOG(LOG_FATAL, "uv_dlopen failed %s %s", path, uv_dlerror(&lib));
32     }
33     RegistExecFunc(&lib);
34 }
35 
~ExtClient()36 ExtClient::~ExtClient()
37 {
38     uv_dlclose(&lib);
39 }
40 
SharedLibraryExist()41 bool ExtClient::SharedLibraryExist()
42 {
43 #ifdef _WIN32
44     const char *path = "libexternal_hdc.dll";
45 #elif HOST_MAC
46     const char *path = "libexternal_hdc.dylib";
47 #else
48     const char *path = "libexternal_hdc.z.so";
49 #endif
50     uv_lib_t lib;
51     int rc = uv_dlopen(path, &lib);
52     if (rc != 0) {
53         return false;
54     }
55     uv_dlclose(&lib);
56     return true;
57 }
58 
ExecuteCommand(const string & command)59 void ExtClient::ExecuteCommand(const string &command)
60 {
61     if (!strncmp(command.c_str(), CMDSTR_SOFTWARE_VERSION.c_str(), CMDSTR_SOFTWARE_VERSION.size())) {
62         Version(command);
63     } else if (!strncmp(command.c_str(), CMDSTR_SOFTWARE_HELP.c_str(), CMDSTR_SOFTWARE_HELP.size())) {
64         Help(command);
65     } else if (!strncmp(command.c_str(), CMDSTR_TARGET_DISCOVER.c_str(), CMDSTR_TARGET_DISCOVER.size())) {
66         Discover(command);
67     } else if (!strncmp(command.c_str(), CMDSTR_SERVICE_START.c_str(), CMDSTR_SERVICE_START.size())) {
68         Start(command);
69     } else if (!strncmp(command.c_str(), CMDSTR_SERVICE_KILL.c_str(), CMDSTR_SERVICE_KILL.size())) {
70         Kill(command);
71     } else if (!strncmp(command.c_str(), CMDSTR_CONNECT_TARGET.c_str(), CMDSTR_CONNECT_TARGET.size())) {
72         Connect(command);
73     } else if (!strncmp(command.c_str(), CMDSTR_LIST_TARGETS.c_str(), CMDSTR_LIST_TARGETS.size())) {
74         ListTargets(command);
75     } else if (!strncmp(command.c_str(), CMDSTR_SHELL.c_str(), CMDSTR_SHELL.size())) {
76         Shell(command);
77     } else if (!strncmp(command.c_str(), CMDSTR_FILE_SEND.c_str(), CMDSTR_FILE_SEND.size()) ||
78                !strncmp(command.c_str(), CMDSTR_FILE_RECV.c_str(), CMDSTR_FILE_RECV.size())) {
79         File(command);
80     } else if (!strncmp(command.c_str(), CMDSTR_APP_INSTALL.c_str(), CMDSTR_APP_INSTALL.size())) {
81         Install(command);
82     } else if (!strncmp(command.c_str(), CMDSTR_APP_UNINSTALL.c_str(), CMDSTR_APP_UNINSTALL.size())) {
83         Uninstall(command);
84     } else if (!strncmp(command.c_str(), CMDSTR_FORWARD_FPORT.c_str(), CMDSTR_FORWARD_FPORT.size())) {
85         Fport(command);
86     } else if (!strncmp(command.c_str(), CMDSTR_FORWARD_RPORT.c_str(), CMDSTR_FORWARD_RPORT.size())) {
87         Rport(command);
88     } else if (!strncmp(command.c_str(), CMDSTR_LIST_JDWP.c_str(), CMDSTR_LIST_JDWP.size())) {
89         Jpid(command);
90     } else if (!strncmp(command.c_str(), CMDSTR_TRACK_JDWP.c_str(), CMDSTR_TRACK_JDWP.size())) {
91         TrackJpid(command);
92     } else if (!strncmp(command.c_str(), (CMDSTR_SHELL + " ").c_str(), CMDSTR_SHELL.size() + 1) ||
93                !strncmp(command.c_str(), CMDSTR_TARGET_REBOOT.c_str(), CMDSTR_TARGET_REBOOT.size()) ||
94                !strncmp(command.c_str(), CMDSTR_TARGET_MOUNT.c_str(), CMDSTR_TARGET_MOUNT.size()) ||
95                !strncmp(command.c_str(), CMDSTR_STARTUP_MODE.c_str(), CMDSTR_STARTUP_MODE.size()) ||
96                !strncmp(command.c_str(), CMDSTR_TARGET_MODE.c_str(), CMDSTR_TARGET_MODE.size()) ||
97                !strncmp(command.c_str(), CMDSTR_HILOG.c_str(), CMDSTR_HILOG.size())) {
98         Utility(command);
99     } else if (!strncmp(command.c_str(), CMDSTR_BUGREPORT.c_str(), CMDSTR_BUGREPORT.size())) {
100         Bugreport(command);
101     } else if (!strncmp(command.c_str(), CMDSTR_WAIT_FOR.c_str(), CMDSTR_WAIT_FOR.size())) {
102         WaitFor(command);
103     } else {
104         UnknowCommand(command);
105     }
106 }
107 
Version(const std::string & str)108 void ExtClient::Version(const std::string &str)
109 {
110     const char *name = "HdcExtVersion";
111     Handle(str, name);
112 }
113 
Help(const std::string & str)114 void ExtClient::Help(const std::string &str)
115 {
116     const char *name = "HdcExtHelp";
117     Handle(str, name);
118 }
119 
Discover(const std::string & str)120 void ExtClient::Discover(const std::string &str)
121 {
122     const char *name = "HdcExtDiscover";
123     Handle(str, name);
124 }
125 
Start(const std::string & str)126 void ExtClient::Start(const std::string &str)
127 {
128     const char *name = "HdcExtStart";
129     Handle(str, name);
130 }
131 
Kill(const std::string & str)132 void ExtClient::Kill(const std::string &str)
133 {
134     const char *name = "HdcExtKill";
135     Handle(str, name);
136 }
137 
Connect(const std::string & str)138 void ExtClient::Connect(const std::string &str)
139 {
140     const char *name = "HdcExtConnect";
141     Handle(str, name);
142 }
143 
ListTargets(const std::string & str)144 void ExtClient::ListTargets(const std::string &str)
145 {
146     typedef void (*HdcExtListTargets)(const char *, uint64_t, char *, uint64_t &);
147     const char *name = "HdcExtListTargets";
148     HdcExtListTargets listTargets;
149     int rc = uv_dlsym(&lib, name, (void **) &listTargets);
150     if (rc != 0) {
151         WRITE_LOG(LOG_FATAL, "uv_dlsym %s failed %s", name, uv_dlerror(&lib));
152     } else {
153         uint64_t size = 4096;
154         char *buffer = new(std::nothrow) char[size]();
155         if (buffer == nullptr) {
156             WRITE_LOG(LOG_FATAL, "new buffer failed with function %s", name);
157             return;
158         }
159         listTargets(str.c_str(), str.size(), buffer, size);
160         string extdevs(buffer);
161         UpdateList(extdevs);
162         delete[] buffer;
163         if (extdevs.empty()) {
164             return;
165         }
166         if (g_show) {
167             const string listv = "list targets -v";
168             if (!strncmp(str.c_str(), listv.c_str(), listv.size())) {
169                 string all = extdevs;
170                 all = Base::ReplaceAll(all, "\n", "\texternal\n");
171                 Base::PrintMessage("%s", all.c_str());
172             } else {
173                 Base::PrintMessage("%s", extdevs.c_str());
174             }
175         }
176     }
177 }
178 
UpdateList(const string & str)179 void ExtClient::UpdateList(const string &str)
180 {
181     if (str.empty()) {
182         return;
183     }
184     vector<string> devs;
185     Base::SplitString(str, "\n", devs);
186     for (size_t i = 0; i < devs.size(); i++) {
187         string::size_type pos = devs[i].find("\t");
188         if (pos != string::npos || (pos = devs[i].find(" ")) != string::npos) {
189             string key = devs[i].substr(0, pos);
190             g_lists[key] = "external";
191         }
192     }
193 }
194 
Shell(const std::string & str)195 void ExtClient::Shell(const std::string &str)
196 {
197     const char *name = "HdcExtShell";
198     string value = WithConnectKey(str);
199     Handle(value, name);
200 }
201 
File(const std::string & str)202 void ExtClient::File(const std::string &str)
203 {
204     const char *name = "HdcExtFile";
205     std::string cmd = RemoveRemoteCwd(str);
206     string value = WithConnectKey(cmd);
207     Handle(value, name);
208 }
209 
Install(const std::string & str)210 void ExtClient::Install(const std::string &str)
211 {
212     const char *name = "HdcExtInstall";
213     std::string cmd = RemoveRemoteCwd(str);
214     string value = WithConnectKey(cmd);
215     Handle(value, name);
216 }
217 
Uninstall(const std::string & str)218 void ExtClient::Uninstall(const std::string &str)
219 {
220     const char *name = "HdcExtUninstall";
221     string value = WithConnectKey(str);
222     Handle(value, name);
223 }
224 
Fport(const std::string & str)225 void ExtClient::Fport(const std::string &str)
226 {
227     const char *name = "HdcExtFport";
228     string value = WithConnectKey(str);
229     Handle(value, name);
230 }
231 
Rport(const std::string & str)232 void ExtClient::Rport(const std::string &str)
233 {
234     const char *name = "HdcExtRport";
235     string value = WithConnectKey(str);
236     Handle(value, name);
237 }
238 
Jpid(const std::string & str)239 void ExtClient::Jpid(const std::string &str)
240 {
241     const char *name = "HdcExtJpid";
242     string value = WithConnectKey(str);
243     Handle(value, name);
244 }
245 
TrackJpid(const std::string & str)246 void ExtClient::TrackJpid(const std::string &str)
247 {
248     const char *name = "HdcExtTrackJpid";
249     string value = WithConnectKey(str);
250     Handle(value, name);
251 }
252 
Utility(const std::string & str)253 void ExtClient::Utility(const std::string &str)
254 {
255     const char *name = "HdcExtUtility";
256     string value = WithConnectKey(str);
257     Handle(value, name);
258 }
259 
Bugreport(const std::string & str)260 void ExtClient::Bugreport(const std::string &str)
261 {
262     const char *name = "HdcExtBugreport";
263     string value = WithConnectKey(str);
264     Handle(value, name);
265 }
266 
WaitFor(const std::string & str)267 void ExtClient::WaitFor(const std::string &str)
268 {
269     std::thread([str]() {
270         WaitForExtent(str);
271         _exit(0);
272     }).detach();
273 }
274 
UnknowCommand(const std::string & str)275 void ExtClient::UnknowCommand(const std::string &str)
276 {
277     const char *name = "HdcExtUnknowCommand";
278     Handle(str, name);
279 }
280 
RemoveRemoteCwd(const std::string & str)281 std::string ExtClient::RemoveRemoteCwd(const std::string &str)
282 {
283     int argc = 0;
284     std::string cmd = str;
285     char **argv = Base::SplitCommandToArgs(cmd.c_str(), &argc);
286     if(argv == nullptr) {
287         return cmd;
288     }
289     for (int i = 0; i < argc; i++) {
290         if (argv[i] == CMDSTR_REMOTE_PARAMETER) {
291             std::string remove = Base::StringFormat("%s %s \"%s\" ", argv[i], argv[i + 1], argv[i + 2]);
292             if (cmd.find(remove) != std::string::npos) {
293                 cmd.replace(cmd.find(remove), remove.size(), "");
294             }
295             break;
296         }
297     }
298     delete[](reinterpret_cast<char *>(argv));
299     return cmd;
300 }
301 
Handle(const std::string & str,const char * name)302 void ExtClient::Handle(const std::string &str, const char *name)
303 {
304     typedef void (*HdcExtCommand)(const char *, uint64_t, char *, uint64_t &);
305     HdcExtCommand command;
306     int rc = uv_dlsym(&lib, name, (void **) &command);
307     if (rc != 0) {
308         WRITE_LOG(LOG_FATAL, "uv_dlsym %s failed %s", name, uv_dlerror(&lib));
309     } else {
310         uint64_t size = 4096;
311         char *buffer = new(std::nothrow) char[size]();
312         if (buffer == nullptr) {
313             WRITE_LOG(LOG_FATAL, "new buffer failed with function %s", name);
314             return;
315         }
316         command(str.c_str(), str.size(), buffer, size);
317         std::string strBuf(buffer);
318         if (!strBuf.empty()) {
319             Base::PrintMessage("%s", strBuf.c_str());
320         }
321         delete[] buffer;
322     }
323 }
324 
WithConnectKey(const string & str)325 std::string ExtClient::WithConnectKey(const string &str)
326 {
327     std::string value;
328     if (!connectKey.empty()) {
329         value = "-t " + connectKey + " ";
330     }
331     if (!containerInOut.empty()) {
332         value = value + containerInOut + " ";
333     }
334     value = value + str;
335     return value;
336 }
337 
WaitForExtent(const std::string & str)338 void ExtClient::WaitForExtent(const std::string &str)
339 {
340     uv_lib_t lib;
341 #ifdef _WIN32
342     const char *path = "libexternal_hdc.dll";
343 #elif HOST_MAC
344     const char *path = "libexternal_hdc.dylib";
345 #else
346     const char *path = "libexternal_hdc.z.so";
347 #endif
348     int rc = uv_dlopen(path, &lib);
349     if (rc != 0) {
350         WRITE_LOG(LOG_FATAL, "uv_dlopen failed %s %s", path, uv_dlerror(&lib));
351         return;
352     }
353     RegistExecFunc(&lib);
354     const char *name = "HdcExtWaitFor";
355     typedef void (*HdcExtCommand)(const char *, uint64_t, char *, uint64_t &);
356     HdcExtCommand command;
357     rc = uv_dlsym(&lib, name, (void **) &command);
358     if (rc != 0) {
359         WRITE_LOG(LOG_FATAL, "uv_dlsym %s failed %s", name, uv_dlerror(&lib));
360     } else {
361         uint64_t size = 4096;
362         char *buffer = new(std::nothrow) char[size]();
363         if (buffer == nullptr) {
364             WRITE_LOG(LOG_FATAL, "new buffer failed with function %s", name);
365             return;
366         }
367         command(str.c_str(), str.size(), buffer, size);
368         std::string strBuf(buffer);
369         if (!strBuf.empty()) {
370             Base::PrintMessage("%s", strBuf.c_str());
371         }
372         delete[] buffer;
373     }
374     uv_dlclose(&lib);
375 }
376 
OnExit(uv_process_t * req,int64_t exitStatus,int termSignal)377 static void OnExit(uv_process_t *req, int64_t exitStatus, int termSignal)
378 {
379     uv_close((uv_handle_t*) req, nullptr);
380 }
381 
ExternalExecFunc(int argc,char * argv[])382 static int ExternalExecFunc(int argc, char *argv[])
383 {
384 #define EXTERNAL_KEEP_FDS 3
385     uv_loop_t loop;
386     uv_process_t childReq = { 0 };
387     uv_process_options_t options = { 0 };
388     uv_stdio_container_t childStdio[EXTERNAL_KEEP_FDS];
389 
390     if (argc <= 0) {
391         return 1;
392     }
393 
394     uv_loop_init(&loop);
395 
396     for (int i = 0; i < EXTERNAL_KEEP_FDS; i++) {
397         childStdio[i].flags = UV_INHERIT_FD;
398         childStdio[i].data.fd = i;
399     }
400 
401     size_t pathSize = BUF_SIZE_DEFAULT4;
402     char execPath[pathSize];
403     (void)memset_s(execPath, pathSize, 0, pathSize);
404     int ret = uv_exepath(execPath, &pathSize);
405     if (ret < 0) {
406         return 1;
407     }
408     string path = string(dirname(execPath)) + "/" + string(argv[0]);
409     options.file = path.c_str();
410     options.args = argv;
411     options.exit_cb = OnExit;
412     options.stdio_count = EXTERNAL_KEEP_FDS;
413     options.stdio = childStdio;
414 
415     if (uv_spawn(&loop, &childReq, &options) != 0) {
416         return 1;
417     }
418     uv_run(&loop, UV_RUN_DEFAULT);
419 
420 #ifdef HOST_MINGW
421     DWORD status = 0;
422     if (GetExitCodeProcess(childReq.process_handle, &status)) {
423         return uv_translate_sys_error(GetLastError());
424     }
425 #else
426     int status = 0;
427     if (!WIFEXITED(childReq.status)) {
428         return errno;
429     }
430     status = WEXITSTATUS(childReq.status);
431 #endif
432     return static_cast<int>(status);
433 }
434 
RegistExecFunc(uv_lib_t * lib)435 void ExtClient::RegistExecFunc(uv_lib_t *lib)
436 {
437     typedef void (*HdcExtRegistExec)(int *);
438     HdcExtRegistExec registExec;
439     const char *name = "HdcExtRegistExecFunc";
440     int rc = uv_dlsym(lib, name, (void **) &registExec);
441     if (rc == 0) {
442         registExec(reinterpret_cast<int *>(ExternalExecFunc));
443     }
444 }
445 }
446 
447