xref: /developtools/hdc/src/common/tcp.cpp (revision cc290419)
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 "tcp.h"
16cc290419Sopenharmony_ci
17cc290419Sopenharmony_cinamespace Hdc {
18cc290419Sopenharmony_ciHdcTCPBase::HdcTCPBase(const bool serverOrDaemonIn, void *ptrMainBase)
19cc290419Sopenharmony_ci{
20cc290419Sopenharmony_ci    // Calling the initialization
21cc290419Sopenharmony_ci    InitialChildClass(serverOrDaemonIn, ptrMainBase);
22cc290419Sopenharmony_ci}
23cc290419Sopenharmony_ci
24cc290419Sopenharmony_ciHdcTCPBase::~HdcTCPBase()
25cc290419Sopenharmony_ci{
26cc290419Sopenharmony_ci}
27cc290419Sopenharmony_ci
28cc290419Sopenharmony_ci// Subclasses must be explicitly called
29cc290419Sopenharmony_civoid HdcTCPBase::InitialChildClass(const bool serverOrDaemonIn, void *ptrMainBase)
30cc290419Sopenharmony_ci{
31cc290419Sopenharmony_ci    serverOrDaemon = serverOrDaemonIn;
32cc290419Sopenharmony_ci    clsMainBase = ptrMainBase;
33cc290419Sopenharmony_ci}
34cc290419Sopenharmony_ci
35cc290419Sopenharmony_civoid HdcTCPBase::RecvUDP(uv_udp_t *handle, ssize_t nread, const uv_buf_t *rcvbuf, const struct sockaddr *addr,
36cc290419Sopenharmony_ci                         unsigned flags)
37cc290419Sopenharmony_ci{
38cc290419Sopenharmony_ci    while (true) {
39cc290419Sopenharmony_ci        HdcTCPBase *thisClass = (HdcTCPBase *)handle->data;
40cc290419Sopenharmony_ci        if (nread <= 0) {
41cc290419Sopenharmony_ci            // ==0 finish;<0 error
42cc290419Sopenharmony_ci            break;
43cc290419Sopenharmony_ci        }
44cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "RecvUDP %s", rcvbuf->base);
45cc290419Sopenharmony_ci        if (strncmp(rcvbuf->base, HANDSHAKE_MESSAGE.c_str(), HANDSHAKE_MESSAGE.size())) {
46cc290419Sopenharmony_ci            break;
47cc290419Sopenharmony_ci        }
48cc290419Sopenharmony_ci        thisClass->RecvUDPEntry(addr, handle, rcvbuf);
49cc290419Sopenharmony_ci        break;
50cc290419Sopenharmony_ci    }
51cc290419Sopenharmony_ci    delete[] rcvbuf->base;
52cc290419Sopenharmony_ci}
53cc290419Sopenharmony_ci
54cc290419Sopenharmony_civoid HdcTCPBase::AllocStreamUDP(uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf)
55cc290419Sopenharmony_ci{
56cc290419Sopenharmony_ci    int bufLen = BUF_SIZE_DEFAULT;
57cc290419Sopenharmony_ci    char *pRecvBuf = reinterpret_cast<char *>(new uint8_t[bufLen]());
58cc290419Sopenharmony_ci    if (!pRecvBuf) {
59cc290419Sopenharmony_ci        return;
60cc290419Sopenharmony_ci    }
61cc290419Sopenharmony_ci    buf->base = pRecvBuf;
62cc290419Sopenharmony_ci    buf->len = bufLen;
63cc290419Sopenharmony_ci}
64cc290419Sopenharmony_ci
65cc290419Sopenharmony_civoid HdcTCPBase::SendUDPFinish(uv_udp_send_t *req, int status)
66cc290419Sopenharmony_ci{
67cc290419Sopenharmony_ci    delete req;
68cc290419Sopenharmony_ci}
69cc290419Sopenharmony_ci
70cc290419Sopenharmony_civoid HdcTCPBase::ReadStream(uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf)
71cc290419Sopenharmony_ci{
72cc290419Sopenharmony_ci    HSession hSession = (HSession)tcp->data;
73cc290419Sopenharmony_ci    HdcTCPBase *thisClass = (HdcTCPBase *)hSession->classModule;
74cc290419Sopenharmony_ci    HdcSessionBase *hSessionBase = (HdcSessionBase *)thisClass->clsMainBase;
75cc290419Sopenharmony_ci    bool ret = false;
76cc290419Sopenharmony_ci    while (true) {
77cc290419Sopenharmony_ci        if (nread == UV_ENOBUFS) {
78cc290419Sopenharmony_ci            WRITE_LOG(LOG_DEBUG, "Session IOBuf max");
79cc290419Sopenharmony_ci            break;
80cc290419Sopenharmony_ci        } else if (nread < 0) {
81cc290419Sopenharmony_ci            // I originally in the IO main thread, no need to send asynchronous messages, close the socket as soon as
82cc290419Sopenharmony_ci            // possible
83cc290419Sopenharmony_ci            constexpr int bufSize = 1024;
84cc290419Sopenharmony_ci            char buffer[bufSize] = { 0 };
85cc290419Sopenharmony_ci            uv_strerror_r(static_cast<int>(nread), buffer, bufSize);
86cc290419Sopenharmony_ci            WRITE_LOG(LOG_DEBUG, "HdcTCPBase::ReadStream < 0 %s", buffer);
87cc290419Sopenharmony_ci            break;
88cc290419Sopenharmony_ci        }
89cc290419Sopenharmony_ci        if (hSessionBase->FetchIOBuf(hSession, hSession->ioBuf, nread) < 0) {
90cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "ReadStream FetchIOBuf error nread:%zd", nread);
91cc290419Sopenharmony_ci            break;
92cc290419Sopenharmony_ci        }
93cc290419Sopenharmony_ci        ret = true;
94cc290419Sopenharmony_ci        break;
95cc290419Sopenharmony_ci    }
96cc290419Sopenharmony_ci    if (!ret) {
97cc290419Sopenharmony_ci        // The first time is closed first, prevent the write function from continuing to write
98cc290419Sopenharmony_ci        Base::TryCloseHandle(reinterpret_cast<uv_handle_t *>(tcp));
99cc290419Sopenharmony_ci        hSessionBase->FreeSession(hSession->sessionId);
100cc290419Sopenharmony_ci    }
101cc290419Sopenharmony_ci}
102cc290419Sopenharmony_ci
103cc290419Sopenharmony_ciint HdcTCPBase::WriteUvTcpFd(uv_tcp_t *tcp, uint8_t *buf, int size)
104cc290419Sopenharmony_ci{
105cc290419Sopenharmony_ci    std::lock_guard<std::mutex> lock(writeTCPMutex);
106cc290419Sopenharmony_ci    uint8_t *data = buf;
107cc290419Sopenharmony_ci    int cnt = size;
108cc290419Sopenharmony_ci    uv_os_fd_t uvfd;
109cc290419Sopenharmony_ci    uv_fileno(reinterpret_cast<uv_handle_t*>(tcp), &uvfd);
110cc290419Sopenharmony_ci#ifdef _WIN32
111cc290419Sopenharmony_ci    int fd = (uv_os_sock_t)uvfd;
112cc290419Sopenharmony_ci#else
113cc290419Sopenharmony_ci    int fd = reinterpret_cast<int>(uvfd);
114cc290419Sopenharmony_ci#endif
115cc290419Sopenharmony_ci    constexpr int intrmax = 60000;
116cc290419Sopenharmony_ci    int intrcnt = 0;
117cc290419Sopenharmony_ci    while (cnt > 0) {
118cc290419Sopenharmony_ci#ifdef HDC_EMULATOR
119cc290419Sopenharmony_ci        int rc = write(fd, reinterpret_cast<const char*>(data), cnt);
120cc290419Sopenharmony_ci#else
121cc290419Sopenharmony_ci        int rc = send(fd, reinterpret_cast<const char*>(data), cnt, 0);
122cc290419Sopenharmony_ci#endif
123cc290419Sopenharmony_ci        if (rc < 0) {
124cc290419Sopenharmony_ci#ifdef _WIN32
125cc290419Sopenharmony_ci            int err = WSAGetLastError();
126cc290419Sopenharmony_ci            if (err == WSAEINTR || err == WSAEWOULDBLOCK) {
127cc290419Sopenharmony_ci#else
128cc290419Sopenharmony_ci            int err = errno;
129cc290419Sopenharmony_ci            if (err == EINTR || err == EAGAIN) {
130cc290419Sopenharmony_ci#endif
131cc290419Sopenharmony_ci                if (++intrcnt > intrmax) {
132cc290419Sopenharmony_ci                    WRITE_LOG(LOG_WARN, "WriteUvTcpFd fd:%d send interrupt err:%d", fd, err);
133cc290419Sopenharmony_ci                    intrcnt = 0;
134cc290419Sopenharmony_ci                }
135cc290419Sopenharmony_ci                std::this_thread::yield();
136cc290419Sopenharmony_ci                continue;
137cc290419Sopenharmony_ci            } else {
138cc290419Sopenharmony_ci                WRITE_LOG(LOG_FATAL, "WriteUvTcpFd fd:%d send rc:%d err:%d", fd, rc, err);
139cc290419Sopenharmony_ci                cnt = ERR_GENERIC;
140cc290419Sopenharmony_ci                break;
141cc290419Sopenharmony_ci            }
142cc290419Sopenharmony_ci        }
143cc290419Sopenharmony_ci        data += rc;
144cc290419Sopenharmony_ci        cnt -= rc;
145cc290419Sopenharmony_ci    }
146cc290419Sopenharmony_ci    delete[] buf;
147cc290419Sopenharmony_ci    return cnt == 0 ? size : cnt;
148cc290419Sopenharmony_ci}
149cc290419Sopenharmony_ci}  // namespace Hdc
150