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