• 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 "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     LoopStatus loopBroadcastStatus(&loopBroadcast, "loopBroadcast");
68     uv_loop_init(&loopBroadcast);
69     loopBroadcastStatus.StartReportTimer();
70     struct sockaddr_in6 addr;
71     uv_udp_send_t req;
72     uv_udp_t client;
73     // send
74     uv_ip6_addr(broadcastLanIP, 0, &addr);
75     uv_udp_init(&loopBroadcast, &client);
76     uv_udp_bind(&client, (const struct sockaddr *)&addr, 0);
77     uv_udp_set_broadcast(&client, 1);
78     uv_ip6_addr("FFFF:FFFF:FFFF", DEFAULT_PORT, &addr);
79     uv_buf_t buf = uv_buf_init((char *)HANDSHAKE_MESSAGE.c_str(), HANDSHAKE_MESSAGE.size());
80     uv_udp_send(&req, &client, &buf, 1, (const struct sockaddr *)&addr, nullptr);
81     // recv
82     uv_udp_t server;
83     server.data = this;
84     uv_ip6_addr(broadcastLanIP, DEFAULT_PORT, &addr);
85     uv_udp_init(&loopBroadcast, &server);
86     uv_udp_bind(&server, (const struct sockaddr *)&addr, UV_UDP_REUSEADDR);
87     uv_udp_recv_start(&server, AllocStreamUDP, RecvUDP);
88     // find timeout
89     uv_timer_t tLastCheck;
90     uv_timer_init(&loopBroadcast, &tLastCheck);
91     uv_timer_start(&tLastCheck, (uv_timer_cb)BroadcastTimer, TIME_BASE, 0);  // timeout debug 1s
92 
93     uv_run(&loopBroadcast, UV_RUN_DEFAULT);
94     uv_loop_close(&loopBroadcast);
95     broadcastFindWorking = false;
96 }
97 
Connect(uv_connect_t * connection,int status)98 void HdcHostTCP::Connect(uv_connect_t *connection, int status)
99 {
100     HSession hSession = (HSession)connection->data;
101     delete connection;
102     HdcSessionBase *ptrConnect = (HdcSessionBase *)hSession->classInstance;
103     auto ctrl = ptrConnect->BuildCtrlString(SP_START_SESSION, 0, nullptr, 0);
104     if (status < 0) {
105         WRITE_LOG(LOG_FATAL, "Connect status:%d", status);
106         hSession->isRunningOk = false;
107         char buffer[BUF_SIZE_DEFAULT] = { 0 };
108         uv_strerror_r(status, buffer, BUF_SIZE_DEFAULT);
109         hSession->faultInfo += buffer;
110         goto Finish;
111     }
112     if ((hSession->fdChildWorkTCP = Base::DuplicateUvSocket(&hSession->hWorkTCP)) < 0) {
113         WRITE_LOG(LOG_FATAL, "Connect fdChildWorkTCP:%d", hSession->fdChildWorkTCP);
114         goto Finish;
115     }
116     uv_read_stop((uv_stream_t *)&hSession->hWorkTCP);
117     Base::SetTcpOptions((uv_tcp_t *)&hSession->hWorkTCP);
118     WRITE_LOG(LOG_INFO, "HdcHostTCP::Connect start session work thread, sid:%u", hSession->sessionId);
119     Base::StartWorkThread(&ptrConnect->loopMain, ptrConnect->SessionWorkThread, Base::FinishWorkThread, hSession);
120     // wait for thread up
121     while (hSession->childLoop.active_handles == 0) {
122         uv_sleep(MINOR_TIMEOUT);
123     }
124     Base::SendToPollFd(hSession->ctrlFd[STREAM_MAIN], ctrl.data(), ctrl.size());
125     return;
126 Finish:
127     WRITE_LOG(LOG_FATAL, "Connect failed sessionId:%u", hSession->sessionId);
128     hSession->childCleared = true;
129     ptrConnect->FreeSession(hSession->sessionId);
130 }
131 
ConnectDaemon(const string & connectKey,bool isCheck)132 HSession HdcHostTCP::ConnectDaemon(const string &connectKey, bool isCheck)
133 {
134     char ip[BUF_SIZE_TINY] = "";
135     uint16_t port = 0;
136     if (Base::ConnectKey2IPPort(connectKey.c_str(), ip, &port, sizeof(ip)) < 0) {
137         WRITE_LOG(LOG_FATAL, "ConnectKey2IPPort error connectKey:%s", Hdc::MaskString(connectKey).c_str());
138         return nullptr;
139     }
140 
141     HdcSessionBase *ptrConnect = (HdcSessionBase *)clsMainBase;
142     HSession hSession = ptrConnect->MallocSession(true, CONN_TCP, this);
143     if (!hSession) {
144         WRITE_LOG(LOG_FATAL, "hSession nullptr connectKey:%s", Hdc::MaskString(connectKey).c_str());
145         return nullptr;
146     }
147     hSession->isCheck = isCheck;
148     hSession->connectKey = connectKey;
149     ptrConnect->PrintAllSessionConnection(hSession->sessionId);
150     struct sockaddr_in dest;
151     uv_ip4_addr(ip, port, &dest);
152     uv_connect_t *conn = new(std::nothrow) uv_connect_t();
153     if (conn == nullptr) {
154         WRITE_LOG(LOG_FATAL, "ConnectDaemon new conn failed");
155         delete hSession;
156         hSession = nullptr;
157         return nullptr;
158     }
159     conn->data = hSession;
160     WRITE_LOG(LOG_INFO, "start tcp connect, connectKey:%s sid:%u", Hdc::MaskString(connectKey).c_str(),
161         hSession->sessionId);
162     uv_tcp_connect(conn, (uv_tcp_t *)&hSession->hWorkTCP, (const struct sockaddr *)&dest, Connect);
163     return hSession;
164 }
165 
FindLanDaemon()166 void HdcHostTCP::FindLanDaemon()
167 {
168     uv_interface_address_t *info;
169     int count;
170     int i;
171     int ret;
172     char ipAddr[BUF_SIZE_TINY] = "";
173     if (broadcastFindWorking) {
174         return;
175     }
176     lstDaemonResult.clear();
177     ret = uv_interface_addresses(&info, &count);
178     if (ret != 0 || count <= 0) {
179         WRITE_LOG(LOG_FATAL, "uv_interface_addresses failed %d, count is %d", ret, count);
180         return;
181     }
182     i = count;
183     while (--i) {
184         uv_interface_address_t interface = info[i];
185         if (interface.address.address6.sin6_family == AF_INET6) {
186             continue;
187         }
188         uv_ip6_name(&interface.address.address6, ipAddr, sizeof(ipAddr));
189         BroadcastFindDaemon(ipAddr);
190     }
191     uv_free_interface_addresses(info, count);
192 }
193 }  // namespace Hdc
194