1 /*
2  * sl_socket.c - CC31xx/CC32xx Host Driver Implementation
3  *
4  * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
5  *
6  *
7  *  Redistribution and use in source and binary forms, with or without
8  *  modification, are permitted provided that the following conditions
9  *  are met:
10  *
11  *    Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *
14  *    Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the
17  *    distribution.
18  *
19  *    Neither the name of Texas Instruments Incorporated nor the names of
20  *    its contributors may be used to endorse or promote products derived
21  *    from this software without specific prior written permission.
22  *
23  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  *
35 */
36 
37 
38 /*****************************************************************************/
39 /* Include files                                                             */
40 /*****************************************************************************/
41 #include <ti/drivers/net/wifi/simplelink.h>
42 #include <ti/drivers/net/wifi/source/protocol.h>
43 #include <ti/drivers/net/wifi/source/driver.h>
44 #include <ti/drivers/net/wifi/eventreg.h>
45 
46 static void     _SlSocketBuildAddress(const SlSockAddr_t *addr, SlSocketAddrCommand_u    *pCmd);
47 _SlReturnVal_t  _SlSocketHandleAsync_Connect(void *pVoidBuf);
48 _SlReturnVal_t _SlSocketHandleAsync_Close(void *pVoidBuf);
49 
50 void             _SlSocketParseAddress(SlSocketAddrResponse_u *pRsp, SlSockAddr_t *addr, SlSocklen_t *addrlen);
51 _SlReturnVal_t   _SlSocketHandleAsync_Accept(void *pVoidBuf);
52 _SlReturnVal_t   _SlSocketHandleAsync_Select(void *pVoidBuf);
53 _SlReturnVal_t   _SlSocketHandleAsync_StartTLS(void *pVoidBuf);
54 
55 #if (defined(SL_PLATFORM_MULTI_THREADED) && !defined(slcb_SocketTriggerEventHandler))
56 static _i16      _SlDrvClearCtrlSocket(void);
57 static _i8       _SlDrvGetNextTimeoutValue(void);
58 #endif
59 
60 /*******************************************************************************/
61 /* Functions                                                                   */
62 /*******************************************************************************/
63 
64 
65 /* ******************************************************************************/
66 /*  _SlSocketBuildAddress */
67 /* ******************************************************************************/
_SlSocketBuildAddress(const SlSockAddr_t * addr,SlSocketAddrCommand_u * pCmd)68 static void _SlSocketBuildAddress(const SlSockAddr_t *addr, SlSocketAddrCommand_u    *pCmd)
69 {
70 
71     /* Note: parsing of family and port in the generic way for all IPV4, IPV6 and EUI48
72              is possible as long as these parameters are in the same offset and size for these
73              three families. */
74     pCmd->IpV4.FamilyAndFlags = (_u8)((addr->sa_family << 4) & 0xF0);
75     pCmd->IpV4.Port = ((SlSockAddrIn_t *)addr)->sin_port;
76 
77     if(SL_AF_INET == addr->sa_family)
78     {
79         pCmd->IpV4.Address  = ((SlSockAddrIn_t *)addr)->sin_addr.s_addr;
80     }
81 #ifdef SL_SUPPORT_IPV6
82     else
83     {
84         sl_Memcpy(pCmd->IpV6.Address, ((SlSockAddrIn6_t *)addr)->sin6_addr._S6_un._S6_u32, 16 );
85     }
86 #endif
87 }
88 
89 /*******************************************************************************/
90 /*  _SlSocketParseAddress */
91 /*******************************************************************************/
_SlSocketParseAddress(SlSocketAddrResponse_u * pRsp,SlSockAddr_t * addr,SlSocklen_t * addrlen)92 void _SlSocketParseAddress(SlSocketAddrResponse_u    *pRsp, SlSockAddr_t *addr, SlSocklen_t *addrlen)
93 {
94     /*  Note: parsing of family and port in the generic way for all IPV4, IPV6 and EUI48 */
95     /*  is possible as long as these parameters are in the same offset and size for these */
96     /*  three families. */
97     addr->sa_family                    = pRsp->IpV4.Family;
98     ((SlSockAddrIn_t *)addr)->sin_port = pRsp->IpV4.Port;
99 
100     *addrlen = (SL_AF_INET == addr->sa_family) ? sizeof(SlSockAddrIn_t) : sizeof(SlSockAddrIn6_t);
101 
102     if(SL_AF_INET == addr->sa_family)
103     {
104         ((SlSockAddrIn_t *)addr)->sin_addr.s_addr  = pRsp->IpV4.Address;
105     }
106 #ifdef SL_SUPPORT_IPV6
107     else
108     {
109          sl_Memcpy(((SlSockAddrIn6_t *)addr)->sin6_addr._S6_un._S6_u32, pRsp->IpV6.Address, 16);
110     }
111 #endif
112 }
113 
114 /*******************************************************************************/
115 /* sl_Socket */
116 /*******************************************************************************/
117 typedef union
118 {
119     _u32                Dummy;
120     SlSocketCommand_t   Cmd;
121     SlSocketResponse_t  Rsp;
122 }_SlSockSocketMsg_u;
123 
124 #if _SL_INCLUDE_FUNC(sl_Socket)
125 
126 static const _SlCmdCtrl_t _SlSockSocketCmdCtrl =
127 {
128     SL_OPCODE_SOCKET_SOCKET,
129     (_SlArgSize_t)sizeof(SlSocketCommand_t),
130     (_SlArgSize_t)sizeof(SlSocketResponse_t)
131 };
132 
sl_Socket(_i16 Domain,_i16 Type,_i16 Protocol)133 _i16 sl_Socket(_i16 Domain, _i16 Type, _i16 Protocol)
134 {
135     _SlSockSocketMsg_u  Msg;
136 
137     Msg.Cmd.Domain       = (_u8)Domain;
138     Msg.Cmd.Type         = (_u8)Type;
139     Msg.Cmd.Protocol     = (_u8)Protocol;
140 
141     /* verify that this api is allowed. if not allowed then
142     ignore the API execution and return immediately with an error */
143     VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
144 
145     VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSockSocketCmdCtrl, &Msg, NULL));
146 
147     if( Msg.Rsp.StatusOrLen < 0 )
148     {
149         return ( Msg.Rsp.StatusOrLen);
150     }
151     else
152     {
153         return (_i16)((_u8)Msg.Rsp.Sd);
154     }
155 }
156 #endif
157 
158 /*******************************************************************************/
159 /*  sl_Close  */
160 /*******************************************************************************/
161 typedef union
162 {
163     SlCloseCommand_t    Cmd;
164     SlSocketResponse_t  Rsp;
165 }_SlSockCloseMsg_u;
166 
167 #if _SL_INCLUDE_FUNC(sl_Close)
168 
169 static const _SlCmdCtrl_t _SlSockCloseCmdCtrl =
170 {
171     SL_OPCODE_SOCKET_CLOSE,
172     (_SlArgSize_t)sizeof(SlCloseCommand_t),
173     (_SlArgSize_t)sizeof(SlSocketResponse_t)
174 };
175 
sl_Close(_i16 sd)176 _i16 sl_Close(_i16 sd)
177 {
178     _SlSockCloseMsg_u    Msg;
179     _i16                 ObjIdx = MAX_CONCURRENT_ACTIONS;
180     SlSocketResponse_t   AsyncRsp;
181     _SlReturnVal_t       RetVal;
182     _u8                  bSocketInAction = FALSE;
183 
184     /* verify that this api is allowed. if not allowed then
185     ignore the API execution and return immediately with an error */
186     VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
187 
188     Msg.Cmd.Sd = (_u8)sd;
189     _SlDrvMemZero(&AsyncRsp, sizeof(SlSocketResponse_t));
190 
191     /* check if the socket has already action in progress */
192     bSocketInAction = !!(g_pCB->ActiveActionsBitmap & (1<<sd));
193 
194     if (bSocketInAction == FALSE)
195     {
196         ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&AsyncRsp, CLOSE_ID, (_u8)(sd  & SL_BSD_SOCKET_ID_MASK));
197 
198         if (ObjIdx < 0)
199         {
200             return ObjIdx;
201         }
202     }
203 
204     VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSockCloseCmdCtrl, &Msg, NULL));
205 
206     RetVal = Msg.Rsp.StatusOrLen;
207 
208     if (bSocketInAction == FALSE)
209     {
210         if( SL_RET_CODE_OK == RetVal)
211         {
212             RetVal = _SlDrvWaitForInternalAsyncEvent(ObjIdx, SL_DRIVER_TIMEOUT_LONG, SL_OPCODE_SOCKET_SOCKETCLOSEASYNCEVENT);
213 
214             if(RetVal >= 0)
215             {
216                 RetVal = AsyncRsp.StatusOrLen;
217             }
218         }
219 
220         _SlDrvReleasePoolObj(ObjIdx);
221     }
222 
223     return RetVal;
224 }
225 #endif
226 
227 /*******************************************************************************/
228 /*  sl_Bind */
229 /*******************************************************************************/
230 typedef union
231 {
232     SlSocketAddrCommand_u    Cmd;
233     SlSocketResponse_t       Rsp;
234 }_SlSockBindMsg_u;
235 
236 #if _SL_INCLUDE_FUNC(sl_Bind)
sl_Bind(_i16 sd,const SlSockAddr_t * addr,_i16 addrlen)237 _i16 sl_Bind(_i16 sd, const SlSockAddr_t *addr, _i16 addrlen)
238 {
239     _SlSockBindMsg_u    Msg;
240     _SlCmdCtrl_t        CmdCtrl = {0, 0, (_SlArgSize_t)sizeof(SlSocketResponse_t)};
241 
242     /* verify that this api is allowed. if not allowed then
243     ignore the API execution and return immediately with an error */
244     VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
245 
246     switch(addr->sa_family)
247     {
248         case SL_AF_INET:
249             CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND;
250             CmdCtrl.TxDescLen = (_SlArgSize_t)sizeof(SlSocketAddrIPv4Command_t);
251             break;
252 #ifdef SL_SUPPORT_IPV6
253         case SL_AF_INET6:
254             CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND_V6;
255             CmdCtrl.TxDescLen = (_SlArgSize_t)sizeof(SlSocketAddrIPv6Command_t);
256             break;
257 #endif
258         case SL_AF_RF:
259         default:
260             return SL_RET_CODE_INVALID_INPUT;
261     }
262 
263     Msg.Cmd.IpV4.LenOrPadding = 0;
264     Msg.Cmd.IpV4.Sd = (_u8)sd;
265 
266     _SlSocketBuildAddress(addr, &Msg.Cmd);
267     VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&CmdCtrl, &Msg, NULL));
268 
269     return Msg.Rsp.StatusOrLen;
270 }
271 #endif
272 
273 /*******************************************************************************/
274 /*  sl_Sendto */
275 /*******************************************************************************/
276 typedef union
277 {
278     SlSocketAddrCommand_u    Cmd;
279     /*  no response for 'sendto' commands*/
280 }_SlSendtoMsg_u;
281 
282 #if _SL_INCLUDE_FUNC(sl_SendTo)
sl_SendTo(_i16 sd,const void * pBuf,_i16 Len,_i16 flags,const SlSockAddr_t * to,SlSocklen_t tolen)283 _i16 sl_SendTo(_i16 sd, const void *pBuf, _i16 Len, _i16 flags, const SlSockAddr_t *to, SlSocklen_t tolen)
284 {
285     _SlSendtoMsg_u   Msg;
286     _SlCmdCtrl_t     CmdCtrl = {0, 0, 0};
287     _SlCmdExt_t      CmdExt;
288     _i16             RetVal;
289 
290     /* verify that this api is allowed. if not allowed then
291     ignore the API execution and return immediately with an error */
292     VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
293    /* RAW transceiver use only sl_Send  */
294     if ((sd & SL_SOCKET_PAYLOAD_TYPE_MASK) == SL_SOCKET_PAYLOAD_TYPE_RAW_TRANCEIVER)
295     {
296         return SL_ERROR_BSD_SOC_ERROR;
297     }
298     else
299     {
300         if (Len < 1)
301         {
302             /* ignore */
303             return 0;
304         }
305     }
306 
307     _SlDrvResetCmdExt(&CmdExt);
308     CmdExt.TxPayload1Len = (_u16)Len;
309     CmdExt.pTxPayload1 = (_u8 *)pBuf;
310 
311     switch(to->sa_family)
312     {
313         case SL_AF_INET:
314             CmdCtrl.Opcode = SL_OPCODE_SOCKET_SENDTO;
315             CmdCtrl.TxDescLen = (_SlArgSize_t)sizeof(SlSocketAddrIPv4Command_t);
316             break;
317 #ifdef SL_SUPPORT_IPV6
318         case SL_AF_INET6:
319             CmdCtrl.Opcode = SL_OPCODE_SOCKET_SENDTO_V6;
320             CmdCtrl.TxDescLen = (_SlArgSize_t)sizeof(SlSocketAddrIPv6Command_t);
321             break;
322 #endif
323         case SL_AF_RF:
324         default:
325             return SL_RET_CODE_INVALID_INPUT;
326     }
327 
328     Msg.Cmd.IpV4.LenOrPadding = Len;
329     Msg.Cmd.IpV4.Sd = (_u8)sd;
330     _SlSocketBuildAddress(to, &Msg.Cmd);
331     Msg.Cmd.IpV4.FamilyAndFlags |= flags & 0x0F;
332 
333     RetVal = _SlDrvDataWriteOp((_SlSd_t)sd, &CmdCtrl, &Msg, &CmdExt);
334     if(SL_OS_RET_CODE_OK != RetVal)
335     {
336         return RetVal;
337     }
338 
339     return (_i16)Len;
340 }
341 #endif
342 
343 /*******************************************************************************/
344 /*  sl_Recvfrom */
345 /*******************************************************************************/
346 typedef union
347 {
348     SlSendRecvCommand_t       Cmd;
349     SlSocketAddrResponse_u    Rsp;
350 }_SlRecvfromMsg_u;
351 
352 static const _SlCmdCtrl_t _SlRecvfomCmdCtrl =
353 {
354     SL_OPCODE_SOCKET_RECVFROM,
355     (_SlArgSize_t)sizeof(SlSendRecvCommand_t),
356     (_SlArgSize_t)sizeof(SlSocketAddrResponse_u)
357 };
358 
359 #if _SL_INCLUDE_FUNC(sl_RecvFrom)
sl_RecvFrom(_i16 sd,void * buf,_i16 Len,_i16 flags,SlSockAddr_t * from,SlSocklen_t * fromlen)360 _i16 sl_RecvFrom(_i16 sd, void *buf, _i16 Len, _i16 flags, SlSockAddr_t *from, SlSocklen_t *fromlen)
361 {
362     _SlRecvfromMsg_u    Msg;
363     _SlCmdExt_t         CmdExt;
364     _i16                RetVal;
365 
366     /* verify that this api is allowed. if not allowed then
367     ignore the API execution and return immediately with an error */
368     VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
369 
370     /* RAW transceiver use only sl_Recv  */
371     if ((sd & SL_SOCKET_PAYLOAD_TYPE_MASK) == SL_SOCKET_PAYLOAD_TYPE_RAW_TRANCEIVER)
372     {
373         return SL_ERROR_BSD_SOC_ERROR;
374     }
375 
376     _SlDrvResetCmdExt(&CmdExt);
377     CmdExt.RxPayloadLen = Len;
378     CmdExt.pRxPayload = (_u8 *)buf;
379 
380     Msg.Cmd.Sd = (_u8)sd;
381     Msg.Cmd.StatusOrLen = (_u16)Len;
382 
383     /*  no size truncation in recv path */
384     CmdExt.RxPayloadLen = (_i16)Msg.Cmd.StatusOrLen;
385 
386     Msg.Cmd.FamilyAndFlags = (_u8)(flags & 0x0F);
387 
388     if(sizeof(SlSockAddrIn_t) == *fromlen)
389     {
390         Msg.Cmd.FamilyAndFlags |= (SL_AF_INET << 4);
391     }
392     else if (sizeof(SlSockAddrIn6_t) == *fromlen)
393     {
394         Msg.Cmd.FamilyAndFlags |= (SL_AF_INET6 << 4);
395     }
396     else
397     {
398         return SL_RET_CODE_INVALID_INPUT;
399     }
400 
401     RetVal = _SlDrvDataReadOp((_SlSd_t)sd, (_SlCmdCtrl_t *)&_SlRecvfomCmdCtrl, &Msg, &CmdExt);
402     if( RetVal != SL_OS_RET_CODE_OK )
403     {
404         return RetVal;
405     }
406 
407     RetVal = Msg.Rsp.IpV4.StatusOrLen;
408 
409     if(RetVal >= 0)
410     {
411         VERIFY_PROTOCOL(sd == (_i16)Msg.Rsp.IpV4.Sd);
412 #if 0
413         _SlSocketParseAddress(&Msg.Rsp, from, fromlen);
414 #else
415         from->sa_family = Msg.Rsp.IpV4.Family;
416         if(SL_AF_INET == from->sa_family)
417         {
418             ((SlSockAddrIn_t *)from)->sin_port = Msg.Rsp.IpV4.Port;
419             ((SlSockAddrIn_t *)from)->sin_addr.s_addr = Msg.Rsp.IpV4.Address;
420             *fromlen = (SlSocklen_t)sizeof(SlSockAddrIn_t);
421         }
422 #ifdef SL_SUPPORT_IPV6
423         else if(SL_AF_INET6 == from->sa_family)
424         {
425             VERIFY_PROTOCOL(*fromlen >= sizeof(SlSockAddrIn6_t));
426 
427             ((SlSockAddrIn6_t *)from)->sin6_port = Msg.Rsp.IpV6.Port;
428             sl_Memcpy(((SlSockAddrIn6_t *)from)->sin6_addr._S6_un._S6_u32, Msg.Rsp.IpV6.Address, 16);
429             *fromlen = sizeof(SlSockAddrIn6_t);
430         }
431 #endif
432 #endif
433     }
434 
435     return (_i16)RetVal;
436 }
437 #endif
438 
439 /*******************************************************************************/
440 /*  sl_Connect */
441 /*******************************************************************************/
442 typedef union
443 {
444     SlSocketAddrCommand_u    Cmd;
445     SlSocketResponse_t       Rsp;
446 }_SlSockConnectMsg_u;
447 
448 #if _SL_INCLUDE_FUNC(sl_Connect)
sl_Connect(_i16 sd,const SlSockAddr_t * addr,_i16 addrlen)449 _i16 sl_Connect(_i16 sd, const SlSockAddr_t *addr, _i16 addrlen)
450 {
451       _SlSockConnectMsg_u  Msg;
452       _SlReturnVal_t       RetVal;
453       _SlCmdCtrl_t         CmdCtrl = {0, (_SlArgSize_t)0, (_SlArgSize_t)sizeof(SlSocketResponse_t)};
454       SlSocketResponse_t   AsyncRsp;
455       _i16 ObjIdx = MAX_CONCURRENT_ACTIONS;
456 
457     /* verify that this api is allowed. if not allowed then
458     ignore the API execution and return immediately with an error */
459     VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
460     _SlDrvMemZero(&AsyncRsp, sizeof(SlSocketResponse_t));
461 
462     switch(addr->sa_family)
463     {
464         case SL_AF_INET :
465             CmdCtrl.Opcode = SL_OPCODE_SOCKET_CONNECT;
466             CmdCtrl.TxDescLen = (_SlArgSize_t)sizeof(SlSocketAddrIPv4Command_t);
467             /* Do nothing - cmd already initialized to this type */
468             break;
469 #ifdef SL_SUPPORT_IPV6
470         case SL_AF_INET6:
471             CmdCtrl.Opcode = SL_OPCODE_SOCKET_CONNECT_V6;
472             CmdCtrl.TxDescLen = (_SlArgSize_t)sizeof(SlSocketAddrIPv6Command_t);
473             break;
474 #endif
475         case SL_AF_RF:
476         default:
477             return SL_RET_CODE_INVALID_INPUT;
478     }
479 
480     Msg.Cmd.IpV4.LenOrPadding = 0;
481     Msg.Cmd.IpV4.Sd = (_u8)sd;
482 
483     _SlSocketBuildAddress(addr, &Msg.Cmd);
484 
485     ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&AsyncRsp, CONNECT_ID, (_u8)(sd  & SL_BSD_SOCKET_ID_MASK));
486 
487     if (ObjIdx < 0)
488     {
489         return ObjIdx;
490     }
491 
492     /* send the command */
493     VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&CmdCtrl, &Msg, NULL));
494     VERIFY_PROTOCOL(Msg.Rsp.Sd == (_u8)sd);
495 
496     RetVal = Msg.Rsp.StatusOrLen;
497 
498     int ret_pool = 0; // for _SlDrvReleasePoolObj
499     if(SL_RET_CODE_OK == RetVal)
500     {
501         /*In case socket is non-blocking one, the async event should be received immediately */
502         if( g_pCB->SocketNonBlocking & (1<<(sd & SL_BSD_SOCKET_ID_MASK) ))
503         {
504             ret_pool = _SlDrvWaitForInternalAsyncEvent(ObjIdx, SL_DRIVER_TIMEOUT_SHORT, SL_OPCODE_SOCKET_CONNECTASYNCRESPONSE);
505         }
506         else
507         {
508             /* wait for async and get Data Read parameters */
509             ret_pool = _SlDrvWaitForInternalAsyncEvent(ObjIdx, 0, 0);
510         }
511 
512         RetVal = AsyncRsp.StatusOrLen;
513 
514         if (0 <= RetVal)
515         {
516             VERIFY_PROTOCOL(AsyncRsp.Sd == (_u8)sd);
517         }
518     }
519 
520     _SlDrvReleasePoolObj(ObjIdx);
521 
522     if(ret_pool < 0)
523     {
524         return ret_pool;
525     }
526     else
527     {
528         return RetVal;
529     }
530 }
531 
532 #endif
533 
534 
535 /*******************************************************************************/
536 /*   _SlSocketHandleAsync_Connect */
537 /*******************************************************************************/
_SlSocketHandleAsync_Connect(void * pVoidBuf)538 _SlReturnVal_t _SlSocketHandleAsync_Connect(void *pVoidBuf)
539 {
540     SlSocketResponse_t          *pMsgArgs   = (SlSocketResponse_t *)_SL_RESP_ARGS_START(pVoidBuf);
541 
542     SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
543 
544     VERIFY_PROTOCOL((pMsgArgs->Sd & SL_BSD_SOCKET_ID_MASK) <= SL_MAX_SOCKETS);
545     VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs);
546 
547     ((SlSocketResponse_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->Sd = pMsgArgs->Sd;
548     ((SlSocketResponse_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->StatusOrLen = pMsgArgs->StatusOrLen;
549 
550     SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj);
551     SL_DRV_PROTECTION_OBJ_UNLOCK();
552 
553     return SL_OS_RET_CODE_OK;
554 }
555 
556 /*******************************************************************************/
557 /*   _SlSocketHandleAsync_Close */
558 /*******************************************************************************/
_SlSocketHandleAsync_Close(void * pVoidBuf)559 _SlReturnVal_t _SlSocketHandleAsync_Close(void *pVoidBuf)
560 {
561     SlSocketResponse_t *pMsgArgs = (SlSocketResponse_t *)_SL_RESP_ARGS_START(pVoidBuf);
562 
563     SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
564 
565     VERIFY_PROTOCOL((pMsgArgs->Sd & SL_BSD_SOCKET_ID_MASK) <= SL_MAX_SOCKETS);
566     VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs);
567 
568     ((SlSocketResponse_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->Sd = pMsgArgs->Sd;
569     ((SlSocketResponse_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->StatusOrLen = pMsgArgs->StatusOrLen;
570 
571     SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj);
572     SL_DRV_PROTECTION_OBJ_UNLOCK();
573 
574     return SL_OS_RET_CODE_OK;
575 }
576 
577 /*******************************************************************************/
578 /*  sl_Send */
579 /*******************************************************************************/
580 typedef union
581 {
582     SlSendRecvCommand_t    Cmd;
583     /*  no response for 'sendto' commands*/
584 }_SlSendMsg_u;
585 
586 static const _SlCmdCtrl_t _SlSendCmdCtrl =
587 {
588     SL_OPCODE_SOCKET_SEND,
589     (_SlArgSize_t)sizeof(SlSendRecvCommand_t),
590     (_SlArgSize_t)0
591 };
592 
593 #if _SL_INCLUDE_FUNC(sl_Send)
sl_Send(_i16 sd,const void * pBuf,_i16 Len,_i16 flags)594 _i16 sl_Send(_i16 sd, const void *pBuf, _i16 Len, _i16 flags)
595 {
596     _SlSendMsg_u  Msg;
597     _SlCmdExt_t   CmdExt;
598     _i16          RetVal;
599     _u32          tempVal;
600 
601     /* verify that this api is allowed. if not allowed then
602     ignore the API execution and return immediately with an error */
603     VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
604 
605     _SlDrvResetCmdExt(&CmdExt);
606     CmdExt.TxPayload1Len = (_u16)Len;
607     CmdExt.pTxPayload1 = (_u8 *)pBuf;
608 
609     /* Only for RAW transceiver type socket, relay the flags parameter in the 2 bytes (4 byte aligned) before the actual payload */
610     if ((sd & SL_SOCKET_PAYLOAD_TYPE_MASK) == SL_SOCKET_PAYLOAD_TYPE_RAW_TRANCEIVER)
611     {
612         tempVal = (_u32)flags;
613         CmdExt.pRxPayload = (_u8 *)&tempVal;
614         CmdExt.RxPayloadLen = -4; /* the (-) sign is used to mark the rx buff as output buff as well*/
615     }
616     else
617     {
618         CmdExt.pRxPayload = NULL;
619         if (Len < 1)
620         {
621             /* ignore */
622             return 0;
623         }
624     }
625 
626     Msg.Cmd.StatusOrLen = Len;
627     Msg.Cmd.Sd = (_u8)sd;
628     Msg.Cmd.FamilyAndFlags |= flags & 0x0F;
629 
630     RetVal = _SlDrvDataWriteOp((_u8)sd, (_SlCmdCtrl_t *)&_SlSendCmdCtrl, &Msg, &CmdExt);
631     if(SL_OS_RET_CODE_OK != RetVal)
632     {
633         return RetVal;
634     }
635 
636     return (_i16)Len;
637 }
638 #endif
639 
640 /*******************************************************************************/
641 /*  sl_Listen */
642 /*******************************************************************************/
643 typedef union
644 {
645     SlListenCommand_t    Cmd;
646     _BasicResponse_t     Rsp;
647 }_SlListenMsg_u;
648 
649 #if _SL_INCLUDE_FUNC(sl_Listen)
650 
651 static const _SlCmdCtrl_t _SlListenCmdCtrl =
652 {
653     SL_OPCODE_SOCKET_LISTEN,
654     (_SlArgSize_t)sizeof(SlListenCommand_t),
655     (_SlArgSize_t)sizeof(_BasicResponse_t),
656 };
657 
sl_Listen(_i16 sd,_i16 backlog)658 _i16 sl_Listen(_i16 sd, _i16 backlog)
659 {
660     _SlListenMsg_u  Msg;
661 
662     /* verify that this api is allowed. if not allowed then
663     ignore the API execution and return immediately with an error */
664     VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
665 
666     Msg.Cmd.Sd = (_u8)sd;
667     Msg.Cmd.Backlog = (_u8)backlog;
668 
669     VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlListenCmdCtrl, &Msg, NULL));
670     return (_i16)Msg.Rsp.status;
671 }
672 #endif
673 
674 /*******************************************************************************/
675 /*  sl_Accept */
676 /*******************************************************************************/
677 typedef union
678 {
679     SlAcceptCommand_t   Cmd;
680     SlSocketResponse_t  Rsp;
681 }_SlSockAcceptMsg_u;
682 
683 #if _SL_INCLUDE_FUNC(sl_Accept)
684 
685 static const _SlCmdCtrl_t _SlAcceptCmdCtrl =
686 {
687     SL_OPCODE_SOCKET_ACCEPT,
688     (_SlArgSize_t)sizeof(SlAcceptCommand_t),
689     (_SlArgSize_t)sizeof(_BasicResponse_t),
690 };
691 
sl_Accept(_i16 sd,SlSockAddr_t * addr,SlSocklen_t * addrlen)692 _i16 sl_Accept(_i16 sd, SlSockAddr_t *addr, SlSocklen_t *addrlen)
693 {
694     _SlSockAcceptMsg_u       Msg;
695     _SlReturnVal_t           RetVal;
696     SlSocketAddrResponse_u   AsyncRsp;
697     int ret_pool = 0; // for _SlDrvReleasePoolObj
698 
699     _i16 ObjIdx = MAX_CONCURRENT_ACTIONS;
700 
701     /* verify that this api is allowed. if not allowed then
702     ignore the API execution and return immediately with an error */
703     VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
704 
705     Msg.Cmd.Sd = (_u8)sd;
706 
707     if((addr != NULL) && (addrlen != NULL))
708     {
709         /* If addr is present, addrlen has to be provided */
710         Msg.Cmd.Family = (_u8)((sizeof(SlSockAddrIn_t) == *addrlen) ? SL_AF_INET : SL_AF_INET6);
711     }
712     else
713     {
714         /* In any other case, addrlen is ignored */
715         Msg.Cmd.Family = (_u8)0;
716     }
717 
718     ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&AsyncRsp, ACCEPT_ID, (_u8)sd  & SL_BSD_SOCKET_ID_MASK);
719 
720     if (ObjIdx < 0)
721     {
722         return ObjIdx;
723     }
724 
725     /* send the command */
726     VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlAcceptCmdCtrl, &Msg, NULL));
727     VERIFY_PROTOCOL(Msg.Rsp.Sd == (_u8)sd);
728 
729     RetVal = Msg.Rsp.StatusOrLen;
730 
731     if(SL_OS_RET_CODE_OK == RetVal)
732     {
733         /* in case socket is non-blocking one, the async event should be received immediately */
734         if( g_pCB->SocketNonBlocking & (1<<(sd & SL_BSD_SOCKET_ID_MASK) ))
735         {
736             ret_pool = _SlDrvWaitForInternalAsyncEvent(ObjIdx, SL_DRIVER_TIMEOUT_SHORT, SL_OPCODE_SOCKET_ACCEPTASYNCRESPONSE);
737         }
738         else
739         {
740             /* wait for async and get Data Read parameters */
741             ret_pool = _SlDrvWaitForInternalAsyncEvent(ObjIdx,0,0);
742         }
743 
744         RetVal = AsyncRsp.IpV4.StatusOrLen;
745 
746         if (0 <= RetVal)
747         {
748             VERIFY_PROTOCOL(AsyncRsp.IpV4.Sd == (_u8)sd);
749         }
750 
751 
752 #if 0 /*  Kept for backup */
753         _SlSocketParseAddress(&AsyncRsp, addr, addrlen);
754 #else
755         if((addr != NULL) && (addrlen != NULL))
756         {
757             addr->sa_family = AsyncRsp.IpV4.Family;
758 
759             if(SL_AF_INET == addr->sa_family)
760             {
761                 if( *addrlen == (SlSocklen_t)sizeof( SlSockAddrIn_t ) )
762                 {
763                     ((SlSockAddrIn_t *)addr)->sin_port         = AsyncRsp.IpV4.Port;
764                     ((SlSockAddrIn_t *)addr)->sin_addr.s_addr  = AsyncRsp.IpV4.Address;
765                 }
766                 else
767                 {
768                     *addrlen = 0;
769                 }
770             }
771 #ifdef SL_SUPPORT_IPV6
772             else if(SL_AF_INET6 == addr->sa_family)
773             {
774                 if( *addrlen == sizeof( SlSockAddrIn6_t ) )
775                 {
776                     ((SlSockAddrIn6_t *)addr)->sin6_port                   = AsyncRsp.IpV6.Port    ;
777                     sl_Memcpy(((SlSockAddrIn6_t *)addr)->sin6_addr._S6_un._S6_u32, AsyncRsp.IpV6.Address, 16);
778                 }
779                 else
780                 {
781                     *addrlen = 0;
782                 }
783             }
784 #endif
785         }
786 #endif
787     }
788 
789     _SlDrvReleasePoolObj(ObjIdx);
790 
791     if(ret_pool < 0)
792     {
793         return ret_pool;
794     }
795     else
796     {
797         return (_i16)RetVal;
798     }
799 }
800 #endif
801 
802 
803 /*******************************************************************************/
804 /*  sl_Htonl */
805 /*******************************************************************************/
sl_Htonl(_u32 val)806 _u32 sl_Htonl( _u32 val )
807 {
808     _u32 i = 1;
809     _i8 *p = (_i8 *)&i;
810     if (p[0] == 1) /* little endian */
811     {
812         p[0] = ((_i8* )&val)[3];
813         p[1] = ((_i8* )&val)[2];
814         p[2] = ((_i8* )&val)[1];
815         p[3] = ((_i8* )&val)[0];
816         return i;
817     }
818     else /* big endian */
819     {
820         return val;
821     }
822 }
823 
824 /*******************************************************************************/
825 /*  sl_Htonl */
826 /*******************************************************************************/
sl_Htons(_u16 val)827 _u16 sl_Htons( _u16 val )
828 {
829     _i16 i = 1;
830     _i8 *p = (_i8 *)&i;
831     if (p[0] == 1) /* little endian */
832     {
833         p[0] = ((_i8* )&val)[1];
834         p[1] = ((_i8* )&val)[0];
835         return (_u16)i;
836     }
837     else /* big endian */
838     {
839         return val;
840     }
841 }
842 
843 /*******************************************************************************/
844 /*   _SlSocketHandleAsync_Accept */
845 /*******************************************************************************/
_SlSocketHandleAsync_Accept(void * pVoidBuf)846 _SlReturnVal_t _SlSocketHandleAsync_Accept(void *pVoidBuf)
847 {
848     SlSocketAddrResponse_u *pMsgArgs = (SlSocketAddrResponse_u *)_SL_RESP_ARGS_START(pVoidBuf);
849 
850     SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
851 
852     VERIFY_PROTOCOL(( pMsgArgs->IpV4.Sd & SL_BSD_SOCKET_ID_MASK) <= SL_MAX_SOCKETS);
853     VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs);
854 
855     sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs,sizeof(SlSocketAddrResponse_u));
856     SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj);
857 
858     SL_DRV_PROTECTION_OBJ_UNLOCK();
859 
860     return SL_OS_RET_CODE_OK;
861 }
862 
863 /*******************************************************************************/
864 /*  sl_Recv */
865 /*******************************************************************************/
866 typedef union
867 {
868     SlSendRecvCommand_t  Cmd;
869     SlSocketResponse_t   Rsp;
870 }_SlRecvMsg_u;
871 
872 #if _SL_INCLUDE_FUNC(sl_Recv)
873 
874 static const _SlCmdCtrl_t _SlRecvCmdCtrl =
875 {
876     SL_OPCODE_SOCKET_RECV,
877     (_SlArgSize_t)sizeof(SlSendRecvCommand_t),
878     (_SlArgSize_t)sizeof(SlSocketResponse_t)
879 };
880 
sl_Recv(_i16 sd,void * pBuf,_i16 Len,_i16 flags)881 _i16 sl_Recv(_i16 sd, void *pBuf, _i16 Len, _i16 flags)
882 {
883     _SlRecvMsg_u   Msg;
884     _SlCmdExt_t    CmdExt;
885     _SlReturnVal_t status;
886 
887     /* verify that this api is allowed. if not allowed then
888     ignore the API execution and return immediately with an error */
889     VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
890 
891     _SlDrvResetCmdExt(&CmdExt);
892     CmdExt.RxPayloadLen = Len;
893     CmdExt.pRxPayload = (_u8 *)pBuf;
894 
895     Msg.Cmd.Sd = (_u8)sd;
896     Msg.Cmd.StatusOrLen = (_u16)Len;
897 
898     /*  no size truncation in recv path */
899     CmdExt.RxPayloadLen = (_i16)Msg.Cmd.StatusOrLen;
900 
901     Msg.Cmd.FamilyAndFlags = (_u8)(flags & 0x0F);
902 
903     status = _SlDrvDataReadOp((_SlSd_t)sd, (_SlCmdCtrl_t *)&_SlRecvCmdCtrl, &Msg, &CmdExt);
904     if( status != SL_OS_RET_CODE_OK )
905     {
906         return status;
907     }
908 
909     /*  if the Device side sends less than expected it is not the Driver's role */
910     /*  the returned value could be smaller than the requested size */
911     return (_i16)Msg.Rsp.StatusOrLen;
912 }
913 #endif
914 
915 /*******************************************************************************/
916 /*  sl_SetSockOpt */
917 /*******************************************************************************/
918 typedef union
919 {
920     SlSetSockOptCommand_t    Cmd;
921     SlSocketResponse_t       Rsp;
922 }_SlSetSockOptMsg_u;
923 
924 static const _SlCmdCtrl_t _SlSetSockOptCmdCtrl =
925 {
926     SL_OPCODE_SOCKET_SETSOCKOPT,
927     (_SlArgSize_t)sizeof(SlSetSockOptCommand_t),
928     (_SlArgSize_t)sizeof(SlSocketResponse_t)
929 };
930 
931 #if _SL_INCLUDE_FUNC(sl_SetSockOpt)
sl_SetSockOpt(_i16 sd,_i16 level,_i16 optname,const void * optval,SlSocklen_t optlen)932 _i16 sl_SetSockOpt(_i16 sd, _i16 level, _i16 optname, const void *optval, SlSocklen_t optlen)
933 {
934     _SlSetSockOptMsg_u    Msg;
935     _SlCmdExt_t           CmdExt;
936 
937     /* verify that this api is allowed. if not allowed then
938     ignore the API execution and return immediately with an error */
939     VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
940 
941     _SlDrvResetCmdExt(&CmdExt);
942     CmdExt.TxPayload1Len = optlen;
943     CmdExt.pTxPayload1 = (_u8 *)optval;
944 
945     Msg.Cmd.Sd = (_u8)sd;
946     Msg.Cmd.Level = (_u8)level;
947     Msg.Cmd.OptionLen = (_u8)optlen;
948     Msg.Cmd.OptionName = (_u8)optname;
949 
950     VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSetSockOptCmdCtrl, &Msg, &CmdExt));
951 
952     return (_i16)Msg.Rsp.StatusOrLen;
953 }
954 #endif
955 
956 /*******************************************************************************/
957 /*  sl_GetSockOpt */
958 /*******************************************************************************/
959 typedef union
960 {
961     SlGetSockOptCommand_t     Cmd;
962     SlGetSockOptResponse_t    Rsp;
963 }_SlGetSockOptMsg_u;
964 
965 
966 #if _SL_INCLUDE_FUNC(sl_GetSockOpt)
967 
968 static const _SlCmdCtrl_t _SlGetSockOptCmdCtrl =
969 {
970     SL_OPCODE_SOCKET_GETSOCKOPT,
971     (_SlArgSize_t)sizeof(SlGetSockOptCommand_t),
972     (_SlArgSize_t)sizeof(SlGetSockOptResponse_t)
973 };
974 
sl_GetSockOpt(_i16 sd,_i16 level,_i16 optname,void * optval,SlSocklen_t * optlen)975 _i16 sl_GetSockOpt(_i16 sd, _i16 level, _i16 optname, void *optval, SlSocklen_t *optlen)
976 {
977     _SlGetSockOptMsg_u    Msg;
978     _SlCmdExt_t           CmdExt;
979 
980     /* verify that this api is allowed. if not allowed then
981     ignore the API execution and return immediately with an error */
982     VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
983     if (*optlen == 0)
984     {
985         return SL_EZEROLEN;
986     }
987 
988     _SlDrvResetCmdExt(&CmdExt);
989     CmdExt.RxPayloadLen = (_i16)(*optlen);
990     CmdExt.pRxPayload = optval;
991 
992     Msg.Cmd.Sd = (_u8)sd;
993     Msg.Cmd.Level = (_u8)level;
994     Msg.Cmd.OptionLen = (_u8)(*optlen);
995     Msg.Cmd.OptionName = (_u8)optname;
996 
997     VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlGetSockOptCmdCtrl, &Msg, &CmdExt));
998 
999     if (CmdExt.RxPayloadLen < CmdExt.ActualRxPayloadLen)
1000     {
1001         *optlen = Msg.Rsp.OptionLen;
1002         return SL_ESMALLBUF;
1003     }
1004     else
1005     {
1006         *optlen = (_u8)CmdExt.ActualRxPayloadLen;
1007     }
1008     return (_i16)Msg.Rsp.Status;
1009 }
1010 #endif
1011 
1012 /********************************************************************************/
1013 /*  sl_Select */
1014 /* ******************************************************************************/
1015 #if _SL_INCLUDE_FUNC(sl_Select)
1016 
1017 typedef union
1018 {
1019     SlSelectCommand_t   Cmd;
1020     _BasicResponse_t    Rsp;
1021 }_SlSelectMsg_u;
1022 
1023 static const _SlCmdCtrl_t _SlSelectCmdCtrl =
1024 {
1025     SL_OPCODE_SOCKET_SELECT,
1026     (_SlArgSize_t)sizeof(SlSelectCommand_t),
1027     (_SlArgSize_t)sizeof(_BasicResponse_t)
1028 };
1029 
1030 /********************************************************************************/
1031 /*  SL_SOCKET_FD_SET */
1032 /* ******************************************************************************/
SL_SOCKET_FD_SET(_i16 fd,SlFdSet_t * fdset)1033 void SL_SOCKET_FD_SET(_i16 fd, SlFdSet_t *fdset)
1034 {
1035     fdset->fd_array[0] |=  (1<< (fd & SL_BSD_SOCKET_ID_MASK));
1036 }
1037 
1038 /*******************************************************************************/
1039 /*  SL_SOCKET_FD_CLR */
1040 /*******************************************************************************/
SL_SOCKET_FD_CLR(_i16 fd,SlFdSet_t * fdset)1041 void SL_SOCKET_FD_CLR(_i16 fd, SlFdSet_t *fdset)
1042 {
1043     fdset->fd_array[0] &=  ~(1<< (fd & SL_BSD_SOCKET_ID_MASK));
1044 }
1045 
1046 /*******************************************************************************/
1047 /*  SL_SOCKET_FD_ISSET */
1048 /*******************************************************************************/
SL_SOCKET_FD_ISSET(_i16 fd,SlFdSet_t * fdset)1049 _i16 SL_SOCKET_FD_ISSET(_i16 fd, SlFdSet_t *fdset)
1050 {
1051     if( fdset->fd_array[0] & (1<< (fd & SL_BSD_SOCKET_ID_MASK)) )
1052     {
1053         return 1;
1054     }
1055     return 0;
1056 }
1057 
1058 /*******************************************************************************/
1059 /*  SL_SOCKET_FD_ZERO */
1060 /*******************************************************************************/
SL_SOCKET_FD_ZERO(SlFdSet_t * fdset)1061 void SL_SOCKET_FD_ZERO(SlFdSet_t *fdset)
1062 {
1063     fdset->fd_array[0] = 0;
1064 }
1065 
1066 #if (defined(SL_PLATFORM_MULTI_THREADED) && !defined(slcb_SocketTriggerEventHandler))
1067 
1068 /*******************************************************************************/
1069 /*  Multiple Select  */
1070 /*******************************************************************************/
1071 
1072 /* Multiple Select Defines */
1073 #define LOCAL_CTRL_PORT                   (3632)
1074 #define SL_LOOPBACK_ADDR                  (0x0100007F)
1075 #define DUMMY_BUF_SIZE                    (4)
1076 #define CTRL_SOCK_FD                      (((_u16)(1)) << g_pCB->MultiSelectCB.CtrlSockFD)
1077 #define SELECT_TIMEOUT                    ((_u16)0)
1078 #define SELECT_NO_TIMEOUT                 (0xFFFFFFFF)
1079 
1080 /* Multiple Select Structures */
1081 _SlSelectMsg_u  Msg;
1082 
1083 static const SlSockAddrIn_t _SlCtrlSockAddr =
1084 {
1085     SL_AF_INET,
1086     LOCAL_CTRL_PORT,
1087     {SL_INADDR_ANY},
1088     {0,0,0,0,0,0,0,0}
1089 };
1090 
1091 static const SlSockAddrIn_t _SlCtrlSockRelease =
1092 {
1093     SL_AF_INET,
1094     LOCAL_CTRL_PORT,
1095     {SL_LOOPBACK_ADDR},
1096     {0,0,0,0,0,0,0,0}
1097 };
1098 
1099 /*******************************************************************************/
1100 /*  CountSetBits */
1101 /*******************************************************************************/
CountSetBits(_u16 fdList)1102 static inline _u8 CountSetBits(_u16 fdList)
1103 {
1104     _u8 Count = 0;
1105 
1106     while(fdList)
1107     {
1108         Count += (fdList & ((_u16)1));
1109         fdList = fdList >> 1;
1110     }
1111 
1112     return Count;
1113 }
1114 
1115 /*******************************************************************************/
1116 /*   _SlSocketHandleAsync_Select */
1117 /*******************************************************************************/
_SlSocketHandleAsync_Select(void * pVoidBuf)1118 _SlReturnVal_t _SlSocketHandleAsync_Select(void *pVoidBuf)
1119 {
1120     _SlReturnVal_t               RetVal;
1121     SlSelectAsyncResponse_t     *pMsgArgs   = (SlSelectAsyncResponse_t *)_SL_RESP_ARGS_START(pVoidBuf);
1122     _u8                          RegIdx = 0;
1123     _u32                         time_now;
1124     _u8                          TimeoutEvent = 0;
1125     _u16                         SelectEvent = 0;
1126     _u8                          PendingSelect = FALSE;
1127 
1128     _SlDrvMemZero(&Msg, sizeof(_SlSelectMsg_u));
1129 
1130     SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
1131 
1132     SL_DRV_OBJ_LOCK_FOREVER(&g_pCB->MultiSelectCB.SelectLockObj);
1133 
1134     /* Check if this context was triggered by a 'select joiner' only,
1135      * without timeout occurring, in order to launch the next select as quick as possible */
1136     if((CTRL_SOCK_FD == pMsgArgs->ReadFds) && (pMsgArgs->Status != SELECT_TIMEOUT))
1137     {
1138         RetVal = _SlDrvClearCtrlSocket();
1139         Msg.Cmd.ReadFds  = g_pCB->MultiSelectCB.readsds;
1140         Msg.Cmd.WriteFds = g_pCB->MultiSelectCB.writesds;
1141         Msg.Cmd.ReadFds |= CTRL_SOCK_FD;
1142         Msg.Cmd.tv_sec  = 0xFFFF;
1143         Msg.Cmd.tv_usec = 0xFFFF;
1144 
1145         RegIdx = _SlDrvGetNextTimeoutValue();
1146 
1147         SL_TRACE3(DBG_MSG, MSG_312, "\n\rAdded caller: call Select with: Write:%x Sec:%d uSec:%d\n\r",
1148                                                     Msg.Cmd.WriteFds, Msg.Cmd.tv_sec, Msg.Cmd.tv_usec);
1149 
1150         RetVal = _SlDrvCmdSend_noWait((_SlCmdCtrl_t *)&_SlSelectCmdCtrl, &Msg, NULL);
1151 
1152         SL_DRV_OBJ_UNLOCK(&g_pCB->MultiSelectCB.SelectLockObj);
1153 
1154         SL_DRV_PROTECTION_OBJ_UNLOCK();
1155 
1156         return RetVal;
1157     }
1158 
1159     /* If we're triggered by the NWP, take time-stamps to monitor the time-outs */
1160     time_now = ((slcb_GetTimestamp() / SL_TIMESTAMP_TICKS_IN_10_MILLISECONDS) * 10);
1161 
1162     /* If it's a proper select response, or if timeout occurred, release the relevant waiters */
1163     for(RegIdx = 0 ; RegIdx < MAX_CONCURRENT_ACTIONS ; RegIdx++)
1164     {
1165         if(g_pCB->MultiSelectCB.SelectEntry[RegIdx] != NULL)
1166         {
1167             /*  In case a certain entry has 100 mSec or less until it's timeout, the overhead
1168              *  caused by calling select again with it's fd lists is redundant, just return a time-out. */
1169 
1170             TimeoutEvent = ((time_now + 100) >= g_pCB->MultiSelectCB.SelectEntry[RegIdx]->TimeStamp);
1171 
1172             if(pMsgArgs->Status != SELECT_TIMEOUT)
1173             {
1174                 SelectEvent = ((g_pCB->MultiSelectCB.SelectEntry[RegIdx]->readlist & pMsgArgs->ReadFds) ||
1175                                (g_pCB->MultiSelectCB.SelectEntry[RegIdx]->writelist & pMsgArgs->WriteFds));
1176             }
1177 
1178             if(SelectEvent || TimeoutEvent)
1179             {
1180 
1181 
1182                 /* Clear the global select socket descriptor bitmaps */
1183                 g_pCB->MultiSelectCB.readsds  &= ~(g_pCB->MultiSelectCB.SelectEntry[RegIdx]->readlist);
1184                 g_pCB->MultiSelectCB.writesds &= ~(g_pCB->MultiSelectCB.SelectEntry[RegIdx]->writelist);
1185 
1186                 if(SelectEvent)
1187                 {
1188                     /* set the corresponding fd lists. */
1189                     g_pCB->MultiSelectCB.SelectEntry[RegIdx]->Response.ReadFds = (pMsgArgs->ReadFds & g_pCB->MultiSelectCB.SelectEntry[RegIdx]->readlist);
1190                     g_pCB->MultiSelectCB.SelectEntry[RegIdx]->Response.WriteFds = (pMsgArgs->WriteFds & g_pCB->MultiSelectCB.SelectEntry[RegIdx]->writelist);
1191                     g_pCB->MultiSelectCB.SelectEntry[RegIdx]->Response.ReadFdsCount = CountSetBits(g_pCB->MultiSelectCB.SelectEntry[RegIdx]->readlist);
1192                     g_pCB->MultiSelectCB.SelectEntry[RegIdx]->Response.WriteFdsCount = CountSetBits(g_pCB->MultiSelectCB.SelectEntry[RegIdx]->writelist);
1193                     g_pCB->MultiSelectCB.SelectEntry[RegIdx]->Response.Status = (g_pCB->MultiSelectCB.SelectEntry[RegIdx]->Response.ReadFdsCount +
1194                                                                                  g_pCB->MultiSelectCB.SelectEntry[RegIdx]->Response.WriteFdsCount);
1195                 }
1196                 else
1197                 {
1198                     g_pCB->MultiSelectCB.SelectEntry[RegIdx]->Response.Status = SELECT_TIMEOUT;
1199                 }
1200 
1201                 g_pCB->MultiSelectCB.SelectEntry[RegIdx]->Response.ReadFds &= ~(CTRL_SOCK_FD);
1202 
1203                 /* Signal the waiting caller. */
1204                 SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[g_pCB->MultiSelectCB.SelectEntry[RegIdx]->ObjIdx].SyncObj);
1205 
1206                 /* Clean it's table entry */
1207                 g_pCB->MultiSelectCB.SelectEntry[RegIdx] = NULL;
1208             }
1209             else
1210             {
1211                 PendingSelect = TRUE;
1212             }
1213         }
1214     }
1215 
1216     /* In case where A caller was added, but also some sockfd were set on the NWP,
1217      * We clear the control socket. */
1218     if((pMsgArgs->ReadFds & CTRL_SOCK_FD) && (pMsgArgs->Status != SELECT_TIMEOUT))
1219     {
1220         RetVal = _SlDrvClearCtrlSocket();
1221     }
1222 
1223     /* If more readers/Writers are present, send select again */
1224     if((0 != g_pCB->MultiSelectCB.readsds) || (0 != g_pCB->MultiSelectCB.writesds) || (TRUE == PendingSelect))
1225     {
1226         Msg.Cmd.ReadFds  = g_pCB->MultiSelectCB.readsds;
1227         Msg.Cmd.ReadFds |= CTRL_SOCK_FD;
1228         Msg.Cmd.WriteFds = g_pCB->MultiSelectCB.writesds;
1229 
1230         /* Set timeout to blocking, in case there is no caller with timeout value. */
1231         Msg.Cmd.tv_sec  = 0xFFFF;
1232         Msg.Cmd.tv_usec = 0xFFFF;
1233 
1234         /* Get the next awaiting timeout caller */
1235         RegIdx = _SlDrvGetNextTimeoutValue();
1236 
1237         SL_TRACE3(DBG_MSG, MSG_312, "\n\rRelease Partial: call Select with: Read:%x Sec:%d uSec:%d\n\r",
1238                                     Msg.Cmd.ReadFds, Msg.Cmd.tv_sec, Msg.Cmd.tv_usec);
1239 
1240         RetVal = _SlDrvCmdSend_noWait((_SlCmdCtrl_t *)&_SlSelectCmdCtrl, &Msg, NULL);
1241     }
1242     else
1243     {
1244         while(g_pCB->MultiSelectCB.ActiveWaiters)
1245         {
1246             SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->MultiSelectCB.SelectSyncObj);
1247             g_pCB->MultiSelectCB.ActiveWaiters--;
1248         }
1249 
1250         g_pCB->MultiSelectCB.ActiveSelect = FALSE;
1251 
1252         SL_TRACE1(DBG_MSG, MSG_312, "\n\rSelect isn't Active: %d\n\r", g_pCB->MultiSelectCB.ActiveSelect);
1253     }
1254 
1255     SL_DRV_OBJ_UNLOCK(&g_pCB->MultiSelectCB.SelectLockObj);
1256 
1257     SL_DRV_PROTECTION_OBJ_UNLOCK();
1258 
1259     return SL_OS_RET_CODE_OK;
1260 }
1261 
1262 /*******************************************************************************/
1263 /*  SlDrvGetNextTimeoutValue */
1264 /*******************************************************************************/
_SlDrvGetNextTimeoutValue(void)1265 static _i8 _SlDrvGetNextTimeoutValue(void)
1266 {
1267     _u32 time_now;
1268     _i8  Found = -1;
1269     _u8  idx = 0;
1270 
1271     /* Take a timestamp */
1272     time_now = ((slcb_GetTimestamp() / SL_TIMESTAMP_TICKS_IN_10_MILLISECONDS) * 10);
1273 
1274     /* Go through all waiting time-outs, and select the closest */
1275     for(idx = 0 ; idx < MAX_CONCURRENT_ACTIONS ; idx++)
1276     {
1277         if(NULL != g_pCB->MultiSelectCB.SelectEntry[idx])
1278         {
1279             /* Check if the time-stamp is bigger or equal to current time, and if it's the minimal time-stamp (closest event) */
1280             if(g_pCB->MultiSelectCB.SelectEntry[idx]->TimeStamp >= time_now)
1281             {
1282                 if(Found == -1)
1283                 {
1284                     Found = idx;
1285                 }
1286                 else
1287                 {
1288                     if(g_pCB->MultiSelectCB.SelectEntry[idx]->TimeStamp <= g_pCB->MultiSelectCB.SelectEntry[Found]->TimeStamp)
1289                     {
1290                         Found = idx;
1291                     }
1292                 }
1293             }
1294         }
1295     }
1296 
1297     if(Found != -1)
1298     {
1299         /* If a non-wait-forever index was found, calculate delta until closest event */
1300         if(g_pCB->MultiSelectCB.SelectEntry[Found]->TimeStamp != SELECT_NO_TIMEOUT)
1301         {
1302             _i32 delta = (g_pCB->MultiSelectCB.SelectEntry[Found]->TimeStamp - time_now);
1303 
1304             if(delta >= 0)
1305             {
1306                 Msg.Cmd.tv_sec  = (delta / 1000);
1307                 Msg.Cmd.tv_usec = (((delta % 1000) * 1000) >> 10);
1308             }
1309             else
1310             {
1311                 /* if delta time calculated is negative, call a non-blocking select */
1312                 Msg.Cmd.tv_sec  = 0;
1313                 Msg.Cmd.tv_usec = 0;
1314             }
1315         }
1316     }
1317 
1318     return Found;
1319 }
1320 
1321 /*******************************************************************************/
1322 /*  _SlDrvClearCtrlSocket */
1323 /*******************************************************************************/
_SlDrvClearCtrlSocket(void)1324 static _i16 _SlDrvClearCtrlSocket(void)
1325 {
1326     _SlRecvfromMsg_u    Msg;
1327     _SlCmdExt_t         CmdExt;
1328     _u8                 dummyBuf[DUMMY_BUF_SIZE];
1329     _SlReturnVal_t      RetVal;
1330 
1331     /* Prepare a recvFrom Cmd */
1332     _SlDrvResetCmdExt(&CmdExt);
1333     _SlDrvMemZero(&Msg, sizeof(_SlRecvfromMsg_u));
1334 
1335     CmdExt.RxPayloadLen = DUMMY_BUF_SIZE;
1336     CmdExt.pRxPayload = (_u8 *)&dummyBuf;
1337 
1338     Msg.Cmd.Sd = (_u8)g_pCB->MultiSelectCB.CtrlSockFD;
1339     Msg.Cmd.StatusOrLen = (_u16)DUMMY_BUF_SIZE;
1340     Msg.Cmd.FamilyAndFlags = (SL_AF_INET << 4);
1341 
1342     RetVal = _SlDrvCmdSend_noWait((_SlCmdCtrl_t *)&_SlRecvfomCmdCtrl, &Msg, &CmdExt);
1343 
1344     return RetVal;
1345 }
1346 
1347 /*******************************************************************************/
1348 /*  _SlDrvOpenCtrlSocket */
1349 /*******************************************************************************/
_SlDrvOpenCtrlSocket(void)1350 static _i16 _SlDrvOpenCtrlSocket(void)
1351 {
1352     _i16 retVal;
1353 
1354     /* In case a control socket is already open, return. */
1355     if(g_pCB->MultiSelectCB.CtrlSockFD != 0xFF)
1356     {
1357         return 0;
1358     }
1359 
1360     /* Open a local control socket */
1361     retVal = sl_Socket(SL_AF_INET, SL_SOCK_DGRAM, 0);
1362 
1363     if(retVal == SL_ERROR_BSD_ENSOCK)
1364     {
1365         return 0;
1366     }
1367     else if(retVal < 0)
1368     {
1369        return retVal;
1370     }
1371     else
1372     {
1373         g_pCB->MultiSelectCB.CtrlSockFD = retVal;
1374     }
1375 
1376     /* Bind it to local control port */
1377     retVal = sl_Bind(g_pCB->MultiSelectCB.CtrlSockFD, (const SlSockAddr_t *)&_SlCtrlSockAddr, sizeof(SlSockAddrIn_t));
1378 
1379     return retVal;
1380 }
1381 
1382 /*******************************************************************************/
1383 /*  _SlDrvCloseCtrlSocket */
1384 /*******************************************************************************/
_SlDrvCloseCtrlSocket(void)1385 static _i16 _SlDrvCloseCtrlSocket(void)
1386 {
1387     _i16 retVal = 0;
1388     _i16 sockfd = 0xFF;
1389 
1390     /* Close the internal Control socket */
1391     sockfd = g_pCB->MultiSelectCB.CtrlSockFD;
1392 
1393     if(sockfd != 0xFF)
1394     {
1395         /* Close the local control socket */
1396         retVal = sl_Close(sockfd);
1397     }
1398 
1399     g_pCB->MultiSelectCB.CtrlSockFD = 0xFF;
1400 
1401     if(retVal < 0)
1402     {
1403         return SL_ERROR_BSD_SOC_ERROR;
1404     }
1405 
1406     return retVal;
1407 }
1408 
1409 /*******************************************************************************/
1410 /*  to_Msec */
1411 /*******************************************************************************/
to_mSec(struct SlTimeval_t * timeout)1412 static inline _u32 to_mSec(struct SlTimeval_t* timeout)
1413 {
1414     return (((slcb_GetTimestamp() / SL_TIMESTAMP_TICKS_IN_10_MILLISECONDS) * 10) + (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000));
1415 }
1416 
1417 /*******************************************************************************/
1418 /*  _SlDrvUnRegisterForSelectAsync */
1419 /*******************************************************************************/
_SlDrvUnRegisterForSelectAsync(_SlSelectEntry_t * pEntry,_u8 SelectInProgress)1420 static _i16 _SlDrvUnRegisterForSelectAsync(_SlSelectEntry_t* pEntry, _u8 SelectInProgress)
1421 {
1422     SL_DRV_OBJ_LOCK_FOREVER(&g_pCB->MultiSelectCB.SelectLockObj);
1423 
1424     /* Clear the global select fd lists */
1425     g_pCB->MultiSelectCB.readsds  &= ~(pEntry->readlist);
1426     g_pCB->MultiSelectCB.writesds &= ~(pEntry->writelist);
1427 
1428     /* Empty the caller's table entry. */
1429     g_pCB->MultiSelectCB.SelectEntry[pEntry->ObjIdx] = NULL;
1430 
1431     if(g_pCB->MultiSelectCB.ActiveSelect == FALSE)
1432     {
1433         _SlDrvCloseCtrlSocket();
1434     }
1435 
1436     SL_DRV_OBJ_UNLOCK(&g_pCB->MultiSelectCB.SelectLockObj);
1437 
1438     /* Release it's pool object */
1439     _SlDrvReleasePoolObj(pEntry->ObjIdx);
1440 
1441     return SL_ERROR_BSD_SOC_ERROR;
1442 }
1443 
1444 /*******************************************************************************/
1445 /*  _SlDrvRegisterForSelectAsync */
1446 /*******************************************************************************/
_SlDrvRegisterForSelectAsync(_SlSelectEntry_t * pEntry,_SlSelectMsg_u * pMsg,struct SlTimeval_t * timeout,_u8 SelectInProgress)1447 static _i16 _SlDrvRegisterForSelectAsync(_SlSelectEntry_t* pEntry, _SlSelectMsg_u* pMsg, struct SlTimeval_t *timeout, _u8 SelectInProgress)
1448 {
1449     _SlReturnVal_t _RetVal = 0;
1450     _u8            dummyBuf[4] = {0};
1451 
1452     /* Register this caller's parameters */
1453     pEntry->readlist  = pMsg->Cmd.ReadFds;
1454     pEntry->writelist = pMsg->Cmd.WriteFds;
1455 
1456     if((pMsg->Cmd.tv_sec != 0xFFFF) && (timeout != NULL))
1457     {
1458         pEntry->TimeStamp = to_mSec(timeout);
1459     }
1460     else
1461     {
1462         pEntry->TimeStamp = SELECT_NO_TIMEOUT;
1463     }
1464 
1465     g_pCB->MultiSelectCB.readsds  |= pMsg->Cmd.ReadFds;
1466     g_pCB->MultiSelectCB.writesds |= pMsg->Cmd.WriteFds;
1467     g_pCB->MultiSelectCB.SelectEntry[pEntry->ObjIdx] = pEntry;
1468 
1469     SL_TRACE3(DBG_MSG, MSG_312, "\n\rRegistered: Objidx:%d, sec:%d, usec%d\n\r",
1470               pEntry->ObjIdx, pMsg->Cmd.tv_sec, pMsg->Cmd.tv_usec);
1471 
1472     if((!SelectInProgress) || (g_pCB->MultiSelectCB.ActiveSelect == FALSE))
1473     {
1474         /* Add ctrl socket to the read list for this 'select' call */
1475         pMsg->Cmd.ReadFds |= CTRL_SOCK_FD;
1476 
1477         SL_DRV_OBJ_UNLOCK(&g_pCB->MultiSelectCB.SelectLockObj);
1478 
1479         _RetVal = _SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSelectCmdCtrl, pMsg, NULL);
1480 
1481         if((_RetVal == SL_RET_CODE_OK) && (g_pCB->MultiSelectCB.CtrlSockFD != 0xFF))
1482         {
1483             /* Signal any waiting "Select" callers */
1484             SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->MultiSelectCB.SelectSyncObj);
1485         }
1486     }
1487     else
1488     {
1489         SL_DRV_OBJ_UNLOCK(&g_pCB->MultiSelectCB.SelectLockObj);
1490 #if (defined (SL_PLATFORM_MULTI_THREADED)) && (!defined (SL_PLATFORM_EXTERNAL_SPAWN))
1491         /* Wait here to be signaled by a successfully completed select caller */
1492         if (_SlDrvIsSpawnOwnGlobalLock())
1493         {
1494            while (TRUE)
1495            {
1496                /* If we are in spawn context, this is an API which was called from event handler,
1497                read any async event and check if we got signaled */
1498                _SlInternalSpawnWaitForEvent();
1499                /* is it mine? */
1500                if (0 == sl_SyncObjWait(&g_pCB->MultiSelectCB.SelectSyncObj, SL_OS_NO_WAIT))
1501                {
1502                   break;
1503                }
1504            }
1505         }
1506         else
1507 #endif
1508         {
1509            SL_DRV_SYNC_OBJ_WAIT_FOREVER(&g_pCB->MultiSelectCB.SelectSyncObj);
1510         }
1511 
1512         _RetVal = sl_SendTo(g_pCB->MultiSelectCB.CtrlSockFD,
1513                                 &dummyBuf[0],
1514                                 sizeof(dummyBuf),
1515                                 0,
1516                                 (const SlSockAddr_t *)&_SlCtrlSockRelease,
1517                                 sizeof(SlSockAddrIn_t));
1518     }
1519 
1520     return _RetVal;
1521 }
1522 
1523 /********************************************************************************/
1524 /*  sl_Select */
1525 /* ******************************************************************************/
sl_Select(_i16 nfds,SlFdSet_t * readsds,SlFdSet_t * writesds,SlFdSet_t * exceptsds,struct SlTimeval_t * timeout)1526 _i16 sl_Select(_i16 nfds, SlFdSet_t *readsds, SlFdSet_t *writesds, SlFdSet_t *exceptsds, struct SlTimeval_t *timeout)
1527 {
1528     _i16                      ret;
1529     _u8                       isCaller = FALSE;
1530     _SlSelectMsg_u            Msg;
1531     _SlSelectEntry_t          SelectParams;
1532     _u8                       SelectInProgress = FALSE;
1533 
1534     /* verify that this API is allowed. if not allowed then
1535     ignore the API execution and return immediately with an error */
1536     VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
1537     _SlDrvMemZero(&Msg,          sizeof(_SlSelectMsg_u));
1538     _SlDrvMemZero(&SelectParams, sizeof(_SlSelectEntry_t));
1539 
1540     Msg.Cmd.Nfds = (_u8)nfds;
1541 
1542     if(readsds)
1543     {
1544         Msg.Cmd.ReadFds = (_u16)readsds->fd_array[0];
1545     }
1546 
1547     if(writesds)
1548     {
1549         Msg.Cmd.WriteFds = (_u16)writesds->fd_array[0];
1550     }
1551 
1552     if(NULL == timeout)
1553     {
1554         Msg.Cmd.tv_sec = 0xffff;
1555         Msg.Cmd.tv_usec = 0xffff;
1556     }
1557     else
1558     {
1559         if(0xffff <= timeout->tv_sec)
1560         {
1561             Msg.Cmd.tv_sec = 0xffff;
1562         }
1563         else
1564         {
1565             Msg.Cmd.tv_sec = (_u16)timeout->tv_sec;
1566         }
1567 
1568         /* this divides by 1024 to fit the result in a int16_t.
1569          * Upon receiving, the NWP multiply this value by 1024.         */
1570         timeout->tv_usec = (timeout->tv_usec >> 10);
1571 
1572         if(0xffff <= timeout->tv_usec)
1573         {
1574             Msg.Cmd.tv_usec = 0xffff;
1575         }
1576         else
1577         {
1578             Msg.Cmd.tv_usec = (_u16)timeout->tv_usec;
1579         }
1580     }
1581 
1582     while(FALSE == isCaller)
1583     {
1584         SelectParams.ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&SelectParams.Response, SELECT_ID, SL_MAX_SOCKETS);
1585 
1586         if (SelectParams.ObjIdx < 0)
1587         {
1588             return SelectParams.ObjIdx;
1589         }
1590 
1591         SL_DRV_OBJ_LOCK_FOREVER(&g_pCB->MultiSelectCB.SelectLockObj);
1592 
1593         /* Check if no other 'Select' calls are in progress */
1594         if(FALSE == g_pCB->MultiSelectCB.ActiveSelect)
1595         {
1596             g_pCB->MultiSelectCB.ActiveSelect = TRUE;
1597         }
1598         else
1599         {
1600             SelectInProgress = TRUE;
1601         }
1602 
1603         if(!SelectInProgress)
1604         {
1605             ret = _SlDrvOpenCtrlSocket();
1606 
1607             if(ret < 0)
1608             {
1609                 _SlDrvCloseCtrlSocket();
1610                 g_pCB->MultiSelectCB.ActiveSelect = FALSE;
1611                 SL_DRV_OBJ_UNLOCK(&g_pCB->MultiSelectCB.SelectLockObj);
1612                 _SlDrvReleasePoolObj(SelectParams.ObjIdx);
1613                 return ret;
1614             }
1615             else
1616             {
1617                 /* All conditions are met for calling "Select" */
1618                 isCaller = TRUE;
1619             }
1620         }
1621         else if(g_pCB->MultiSelectCB.CtrlSockFD == 0xFF)
1622         {
1623             _SlDrvReleasePoolObj(SelectParams.ObjIdx);
1624 
1625             /* This is not a first select caller and all sockets are open,
1626              * caller is expected to wait until select is inactive,
1627              * before trying to register again.                         */
1628             g_pCB->MultiSelectCB.ActiveWaiters++;
1629 
1630             SL_DRV_OBJ_UNLOCK(&g_pCB->MultiSelectCB.SelectLockObj);
1631 
1632             /* Wait here to be signaled by a successfully completed select caller */
1633 #if (defined (SL_PLATFORM_MULTI_THREADED)) && (!defined (SL_PLATFORM_EXTERNAL_SPAWN))
1634             if (_SlDrvIsSpawnOwnGlobalLock())
1635             {
1636                while (TRUE)
1637                {
1638                    /* If we are in spawn context, this is an API which was called from event handler,
1639                    read any async event and check if we got signaled */
1640                    _SlInternalSpawnWaitForEvent();
1641                    /* is it mine? */
1642                    if (0 == sl_SyncObjWait(&g_pCB->MultiSelectCB.SelectSyncObj, SL_OS_NO_WAIT))
1643                    {
1644                       break;
1645                    }
1646                }
1647             }
1648             else
1649 #endif
1650             {
1651                SL_DRV_SYNC_OBJ_WAIT_FOREVER(&g_pCB->MultiSelectCB.SelectSyncObj);
1652             }
1653 
1654 
1655             if((_i16)g_pCB->MultiSelectCB.SelectCmdResp.status != SL_RET_CODE_OK)
1656             {
1657                 return (_i16)(g_pCB->MultiSelectCB.SelectCmdResp.status);
1658             }
1659 
1660             SelectInProgress = FALSE;
1661         }
1662         else
1663         {
1664             /* All conditions are met for calling "Select" */
1665             isCaller = TRUE;
1666         }
1667     }
1668 
1669     /* Register this caller details for an select Async event.
1670      * SelectLockObj is released inside this function,
1671      * right before sending 'Select' command.                 */
1672     ret = _SlDrvRegisterForSelectAsync(&SelectParams, &Msg, timeout, SelectInProgress);
1673 
1674     if(ret < 0)
1675     {
1676         return (_SlDrvUnRegisterForSelectAsync(&SelectParams, SelectInProgress));
1677     }
1678 
1679     /* Wait here for a Async event, or command response in case select fails.*/
1680     ret = _SlDrvWaitForInternalAsyncEvent(SelectParams.ObjIdx, 0, 0);
1681 
1682     _SlDrvReleasePoolObj(SelectParams.ObjIdx);
1683     if(ret < 0)
1684     {
1685         return ret;
1686     }
1687 
1688     ret = (_i16)g_pCB->MultiSelectCB.SelectCmdResp.status;
1689 
1690     if(ret == SL_RET_CODE_OK)
1691     {
1692         ret = (_i16)SelectParams.Response.Status;
1693 
1694         if(ret > SELECT_TIMEOUT)
1695         {
1696             if(readsds)
1697             {
1698                 readsds->fd_array[0] = SelectParams.Response.ReadFds;
1699             }
1700 
1701             if(writesds)
1702             {
1703                 writesds->fd_array[0] = SelectParams.Response.WriteFds;
1704             }
1705         }
1706     }
1707 
1708     return ret;
1709 }
1710 
1711 #else
1712 
1713 /*******************************************************************************/
1714 /*   _SlSocketHandleAsync_Select */
1715 /*******************************************************************************/
_SlSocketHandleAsync_Select(void * pVoidBuf)1716 _SlReturnVal_t _SlSocketHandleAsync_Select(void *pVoidBuf)
1717 {
1718     SlSelectAsyncResponse_t *pMsgArgs = (SlSelectAsyncResponse_t *)_SL_RESP_ARGS_START(pVoidBuf);
1719 #if ((defined(SL_RUNTIME_EVENT_REGISTERATION) || defined(slcb_SocketTriggerEventHandler)))
1720     SlSockTriggerEvent_t SockTriggerEvent;
1721 #endif
1722 
1723     SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
1724 
1725     VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs);
1726 
1727     sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs, sizeof(SlSelectAsyncResponse_t));
1728 
1729 #if ((defined(SL_RUNTIME_EVENT_REGISTERATION) || defined(slcb_SocketTriggerEventHandler)))
1730     if(1 == _SlIsEventRegistered(SL_EVENT_HDL_SOCKET_TRIGGER))
1731     {
1732         if (g_pCB->SocketTriggerSelect.Info.State == SOCK_TRIGGER_WAITING_FOR_RESP)
1733         {
1734 
1735             SockTriggerEvent.Event = SL_SOCKET_TRIGGER_EVENT_SELECT;
1736             SockTriggerEvent.EventData = 0;
1737 
1738             g_pCB->SocketTriggerSelect.Info.State = SOCK_TRIGGER_RESP_RECEIVED;
1739 
1740             SL_DRV_PROTECTION_OBJ_UNLOCK();
1741 
1742             /* call the user handler */
1743             _SlDrvHandleSocketTriggerEvents(&SockTriggerEvent);
1744 
1745             return SL_OS_RET_CODE_OK;
1746         }
1747         else
1748         {
1749             SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj);
1750         }
1751     }
1752     else
1753 #endif
1754     {
1755 
1756         SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj);
1757     }
1758 
1759     SL_DRV_PROTECTION_OBJ_UNLOCK();
1760 
1761     return SL_OS_RET_CODE_OK;
1762 }
1763 
sl_Select(_i16 nfds,SlFdSet_t * readsds,SlFdSet_t * writesds,SlFdSet_t * exceptsds,struct SlTimeval_t * timeout)1764 _i16 sl_Select(_i16 nfds, SlFdSet_t *readsds, SlFdSet_t *writesds, SlFdSet_t *exceptsds, struct SlTimeval_t *timeout)
1765 {
1766     _SlSelectMsg_u            Msg;
1767     SlSelectAsyncResponse_t   AsyncRsp;
1768     _i16                      ObjIdx = MAX_CONCURRENT_ACTIONS;
1769     _i16                      ret = 0;
1770 #if ((defined(SL_RUNTIME_EVENT_REGISTERATION) || defined(slcb_SocketTriggerEventHandler)))
1771     _u8                       IsNonBlocking = FALSE;
1772 #endif
1773 
1774     /* verify that this API is allowed. if not allowed then
1775     ignore the API execution and return immediately with an error */
1776     VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
1777 
1778 #if ((defined(SL_RUNTIME_EVENT_REGISTERATION) || defined(slcb_SocketTriggerEventHandler)))
1779     if(1 == _SlIsEventRegistered(SL_EVENT_HDL_SOCKET_TRIGGER))
1780     {
1781         if( NULL != timeout )
1782         {
1783             /* Set that we are in Non-Blocking mode */
1784             if ( (0 == timeout->tv_sec) && (0 == timeout->tv_usec) )
1785             {
1786                 IsNonBlocking = TRUE;
1787             }
1788             else
1789             {
1790                 SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
1791 
1792                 /* If there is a trigger select running in the progress abort the new blocking request */
1793                 if (g_pCB->SocketTriggerSelect.Info.State > SOCK_TRIGGER_READY)
1794                 {
1795                     SL_DRV_PROTECTION_OBJ_UNLOCK();
1796                     return SL_RET_CODE_SOCKET_SELECT_IN_PROGRESS_ERROR;
1797                 }
1798 
1799                 SL_DRV_PROTECTION_OBJ_UNLOCK();
1800             }
1801 
1802             if (IsNonBlocking == TRUE)
1803             {
1804                 /* return EAGAIN if we alreay have select trigger in progress */
1805                 if (g_pCB->SocketTriggerSelect.Info.State == SOCK_TRIGGER_WAITING_FOR_RESP)
1806                 {
1807                     return SL_ERROR_BSD_EAGAIN;
1808                 }
1809                 /* return the stored response if already received */
1810                 else if (g_pCB->SocketTriggerSelect.Info.State == SOCK_TRIGGER_RESP_RECEIVED)
1811                 {
1812                     if(  ((_i16)g_pCB->SocketTriggerSelect.Resp.Status) >= 0 )
1813                     {
1814                         if( readsds )
1815                         {
1816                             readsds->fd_array[0]  = g_pCB->SocketTriggerSelect.Resp.ReadFds;
1817                         }
1818                         if( writesds )
1819                         {
1820                             writesds->fd_array[0] = g_pCB->SocketTriggerSelect.Resp.WriteFds;
1821                         }
1822                     }
1823 
1824                     /* Now relaese the pool object */
1825                     _SlDrvReleasePoolObj(g_pCB->SocketTriggerSelect.Info.ObjPoolIdx);
1826 
1827                     g_pCB->SocketTriggerSelect.Info.ObjPoolIdx = MAX_CONCURRENT_ACTIONS;
1828 
1829                     /* Reset the socket select trigger object */
1830                     g_pCB->SocketTriggerSelect.Info.State = SOCK_TRIGGER_READY;
1831 
1832                     return (_i16)g_pCB->SocketTriggerSelect.Resp.Status;
1833                 }
1834             }
1835         }
1836     }
1837 #endif
1838 
1839     Msg.Cmd.Nfds          = (_u8)nfds;
1840     Msg.Cmd.ReadFdsCount  = 0;
1841     Msg.Cmd.WriteFdsCount = 0;
1842 
1843     Msg.Cmd.ReadFds  = 0;
1844     Msg.Cmd.WriteFds = 0;
1845 
1846 
1847     if( readsds )
1848     {
1849         Msg.Cmd.ReadFds = (_u16)readsds->fd_array[0];
1850     }
1851     if( writesds )
1852     {
1853         Msg.Cmd.WriteFds = (_u16)writesds->fd_array[0];
1854     }
1855     if( NULL == timeout )
1856     {
1857         Msg.Cmd.tv_sec = 0xffff;
1858         Msg.Cmd.tv_usec = 0xffff;
1859     }
1860     else
1861     {
1862         if( 0xffff <= timeout->tv_sec )
1863         {
1864             Msg.Cmd.tv_sec = 0xffff;
1865         }
1866         else
1867         {
1868             Msg.Cmd.tv_sec = (_u16)timeout->tv_sec;
1869         }
1870 
1871         /*  convert to milliseconds */
1872         timeout->tv_usec = timeout->tv_usec >> 10;
1873 
1874         if( 0xffff <= timeout->tv_usec )
1875         {
1876             Msg.Cmd.tv_usec = 0xffff;
1877         }
1878         else
1879         {
1880             Msg.Cmd.tv_usec = (_u16)timeout->tv_usec;
1881         }
1882 
1883     }
1884 
1885     /* Use Obj to issue the command, if not available try later */
1886     ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&AsyncRsp, SELECT_ID, SL_MAX_SOCKETS);
1887 
1888     if (ObjIdx < 0)
1889     {
1890         return ObjIdx;
1891     }
1892 
1893     /* send the command */
1894     VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSelectCmdCtrl, &Msg, NULL));
1895 
1896     if(SL_OS_RET_CODE_OK == (_i16)Msg.Rsp.status)
1897     {
1898         ret = _SlDrvWaitForInternalAsyncEvent(ObjIdx,0,0);
1899 
1900         Msg.Rsp.status = (_i16)AsyncRsp.Status;
1901 
1902         /* this code handles the socket trigger mode case */
1903 #if((defined(SL_RUNTIME_EVENT_REGISTERATION) || defined(slcb_SocketTriggerEventHandler)))
1904         if(1 == _SlIsEventRegistered(SL_EVENT_HDL_SOCKET_TRIGGER))
1905         {
1906             /* if no data returned and we are in trigger mode,
1907                send another select cmd but now with timeout infinite,
1908                and return immediately with EAGAIN to the user */
1909             if ((IsNonBlocking == TRUE) && (AsyncRsp.Status == 0))
1910             {
1911                 /* set the select trigger-in-progress bit */
1912                 g_pCB->SocketTriggerSelect.Info.State  = SOCK_TRIGGER_WAITING_FOR_RESP;
1913 
1914                 Msg.Cmd.tv_sec = 0xffff;
1915                 Msg.Cmd.tv_usec = 0xffff;
1916 
1917                 /* Release pool object and try to take another call */
1918                 _SlDrvReleasePoolObj(ObjIdx);
1919 
1920                 if(ret < 0)
1921                 {
1922                     return ret;
1923                 }
1924 
1925                 /* Use Obj to issue the command, if not available try later */
1926                 ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&g_pCB->SocketTriggerSelect.Resp, SELECT_ID, SL_MAX_SOCKETS);
1927 
1928                 if (MAX_CONCURRENT_ACTIONS == ObjIdx)
1929                 {
1930                     return SL_POOL_IS_EMPTY;
1931                 }
1932 
1933                 /* Save the pool index to be released only after the user read the response  */
1934                 g_pCB->SocketTriggerSelect.Info.ObjPoolIdx = ObjIdx;
1935 
1936                 /* send the command */
1937                 VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSelectCmdCtrl, &Msg, NULL));
1938                 return SL_ERROR_BSD_EAGAIN;
1939 
1940             }
1941         }
1942 #endif
1943 
1944         if(  ((_i16)Msg.Rsp.status) >= 0 )
1945         {
1946             if( readsds )
1947             {
1948                 readsds->fd_array[0]  = AsyncRsp.ReadFds;
1949             }
1950             if( writesds )
1951             {
1952                 writesds->fd_array[0] = AsyncRsp.WriteFds;
1953             }
1954         }
1955     }
1956 
1957     _SlDrvReleasePoolObj(ObjIdx);
1958 
1959     if(ret < 0)
1960     {
1961         return ret;
1962     }
1963 
1964     return (_i16)Msg.Rsp.status;
1965 }
1966 
1967 #endif /* defined(SL_PLATFORM_MULTI_THREADED) || !defined(slcb_SocketTriggerEventHandler) */
1968 #endif /* _SL_INCLUDE_FUNC(sl_Select) */
1969 
1970 /*******************************************************************************/
1971 /*  sl_StartTLS */
1972 /*******************************************************************************/
1973 #if _SL_INCLUDE_FUNC(sl_StartTLS)
sl_StartTLS(_i16 sd)1974 _i16 sl_StartTLS(_i16 sd)
1975 {
1976     _SlReturnVal_t       RetVal;
1977     SlSocketAsyncEvent_t AsyncRsp;
1978     _u32                 tempValue;
1979     _i16 ObjIdx = MAX_CONCURRENT_ACTIONS;
1980     _i8 ret;
1981     int ret_pool = 0; // for _SlDrvReleasePoolObj
1982     SlEventsListNode_t startTLS;
1983     _u8 ActionIndex;
1984 
1985     /* verify that this api is allowed. if not allowed then
1986        ignore the API execution and return immediately with an error */
1987     VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
1988     _SlDrvMemZero(&AsyncRsp, sizeof(SlSocketAsyncEvent_t));
1989 
1990     /* Check if there already Object with ActionID "startTLS" on the same socket */
1991     for (ActionIndex = 0; ActionIndex < MAX_CONCURRENT_ACTIONS; ++ActionIndex)
1992     {
1993         if(((g_pCB->ObjPool[ActionIndex].AdditionalData & 0x0F) == sd) && ((g_pCB->ObjPool[ActionIndex].ActionID) == START_TLS_ID))
1994         {
1995             return SL_RET_CODE_STARTTLS_IN_PROGRESS_ON_THIS_SD;
1996         }
1997 
1998     }
1999 
2000     ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&AsyncRsp, START_TLS_ID, (_u8)(sd  & SL_BSD_SOCKET_ID_MASK));
2001 
2002     if (ObjIdx < 0)
2003     {
2004         return ObjIdx;
2005     }
2006 
2007     startTLS.event = (void *)_SlSocketHandleAsync_StartTLS;
2008     sl_RegisterLibsEventHandler(SL_EVENT_HDL_SOCKET, &startTLS);
2009 
2010     /* send Start TLS to sl_SetSockOpt */
2011     RetVal = sl_SetSockOpt(sd, SL_SOL_SOCKET, SL_SO_STARTTLS, &tempValue, sizeof(tempValue));
2012 
2013     if(SL_RET_CODE_OK == RetVal)
2014     {
2015         /* wait for async and get Data Read parameters */
2016         ret_pool = _SlDrvWaitForInternalAsyncEvent(ObjIdx,0,0);
2017 
2018         VERIFY_PROTOCOL(AsyncRsp.Sd == (_u8)sd);
2019 
2020         RetVal = AsyncRsp.Val;
2021     }
2022 
2023     ret = sl_UnregisterLibsEventHandler(SL_EVENT_HDL_SOCKET, &startTLS);
2024     _SlDrvReleasePoolObj(ObjIdx);
2025     if(ret < 0)
2026     {
2027         return ret;
2028     }
2029 
2030     if(ret_pool < 0)
2031     {
2032         return ret_pool;
2033     }
2034 
2035     return RetVal;
2036 }
2037 
2038 /*******************************************************************************/
2039 /*   _SlSocketHandleAsync_StartTLS */
2040 /*******************************************************************************/
_SlSocketHandleAsync_StartTLS(void * pVoidBuf)2041 _SlReturnVal_t _SlSocketHandleAsync_StartTLS(void *pVoidBuf)
2042 {
2043     _u8 ActionIndex;
2044 
2045     SlSocketAsyncEvent_t *pMsgArgs = (SlSocketAsyncEvent_t *)((_u32)pVoidBuf+sizeof(_u32));
2046 
2047     SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
2048 
2049     VERIFY_PROTOCOL((pMsgArgs->Sd & SL_BSD_SOCKET_ID_MASK) <= SL_MAX_SOCKETS);
2050 
2051     /* Match the action index*/
2052     for (ActionIndex = 0; ActionIndex < MAX_CONCURRENT_ACTIONS; ++ActionIndex)
2053     {
2054         if((g_pCB->ObjPool[ActionIndex].AdditionalData & 0x0F) == pMsgArgs->Sd && ((g_pCB->ObjPool[ActionIndex].ActionID) == START_TLS_ID))
2055         {
2056             break;
2057         }
2058     }
2059 
2060     if(ActionIndex == MAX_CONCURRENT_ACTIONS)
2061     {
2062        return EVENT_PROPAGATION_CONTINUE;
2063     }
2064 
2065     VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[ActionIndex].pRespArgs);
2066 
2067     ((SlSocketAsyncEvent_t *)(g_pCB->ObjPool[ActionIndex].pRespArgs))->Sd = pMsgArgs->Sd;
2068     ((SlSocketAsyncEvent_t *)(g_pCB->ObjPool[ActionIndex].pRespArgs))->Type = pMsgArgs->Type;
2069     ((SlSocketAsyncEvent_t *)(g_pCB->ObjPool[ActionIndex].pRespArgs))->Val = pMsgArgs->Val;
2070 
2071 
2072     SL_DRV_PROTECTION_OBJ_UNLOCK();
2073     if ((SL_SSL_NOTIFICATION_HANDSHAKE_FAILED == pMsgArgs->Type || SL_SSL_NOTIFICATION_CONNECTED_SECURED == pMsgArgs->Type))
2074     {
2075         SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[ActionIndex].SyncObj);
2076         return EVENT_PROPAGATION_BLOCK;
2077     }
2078     else
2079     {
2080         return EVENT_PROPAGATION_CONTINUE;
2081     }
2082 }
2083 #endif
2084