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