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