1 /*
2 * This file is part of the openHiTLS project.
3 *
4 * openHiTLS is licensed under the Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 *
8 * http://license.coscl.org.cn/MulanPSL2
9 *
10 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13 * See the Mulan PSL v2 for more details.
14 */
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <stdbool.h>
19 #include <sys/socket.h>
20 #include <arpa/inet.h>
21 #include <unistd.h>
22 #include <fcntl.h>
23 #include <sys/types.h>
24 #include <errno.h>
25
26 #include "hitls_build.h"
27 #ifdef HITLS_BSL_UIO_TCP
28 #include "securec.h"
29 #include "bsl_uio.h"
30 #include "hitls_error.h"
31 #include "hitls_type.h"
32 #include "hitls.h"
33 #include "tls.h"
34 #include "hs_ctx.h"
35 #include "bsl_errno.h"
36 #include "uio_base.h"
37
38 #include "logger.h"
39 #include "hlt_type.h"
40 #include "socket_common.h"
41 #include "tcp_channel.h"
42
43 /**
44 * @brief Connects to the peer and returns a socket descriptor.
45 *
46 * @return -1 is returned when an error occurs
47 * */
TcpConnect(const char * targetIP,const int targetPort)48 int TcpConnect(const char *targetIP, const int targetPort)
49 {
50 (void)targetIP;
51 int fd;
52 struct sockaddr_in serverAddr;
53
54 // Create a socket
55 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
56 LOG_ERROR("socket() fail\n");
57 return -1;
58 }
59 int option = 1;
60 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)) < 0) {
61 close(fd);
62 LOG_ERROR("setsockopt() fail\n");
63 return -1;
64 }
65
66 struct linger so_linger;
67 so_linger.l_onoff = true;
68 so_linger.l_linger = 0;
69 if (setsockopt(fd, SOL_SOCKET, SO_LINGER, &so_linger, sizeof(so_linger)) < 0) {
70 close(fd);
71 LOG_ERROR("setsockopt() linger fail\n");
72 return -1;
73 }
74
75 // Set the protocol and port number
76 (void)memset_s(&serverAddr, sizeof(serverAddr), 0, sizeof(serverAddr));
77 serverAddr.sin_family = AF_INET;
78 serverAddr.sin_port = htons(targetPort);
79
80 // Set the IP address
81 serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
82
83 // Connection
84 int index = 0;
85 const int maxConnTime = 8000;
86 do {
87 if (connect(fd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == 0) {
88 break;
89 }
90 usleep(1000); // Delay 100000 us
91 LOG_ERROR("Connect error try again\n");
92 } while (index++ < maxConnTime);
93 if (index >= maxConnTime) {
94 close(fd);
95 LOG_ERROR("Connect error\n");
96 return -1;
97 }
98 SetBlockMode(fd, false);
99 return fd;
100 }
101
TcpBind(const int localPort)102 int TcpBind(const int localPort)
103 {
104 int lisentFd, ret;
105 struct sockaddr_in serverAddr;
106
107 // Create a socket
108 if ((lisentFd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
109 LOG_ERROR("create socket fail\n");
110 return -1;
111 }
112
113 int option = 1;
114 if (setsockopt(lisentFd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)) < 0) {
115 close(lisentFd);
116 LOG_ERROR("setsockopt fail\n");
117 return -1;
118 }
119
120 struct linger so_linger;
121 so_linger.l_onoff = true;
122 so_linger.l_linger = 0;
123 if (setsockopt(lisentFd, SOL_SOCKET, SO_LINGER, &so_linger, sizeof(so_linger)) < 0) {
124 close(lisentFd);
125 LOG_ERROR("setsockopt() linger fail\n");
126 return -1;
127 }
128
129 // Set the protocol and port number
130 (void)memset_s(&serverAddr, sizeof(serverAddr), 0, sizeof(serverAddr));
131 serverAddr.sin_family = AF_INET;
132 serverAddr.sin_port = htons(localPort);
133 serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
134 uint32_t tryNum = 0;
135 LOG_DEBUG("bind socket ing...\n");
136 do {
137 ret = bind(lisentFd, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
138 usleep(1000); // 1000 microseconds, that is, 1 ms
139 tryNum++;
140 } while ((ret != 0) && (tryNum < 8000)); // 8000: indicates that the binding attempt is 8 seconds
141 if (ret != 0) {
142 close(lisentFd);
143 LOG_DEBUG("bind socket fail\n");
144 return -1;
145 }
146
147 if (listen(lisentFd, 5) != 0) { // core should queue for the corresponding socket5
148 close(lisentFd);
149 LOG_DEBUG("listen socket fail\n");
150 return -1;
151 }
152 SetBlockMode(lisentFd, false);
153 return lisentFd;
154 }
155
TcpAccept(char * ip,int listenFd,bool isBlock,bool needClose)156 int TcpAccept(char *ip, int listenFd, bool isBlock, bool needClose)
157 {
158 (void)ip;
159 int32_t ret;
160
161 struct sockaddr_in clientAddr;
162 unsigned int len = sizeof(struct sockaddr_in);
163 int fd = -1;
164 uint32_t tryNum = 0;
165 LOG_DEBUG("tcp Accept ing...\n");
166 do {
167 fd = accept(listenFd, (struct sockaddr *)&clientAddr, &len);
168 tryNum++;
169 usleep(1000); // 1000 microseconds, that is, 1 ms
170 // 10000: indicates that the system attempts to listen on the system for 10 seconds
171 } while ((fd == -1) && (tryNum < 10000));
172 if (fd == -1) {
173 LOG_DEBUG("TCP accept fail\n");
174 return -1;
175 }
176
177 // Whether to block the interface
178 ret = SetBlockMode(fd, isBlock);
179 if (ret != 0) {
180 close(listenFd);
181 close(fd);
182 LOG_DEBUG("SetBlockMode ERROR");
183 }
184 // Disable listenFd
185 if (needClose) {
186 close(listenFd);
187 }
188
189 struct linger so_linger;
190 so_linger.l_onoff = 1;
191 so_linger.l_linger = 1;
192 setsockopt(fd,SOL_SOCKET,SO_LINGER, &so_linger,sizeof(so_linger));
193
194 LOG_DEBUG("accept a fd:%d\n", fd);
195 return fd;
196 }
197
198 /* Disable the specified socket */
TcpClose(int sd)199 void TcpClose(int sd)
200 {
201 close(sd);
202 }
203
TcpFrameWrite(BSL_UIO * uio,const void * buf,uint32_t len,uint32_t * writeLen)204 int32_t TcpFrameWrite(BSL_UIO *uio, const void *buf, uint32_t len, uint32_t *writeLen)
205 {
206 int32_t ret;
207 uint8_t *newBuf = NULL;
208 const void *sendBuf = buf;
209 uint32_t sendLen = len;
210 HLT_FrameHandle *frameHandle = GetFrameHandle();
211
212 if (frameHandle->frameCallBack != NULL && frameHandle->pointType == POINT_SEND) {
213 newBuf = GetNewBuf(buf, len, &sendLen);
214 if (sendLen == 0) { // sendLen value changes and becomes 0, the value is IO_BUSY
215 *writeLen = 0;
216 return BSL_SUCCESS;
217 }
218 if (newBuf != NULL) {
219 sendBuf = (void *)newBuf;
220 }
221 }
222 ret = BSL_UIO_TcpMethod()->uioWrite(uio, sendBuf, sendLen, writeLen);
223 if (sendLen != len && *writeLen != 0) {
224 *writeLen = len;
225 }
226 FreeNewBuf(newBuf);
227 return ret;
228 }
229
TcpFrameRead(BSL_UIO * uio,void * buf,uint32_t len,uint32_t * readLen)230 int32_t TcpFrameRead(BSL_UIO *uio, void *buf, uint32_t len, uint32_t *readLen)
231 {
232 int ret;
233 ret = BSL_UIO_TcpMethod()->uioRead(uio, buf, len, readLen);
234 if (ret != BSL_SUCCESS) {
235 return ret;
236 }
237
238 uint8_t *newBuf = NULL;
239 uint32_t packLen = *readLen;
240 HLT_FrameHandle *frameHandle = GetFrameHandle();
241 if (frameHandle->frameCallBack != NULL && frameHandle->pointType == POINT_RECV) {
242 newBuf = GetNewBuf(buf, len, &packLen);
243 if (packLen == 0) { // packLen changes and becomes 0, the value is IO_BUSY
244 *readLen = 0;
245 return BSL_SUCCESS;
246 }
247 if (newBuf != NULL) {
248 if (memcpy_s(buf, len, (uint8_t *)newBuf, packLen) != EOK) {
249 FreeNewBuf(newBuf);
250 return BSL_UIO_IO_EXCEPTION;
251 }
252 *readLen = packLen;
253 }
254 FreeNewBuf(newBuf);
255 }
256 return BSL_SUCCESS;
257 }
258
SelectTcpWrite(BSL_UIO * uio,const void * buf,uint32_t len,uint32_t * writeLen)259 int32_t SelectTcpWrite(BSL_UIO *uio, const void *buf, uint32_t len, uint32_t *writeLen)
260 {
261 HLT_FrameHandle *frameHandle = GetFrameHandle();
262 if (frameHandle->method.uioWrite != NULL) {
263 return frameHandle->method.uioWrite(uio, buf, len, writeLen);
264 }
265 return TcpFrameWrite(uio, buf, len, writeLen);
266 }
267
SelectTcpRead(BSL_UIO * uio,void * buf,uint32_t len,uint32_t * readLen)268 int32_t SelectTcpRead(BSL_UIO *uio, void *buf, uint32_t len, uint32_t *readLen)
269 {
270 HLT_FrameHandle *frameHandle = GetFrameHandle();
271 if (frameHandle->method.uioRead != NULL) {
272 return frameHandle->method.uioRead(uio, buf, len, readLen);
273 }
274 return TcpFrameRead(uio, buf, len, readLen);
275 }
276
277 static BSL_UIO_Method g_TcpUioMethodDefault;
278
279 /* Provide the default Linux implementation method */
TcpGetDefaultMethod(void)280 void *TcpGetDefaultMethod(void)
281 {
282 const BSL_UIO_Method *ori = BSL_UIO_TcpMethod();
283 memcpy(&g_TcpUioMethodDefault, ori, sizeof(g_TcpUioMethodDefault));
284 g_TcpUioMethodDefault.uioWrite = SelectTcpWrite;
285 g_TcpUioMethodDefault.uioRead = SelectTcpRead;
286 return &g_TcpUioMethodDefault;
287 }
288 #endif
289