• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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