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