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 "epoll_app.h"
17 #include "spunge_app.h"
18 #include "res.h"
19 #include "fillp_flow_control.h"
20 #include "spunge_message.h"
21 #include "socket_common.h"
22 #include "fillp_common.h"
23 #include "spunge_stack.h"
24 
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28 
SpungeAllocSystemSocket(FILLP_INT domain,FILLP_INT type,FILLP_INT protocol)29 struct SockOsSocket *SpungeAllocSystemSocket(FILLP_INT domain, FILLP_INT type, FILLP_INT protocol)
30 {
31     struct SpungeInstance *curInst = SPUNGE_GET_CUR_INSTANCE();
32     struct SockOsSocket *osSock;
33 
34     osSock = (struct SockOsSocket *)SpungeAlloc(1, sizeof(struct SockOsSocket), SPUNGE_ALLOC_TYPE_CALLOC);
35     if (osSock == FILLP_NULL_PTR) {
36         FILLP_LOGERR("Failed to allocate memory for os socket \r\n");
37         return FILLP_NULL_PTR;
38     }
39 
40     osSock->reference = 0;
41     osSock->addrType = domain;
42 
43     osSock->ioSock = SysIoSocketFactory(domain, type, protocol);
44     if (osSock->ioSock == FILLP_NULL_PTR) {
45         FILLP_LOGERR("Alloc osSock fail");
46         SpungeFree(osSock, SPUNGE_ALLOC_TYPE_CALLOC);
47         osSock = FILLP_NULL_PTR;
48         return osSock;
49     }
50 
51     HLIST_INIT_NODE(&osSock->osListNode);
52     HlistAddTail(&curInst->osSockist, &osSock->osListNode);
53 
54     return osSock;
55 }
56 
SpungeEpollFreeResource(struct FtSocket * sock)57 static void SpungeEpollFreeResource(struct FtSocket *sock)
58 {
59     FILLP_UINT32 i;
60 
61     HLIST_INIT(&sock->epTaskList);
62 
63     if (sock->eventEpoll != FILLP_NULL_PTR) {
64         (void)SYS_ARCH_SEM_DESTROY(&sock->eventEpoll->waitSem);
65 
66         (void)SYS_ARCH_SEM_DESTROY(&sock->eventEpoll->appCoreSem);
67 
68         (void)SYS_ARCH_SEM_DESTROY(&sock->eventEpoll->appSem);
69     }
70 
71     /* Scan the epoll instance list to which this FtSocket is associated with */
72     for (i = 0; i < FILLP_NUM_OF_EPOLL_INSTANCE_SUPPORTED; i++) {
73         /* Delete happens from higher array index to lower array index. So until
74            the 0th index is cleared, continue to remove epoll instance
75         */
76         if (sock->associatedEpollInstanceArr[0] != FILLP_INVALID_INT) {
77             struct FtSocket *epollSock = FILLP_NULL_PTR;
78             FILLP_INT assIdex = sock->associatedEpollInstanceArr[0];
79 
80             if ((assIdex < 0) || (assIdex >= SYS_ARCH_ATOMIC_READ(&g_spunge->sockTable->used))) {
81                 /* Socket index is not in range, skip and continue */
82                 continue;
83             }
84 
85             epollSock = g_spunge->sockTable->sockPool[assIdex];
86 
87             if (epollSock->allocState == SOCK_ALLOC_STATE_FREE) {
88                 SpungeDelEpInstFromFtSocket(sock, assIdex);
89 
90                 /* Socket state is in free state, skip and continue */
91                 continue;
92             }
93 
94             (void)SpungeEpollFindRemove(sock->associatedEpollInstanceArr[0], sock->index);
95         }
96     }
97 
98     sock->associatedEpollInstanceIdx = 0;
99 
100     (void)SYS_ARCH_ATOMIC_SET(&sock->rcvEvent, 0);
101     (void)SYS_ARCH_ATOMIC_SET(&sock->sendEvent, 0);
102     (void)SYS_ARCH_ATOMIC_SET(&sock->sendEventCount, 0);
103     sock->errEvent = 0;
104 }
105 
SpungeFreeAcceptBox(struct FtSocket * sock)106 void SpungeFreeAcceptBox(struct FtSocket *sock)
107 {
108     FILLP_INT i;
109     struct FtNetconn *conn = FILLP_NULL_PTR;
110     int count;
111 
112     for (i = 0; i < SPUNGE_SOCKET_BOX_SIZE; i++) {
113         count = FillpQueuePop(sock->acceptBox, (void *)&conn, 1);
114         if (count > 0) {
115             FillpNetconnDestroy(conn);
116         } else {
117             break;
118         }
119     }
120 
121     FillpQueueDestroy(sock->acceptBox);
122     sock->acceptBox = FILLP_NULL_PTR;
123     return;
124 }
125 
SpungeIncFreeCntPostEagain(struct FtSocket * sock)126 void SpungeIncFreeCntPostEagain(struct FtSocket *sock)
127 {
128     FillpErrorType ret;
129     sock->freeTimeCount++;
130     FILLP_LOGDBG("fillp_sock_id:%d,sock->freeTimeCount:%d, errno:%d",
131         sock->index, sock->freeTimeCount, FT_OS_GET_ERRNO);
132 
133     ret = SpungePostMsg(SPUNGE_GET_CUR_INSTANCE(), (void *)sock, MSG_TYPE_FREE_SOCK_EAGAIN, FILLP_FALSE);
134     if (ret != ERR_OK) {
135         FILLP_LOGERR("FAILED TO POST -- MSG_TYPE_FREE_SOCK_EAGAIN--- to CORE."
136             "Socket leak can happen : Sock ID: %d\r\n", sock->index);
137     }
138 }
139 
RecursiveRbTree(struct RbNode * node)140 static void RecursiveRbTree(struct RbNode *node)
141 {
142     struct RbNode *parent = node;
143     struct EpItem *epi = FILLP_NULL_PTR;
144     struct RbNode *right = FILLP_NULL_PTR;
145     struct FtSocket *sock = FILLP_NULL_PTR;
146     struct RbNode *left = FILLP_NULL_PTR;
147 
148     if (node == FILLP_NULL_PTR) {
149         FILLP_LOGERR("RecursiveRbTree: Inavild parameters passed.");
150         return;
151     }
152 
153     left = (struct RbNode *)(parent->rbLeft);
154 
155     if (left != FILLP_NULL_PTR) {
156         RecursiveRbTree(left);
157     }
158 
159     right = (struct RbNode *)(parent->rbRight);
160     epi = EpItemEntryRbNode(parent);
161     if (epi == FILLP_NULL_PTR) {
162         FILLP_LOGERR("RecursiveRbTree: EpItemEntryRbNode returns NULL. ");
163 
164         return;
165     }
166 
167     sock = SockGetSocket(epi->fileDespcriptor);
168     if (sock != FILLP_NULL_PTR) {
169         (void)SYS_ARCH_ATOMIC_DEC(&sock->epollWaiting, 1);
170 
171         if (SYS_ARCH_SEM_WAIT(&sock->epollTaskListLock)) {
172             FILLP_LOGERR("Error to wait epoll_task_list");
173             return;
174         }
175         HlistDelNode(&epi->sockWaitNode);
176         DympFree(epi);
177         (void)SYS_ARCH_SEM_POST(&sock->epollTaskListLock);
178     }
179 
180     if (right != FILLP_NULL_PTR) {
181         RecursiveRbTree(right);
182     }
183 }
184 
185 /*
186  * @Description : Closes the epoll socket and releases all associated resources.
187  * @param : epoll ft sock index
188  * @return : success: ERR_OK  fail: error code
189  * @NOTE: caller must have acquired (wait) the close semaphore to protect from MT scenarios. this
190  * function on completion will post the event back to semaphore once execution is completed.
191  */
SpungEpollClose(struct FtSocket * sock)192 void SpungEpollClose(struct FtSocket *sock)
193 {
194     struct EventPoll *ep = (sock->eventEpoll);
195     struct RbRoot rtNoe;
196     struct RbNode *parent = FILLP_NULL_PTR;
197     SYS_ARCH_RW_SEM *sockConnSem = &sock->sockConnSem;
198 
199     if (ep == FILLP_NULL_PTR) {
200         sock->allocState = SOCK_ALLOC_STATE_FREE;
201         FILLP_LOGERR("eventEpoll is NULL. fillp_sock_id:%d", sock->index);
202         return;
203     }
204 
205     if (SYS_ARCH_RWSEM_TRYWRWAIT(sockConnSem) != ERR_OK) {
206         int ret;
207         sock->allocState = SOCK_ALLOC_STATE_EPOLL_TO_CLOSE;
208         (void)SYS_ARCH_SEM_POST(&ep->waitSem);
209         ret = SpungePostMsg(SPUNGE_GET_CUR_INSTANCE(), (void *)sock, MSG_TYPE_FREE_SOCK_EAGAIN, FILLP_FALSE);
210         if (ret != ERR_OK) {
211             FILLP_LOGERR("FAILED TO POST -- MSG_TYPE_FREE_SOCK_EAGAIN--- to CORE."
212                 "Socket leak can happen : Sock ID: %d", sock->index);
213         }
214         return;
215     }
216 
217     rtNoe = ep->rbr;
218     parent = rtNoe.rbNode;
219     if (parent != FILLP_NULL_PTR) {
220         RecursiveRbTree(parent);
221     }
222 
223     SpungeEpollFreeResource(sock);
224 
225     DympFree(sock->eventEpoll);
226     sock->eventEpoll = FILLP_NULL_PTR;
227 
228     sock->flags = 0;
229     sock->traceFlag = 0;
230     sock->allocState = SOCK_ALLOC_STATE_FREE;
231     sock->freeTimeCount = FILLP_NULL_NUM;
232     (void)SYS_ARCH_RWSEM_WRPOST(&sock->sockConnSem);
233 
234     (void)FillpQueuePush(g_spunge->sockTable->freeQueqe, (void *)&sock, FILLP_FALSE, 1);
235 }
236 
SpungeCloseCBSocket(struct FtSocket * sock)237 static void SpungeCloseCBSocket(struct FtSocket *sock)
238 {
239     if ((FILLP_SOCKETCLOSE_CBK != FILLP_NULL_PTR) && (sock->isListenSock == FILLP_FALSE) &&
240         (sock->netconn != FILLP_NULL_PTR) && (sock->netconn->pcb != FILLP_NULL_PTR) &&
241         (sock->netconn->state == CONN_STATE_CLOSED)) {
242         SysIoUdpSock *udpSock = FILLP_NULL_PTR;
243         struct SockOsSocket *osSock = NETCONN_GET_OSSOCK(sock->netconn, sock->inst->instIndex);
244         if (osSock != FILLP_NULL_PTR) {
245             udpSock = (SysIoUdpSock *)osSock->ioSock;
246             FILLP_SOCKETCLOSE_CBK(udpSock->udpSock, (struct sockaddr *)&sock->netconn->pcb->localAddr,
247                 (struct sockaddr *)&sock->netconn->pcb->remoteAddr);
248         }
249     }
250 }
251 
SpungeFreeSock(struct FtSocket * sock)252 void SpungeFreeSock(struct FtSocket *sock)
253 {
254     if ((sock == FILLP_NULL_PTR) || (sock->allocState == SOCK_ALLOC_STATE_FREE)) {
255         return;
256     }
257 
258     FILLP_LOGDTL("fillp_sock_id:%d", sock->index);
259     FillpErrorType ret = SYS_ARCH_RWSEM_TRYWRWAIT(&sock->sockConnSem);
260     if (ret != ERR_OK) {
261         SpungeIncFreeCntPostEagain(sock);
262         return;
263     }
264 
265     if (sock->allocState != SOCK_ALLOC_STATE_EPOLL) {
266         if ((sock->netconn != FILLP_NULL_PTR) && !SpungeConnCheckUnsendBoxEmpty(sock->netconn)) {
267             FILLP_LOGDBG("Unsend Box still not empty, fillp_sock_id:%d", sock->index);
268             SpungeIncFreeCntPostEagain(sock);
269             (void)SYS_ARCH_RWSEM_WRPOST(&sock->sockConnSem);
270             return;
271         }
272     }
273 
274     FILLP_LOGINF("spunge_free_start, fillp_sock_id:%d", sock->index);
275     SpungeCloseCBSocket(sock);
276     SpungeEpollFreeResource(sock);
277 
278     if (sock->netconn != FILLP_NULL_PTR) {
279         struct SockOsSocket *osSock = NETCONN_GET_OSSOCK(sock->netconn, sock->inst->instIndex);
280         if (OS_SOCK_OPS_FUNC_VALID(osSock, freeSock)) {
281             osSock->ioSock->ops->freeSock((void *)sock, (void *)osSock);
282         }
283         FillpNetconnDestroy(sock->netconn);
284         sock->netconn = FILLP_NULL_PTR;
285     }
286 
287     if (sock->acceptBox != FILLP_NULL_PTR) {
288         SpungeFreeAcceptBox(sock);
289     }
290 
291     sock->flags = 0;
292     sock->traceFlag = 0;
293     if (sock->isListenSock == FILLP_TRUE) {
294         (void)SYS_ARCH_SEM_DESTROY(&sock->acceptSem);
295         sock->isListenSock = FILLP_FALSE;
296     }
297 
298     sock->allocState = SOCK_ALLOC_STATE_FREE;
299     sock->freeTimeCount = FILLP_NULL_NUM;
300 
301     (void)FillpQueuePush(g_spunge->sockTable->freeQueqe, (void *)&sock, FILLP_FALSE, 1);
302     (void)SYS_ARCH_RWSEM_WRPOST(&sock->sockConnSem);
303 }
304 
SpungeShutdownSock(void * argSock,FILLP_INT how)305 void SpungeShutdownSock(void *argSock, FILLP_INT how)
306 {
307     struct FtSocket *sock = (struct FtSocket *)argSock;
308     struct FtNetconn *netconn = sock->netconn;
309     FILLP_INT connState;
310 
311     if (netconn == FILLP_NULL_PTR) {
312         FILLP_LOGERR("sock->netconn is NULL");
313         return;
314     }
315 
316     connState = NETCONN_GET_STATE(netconn);
317     FILLP_LOGINF("Shutdown,fillp_sock_id:%d,connState:%d", sock->index, connState);
318 
319     if (((how == SPUNGE_SHUT_RD) || (how == SPUNGE_SHUT_RDWR)) && !netconn->shutdownRdSet) {
320         netconn->shutdownRdSet = 1;
321 #ifdef SOCK_RECV_SEM
322         (void)SYS_ARCH_SEM_POST(&SOCK_GET_RECVSEM(sock));
323 #endif /* SOCK_RECV_SEM */
324 
325         if (sock->isListenSock == FILLP_TRUE) {
326             (void)SYS_ARCH_SEM_POST(&sock->acceptSem);
327         }
328     }
329 
330     if (((how == SPUNGE_SHUT_WR) || (how == SPUNGE_SHUT_RDWR)) && !netconn->shutdownWrSet) {
331         netconn->shutdownWrSet = 1;
332         (void)SYS_ARCH_SEM_POST(&SOCK_GET_SENDSEM(sock));
333     }
334 }
335 
SpungeConnCheckUnsendBoxEmpty(struct FtNetconn * conn)336 FILLP_BOOL SpungeConnCheckUnsendBoxEmpty(struct FtNetconn *conn)
337 {
338     FILLP_ULLONG con;
339     FILLP_ULLONG prod;
340     void *data = FILLP_NULL_PTR;
341     struct FillpPcbItem *item = FILLP_NULL_PTR;
342     FillpQueue *unsendBox = FILLP_NULL_PTR;
343 
344     if ((conn == FILLP_NULL_PTR) || (conn->pcb == FILLP_NULL_PTR)) {
345         FILLP_LOGERR("NULL Pointer");
346         return FILLP_TRUE;
347     }
348     unsendBox = conn->pcb->fpcb.send.unsendBox;
349 
350     if (unsendBox == FILLP_NULL_PTR) {
351         return FILLP_TRUE;
352     }
353 
354     con = unsendBox->ring.cons.head + 1;
355     prod = unsendBox->ring.prod.tail;
356 
357     while ((prod >= con) && ((FILLP_LLONG)(prod - con)) >= 0) {
358         data = unsendBox->ring.ringCache[con % unsendBox->ring.size];
359         con++;
360 
361         if (data == FILLP_NULL_PTR) {
362             continue;
363         }
364 
365         item = (struct FillpPcbItem *)data;
366         if (item->netconn == (void *)conn) {
367             FILLP_LOGDBG("Still has data in unsedn box");
368             return FILLP_FALSE;
369         }
370     }
371 
372     return FILLP_TRUE;
373 }
374 
SpungeDestroyNoWait(struct FillpPcb * pcb,struct FtSocket * sock,struct FtNetconn * conn)375 static int SpungeDestroyNoWait(struct FillpPcb *pcb, struct FtSocket *sock, struct FtNetconn *conn)
376 {
377 #if FILLP_DEFAULT_DESTROY_STACK_WITHOUT_WAIT_SOCKET_CLOSE
378     /* for miracast, ignore the unSend unAck and unRecv packets, skip the disconnection flow,
379         because app will call FtClose once wifi disconnect, stack can't free socket until
380         10s keep alive timeout. That would lead FtDestroy block a long time. */
381     if (pcb->pcbInst->waitTobeCoreKilled == FILLP_TRUE) {
382         FILLP_LOGERR("ignore unsend packet, skip dissconnetion flow and about to free socket %d", sock->index);
383         SpungeConnClosed(conn);
384         return 1;
385     }
386 #endif
387     return 0;
388 }
389 
SpungeCheckDisconn(void * argConn)390 void SpungeCheckDisconn(void *argConn)
391 {
392     struct FtNetconn *conn = (struct FtNetconn *)argConn;
393     struct FtSocket *sock = (struct FtSocket *)conn->sock;
394     struct FillpPcb *pcb = FILLP_NULL_PTR;
395     FILLP_UINT8 connState;
396     struct FillpSendPcb *sendPcb = FILLP_NULL_PTR;
397 
398     if (sock == FILLP_NULL_PTR || conn->pcb == FILLP_NULL_PTR) {
399         FILLP_LOGERR("NULL pointer sock or conn->pcb");
400         return;
401     }
402 
403     pcb = &conn->pcb->fpcb;
404 
405     connState = NETCONN_GET_STATE(conn);
406     FILLP_LOGDBG("fillp_sock_id:%d", sock->index);
407     if (!(connState == CONN_STATE_CONNECTED || connState == CONN_STATE_CLOSING)) {
408         FILLP_LOGERR("No need to check disconn message anymore,fillp_sock_id:%d,connState:%u",
409             sock->index, connState);
410         return;
411     }
412 
413     if (connState == CONN_STATE_CONNECTED) {
414         /* Check all unsend box */
415         if (!SpungeConnCheckUnsendBoxEmpty(conn)) {
416             goto TIMER_REPEAT;
417         }
418 
419         if (SpungeDestroyNoWait(pcb, sock, conn) != 0) {
420             return;
421         }
422         /* Check if all send data are sent out */
423         sendPcb = &conn->pcb->fpcb.send;
424         FillpAckSendPcb(&conn->pcb->fpcb, 0);
425 
426         if ((sock->lingering == FILLP_FALSE) && (sendPcb->unackList.count ||
427             sendPcb->unrecvList.nodeNum || !HLIST_EMPTY(&sendPcb->unSendList) ||
428             sendPcb->itemWaitTokenLists.nodeNum || sendPcb->redunList.nodeNum)) {
429             FILLP_LOGDBG("Still has data to send");
430             goto TIMER_REPEAT;
431         }
432 
433         FILLP_LOGINF("Now all unSend data are checked.Going to send fin fillp_sock_id:%d", sock->index);
434         conn->sendBufRunOut = FILLP_TRUE;
435         /* Need to reconsider the disconn message send */
436         FillpNetconnSetState(conn, CONN_STATE_CLOSING);
437         pcb->finCheckTimer.interval =
438             (FILLP_UINT32)FILLP_UTILS_MS2US((FILLP_LLONG)sock->resConf.common.disconnectRetryTimeout);
439     } else if (SpungeDestroyNoWait(pcb, sock, conn) != 0) {
440         return;
441     }
442 
443     if (pcb->isFinAckReceived != FILLP_TRUE) {
444         FillpSendFin(pcb);
445     }
446 
447 TIMER_REPEAT:
448     FillpEnableFinCheckTimer(pcb);
449 }
450 
SpungeSendConnectMsg(void * argConn)451 void SpungeSendConnectMsg(void *argConn)
452 {
453     struct FtNetconn *conn = (struct FtNetconn *)argConn;
454     struct FtSocket *sock = (struct FtSocket *)conn->sock;
455     struct SockOsSocket *osSock = FILLP_NULL_PTR;
456     FILLP_UINT8 connState = NETCONN_GET_STATE(conn);
457     if (connState != CONN_STATE_CONNECTING) {
458         FILLP_LOGINF("socket state = %u is not in connecting state for the conn",
459             connState);
460         return;
461     }
462 
463     if (NetconnIsConnectTimeout(conn)) {
464         if (sock == FILLP_NULL_PTR) {
465             FILLP_LOGWAR("connection state idle for the conn");
466 
467             /* No need to stop the conenct timer again, as it is already stopped upon earlier socket_clear */
468             return;
469         }
470 
471         FillpNetconnSetState(conn, CONN_STATE_IDLE);
472         SET_ERRNO(FILLP_ETIMEDOUT);
473         sock->coreErrType[MSG_TYPE_DO_CONNECT] = ERR_CONN_TIMEOUT;
474         if (SOCK_IS_NONBLOCKING(sock)) {
475             FILLP_SOCK_SET_ERR(sock, FILLP_ECONNREFUSED);
476             FillpNetconnSetSafeErr(conn, ERR_CONNREFUSED);
477         } else {
478             FillpNetconnSetSafeErr(conn, ERR_CONN_TIMEOUT);
479         }
480 
481         SpungeConnConnectFail(conn->sock);
482 
483         return;
484     }
485 
486     FillpEnableConnRetryCheckTimer(&conn->pcb->fpcb);
487 
488     osSock = NETCONN_GET_OSSOCK(conn, SPUNGE_GET_CUR_INSTANCE()->instIndex);
489     if (!OS_SOCK_OPS_FUNC_VALID(osSock, connected) || !OS_SOCK_OPS_FUNC_VALID(osSock, sendPacket)) {
490         FILLP_LOGERR("osSock is NULL");
491         return;
492     }
493     osSock->ioSock->ops->connected(sock, osSock->ioSock);
494     if (osSock->ioSock->ops->sendPacket(
495         FILLP_PKT_TYPE_CONN_REQ, (void *)osSock->ioSock, (void *)conn->pcb, FILLP_NULL_PTR) == -1) {
496         FILLP_LOGINF("send conn req fail for sockId:%d", sock->index);
497     }
498 }
499 
SpinstAddToPcbList(struct SpungeInstance * inst,struct HlistNode * node)500 void SpinstAddToPcbList(struct SpungeInstance *inst, struct HlistNode *node)
501 {
502     HlistAddTail(&inst->pcbList.list, node);
503 }
504 
SpinstDeleteFromPcbList(struct SpungeInstance * inst,struct HlistNode * node)505 void SpinstDeleteFromPcbList(struct SpungeInstance *inst, struct HlistNode *node)
506 {
507     HlistDelete(&inst->pcbList.list, node);
508 }
509 
SpungeAllocUnsendBox(struct SpungeInstance * inst)510 FillpQueue *SpungeAllocUnsendBox(struct SpungeInstance *inst)
511 {
512     return inst->unsendBox[0];
513 }
514 
SpungeFreeUnsendBox(struct FillpPcb * pcb)515 void SpungeFreeUnsendBox(struct FillpPcb *pcb)
516 {
517     FILLP_UNUSED_PARA(pcb);
518 }
519 
520 /* This function is called when the connection is sure closed
521     For : 1) close() involked and rst send out
522           2) recved rst from peer
523           3) disconnect send out and disconn recved (local and peer send disconnect both)
524           if close() involked, the recv box data will be dropped, or the recv() still returns positive if data remains,
525           return 0 if all data taken
526  */
SpungeConnClosed(struct FtNetconn * conn)527 void SpungeConnClosed(struct FtNetconn *conn)
528 {
529     if (NETCONN_GET_STATE(conn) == CONN_STATE_CLOSED) {
530         FILLP_LOGERR("Already closed");
531         return;
532     }
533 
534     if (conn->sock == FILLP_NULL_PTR) {
535         FILLP_LOGERR("conn socket is NULL");
536         return;
537     }
538 
539     if (conn->pcb == FILLP_NULL_PTR) {
540         FILLP_LOGERR("conn pcb is NULL");
541         return;
542     }
543 
544     FILLP_LOGINF("fillp_sock_id:%d", ((struct FtSocket *)conn->sock)->index);
545 
546     FillpNetconnSetState(conn, CONN_STATE_CLOSED);
547     FillpPcbRemoveTimers(&conn->pcb->fpcb);
548 
549     if (conn->closeSet) {
550         /* Try to release the recv box data */
551         if (SpungePostMsg(SPUNGE_GET_CUR_INSTANCE(), (void *)((struct FtSocket *)conn->sock),
552             MSG_TYPE_FREE_SOCK_EAGAIN, FILLP_FALSE) != ERR_OK) {
553             FILLP_LOGERR("FAILED TO POST -- MSG_TYPE_FREE_SOCK_EAGAIN--- to CORE"
554                          " Sock ID: %d", ((struct FtSocket*)conn->sock)->index);
555         }
556     }
557 }
558 
SpungeConnConnectSuccess(void * argSock)559 void SpungeConnConnectSuccess(void *argSock)
560 {
561     struct FtSocket *sock = (struct FtSocket *)argSock;
562     if (!SOCK_IS_NONBLOCKING(sock)) {
563         (void)SYS_ARCH_SEM_POST(&sock->connBlockSem);
564     }
565 
566     sock->errEvent = 0;
567     SpungeEpollEventCallback(sock, SPUNGE_EPOLLOUT, 1);
568 }
569 
SpungeConnConnectFail(void * argSock)570 void SpungeConnConnectFail(void *argSock)
571 {
572     struct FtSocket *sock = (struct FtSocket *)argSock;
573     if (!SOCK_IS_NONBLOCKING(sock)) {
574         (void)SYS_ARCH_SEM_POST(&sock->connBlockSem);
575     }
576     sock->errEvent |= (FILLP_UINT32)SPUNGE_EPOLLHUP;
577     SpungeEpollEventCallback(sock, (FILLP_INT)SPUNGE_EPOLLOUT | (FILLP_INT)SPUNGE_EPOLLHUP, 1);
578 }
579 
580 #ifdef __cplusplus
581 }
582 #endif
583