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 "server_for_client.h"
16 #ifndef TEST_HASH
17 #include "hdc_hash_gen.h"
18 #endif
19 #include "server.h"
20
21 namespace Hdc {
HdcServerForClient(const bool serverOrClient,const string & addrString,void * pClsServer,uv_loop_t * loopMainIn)22 HdcServerForClient::HdcServerForClient(const bool serverOrClient, const string &addrString, void *pClsServer,
23 uv_loop_t *loopMainIn)
24 : HdcChannelBase(serverOrClient, addrString, loopMainIn)
25 {
26 clsServer = pClsServer;
27 }
28
~HdcServerForClient()29 HdcServerForClient::~HdcServerForClient()
30 {
31 WRITE_LOG(LOG_DEBUG, "~HdcServerForClient");
32 }
33
Stop()34 void HdcServerForClient::Stop()
35 {
36 Base::TryCloseHandle((uv_handle_t *)&tcpListen);
37 }
38
GetTCPListenPort()39 uint16_t HdcServerForClient::GetTCPListenPort()
40 {
41 return channelPort;
42 }
43
AcceptClient(uv_stream_t * server,int status)44 void HdcServerForClient::AcceptClient(uv_stream_t *server, int status)
45 {
46 uv_tcp_t *pServTCP = (uv_tcp_t *)server;
47 HdcServerForClient *thisClass = (HdcServerForClient *)pServTCP->data;
48 HChannel hChannel = nullptr;
49 uint32_t uid = thisClass->MallocChannel(&hChannel);
50 if (!hChannel) {
51 return;
52 }
53 if (uv_accept(server, (uv_stream_t *)&hChannel->hWorkTCP) < 0) {
54 thisClass->FreeChannel(uid);
55 return;
56 }
57 WRITE_LOG(LOG_DEBUG, "HdcServerForClient acceptClient");
58 // limit first recv
59 int bufMaxSize = 0;
60 uv_recv_buffer_size((uv_handle_t *)&hChannel->hWorkTCP, &bufMaxSize);
61 auto funcChannelHeaderAlloc = [](uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf) -> void {
62 HChannel context = (HChannel)handle->data;
63 Base::ReallocBuf(&context->ioBuf, &context->bufSize, sizeWanted); // sizeWanted default 6k
64 buf->base = (char *)context->ioBuf + context->availTailIndex;
65 #ifdef HDC_VERSION_CHECK
66 buf->len = sizeof(struct ChannelHandShake) + DWORD_SERIALIZE_SIZE; // only recv static size
67 #else
68 buf->len = offsetof(struct ChannelHandShake, version) + DWORD_SERIALIZE_SIZE;
69 #endif
70 };
71 // first packet static size, after this packet will be dup for normal recv
72 uv_read_start((uv_stream_t *)&hChannel->hWorkTCP, funcChannelHeaderAlloc, ReadStream);
73 // channel handshake step1
74 struct ChannelHandShake handShake = {};
75 if (EOK == strcpy_s(handShake.banner, sizeof(handShake.banner), HANDSHAKE_MESSAGE.c_str())) {
76 handShake.channelId = htonl(hChannel->channelId);
77 string ver = Base::GetVersion() + HDC_MSG_HASH;
78 WRITE_LOG(LOG_DEBUG, "Server ver:%s", ver.c_str());
79 if (EOK != strcpy_s(handShake.version, sizeof(handShake.version), ver.c_str())) {
80 WRITE_LOG(LOG_FATAL, "strcpy_s failed");
81 return;
82 }
83 #ifdef HDC_VERSION_CHECK
84 thisClass->Send(hChannel->channelId, (uint8_t *)&handShake, sizeof(struct ChannelHandShake));
85 #else
86 // do not send version message if check feature disable
87 thisClass->Send(hChannel->channelId, reinterpret_cast<uint8_t *>(&handShake),
88 offsetof(struct ChannelHandShake, version));
89 #endif
90 }
91 }
92
SetTCPListen()93 void HdcServerForClient::SetTCPListen()
94 {
95 tcpListen.data = this;
96 struct sockaddr_in6 addr;
97 uv_tcp_init(loopMain, &tcpListen);
98
99 WRITE_LOG(LOG_DEBUG, "channelHost %s, port: %d", channelHost.c_str(), channelPort);
100 uv_ip6_addr(channelHost.c_str(), channelPort, &addr);
101 uv_tcp_bind(&tcpListen, (const struct sockaddr *)&addr, 0);
102 uv_listen((uv_stream_t *)&tcpListen, 128, (uv_connection_cb)AcceptClient);
103 }
104
Initial()105 int HdcServerForClient::Initial()
106 {
107 if (!clsServer) {
108 WRITE_LOG(LOG_FATAL, "Module client initial failed");
109 return -1;
110 }
111 if (!channelHostPort.size() || !channelHost.size() || !channelPort) {
112 WRITE_LOG(LOG_FATAL, "Listen string initial failed");
113 return -2;
114 }
115 SetTCPListen();
116 return 0;
117 }
118
EchoClient(HChannel hChannel,MessageLevel level,const char * msg,...)119 void HdcServerForClient::EchoClient(HChannel hChannel, MessageLevel level, const char *msg, ...)
120 {
121 string logInfo = "";
122 switch (level) {
123 case MSG_FAIL:
124 logInfo = MESSAGE_FAIL;
125 break;
126 case MSG_INFO:
127 logInfo = MESSAGE_INFO;
128 break;
129 default: // successful, not append extra info
130 break;
131 }
132 va_list vaArgs;
133 va_start(vaArgs, msg);
134 string log = logInfo + Base::StringFormat(msg, vaArgs);
135 va_end(vaArgs);
136 if (log.back() != '\n') {
137 log += "\r\n";
138 }
139 SendChannel(hChannel, const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(log.c_str())), log.size());
140 }
141
EchoClientRaw(const HChannel hChannel,uint8_t * payload,const int payloadSize)142 void HdcServerForClient::EchoClientRaw(const HChannel hChannel, uint8_t *payload, const int payloadSize)
143 {
144 SendChannel(hChannel, payload, payloadSize);
145 }
146
147 // HdcServerForClient passthrough file command to client
SendCommandToClient(const HChannel hChannel,const uint16_t commandFlag,uint8_t * payload,const int payloadSize)148 void HdcServerForClient::SendCommandToClient(const HChannel hChannel, const uint16_t commandFlag,
149 uint8_t *payload, const int payloadSize)
150 {
151 SendChannelWithCmd(hChannel, commandFlag, payload, payloadSize);
152 }
153
SendToDaemon(HChannel hChannel,const uint16_t commandFlag,uint8_t * bufPtr,const int bufSize)154 bool HdcServerForClient::SendToDaemon(HChannel hChannel, const uint16_t commandFlag, uint8_t *bufPtr, const int bufSize)
155 {
156 HDaemonInfo hdi = nullptr;
157 bool ret = false;
158 HdcServer *ptrServer = (HdcServer *)clsServer;
159 while (true) {
160 ptrServer->AdminDaemonMap(OP_QUERY, hChannel->connectKey, hdi);
161 if (hdi == nullptr) {
162 break;
163 }
164 if (hdi->connStatus != STATUS_CONNECTED) {
165 break;
166 }
167 if (!hdi->hSession) {
168 break;
169 }
170 if (ptrServer->Send(hdi->hSession->sessionId, hChannel->channelId, commandFlag, bufPtr, bufSize) < 0) {
171 break;
172 }
173 ret = true;
174 break;
175 }
176 return ret;
177 }
178
OrderFindTargets(HChannel hChannel)179 void HdcServerForClient::OrderFindTargets(HChannel hChannel)
180 {
181 int count = 0;
182 EchoClient(hChannel, MSG_INFO, "Please add HDC server's firewall ruler to allow udp incoming, udpport:%d",
183 DEFAULT_PORT);
184 HdcServer *ptrServer = (HdcServer *)clsServer;
185 ptrServer->clsTCPClt->FindLanDaemon();
186 list<string> &lst = ptrServer->clsTCPClt->lstDaemonResult;
187 // refresh main list
188 HdcDaemonInformation di;
189 while (!lst.empty()) {
190 di = {};
191 ++count;
192 di.connectKey = lst.front();
193 di.connType = CONN_TCP;
194 di.connStatus = STATUS_READY;
195 HDaemonInfo pDi = reinterpret_cast<HDaemonInfo>(&di);
196 ptrServer->AdminDaemonMap(OP_ADD, STRING_EMPTY, pDi);
197 lst.pop_front();
198 }
199 EchoClient(hChannel, MSG_INFO, "Broadcast find daemon, total:%d", count);
200 #ifdef UNIT_TEST
201 string bufString = std::to_string(count);
202 Base::WriteBinFile((UT_TMP_PATH + "/base-discover.result").c_str(), (uint8_t *)bufString.c_str(), bufString.size(),
203 true);
204 #endif
205 }
206
OrderConnecTargetResult(uv_timer_t * req)207 void HdcServerForClient::OrderConnecTargetResult(uv_timer_t *req)
208 {
209 HChannel hChannel = (HChannel)req->data;
210 HdcServerForClient *thisClass = (HdcServerForClient *)hChannel->clsChannel;
211 HdcServer *ptrServer = (HdcServer *)thisClass->clsServer;
212 bool bConnectOK = false;
213 bool bExitRepet = false;
214 HDaemonInfo hdi = nullptr;
215 string sRet;
216 string target = std::string(hChannel->bufStd + 2);
217 if (target == "any") {
218 ptrServer->AdminDaemonMap(OP_GET_ANY, target, hdi);
219 } else {
220 ptrServer->AdminDaemonMap(OP_QUERY, target, hdi);
221 }
222 if (hdi && hdi->connStatus == STATUS_CONNECTED) {
223 bConnectOK = true;
224 }
225 while (true) {
226 if (bConnectOK) {
227 bExitRepet = true;
228 if (hChannel->isCheck) {
229 WRITE_LOG(LOG_INFO, "%s check device success and remove %s", __FUNCTION__, hChannel->key.c_str());
230 thisClass->CommandRemoveSession(hChannel, hChannel->key.c_str());
231 thisClass->EchoClient(hChannel, MSG_OK, const_cast<char *>(hdi->version.c_str()));
232 } else {
233 sRet = "Connect OK";
234 thisClass->EchoClient(hChannel, MSG_OK, const_cast<char *>(sRet.c_str()));
235 }
236 break;
237 } else {
238 uint16_t *bRetryCount = reinterpret_cast<uint16_t *>(hChannel->bufStd);
239 ++(*bRetryCount);
240 if (*bRetryCount > 500) {
241 // 5s
242 bExitRepet = true;
243 sRet = "Connect failed";
244 thisClass->EchoClient(hChannel, MSG_FAIL, const_cast<char *>(sRet.c_str()));
245 break;
246 }
247 }
248 break;
249 }
250 if (bExitRepet) {
251 thisClass->FreeChannel(hChannel->channelId);
252 Base::TryCloseHandle((const uv_handle_t *)req, Base::CloseTimerCallback);
253 }
254 }
255
NewConnectTry(void * ptrServer,HChannel hChannel,const string & connectKey,bool isCheck)256 bool HdcServerForClient::NewConnectTry(void *ptrServer, HChannel hChannel, const string &connectKey, bool isCheck)
257 {
258 #ifdef HDC_DEBUG
259 WRITE_LOG(LOG_ALL, "%s %s", __FUNCTION__, connectKey.c_str());
260 #endif
261 int childRet = ((HdcServer *)ptrServer)->CreateConnect(connectKey, isCheck);
262 bool ret = false;
263 if (childRet == -1) {
264 EchoClient(hChannel, MSG_INFO, "Target is connected, repeat operation");
265 } else if (childRet == -2) {
266 EchoClient(hChannel, MSG_FAIL, "CreateConnect failed");
267 WRITE_LOG(LOG_FATAL, "CreateConnect failed");
268 } else {
269 Base::ZeroBuf(hChannel->bufStd, 2);
270 childRet = snprintf_s(hChannel->bufStd + 2, sizeof(hChannel->bufStd) - 2, sizeof(hChannel->bufStd) - 3, "%s",
271 const_cast<char *>(connectKey.c_str()));
272 if (childRet > 0) {
273 Base::TimerUvTask(loopMain, hChannel, OrderConnecTargetResult, 10);
274 ret = true;
275 }
276 }
277 return ret;
278 }
279
CommandRemoveSession(HChannel hChannel,const char * connectKey)280 bool HdcServerForClient::CommandRemoveSession(HChannel hChannel, const char *connectKey)
281 {
282 HdcServer *ptrServer = (HdcServer *)clsServer;
283 HDaemonInfo hdiOld = nullptr;
284 (reinterpret_cast<HdcServer *>(ptrServer))->AdminDaemonMap(OP_QUERY, connectKey, hdiOld);
285 if (!hdiOld) {
286 EchoClient(hChannel, MSG_FAIL, "No target available");
287 return false;
288 }
289 (reinterpret_cast<HdcServer *>(ptrServer))->FreeSession(hdiOld->hSession->sessionId);
290 return true;
291 }
292
CommandRemoveForward(const string & forwardKey)293 bool HdcServerForClient::CommandRemoveForward(const string &forwardKey)
294 {
295 HdcServer *ptrServer = (HdcServer *)clsServer;
296 HForwardInfo hfi = nullptr;
297 ptrServer->AdminForwardMap(OP_QUERY, forwardKey, hfi);
298 if (!hfi) {
299 return false;
300 }
301 HSession hSession = ptrServer->AdminSession(OP_QUERY, hfi->sessionId, nullptr);
302 if (!hSession) {
303 ptrServer->AdminForwardMap(OP_REMOVE, forwardKey, hfi);
304 return true;
305 }
306 ptrServer->ClearOwnTasks(hSession, hfi->channelId);
307 FreeChannel(hfi->channelId);
308 hfi = nullptr;
309 ptrServer->AdminForwardMap(OP_REMOVE, forwardKey, hfi);
310 return true;
311 }
312
GetTargetList(HChannel hChannel,void * formatCommandInput)313 void HdcServerForClient::GetTargetList(HChannel hChannel, void *formatCommandInput)
314 {
315 TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput;
316 HdcServer *ptrServer = (HdcServer *)clsServer;
317 uint16_t cmd = OP_GET_STRLIST;
318 if (formatCommand->parameters == "v") {
319 cmd = OP_GET_STRLIST_FULL;
320 }
321 HDaemonInfo hdi = nullptr;
322 string sRet = ptrServer->AdminDaemonMap(cmd, STRING_EMPTY, hdi);
323 if (!sRet.length()) {
324 sRet = EMPTY_ECHO;
325 }
326 EchoClient(hChannel, MSG_OK, const_cast<char *>(sRet.c_str()));
327 #ifdef UNIT_TEST
328 Base::WriteBinFile((UT_TMP_PATH + "/base-list.result").c_str(), (uint8_t *)MESSAGE_SUCCESS.c_str(),
329 MESSAGE_SUCCESS.size(), true);
330 #endif
331 }
332
GetAnyTarget(HChannel hChannel)333 bool HdcServerForClient::GetAnyTarget(HChannel hChannel)
334 {
335 HdcServer *ptrServer = (HdcServer *)clsServer;
336 HDaemonInfo hdi = nullptr;
337 ptrServer->AdminDaemonMap(OP_GET_ANY, STRING_EMPTY, hdi);
338 if (!hdi) {
339 EchoClient(hChannel, MSG_FAIL, "No target available");
340 return false;
341 }
342 // can not use hdi->connectKey.This memory may be released to re-Malloc
343 string connectKey = hdi->connectKey;
344 bool ret = NewConnectTry(ptrServer, hChannel, connectKey);
345 #ifdef UNIT_TEST
346 Base::WriteBinFile((UT_TMP_PATH + "/base-any.result").c_str(), (uint8_t *)MESSAGE_SUCCESS.c_str(),
347 MESSAGE_SUCCESS.size(), true);
348 #endif
349 return ret;
350 }
351
WaitForAny(HChannel hChannel)352 bool HdcServerForClient::WaitForAny(HChannel hChannel)
353 {
354 HdcServer *ptrServer = (HdcServer *)clsServer;
355 HDaemonInfo hdi = nullptr;
356 ptrServer->AdminDaemonMap(OP_WAIT_FOR_ANY, STRING_EMPTY, hdi);
357 if (!hdi) {
358 EchoClient(hChannel, MSG_FAIL, "No any connected target");
359 return false;
360 }
361 string key = hdi->connectKey;
362 EchoClient(hChannel, MSG_OK, "Wait for connected target is %s", key.c_str());
363 return true;
364 }
365
RemoveForward(HChannel hChannel,const char * parameterString)366 bool HdcServerForClient::RemoveForward(HChannel hChannel, const char *parameterString)
367 {
368 HdcServer *ptrServer = (HdcServer *)clsServer;
369 if (parameterString == nullptr) { // remove all
370 HForwardInfo hfi = nullptr; // dummy
371 string echo = ptrServer->AdminForwardMap(OP_GET_STRLIST, "", hfi);
372 if (!echo.length()) {
373 return false;
374 }
375 vector<string> filterStrings;
376 Base::SplitString(echo, string("\n"), filterStrings);
377 for (auto &&s : filterStrings) {
378 if (CommandRemoveForward(s.c_str())) {
379 EchoClient(hChannel, MSG_OK, "Remove forward ruler success, ruler:%s", s.c_str());
380 } else {
381 EchoClient(hChannel, MSG_FAIL, "Remove forward ruler failed, ruler is not exist %s", s.c_str());
382 }
383 }
384 } else { // remove single
385 if (CommandRemoveForward(parameterString)) {
386 EchoClient(hChannel, MSG_OK, "Remove forward ruler success, ruler:%s", parameterString);
387 } else {
388 EchoClient(hChannel, MSG_FAIL, "Remove forward ruler failed, ruler is not exist %s", parameterString);
389 }
390 }
391 return true;
392 }
393
DoCommandLocal(HChannel hChannel,void * formatCommandInput)394 bool HdcServerForClient::DoCommandLocal(HChannel hChannel, void *formatCommandInput)
395 {
396 TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput;
397 HdcServer *ptrServer = (HdcServer *)clsServer;
398 bool ret = false;
399 // Main thread command, direct Listen main thread
400 switch (formatCommand->cmdFlag) {
401 case CMD_KERNEL_TARGET_DISCOVER: {
402 OrderFindTargets(hChannel);
403 ret = false;
404 break;
405 }
406 case CMD_KERNEL_TARGET_LIST: {
407 GetTargetList(hChannel, formatCommandInput);
408 ret = false;
409 break;
410 }
411 case CMD_CHECK_SERVER: {
412 WRITE_LOG(LOG_DEBUG, "CMD_CHECK_SERVER command");
413 ReportServerVersion(hChannel);
414 ret = false;
415 break;
416 }
417 case CMD_WAIT_FOR: {
418 WRITE_LOG(LOG_DEBUG, "CMD_WAIT_FOR command");
419 ret = !WaitForAny(hChannel);
420 break;
421 }
422 case CMD_KERNEL_TARGET_ANY: {
423 #ifdef HDC_DEBUG
424 WRITE_LOG(LOG_DEBUG, "%s CMD_KERNEL_TARGET_ANY %s", __FUNCTION__, formatCommand->parameters.c_str());
425 #endif
426 ret = GetAnyTarget(hChannel);
427 break;
428 }
429 case CMD_KERNEL_TARGET_CONNECT: {
430 #ifdef HDC_DEBUG
431 WRITE_LOG(LOG_DEBUG, "%s CMD_KERNEL_TARGET_CONNECT %s", __FUNCTION__, formatCommand->parameters.c_str());
432 #endif
433 ret = NewConnectTry(ptrServer, hChannel, formatCommand->parameters.c_str());
434 break;
435 }
436 case CMD_CHECK_DEVICE: {
437 WRITE_LOG(LOG_INFO, "%s CMD_CHECK_DEVICE %s", __FUNCTION__, formatCommand->parameters.c_str());
438 hChannel->isCheck = true;
439 hChannel->key = formatCommand->parameters.c_str();
440 ret = NewConnectTry(ptrServer, hChannel, formatCommand->parameters.c_str(), true);
441 break;
442 }
443 case CMD_KERNEL_TARGET_DISCONNECT: {
444 CommandRemoveSession(hChannel, formatCommand->parameters.c_str());
445 break;
446 }
447 case CMD_KERNEL_SERVER_KILL: {
448 WRITE_LOG(LOG_DEBUG, "Recv server kill command");
449 uv_stop(loopMain);
450 ret = true;
451 break;
452 }
453 // task will be global task,Therefore, it can only be controlled in the global session.
454 case CMD_FORWARD_LIST: {
455 HForwardInfo hfi = nullptr; // dummy
456 string echo = ptrServer->AdminForwardMap(OP_GET_STRLIST_FULL, "", hfi);
457 if (!echo.length()) {
458 echo = EMPTY_ECHO;
459 }
460 EchoClient(hChannel, MSG_OK, const_cast<char *>(echo.c_str()));
461 break;
462 }
463 case CMD_FORWARD_REMOVE: {
464 RemoveForward(hChannel, formatCommand->parameters.c_str());
465 break;
466 }
467 case CMD_KERNEL_ENABLE_KEEPALIVE: {
468 // just use for 'list targets' now
469 hChannel->keepAlive = true;
470 ret = true;
471 break;
472 }
473 default: {
474 EchoClient(hChannel, MSG_FAIL, "ExecuteCommand need connect-key?");
475 break;
476 }
477 }
478 return ret;
479 }
480
TaskCommand(HChannel hChannel,void * formatCommandInput)481 bool HdcServerForClient::TaskCommand(HChannel hChannel, void *formatCommandInput)
482 {
483 TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput;
484 HdcServer *ptrServer = (HdcServer *)clsServer;
485 string cmdFlag;
486 uint8_t sizeCmdFlag = 0;
487 if (formatCommand->cmdFlag == CMD_FILE_INIT) {
488 cmdFlag = "send ";
489 sizeCmdFlag = 5; // 5: cmdFlag send size
490 HandleRemote(hChannel, formatCommand->parameters, RemoteType::REMOTE_FILE);
491 } else if (formatCommand->cmdFlag == CMD_FORWARD_INIT) {
492 cmdFlag = "fport ";
493 sizeCmdFlag = 6; // 6: cmdFlag fport size
494 } else if (formatCommand->cmdFlag == CMD_APP_INIT) {
495 cmdFlag = "install ";
496 sizeCmdFlag = 8; // 8: cmdFlag install size
497 HandleRemote(hChannel, formatCommand->parameters, RemoteType::REMOTE_APP);
498 } else if (formatCommand->cmdFlag == CMD_APP_UNINSTALL) {
499 cmdFlag = "uninstall ";
500 sizeCmdFlag = 10; // 10: cmdFlag uninstall size
501 } else if (formatCommand->cmdFlag == CMD_UNITY_BUGREPORT_INIT) {
502 cmdFlag = "bugreport ";
503 sizeCmdFlag = 10; // 10: cmdFlag bugreport size
504 } else if (formatCommand->cmdFlag == CMD_APP_SIDELOAD) {
505 cmdFlag = "sideload ";
506 sizeCmdFlag = 9;
507 } else if (formatCommand->cmdFlag == CMD_FLASHD_UPDATE_INIT) {
508 cmdFlag = "update ";
509 sizeCmdFlag = 7; // 7: cmdFlag update size
510 } else if (formatCommand->cmdFlag == CMD_FLASHD_FLASH_INIT) {
511 cmdFlag = "flash ";
512 sizeCmdFlag = 6; // 6: cmdFlag flash size
513 }
514 int sizeSend = formatCommand->parameters.size();
515 if (!strncmp(formatCommand->parameters.c_str(), cmdFlag.c_str(), sizeCmdFlag)) { // local do
516 HSession hSession = FindAliveSession(hChannel->targetSessionId);
517 if (!hSession) {
518 return false;
519 }
520 if ((formatCommand->cmdFlag == CMD_FILE_INIT || formatCommand->cmdFlag == CMD_APP_INIT ) &&
521 hChannel->fromClient) {
522 // remote client mode, CMD_FILE_INIT and CMD_APP_INIT command send back to client
523 WRITE_LOG(LOG_DEBUG, "command send back to remote client channelId:%u", hChannel->channelId);
524 SendChannelWithCmd(hChannel, formatCommand->cmdFlag,
525 reinterpret_cast<uint8_t *>(const_cast<char *>(formatCommand->parameters.c_str())) + sizeCmdFlag,
526 sizeSend - sizeCmdFlag);
527 return false;
528 }
529 ptrServer->DispatchTaskData(hSession, hChannel->channelId, formatCommand->cmdFlag,
530 reinterpret_cast<uint8_t *>(const_cast<char *>(formatCommand->parameters.c_str())) + sizeCmdFlag,
531 sizeSend - sizeCmdFlag);
532 } else { // Send to Daemon-side to do
533 WRITE_LOG(LOG_INFO, "TaskCommand recv cmd send to daemon cmd = %u", formatCommand->cmdFlag);
534 SendToDaemon(hChannel, formatCommand->cmdFlag,
535 reinterpret_cast<uint8_t *>(const_cast<char *>(formatCommand->parameters.c_str())) + sizeCmdFlag,
536 sizeSend - sizeCmdFlag);
537 }
538 return true;
539 }
540
HandleRemote(HChannel hChannel,string & parameters,RemoteType flag)541 void HdcServerForClient::HandleRemote(HChannel hChannel, string ¶meters, RemoteType flag)
542 {
543 hChannel->remote = flag;
544 int argc = 0;
545 char **argv = Base::SplitCommandToArgs(parameters.c_str(), &argc);
546 for (int i = 0; i < argc; i++) {
547 if (argv[i] == CMDSTR_REMOTE_PARAMETER) {
548 hChannel->fromClient = true;
549 WRITE_LOG(LOG_DEBUG, "remote client mode channelId:%u", hChannel->channelId);
550 break;
551 }
552 }
553 if (hChannel->fromClient) {
554 string remote = CMDSTR_REMOTE_PARAMETER + " ";
555 if (parameters.find(remote) != std::string::npos) {
556 parameters.replace(parameters.find(remote), remote.size(), "");
557 WRITE_LOG(LOG_DEBUG, "parameters: %s", parameters.c_str());
558 }
559 }
560 }
561
DoCommandRemote(HChannel hChannel,void * formatCommandInput)562 bool HdcServerForClient::DoCommandRemote(HChannel hChannel, void *formatCommandInput)
563 {
564 TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput;
565 bool ret = false;
566 int sizeSend = formatCommand->parameters.size();
567 string cmdFlag;
568 switch (formatCommand->cmdFlag) {
569 // Some simple commands only need to forward the instruction, no need to start Task
570 case CMD_SHELL_INIT:
571 case CMD_SHELL_DATA:
572 case CMD_UNITY_EXECUTE:
573 case CMD_UNITY_TERMINATE:
574 case CMD_UNITY_REMOUNT:
575 case CMD_UNITY_REBOOT:
576 case CMD_UNITY_RUNMODE:
577 case CMD_UNITY_HILOG:
578 case CMD_UNITY_ROOTRUN:
579 case CMD_JDWP_TRACK:
580 case CMD_JDWP_LIST: {
581 if (!SendToDaemon(hChannel, formatCommand->cmdFlag,
582 reinterpret_cast<uint8_t *>(const_cast<char *>(formatCommand->parameters.c_str())),
583 sizeSend)) {
584 break;
585 }
586 ret = true;
587 if (formatCommand->cmdFlag == CMD_SHELL_INIT) {
588 hChannel->interactiveShellMode = true;
589 }
590 break;
591 }
592 case CMD_FILE_INIT:
593 case CMD_FORWARD_INIT:
594 case CMD_APP_INIT:
595 case CMD_APP_UNINSTALL:
596 case CMD_UNITY_BUGREPORT_INIT:
597 case CMD_APP_SIDELOAD:
598 case CMD_FLASHD_UPDATE_INIT:
599 case CMD_FLASHD_FLASH_INIT:
600 case CMD_FLASHD_ERASE:
601 case CMD_FLASHD_FORMAT: {
602 TaskCommand(hChannel, formatCommandInput);
603 ret = true;
604 break;
605 }
606 default:
607 break;
608 }
609 if (!ret) {
610 EchoClient(hChannel, MSG_FAIL, "Failed to communicate with daemon");
611 }
612 return ret;
613 }
614 // Do not specify Target's operations no longer need to put it in the thread.
DoCommand(HChannel hChannel,void * formatCommandInput)615 bool HdcServerForClient::DoCommand(HChannel hChannel, void *formatCommandInput)
616 {
617 bool ret = false;
618 TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput;
619 if (!hChannel->hChildWorkTCP.loop || formatCommand->cmdFlag == CMD_FORWARD_REMOVE) {
620 // Main thread command, direct Listen main thread
621 ret = DoCommandLocal(hChannel, formatCommandInput);
622 } else { // CONNECT DAEMON's work thread command, non-primary thread
623 ret = DoCommandRemote(hChannel, formatCommandInput);
624 }
625 return ret;
626 }
627
628 // just call from BindChannelToSession
FindAliveSessionFromDaemonMap(const HChannel hChannel)629 HSession HdcServerForClient::FindAliveSessionFromDaemonMap(const HChannel hChannel)
630 {
631 HSession hSession = nullptr;
632 HDaemonInfo hdi = nullptr;
633 HdcServer *ptrServer = (HdcServer *)clsServer;
634 ptrServer->AdminDaemonMap(OP_QUERY, hChannel->connectKey, hdi);
635 if (!hdi) {
636 EchoClient(hChannel, MSG_FAIL, "Not match target founded, check connect-key please");
637 return nullptr;
638 }
639 if (hdi->connStatus != STATUS_CONNECTED) {
640 EchoClient(hChannel, MSG_FAIL, "Device not founded or connected");
641 return nullptr;
642 }
643 if (hdi->hSession->isDead) {
644 EchoClient(hChannel, MSG_FAIL, "Bind tartget session is dead");
645 return nullptr;
646 }
647 hSession = reinterpret_cast<HSession>(hdi->hSession);
648 return hSession;
649 }
650
BindChannelToSession(HChannel hChannel,uint8_t * bufPtr,const int bytesIO)651 int HdcServerForClient::BindChannelToSession(HChannel hChannel, uint8_t *bufPtr, const int bytesIO)
652 {
653 if (FindAliveSessionFromDaemonMap(hChannel) == nullptr) {
654 return ERR_SESSION_NOFOUND;
655 }
656 bool isClosing = uv_is_closing((const uv_handle_t *)&hChannel->hWorkTCP);
657 if (!isClosing && (hChannel->fdChildWorkTCP = Base::DuplicateUvSocket(&hChannel->hWorkTCP)) < 0) {
658 WRITE_LOG(LOG_FATAL, "Duplicate socket failed, cid:%d", hChannel->channelId);
659 return ERR_SOCKET_DUPLICATE;
660 }
661 uv_close_cb funcWorkTcpClose = [](uv_handle_t *handle) -> void {
662 HChannel hChannel = (HChannel)handle->data;
663 --hChannel->ref;
664 };
665 ++hChannel->ref;
666 if (!isClosing) {
667 uv_close((uv_handle_t *)&hChannel->hWorkTCP, funcWorkTcpClose);
668 }
669 Base::DoNextLoop(loopMain, hChannel, [](const uint8_t flag, string &msg, const void *data) {
670 // Thread message can avoid using thread lock and improve program efficiency
671 // If not next loop call, ReadStream will thread conflict
672 HChannel hChannel = (HChannel)data;
673 auto thisClass = (HdcServerForClient *)hChannel->clsChannel;
674 HSession hSession = nullptr;
675 if ((hSession = thisClass->FindAliveSessionFromDaemonMap(hChannel)) == nullptr) {
676 return;
677 }
678 auto ctrl = HdcSessionBase::BuildCtrlString(SP_ATTACH_CHANNEL, hChannel->channelId, nullptr, 0);
679 Base::SendToStream((uv_stream_t *)&hSession->ctrlPipe[STREAM_MAIN], ctrl.data(), ctrl.size());
680 });
681 return RET_SUCCESS;
682 }
683
CheckAutoFillTarget(HChannel hChannel)684 bool HdcServerForClient::CheckAutoFillTarget(HChannel hChannel)
685 {
686 HdcServer *ptrServer = (HdcServer *)clsServer;
687 if (!hChannel->connectKey.size()) {
688 return false; // Operation of non-bound destination of scanning
689 }
690 if (hChannel->connectKey == CMDSTR_CONNECT_ANY) {
691 HDaemonInfo hdiOld = nullptr;
692 ptrServer->AdminDaemonMap(OP_GET_ONLY, "", hdiOld);
693 if (!hdiOld) {
694 return false;
695 }
696 hChannel->connectKey = hdiOld->connectKey;
697 return true;
698 }
699 return true;
700 }
701
ChannelHandShake(HChannel hChannel,uint8_t * bufPtr,const int bytesIO)702 int HdcServerForClient::ChannelHandShake(HChannel hChannel, uint8_t *bufPtr, const int bytesIO)
703 {
704 vector<uint8_t> rebuildHandshake;
705 rebuildHandshake.insert(rebuildHandshake.end(), bufPtr, bufPtr + bytesIO);
706 rebuildHandshake.push_back(0x00);
707 struct ChannelHandShake *handShake = reinterpret_cast<struct ChannelHandShake *>(rebuildHandshake.data());
708 if (strncmp(handShake->banner, HANDSHAKE_MESSAGE.c_str(), HANDSHAKE_MESSAGE.size())) {
709 hChannel->availTailIndex = 0;
710 WRITE_LOG(LOG_DEBUG, "Channel Hello failed");
711 return ERR_HANDSHAKE_NOTMATCH;
712 }
713 if (strlen(handShake->connectKey) > sizeof(handShake->connectKey)) {
714 hChannel->availTailIndex = 0;
715 WRITE_LOG(LOG_DEBUG, "Connectkey's size incorrect");
716 return ERR_HANDSHAKE_CONNECTKEY_FAILED;
717 }
718 // channel handshake step3
719 WRITE_LOG(LOG_DEBUG, "ServerForClient channel handshake finished");
720 hChannel->connectKey = handShake->connectKey;
721 hChannel->handshakeOK = true;
722 if (!CheckAutoFillTarget(hChannel)) {
723 return 0;
724 }
725 // channel handshake stBindChannelToSession
726 if (BindChannelToSession(hChannel, nullptr, 0)) {
727 hChannel->availTailIndex = 0;
728 WRITE_LOG(LOG_FATAL, "BindChannelToSession failed");
729 return ERR_GENERIC;
730 }
731 return 0;
732 }
733
ReportServerVersion(HChannel hChannel)734 void HdcServerForClient::ReportServerVersion(HChannel hChannel)
735 {
736 string version = Base::GetVersion();
737 SendChannelWithCmd(hChannel, CMD_CHECK_SERVER,
738 const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(version.c_str())),
739 version.size());
740 }
741
742 // Here is Server to get data, the source is the SERVER's ChildWork to send data
ReadChannel(HChannel hChannel,uint8_t * bufPtr,const int bytesIO)743 int HdcServerForClient::ReadChannel(HChannel hChannel, uint8_t *bufPtr, const int bytesIO)
744 {
745 int ret = 0;
746 if (!hChannel->handshakeOK) {
747 return ChannelHandShake(hChannel, bufPtr, bytesIO);
748 }
749
750 uint16_t command = *reinterpret_cast<uint16_t *>(bufPtr);
751 if (command != 0 && (hChannel->remote > RemoteType::REMOTE_NONE)) {
752 // server directly passthrough file command to daemon
753 if (!SendToDaemon(hChannel, command, bufPtr + sizeof(uint16_t), bytesIO - sizeof(uint16_t))) {
754 WRITE_LOG(LOG_FATAL, "Client ReadChannel : direct send to daemon failed");
755 }
756 return ret;
757 }
758 struct TranslateCommand::FormatCommand formatCommand = { 0 };
759 if (!hChannel->interactiveShellMode) {
760 string retEcho = String2FormatCommand(reinterpret_cast<char *>(bufPtr), bytesIO, &formatCommand);
761 if (retEcho.length()) {
762 if (!strcmp(reinterpret_cast<char *>(bufPtr), CMDSTR_SOFTWARE_HELP.c_str()) ||
763 !strcmp(reinterpret_cast<char *>(bufPtr), CMDSTR_SOFTWARE_VERSION.c_str()) ||
764 !strcmp(reinterpret_cast<char *>(bufPtr), "flash")) {
765 EchoClient(hChannel, MSG_OK, retEcho.c_str());
766 } else {
767 EchoClient(hChannel, MSG_FAIL, retEcho.c_str());
768 }
769 }
770 WRITE_LOG(LOG_DEBUG, "ReadChannel command: %s", bufPtr);
771 if (formatCommand.bJumpDo) {
772 ret = -10;
773 return ret;
774 }
775 } else {
776 formatCommand.parameters = string(reinterpret_cast<char *>(bufPtr), bytesIO);
777 formatCommand.cmdFlag = CMD_SHELL_DATA;
778 }
779
780 if (!DoCommand(hChannel, &formatCommand)) {
781 return -3; // -3: error or want close
782 }
783 ret = bytesIO;
784 return ret;
785 };
786
787 // avoid session dead
FindAliveSession(uint32_t sessionId)788 HSession HdcServerForClient::FindAliveSession(uint32_t sessionId)
789 {
790 HdcServer *ptrServer = (HdcServer *)clsServer;
791 HSession hSession = ptrServer->AdminSession(OP_QUERY, sessionId, nullptr);
792 if (!hSession || hSession->isDead) {
793 return nullptr;
794 } else {
795 return hSession;
796 }
797 }
798
ChannelSendSessionCtrlMsg(vector<uint8_t> & ctrlMsg,uint32_t sessionId)799 bool HdcServerForClient::ChannelSendSessionCtrlMsg(vector<uint8_t> &ctrlMsg, uint32_t sessionId)
800 {
801 HSession hSession = FindAliveSession(sessionId);
802 if (!hSession) {
803 return false;
804 }
805 return Base::SendToStream((uv_stream_t *)&hSession->ctrlPipe[STREAM_MAIN], ctrlMsg.data(), ctrlMsg.size()) > 0;
806 }
807 } // namespace Hdc
808