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 {
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 ¶meters, 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 }
631
DoCommandRemote(HChannel hChannel, void *formatCommandInput)632 bool HdcServerForClient::DoCommandRemote(HChannel hChannel, void *formatCommandInput)
633 {
634 TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput;
635 bool ret = false;
636 int sizeSend = formatCommand->parameters.size();
637 string cmdFlag;
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_REMOUNT:
644 case CMD_UNITY_REBOOT:
645 case CMD_UNITY_RUNMODE:
646 case CMD_UNITY_HILOG:
647 case CMD_UNITY_ROOTRUN:
648 case CMD_JDWP_TRACK:
649 case CMD_JDWP_LIST: {
650 if (!SendToDaemon(hChannel, formatCommand->cmdFlag,
651 reinterpret_cast<uint8_t *>(const_cast<char *>(formatCommand->parameters.c_str())),
652 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, "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)684 bool HdcServerForClient::DoCommand(HChannel hChannel, void *formatCommandInput)
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 ret = DoCommandRemote(hChannel, formatCommandInput);
693 }
694 return ret;
695 }
696
697 // just call from BindChannelToSession
FindAliveSessionFromDaemonMap(const HChannel hChannel)698 HSession HdcServerForClient::FindAliveSessionFromDaemonMap(const HChannel hChannel)
699 {
700 HSession hSession = nullptr;
701 HDaemonInfo hdi = nullptr;
702 HdcServer *ptrServer = (HdcServer *)clsServer;
703 ptrServer->AdminDaemonMap(OP_QUERY, hChannel->connectKey, hdi);
704 if (!hdi) {
705 EchoClient(hChannel, MSG_FAIL, "Not match target founded, check connect-key please");
706 return nullptr;
707 }
708 if (hdi->connStatus != STATUS_CONNECTED) {
709 EchoClient(hChannel, MSG_FAIL, "Device not founded or connected");
710 return nullptr;
711 }
712 if (hdi->hSession->isDead) {
713 EchoClient(hChannel, MSG_FAIL, "Bind tartget session is dead");
714 return nullptr;
715 }
716 if (!hdi->hSession->handshakeOK) {
717 WRITE_LOG(LOG_WARN, "hSession handShake is false sid:%u cid:%u",
718 hdi->hSession->sessionId, hChannel->channelId);
719 const string errMsg = "[E000004]:The communication channel is being established.\r\n"\
720 "Please wait for several seconds and try again.";
721 EchoClient(hChannel, MSG_FAIL, errMsg.c_str());
722 return nullptr;
723 }
724 hSession = reinterpret_cast<HSession>(hdi->hSession);
725 return hSession;
726 }
727
BindChannelToSession(HChannel hChannel, uint8_t *bufPtr, const int bytesIO)728 int HdcServerForClient::BindChannelToSession(HChannel hChannel, uint8_t *bufPtr, const int bytesIO)
729 {
730 if (FindAliveSessionFromDaemonMap(hChannel) == nullptr) {
731 WRITE_LOG(LOG_FATAL, "Find no alive session channelId:%u", hChannel->channelId);
732 return ERR_SESSION_NOFOUND;
733 }
734 bool isClosing = uv_is_closing((const uv_handle_t *)&hChannel->hWorkTCP);
735 if (!isClosing && (hChannel->fdChildWorkTCP = Base::DuplicateUvSocket(&hChannel->hWorkTCP)) < 0) {
736 WRITE_LOG(LOG_FATAL, "Duplicate socket failed channelId:%u", hChannel->channelId);
737 return ERR_SOCKET_DUPLICATE;
738 }
739 uv_close_cb funcWorkTcpClose = [](uv_handle_t *handle) -> void {
740 HChannel hChannel = (HChannel)handle->data;
741 --hChannel->ref;
742 };
743 ++hChannel->ref;
744 if (!isClosing) {
745 uv_close((uv_handle_t *)&hChannel->hWorkTCP, funcWorkTcpClose);
746 }
747 Base::DoNextLoop(loopMain, hChannel, [](const uint8_t flag, string &msg, const void *data) {
748 // Thread message can avoid using thread lock and improve program efficiency
749 // If not next loop call, ReadStream will thread conflict
750 HChannel hChannel = (HChannel)data;
751 auto thisClass = (HdcServerForClient *)hChannel->clsChannel;
752 HSession hSession = nullptr;
753 if ((hSession = thisClass->FindAliveSessionFromDaemonMap(hChannel)) == nullptr) {
754 WRITE_LOG(LOG_FATAL, "hSession nullptr channelId:%u", hChannel->channelId);
755 return;
756 }
757 auto ctrl = HdcSessionBase::BuildCtrlString(SP_ATTACH_CHANNEL, hChannel->channelId, nullptr, 0);
758 Base::SendToPollFd(hSession->ctrlFd[STREAM_MAIN], ctrl.data(), ctrl.size());
759 });
760 return RET_SUCCESS;
761 }
762
CheckAutoFillTarget(HChannel hChannel)763 bool HdcServerForClient::CheckAutoFillTarget(HChannel hChannel)
764 {
765 HdcServer *ptrServer = (HdcServer *)clsServer;
766 if (!hChannel->connectKey.size()) {
767 WRITE_LOG(LOG_FATAL, "connectKey.size 0 channelId:%u", hChannel->channelId);
768 return false; // Operation of non-bound destination of scanning
769 }
770 if (hChannel->connectKey == CMDSTR_CONNECT_ANY) {
771 HDaemonInfo hdiOld = nullptr;
772 ptrServer->AdminDaemonMap(OP_GET_ONLY, "", hdiOld);
773 if (!hdiOld) {
774 WRITE_LOG(LOG_WARN, "No any key found channelId:%u", hChannel->channelId);
775 return false;
776 }
777 if (!hdiOld->hSession) {
778 WRITE_LOG(LOG_WARN, "hSession is null. channelId:%u", hChannel->channelId);
779 return false;
780 }
781 if (!hdiOld->hSession->handshakeOK) {
782 WRITE_LOG(LOG_WARN, "hSession handShake is false SessionId:%u", hdiOld->hSession->sessionId);
783 return false;
784 }
785 hChannel->connectKey = hdiOld->connectKey;
786 return true;
787 }
788 return true;
789 }
790
ChannelHandShake(HChannel hChannel, uint8_t *bufPtr, const int bytesIO)791 int HdcServerForClient::ChannelHandShake(HChannel hChannel, uint8_t *bufPtr, const int bytesIO)
792 {
793 vector<uint8_t> rebuildHandshake;
794 rebuildHandshake.insert(rebuildHandshake.end(), bufPtr, bufPtr + bytesIO);
795 rebuildHandshake.push_back(0x00);
796 struct ChannelHandShake *handShake = reinterpret_cast<struct ChannelHandShake *>(rebuildHandshake.data());
797 if (strncmp(handShake->banner, HANDSHAKE_MESSAGE.c_str(), HANDSHAKE_MESSAGE.size())) {
798 hChannel->availTailIndex = 0;
799 WRITE_LOG(LOG_DEBUG, "Channel Hello failed");
800 return ERR_HANDSHAKE_NOTMATCH;
801 }
802 if (strlen(handShake->connectKey) > sizeof(handShake->connectKey)) {
803 hChannel->availTailIndex = 0;
804 WRITE_LOG(LOG_DEBUG, "Connectkey's size incorrect");
805 return ERR_HANDSHAKE_CONNECTKEY_FAILED;
806 }
807 // channel handshake step3
808 WRITE_LOG(LOG_DEBUG, "ServerForClient cid:%u sid:%u handshake finished",
809 hChannel->channelId, hChannel->targetSessionId);
810 hChannel->connectKey = handShake->connectKey;
811 hChannel->handshakeOK = true;
812 if (handShake->banner[WAIT_TAG_OFFSET] == WAIT_DEVICE_TAG || !CheckAutoFillTarget(hChannel)) {
813 WRITE_LOG(LOG_WARN, "No target channelId:%u", hChannel->channelId);
814 return 0;
815 }
816 // channel handshake stBindChannelToSession
817 if (BindChannelToSession(hChannel, nullptr, 0)) {
818 hChannel->availTailIndex = 0;
819 WRITE_LOG(LOG_FATAL, "BindChannelToSession failed channelId:%u sid:%u",
820 hChannel->channelId, hChannel->targetSessionId);
821 return ERR_GENERIC;
822 }
823 return 0;
824 }
825
ReportServerVersion(HChannel hChannel)826 void HdcServerForClient::ReportServerVersion(HChannel hChannel)
827 {
828 string version = Base::GetVersion();
829 SendChannelWithCmd(hChannel, CMD_CHECK_SERVER,
830 const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(version.c_str())),
831 version.size());
832 }
833
834 // 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)835 int HdcServerForClient::ReadChannel(HChannel hChannel, uint8_t *bufPtr, const int bytesIO)
836 {
837 int ret = 0;
838 if (!hChannel->handshakeOK) {
839 return ChannelHandShake(hChannel, bufPtr, bytesIO);
840 }
841 HDaemonInfo hdi = nullptr;
842 HdcServer *ptrServer = (HdcServer *)clsServer;
843 ptrServer->AdminDaemonMap(OP_QUERY, hChannel->connectKey, hdi);
844 if (hdi && !hdi->emgmsg.empty()) {
845 EchoClient(hChannel, MSG_FAIL, hdi->emgmsg.c_str());
846 return ERR_GENERIC;
847 }
848 uint16_t command = *reinterpret_cast<uint16_t *>(bufPtr);
849 if (command != 0 && (hChannel->remote > RemoteType::REMOTE_NONE)) {
850 // server directly passthrough file command to daemon
851 if (!SendToDaemon(hChannel, command, bufPtr + sizeof(uint16_t), bytesIO - sizeof(uint16_t))) {
852 WRITE_LOG(LOG_FATAL, "Client ReadChannel : direct send to daemon failed");
853 }
854 return ret;
855 }
856 struct TranslateCommand::FormatCommand formatCommand = { 0 };
857 if (!hChannel->interactiveShellMode) {
858 string retEcho = String2FormatCommand(reinterpret_cast<char *>(bufPtr), bytesIO, &formatCommand);
859 if (retEcho.length()) {
860 if (!strncmp(reinterpret_cast<char *>(bufPtr), CMDSTR_SOFTWARE_HELP.c_str(),
861 CMDSTR_SOFTWARE_HELP.size()) ||
862 !strcmp(reinterpret_cast<char *>(bufPtr), CMDSTR_SOFTWARE_VERSION.c_str()) ||
863 !strcmp(reinterpret_cast<char *>(bufPtr), "flash")) {
864 EchoClient(hChannel, MSG_OK, retEcho.c_str());
865 } else {
866 EchoClient(hChannel, MSG_FAIL, retEcho.c_str());
867 }
868 }
869 WRITE_LOG(LOG_DEBUG, "ReadChannel cid:%u sid:%u key:%s command: %s",
870 hChannel->channelId, hChannel->targetSessionId, Hdc::MaskString(hChannel->connectKey).c_str(), bufPtr);
871 if (formatCommand.bJumpDo) {
872 WRITE_LOG(LOG_FATAL, "ReadChannel bJumpDo true");
873 return -10; // -10 error formatCommand
874 }
875 } else {
876 formatCommand.parameters = string(reinterpret_cast<char *>(bufPtr), bytesIO);
877 formatCommand.cmdFlag = CMD_SHELL_DATA;
878 }
879
880 if (!DoCommand(hChannel, &formatCommand)) {
881 return -3; // -3: error or want close
882 }
883 ret = bytesIO;
884 return ret;
885 };
886
887 // avoid session dead
FindAliveSession(uint32_t sessionId)888 HSession HdcServerForClient::FindAliveSession(uint32_t sessionId)
889 {
890 HdcServer *ptrServer = (HdcServer *)clsServer;
891 HSession hSession = ptrServer->AdminSession(OP_QUERY, sessionId, nullptr);
892 if (!hSession || hSession->isDead) {
893 WRITE_LOG(LOG_FATAL, "FindAliveSession hSession nullptr or isDead sessionId:%u", sessionId);
894 return nullptr;
895 } else {
896 return hSession;
897 }
898 }
899
ChannelSendSessionCtrlMsg(vector<uint8_t> &ctrlMsg, uint32_t sessionId)900 bool HdcServerForClient::ChannelSendSessionCtrlMsg(vector<uint8_t> &ctrlMsg, uint32_t sessionId)
901 {
902 HSession hSession = FindAliveSession(sessionId);
903 if (!hSession) {
904 WRITE_LOG(LOG_FATAL, "ChannelSendSessionCtrlMsg hSession nullptr sessionId:%u", sessionId);
905 return false;
906 }
907 int rc = Base::SendToPollFd(hSession->ctrlFd[STREAM_MAIN], ctrlMsg.data(), ctrlMsg.size());
908 if (rc <= 0) {
909 WRITE_LOG(LOG_FATAL, "send ctrlmsg failed sessionId:%u rc:%d", sessionId, rc);
910 }
911 return rc > 0;
912 }
913 } // namespace Hdc
914