1cc290419Sopenharmony_ci/* 2cc290419Sopenharmony_ci * Copyright (C) 2021 Huawei Device Co., Ltd. 3cc290419Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4cc290419Sopenharmony_ci * you may not use this file except in compliance with the License. 5cc290419Sopenharmony_ci * You may obtain a copy of the License at 6cc290419Sopenharmony_ci * 7cc290419Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8cc290419Sopenharmony_ci * 9cc290419Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10cc290419Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11cc290419Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12cc290419Sopenharmony_ci * See the License for the specific language governing permissions and 13cc290419Sopenharmony_ci * limitations under the License. 14cc290419Sopenharmony_ci */ 15cc290419Sopenharmony_ci#include "host_tcp.h" 16cc290419Sopenharmony_ci#include "server.h" 17cc290419Sopenharmony_ci 18cc290419Sopenharmony_cinamespace Hdc { 19cc290419Sopenharmony_ciHdcHostTCP::HdcHostTCP(const bool serverOrDaemonIn, void *ptrMainBase) 20cc290419Sopenharmony_ci : HdcTCPBase(serverOrDaemonIn, ptrMainBase) 21cc290419Sopenharmony_ci{ 22cc290419Sopenharmony_ci broadcastFindWorking = false; 23cc290419Sopenharmony_ci} 24cc290419Sopenharmony_ci 25cc290419Sopenharmony_ciHdcHostTCP::~HdcHostTCP() 26cc290419Sopenharmony_ci{ 27cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "~HdcHostTCP"); 28cc290419Sopenharmony_ci} 29cc290419Sopenharmony_ci 30cc290419Sopenharmony_civoid HdcHostTCP::Stop() 31cc290419Sopenharmony_ci{ 32cc290419Sopenharmony_ci} 33cc290419Sopenharmony_ci 34cc290419Sopenharmony_civoid HdcHostTCP::RecvUDPEntry(const sockaddr *addrSrc, uv_udp_t *handle, const uv_buf_t *rcvbuf) 35cc290419Sopenharmony_ci{ 36cc290419Sopenharmony_ci char bufString[BUF_SIZE_TINY]; 37cc290419Sopenharmony_ci int port = 0; 38cc290419Sopenharmony_ci char *p = strstr(rcvbuf->base, "-"); 39cc290419Sopenharmony_ci if (!p) { 40cc290419Sopenharmony_ci return; 41cc290419Sopenharmony_ci } 42cc290419Sopenharmony_ci port = atoi(p + 1); 43cc290419Sopenharmony_ci if (!port) { 44cc290419Sopenharmony_ci return; 45cc290419Sopenharmony_ci } 46cc290419Sopenharmony_ci uv_ip6_name((sockaddr_in6 *)addrSrc, bufString, sizeof(bufString)); 47cc290419Sopenharmony_ci string addrPort = string(bufString); 48cc290419Sopenharmony_ci addrPort += string(":") + std::to_string(port); 49cc290419Sopenharmony_ci lstDaemonResult.push_back(addrPort); 50cc290419Sopenharmony_ci} 51cc290419Sopenharmony_ci 52cc290419Sopenharmony_civoid HdcHostTCP::BroadcastTimer(uv_idle_t *handle) 53cc290419Sopenharmony_ci{ 54cc290419Sopenharmony_ci uv_stop(handle->loop); 55cc290419Sopenharmony_ci} 56cc290419Sopenharmony_ci 57cc290419Sopenharmony_ci// Executive Administration Network Broadcast Discovery, broadcastLanIP==which interface to broadcast 58cc290419Sopenharmony_civoid HdcHostTCP::BroadcastFindDaemon(const char *broadcastLanIP) 59cc290419Sopenharmony_ci{ 60cc290419Sopenharmony_ci if (broadcastFindWorking) { 61cc290419Sopenharmony_ci return; 62cc290419Sopenharmony_ci } 63cc290419Sopenharmony_ci broadcastFindWorking = true; 64cc290419Sopenharmony_ci lstDaemonResult.clear(); 65cc290419Sopenharmony_ci 66cc290419Sopenharmony_ci uv_loop_t loopBroadcast; 67cc290419Sopenharmony_ci uv_loop_init(&loopBroadcast); 68cc290419Sopenharmony_ci struct sockaddr_in6 addr; 69cc290419Sopenharmony_ci uv_udp_send_t req; 70cc290419Sopenharmony_ci uv_udp_t client; 71cc290419Sopenharmony_ci // send 72cc290419Sopenharmony_ci uv_ip6_addr(broadcastLanIP, 0, &addr); 73cc290419Sopenharmony_ci uv_udp_init(&loopBroadcast, &client); 74cc290419Sopenharmony_ci uv_udp_bind(&client, (const struct sockaddr *)&addr, 0); 75cc290419Sopenharmony_ci uv_udp_set_broadcast(&client, 1); 76cc290419Sopenharmony_ci uv_ip6_addr("FFFF:FFFF:FFFF", DEFAULT_PORT, &addr); 77cc290419Sopenharmony_ci uv_buf_t buf = uv_buf_init((char *)HANDSHAKE_MESSAGE.c_str(), HANDSHAKE_MESSAGE.size()); 78cc290419Sopenharmony_ci uv_udp_send(&req, &client, &buf, 1, (const struct sockaddr *)&addr, nullptr); 79cc290419Sopenharmony_ci // recv 80cc290419Sopenharmony_ci uv_udp_t server; 81cc290419Sopenharmony_ci server.data = this; 82cc290419Sopenharmony_ci uv_ip6_addr(broadcastLanIP, DEFAULT_PORT, &addr); 83cc290419Sopenharmony_ci uv_udp_init(&loopBroadcast, &server); 84cc290419Sopenharmony_ci uv_udp_bind(&server, (const struct sockaddr *)&addr, UV_UDP_REUSEADDR); 85cc290419Sopenharmony_ci uv_udp_recv_start(&server, AllocStreamUDP, RecvUDP); 86cc290419Sopenharmony_ci // find timeout 87cc290419Sopenharmony_ci uv_timer_t tLastCheck; 88cc290419Sopenharmony_ci uv_timer_init(&loopBroadcast, &tLastCheck); 89cc290419Sopenharmony_ci uv_timer_start(&tLastCheck, (uv_timer_cb)BroadcastTimer, TIME_BASE, 0); // timeout debug 1s 90cc290419Sopenharmony_ci 91cc290419Sopenharmony_ci uv_run(&loopBroadcast, UV_RUN_DEFAULT); 92cc290419Sopenharmony_ci uv_loop_close(&loopBroadcast); 93cc290419Sopenharmony_ci broadcastFindWorking = false; 94cc290419Sopenharmony_ci} 95cc290419Sopenharmony_ci 96cc290419Sopenharmony_civoid HdcHostTCP::Connect(uv_connect_t *connection, int status) 97cc290419Sopenharmony_ci{ 98cc290419Sopenharmony_ci HSession hSession = (HSession)connection->data; 99cc290419Sopenharmony_ci delete connection; 100cc290419Sopenharmony_ci HdcSessionBase *ptrConnect = (HdcSessionBase *)hSession->classInstance; 101cc290419Sopenharmony_ci auto ctrl = ptrConnect->BuildCtrlString(SP_START_SESSION, 0, nullptr, 0); 102cc290419Sopenharmony_ci if (status < 0) { 103cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "Connect status:%d", status); 104cc290419Sopenharmony_ci goto Finish; 105cc290419Sopenharmony_ci } 106cc290419Sopenharmony_ci if ((hSession->fdChildWorkTCP = Base::DuplicateUvSocket(&hSession->hWorkTCP)) < 0) { 107cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "Connect fdChildWorkTCP:%d", hSession->fdChildWorkTCP); 108cc290419Sopenharmony_ci goto Finish; 109cc290419Sopenharmony_ci } 110cc290419Sopenharmony_ci uv_read_stop((uv_stream_t *)&hSession->hWorkTCP); 111cc290419Sopenharmony_ci Base::SetTcpOptions((uv_tcp_t *)&hSession->hWorkTCP); 112cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "HdcHostTCP::Connect"); 113cc290419Sopenharmony_ci Base::StartWorkThread(&ptrConnect->loopMain, ptrConnect->SessionWorkThread, Base::FinishWorkThread, hSession); 114cc290419Sopenharmony_ci // wait for thread up 115cc290419Sopenharmony_ci while (hSession->childLoop.active_handles == 0) { 116cc290419Sopenharmony_ci uv_sleep(MINOR_TIMEOUT); 117cc290419Sopenharmony_ci } 118cc290419Sopenharmony_ci Base::SendToPollFd(hSession->ctrlFd[STREAM_MAIN], ctrl.data(), ctrl.size()); 119cc290419Sopenharmony_ci return; 120cc290419Sopenharmony_ciFinish: 121cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "Connect failed sessionId:%u", hSession->sessionId); 122cc290419Sopenharmony_ci hSession->childCleared = true; 123cc290419Sopenharmony_ci ptrConnect->FreeSession(hSession->sessionId); 124cc290419Sopenharmony_ci} 125cc290419Sopenharmony_ci 126cc290419Sopenharmony_ciHSession HdcHostTCP::ConnectDaemon(const string &connectKey, bool isCheck) 127cc290419Sopenharmony_ci{ 128cc290419Sopenharmony_ci char ip[BUF_SIZE_TINY] = ""; 129cc290419Sopenharmony_ci uint16_t port = 0; 130cc290419Sopenharmony_ci if (Base::ConnectKey2IPPort(connectKey.c_str(), ip, &port, sizeof(ip)) < 0) { 131cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "ConnectKey2IPPort error connectKey:%s", Hdc::MaskString(connectKey).c_str()); 132cc290419Sopenharmony_ci return nullptr; 133cc290419Sopenharmony_ci } 134cc290419Sopenharmony_ci 135cc290419Sopenharmony_ci HdcSessionBase *ptrConnect = (HdcSessionBase *)clsMainBase; 136cc290419Sopenharmony_ci HSession hSession = ptrConnect->MallocSession(true, CONN_TCP, this); 137cc290419Sopenharmony_ci if (!hSession) { 138cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "hSession nullptr connectKey:%s", Hdc::MaskString(connectKey).c_str()); 139cc290419Sopenharmony_ci return nullptr; 140cc290419Sopenharmony_ci } 141cc290419Sopenharmony_ci hSession->isCheck = isCheck; 142cc290419Sopenharmony_ci hSession->connectKey = connectKey; 143cc290419Sopenharmony_ci struct sockaddr_in dest; 144cc290419Sopenharmony_ci uv_ip4_addr(ip, port, &dest); 145cc290419Sopenharmony_ci uv_connect_t *conn = new(std::nothrow) uv_connect_t(); 146cc290419Sopenharmony_ci if (conn == nullptr) { 147cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "ConnectDaemon new conn failed"); 148cc290419Sopenharmony_ci delete hSession; 149cc290419Sopenharmony_ci hSession = nullptr; 150cc290419Sopenharmony_ci return nullptr; 151cc290419Sopenharmony_ci } 152cc290419Sopenharmony_ci conn->data = hSession; 153cc290419Sopenharmony_ci uv_tcp_connect(conn, (uv_tcp_t *)&hSession->hWorkTCP, (const struct sockaddr *)&dest, Connect); 154cc290419Sopenharmony_ci return hSession; 155cc290419Sopenharmony_ci} 156cc290419Sopenharmony_ci 157cc290419Sopenharmony_civoid HdcHostTCP::FindLanDaemon() 158cc290419Sopenharmony_ci{ 159cc290419Sopenharmony_ci uv_interface_address_t *info; 160cc290419Sopenharmony_ci int count; 161cc290419Sopenharmony_ci int i; 162cc290419Sopenharmony_ci char ipAddr[BUF_SIZE_TINY] = ""; 163cc290419Sopenharmony_ci if (broadcastFindWorking) { 164cc290419Sopenharmony_ci return; 165cc290419Sopenharmony_ci } 166cc290419Sopenharmony_ci lstDaemonResult.clear(); 167cc290419Sopenharmony_ci uv_interface_addresses(&info, &count); 168cc290419Sopenharmony_ci i = count; 169cc290419Sopenharmony_ci while (--i) { 170cc290419Sopenharmony_ci uv_interface_address_t interface = info[i]; 171cc290419Sopenharmony_ci if (interface.address.address6.sin6_family == AF_INET6) { 172cc290419Sopenharmony_ci continue; 173cc290419Sopenharmony_ci } 174cc290419Sopenharmony_ci uv_ip6_name(&interface.address.address6, ipAddr, sizeof(ipAddr)); 175cc290419Sopenharmony_ci BroadcastFindDaemon(ipAddr); 176cc290419Sopenharmony_ci } 177cc290419Sopenharmony_ci uv_free_interface_addresses(info, count); 178cc290419Sopenharmony_ci} 179cc290419Sopenharmony_ci} // namespace Hdc 180