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 "hitls_build.h"
17 #ifdef HITLS_BSL_UIO_UDP
18 #include "securec.h"
19 #include "bsl_sal.h"
20 #include "bsl_binlog_id.h"
21 #include "bsl_log_internal.h"
22 #include "bsl_log.h"
23 #include "bsl_err_internal.h"
24 #include "bsl_errno.h"
25 #include "bsl_uio.h"
26 #include "sal_net.h"
27 #include "uio_base.h"
28 #include "uio_abstraction.h"
29
30 typedef struct {
31 BSL_SAL_SockAddr peer;
32 int32_t fd; // Network socket
33 uint32_t connected;
34 } UdpParameters;
35
UdpNew(BSL_UIO * uio)36 static int32_t UdpNew(BSL_UIO *uio)
37 {
38 if (uio->ctx != NULL) {
39 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID05056, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
40 "Uio: ctx is already existed.", 0, 0, 0, 0);
41 BSL_ERR_PUSH_ERROR(BSL_UIO_FAIL);
42 return BSL_UIO_FAIL;
43 }
44
45 UdpParameters *parameters = (UdpParameters *)BSL_SAL_Calloc(1u, sizeof(UdpParameters));
46 if (parameters == NULL) {
47 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID05073, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
48 "Uio: udp param malloc fail.", 0, 0, 0, 0);
49 BSL_ERR_PUSH_ERROR(BSL_UIO_FAIL);
50 return BSL_UIO_FAIL;
51 }
52 int32_t ret = SAL_SockAddrNew(&(parameters->peer));
53 if (ret != BSL_SUCCESS) {
54 BSL_ERR_PUSH_ERROR(ret);
55 BSL_SAL_Free(parameters);
56 return ret;
57 }
58 parameters->fd = -1;
59 parameters->connected = 0;
60
61 uio->ctx = parameters;
62 uio->ctxLen = sizeof(UdpParameters);
63 // Specifies whether to be closed by uio when setting fd.
64 // The default value of init is 0. Set the value of init to 1 after the fd is set.
65 return BSL_SUCCESS;
66 }
67
UdpSocketDestroy(BSL_UIO * uio)68 static int32_t UdpSocketDestroy(BSL_UIO *uio)
69 {
70 if (uio == NULL) {
71 return BSL_SUCCESS;
72 }
73 UdpParameters *ctx = BSL_UIO_GetCtx(uio);
74 if (ctx != NULL) {
75 if (BSL_UIO_GetIsUnderlyingClosedByUio(uio) && ctx->fd != -1) {
76 (void)BSL_SAL_SockClose(ctx->fd);
77 }
78 SAL_SockAddrFree(ctx->peer);
79 BSL_SAL_Free(ctx);
80 BSL_UIO_SetCtx(uio, NULL);
81 }
82 uio->init = false;
83 return BSL_SUCCESS;
84 }
85
UdpGetPeerIpAddr(UdpParameters * parameters,int32_t larg,uint8_t * parg)86 static int32_t UdpGetPeerIpAddr(UdpParameters *parameters, int32_t larg, uint8_t *parg)
87 {
88 uint32_t uniAddrSize = SAL_SockAddrSize(parameters->peer);
89 if (parg == NULL || (uint32_t)larg < uniAddrSize) {
90 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID05074, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
91 "Uio: Get peer ip address input error.", 0, 0, 0, 0);
92 return BSL_NULL_INPUT;
93 }
94 SAL_SockAddrCopy(parg, parameters->peer);
95 return BSL_SUCCESS;
96 }
97
UdpSetPeerIpAddr(UdpParameters * parameters,const uint8_t * addr,uint32_t size)98 static int32_t UdpSetPeerIpAddr(UdpParameters *parameters, const uint8_t *addr, uint32_t size)
99 {
100 uint32_t uniAddrSize = SAL_SockAddrSize(parameters->peer);
101 if (addr == NULL || uniAddrSize == 0 || size > uniAddrSize) {
102 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID05073, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
103 "Uio: NULL error.", 0, 0, 0, 0);
104 BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
105 return BSL_NULL_INPUT;
106 }
107 SAL_SockAddrCopy(parameters->peer, (BSL_SAL_SockAddr)(uintptr_t)addr);
108 return BSL_SUCCESS;
109 }
110
UdpSetFd(BSL_UIO * uio,int32_t size,const int32_t * fd)111 static int32_t UdpSetFd(BSL_UIO *uio, int32_t size, const int32_t *fd)
112 {
113 if (fd == NULL) {
114 BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
115 return BSL_NULL_INPUT;
116 }
117 if (size != (int32_t)sizeof(*fd)) {
118 BSL_ERR_PUSH_ERROR(BSL_INVALID_ARG);
119 return BSL_INVALID_ARG;
120 }
121 UdpParameters *udpCtx = BSL_UIO_GetCtx(uio); // ctx is not NULL
122 if (udpCtx->fd != -1) {
123 if (BSL_UIO_GetIsUnderlyingClosedByUio(uio)) {
124 (void)BSL_SAL_SockClose(udpCtx->fd);
125 }
126 }
127 udpCtx->fd = *fd;
128 uio->init = true;
129 return BSL_SUCCESS;
130 }
131
UdpGetFd(BSL_UIO * uio,int32_t size,int32_t * fd)132 static int32_t UdpGetFd(BSL_UIO *uio, int32_t size, int32_t *fd)
133 {
134 if (fd == NULL) {
135 BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
136 return BSL_NULL_INPUT;
137 }
138 if (size != (int32_t)sizeof(int32_t)) {
139 BSL_ERR_PUSH_ERROR(BSL_INVALID_ARG);
140 return BSL_INVALID_ARG;
141 }
142 UdpParameters *ctx = BSL_UIO_GetCtx(uio); // ctx is not NULL
143 *fd = ctx->fd;
144 return BSL_SUCCESS;
145 }
146
UdpSocketCtrl(BSL_UIO * uio,int32_t cmd,int32_t larg,void * parg)147 int32_t UdpSocketCtrl(BSL_UIO *uio, int32_t cmd, int32_t larg, void *parg)
148 {
149 UdpParameters *parameters = BSL_UIO_GetCtx(uio);
150 if (parameters == NULL) {
151 BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
152 return BSL_NULL_INPUT;
153 }
154 switch (cmd) {
155 case BSL_UIO_SET_FD:
156 return UdpSetFd(uio, larg, parg);
157 case BSL_UIO_GET_FD:
158 return UdpGetFd(uio, larg, parg);
159 case BSL_UIO_SET_PEER_IP_ADDR:
160 return UdpSetPeerIpAddr(parameters, parg, (uint32_t)larg);
161 case BSL_UIO_GET_PEER_IP_ADDR:
162 return UdpGetPeerIpAddr(parameters, larg, parg);
163 case BSL_UIO_UDP_SET_CONNECTED:
164 if (parg != NULL) {
165 parameters->connected = 1;
166 return UdpSetPeerIpAddr(parameters, parg, (uint32_t)larg);
167 } else {
168 parameters->connected = 0;
169 return BSL_SUCCESS;
170 }
171 case BSL_UIO_FLUSH:
172 return BSL_SUCCESS;
173 default:
174 break;
175 }
176 BSL_ERR_PUSH_ERROR(BSL_UIO_FAIL);
177 return BSL_UIO_FAIL;
178 }
179
UdpSocketWrite(BSL_UIO * uio,const void * buf,uint32_t len,uint32_t * writeLen)180 static int32_t UdpSocketWrite(BSL_UIO *uio, const void *buf, uint32_t len, uint32_t *writeLen)
181 {
182 int32_t err = 0;
183 int32_t sendBytes = 0;
184 int32_t fd = BSL_UIO_GetFd(uio);
185 UdpParameters *ctx = (UdpParameters *)BSL_UIO_GetCtx(uio);
186 if (ctx == NULL || fd < 0) {
187 BSL_ERR_PUSH_ERROR(BSL_UIO_IO_EXCEPTION);
188 return BSL_UIO_IO_EXCEPTION;
189 }
190
191 uint32_t peerAddrSize = SAL_SockAddrSize(ctx->peer);
192 if (ctx->connected == 1) {
193 sendBytes = SAL_Write(fd, buf, len, &err);
194 } else {
195 sendBytes = SAL_Sendto(fd, buf, len, 0, ctx->peer, peerAddrSize, &err);
196 }
197
198 (void)BSL_UIO_ClearFlags(uio, BSL_UIO_FLAGS_RWS | BSL_UIO_FLAGS_SHOULD_RETRY);
199 if (sendBytes < 0) {
200 /* None-fatal error */
201 if (UioIsNonFatalErr(err)) {
202 (void)BSL_UIO_SetFlags(uio, BSL_UIO_FLAGS_WRITE | BSL_UIO_FLAGS_SHOULD_RETRY);
203 return BSL_SUCCESS;
204 }
205 /* Fatal error */
206 BSL_ERR_PUSH_ERROR(BSL_UIO_IO_EXCEPTION);
207 return BSL_UIO_IO_EXCEPTION;
208 }
209
210 *writeLen = (uint32_t)sendBytes;
211 return BSL_SUCCESS;
212 }
213
UdpSocketRead(BSL_UIO * uio,void * buf,uint32_t len,uint32_t * readLen)214 static int32_t UdpSocketRead(BSL_UIO *uio, void *buf, uint32_t len, uint32_t *readLen)
215 {
216 *readLen = 0;
217 int32_t err = 0;
218 int32_t fd = BSL_UIO_GetFd(uio);
219 UdpParameters *ctx = BSL_UIO_GetCtx(uio);
220 if (ctx == NULL || fd < 0) {
221 BSL_ERR_PUSH_ERROR(BSL_UIO_IO_EXCEPTION);
222 return BSL_UIO_IO_EXCEPTION;
223 }
224 int32_t addrlen = (int32_t)SAL_SockAddrSize(ctx->peer);
225 int32_t ret = SAL_RecvFrom(fd, buf, len, 0, ctx->peer, &addrlen, &err);
226 if (ret < 0) {
227 if (UioIsNonFatalErr(err) == true) {
228 (void)BSL_UIO_SetFlags(uio, BSL_UIO_FLAGS_READ | BSL_UIO_FLAGS_SHOULD_RETRY);
229 return BSL_SUCCESS;
230 }
231 /* Fatal error */
232 BSL_ERR_PUSH_ERROR(BSL_UIO_IO_EXCEPTION);
233 return BSL_UIO_IO_EXCEPTION;
234 } else if (ret == 0) {
235 BSL_ERR_PUSH_ERROR(BSL_UIO_IO_EXCEPTION);
236 return BSL_UIO_IO_EXCEPTION;
237 }
238 *readLen = (uint32_t)ret;
239 return BSL_SUCCESS;
240 }
241
BSL_UIO_UdpMethod(void)242 const BSL_UIO_Method *BSL_UIO_UdpMethod(void)
243 {
244 static const BSL_UIO_Method method = {
245 BSL_UIO_UDP,
246 UdpSocketWrite,
247 UdpSocketRead,
248 UdpSocketCtrl,
249 NULL,
250 NULL,
251 UdpNew,
252 UdpSocketDestroy
253 };
254 return &method;
255 }
256 #endif /* HITLS_BSL_UIO_UDP */
257