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 18namespace Hdc { 19HdcHostTCP::HdcHostTCP(const bool serverOrDaemonIn, void *ptrMainBase) 20 : HdcTCPBase(serverOrDaemonIn, ptrMainBase) 21{ 22 broadcastFindWorking = false; 23} 24 25HdcHostTCP::~HdcHostTCP() 26{ 27 WRITE_LOG(LOG_DEBUG, "~HdcHostTCP"); 28} 29 30void HdcHostTCP::Stop() 31{ 32} 33 34void 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 52void 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 58void 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 96void 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; 120Finish: 121 WRITE_LOG(LOG_FATAL, "Connect failed sessionId:%u", hSession->sessionId); 122 hSession->childCleared = true; 123 ptrConnect->FreeSession(hSession->sessionId); 124} 125 126HSession HdcHostTCP::ConnectDaemon(const string &connectKey, bool isCheck) 127{ 128 char ip[BUF_SIZE_TINY] = ""; 129 uint16_t port = 0; 130 if (Base::ConnectKey2IPPort(connectKey.c_str(), ip, &port, sizeof(ip)) < 0) { 131 WRITE_LOG(LOG_FATAL, "ConnectKey2IPPort error connectKey:%s", Hdc::MaskString(connectKey).c_str()); 132 return nullptr; 133 } 134 135 HdcSessionBase *ptrConnect = (HdcSessionBase *)clsMainBase; 136 HSession hSession = ptrConnect->MallocSession(true, CONN_TCP, this); 137 if (!hSession) { 138 WRITE_LOG(LOG_FATAL, "hSession nullptr connectKey:%s", Hdc::MaskString(connectKey).c_str()); 139 return nullptr; 140 } 141 hSession->isCheck = isCheck; 142 hSession->connectKey = connectKey; 143 struct sockaddr_in dest; 144 uv_ip4_addr(ip, port, &dest); 145 uv_connect_t *conn = new(std::nothrow) uv_connect_t(); 146 if (conn == nullptr) { 147 WRITE_LOG(LOG_FATAL, "ConnectDaemon new conn failed"); 148 delete hSession; 149 hSession = nullptr; 150 return nullptr; 151 } 152 conn->data = hSession; 153 uv_tcp_connect(conn, (uv_tcp_t *)&hSession->hWorkTCP, (const struct sockaddr *)&dest, Connect); 154 return hSession; 155} 156 157void HdcHostTCP::FindLanDaemon() 158{ 159 uv_interface_address_t *info; 160 int count; 161 int i; 162 char ipAddr[BUF_SIZE_TINY] = ""; 163 if (broadcastFindWorking) { 164 return; 165 } 166 lstDaemonResult.clear(); 167 uv_interface_addresses(&info, &count); 168 i = count; 169 while (--i) { 170 uv_interface_address_t interface = info[i]; 171 if (interface.address.address6.sin6_family == AF_INET6) { 172 continue; 173 } 174 uv_ip6_name(&interface.address.address6, ipAddr, sizeof(ipAddr)); 175 BroadcastFindDaemon(ipAddr); 176 } 177 uv_free_interface_addresses(info, count); 178} 179} // namespace Hdc 180