• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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