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