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