• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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