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