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