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