1 /*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "sysio.h"
17 #include "sockets.h"
18 #include "socket_common.h"
19 #include "spunge_mem.h"
20 #include "opt.h"
21 #include "res.h"
22 #include "spunge.h"
23
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
27 static int SysioSendUdp(
28 void *arg,
29 FILLP_CONST char *buf,
30 FILLP_SIZE_T size,
31 FILLP_SOCKADDR *dest,
32 FILLP_UINT16 destAddrLen);
33
34 static struct SpungePcb*SysioGetPcbFromRemoteaddrUdp(
35 struct sockaddr *addr,
36 FILLP_CONST struct SockOsSocket *osSock,
37 FILLP_CONST struct Hlist *list);
38
39 static int SysioDoSocketUdp(void *argSock);
40 static void *SysioRecvUdp(void *arg, FILLP_CONST void *buf, void *databuf);
41 static void *SysioCreateSocketUdp(
42 FILLP_INT domain,
43 FILLP_INT type,
44 FILLP_INT protocol);
45 static int SysioDestroySocketUdp(void *arg);
46 static int SysioBindUdp(void *argSock, void *argPcb, FILLP_SOCKADDR *addr, FILLP_UINT16 len);
47 static int SysioCanSockReadUdp(void *arg);
48 static int SysioSelectUdp(void *arg, FILLP_INT timeoutUs);
49 static void *SysioFetchPacketUdp(void *sock, void *buf, void *count);
50 static int SysioConnectUdp(void *argSock, void *argPcb);
51 static void SysioRemovePcbUdp(void *argSock, void *argPcb);
52 static void SysioAddPcbUdp(void *argSock, void *argPcb);
53 static void SysioFreeSocketUdp(void *argSock, void *argOsSock);
54 static int SysioSendPacketUdp(
55 int msgType,
56 void *argSock,
57 void *argPcb,
58 void *argBuf);
59 static int SysioHandlePacketUdp(
60 int msgType,
61 void *argSock,
62 void *argPcb,
63 void *argBuf);
64
65 static int SysioListenUdp(void *argSock);
66
67 static int SysioGetSocknameUdp(void *argSock, void *name, void *nameLen);
68
SysioGetOsSocketUdp(void * argSock)69 static int SysioGetOsSocketUdp(void *argSock)
70 {
71 SysIoUdpSock *udpSock = (SysIoUdpSock *)argSock;
72 return udpSock->udpSock;
73 }
74
75 static void SysioConnectedUdp(void *argSock, void *argOsSock);
76 static int SysioGetsockoptUdp(
77 void *arg,
78 FILLP_INT level,
79 FILLP_INT optName,
80 void *optVal,
81 FILLP_INT *optLen);
82 static int SysioSetsockoptUdp(
83 void *arg,
84 FILLP_INT level,
85 FILLP_INT optName,
86 FILLP_CONST void *optVal,
87 socklen_t optLen);
88
89 SysioUdpT g_udpIo = {
90 {
91 SysioDoSocketUdp,
92 SysioSendUdp,
93 SysioRecvUdp,
94 SysioFetchPacketUdp,
95 SysioSelectUdp,
96 SysioCreateSocketUdp,
97 SysioDestroySocketUdp,
98 SysioListenUdp,
99 SysioBindUdp,
100 SysioConnectUdp,
101 SysioCanSockReadUdp,
102 SysioHandlePacketUdp,
103 SysioSendPacketUdp,
104 SysioRemovePcbUdp,
105 SysioFreeSocketUdp,
106 SysioGetSocknameUdp,
107 SysioAddPcbUdp,
108 SysioGetOsSocketUdp,
109 SysioConnectedUdp,
110 SysioGetsockoptUdp,
111 SysioSetsockoptUdp
112 },
113 0,
114 0,
115 0,
116 {
117 {
118 0, 0, 0,
119 },
120 0,
121 #ifdef FILLP_64BIT_ALIGN
122 {
123 0
124 }
125 #endif
126 }
127 };
128
SysioDoSocketUdp(void * argSock)129 static int SysioDoSocketUdp(void *argSock)
130 {
131 FILLP_UNUSED_PARA(argSock);
132 return ERR_OK;
133 }
134
SysioListenUdp(void * argSock)135 static int SysioListenUdp(void *argSock)
136 {
137 struct FtSocket *sock = (struct FtSocket *)argSock;
138 HlistAddTail(&g_udpIo.listenPcbList, &sock->listenNode);
139 return ERR_OK;
140 }
141
SysioSendUdp(void * arg,FILLP_CONST char * buf,FILLP_SIZE_T size,FILLP_SOCKADDR * dest,FILLP_UINT16 destAddrLen)142 static int SysioSendUdp(
143 void *arg,
144 FILLP_CONST char *buf,
145 FILLP_SIZE_T size,
146 FILLP_SOCKADDR *dest,
147 FILLP_UINT16 destAddrLen)
148 {
149 int ret;
150
151 #if defined(FILLP_LINUX) && !defined(FILLP_MAC)
152 FILLP_INT flg = MSG_NOSIGNAL;
153 #else
154 FILLP_INT flg = 0;
155 #endif
156
157 SysIoUdpSock *udpSock = (SysIoUdpSock *)arg;
158
159 if (udpSock->connected) {
160 ret = (int)FILLP_SEND(udpSock->udpSock, buf, (FILLP_INT)size, flg);
161 } else {
162 ret = (int)FILLP_SENDTO(udpSock->udpSock, buf, size, flg, dest, destAddrLen);
163 }
164
165 return ret;
166 }
167
SysioGetsockoptUdp(void * arg,FILLP_INT level,FILLP_INT optName,void * optVal,FILLP_INT * optLen)168 static int SysioGetsockoptUdp(
169 void *arg,
170 FILLP_INT level,
171 FILLP_INT optName,
172 void *optVal,
173 FILLP_INT *optLen)
174 {
175 SysIoUdpSock *udpSock = (SysIoUdpSock *)arg;
176
177 return FILLP_GETSOCKOPT(udpSock->udpSock, level, optName, optVal, optLen);
178 }
179
SysioSetsockoptUdp(void * arg,FILLP_INT level,FILLP_INT optName,FILLP_CONST void * optVal,socklen_t optLen)180 static int SysioSetsockoptUdp(
181 void *arg,
182 FILLP_INT level,
183 FILLP_INT optName,
184 FILLP_CONST void *optVal,
185 socklen_t optLen)
186 {
187 SysIoUdpSock *udpSock = (SysIoUdpSock *)arg;
188
189 return FILLP_SETSOCKOPT(udpSock->udpSock, level, optName, optVal, optLen);
190 }
191
SysioRecvUdp(void * arg,FILLP_CONST void * buf,void * databuf)192 static void *SysioRecvUdp(void *arg, FILLP_CONST void *buf, void *databuf)
193 {
194 FILLP_UNUSED_PARA(arg);
195 FILLP_UNUSED_PARA(buf);
196 FILLP_UNUSED_PARA(databuf);
197 return FILLP_NULL_PTR;
198 }
199
SysioSelectUdp(void * arg,FILLP_INT timeoutUs)200 static int SysioSelectUdp(void *arg, FILLP_INT timeoutUs)
201 {
202 (void)FILLP_FD_COPY_FD_SET(g_udpIo.readableSet, g_udpIo.readSet);
203
204 FILLP_UNUSED_PARA(arg);
205 FILLP_UNUSED_PARA(timeoutUs);
206 return ERR_OK;
207 }
208
SysioFreeSocketUdp(void * argSock,void * argOsSock)209 static void SysioFreeSocketUdp(void *argSock, void *argOsSock)
210 {
211 struct FtSocket *sock = (struct FtSocket *)argSock;
212 if (sock->isListenSock) {
213 struct HlistNode *node = HLIST_FIRST(&g_udpIo.listenPcbList);
214 while (node != FILLP_NULL_PTR) {
215 if (node == &sock->listenNode) {
216 HlistDelete(&g_udpIo.listenPcbList, node);
217 break;
218 }
219 node = node->next;
220 }
221 }
222
223 FILLP_UNUSED_PARA(argOsSock);
224
225 return;
226 }
227
SysioFetchPacketUdp(void * sock,void * buf,void * count)228 static void *SysioFetchPacketUdp(void *sock, void *buf, void *count)
229 {
230 struct SockOsSocket *osSock = (struct SockOsSocket *)sock;
231 SysIoUdpSock *sysioUdpSock = (SysIoUdpSock *)osSock->ioSock;
232 struct NetBuf *netbuf = (struct NetBuf *)buf;
233 FILLP_SIZE_T addLen = sizeof(struct sockaddr_in6);
234 FILLP_UINT32 hashIndex;
235 FILLP_LLONG recvTime = 0;
236
237 struct SpungePcb *spcb = FILLP_NULL_PTR;
238 struct Hlist *list = FILLP_NULL_PTR;
239
240 FILLP_UNUSED_PARA(count);
241 FILLP_UNUSED_PARA(recvTime);
242 netbuf->len = (int)FILLP_RECVFROM(sysioUdpSock->udpSock, netbuf->p,
243 (size_t)FILLP_MAX_PKT_SIZE, 0, &netbuf->addr, (FILLP_SIZE_T *)&addLen);
244 if (netbuf->len <= FILLP_HLEN) {
245 return FILLP_NULL_PTR; /* No data received */
246 }
247
248 netbuf->len -= FILLP_HLEN;
249
250 hashIndex = UtilsAddrHashKey((struct sockaddr_in *)&netbuf->addr);
251 list = &(sysioUdpSock->pcbHash[hashIndex & (UDP_HASH_TABLE_SIZE - 1)].list);
252 spcb = SysioGetPcbFromRemoteaddrUdp((struct sockaddr *)&netbuf->addr, osSock, list);
253 return spcb;
254 }
255
SysioSetSocketOpt(SysIoUdpSock * udpSock)256 static int SysioSetSocketOpt(SysIoUdpSock *udpSock)
257 {
258 if (SysArchSetSockBlocking(udpSock->udpSock, FILLP_FALSE)) {
259 SET_ERRNO(FT_OS_GET_ERRNO);
260 FILLP_LOGERR("set sock nonblocking fail errno=%d", FT_OS_GET_ERRNO);
261 return -1;
262 }
263
264 if (SysArchSetSockRcvbuf(udpSock->udpSock, g_appResource.common.recvBufSize)) {
265 SET_ERRNO(FT_OS_GET_ERRNO);
266 FILLP_LOGERR("Fail to set sock recvBuf errno=%d", FT_OS_GET_ERRNO);
267 return -1;
268 }
269 #ifndef NSTACKX_WITH_LITEOS
270 if (SysArchSetSockSndbuf(udpSock->udpSock, g_appResource.common.udpSendBufSize)) {
271 SET_ERRNO(FT_OS_GET_ERRNO);
272 FILLP_LOGERR("Fail to set sock sndBuf errno=%d", FT_OS_GET_ERRNO);
273 return -1;
274 }
275 #endif
276 return 0;
277 }
278
SysioMaxUdpSockSet(int fd)279 static inline void SysioMaxUdpSockSet(int fd)
280 {
281 if (fd > g_udpIo.maxUdpSock) {
282 g_udpIo.maxUdpSock = fd;
283 }
284 }
285
SysioCreateSocketUdp(FILLP_INT domain,FILLP_INT type,FILLP_INT protocol)286 static void *SysioCreateSocketUdp(FILLP_INT domain, FILLP_INT type, FILLP_INT protocol)
287 {
288 int i;
289 size_t sockSize = sizeof(SysIoUdpSock);
290
291 SysIoUdpSock *udpSock = (SysIoUdpSock *)SpungeAlloc(1, sockSize, SPUNGE_ALLOC_TYPE_CALLOC);
292 if (udpSock == FILLP_NULL_PTR) {
293 goto FAIL;
294 }
295
296 udpSock->sysIoSock.ops = &g_udpIo.ops;
297 udpSock->connected = FILLP_FALSE;
298
299 FILLP_UNUSED_PARA(type);
300 FILLP_UNUSED_PARA(protocol);
301
302 udpSock->udpSock = FILLP_SOCKET(domain, (FILLP_INT)SOCK_DGRAM, 0);
303 udpSock->addrType = domain;
304 if (udpSock->udpSock == -1) {
305 SET_ERRNO(FT_OS_GET_ERRNO);
306 FILLP_LOGERR("Can't create udp socket errno=%d", FT_OS_GET_ERRNO);
307 goto FAIL;
308 }
309 FILLP_LOGINF("alloc udp socket %d", udpSock->udpSock);
310 if (SysioSetSocketOpt(udpSock) != 0) {
311 goto FAIL;
312 }
313 SysioMaxUdpSockSet(udpSock->udpSock);
314 FILLP_FD_SET((FILLP_UINT)udpSock->udpSock, g_udpIo.readSet);
315
316 udpSock->pcbHash = (struct SpungePcbhashbucket *)SpungeAlloc(UDP_HASH_TABLE_SIZE,
317 sizeof(struct SpungePcbhashbucket), SPUNGE_ALLOC_TYPE_CALLOC);
318 if (udpSock->pcbHash == FILLP_NULL_PTR) {
319 FILLP_FD_CLR((FILLP_UINT32)udpSock->udpSock, g_udpIo.readSet);
320 FILLP_LOGERR("Failed to allocate memory for pcb hash bucket");
321 goto FAIL;
322 }
323 for (i = 0; i < UDP_HASH_TABLE_SIZE; i++) {
324 HLIST_INIT(&udpSock->pcbHash[i].list);
325 }
326
327 return (void *)udpSock;
328 FAIL:
329 if (udpSock != FILLP_NULL_PTR) {
330 if (udpSock->udpSock >= 0) {
331 (void)FILLP_CLOSE(udpSock->udpSock);
332 udpSock->udpSock = -1;
333 }
334 SpungeFree(udpSock, SPUNGE_ALLOC_TYPE_CALLOC);
335 udpSock = FILLP_NULL_PTR;
336 }
337
338 return (void *)udpSock;
339 }
340
SysioDestroySocketUdp(void * arg)341 static int SysioDestroySocketUdp(void *arg)
342 {
343 SysIoUdpSock *udpSock = (SysIoUdpSock *)arg;
344 if (udpSock->udpSock >= 0) {
345 if (g_udpIo.readSet != FILLP_NULL_PTR) {
346 if (FILLP_FD_ISSET(udpSock->udpSock, g_udpIo.readSet)) {
347 FILLP_FD_CLR((FILLP_UINT32)udpSock->udpSock, g_udpIo.readSet);
348 }
349 }
350 (void)FILLP_CLOSE(udpSock->udpSock);
351 FILLP_LOGINF("close udp socket %d", udpSock->udpSock);
352 udpSock->udpSock = -1;
353 }
354
355 udpSock->connected = FILLP_FALSE;
356 if (udpSock->pcbHash != FILLP_NULL_PTR) {
357 SpungeFree(udpSock->pcbHash, SPUNGE_ALLOC_TYPE_CALLOC);
358 udpSock->pcbHash = FILLP_NULL_PTR;
359 }
360 SpungeFree(udpSock, SPUNGE_ALLOC_TYPE_CALLOC);
361 return ERR_OK;
362 }
363
SysioBindUdp(void * argSock,void * argPcb,FILLP_SOCKADDR * addr,FILLP_UINT16 len)364 static int SysioBindUdp(void *argSock, void *argPcb, FILLP_SOCKADDR *addr, FILLP_UINT16 len)
365 {
366 SysIoUdpSock *udpSock = (SysIoUdpSock *)argSock;
367
368 int err = FILLP_BIND(udpSock->udpSock, addr, (FILLP_INT32)len);
369 if (err != ERR_OK) {
370 FILLP_LOGERR("Bind error");
371 return err;
372 }
373
374 FILLP_UNUSED_PARA(argPcb);
375
376 return err;
377 }
378
SysioConnectUdp(void * argSock,void * argPcb)379 static int SysioConnectUdp(void *argSock, void *argPcb)
380 {
381 SysIoUdpSock *udpSock = (SysIoUdpSock *)argSock;
382 struct SpungePcb *pcb = (struct SpungePcb *)argPcb;
383
384 FILLP_UINT32 addrHashKey = UtilsAddrHashKey((struct sockaddr_in *)&pcb->remoteAddr);
385 HlistAddTail(&udpSock->pcbHash[addrHashKey & (UDP_HASH_TABLE_SIZE - 1)].list, &pcb->hashNode);
386
387 return ERR_OK;
388 }
389
SysioRemovePcbUdp(void * argSock,void * argPcb)390 static void SysioRemovePcbUdp(void *argSock, void *argPcb)
391 {
392 SysIoUdpSock *udpSock = (SysIoUdpSock *)argSock;
393 struct SpungePcb *pcb = (struct SpungePcb*)argPcb;
394 if (udpSock->pcbHash == FILLP_NULL_PTR) {
395 return;
396 }
397 FILLP_UINT32 addrHashKey = UtilsAddrHashKey((struct sockaddr_in *)&pcb->remoteAddr);
398 struct Hlist *pcbHashList = &(udpSock->pcbHash[addrHashKey & (UDP_HASH_TABLE_SIZE - 1)].list);
399 struct HlistNode *node = FILLP_NULL_PTR;
400 /* Ipv6 is not supported for raw socket so check is not added */
401 if ((pcbHashList != FILLP_NULL_PTR) && !HLIST_EMPTY(pcbHashList)) {
402 node = HLIST_FIRST(pcbHashList);
403 while (node != FILLP_NULL_PTR) {
404 if (node == &pcb->hashNode) {
405 break;
406 }
407 node = node->next;
408 }
409 }
410
411 if (node != FILLP_NULL_PTR) {
412 HlistDelete(pcbHashList, node);
413 }
414 }
415
SysioAddPcbUdp(void * argSock,void * argPcb)416 static void SysioAddPcbUdp(void *argSock, void *argPcb)
417 {
418 FILLP_UNUSED_PARA(argSock);
419 FILLP_UNUSED_PARA(argPcb);
420
421 return;
422 }
423
424
SysioCanSockReadUdp(void * arg)425 static int SysioCanSockReadUdp(void *arg)
426 {
427 SysIoUdpSock *udpSock = (SysIoUdpSock *)arg;
428 return FILLP_FD_ISSET(udpSock->udpSock, g_udpIo.readableSet);
429 }
430
SysioHandlePacketUdp(int msgType,void * argSock,void * argPcb,void * argBuf)431 static int SysioHandlePacketUdp(
432 int msgType,
433 void *argSock,
434 void *argPcb,
435 void *argBuf)
436 {
437 SysIoUdpSock *udpSock = (SysIoUdpSock *)argSock;
438 struct SpungePcb *pcb = (struct SpungePcb *)argPcb;
439
440 switch (msgType) {
441 case FILLP_PKT_TYPE_CONN_CONFIRM: {
442 FILLP_UINT32 addrHashKey = UtilsAddrHashKey((struct sockaddr_in *)&pcb->remoteAddr);
443 HlistAddTail(&udpSock->pcbHash[addrHashKey & (UDP_HASH_TABLE_SIZE - 1)].list, &pcb->hashNode);
444 break;
445 }
446 default:
447 FILLP_LOGERR("Unsupported message type");
448 return ERR_PARAM;
449 }
450
451 FILLP_UNUSED_PARA(argBuf);
452
453 return ERR_OK;
454 }
455
SysioGetSocknameUdp(void * argSock,void * name,void * nameLen)456 static int SysioGetSocknameUdp(void *argSock, void *name, void *nameLen)
457 {
458 SysIoUdpSock *udpSock = (SysIoUdpSock *)argSock;
459 return FILLP_GETSOCKNAME(udpSock->udpSock, name, nameLen);
460 }
461
SysioSendPacketUdp(int msgType,void * argSock,void * argPcb,void * argBuf)462 static int SysioSendPacketUdp(
463 int msgType,
464 void *argSock,
465 void *argPcb,
466 void *argBuf)
467 {
468 struct SpungePcb *pcb = (struct SpungePcb*)argPcb;
469 struct FtNetconn *conn = (struct FtNetconn *)pcb->conn;
470
471 FILLP_UNUSED_PARA(argSock);
472
473 switch (msgType) {
474 case FILLP_PKT_TYPE_DATA: {
475 struct NetBuf *sendBuf = (struct NetBuf *)argBuf;
476 return pcb->fpcb.sendFunc(conn, sendBuf->p, sendBuf->len + FILLP_HLEN, pcb);
477 }
478
479 case FILLP_PKT_TYPE_CONN_REQ: {
480 return FillpSendConnReq(&pcb->fpcb);
481 }
482
483 default:
484 FILLP_LOGERR("Unsupported message type");
485 return ERR_PARAM;
486 }
487 }
488
SysioGetListenSocketByOssock(FILLP_CONST struct SockOsSocket * osSock)489 static struct SpungePcb *SysioGetListenSocketByOssock(
490 FILLP_CONST struct SockOsSocket *osSock)
491 {
492 struct HlistNode *node = FILLP_NULL_PTR;
493 struct FtSocket *sock = FILLP_NULL_PTR;
494 FILLP_INT instIndex = SPUNGE_GET_CUR_INSTANCE()->instIndex;
495
496 if ((instIndex < 0) || (instIndex >= MAX_SPUNGEINSTANCE_NUM)) {
497 return FILLP_NULL_PTR;
498 }
499
500 node = HLIST_FIRST(&g_udpIo.listenPcbList);
501 while (node != FILLP_NULL_PTR) {
502 sock = SockEntryListenSocket(node);
503 if (osSock == sock->netconn->osSocket[instIndex]) {
504 return sock->netconn->pcb;
505 }
506 node = node->next;
507 }
508
509 return FILLP_NULL_PTR;
510 }
511
SysioGetPcbFromRemoteaddrUdp(struct sockaddr * addr,FILLP_CONST struct SockOsSocket * osSock,FILLP_CONST struct Hlist * list)512 static struct SpungePcb *SysioGetPcbFromRemoteaddrUdp(
513 struct sockaddr *addr,
514 FILLP_CONST struct SockOsSocket *osSock,
515 FILLP_CONST struct Hlist *list)
516 {
517 struct HlistNode *node = FILLP_NULL_PTR;
518 struct SpungePcb *spcb = FILLP_NULL_PTR;
519
520 if (list != FILLP_NULL_PTR) {
521 node = HLIST_FIRST(list);
522 while (node != FILLP_NULL_PTR) {
523 spcb = SpungePcbHashNodeEntry(node);
524 if (UtilsAddrMatch((struct sockaddr_in *)addr, (struct sockaddr_in *)&spcb->remoteAddr)) {
525 return spcb;
526 }
527 spcb = FILLP_NULL_PTR;
528 node = node->next;
529 }
530 }
531
532 /* Now trying to find listen socket */
533 return SysioGetListenSocketByOssock(osSock);
534 }
535
SysioConnectedUdp(void * argSock,void * argOsSock)536 static void SysioConnectedUdp(void *argSock, void *argOsSock)
537 {
538 SysIoUdpSock *udpSock = (SysIoUdpSock *)argOsSock;
539 struct FtSocket *sock = (struct FtSocket *)argSock;
540
541 if (FILLP_CONNECT(udpSock->udpSock, (struct sockaddr *)&sock->netconn->pcb->remoteAddr,
542 (FILLP_INT32)UtilsAddrValidLength((struct sockaddr_in *)&sock->netconn->pcb->remoteAddr)) == 0) {
543 FILLP_LOGDBG("UDP Connect success!!!!");
544 udpSock->connected = FILLP_TRUE;
545 } else {
546 FILLP_LOGINF("UDP Connect Failure !!!!");
547 }
548 }
549
550 #ifdef __cplusplus
551 }
552 #endif
553