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 #ifdef HDC_EMULATOR
119 int rc = write(fd, reinterpret_cast<const char*>(data), cnt);
120 #else
121 int rc = send(fd, reinterpret_cast<const char*>(data), cnt, 0);
122 #endif
123 if (rc < 0) {
124 #ifdef _WIN32
125 int err = WSAGetLastError();
126 if (err == WSAEINTR || err == WSAEWOULDBLOCK) {
127 #else
128 int err = errno;
129 if (err == EINTR || err == EAGAIN) {
130 #endif
131 if (++intrcnt > intrmax) {
132 WRITE_LOG(LOG_WARN, "WriteUvTcpFd fd:%d send interrupt err:%d", fd, err);
133 intrcnt = 0;
134 }
135 continue;
136 } else {
137 WRITE_LOG(LOG_FATAL, "WriteUvTcpFd fd:%d send rc:%d err:%d", fd, rc, err);
138 cnt = ERR_GENERIC;
139 break;
140 }
141 }
142 data += rc;
143 cnt -= rc;
144 }
145 delete[] buf;
146 return cnt == 0 ? size : cnt;
147 }
148 } // namespace Hdc
149