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