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 "daemon_tcp.h"
16
17 namespace Hdc {
HdcDaemonTCP(const bool serverOrDaemonIn,void * ptrMainBase)18 HdcDaemonTCP::HdcDaemonTCP(const bool serverOrDaemonIn, void *ptrMainBase)
19 : HdcTCPBase(serverOrDaemonIn, ptrMainBase)
20 {
21 // If the listening value for the property setting is obtained, it will be 0 randomly assigned.
22 string strTCPPort;
23 SystemDepend::GetDevItem("persist.hdc.port", strTCPPort);
24 tcpListenPort = atoi(strTCPPort.c_str());
25 if (tcpListenPort <= 0) {
26 tcpListenPort = 0;
27 }
28 #ifdef HDC_DEBUG
29 const uint16_t DEBUG_TCP_PORT = 10178;
30 tcpListenPort = DEBUG_TCP_PORT;
31 #endif
32 }
33
~HdcDaemonTCP()34 HdcDaemonTCP::~HdcDaemonTCP()
35 {
36 }
37
Stop()38 void HdcDaemonTCP::Stop()
39 {
40 Base::TryCloseHandle((const uv_handle_t *)&servUDP);
41 Base::TryCloseHandle((const uv_handle_t *)&servTCP);
42 WRITE_LOG(LOG_DEBUG, "~HdcDaemonTCP");
43 }
44
TransmitConfig(const sockaddr * addrSrc,uv_udp_t * handle)45 void HdcDaemonTCP::TransmitConfig(const sockaddr *addrSrc, uv_udp_t *handle)
46 {
47 char srcIP[BUF_SIZE_TINY] = "";
48 struct sockaddr addrSrcIPPort;
49 uv_udp_send_t *req = new uv_udp_send_t();
50 if (!req) {
51 return;
52 }
53 string sendBuf = Base::StringFormat("%s-%d", HANDSHAKE_MESSAGE.c_str(), tcpListenPort);
54 uv_buf_t sndbuf = uv_buf_init((char *)sendBuf.c_str(), sendBuf.size());
55 uv_ip4_name((sockaddr_in *)addrSrc, srcIP, sizeof(srcIP));
56 uv_ip4_addr(srcIP, DEFAULT_PORT, (sockaddr_in *)&addrSrcIPPort);
57 uv_udp_send(req, handle, &sndbuf, 1, &addrSrcIPPort, SendUDPFinish);
58 }
59
AcceptClient(uv_stream_t * server,int status)60 void HdcDaemonTCP::AcceptClient(uv_stream_t *server, int status)
61 {
62 uv_loop_t *ptrLoop = server->loop;
63 uv_tcp_t *pServTCP = (uv_tcp_t *)server;
64 HdcDaemonTCP *thisClass = (HdcDaemonTCP *)pServTCP->data;
65 HdcSessionBase *ptrConnect = (HdcSessionBase *)thisClass->clsMainBase;
66 HdcSessionBase *daemon = reinterpret_cast<HdcSessionBase *>(thisClass->clsMainBase);
67 const uint16_t maxWaitTime = UV_DEFAULT_INTERVAL;
68 auto ctrl = daemon->BuildCtrlString(SP_START_SESSION, 0, nullptr, 0);
69 HSession hSession = ptrConnect->MallocSession(false, CONN_TCP, thisClass);
70 if (!hSession) {
71 return;
72 }
73 if (uv_accept(server, (uv_stream_t *)&hSession->hWorkTCP) < 0) {
74 goto Finish;
75 }
76 if ((hSession->fdChildWorkTCP = Base::DuplicateUvSocket(&hSession->hWorkTCP)) < 0) {
77 goto Finish;
78 };
79 Base::TryCloseHandle((uv_handle_t *)&hSession->hWorkTCP);
80 Base::StartWorkThread(ptrLoop, ptrConnect->SessionWorkThread, Base::FinishWorkThread, hSession);
81 // wait for thread up
82 while (hSession->childLoop.active_handles == 0) {
83 usleep(maxWaitTime);
84 }
85 Base::SendToStream((uv_stream_t *)&hSession->ctrlPipe[STREAM_MAIN], ctrl.data(), ctrl.size());
86 return;
87 Finish:
88 ptrConnect->FreeSession(hSession->sessionId);
89 }
90
RecvUDPEntry(const sockaddr * addrSrc,uv_udp_t * handle,const uv_buf_t * rcvbuf)91 void HdcDaemonTCP::RecvUDPEntry(const sockaddr *addrSrc, uv_udp_t *handle, const uv_buf_t *rcvbuf)
92 {
93 TransmitConfig(addrSrc, handle);
94 }
95
SetUDPListen()96 void HdcDaemonTCP::SetUDPListen()
97 {
98 struct sockaddr_in addr;
99 HdcSessionBase *ptrConnect = (HdcSessionBase *)clsMainBase;
100 // udp broadcast
101 servUDP.data = this;
102 uv_udp_init(&ptrConnect->loopMain, &servUDP);
103 uv_ip4_addr("0.0.0.0", DEFAULT_PORT, &addr);
104 uv_udp_bind(&servUDP, (const struct sockaddr *)&addr, UV_UDP_REUSEADDR);
105 uv_udp_recv_start(&servUDP, AllocStreamUDP, RecvUDP);
106 }
107
108 // Set the daemon-side TCP listening
SetTCPListen()109 int HdcDaemonTCP::SetTCPListen()
110 {
111 // tcp listen
112 HdcSessionBase *ptrConnect = (HdcSessionBase *)clsMainBase;
113 servTCP.data = this;
114 struct sockaddr_in addr = {};
115 int namelen;
116 const int DEFAULT_BACKLOG = 128;
117
118 uv_tcp_init(&ptrConnect->loopMain, &servTCP);
119 uv_ip4_addr("0.0.0.0", tcpListenPort, &addr); // tcpListenPort == 0
120 uv_tcp_bind(&servTCP, (const struct sockaddr *)&addr, 0);
121 if (uv_listen((uv_stream_t *)&servTCP, DEFAULT_BACKLOG, (uv_connection_cb)AcceptClient)) {
122 return ERR_API_FAIL;
123 }
124 // Get listen port
125 Base::ZeroStruct(addr);
126 namelen = sizeof(addr);
127 if (uv_tcp_getsockname(&servTCP, (sockaddr *)&addr, &namelen)) {
128 return ERR_API_FAIL;
129 }
130 tcpListenPort = ntohs(addr.sin_port);
131 return RET_SUCCESS;
132 }
133
Initial()134 int HdcDaemonTCP::Initial()
135 {
136 WRITE_LOG(LOG_DEBUG, "HdcDaemonTCP init");
137 SetUDPListen();
138 if (SetTCPListen() != RET_SUCCESS) {
139 WRITE_LOG(LOG_FATAL, "TCP listen failed");
140 return ERR_GENERIC;
141 }
142 #ifndef UNIT_TEST
143 WRITE_LOG(LOG_INFO, "TCP listen on port:[%d]", tcpListenPort);
144 #endif
145 return RET_SUCCESS;
146 }
147 } // namespace Hdc
148