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
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <stdbool.h>
20 #include <sys/socket.h>
21 #include <arpa/inet.h>
22 #include <unistd.h>
23 #include <fcntl.h>
24 #include <sys/types.h>
25 #include <errno.h>
26
27 #include "hitls_build.h"
28 #ifdef HITLS_BSL_UIO_UDP
29 #include "securec.h"
30 #include "bsl_uio.h"
31 #include "hitls_error.h"
32 #include "hitls_type.h"
33 #include "hitls.h"
34 #include "tls.h"
35 #include "hs_ctx.h"
36 #include "bsl_errno.h"
37 #include "uio_base.h"
38
39 #include "logger.h"
40 #include "hlt_type.h"
41 #include "socket_common.h"
42 #include "udp_channel.h"
43
44 /**
45 * @brief Connects to the peer and returns a socket descriptor.
46 *
47 * @return -1 is returned when an error occurs
48 * */
UdpConnect(const char * targetIP,const int targetPort)49 int UdpConnect(const char *targetIP, const int targetPort)
50 {
51 (void)targetIP;
52 (void)targetPort;
53 int fd;
54 struct sockaddr_in serverAddr;
55
56 // Create a socket
57 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
58 LOG_ERROR("socket() fail\n");
59 return -1;
60 }
61 int option = 1;
62 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)) < 0) {
63 close(fd);
64 LOG_ERROR("setsockopt() fail\n");
65 return -1;
66 }
67
68 // Set the protocol and port number
69 bzero(&serverAddr, sizeof(serverAddr));
70 serverAddr.sin_family = AF_INET;
71 serverAddr.sin_port = htons(targetPort);
72 // Set the IP address
73 serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
74
75 // Connection
76 int index = 0;
77 const int maxConnTime = 8000;
78 do {
79 if (connect(fd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == 0) {
80 break;
81 }
82 usleep(1000); // Delay 100000 us
83 LOG_ERROR("Connect error try again\n");
84 } while (index++ < maxConnTime);
85 if (index >= maxConnTime) {
86 close(fd);
87 LOG_ERROR("Connect error\n");
88 return -1;
89 }
90 SetBlockMode(fd, false);
91 return fd;
92 }
93
UdpBind(const int localPort)94 int UdpBind(const int localPort)
95 {
96 int lisentFd, ret;
97 struct sockaddr_in serverAddr;
98
99 // Create a socket
100 if ((lisentFd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
101 LOG_ERROR("create socket fail\n");
102 return -1;
103 }
104
105 int option = 1;
106 if (setsockopt(lisentFd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)) < 0) {
107 close(lisentFd);
108 LOG_ERROR("setsockopt fail\n");
109 return -1;
110 }
111
112 // Set the protocol and port number
113 bzero(&serverAddr, sizeof(serverAddr));
114 serverAddr.sin_family = AF_INET;
115 serverAddr.sin_port = htons(localPort);
116 serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
117 uint32_t tryNum = 0;
118 LOG_DEBUG("bind socket ing...\n");
119 do {
120 ret = bind(lisentFd, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
121 usleep(1000); // 1000 microseconds, that is, 1 ms
122 tryNum++;
123 } while ((ret != 0) && (tryNum < 8000)); // 8000: indicates that the binding attempt is 8 seconds
124 if (ret != 0) {
125 close(lisentFd);
126 LOG_DEBUG("bind socket fail\n");
127 return -1;
128 }
129
130 SetBlockMode(lisentFd, false);
131 return lisentFd;
132 }
133
UdpAccept(char * ip,int listenFd,bool isBlock,bool needClose)134 int UdpAccept(char *ip, int listenFd, bool isBlock, bool needClose)
135 {
136 (void)ip;
137 (void)listenFd;
138 (void)isBlock;
139
140 if (needClose) {
141 close(listenFd);
142 }
143 return listenFd;
144 }
145
146 /* Disable the specified socket */
UdpClose(int sd)147 void UdpClose(int sd)
148 {
149 close(sd);
150 }
151
UdpFrameWrite(BSL_UIO * uio,const void * buf,uint32_t len,uint32_t * writeLen)152 int32_t UdpFrameWrite(BSL_UIO *uio, const void *buf, uint32_t len, uint32_t *writeLen)
153 {
154 int32_t ret;
155 uint8_t *newBuf = NULL;
156 const void *sendBuf = buf;
157 uint32_t sendLen = len;
158 HLT_FrameHandle *frameHandle = GetFrameHandle();
159
160 if (frameHandle->frameCallBack != NULL && frameHandle->pointType == POINT_SEND) {
161 newBuf = GetNewBuf(buf, len, &sendLen);
162 if (sendLen == 0) { // sendLen value changes and becomes 0, the value is IO_BUSY
163 *writeLen = 0;
164 return BSL_SUCCESS;
165 }
166 if (newBuf != NULL) {
167 sendBuf = (void *)newBuf;
168 }
169 }
170 ret = BSL_UIO_UdpMethod()->uioWrite(uio, sendBuf, sendLen, writeLen);
171 if (sendLen != len && *writeLen != 0) {
172 *writeLen = len;
173 }
174 FreeNewBuf(newBuf);
175 return ret;
176 }
177
UdpFrameRead(BSL_UIO * uio,void * buf,uint32_t len,uint32_t * readLen)178 int32_t UdpFrameRead(BSL_UIO *uio, void *buf, uint32_t len, uint32_t *readLen)
179 {
180 int ret;
181 ret = BSL_UIO_UdpMethod()->uioRead(uio, buf, len, readLen);
182 if (ret != BSL_SUCCESS) {
183 return ret;
184 }
185
186 uint8_t *newBuf = NULL;
187 uint32_t packLen = *readLen;
188 HLT_FrameHandle *frameHandle = GetFrameHandle();
189 if (frameHandle->frameCallBack != NULL && frameHandle->pointType == POINT_RECV) {
190 newBuf = GetNewBuf(buf, len, &packLen);
191 if (packLen == 0) { // packLen changes and becomes 0, the value is IO_BUSY
192 *readLen = 0;
193 return BSL_SUCCESS;
194 }
195 if (newBuf != NULL) {
196 if (memcpy_s(buf, len, (uint8_t *)newBuf, packLen) != EOK) {
197 FreeNewBuf(newBuf);
198 return BSL_UIO_IO_EXCEPTION;
199 }
200 *readLen = packLen;
201 }
202 FreeNewBuf(newBuf);
203 }
204 return BSL_SUCCESS;
205 }
206
SelectUdpWrite(BSL_UIO * uio,const void * buf,uint32_t len,uint32_t * writeLen)207 int32_t SelectUdpWrite(BSL_UIO *uio, const void *buf, uint32_t len, uint32_t *writeLen)
208 {
209 HLT_FrameHandle *frameHandle = GetFrameHandle();
210 if (frameHandle->method.uioWrite != NULL) {
211 return frameHandle->method.uioWrite(uio, buf, len, writeLen);
212 }
213 return UdpFrameWrite(uio, buf, len, writeLen);
214 }
215
SelectUdpRead(BSL_UIO * uio,void * buf,uint32_t len,uint32_t * readLen)216 int32_t SelectUdpRead(BSL_UIO *uio, void *buf, uint32_t len, uint32_t *readLen)
217 {
218 HLT_FrameHandle *frameHandle = GetFrameHandle();
219 if (frameHandle->method.uioRead != NULL) {
220 return frameHandle->method.uioRead(uio, buf, len, readLen);
221 }
222 return UdpFrameRead(uio, buf, len, readLen);
223 }
224
225 static BSL_UIO_Method g_UdpUioMethodDefault;
226
227 /* Provide the default Linux implementation method */
UdpGetDefaultMethod(void)228 void *UdpGetDefaultMethod(void)
229 {
230 const BSL_UIO_Method *ori = BSL_UIO_UdpMethod();
231 memcpy_s(&g_UdpUioMethodDefault, sizeof(g_UdpUioMethodDefault), ori, sizeof(g_UdpUioMethodDefault));
232 g_UdpUioMethodDefault.uioWrite = SelectUdpWrite;
233 g_UdpUioMethodDefault.uioRead = SelectUdpRead;
234 return &g_UdpUioMethodDefault;
235 }
236 #endif