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 #ifdef __OHOS__
21 #include <sys/un.h>
22 #endif
23 #include "host_shell_option.h"
24 namespace Hdc {
25 static const int MAX_RETRY_COUNT = 500;
26 static const int MAX_CONNECT_DEVICE_RETRY_COUNT = 100;
27 #ifdef __OHOS__
28 static const int MAX_CONNECTIONS_COUNT = 16;
29 #endif
30
HdcServerForClient(const bool serverOrClient,const string & addrString,void * pClsServer,uv_loop_t * loopMainIn)31 HdcServerForClient::HdcServerForClient(const bool serverOrClient, const string &addrString, void *pClsServer,
32 uv_loop_t *loopMainIn)
33 : HdcChannelBase(serverOrClient, addrString, loopMainIn)
34 {
35 clsServer = pClsServer;
36 }
37
~HdcServerForClient()38 HdcServerForClient::~HdcServerForClient()
39 {
40 WRITE_LOG(LOG_DEBUG, "~HdcServerForClient");
41 }
42
Stop()43 void HdcServerForClient::Stop()
44 {
45 Base::TryCloseHandle((uv_handle_t *)&tcpListen);
46 #ifdef __OHOS__
47 Base::TryCloseHandle((uv_handle_t *)&udsListen);
48 #endif
49 }
50
GetTCPListenPort()51 uint16_t HdcServerForClient::GetTCPListenPort()
52 {
53 return channelPort;
54 }
55
56 #ifdef __OHOS__
AcceptUdsClient(uv_stream_t * server,int status)57 void HdcServerForClient::AcceptUdsClient(uv_stream_t *server, int status)
58 {
59 StartTraceScope("HdcServerForClient::AcceptUdsClient");
60 HdcServerForClient *thisClass = (HdcServerForClient *)(((uv_pipe_t *)server)->data);
61 CALLSTAT_GUARD(thisClass->loopMainStatus, server->loop, "HdcServerForClient::AcceptUdsClient");
62 HChannel hChannel = new HdcChannel();
63 if (hChannel == nullptr) {
64 WRITE_LOG(LOG_FATAL, "AcceptUdsClient new channel fail");
65 return;
66 }
67 hChannel->isUds = true;
68 uint32_t uid = thisClass->MallocChannel(&hChannel);
69 hChannel->startTime = Base::GetRuntimeMSec();
70 int rc = 0;
71 if ((rc = uv_accept(server, (uv_stream_t *)&hChannel->hWorkUds)) < 0) {
72 WRITE_LOG(LOG_FATAL, "AcceptUdsClient uv_accept error rc:%d uid:%u", rc, uid);
73 thisClass->FreeChannel(uid);
74 return;
75 }
76 WRITE_LOG(LOG_DEBUG, "AcceptUdsClient uid:%u", uid);
77 // limit first recv
78 int bufMaxSize = 0;
79 uv_recv_buffer_size((uv_handle_t *)&hChannel->hWorkUds, &bufMaxSize);
80 auto funcChannelHeaderAlloc = [](uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf) -> void {
81 HChannel context = (HChannel)handle->data;
82 Base::ReallocBuf(&context->ioBuf, &context->bufSize, Base::GetMaxBufSize() * BUF_EXTEND_SIZE);
83 buf->base = (char *)context->ioBuf + context->availTailIndex;
84 #ifdef HDC_VERSION_CHECK
85 buf->len = sizeof(struct ChannelHandShake) + DWORD_SERIALIZE_SIZE; // only recv static size
86 #else
87 buf->len = offsetof(struct ChannelHandShake, version) + DWORD_SERIALIZE_SIZE;
88 #endif
89 };
90 // first packet static size, after this packet will be dup for normal recv
91 uv_read_start((uv_stream_t *)&hChannel->hWorkUds, funcChannelHeaderAlloc, ReadStream);
92 // channel handshake step1
93 struct ChannelHandShake handShake = {};
94 if (EOK == strcpy_s(handShake.banner, sizeof(handShake.banner), HANDSHAKE_MESSAGE.c_str())) {
95 handShake.banner[BANNER_FEATURE_TAG_OFFSET] = HUGE_BUF_TAG; // set feature tag for huge buf size
96 handShake.banner[SERVICE_KILL_OFFSET] = SERVICE_KILL_TAG;
97 handShake.channelId = htonl(hChannel->channelId);
98 string ver = Base::GetVersion() + HDC_MSG_HASH;
99 WRITE_LOG(LOG_DEBUG, "Server ver:%s", ver.c_str());
100 if (EOK != strcpy_s(handShake.version, sizeof(handShake.version), ver.c_str())) {
101 WRITE_LOG(LOG_FATAL, "strcpy_s failed");
102 return;
103 }
104 #ifdef HDC_VERSION_CHECK
105 thisClass->Send(hChannel->channelId, (uint8_t *)&handShake, sizeof(struct ChannelHandShake));
106 #else
107 // do not send version message if check feature disable
108 thisClass->Send(hChannel->channelId, reinterpret_cast<uint8_t *>(&handShake),
109 offsetof(struct ChannelHandShake, version));
110 #endif
111 }
112 }
113 #endif
114
AcceptClient(uv_stream_t * server,int status)115 void HdcServerForClient::AcceptClient(uv_stream_t *server, int status)
116 {
117 StartTraceScope("HdcServerForClient::AcceptClient");
118 uv_tcp_t *pServTCP = (uv_tcp_t *)server;
119 HdcServerForClient *thisClass = (HdcServerForClient *)pServTCP->data;
120 CALLSTAT_GUARD(thisClass->loopMainStatus, server->loop, "HdcServerForClient::AcceptClient");
121 #ifdef HOST_OHOS
122 HChannel hChannel = new HdcChannel();
123 if (hChannel == nullptr) {
124 WRITE_LOG(LOG_FATAL, "AcceptClient new channel fail");
125 return;
126 }
127 #else
128 HChannel hChannel = nullptr;
129 #endif
130 uint32_t uid = thisClass->MallocChannel(&hChannel);
131 if (!hChannel) {
132 WRITE_LOG(LOG_FATAL, "AcceptClient hChannel is nullptr");
133 return;
134 }
135 hChannel->startTime = Base::GetRuntimeMSec();
136 int rc = uv_accept(server, (uv_stream_t *)&hChannel->hWorkTCP);
137 if (rc < 0) {
138 WRITE_LOG(LOG_FATAL, "AcceptClient uv_accept error rc:%d uid:%u", rc, uid);
139 thisClass->FreeChannel(uid);
140 return;
141 }
142 WRITE_LOG(LOG_DEBUG, "AcceptClient uid:%u", uid);
143 // limit first recv
144 int bufMaxSize = 0;
145 uv_recv_buffer_size((uv_handle_t *)&hChannel->hWorkTCP, &bufMaxSize);
146 auto funcChannelHeaderAlloc = [](uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf) -> void {
147 HChannel context = (HChannel)handle->data;
148 Base::ReallocBuf(&context->ioBuf, &context->bufSize, Base::GetMaxBufSize() * BUF_EXTEND_SIZE);
149 buf->base = (char *)context->ioBuf + context->availTailIndex;
150 #ifdef HDC_VERSION_CHECK
151 buf->len = sizeof(struct ChannelHandShake) + DWORD_SERIALIZE_SIZE; // only recv static size
152 #else
153 buf->len = offsetof(struct ChannelHandShake, version) + DWORD_SERIALIZE_SIZE;
154 #endif
155 };
156 // first packet static size, after this packet will be dup for normal recv
157 uv_read_start((uv_stream_t *)&hChannel->hWorkTCP, funcChannelHeaderAlloc, ReadStream);
158 // channel handshake step1
159 struct ChannelHandShake handShake = {};
160 if (EOK == strcpy_s(handShake.banner, sizeof(handShake.banner), HANDSHAKE_MESSAGE.c_str())) {
161 handShake.banner[BANNER_FEATURE_TAG_OFFSET] = HUGE_BUF_TAG; // set feature tag for huge buf size
162 #ifdef HOST_OHOS
163 handShake.banner[SERVICE_KILL_OFFSET] = SERVICE_KILL_TAG;
164 #endif
165 handShake.channelId = htonl(hChannel->channelId);
166 string ver = Base::GetVersion() + HDC_MSG_HASH;
167 WRITE_LOG(LOG_DEBUG, "Server ver:%s", ver.c_str());
168 if (EOK != strcpy_s(handShake.version, sizeof(handShake.version), ver.c_str())) {
169 WRITE_LOG(LOG_FATAL, "strcpy_s failed");
170 return;
171 }
172 #ifdef HDC_VERSION_CHECK
173 thisClass->Send(hChannel->channelId, (uint8_t *)&handShake, sizeof(struct ChannelHandShake));
174 #else
175 // do not send version message if check feature disable
176 thisClass->Send(hChannel->channelId, reinterpret_cast<uint8_t *>(&handShake),
177 offsetof(struct ChannelHandShake, version));
178 #endif
179 }
180 }
181
182 #ifdef __OHOS__
SetUdsListen()183 bool HdcServerForClient::SetUdsListen()
184 {
185 udsListen.data = this;
186 int ret = -1;
187 ret = uv_pipe_init(loopMain, &udsListen, 0);
188
189 unlink(UDS_PATH.c_str());
190
191 if ((ret = uv_pipe_bind(&udsListen, UDS_PATH.c_str())) != 0) {
192 WRITE_LOG(LOG_WARN, "bind uds addr fail! ret:%d", ret);
193 return false;
194 }
195
196 uv_fs_t req = {};
197 ret = uv_fs_chmod(nullptr, &req, UDS_PATH.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
198 nullptr);
199 if (ret < 0) {
200 char buffer[BUF_SIZE_DEFAULT] = { 0 };
201 uv_strerror_r(ret, buffer, BUF_SIZE_DEFAULT);
202 WRITE_LOG(LOG_WARN, "uv_fs_chmod uds failed %s", buffer);
203 uv_fs_req_cleanup(&req);
204 return false;
205 }
206 uv_fs_req_cleanup(&req);
207
208 if ((ret = uv_listen((uv_stream_t *)&udsListen, MAX_CONNECTIONS_COUNT, AcceptUdsClient)) != 0) {
209 WRITE_LOG(LOG_WARN, "uds listen fail! ret:%d", ret);
210 return false;
211 }
212 return true;
213 }
214 #endif
215
SetTCPListen()216 bool HdcServerForClient::SetTCPListen()
217 {
218 char buffer[BUF_SIZE_DEFAULT] = { 0 };
219 tcpListen.data = this;
220 struct sockaddr_in6 addr;
221 uv_tcp_init(loopMain, &tcpListen);
222
223 WRITE_LOG(LOG_DEBUG, "channelHost %s, port: %d", channelHost.c_str(), channelPort);
224 int rc = uv_ip6_addr(channelHost.c_str(), channelPort, &addr);
225 if (rc != 0) {
226 uv_strerror_r(rc, buffer, BUF_SIZE_DEFAULT);
227 WRITE_LOG(LOG_FATAL, "uv_ip6_addr %d %s", rc, buffer);
228 return false;
229 }
230 rc = uv_tcp_bind(&tcpListen, (const struct sockaddr *)&addr, 0);
231 if (rc != 0) {
232 WRITE_LOG(LOG_WARN, "uv_tcp_bind ipv6 %d", rc);
233 if (rc == -EAFNOSUPPORT) {
234 size_t index = channelHost.find(IPV4_MAPPING_PREFIX);
235 size_t size = IPV4_MAPPING_PREFIX.size();
236 if (index != std::string::npos) {
237 struct sockaddr_in addr4v;
238 std::string ipv4 = channelHost.substr(index + size);
239 uv_ip4_addr(ipv4.c_str(), channelPort, &addr4v);
240 rc = uv_tcp_bind(&tcpListen, (const struct sockaddr *)&addr4v, 0);
241 if (rc != 0) {
242 uv_strerror_r(rc, buffer, BUF_SIZE_DEFAULT);
243 WRITE_LOG(LOG_FATAL, "uv_tcp_bind ipv4 %s failed %d %s",
244 ipv4.c_str(), rc, buffer);
245 return false;
246 }
247 }
248 } else {
249 uv_strerror_r(rc, buffer, BUF_SIZE_DEFAULT);
250 WRITE_LOG(LOG_FATAL, "uv_tcp_bind %d %s", rc, buffer);
251 return false;
252 }
253 }
254 int backLog = 128;
255 rc = uv_listen((uv_stream_t *)&tcpListen, backLog, (uv_connection_cb)AcceptClient);
256 if (rc != 0) {
257 uv_strerror_r(rc, buffer, BUF_SIZE_DEFAULT);
258 WRITE_LOG(LOG_FATAL, "uv_listen %d %s", rc, buffer);
259 return false;
260 }
261 return true;
262 }
263
Initial()264 int HdcServerForClient::Initial()
265 {
266 if (!clsServer) {
267 WRITE_LOG(LOG_FATAL, "Module client initial failed");
268 return -1;
269 }
270 #ifndef __OHOS__
271 if (!channelHostPort.size() || !channelHost.size() || !channelPort) {
272 WRITE_LOG(LOG_FATAL, "Listen string initial failed");
273 return -2; // -2:err for Listen initial failed
274 }
275 if (!SetTCPListen()) {
276 WRITE_LOG(LOG_FATAL, "SetTCPListen failed");
277 int listenError = -3; // -3:error for SetTCPListen failed
278 return listenError;
279 }
280 #else
281 if (!channelHostPort.size() || !channelHost.size() || !channelPort) {
282 WRITE_LOG(LOG_FATAL, "Listen string initial failed");
283 } else {
284 if (!SetTCPListen()) {
285 WRITE_LOG(LOG_FATAL, "SetTCPListen failed");
286 }
287 }
288 if (!SetUdsListen()) {
289 WRITE_LOG(LOG_FATAL, "SetUdsListen failed");
290 int listenError = -3; // -3:error for SetUdsListen failed
291 return listenError;
292 }
293 #endif
294
295 return 0;
296 }
297
EchoClient(HChannel hChannel,MessageLevel level,const char * msg,...)298 void HdcServerForClient::EchoClient(HChannel hChannel, MessageLevel level, const char *msg, ...)
299 {
300 StartTraceScope("HdcServerForClient::EchoClient");
301 string logInfo = "";
302 switch (level) {
303 case MSG_FAIL:
304 logInfo = MESSAGE_FAIL;
305 break;
306 case MSG_INFO:
307 logInfo = MESSAGE_INFO;
308 break;
309 default: // successful, not append extra info
310 break;
311 }
312 va_list vaArgs;
313 va_start(vaArgs, msg);
314 string log = logInfo + Base::StringFormat(msg, vaArgs);
315 va_end(vaArgs);
316 if (log.back() != '\n') {
317 log += "\r\n";
318 }
319 SendChannel(hChannel, const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(log.c_str())), log.size());
320 }
321
EchoClientRaw(const HChannel hChannel,uint8_t * payload,const int payloadSize)322 void HdcServerForClient::EchoClientRaw(const HChannel hChannel, uint8_t *payload, const int payloadSize)
323 {
324 SendChannel(hChannel, payload, payloadSize);
325 }
326
327 // HdcServerForClient passthrough file command to client
SendCommandToClient(const HChannel hChannel,const uint16_t commandFlag,uint8_t * payload,const int payloadSize)328 void HdcServerForClient::SendCommandToClient(const HChannel hChannel, const uint16_t commandFlag,
329 uint8_t *payload, const int payloadSize)
330 {
331 if (Base::CanPrintCmd(commandFlag)) {
332 WRITE_LOG(LOG_INFO, "SendCommandToClient cid:%u sid:%u commandID:%u payloadSize:%d",
333 hChannel->channelId, hChannel->targetSessionId, commandFlag, payloadSize);
334 }
335 SendChannelWithCmd(hChannel, commandFlag, payload, payloadSize);
336 }
337
SendToDaemon(HChannel hChannel,const uint16_t commandFlag,uint8_t * bufPtr,const int bufSize)338 bool HdcServerForClient::SendToDaemon(HChannel hChannel, const uint16_t commandFlag, uint8_t *bufPtr, const int bufSize)
339 {
340 StartTraceScope("HdcServerForClient::SendToDaemon");
341 HDaemonInfo hdi = nullptr;
342 bool ret = false;
343 HdcServer *ptrServer = (HdcServer *)clsServer;
344 if (Base::CanPrintCmd(commandFlag)) {
345 WRITE_LOG(LOG_INFO, "SendToDaemon cid:%u sid:%u key:%s commandID:%u sizeSend:%d", hChannel->channelId,
346 hChannel->targetSessionId, Hdc::MaskString(hChannel->connectKey).c_str(), commandFlag, bufSize);
347 }
348 while (true) {
349 ptrServer->AdminDaemonMap(OP_QUERY, hChannel->connectKey, hdi);
350 if (hdi == nullptr) {
351 WRITE_LOG(LOG_FATAL, "SendToDaemon hdi nullptr");
352 break;
353 }
354 if (hdi->connStatus != STATUS_CONNECTED) {
355 WRITE_LOG(LOG_FATAL, "SendToDaemon not connected");
356 break;
357 }
358 if (!hdi->hSession) {
359 WRITE_LOG(LOG_FATAL, "SendToDaemon hdi->hSession nullptr");
360 break;
361 }
362 if (ptrServer->Send(hdi->hSession->sessionId, hChannel->channelId, commandFlag, bufPtr, bufSize) < 0) {
363 WRITE_LOG(LOG_FATAL, "SendToDaemon Send failed channelId:%u", hChannel->channelId);
364 break;
365 }
366 ret = true;
367 break;
368 }
369 return ret;
370 }
371
OrderFindTargets(HChannel hChannel)372 void HdcServerForClient::OrderFindTargets(HChannel hChannel)
373 {
374 int count = 0;
375 EchoClient(hChannel, MSG_INFO, "Please add HDC server's firewall ruler to allow udp incoming, udpport:%d",
376 DEFAULT_PORT);
377 HdcServer *ptrServer = (HdcServer *)clsServer;
378 ptrServer->clsTCPClt->FindLanDaemon();
379 list<string> &lst = ptrServer->clsTCPClt->lstDaemonResult;
380 // refresh main list
381 HdcDaemonInformation di;
382 while (!lst.empty()) {
383 di = {};
384 ++count;
385 di.connectKey = lst.front();
386 di.connType = CONN_TCP;
387 di.connStatus = STATUS_READY;
388 di.inited = false;
389 HDaemonInfo pDi = reinterpret_cast<HDaemonInfo>(&di);
390 ptrServer->AdminDaemonMap(OP_ADD, STRING_EMPTY, pDi);
391 lst.pop_front();
392 }
393 EchoClient(hChannel, MSG_INFO, "Broadcast find daemon, total:%d", count);
394 #ifdef UNIT_TEST
395 string bufString = std::to_string(count);
396 Base::WriteBinFile((UT_TMP_PATH + "/base-discover.result").c_str(), (uint8_t *)bufString.c_str(), bufString.size(),
397 true);
398 #endif
399 }
400
OrderConnecTargetResult(uv_timer_t * req)401 void HdcServerForClient::OrderConnecTargetResult(uv_timer_t *req)
402 {
403 HChannel hChannel = (HChannel)req->data;
404 HdcServerForClient *thisClass = (HdcServerForClient *)hChannel->clsChannel;
405 HdcServer *ptrServer = (HdcServer *)thisClass->clsServer;
406 bool bConnectOK = false;
407 bool bExitRepet = false;
408 HDaemonInfo hdi = nullptr;
409 string sRet;
410 string target = std::string(hChannel->bufStd + 2);
411 if (target == "any") {
412 ptrServer->AdminDaemonMap(OP_GET_ANY, target, hdi);
413 } else {
414 ptrServer->AdminDaemonMap(OP_QUERY, target, hdi);
415 }
416 if (hdi && hdi->connStatus == STATUS_CONNECTED) {
417 bConnectOK = true;
418 }
419 while (true) {
420 if (bConnectOK) {
421 bExitRepet = true;
422 if (hChannel->isCheck) {
423 WRITE_LOG(LOG_INFO, "%s check device success and remove %s", __FUNCTION__, hChannel->key.c_str());
424 thisClass->CommandRemoveSession(hChannel, hChannel->key.c_str());
425 thisClass->EchoClient(hChannel, MSG_OK, const_cast<char *>(hdi->version.c_str()));
426 } else {
427 sRet = "Connect OK";
428 thisClass->EchoClient(hChannel, MSG_OK, const_cast<char *>(sRet.c_str()));
429 }
430 break;
431 } else {
432 uint16_t *bRetryCount = reinterpret_cast<uint16_t *>(hChannel->bufStd);
433 ++(*bRetryCount);
434 if (*bRetryCount > MAX_RETRY_COUNT ||
435 (hChannel->connectLocalDevice && *bRetryCount > MAX_CONNECT_DEVICE_RETRY_COUNT)) {
436 // 5s or localDevice 1s
437 bExitRepet = true;
438 sRet = "Connect failed";
439 thisClass->EchoClient(hChannel, MSG_FAIL, const_cast<char *>(sRet.c_str()));
440 hdi->inited = false;
441 hdi->connStatus = STATUS_OFFLINE;
442 ptrServer->AdminDaemonMap(OP_UPDATE, target, hdi);
443 break;
444 }
445 }
446 break;
447 }
448 if (bExitRepet) {
449 thisClass->FreeChannel(hChannel->channelId);
450 Base::TryCloseHandle((const uv_handle_t *)req, Base::CloseTimerCallback);
451 }
452 }
453
NewConnectTry(void * ptrServer,HChannel hChannel,const string & connectKey,bool isCheck)454 bool HdcServerForClient::NewConnectTry(void *ptrServer, HChannel hChannel, const string &connectKey, bool isCheck)
455 {
456 #ifdef HDC_DEBUG
457 WRITE_LOG(LOG_ALL, "%s %s", __FUNCTION__, Hdc::MaskString(connectKey).c_str());
458 #endif
459 int childRet = ((HdcServer *)ptrServer)->CreateConnect(connectKey, isCheck);
460 bool ret = false;
461 int connectError = -2;
462 constexpr uint8_t bufOffsetTwo = 2;
463 constexpr uint8_t bufOffsetThree = 3;
464 if (childRet == -1) {
465 EchoClient(hChannel, MSG_INFO, "Target is connected, repeat operation");
466 } else if (childRet == connectError) {
467 EchoClient(hChannel, MSG_FAIL, "CreateConnect failed");
468 WRITE_LOG(LOG_FATAL, "CreateConnect failed");
469 } else {
470 size_t pos = connectKey.find(":");
471 if (pos != std::string::npos) {
472 string ip = connectKey.substr(0, pos);
473 if (ip == "127.0.0.1") {
474 hChannel->connectLocalDevice = true;
475 }
476 }
477 Base::ZeroBuf(hChannel->bufStd, bufOffsetTwo);
478 childRet = snprintf_s(hChannel->bufStd + bufOffsetTwo, sizeof(hChannel->bufStd) - bufOffsetTwo,
479 sizeof(hChannel->bufStd) - bufOffsetThree, "%s",
480 const_cast<char *>(connectKey.c_str()));
481 if (childRet > 0) {
482 Base::TimerUvTask(loopMain, hChannel, OrderConnecTargetResult, UV_START_REPEAT);
483 ret = true;
484 }
485 }
486 return ret;
487 }
488
CommandRemoveSession(HChannel hChannel,const char * connectKey)489 bool HdcServerForClient::CommandRemoveSession(HChannel hChannel, const char *connectKey)
490 {
491 HdcServer *ptrServer = (HdcServer *)clsServer;
492 HDaemonInfo hdiOld = nullptr;
493 (reinterpret_cast<HdcServer *>(ptrServer))->AdminDaemonMap(OP_QUERY, connectKey, hdiOld);
494 if (hdiOld == nullptr || hdiOld->hSession == nullptr) {
495 EchoClient(hChannel, MSG_FAIL, "No target available");
496 WRITE_LOG(LOG_FATAL, "CommandRemoveSession No target available");
497 return false;
498 }
499 (reinterpret_cast<HdcServer *>(ptrServer))->FreeSession(hdiOld->hSession->sessionId);
500 return true;
501 }
502
CommandRemoveForward(const string & forwardKey)503 bool HdcServerForClient::CommandRemoveForward(const string &forwardKey)
504 {
505 StartTraceScope("HdcServerForClient::CommandRemoveForward");
506 bool ret = RemoveFportkey("0|" + forwardKey);
507 ret |= RemoveFportkey("1|" + forwardKey);
508 return ret;
509 }
510
RemoveFportkey(const string & forwardKey)511 bool HdcServerForClient::RemoveFportkey(const string &forwardKey)
512 {
513 StartTraceScope("HdcServerForClient::RemoveFportkey");
514 HdcServer *ptrServer = (HdcServer *)clsServer;
515 HForwardInfo hfi = nullptr;
516 ptrServer->AdminForwardMap(OP_QUERY, forwardKey, hfi);
517 if (!hfi) {
518 WRITE_LOG(LOG_FATAL, "CommandRemoveForward hfi nullptr forwardKey:%s", forwardKey.c_str());
519 return false;
520 }
521 HSession hSession = ptrServer->AdminSession(OP_QUERY, hfi->sessionId, nullptr);
522 if (!hSession) {
523 WRITE_LOG(LOG_FATAL, "CommandRemoveForward hSession nullptr sessionId:%u", hfi->sessionId);
524 ptrServer->AdminForwardMap(OP_REMOVE, forwardKey, hfi);
525 return true;
526 }
527 hSession->commandCount++;
528 ptrServer->ClearOwnTasks(hSession, hfi->channelId);
529 FreeChannel(hfi->channelId);
530 hfi = nullptr;
531 ptrServer->AdminForwardMap(OP_REMOVE, forwardKey, hfi);
532 return true;
533 }
534
GetTargetList(HChannel hChannel,void * formatCommandInput)535 void HdcServerForClient::GetTargetList(HChannel hChannel, void *formatCommandInput)
536 {
537 TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput;
538 HdcServer *ptrServer = (HdcServer *)clsServer;
539 uint16_t cmd = OP_GET_STRLIST;
540 if (formatCommand->parameters == "v") {
541 cmd = OP_GET_STRLIST_FULL;
542 }
543 HDaemonInfo hdi = nullptr;
544 string sRet = ptrServer->AdminDaemonMap(cmd, STRING_EMPTY, hdi);
545 if (!sRet.length()) {
546 sRet = EMPTY_ECHO;
547 }
548 EchoClient(hChannel, MSG_OK, const_cast<char *>(sRet.c_str()));
549 #ifdef UNIT_TEST
550 Base::WriteBinFile((UT_TMP_PATH + "/base-list.result").c_str(), (uint8_t *)MESSAGE_SUCCESS.c_str(),
551 MESSAGE_SUCCESS.size(), true);
552 #endif
553 }
554
GetAnyTarget(HChannel hChannel)555 bool HdcServerForClient::GetAnyTarget(HChannel hChannel)
556 {
557 HdcServer *ptrServer = (HdcServer *)clsServer;
558 HDaemonInfo hdi = nullptr;
559 ptrServer->AdminDaemonMap(OP_GET_ANY, STRING_EMPTY, hdi);
560 if (!hdi) {
561 EchoClient(hChannel, MSG_FAIL, "No target available");
562 return false;
563 }
564 // can not use hdi->connectKey.This memory may be released to re-Malloc
565 string connectKey = hdi->connectKey;
566 bool ret = NewConnectTry(ptrServer, hChannel, connectKey);
567 #ifdef UNIT_TEST
568 Base::WriteBinFile((UT_TMP_PATH + "/base-any.result").c_str(), (uint8_t *)MESSAGE_SUCCESS.c_str(),
569 MESSAGE_SUCCESS.size(), true);
570 #endif
571 return ret;
572 }
573
WaitForAny(HChannel hChannel)574 bool HdcServerForClient::WaitForAny(HChannel hChannel)
575 {
576 HdcServer *ptrServer = (HdcServer *)clsServer;
577 HDaemonInfo hdi = nullptr;
578 if (!hChannel->connectKey.empty()) {
579 ptrServer->AdminDaemonMap(OP_WAIT_FOR_ANY, hChannel->connectKey, hdi);
580 } else {
581 ptrServer->AdminDaemonMap(OP_WAIT_FOR_ANY, STRING_EMPTY, hdi);
582 }
583 if (!hdi) {
584 EchoClient(hChannel, MSG_FAIL, "No any connected target");
585 return false;
586 }
587 string key = hdi->connectKey;
588 EchoClient(hChannel, MSG_OK, "Wait for connected target is %s", key.c_str());
589 return true;
590 }
591
RemoveForward(HChannel hChannel,const char * parameterString)592 bool HdcServerForClient::RemoveForward(HChannel hChannel, const char *parameterString)
593 {
594 StartTraceScope("HdcServerForClient::RemoveForward");
595 HdcServer *ptrServer = (HdcServer *)clsServer;
596 if (parameterString == nullptr) { // remove all
597 HForwardInfo hfi = nullptr; // dummy
598 string echo = ptrServer->AdminForwardMap(OP_GET_STRLIST, "", hfi);
599 if (!echo.length()) {
600 return false;
601 }
602 vector<string> filterStrings;
603 Base::SplitString(echo, string("\n"), filterStrings);
604 for (auto &&s : filterStrings) {
605 if (CommandRemoveForward(s.c_str())) {
606 EchoClient(hChannel, MSG_OK, "Remove forward ruler success, ruler:%s", s.c_str());
607 } else {
608 EchoClient(hChannel, MSG_FAIL, "Remove forward ruler failed, ruler is not exist %s", s.c_str());
609 }
610 }
611 } else { // remove single
612 if (CommandRemoveForward(parameterString)) {
613 EchoClient(hChannel, MSG_OK, "Remove forward ruler success, ruler:%s", parameterString);
614 } else {
615 EchoClient(hChannel, MSG_FAIL, "Remove forward ruler failed, ruler is not exist %s", parameterString);
616 }
617 }
618 return true;
619 }
620
DoCommandLocal(HChannel hChannel,void * formatCommandInput)621 bool HdcServerForClient::DoCommandLocal(HChannel hChannel, void *formatCommandInput)
622 {
623 StartTraceScope("HdcServerForClient::DoCommandLocal");
624 TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput;
625 HdcServer *ptrServer = (HdcServer *)clsServer;
626 bool ret = false;
627 // Main thread command, direct Listen main thread
628 switch (formatCommand->cmdFlag) {
629 case CMD_KERNEL_TARGET_DISCOVER: {
630 OrderFindTargets(hChannel);
631 hChannel->isSuccess = true;
632 ret = false;
633 break;
634 }
635 case CMD_KERNEL_TARGET_LIST: {
636 GetTargetList(hChannel, formatCommandInput);
637 hChannel->isSuccess = true;
638 ret = false;
639 break;
640 }
641 case CMD_SERVICE_START: {
642 PrintLastError(hChannel);
643 hChannel->isSuccess = true;
644 ret = false;
645 break;
646 }
647 #ifdef HOST_OHOS
648 case CMD_SERVER_KILL: {
649 WRITE_LOG(LOG_FATAL, "CMD_SERVER_KILL command");
650 ptrServer->SessionSoftReset();
651 hChannel->isSuccess = true;
652 EchoClient(hChannel, MSG_OK, "Kill server finish");
653 _exit(0);
654 }
655 #endif
656 case CMD_CHECK_SERVER: {
657 WRITE_LOG(LOG_DEBUG, "CMD_CHECK_SERVER command");
658 ReportServerVersion(hChannel);
659 hChannel->isSuccess = true;
660 ret = false;
661 break;
662 }
663 case CMD_WAIT_FOR: {
664 WRITE_LOG(LOG_DEBUG, "CMD_WAIT_FOR command");
665 ret = !WaitForAny(hChannel);
666 hChannel->isSuccess = ret;
667 break;
668 }
669 case CMD_KERNEL_TARGET_ANY: {
670 #ifdef HDC_DEBUG
671 WRITE_LOG(LOG_DEBUG, "%s CMD_KERNEL_TARGET_ANY %s", __FUNCTION__, formatCommand->parameters.c_str());
672 #endif
673 ret = GetAnyTarget(hChannel);
674 hChannel->isSuccess = ret;
675 break;
676 }
677 case CMD_KERNEL_TARGET_CONNECT: {
678 #ifdef HDC_DEBUG
679 WRITE_LOG(LOG_DEBUG, "%s CMD_KERNEL_TARGET_CONNECT %s", __FUNCTION__, formatCommand->parameters.c_str());
680 #endif
681 ret = NewConnectTry(ptrServer, hChannel, formatCommand->parameters.c_str());
682 hChannel->isSuccess = ret;
683 break;
684 }
685 case CMD_CHECK_DEVICE: {
686 WRITE_LOG(LOG_INFO, "%s CMD_CHECK_DEVICE %s", __FUNCTION__, formatCommand->parameters.c_str());
687 hChannel->isCheck = true;
688 hChannel->key = formatCommand->parameters.c_str();
689 ret = NewConnectTry(ptrServer, hChannel, formatCommand->parameters.c_str(), true);
690 hChannel->isSuccess = ret;
691 break;
692 }
693 case CMD_KERNEL_TARGET_DISCONNECT: {
694 CommandRemoveSession(hChannel, formatCommand->parameters.c_str());
695 hChannel->isSuccess = true;
696 break;
697 }
698 // task will be global task,Therefore, it can only be controlled in the global session.
699 case CMD_FORWARD_LIST: {
700 HForwardInfo hfi = nullptr; // dummy
701 string echo = ptrServer->AdminForwardMap(OP_GET_STRLIST_FULL, "", hfi);
702 if (!echo.length()) {
703 echo = EMPTY_ECHO;
704 }
705 EchoClient(hChannel, MSG_OK, const_cast<char *>(echo.c_str()));
706 hChannel->isSuccess = true;
707 break;
708 }
709 case CMD_FORWARD_REMOVE: {
710 RemoveForward(hChannel, formatCommand->parameters.c_str());
711 hChannel->isSuccess = true;
712 break;
713 }
714 case CMD_KERNEL_ENABLE_KEEPALIVE: {
715 // just use for 'list targets' now
716 hChannel->keepAlive = true;
717 ret = true;
718 hChannel->isSuccess = true;
719 break;
720 }
721 default: {
722 EchoClient(hChannel, MSG_FAIL, "ExecuteCommand need connect-key? please confirm a device by help info");
723 FillChannelResult(hChannel, false, "found no devices");
724 break;
725 }
726 }
727 return ret;
728 }
729
TaskCommand(HChannel hChannel,void * formatCommandInput)730 bool HdcServerForClient::TaskCommand(HChannel hChannel, void *formatCommandInput)
731 {
732 StartTraceScope("HdcServerForClient::TaskCommand");
733 TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput;
734 HdcServer *ptrServer = (HdcServer *)clsServer;
735 string cmdFlag;
736 uint8_t sizeCmdFlag = 0;
737 if (formatCommand->cmdFlag == CMD_FILE_INIT) {
738 cmdFlag = "send ";
739 sizeCmdFlag = 5; // 5: cmdFlag send size
740 HandleRemote(hChannel, formatCommand->parameters, RemoteType::REMOTE_FILE);
741 } else if (formatCommand->cmdFlag == CMD_FORWARD_INIT) {
742 cmdFlag = "fport ";
743 sizeCmdFlag = 6; // 6: cmdFlag fport size
744 } else if (formatCommand->cmdFlag == CMD_APP_INIT) {
745 cmdFlag = "install ";
746 sizeCmdFlag = 8; // 8: cmdFlag install size
747 HandleRemote(hChannel, formatCommand->parameters, RemoteType::REMOTE_APP);
748 } else if (formatCommand->cmdFlag == CMD_APP_UNINSTALL) {
749 cmdFlag = "uninstall ";
750 sizeCmdFlag = 10; // 10: cmdFlag uninstall size
751 } else if (formatCommand->cmdFlag == CMD_UNITY_BUGREPORT_INIT) {
752 cmdFlag = "bugreport ";
753 sizeCmdFlag = 10; // 10: cmdFlag bugreport size
754 } else if (formatCommand->cmdFlag == CMD_APP_SIDELOAD) {
755 cmdFlag = "sideload ";
756 sizeCmdFlag = 9; // 9: cmdFlag sideload size
757 } else if (formatCommand->cmdFlag == CMD_FLASHD_UPDATE_INIT) {
758 cmdFlag = "update ";
759 sizeCmdFlag = 7; // 7: cmdFlag update size
760 } else if (formatCommand->cmdFlag == CMD_FLASHD_FLASH_INIT) {
761 cmdFlag = "flash ";
762 sizeCmdFlag = 6; // 6: cmdFlag flash size
763 }
764 int sizeSend = formatCommand->parameters.size();
765 if (!strncmp(formatCommand->parameters.c_str(), cmdFlag.c_str(), sizeCmdFlag)) { // local do
766 HSession hSession = FindAliveSession(hChannel->targetSessionId);
767 if (!hSession) {
768 return false;
769 }
770 if ((formatCommand->cmdFlag == CMD_FILE_INIT || formatCommand->cmdFlag == CMD_APP_INIT) &&
771 hChannel->fromClient) {
772 // remote client mode, CMD_FILE_INIT and CMD_APP_INIT command send back to client
773 WRITE_LOG(LOG_INFO, "CMD_FILE_INIT|CMD_APP_INIT command send back to remote client, cid:%u",
774 hChannel->channelId);
775 SendChannelWithCmd(hChannel, formatCommand->cmdFlag,
776 reinterpret_cast<uint8_t *>(const_cast<char *>(formatCommand->parameters.c_str())) + sizeCmdFlag,
777 sizeSend - sizeCmdFlag);
778 return false;
779 }
780 ptrServer->DispatchTaskData(hSession, hChannel->channelId, formatCommand->cmdFlag,
781 reinterpret_cast<uint8_t *>(const_cast<char *>(formatCommand->parameters.c_str())) + sizeCmdFlag,
782 sizeSend - sizeCmdFlag);
783 } else { // Send to Daemon-side to do
784 SendToDaemon(hChannel, formatCommand->cmdFlag,
785 reinterpret_cast<uint8_t *>(const_cast<char *>(formatCommand->parameters.c_str())) + sizeCmdFlag,
786 sizeSend - sizeCmdFlag);
787 }
788 return true;
789 }
790
HandleRemote(HChannel hChannel,string & parameters,RemoteType flag)791 void HdcServerForClient::HandleRemote(HChannel hChannel, string ¶meters, RemoteType flag)
792 {
793 StartTraceScope("HdcServerForClient::HandleRemote");
794 hChannel->remote = flag;
795 int argc = 0;
796 char **argv = Base::SplitCommandToArgs(parameters.c_str(), &argc);
797 for (int i = 0; i < argc; i++) {
798 if (argv[i] == CMDSTR_REMOTE_PARAMETER) {
799 hChannel->fromClient = true;
800 WRITE_LOG(LOG_DEBUG, "remote client mode channelId:%u", hChannel->channelId);
801 break;
802 }
803 }
804 if (hChannel->fromClient) {
805 string remote = CMDSTR_REMOTE_PARAMETER + " ";
806 if (parameters.find(remote) != std::string::npos) {
807 parameters.replace(parameters.find(remote), remote.size(), "");
808 WRITE_LOG(LOG_DEBUG, "parameters: %s", Hdc::MaskString(parameters).c_str());
809 }
810 }
811 delete[](reinterpret_cast<char *>(argv));
812 }
813
814 #ifdef __OHOS__
IsServerTransfer(HChannel hChannel,uint16_t cmdFlag,string & parameters)815 bool HdcServerForClient::IsServerTransfer(HChannel hChannel, uint16_t cmdFlag, string ¶meters)
816 {
817 if (cmdFlag == CMD_FILE_INIT || cmdFlag== CMD_APP_INIT) {
818 HandleRemote(hChannel, parameters, RemoteType::REMOTE_FILE);
819 if (!hChannel->fromClient) {
820 EchoClient(hChannel, MSG_FAIL, "[E005200] Unsupport file command");
821 return false;
822 }
823 }
824 return true;
825 }
826 #endif
827
DoCommandRemote(HChannel hChannel,void * formatCommandInput)828 bool HdcServerForClient::DoCommandRemote(HChannel hChannel, void *formatCommandInput)
829 {
830 StartTraceScope("HdcServerForClient::DoCommandRemote");
831 TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput;
832 bool ret = false;
833 int sizeSend = formatCommand->parameters.size();
834 switch (formatCommand->cmdFlag) {
835 // Some simple commands only need to forward the instruction, no need to start Task
836 case CMD_SHELL_INIT:
837 case CMD_SHELL_DATA:
838 case CMD_UNITY_EXECUTE:
839 case CMD_UNITY_EXECUTE_EX:
840 case CMD_UNITY_REMOUNT:
841 case CMD_UNITY_REBOOT:
842 case CMD_UNITY_RUNMODE:
843 case CMD_UNITY_HILOG:
844 case CMD_UNITY_ROOTRUN:
845 case CMD_JDWP_TRACK:
846 case CMD_JDWP_LIST: {
847 if (!SendToDaemon(hChannel, formatCommand->cmdFlag,
848 reinterpret_cast<uint8_t *>(const_cast<char *>(formatCommand->parameters.c_str())), sizeSend)) {
849 break;
850 }
851 ret = true;
852 if (formatCommand->cmdFlag == CMD_SHELL_INIT) {
853 hChannel->interactiveShellMode = true;
854 }
855 break;
856 }
857 case CMD_FILE_INIT:
858 case CMD_FORWARD_INIT:
859 case CMD_APP_INIT: {
860 #ifdef __OHOS__
861 if (!IsServerTransfer(hChannel, formatCommand->cmdFlag, formatCommand->parameters)) {
862 return false;
863 }
864 #endif
865 }
866 case CMD_APP_UNINSTALL:
867 case CMD_UNITY_BUGREPORT_INIT:
868 case CMD_APP_SIDELOAD:
869 case CMD_FLASHD_UPDATE_INIT:
870 case CMD_FLASHD_FLASH_INIT:
871 case CMD_FLASHD_ERASE:
872 case CMD_FLASHD_FORMAT: {
873 TaskCommand(hChannel, formatCommandInput);
874 ret = true;
875 break;
876 }
877 default:
878 break;
879 }
880 if (!ret) {
881 EchoClient(hChannel, MSG_FAIL, "[E002106] Failed to communicate with daemon");
882 }
883 return ret;
884 }
885 // Do not specify Target's operations no longer need to put it in the thread.
DoCommand(HChannel hChannel,void * formatCommandInput,HDaemonInfo & hdi)886 bool HdcServerForClient::DoCommand(HChannel hChannel, void *formatCommandInput, HDaemonInfo &hdi)
887 {
888 StartTraceScope("HdcServerForClient::DoCommand");
889 bool ret = false;
890 TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput;
891 #ifdef __OHOS__
892 if ((!hChannel->hChildWorkTCP.loop && !hChannel->hChildWorkUds.loop) ||
893 #else
894 if (!hChannel->hChildWorkTCP.loop ||
895 #endif
896 formatCommand->cmdFlag == CMD_FORWARD_REMOVE ||
897 #ifdef HOST_OHOS
898 formatCommand->cmdFlag == CMD_SERVER_KILL ||
899 #endif
900 formatCommand->cmdFlag == CMD_SERVICE_START) {
901 hChannel->commandFlag = formatCommand->cmdFlag;
902 hChannel->commandParameters = formatCommand->parameters;
903 // Main thread command, direct Listen main thread
904 ret = DoCommandLocal(hChannel, formatCommandInput);
905 } else { // CONNECT DAEMON's work thread command, non-primary thread
906 if (!CommandMatchDaemonFeature(formatCommand->cmdFlag, hdi)) {
907 // only the cmdFlag in the FEATURE_VERSION_MATCH_MAP needs to be checked, others to permissive.
908 WRITE_LOG(LOG_WARN, "unsupport cmdFlag: %d, due to daemon feature dismatch", formatCommand->cmdFlag);
909 EchoClient(hChannel, MSG_FAIL, "[E002105] Unsupport command");
910 return false;
911 }
912 if (formatCommand->cmdFlag != CMD_SHELL_DATA) {
913 hChannel->commandFlag = formatCommand->cmdFlag;
914 hChannel->commandParameters = formatCommand->parameters;
915 }
916 ret = DoCommandRemote(hChannel, formatCommandInput);
917 }
918 return ret;
919 }
920
921 // just call from BindChannelToSession
FindAliveSessionFromDaemonMap(const HChannel hChannel)922 HSession HdcServerForClient::FindAliveSessionFromDaemonMap(const HChannel hChannel)
923 {
924 StartTraceScope("HdcServerForClient::FindAliveSessionFromDaemonMap");
925 HSession hSession = nullptr;
926 HDaemonInfo hdi = nullptr;
927 HdcServer *ptrServer = (HdcServer *)clsServer;
928 ptrServer->AdminDaemonMap(OP_QUERY, hChannel->connectKey, hdi);
929 if (!hdi) {
930 WRITE_LOG(LOG_WARN, "Not match target founded cid:%u", hChannel->channelId);
931 FillChannelResult(hChannel, false, "no match targets found");
932 EchoClient(hChannel, MSG_FAIL, "Not match target founded, check connect-key please");
933 return nullptr;
934 }
935 if (hdi->connStatus != STATUS_CONNECTED) {
936 WRITE_LOG(LOG_WARN, "Device not found or connected cid:%u", hChannel->channelId);
937 FillChannelResult(hChannel, false, "device not found or connected");
938 EchoClient(hChannel, MSG_FAIL, "[E001005] Device not found or connected");
939 return nullptr;
940 }
941 if (hdi->hSession == nullptr || hdi->hSession->isDead) {
942 WRITE_LOG(LOG_WARN, "Bind tartget session is null or dead cid:%u", hChannel->channelId);
943 FillChannelResult(hChannel, false, "bind tartget session is null or dead");
944 EchoClient(hChannel, MSG_FAIL, "Bind tartget session is dead");
945 return nullptr;
946 }
947 if (!hdi->hSession->handshakeOK) {
948 WRITE_LOG(LOG_WARN, "hSession handShake is false sid:%u cid:%u",
949 hdi->hSession->sessionId, hChannel->channelId);
950 FillChannelResult(hChannel, false, "handshake is not ready");
951 const string errMsg = "[E000004]:The communication channel is being established.\r\n"\
952 "Please wait for several seconds and try again.";
953 EchoClient(hChannel, MSG_FAIL, errMsg.c_str());
954 return nullptr;
955 }
956 hSession = reinterpret_cast<HSession>(hdi->hSession);
957 return hSession;
958 }
959
960 #ifdef __OHOS__
BindChannelToSession(HChannel hChannel,uint8_t * bufPtr,const int bytesIO)961 int HdcServerForClient::BindChannelToSession(HChannel hChannel, uint8_t *bufPtr, const int bytesIO)
962 {
963 StartTraceScope("HdcServerForClient::BindChannelToSession");
964 if (FindAliveSessionFromDaemonMap(hChannel) == nullptr) {
965 WRITE_LOG(LOG_FATAL, "Find no alive session channelId:%u", hChannel->channelId);
966 return ERR_SESSION_NOFOUND;
967 }
968 bool isClosing = false;
969 if (!hChannel->isUds) {
970 isClosing = uv_is_closing((const uv_handle_t *)&hChannel->hWorkTCP);
971 if (!isClosing && (hChannel->fdChildWorkTCP = Base::DuplicateUvSocket(&hChannel->hWorkTCP)) < 0) {
972 WRITE_LOG(LOG_FATAL, "Duplicate socket failed channelId:%u", hChannel->channelId);
973 return ERR_SOCKET_DUPLICATE;
974 }
975 } else {
976 isClosing = uv_is_closing((const uv_handle_t *)&hChannel->hWorkUds);
977 if (!isClosing && (hChannel->fdChildWorkTCP = Base::DuplicateUvPipe(&hChannel->hWorkUds)) < 0) {
978 WRITE_LOG(LOG_FATAL, "Duplicate pipe failed channelId:%u", hChannel->channelId);
979 return ERR_SOCKET_DUPLICATE;
980 }
981 }
982
983 uv_close_cb funcWorkTcpClose = [](uv_handle_t *handle) -> void {
984 HChannel hChannel = (HChannel)handle->data;
985 --hChannel->ref;
986 };
987 ++hChannel->ref;
988 if (!isClosing) {
989 if (!hChannel->isUds) {
990 uv_close((uv_handle_t *)&hChannel->hWorkTCP, funcWorkTcpClose);
991 } else {
992 uv_close((uv_handle_t *)&hChannel->hWorkUds, funcWorkTcpClose);
993 }
994 }
995 Base::DoNextLoop(loopMain, hChannel, [](const uint8_t flag, string &msg, const void *data) {
996 // Thread message can avoid using thread lock and improve program efficiency
997 // If not next loop call, ReadStream will thread conflict
998 HChannel hChannel = (HChannel)data;
999 auto thisClass = (HdcServerForClient *)hChannel->clsChannel;
1000 HSession hSession = nullptr;
1001 if ((hSession = thisClass->FindAliveSessionFromDaemonMap(hChannel)) == nullptr) {
1002 WRITE_LOG(LOG_FATAL, "hSession nullptr channelId:%u", hChannel->channelId);
1003 return;
1004 }
1005 auto ctrl = HdcSessionBase::BuildCtrlString(SP_ATTACH_CHANNEL, hChannel->channelId, nullptr, 0);
1006 Base::SendToPollFd(hSession->ctrlFd[STREAM_MAIN], ctrl.data(), ctrl.size());
1007 });
1008 return RET_SUCCESS;
1009 }
1010 #else
BindChannelToSession(HChannel hChannel,uint8_t * bufPtr,const int bytesIO)1011 int HdcServerForClient::BindChannelToSession(HChannel hChannel, uint8_t *bufPtr, const int bytesIO)
1012 {
1013 StartTraceScope("HdcServerForClient::BindChannelToSession");
1014 if (FindAliveSessionFromDaemonMap(hChannel) == nullptr) {
1015 WRITE_LOG(LOG_FATAL, "Find no alive session channelId:%u", hChannel->channelId);
1016 return ERR_SESSION_NOFOUND;
1017 }
1018 bool isClosing = uv_is_closing((const uv_handle_t *)&hChannel->hWorkTCP);
1019 if (!isClosing && (hChannel->fdChildWorkTCP = Base::DuplicateUvSocket(&hChannel->hWorkTCP)) < 0) {
1020 WRITE_LOG(LOG_FATAL, "Duplicate socket failed channelId:%u", hChannel->channelId);
1021 return ERR_SOCKET_DUPLICATE;
1022 }
1023
1024 uv_close_cb funcWorkTcpClose = [](uv_handle_t *handle) -> void {
1025 HChannel hChannel = (HChannel)handle->data;
1026 --hChannel->ref;
1027 };
1028 ++hChannel->ref;
1029 if (!isClosing) {
1030 uv_close((uv_handle_t *)&hChannel->hWorkTCP, funcWorkTcpClose);
1031 }
1032 Base::DoNextLoop(loopMain, hChannel, [](const uint8_t flag, string &msg, const void *data) {
1033 // Thread message can avoid using thread lock and improve program efficiency
1034 // If not next loop call, ReadStream will thread conflict
1035 HChannel hChannel = (HChannel)data;
1036 auto thisClass = (HdcServerForClient *)hChannel->clsChannel;
1037 HSession hSession = nullptr;
1038 if ((hSession = thisClass->FindAliveSessionFromDaemonMap(hChannel)) == nullptr) {
1039 WRITE_LOG(LOG_FATAL, "hSession nullptr channelId:%u", hChannel->channelId);
1040 return;
1041 }
1042 auto ctrl = HdcSessionBase::BuildCtrlString(SP_ATTACH_CHANNEL, hChannel->channelId, nullptr, 0);
1043 Base::SendToPollFd(hSession->ctrlFd[STREAM_MAIN], ctrl.data(), ctrl.size());
1044 });
1045 return RET_SUCCESS;
1046 }
1047 #endif
1048
CheckAutoFillTarget(HChannel hChannel)1049 bool HdcServerForClient::CheckAutoFillTarget(HChannel hChannel)
1050 {
1051 HdcServer *ptrServer = (HdcServer *)clsServer;
1052 if (!hChannel->connectKey.size()) {
1053 WRITE_LOG(LOG_FATAL, "connectKey.size 0 channelId:%u", hChannel->channelId);
1054 return false; // Operation of non-bound destination of scanning
1055 }
1056 if (hChannel->connectKey == CMDSTR_CONNECT_ANY) {
1057 HDaemonInfo hdiOld = nullptr;
1058 ptrServer->AdminDaemonMap(OP_GET_ONLY, "", hdiOld);
1059 if (!hdiOld) {
1060 WRITE_LOG(LOG_WARN, "No any key found channelId:%u", hChannel->channelId);
1061 return false;
1062 }
1063 if (!hdiOld->hSession) {
1064 WRITE_LOG(LOG_WARN, "hSession is null. channelId:%u", hChannel->channelId);
1065 return false;
1066 }
1067 if (!hdiOld->hSession->handshakeOK) {
1068 WRITE_LOG(LOG_WARN, "hSession handShake is false SessionId:%u", hdiOld->hSession->sessionId);
1069 return false;
1070 }
1071 hChannel->connectKey = hdiOld->connectKey;
1072 return true;
1073 }
1074 return true;
1075 }
1076
ChannelHandShake(HChannel hChannel,uint8_t * bufPtr,const int bytesIO)1077 int HdcServerForClient::ChannelHandShake(HChannel hChannel, uint8_t *bufPtr, const int bytesIO)
1078 {
1079 StartTraceScope("HdcServerForClient::ChannelHandShake");
1080 vector<uint8_t> rebuildHandshake;
1081 rebuildHandshake.insert(rebuildHandshake.end(), bufPtr, bufPtr + bytesIO);
1082 rebuildHandshake.push_back(0x00);
1083 struct ChannelHandShake *handShake = reinterpret_cast<struct ChannelHandShake *>(rebuildHandshake.data());
1084 if (strncmp(handShake->banner, HANDSHAKE_MESSAGE.c_str(), HANDSHAKE_MESSAGE.size())) {
1085 hChannel->availTailIndex = 0;
1086 WRITE_LOG(LOG_DEBUG, "Channel Hello failed");
1087 return ERR_HANDSHAKE_NOTMATCH;
1088 }
1089 if (strlen(handShake->connectKey) > sizeof(handShake->connectKey)) {
1090 hChannel->availTailIndex = 0;
1091 WRITE_LOG(LOG_DEBUG, "Connectkey's size incorrect");
1092 return ERR_HANDSHAKE_CONNECTKEY_FAILED;
1093 }
1094 // channel handshake step3
1095 WRITE_LOG(LOG_DEBUG, "ServerForClient cid:%u sid:%u handshake finished",
1096 hChannel->channelId, hChannel->targetSessionId);
1097 hChannel->connectKey = handShake->connectKey;
1098 hChannel->handshakeOK = true;
1099 if (handShake->banner[WAIT_TAG_OFFSET] == WAIT_DEVICE_TAG || !CheckAutoFillTarget(hChannel)) {
1100 WRITE_LOG(LOG_WARN, "No target channelId:%u", hChannel->channelId);
1101 return 0;
1102 }
1103 // channel handshake stBindChannelToSession
1104 if (BindChannelToSession(hChannel, nullptr, 0)) {
1105 hChannel->availTailIndex = 0;
1106 WRITE_LOG(LOG_FATAL, "BindChannelToSession failed channelId:%u sid:%u",
1107 hChannel->channelId, hChannel->targetSessionId);
1108 return ERR_GENERIC;
1109 }
1110 return 0;
1111 }
1112
ReportServerVersion(HChannel hChannel)1113 void HdcServerForClient::ReportServerVersion(HChannel hChannel)
1114 {
1115 string version = Base::GetVersion();
1116 SendChannelWithCmd(hChannel, CMD_CHECK_SERVER,
1117 const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(version.c_str())),
1118 version.size());
1119 }
1120
1121 // 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)1122 int HdcServerForClient::ReadChannel(HChannel hChannel, uint8_t *bufPtr, const int bytesIO)
1123 {
1124 StartTraceScope("HdcServerForClient::ReadChannel");
1125 if (!hChannel->handshakeOK) {
1126 return ChannelHandShake(hChannel, bufPtr, bytesIO);
1127 }
1128 HDaemonInfo hdi = nullptr;
1129 HdcServer *ptrServer = (HdcServer *)clsServer;
1130 ptrServer->AdminDaemonMap(OP_QUERY, hChannel->connectKey, hdi);
1131 if (hdi && !hdi->emgmsg.empty()) {
1132 EchoClient(hChannel, MSG_FAIL, hdi->emgmsg.c_str());
1133 return ERR_GENERIC;
1134 }
1135 uint16_t command = *reinterpret_cast<uint16_t *>(bufPtr);
1136 if (command != 0 && (hChannel->remote > RemoteType::REMOTE_NONE)) {
1137 // server directly passthrough file command to daemon
1138 if (!SendToDaemon(hChannel, command, bufPtr + sizeof(uint16_t), bytesIO - sizeof(uint16_t))) {
1139 WRITE_LOG(LOG_FATAL, "Client ReadChannel : direct send to daemon failed");
1140 }
1141 return 0;
1142 }
1143 struct TranslateCommand::FormatCommand formatCommand = { 0 };
1144 if (!hChannel->interactiveShellMode) {
1145 string retEcho = String2FormatCommand(reinterpret_cast<char *>(bufPtr), bytesIO, &formatCommand);
1146 if (retEcho.length()) {
1147 if (!strncmp(reinterpret_cast<char *>(bufPtr), CMDSTR_SOFTWARE_HELP.c_str(),
1148 CMDSTR_SOFTWARE_HELP.size()) ||
1149 !strcmp(reinterpret_cast<char *>(bufPtr), CMDSTR_SOFTWARE_VERSION.c_str()) ||
1150 !strcmp(reinterpret_cast<char *>(bufPtr), "flash")) {
1151 EchoClient(hChannel, MSG_OK, retEcho.c_str());
1152 } else {
1153 EchoClient(hChannel, MSG_FAIL, retEcho.c_str());
1154 }
1155 }
1156
1157 WRITE_LOG(LOG_INFO, "ReadChannel cid:%u sid:%u key:%s", hChannel->channelId,
1158 hChannel->targetSessionId, Hdc::MaskString(hChannel->connectKey).c_str());
1159 if (Hdc::Base::GetCmdLogSwitch()) {
1160 string logBuf = Base::CmdLogStringFormat(hChannel->targetSessionId, (reinterpret_cast<char *>(bufPtr)));
1161 ptrServer->PrintCmdLogEx(logBuf);
1162 }
1163 if (formatCommand.bJumpDo) {
1164 WRITE_LOG(LOG_FATAL, "ReadChannel bJumpDo true");
1165 return -10; // -10 error formatCommand
1166 }
1167 } else {
1168 formatCommand.parameters = string(reinterpret_cast<char *>(bufPtr), bytesIO);
1169 formatCommand.cmdFlag = CMD_SHELL_DATA;
1170 }
1171 if (!DoCommand(hChannel, &formatCommand, hdi)) {
1172 return -3; // -3: error or want close
1173 }
1174 return bytesIO;
1175 };
1176
1177 // avoid session dead
FindAliveSession(uint32_t sessionId)1178 HSession HdcServerForClient::FindAliveSession(uint32_t sessionId)
1179 {
1180 StartTraceScope("HdcServerForClient::FindAliveSession");
1181 HdcServer *ptrServer = (HdcServer *)clsServer;
1182 HSession hSession = ptrServer->AdminSession(OP_QUERY, sessionId, nullptr);
1183 if (!hSession || hSession->isDead) {
1184 WRITE_LOG(LOG_FATAL, "FindAliveSession hSession nullptr or isDead sessionId:%u", sessionId);
1185 return nullptr;
1186 } else {
1187 return hSession;
1188 }
1189 }
1190
ChannelSendSessionCtrlMsg(vector<uint8_t> & ctrlMsg,uint32_t sessionId)1191 bool HdcServerForClient::ChannelSendSessionCtrlMsg(vector<uint8_t> &ctrlMsg, uint32_t sessionId)
1192 {
1193 HSession hSession = FindAliveSession(sessionId);
1194 if (!hSession) {
1195 WRITE_LOG(LOG_FATAL, "ChannelSendSessionCtrlMsg hSession nullptr sessionId:%u", sessionId);
1196 return false;
1197 }
1198 int rc = Base::SendToPollFd(hSession->ctrlFd[STREAM_MAIN], ctrlMsg.data(), ctrlMsg.size());
1199 if (rc <= 0) {
1200 WRITE_LOG(LOG_FATAL, "send ctrlmsg failed sessionId:%u rc:%d", sessionId, rc);
1201 }
1202 return rc > 0;
1203 }
1204
PrintLastError(HChannel HChannel)1205 void HdcServerForClient::PrintLastError(HChannel HChannel)
1206 {
1207 HdcServer *ptrServer = (HdcServer *)clsServer;
1208 uint32_t errorCode = ptrServer->lastErrorNum;
1209 if (errorCode > 0) {
1210 string errorString = GetErrorString(errorCode);
1211 EchoClient(HChannel, MSG_FAIL, "[E%06x]%s", errorCode, errorString.c_str());
1212 ptrServer->lastErrorNum = 0;
1213 }
1214 }
1215
GetErrorString(uint32_t errorCode)1216 string HdcServerForClient::GetErrorString(uint32_t errorCode)
1217 {
1218 auto map = ErrorStringEnglish.find(errorCode);
1219 if (map != ErrorStringEnglish.end()) {
1220 return map->second;
1221 }
1222 return ErrorStringEnglish.at(0xFFFFFF); // 0xFFFFFF: Unknown error
1223 }
1224
CommandMatchDaemonFeature(uint16_t cmdFlag,const HDaemonInfo & hdi)1225 bool HdcServerForClient::CommandMatchDaemonFeature(uint16_t cmdFlag, const HDaemonInfo &hdi)
1226 {
1227 StartTraceScope("HdcServerForClient::CommandMatchDaemonFeature");
1228 string cmdFlagStr = std::to_string(cmdFlag);
1229 if (FEATURE_CHECK_SET.find(cmdFlag) == FEATURE_CHECK_SET.end()) { // not need check
1230 return true;
1231 }
1232 auto tagMatch = hdi->daemonFeature.find(cmdFlagStr);
1233 if (tagMatch == hdi->daemonFeature.end()) { // unsupport command
1234 return false;
1235 }
1236 return (tagMatch->second == STR_FEATURE_ENABLE);
1237 }
1238 } // namespace Hdc
1239