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 "host_tcp.h"
16 #include "server.h"
17
18 namespace Hdc {
HdcHostTCP(const bool serverOrDaemonIn,void * ptrMainBase)19 HdcHostTCP::HdcHostTCP(const bool serverOrDaemonIn, void *ptrMainBase)
20 : HdcTCPBase(serverOrDaemonIn, ptrMainBase)
21 {
22 broadcastFindWorking = false;
23 }
24
~HdcHostTCP()25 HdcHostTCP::~HdcHostTCP()
26 {
27 WRITE_LOG(LOG_DEBUG, "~HdcHostTCP");
28 }
29
Stop()30 void HdcHostTCP::Stop()
31 {
32 }
33
RecvUDPEntry(const sockaddr * addrSrc,uv_udp_t * handle,const uv_buf_t * rcvbuf)34 void HdcHostTCP::RecvUDPEntry(const sockaddr *addrSrc, uv_udp_t *handle, const uv_buf_t *rcvbuf)
35 {
36 char bufString[BUF_SIZE_TINY];
37 int port = 0;
38 char *p = strstr(rcvbuf->base, "-");
39 if (!p) {
40 return;
41 }
42 port = atoi(p + 1);
43 if (!port) {
44 return;
45 }
46 uv_ip6_name((sockaddr_in6 *)addrSrc, bufString, sizeof(bufString));
47 string addrPort = string(bufString);
48 addrPort += string(":") + std::to_string(port);
49 lstDaemonResult.push_back(addrPort);
50 }
51
BroadcastTimer(uv_idle_t * handle)52 void HdcHostTCP::BroadcastTimer(uv_idle_t *handle)
53 {
54 uv_stop(handle->loop);
55 }
56
57 // Executive Administration Network Broadcast Discovery, broadcastLanIP==which interface to broadcast
BroadcastFindDaemon(const char * broadcastLanIP)58 void HdcHostTCP::BroadcastFindDaemon(const char *broadcastLanIP)
59 {
60 if (broadcastFindWorking) {
61 return;
62 }
63 broadcastFindWorking = true;
64 lstDaemonResult.clear();
65
66 uv_loop_t loopBroadcast;
67 uv_loop_init(&loopBroadcast);
68 struct sockaddr_in6 addr;
69 uv_udp_send_t req;
70 uv_udp_t client;
71 // send
72 uv_ip6_addr(broadcastLanIP, 0, &addr);
73 uv_udp_init(&loopBroadcast, &client);
74 uv_udp_bind(&client, (const struct sockaddr *)&addr, 0);
75 uv_udp_set_broadcast(&client, 1);
76 uv_ip6_addr("FFFF:FFFF:FFFF", DEFAULT_PORT, &addr);
77 uv_buf_t buf = uv_buf_init((char *)HANDSHAKE_MESSAGE.c_str(), HANDSHAKE_MESSAGE.size());
78 uv_udp_send(&req, &client, &buf, 1, (const struct sockaddr *)&addr, nullptr);
79 // recv
80 uv_udp_t server;
81 server.data = this;
82 uv_ip6_addr(broadcastLanIP, DEFAULT_PORT, &addr);
83 uv_udp_init(&loopBroadcast, &server);
84 uv_udp_bind(&server, (const struct sockaddr *)&addr, UV_UDP_REUSEADDR);
85 uv_udp_recv_start(&server, AllocStreamUDP, RecvUDP);
86 // find timeout
87 uv_timer_t tLastCheck;
88 uv_timer_init(&loopBroadcast, &tLastCheck);
89 uv_timer_start(&tLastCheck, (uv_timer_cb)BroadcastTimer, TIME_BASE, 0); // timeout debug 1s
90
91 uv_run(&loopBroadcast, UV_RUN_DEFAULT);
92 uv_loop_close(&loopBroadcast);
93 broadcastFindWorking = false;
94 }
95
Connect(uv_connect_t * connection,int status)96 void HdcHostTCP::Connect(uv_connect_t *connection, int status)
97 {
98 HSession hSession = (HSession)connection->data;
99 delete connection;
100 HdcSessionBase *ptrConnect = (HdcSessionBase *)hSession->classInstance;
101 auto ctrl = ptrConnect->BuildCtrlString(SP_START_SESSION, 0, nullptr, 0);
102 if (status < 0) {
103 WRITE_LOG(LOG_FATAL, "Connect status:%d", status);
104 goto Finish;
105 }
106 if ((hSession->fdChildWorkTCP = Base::DuplicateUvSocket(&hSession->hWorkTCP)) < 0) {
107 WRITE_LOG(LOG_FATAL, "Connect fdChildWorkTCP:%d", hSession->fdChildWorkTCP);
108 goto Finish;
109 }
110 uv_read_stop((uv_stream_t *)&hSession->hWorkTCP);
111 Base::SetTcpOptions((uv_tcp_t *)&hSession->hWorkTCP);
112 WRITE_LOG(LOG_DEBUG, "HdcHostTCP::Connect");
113 Base::StartWorkThread(&ptrConnect->loopMain, ptrConnect->SessionWorkThread, Base::FinishWorkThread, hSession);
114 // wait for thread up
115 while (hSession->childLoop.active_handles == 0) {
116 uv_sleep(MINOR_TIMEOUT);
117 }
118 Base::SendToPollFd(hSession->ctrlFd[STREAM_MAIN], ctrl.data(), ctrl.size());
119 return;
120 Finish:
121 WRITE_LOG(LOG_FATAL, "Connect failed sessionId:%u", hSession->sessionId);
122 ptrConnect->FreeSession(hSession->sessionId);
123 }
124
ConnectDaemon(const string & connectKey,bool isCheck)125 HSession HdcHostTCP::ConnectDaemon(const string &connectKey, bool isCheck)
126 {
127 char ip[BUF_SIZE_TINY] = "";
128 uint16_t port = 0;
129 if (Base::ConnectKey2IPPort(connectKey.c_str(), ip, &port) < 0) {
130 WRITE_LOG(LOG_FATAL, "ConnectKey2IPPort error connectKey:%s", connectKey.c_str());
131 return nullptr;
132 }
133
134 HdcSessionBase *ptrConnect = (HdcSessionBase *)clsMainBase;
135 HSession hSession = ptrConnect->MallocSession(true, CONN_TCP, this);
136 if (!hSession) {
137 WRITE_LOG(LOG_FATAL, "hSession nullptr connectKey:%s", connectKey.c_str());
138 return nullptr;
139 }
140 hSession->isCheck = isCheck;
141 hSession->connectKey = connectKey;
142 struct sockaddr_in dest;
143 uv_ip4_addr(ip, port, &dest);
144 uv_connect_t *conn = new(std::nothrow) uv_connect_t();
145 if (conn == nullptr) {
146 WRITE_LOG(LOG_FATAL, "ConnectDaemon new conn failed");
147 delete hSession;
148 hSession = nullptr;
149 return nullptr;
150 }
151 conn->data = hSession;
152 uv_tcp_connect(conn, (uv_tcp_t *)&hSession->hWorkTCP, (const struct sockaddr *)&dest, Connect);
153 return hSession;
154 }
155
FindLanDaemon()156 void HdcHostTCP::FindLanDaemon()
157 {
158 uv_interface_address_t *info;
159 int count;
160 int i;
161 char ipAddr[BUF_SIZE_TINY] = "";
162 if (broadcastFindWorking) {
163 return;
164 }
165 lstDaemonResult.clear();
166 uv_interface_addresses(&info, &count);
167 i = count;
168 while (--i) {
169 uv_interface_address_t interface = info[i];
170 if (interface.address.address6.sin6_family == AF_INET6) {
171 continue;
172 }
173 uv_ip6_name(&interface.address.address6, ipAddr, sizeof(ipAddr));
174 BroadcastFindDaemon(ipAddr);
175 }
176 uv_free_interface_addresses(info, count);
177 }
178 } // namespace Hdc
179