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 "sockets.h"
17 #include "spunge.h"
18 #include "socket_common.h"
19 
20 #ifdef __cplusplus
21 extern "C" {
22 #endif
23 
EpollUpdateEpEvent(struct EpItem * epi)24 void EpollUpdateEpEvent(struct EpItem *epi)
25 {
26     struct FtSocket *sock;
27 
28     sock = SockGetSocket(epi->fileDespcriptor);
29     if (sock == FILLP_NULL_PTR) {
30         return;
31     }
32 
33     epi->revents = (epi->event.events & (FILLP_UINT32)sock->errEvent);
34     if ((epi->event.events & SPUNGE_EPOLLIN) && ((SYS_ARCH_ATOMIC_READ(&sock->rcvEvent) > 0) || (sock->offset))) {
35         epi->revents |= SPUNGE_EPOLLIN;
36     } else {
37         epi->revents &= (FILLP_UINT32)(~SPUNGE_EPOLLIN);
38     }
39 
40     if ((epi->event.events & SPUNGE_EPOLLOUT) && (SYS_ARCH_ATOMIC_READ(&sock->sendEvent) > 0) &&
41         (SYS_ARCH_ATOMIC_READ(&sock->sendEventCount) > 0)) {
42         epi->revents |= SPUNGE_EPOLLOUT;
43     } else {
44         epi->revents &= (FILLP_UINT32)(~SPUNGE_EPOLLOUT);
45     }
46 }
47 
48 /**
49  * Callback registered in the netconn layer for each socket-netconn.
50  * Processes recvevent (data available) and wakes up tasks waiting for select.
51  */
EpollEventCallback(struct FtSocket * sock,FILLP_UINT32 upEvent)52 void EpollEventCallback(struct FtSocket *sock, FILLP_UINT32 upEvent)
53 {
54     struct EpItem *sockEpItem = FILLP_NULL_PTR;
55     struct HlistNode *epNode = FILLP_NULL_PTR;
56 
57     if (HLIST_EMPTY(&sock->epTaskList)) {
58         return;
59     }
60 
61     if (SYS_ARCH_SEM_WAIT(&sock->epollTaskListLock)) {
62         FILLP_LOGERR("Error to do sem_wait");
63         return;
64     }
65     epNode = HLIST_FIRST(&sock->epTaskList);
66     while (epNode != FILLP_NULL_PTR) {
67         sockEpItem = EpitemEntrySockWaitNode(epNode);
68         epNode = epNode->next;
69 
70         if (!(sockEpItem->event.events & upEvent)) {
71             continue;
72         }
73 
74         sockEpItem->revents |= (sockEpItem->event.events & upEvent);
75 
76         if (SYS_ARCH_SEM_WAIT(&sockEpItem->ep->appCoreSem)) {
77             FILLP_LOGERR("Error to wait appCoreSem");
78             (void)SYS_ARCH_SEM_POST(&sock->epollTaskListLock);
79             return;
80         }
81         EpSocketReady(sockEpItem->ep, sockEpItem);
82         (void)SYS_ARCH_SEM_POST(&sockEpItem->ep->appCoreSem);
83     }
84 
85     (void)SYS_ARCH_SEM_POST(&sock->epollTaskListLock);
86 }
87 
88 struct GlobalAppResource g_appResource = {
89     {
90         FILLP_DEFAULT_APP_TX_BURST,                 /* udp.txBurst */
91 #ifdef FILLP_64BIT_ALIGN
92         0                                           /* udp.reserve */
93 #endif
94     },
95     {
96         FILLP_DEFAULT_APP_KEEP_ALIVE_TIME,             /* common.keepAliveTime */
97         FILLP_DEFAULT_APP_MAX_SERVER_ALLOW_RECV_CACHE, /* common.maxServerAllowRecvCache */
98         FILLP_DEFAULT_APP_MAX_SERVER_ALLOW_SEND_CACHE, /* common.maxServerAllowSendCache */
99         FILLP_DEFAULT_UDP_SEND_BUFSIZE,                /* common.udpSendBufSize  */
100         FILLP_DEFAULT_UDP_RECV_BUFSIZE,                /* common.recvBufSize */
101         FILLP_DEFAULT_DISCONNECT_TIMER_INTERVAL,       /* common.disconnectRetrytimeout  */
102         FILLP_DEFAULT_APP_SEND_CACHE,                  /* common.sendCache */
103         FILLP_DEFAULT_APP_RECV_CACHE,                  /* common.recvCache */
104         FILLP_DEFAULT_APP_CONNECT_TIMEOUT,             /* common.connectTimeout */
105         0,                                             /* common.reserv */
106         FILLP_DEFAULT_CONNECT_RETRY_TIMER_INTERVAL,    /* common.connRetryTimeout */
107         FILLP_DELAY_NACK_ENABLE,                       /* common.enableNackDelay */
108         FILLP_DEFAULT_ENLARGE_PACK_INTERVAL,           /* common.enlargePackIntervalFlag */
109         FILLP_DEFAULT_DAT_OPT_TIMESTAMP_ENABLE,        /* common.enableDateOptTimestamp */
110         {
111             0,
112             0,
113             0
114         },                                             /* common.pad[] */
115         FILLP_DEFAULT_NACK_DELAY_TIME,                 /* common.nackDelayTimeout */
116         FILLP_APP_FC_STASTICS_INTERVAL                 /* common.fcStasticsInterval */
117     },
118     {
119         FILLP_DEFAULT_MAX_RATE,                        /* flowControl.maxRate */
120         FILLP_DEFAULT_MAX_RECV_RATE,                   /* flowControl.maxRecvRate */
121         FILLP_DEFAULT_APP_OPPOSITE_SET_RATE,           /* flowControl.oppositeSetRate */
122         FILLP_DEFAULT_APP_PACK_INTERVAL,               /* flowControl.packInterval */
123         FILLP_DEFAULT_APP_PKT_SIZE,                    /* flowControl.pktSize */
124         FILLP_DEFAULT_APP_SLOW_START,                  /* flowControl.slowStart */
125         FILLP_DEFAULT_CONST_RATE_ENABLE,               /* flowControl.constRateEnbale */
126         {0}
127     }
128 };
129 
InitGlobalAppResourceDefault(void)130 void InitGlobalAppResourceDefault(void)
131 {
132     g_appResource.udp.txBurst = FILLP_DEFAULT_APP_TX_BURST;
133     g_appResource.common.keepAliveTime = FILLP_DEFAULT_APP_KEEP_ALIVE_TIME;
134     g_appResource.common.recvCache = FILLP_DEFAULT_APP_RECV_CACHE;
135     g_appResource.common.maxServerAllowRecvCache = FILLP_DEFAULT_APP_MAX_SERVER_ALLOW_RECV_CACHE;
136     g_appResource.common.maxServerAllowSendCache = FILLP_DEFAULT_APP_MAX_SERVER_ALLOW_SEND_CACHE;
137     g_appResource.common.udpSendBufSize = FILLP_DEFAULT_UDP_SEND_BUFSIZE;
138     g_appResource.common.sendCache = FILLP_DEFAULT_APP_SEND_CACHE;
139     g_appResource.common.connectTimeout = FILLP_DEFAULT_APP_CONNECT_TIMEOUT;
140     g_appResource.common.connRetryTimeout = FILLP_DEFAULT_CONNECT_RETRY_TIMER_INTERVAL;
141     g_appResource.common.disconnectRetryTimeout = FILLP_DEFAULT_DISCONNECT_TIMER_INTERVAL;
142     g_appResource.common.recvBufSize = FILLP_DEFAULT_UDP_RECV_BUFSIZE;
143     g_appResource.common.enableNackDelay = FILLP_DELAY_NACK_ENABLE;
144 
145     g_appResource.common.nackDelayTimeout = FILLP_DEFAULT_NACK_DELAY_TIME;
146     g_appResource.common.enlargePackIntervalFlag = FILLP_DEFAULT_ENLARGE_PACK_INTERVAL;
147     g_appResource.common.enableDateOptTimestamp = FILLP_DEFAULT_DAT_OPT_TIMESTAMP_ENABLE;
148     g_appResource.common.fcStasticsInterval = FILLP_APP_FC_STASTICS_INTERVAL;
149 
150     g_appResource.flowControl.constRateEnbale = FILLP_DEFAULT_CONST_RATE_ENABLE;
151     g_appResource.flowControl.maxRate = FILLP_DEFAULT_MAX_RATE;
152     g_appResource.flowControl.maxRecvRate = FILLP_DEFAULT_MAX_RECV_RATE;
153 
154     g_appResource.flowControl.oppositeSetRate = FILLP_DEFAULT_APP_OPPOSITE_SET_RATE;
155     g_appResource.flowControl.pktSize = FILLP_DEFAULT_APP_PKT_SIZE;
156     g_appResource.flowControl.packInterval = FILLP_DEFAULT_APP_PACK_INTERVAL;
157     g_appResource.flowControl.slowStart = FILLP_DEFAULT_APP_SLOW_START;
158 }
159 
160 /* Free socket */
161 /* This is for socket alloc/initial fail, it is only used before socket created and socket index returned to user */
SockFreeSocket(struct FtSocket * sock)162 void SockFreeSocket(struct FtSocket *sock)
163 {
164     if (sock == FILLP_NULL_PTR) {
165         return;
166     }
167 
168     (void)FillpQueuePush(g_spunge->sockTable->freeQueqe, (void *)&sock, FILLP_FALSE, 1);
169 }
170 
SpungeInitSocket(struct FtSocketTable * table,int tableIndex)171 static int SpungeInitSocket(struct FtSocketTable *table, int tableIndex)
172 {
173     struct FtSocket *sock;
174     FillpErrorType ret;
175     sock = table->sockPool[tableIndex];
176     sock->index = tableIndex;
177     sock->allocState = SOCK_ALLOC_STATE_FREE;
178     sock->inst = SPUNGE_GET_CUR_INSTANCE();
179 
180     /* initialize all locks here */
181     ret = SYS_ARCH_RWSEM_INIT(&sock->sockConnSem);
182     if (ret != ERR_OK) { /* SFT */
183         FILLP_LOGERR("sock_create_conn_sem returns null, ptr socket id:%d", sock->index);
184         return ret;
185     }
186 
187     ret = SYS_ARCH_SEM_INIT(&sock->connBlockSem, 0);
188     if (ret != ERR_OK) { /* SFT */
189         (void)SYS_ARCH_RWSEM_DESTROY(&sock->sockConnSem);
190         return ret;
191     }
192 
193     ret = SYS_ARCH_SEM_INIT(&sock->sockCloseProtect, 0);
194     if (ret != ERR_OK) {
195         (void)SYS_ARCH_RWSEM_DESTROY(&sock->sockConnSem);
196         (void)SYS_ARCH_SEM_DESTROY(&sock->connBlockSem);
197         return ret;
198     }
199     ret = SYS_ARCH_SEM_INIT(&sock->epollTaskListLock, 1);
200     if (ret != FILLP_OK) {
201         (void)SYS_ARCH_RWSEM_DESTROY(&sock->sockConnSem);
202         (void)SYS_ARCH_SEM_DESTROY(&sock->connBlockSem);
203         (void)SYS_ARCH_SEM_DESTROY(&sock->sockCloseProtect);
204         return ret;
205     }
206 
207     /* TAINTED_ANALYSIS TOOL: NULL_RETURNS */
208     if (FillpQueuePush(table->freeQueqe, (void *)&sock, FILLP_TRUE, 1)) {
209         FILLP_LOGERR("FillpQueuePush return error sock->index=%d", sock->index);
210         (void)SYS_ARCH_RWSEM_DESTROY(&sock->sockConnSem);
211         (void)SYS_ARCH_SEM_DESTROY(&sock->connBlockSem);
212         (void)SYS_ARCH_SEM_DESTROY(&sock->sockCloseProtect);
213         (void)SYS_ARCH_SEM_DESTROY(&sock->epollTaskListLock);
214         return FILLP_FAILURE;
215     }
216 
217     return ERR_OK;
218 }
219 
SpungeAllocFtSock(struct FtSocketTable * table)220 static int SpungeAllocFtSock(struct FtSocketTable *table)
221 {
222     struct FtSocket *sock = FILLP_NULL_PTR;
223     int tableIndex;
224     if (table == FILLP_NULL_PTR || table->sockPool == FILLP_NULL_PTR) {
225         return FILLP_FAILURE;
226     }
227 
228     sock = (struct FtSocket *)SpungeAlloc(1, sizeof(struct FtSocket), SPUNGE_ALLOC_TYPE_CALLOC);
229     if (sock == FILLP_NULL_PTR) {
230         return FILLP_FAILURE;
231     }
232 
233     while (FILLP_TRUE) {
234         tableIndex = SYS_ARCH_ATOMIC_READ(&table->used);
235         if (tableIndex >= table->size) {
236             SpungeFree(sock, SPUNGE_ALLOC_TYPE_CALLOC);
237             return FILLP_FAILURE;
238         }
239 
240         if (CAS((volatile FILLP_ULONG *)&table->sockPool[tableIndex], (volatile FILLP_ULONG)FILLP_NULL_PTR,
241             (volatile FILLP_ULONG)sock) == 0) {
242             FILLP_USLEEP(1);
243         } else {
244             break;
245         }
246     }
247 
248     if (SpungeInitSocket(table, tableIndex) != ERR_OK) {
249         table->sockPool[tableIndex] = FILLP_NULL_PTR;
250         SpungeFree(sock, SPUNGE_ALLOC_TYPE_CALLOC);
251         return FILLP_FAILURE;
252     }
253 
254     SYS_ARCH_ATOMIC_INC(&table->used, 1);
255     return FILLP_OK;
256 }
257 
SockAllocSocket(void)258 struct FtSocket *SockAllocSocket(void)
259 {
260     struct FtSocket *sock = FILLP_NULL_PTR;
261     FILLP_INT ret;
262 
263     while (sock == FILLP_NULL_PTR) {
264         ret = FillpQueuePop(g_spunge->sockTable->freeQueqe, (void *)&sock, 1);
265         if (ret <= 0) {
266             FILLP_LOGDBG("sockets not available from the sockTable->freeQueqe");
267 
268             if (SpungeAllocFtSock(g_spunge->sockTable) != FILLP_OK) {
269                 return FILLP_NULL_PTR;
270             }
271         }
272     }
273 
274     return sock;
275 }
276 
SockGetSocket(FILLP_INT sockIndex)277 struct FtSocket *SockGetSocket(FILLP_INT sockIndex)
278 {
279     struct FtSocket *sock = FILLP_NULL_PTR;
280 
281     if ((g_spunge == FILLP_NULL_PTR) || (!g_spunge->hasInited) || (g_spunge->sockTable == FILLP_NULL_PTR)) {
282         FILLP_LOGERR("FILLP Not yet Initialized");
283 
284         return FILLP_NULL_PTR;
285     }
286 
287     if ((sockIndex < 0) || (sockIndex >= SYS_ARCH_ATOMIC_READ(&g_spunge->sockTable->used))) {
288         FILLP_LOGERR("index value not in the socket table size range. Index= %d", sockIndex);
289         return FILLP_NULL_PTR;
290     }
291 
292     sock = g_spunge->sockTable->sockPool[sockIndex];
293 
294     return sock;
295 }
296 
SockApiGetAndCheck(int sockIdx)297 struct FtSocket *SockApiGetAndCheck(int sockIdx)
298 {
299     struct FtSocket *sock = SockGetSocket(sockIdx);
300     if (sock == FILLP_NULL_PTR) {
301         FILLP_LOGERR("Invalid fillp_sock_id:%d", sockIdx);
302         SET_ERRNO(FILLP_EBADF);
303         return FILLP_NULL_PTR;
304     }
305 
306     if (SYS_ARCH_RWSEM_TRYRDWAIT(&sock->sockConnSem) != ERR_OK) {
307         FILLP_LOGERR("sockConnSem rdwait fail fillp_sock_id:%d", sockIdx);
308         SET_ERRNO(FILLP_EBUSY);
309         return FILLP_NULL_PTR;
310     }
311 
312     if (sock->allocState != SOCK_ALLOC_STATE_COMM) {
313         (void)SYS_ARCH_RWSEM_RDPOST(&sock->sockConnSem);
314         FILLP_LOGERR("sock allocState wrong fillp_sock_id:%d, state:%d", sockIdx, sock->allocState);
315         SET_ERRNO(FILLP_ENOTSOCK);
316         return FILLP_NULL_PTR;
317     }
318 
319     return sock;
320 }
321 
SockCanSendData(FILLP_CONST struct FtSocket * sock)322 FILLP_BOOL SockCanSendData(FILLP_CONST struct FtSocket *sock)
323 {
324     if ((sock->netconn == FILLP_NULL_PTR) || (sock->netconn->shutdownWrSet)) {
325         return FILLP_FALSE;
326     }
327 
328     int netConnState = NETCONN_GET_STATE(sock->netconn);
329     if ((netConnState != CONN_STATE_CONNECTED) &&
330         (netConnState != CONN_STATE_CLOSING)) {
331         return FILLP_FALSE;
332     }
333 
334     return FILLP_TRUE;
335 }
336 
SockCanRecvData(struct FtSocket * sock)337 FILLP_BOOL SockCanRecvData(struct FtSocket *sock)
338 {
339     if ((sock->netconn == FILLP_NULL_PTR) || sock->netconn->shutdownRdSet) {
340         return FILLP_FALSE;
341     }
342 
343     int netConnState = NETCONN_GET_STATE(sock->netconn);
344     if ((netConnState != CONN_STATE_CONNECTED) &&
345         (netConnState != CONN_STATE_CLOSING) &&
346         (netConnState != CONN_STATE_CLOSED)) {
347         return FILLP_FALSE;
348     }
349 
350     return FILLP_TRUE;
351 }
352 
SockUpdatePktDataOpt(struct FtSocket * sock,FILLP_UINT16 addFlag,FILLP_UINT16 delFlag)353 FILLP_INT SockUpdatePktDataOpt(struct FtSocket *sock, FILLP_UINT16 addFlag, FILLP_UINT16 delFlag)
354 {
355     FILLP_UINT16 dataOptLen = 0;
356     FILLP_UINT16 dataOptFlag = (sock->dataOptionFlag | addFlag) & ~(delFlag);
357 
358     if (dataOptFlag == 0) {
359         sock->dataOptionFlag = 0;
360         sock->dataOptionSize = 0;
361         return ERR_OK;
362     }
363 
364     if (dataOptFlag & FILLP_OPT_FLAG_TIMESTAMP) {
365         dataOptLen += (FILLP_UINT16)(FILLP_DATA_OPT_HLEN + FILLP_OPT_TIMESTAMP_LEN);
366     }
367 
368     if ((sock->netconn != FILLP_NULL_PTR) && (sock->netconn->pcb != FILLP_NULL_PTR) &&
369         ((FILLP_UINT32)((FILLP_UINT32)dataOptLen + FILLP_DATA_OFFSET_LEN) >= (FILLP_UINT32)SOCK_GET_PKTSIZE(sock))) {
370         FILLP_LOGERR("option length error. sockIndex= %d, dataOptLen:%u greater than pktsize:%zu", sock->index,
371             (FILLP_UINT32)dataOptLen + FILLP_DATA_OFFSET_LEN, SOCK_GET_PKTSIZE(sock));
372         return FILLP_EINVAL;
373     }
374 
375     sock->dataOptionFlag = dataOptFlag;
376     sock->dataOptionSize = dataOptLen;
377     FILLP_LOGINF("fillp_sock_id:%d, dataOptFlag:%x, dataOptionSize:%u", sock->index, dataOptFlag, dataOptLen);
378     return ERR_OK;
379 }
380 
381 #ifdef __cplusplus
382 }
383 #endif
384