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 == nullptr || hdiOld->hSession == nullptr) {
350 EchoClient(hChannel, MSG_FAIL, "No target available");
351 WRITE_LOG(LOG_FATAL, "CommandRemoveSession No target available");
352 return false;
353 }
354 (reinterpret_cast<HdcServer *>(ptrServer))->FreeSession(hdiOld->hSession->sessionId);
355 return true;
356 }
357
CommandRemoveForward(const string & forwardKey)358 bool HdcServerForClient::CommandRemoveForward(const string &forwardKey)
359 {
360 bool ret = RemoveFportkey("0|" + forwardKey);
361 ret |= RemoveFportkey("1|" + forwardKey);
362 return ret;
363 }
364
RemoveFportkey(const string & forwardKey)365 bool HdcServerForClient::RemoveFportkey(const string &forwardKey)
366 {
367 HdcServer *ptrServer = (HdcServer *)clsServer;
368 HForwardInfo hfi = nullptr;
369 ptrServer->AdminForwardMap(OP_QUERY, forwardKey, hfi);
370 if (!hfi) {
371 WRITE_LOG(LOG_FATAL, "CommandRemoveForward hfi nullptr forwardKey:%s", forwardKey.c_str());
372 return false;
373 }
374 HSession hSession = ptrServer->AdminSession(OP_QUERY, hfi->sessionId, nullptr);
375 if (!hSession) {
376 WRITE_LOG(LOG_FATAL, "CommandRemoveForward hSession nullptr sessionId:%u", hfi->sessionId);
377 ptrServer->AdminForwardMap(OP_REMOVE, forwardKey, hfi);
378 return true;
379 }
380 ptrServer->ClearOwnTasks(hSession, hfi->channelId);
381 FreeChannel(hfi->channelId);
382 hfi = nullptr;
383 ptrServer->AdminForwardMap(OP_REMOVE, forwardKey, hfi);
384 return true;
385 }
386
GetTargetList(HChannel hChannel,void * formatCommandInput)387 void HdcServerForClient::GetTargetList(HChannel hChannel, void *formatCommandInput)
388 {
389 TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput;
390 HdcServer *ptrServer = (HdcServer *)clsServer;
391 uint16_t cmd = OP_GET_STRLIST;
392 if (formatCommand->parameters == "v") {
393 cmd = OP_GET_STRLIST_FULL;
394 }
395 HDaemonInfo hdi = nullptr;
396 string sRet = ptrServer->AdminDaemonMap(cmd, STRING_EMPTY, hdi);
397 if (!sRet.length()) {
398 sRet = EMPTY_ECHO;
399 }
400 EchoClient(hChannel, MSG_OK, const_cast<char *>(sRet.c_str()));
401 #ifdef UNIT_TEST
402 Base::WriteBinFile((UT_TMP_PATH + "/base-list.result").c_str(), (uint8_t *)MESSAGE_SUCCESS.c_str(),
403 MESSAGE_SUCCESS.size(), true);
404 #endif
405 }
406
GetAnyTarget(HChannel hChannel)407 bool HdcServerForClient::GetAnyTarget(HChannel hChannel)
408 {
409 HdcServer *ptrServer = (HdcServer *)clsServer;
410 HDaemonInfo hdi = nullptr;
411 ptrServer->AdminDaemonMap(OP_GET_ANY, STRING_EMPTY, hdi);
412 if (!hdi) {
413 EchoClient(hChannel, MSG_FAIL, "No target available");
414 return false;
415 }
416 // can not use hdi->connectKey.This memory may be released to re-Malloc
417 string connectKey = hdi->connectKey;
418 bool ret = NewConnectTry(ptrServer, hChannel, connectKey);
419 #ifdef UNIT_TEST
420 Base::WriteBinFile((UT_TMP_PATH + "/base-any.result").c_str(), (uint8_t *)MESSAGE_SUCCESS.c_str(),
421 MESSAGE_SUCCESS.size(), true);
422 #endif
423 return ret;
424 }
425
WaitForAny(HChannel hChannel)426 bool HdcServerForClient::WaitForAny(HChannel hChannel)
427 {
428 HdcServer *ptrServer = (HdcServer *)clsServer;
429 HDaemonInfo hdi = nullptr;
430 if (!hChannel->connectKey.empty()) {
431 ptrServer->AdminDaemonMap(OP_WAIT_FOR_ANY, hChannel->connectKey, hdi);
432 } else {
433 ptrServer->AdminDaemonMap(OP_WAIT_FOR_ANY, STRING_EMPTY, hdi);
434 }
435 if (!hdi) {
436 EchoClient(hChannel, MSG_FAIL, "No any connected target");
437 return false;
438 }
439 string key = hdi->connectKey;
440 EchoClient(hChannel, MSG_OK, "Wait for connected target is %s", key.c_str());
441 return true;
442 }
443
RemoveForward(HChannel hChannel,const char * parameterString)444 bool HdcServerForClient::RemoveForward(HChannel hChannel, const char *parameterString)
445 {
446 HdcServer *ptrServer = (HdcServer *)clsServer;
447 if (parameterString == nullptr) { // remove all
448 HForwardInfo hfi = nullptr; // dummy
449 string echo = ptrServer->AdminForwardMap(OP_GET_STRLIST, "", hfi);
450 if (!echo.length()) {
451 return false;
452 }
453 vector<string> filterStrings;
454 Base::SplitString(echo, string("\n"), filterStrings);
455 for (auto &&s : filterStrings) {
456 if (CommandRemoveForward(s.c_str())) {
457 EchoClient(hChannel, MSG_OK, "Remove forward ruler success, ruler:%s", s.c_str());
458 } else {
459 EchoClient(hChannel, MSG_FAIL, "Remove forward ruler failed, ruler is not exist %s", s.c_str());
460 }
461 }
462 } else { // remove single
463 if (CommandRemoveForward(parameterString)) {
464 EchoClient(hChannel, MSG_OK, "Remove forward ruler success, ruler:%s", parameterString);
465 } else {
466 EchoClient(hChannel, MSG_FAIL, "Remove forward ruler failed, ruler is not exist %s", parameterString);
467 }
468 }
469 return true;
470 }
471
DoCommandLocal(HChannel hChannel,void * formatCommandInput)472 bool HdcServerForClient::DoCommandLocal(HChannel hChannel, void *formatCommandInput)
473 {
474 TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput;
475 HdcServer *ptrServer = (HdcServer *)clsServer;
476 bool ret = false;
477 // Main thread command, direct Listen main thread
478 switch (formatCommand->cmdFlag) {
479 case CMD_KERNEL_TARGET_DISCOVER: {
480 OrderFindTargets(hChannel);
481 ret = false;
482 break;
483 }
484 case CMD_KERNEL_TARGET_LIST: {
485 GetTargetList(hChannel, formatCommandInput);
486 ret = false;
487 break;
488 }
489 case CMD_SERVICE_START: {
490 PrintLastError(hChannel);
491 ret = false;
492 break;
493 }
494 case CMD_CHECK_SERVER: {
495 WRITE_LOG(LOG_DEBUG, "CMD_CHECK_SERVER command");
496 ReportServerVersion(hChannel);
497 ret = false;
498 break;
499 }
500 case CMD_WAIT_FOR: {
501 WRITE_LOG(LOG_DEBUG, "CMD_WAIT_FOR command");
502 ret = !WaitForAny(hChannel);
503 break;
504 }
505 case CMD_KERNEL_TARGET_ANY: {
506 #ifdef HDC_DEBUG
507 WRITE_LOG(LOG_DEBUG, "%s CMD_KERNEL_TARGET_ANY %s", __FUNCTION__, formatCommand->parameters.c_str());
508 #endif
509 ret = GetAnyTarget(hChannel);
510 break;
511 }
512 case CMD_KERNEL_TARGET_CONNECT: {
513 #ifdef HDC_DEBUG
514 WRITE_LOG(LOG_DEBUG, "%s CMD_KERNEL_TARGET_CONNECT %s", __FUNCTION__, formatCommand->parameters.c_str());
515 #endif
516 ret = NewConnectTry(ptrServer, hChannel, formatCommand->parameters.c_str());
517 break;
518 }
519 case CMD_CHECK_DEVICE: {
520 WRITE_LOG(LOG_INFO, "%s CMD_CHECK_DEVICE %s", __FUNCTION__, formatCommand->parameters.c_str());
521 hChannel->isCheck = true;
522 hChannel->key = formatCommand->parameters.c_str();
523 ret = NewConnectTry(ptrServer, hChannel, formatCommand->parameters.c_str(), true);
524 break;
525 }
526 case CMD_KERNEL_TARGET_DISCONNECT: {
527 CommandRemoveSession(hChannel, formatCommand->parameters.c_str());
528 break;
529 }
530 // task will be global task,Therefore, it can only be controlled in the global session.
531 case CMD_FORWARD_LIST: {
532 HForwardInfo hfi = nullptr; // dummy
533 string echo = ptrServer->AdminForwardMap(OP_GET_STRLIST_FULL, "", hfi);
534 if (!echo.length()) {
535 echo = EMPTY_ECHO;
536 }
537 EchoClient(hChannel, MSG_OK, const_cast<char *>(echo.c_str()));
538 break;
539 }
540 case CMD_FORWARD_REMOVE: {
541 RemoveForward(hChannel, formatCommand->parameters.c_str());
542 break;
543 }
544 case CMD_KERNEL_ENABLE_KEEPALIVE: {
545 // just use for 'list targets' now
546 hChannel->keepAlive = true;
547 ret = true;
548 break;
549 }
550 default: {
551 EchoClient(hChannel, MSG_FAIL, "ExecuteCommand need connect-key? please confirm a device by help info");
552 break;
553 }
554 }
555 return ret;
556 }
557
TaskCommand(HChannel hChannel,void * formatCommandInput)558 bool HdcServerForClient::TaskCommand(HChannel hChannel, void *formatCommandInput)
559 {
560 TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput;
561 HdcServer *ptrServer = (HdcServer *)clsServer;
562 string cmdFlag;
563 uint8_t sizeCmdFlag = 0;
564 if (formatCommand->cmdFlag == CMD_FILE_INIT) {
565 cmdFlag = "send ";
566 sizeCmdFlag = 5; // 5: cmdFlag send size
567 HandleRemote(hChannel, formatCommand->parameters, RemoteType::REMOTE_FILE);
568 } else if (formatCommand->cmdFlag == CMD_FORWARD_INIT) {
569 cmdFlag = "fport ";
570 sizeCmdFlag = 6; // 6: cmdFlag fport size
571 } else if (formatCommand->cmdFlag == CMD_APP_INIT) {
572 cmdFlag = "install ";
573 sizeCmdFlag = 8; // 8: cmdFlag install size
574 HandleRemote(hChannel, formatCommand->parameters, RemoteType::REMOTE_APP);
575 } else if (formatCommand->cmdFlag == CMD_APP_UNINSTALL) {
576 cmdFlag = "uninstall ";
577 sizeCmdFlag = 10; // 10: cmdFlag uninstall size
578 } else if (formatCommand->cmdFlag == CMD_UNITY_BUGREPORT_INIT) {
579 cmdFlag = "bugreport ";
580 sizeCmdFlag = 10; // 10: cmdFlag bugreport size
581 } else if (formatCommand->cmdFlag == CMD_APP_SIDELOAD) {
582 cmdFlag = "sideload ";
583 sizeCmdFlag = 9; // 9: cmdFlag sideload size
584 } else if (formatCommand->cmdFlag == CMD_FLASHD_UPDATE_INIT) {
585 cmdFlag = "update ";
586 sizeCmdFlag = 7; // 7: cmdFlag update size
587 } else if (formatCommand->cmdFlag == CMD_FLASHD_FLASH_INIT) {
588 cmdFlag = "flash ";
589 sizeCmdFlag = 6; // 6: cmdFlag flash size
590 }
591 int sizeSend = formatCommand->parameters.size();
592 if (!strncmp(formatCommand->parameters.c_str(), cmdFlag.c_str(), sizeCmdFlag)) { // local do
593 HSession hSession = FindAliveSession(hChannel->targetSessionId);
594 if (!hSession) {
595 return false;
596 }
597 if ((formatCommand->cmdFlag == CMD_FILE_INIT || formatCommand->cmdFlag == CMD_APP_INIT) &&
598 hChannel->fromClient) {
599 // remote client mode, CMD_FILE_INIT and CMD_APP_INIT command send back to client
600 WRITE_LOG(LOG_DEBUG, "command send back to remote client channelId:%u", hChannel->channelId);
601 SendChannelWithCmd(hChannel, formatCommand->cmdFlag,
602 reinterpret_cast<uint8_t *>(const_cast<char *>(formatCommand->parameters.c_str())) + sizeCmdFlag,
603 sizeSend - sizeCmdFlag);
604 return false;
605 }
606 ptrServer->DispatchTaskData(hSession, hChannel->channelId, formatCommand->cmdFlag,
607 reinterpret_cast<uint8_t *>(const_cast<char *>(formatCommand->parameters.c_str())) + sizeCmdFlag,
608 sizeSend - sizeCmdFlag);
609 } else { // Send to Daemon-side to do
610 SendToDaemon(hChannel, formatCommand->cmdFlag,
611 reinterpret_cast<uint8_t *>(const_cast<char *>(formatCommand->parameters.c_str())) + sizeCmdFlag,
612 sizeSend - sizeCmdFlag);
613 }
614 return true;
615 }
616
HandleRemote(HChannel hChannel,string & parameters,RemoteType flag)617 void HdcServerForClient::HandleRemote(HChannel hChannel, string ¶meters, RemoteType flag)
618 {
619 hChannel->remote = flag;
620 int argc = 0;
621 char **argv = Base::SplitCommandToArgs(parameters.c_str(), &argc);
622 for (int i = 0; i < argc; i++) {
623 if (argv[i] == CMDSTR_REMOTE_PARAMETER) {
624 hChannel->fromClient = true;
625 WRITE_LOG(LOG_DEBUG, "remote client mode channelId:%u", hChannel->channelId);
626 break;
627 }
628 }
629 if (hChannel->fromClient) {
630 string remote = CMDSTR_REMOTE_PARAMETER + " ";
631 if (parameters.find(remote) != std::string::npos) {
632 parameters.replace(parameters.find(remote), remote.size(), "");
633 WRITE_LOG(LOG_DEBUG, "parameters: %s", parameters.c_str());
634 }
635 }
636 delete[](reinterpret_cast<char *>(argv));
637 }
638
DoCommandRemote(HChannel hChannel,void * formatCommandInput)639 bool HdcServerForClient::DoCommandRemote(HChannel hChannel, void *formatCommandInput)
640 {
641 TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput;
642 bool ret = false;
643 int sizeSend = formatCommand->parameters.size();
644 switch (formatCommand->cmdFlag) {
645 // Some simple commands only need to forward the instruction, no need to start Task
646 case CMD_SHELL_INIT:
647 case CMD_SHELL_DATA:
648 case CMD_UNITY_EXECUTE:
649 case CMD_UNITY_EXECUTE_EX:
650 case CMD_UNITY_REMOUNT:
651 case CMD_UNITY_REBOOT:
652 case CMD_UNITY_RUNMODE:
653 case CMD_UNITY_HILOG:
654 case CMD_UNITY_ROOTRUN:
655 case CMD_JDWP_TRACK:
656 case CMD_JDWP_LIST: {
657 if (!SendToDaemon(hChannel, formatCommand->cmdFlag,
658 reinterpret_cast<uint8_t *>(const_cast<char *>(formatCommand->parameters.c_str())), sizeSend)) {
659 break;
660 }
661 ret = true;
662 if (formatCommand->cmdFlag == CMD_SHELL_INIT) {
663 hChannel->interactiveShellMode = true;
664 }
665 break;
666 }
667 case CMD_FILE_INIT:
668 case CMD_FORWARD_INIT:
669 case CMD_APP_INIT:
670 case CMD_APP_UNINSTALL:
671 case CMD_UNITY_BUGREPORT_INIT:
672 case CMD_APP_SIDELOAD:
673 case CMD_FLASHD_UPDATE_INIT:
674 case CMD_FLASHD_FLASH_INIT:
675 case CMD_FLASHD_ERASE:
676 case CMD_FLASHD_FORMAT: {
677 TaskCommand(hChannel, formatCommandInput);
678 ret = true;
679 break;
680 }
681 default:
682 break;
683 }
684 if (!ret) {
685 EchoClient(hChannel, MSG_FAIL, "[E002106] Failed to communicate with daemon");
686 }
687 return ret;
688 }
689 // Do not specify Target's operations no longer need to put it in the thread.
DoCommand(HChannel hChannel,void * formatCommandInput,HDaemonInfo & hdi)690 bool HdcServerForClient::DoCommand(HChannel hChannel, void *formatCommandInput, HDaemonInfo &hdi)
691 {
692 bool ret = false;
693 TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput;
694 if (!hChannel->hChildWorkTCP.loop ||
695 formatCommand->cmdFlag == CMD_FORWARD_REMOVE ||
696 formatCommand->cmdFlag == CMD_SERVICE_START) {
697 // Main thread command, direct Listen main thread
698 ret = DoCommandLocal(hChannel, formatCommandInput);
699 } else { // CONNECT DAEMON's work thread command, non-primary thread
700 if (!CommandMatchDaemonFeature(formatCommand->cmdFlag, hdi)) {
701 // only the cmdFlag in the FEATURE_VERSION_MATCH_MAP needs to be checked, others to permissive.
702 WRITE_LOG(LOG_WARN, "unsupport cmdFlag: %d, due to daemon feature dismatch", formatCommand->cmdFlag);
703 EchoClient(hChannel, MSG_FAIL, "[E002105] Unsupport command");
704 return false;
705 }
706 ret = DoCommandRemote(hChannel, formatCommandInput);
707 }
708 return ret;
709 }
710
711 // just call from BindChannelToSession
FindAliveSessionFromDaemonMap(const HChannel hChannel)712 HSession HdcServerForClient::FindAliveSessionFromDaemonMap(const HChannel hChannel)
713 {
714 HSession hSession = nullptr;
715 HDaemonInfo hdi = nullptr;
716 HdcServer *ptrServer = (HdcServer *)clsServer;
717 ptrServer->AdminDaemonMap(OP_QUERY, hChannel->connectKey, hdi);
718 if (!hdi) {
719 EchoClient(hChannel, MSG_FAIL, "Not match target founded, check connect-key please");
720 return nullptr;
721 }
722 if (hdi->connStatus != STATUS_CONNECTED) {
723 EchoClient(hChannel, MSG_FAIL, "[E001005] Device not found or connected");
724 return nullptr;
725 }
726 if (hdi->hSession == nullptr || hdi->hSession->isDead) {
727 EchoClient(hChannel, MSG_FAIL, "Bind tartget session is dead");
728 return nullptr;
729 }
730 if (!hdi->hSession->handshakeOK) {
731 WRITE_LOG(LOG_WARN, "hSession handShake is false sid:%u cid:%u",
732 hdi->hSession->sessionId, hChannel->channelId);
733 const string errMsg = "[E000004]:The communication channel is being established.\r\n"\
734 "Please wait for several seconds and try again.";
735 EchoClient(hChannel, MSG_FAIL, errMsg.c_str());
736 return nullptr;
737 }
738 hSession = reinterpret_cast<HSession>(hdi->hSession);
739 return hSession;
740 }
741
BindChannelToSession(HChannel hChannel,uint8_t * bufPtr,const int bytesIO)742 int HdcServerForClient::BindChannelToSession(HChannel hChannel, uint8_t *bufPtr, const int bytesIO)
743 {
744 if (FindAliveSessionFromDaemonMap(hChannel) == nullptr) {
745 WRITE_LOG(LOG_FATAL, "Find no alive session channelId:%u", hChannel->channelId);
746 return ERR_SESSION_NOFOUND;
747 }
748 bool isClosing = uv_is_closing((const uv_handle_t *)&hChannel->hWorkTCP);
749 if (!isClosing && (hChannel->fdChildWorkTCP = Base::DuplicateUvSocket(&hChannel->hWorkTCP)) < 0) {
750 WRITE_LOG(LOG_FATAL, "Duplicate socket failed channelId:%u", hChannel->channelId);
751 return ERR_SOCKET_DUPLICATE;
752 }
753 uv_close_cb funcWorkTcpClose = [](uv_handle_t *handle) -> void {
754 HChannel hChannel = (HChannel)handle->data;
755 --hChannel->ref;
756 };
757 ++hChannel->ref;
758 if (!isClosing) {
759 uv_close((uv_handle_t *)&hChannel->hWorkTCP, funcWorkTcpClose);
760 }
761 Base::DoNextLoop(loopMain, hChannel, [](const uint8_t flag, string &msg, const void *data) {
762 // Thread message can avoid using thread lock and improve program efficiency
763 // If not next loop call, ReadStream will thread conflict
764 HChannel hChannel = (HChannel)data;
765 auto thisClass = (HdcServerForClient *)hChannel->clsChannel;
766 HSession hSession = nullptr;
767 if ((hSession = thisClass->FindAliveSessionFromDaemonMap(hChannel)) == nullptr) {
768 WRITE_LOG(LOG_FATAL, "hSession nullptr channelId:%u", hChannel->channelId);
769 return;
770 }
771 auto ctrl = HdcSessionBase::BuildCtrlString(SP_ATTACH_CHANNEL, hChannel->channelId, nullptr, 0);
772 Base::SendToPollFd(hSession->ctrlFd[STREAM_MAIN], ctrl.data(), ctrl.size());
773 });
774 return RET_SUCCESS;
775 }
776
CheckAutoFillTarget(HChannel hChannel)777 bool HdcServerForClient::CheckAutoFillTarget(HChannel hChannel)
778 {
779 HdcServer *ptrServer = (HdcServer *)clsServer;
780 if (!hChannel->connectKey.size()) {
781 WRITE_LOG(LOG_FATAL, "connectKey.size 0 channelId:%u", hChannel->channelId);
782 return false; // Operation of non-bound destination of scanning
783 }
784 if (hChannel->connectKey == CMDSTR_CONNECT_ANY) {
785 HDaemonInfo hdiOld = nullptr;
786 ptrServer->AdminDaemonMap(OP_GET_ONLY, "", hdiOld);
787 if (!hdiOld) {
788 WRITE_LOG(LOG_WARN, "No any key found channelId:%u", hChannel->channelId);
789 return false;
790 }
791 if (!hdiOld->hSession) {
792 WRITE_LOG(LOG_WARN, "hSession is null. channelId:%u", hChannel->channelId);
793 return false;
794 }
795 if (!hdiOld->hSession->handshakeOK) {
796 WRITE_LOG(LOG_WARN, "hSession handShake is false SessionId:%u", hdiOld->hSession->sessionId);
797 return false;
798 }
799 hChannel->connectKey = hdiOld->connectKey;
800 return true;
801 }
802 return true;
803 }
804
ChannelHandShake(HChannel hChannel,uint8_t * bufPtr,const int bytesIO)805 int HdcServerForClient::ChannelHandShake(HChannel hChannel, uint8_t *bufPtr, const int bytesIO)
806 {
807 vector<uint8_t> rebuildHandshake;
808 rebuildHandshake.insert(rebuildHandshake.end(), bufPtr, bufPtr + bytesIO);
809 rebuildHandshake.push_back(0x00);
810 struct ChannelHandShake *handShake = reinterpret_cast<struct ChannelHandShake *>(rebuildHandshake.data());
811 if (strncmp(handShake->banner, HANDSHAKE_MESSAGE.c_str(), HANDSHAKE_MESSAGE.size())) {
812 hChannel->availTailIndex = 0;
813 WRITE_LOG(LOG_DEBUG, "Channel Hello failed");
814 return ERR_HANDSHAKE_NOTMATCH;
815 }
816 if (strlen(handShake->connectKey) > sizeof(handShake->connectKey)) {
817 hChannel->availTailIndex = 0;
818 WRITE_LOG(LOG_DEBUG, "Connectkey's size incorrect");
819 return ERR_HANDSHAKE_CONNECTKEY_FAILED;
820 }
821 // channel handshake step3
822 WRITE_LOG(LOG_DEBUG, "ServerForClient cid:%u sid:%u handshake finished",
823 hChannel->channelId, hChannel->targetSessionId);
824 hChannel->connectKey = handShake->connectKey;
825 hChannel->handshakeOK = true;
826 if (handShake->banner[WAIT_TAG_OFFSET] == WAIT_DEVICE_TAG || !CheckAutoFillTarget(hChannel)) {
827 WRITE_LOG(LOG_WARN, "No target channelId:%u", hChannel->channelId);
828 return 0;
829 }
830 // channel handshake stBindChannelToSession
831 if (BindChannelToSession(hChannel, nullptr, 0)) {
832 hChannel->availTailIndex = 0;
833 WRITE_LOG(LOG_FATAL, "BindChannelToSession failed channelId:%u sid:%u",
834 hChannel->channelId, hChannel->targetSessionId);
835 return ERR_GENERIC;
836 }
837 return 0;
838 }
839
ReportServerVersion(HChannel hChannel)840 void HdcServerForClient::ReportServerVersion(HChannel hChannel)
841 {
842 string version = Base::GetVersion();
843 SendChannelWithCmd(hChannel, CMD_CHECK_SERVER,
844 const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(version.c_str())),
845 version.size());
846 }
847
848 // 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)849 int HdcServerForClient::ReadChannel(HChannel hChannel, uint8_t *bufPtr, const int bytesIO)
850 {
851 int ret = 0;
852 if (!hChannel->handshakeOK) {
853 return ChannelHandShake(hChannel, bufPtr, bytesIO);
854 }
855 HDaemonInfo hdi = nullptr;
856 HdcServer *ptrServer = (HdcServer *)clsServer;
857 ptrServer->AdminDaemonMap(OP_QUERY, hChannel->connectKey, hdi);
858 if (hdi && !hdi->emgmsg.empty()) {
859 EchoClient(hChannel, MSG_FAIL, hdi->emgmsg.c_str());
860 return ERR_GENERIC;
861 }
862 uint16_t command = *reinterpret_cast<uint16_t *>(bufPtr);
863 if (command != 0 && (hChannel->remote > RemoteType::REMOTE_NONE)) {
864 // server directly passthrough file command to daemon
865 if (!SendToDaemon(hChannel, command, bufPtr + sizeof(uint16_t), bytesIO - sizeof(uint16_t))) {
866 WRITE_LOG(LOG_FATAL, "Client ReadChannel : direct send to daemon failed");
867 }
868 return ret;
869 }
870 struct TranslateCommand::FormatCommand formatCommand = { 0 };
871 if (!hChannel->interactiveShellMode) {
872 string retEcho = String2FormatCommand(reinterpret_cast<char *>(bufPtr), bytesIO, &formatCommand);
873 if (retEcho.length()) {
874 if (!strncmp(reinterpret_cast<char *>(bufPtr), CMDSTR_SOFTWARE_HELP.c_str(),
875 CMDSTR_SOFTWARE_HELP.size()) ||
876 !strcmp(reinterpret_cast<char *>(bufPtr), CMDSTR_SOFTWARE_VERSION.c_str()) ||
877 !strcmp(reinterpret_cast<char *>(bufPtr), "flash")) {
878 EchoClient(hChannel, MSG_OK, retEcho.c_str());
879 } else {
880 EchoClient(hChannel, MSG_FAIL, retEcho.c_str());
881 }
882 }
883 WRITE_LOG(LOG_DEBUG, "ReadChannel cid:%u sid:%u key:%s command: %s",
884 hChannel->channelId, hChannel->targetSessionId, Hdc::MaskString(hChannel->connectKey).c_str(), bufPtr);
885 if (formatCommand.bJumpDo) {
886 WRITE_LOG(LOG_FATAL, "ReadChannel bJumpDo true");
887 return -10; // -10 error formatCommand
888 }
889 } else {
890 formatCommand.parameters = string(reinterpret_cast<char *>(bufPtr), bytesIO);
891 formatCommand.cmdFlag = CMD_SHELL_DATA;
892 }
893 if (!DoCommand(hChannel, &formatCommand, hdi)) {
894 return -3; // -3: error or want close
895 }
896 ret = bytesIO;
897 return ret;
898 };
899
900 // avoid session dead
FindAliveSession(uint32_t sessionId)901 HSession HdcServerForClient::FindAliveSession(uint32_t sessionId)
902 {
903 HdcServer *ptrServer = (HdcServer *)clsServer;
904 HSession hSession = ptrServer->AdminSession(OP_QUERY, sessionId, nullptr);
905 if (!hSession || hSession->isDead) {
906 WRITE_LOG(LOG_FATAL, "FindAliveSession hSession nullptr or isDead sessionId:%u", sessionId);
907 return nullptr;
908 } else {
909 return hSession;
910 }
911 }
912
ChannelSendSessionCtrlMsg(vector<uint8_t> & ctrlMsg,uint32_t sessionId)913 bool HdcServerForClient::ChannelSendSessionCtrlMsg(vector<uint8_t> &ctrlMsg, uint32_t sessionId)
914 {
915 HSession hSession = FindAliveSession(sessionId);
916 if (!hSession) {
917 WRITE_LOG(LOG_FATAL, "ChannelSendSessionCtrlMsg hSession nullptr sessionId:%u", sessionId);
918 return false;
919 }
920 int rc = Base::SendToPollFd(hSession->ctrlFd[STREAM_MAIN], ctrlMsg.data(), ctrlMsg.size());
921 if (rc <= 0) {
922 WRITE_LOG(LOG_FATAL, "send ctrlmsg failed sessionId:%u rc:%d", sessionId, rc);
923 }
924 return rc > 0;
925 }
926
PrintLastError(HChannel HChannel)927 void HdcServerForClient::PrintLastError(HChannel HChannel)
928 {
929 HdcServer *ptrServer = (HdcServer *)clsServer;
930 uint32_t errorCode = ptrServer->lastErrorNum;
931 if (errorCode > 0) {
932 string errorString = GetErrorString(errorCode);
933 EchoClient(HChannel, MSG_FAIL, "[E%06x]%s", errorCode, errorString.c_str());
934 ptrServer->lastErrorNum = 0;
935 }
936 }
937
GetErrorString(uint32_t errorCode)938 string HdcServerForClient::GetErrorString(uint32_t errorCode)
939 {
940 auto map = ErrorStringEnglish.find(errorCode);
941 if (map != ErrorStringEnglish.end()) {
942 return map->second;
943 }
944 return ErrorStringEnglish.at(0xFFFFFF); // 0xFFFFFF: Unknown error
945 }
946
CommandMatchDaemonFeature(uint16_t cmdFlag,const HDaemonInfo & hdi)947 bool HdcServerForClient::CommandMatchDaemonFeature(uint16_t cmdFlag, const HDaemonInfo &hdi)
948 {
949 string cmdFlagStr = std::to_string(cmdFlag);
950 if (FEATURE_CHECK_SET.find(cmdFlag) == FEATURE_CHECK_SET.end()) { // not need check
951 return true;
952 }
953 auto tagMatch = hdi->daemonFeature.find(cmdFlagStr);
954 if (tagMatch == hdi->daemonFeature.end()) { // unsupport command
955 return false;
956 }
957 return (tagMatch->second == STR_FEATURE_ENABLE);
958 }
959 } // namespace Hdc
960