• 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 
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