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