SimpleLink CC31xx/CC32xx Host Driver  Version 3.0.1.55
Simplifies the implementation of Internet connectivity
sl_socket.c
1 /*
2  * sl_socket.c - CC31xx/CC32xx Host Driver Implementation
3  *
4  * Copyright (C) 2017 Texas Instruments Incorporated - https://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 /* ******************************************************************************/
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 /*******************************************************************************/
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 
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 
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 (MAX_CONCURRENT_ACTIONS == ObjIdx)
199  {
200  return SL_POOL_IS_EMPTY;
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 {
233  SlSocketResponse_t Rsp;
234 }_SlSockBindMsg_u;
235 
236 #if _SL_INCLUDE_FUNC(sl_Bind)
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 {
279  /* no response for 'sendto' commands*/
280 }_SlSendtoMsg_u;
281 
282 #if _SL_INCLUDE_FUNC(sl_SendTo)
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 {
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)
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 {
445  SlSocketResponse_t Rsp;
446 }_SlSockConnectMsg_u;
447 
448 #if _SL_INCLUDE_FUNC(sl_Connect)
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 (MAX_CONCURRENT_ACTIONS == ObjIdx)
488  {
489  return SL_POOL_IS_EMPTY;
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 /*******************************************************************************/
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 /*******************************************************************************/
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 {
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)
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 
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 
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 (MAX_CONCURRENT_ACTIONS == ObjIdx)
721  {
722  return SL_POOL_IS_EMPTY;
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 /*******************************************************************************/
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 /*******************************************************************************/
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 /*******************************************************************************/
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 {
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 
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 {
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)
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 {
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 
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 /* ******************************************************************************/
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 /*******************************************************************************/
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 /*******************************************************************************/
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 /*******************************************************************************/
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 /*******************************************************************************/
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 /*******************************************************************************/
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 /*******************************************************************************/
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 a non-wait-forever index was found, calculate delta until closest event */
1298  if(g_pCB->MultiSelectCB.SelectEntry[Found]->TimeStamp != SELECT_NO_TIMEOUT)
1299  {
1300  _i32 delta = (g_pCB->MultiSelectCB.SelectEntry[Found]->TimeStamp - time_now);
1301 
1302  if(delta >= 0)
1303  {
1304  Msg.Cmd.tv_sec = (delta / 1000);
1305  Msg.Cmd.tv_usec = (((delta % 1000) * 1000) >> 10);
1306  }
1307  else
1308  {
1309  /* if delta time calculated is negative, call a non-blocking select */
1310  Msg.Cmd.tv_sec = 0;
1311  Msg.Cmd.tv_usec = 0;
1312  }
1313  }
1314 
1315  return Found;
1316 }
1317 
1318 /*******************************************************************************/
1319 /* _SlDrvClearCtrlSocket */
1320 /*******************************************************************************/
1321 static _i16 _SlDrvClearCtrlSocket(void)
1322 {
1323  _SlRecvfromMsg_u Msg;
1324  _SlCmdExt_t CmdExt;
1325  _u8 dummyBuf[DUMMY_BUF_SIZE];
1326  _SlReturnVal_t RetVal;
1327 
1328  /* Prepare a recvFrom Cmd */
1329  _SlDrvResetCmdExt(&CmdExt);
1330  _SlDrvMemZero(&Msg, sizeof(_SlRecvfromMsg_u));
1331 
1332  CmdExt.RxPayloadLen = DUMMY_BUF_SIZE;
1333  CmdExt.pRxPayload = (_u8 *)&dummyBuf;
1334 
1335  Msg.Cmd.Sd = (_u8)g_pCB->MultiSelectCB.CtrlSockFD;
1336  Msg.Cmd.StatusOrLen = (_u16)DUMMY_BUF_SIZE;
1337  Msg.Cmd.FamilyAndFlags = (SL_AF_INET << 4);
1338 
1339  RetVal = _SlDrvCmdSend_noWait((_SlCmdCtrl_t *)&_SlRecvfomCmdCtrl, &Msg, &CmdExt);
1340 
1341  return RetVal;
1342 }
1343 
1344 /*******************************************************************************/
1345 /* _SlDrvOpenCtrlSocket */
1346 /*******************************************************************************/
1347 static _i16 _SlDrvOpenCtrlSocket(void)
1348 {
1349  _i16 retVal;
1350 
1351  /* In case a control socket is already open, return. */
1352  if(g_pCB->MultiSelectCB.CtrlSockFD != 0xFF)
1353  {
1354  return 0;
1355  }
1356 
1357  /* Open a local control socket */
1358  retVal = sl_Socket(SL_AF_INET, SL_SOCK_DGRAM, 0);
1359 
1360  if(retVal == SL_ERROR_BSD_ENSOCK)
1361  {
1362  return 0;
1363  }
1364  else if(retVal < 0)
1365  {
1366  return retVal;
1367  }
1368  else
1369  {
1370  g_pCB->MultiSelectCB.CtrlSockFD = retVal;
1371  }
1372 
1373  /* Bind it to local control port */
1374  retVal = sl_Bind(g_pCB->MultiSelectCB.CtrlSockFD, (const SlSockAddr_t *)&_SlCtrlSockAddr, sizeof(SlSockAddrIn_t));
1375 
1376  return retVal;
1377 }
1378 
1379 /*******************************************************************************/
1380 /* _SlDrvCloseCtrlSocket */
1381 /*******************************************************************************/
1382 static _i16 _SlDrvCloseCtrlSocket(void)
1383 {
1384  _i16 retVal = 0;
1385  _i16 sockfd = 0xFF;
1386 
1387  /* Close the internal Control socket */
1388  sockfd = g_pCB->MultiSelectCB.CtrlSockFD;
1389 
1390  if(sockfd != 0xFF)
1391  {
1392  /* Close the local control socket */
1393  retVal = sl_Close(sockfd);
1394  }
1395 
1396  g_pCB->MultiSelectCB.CtrlSockFD = 0xFF;
1397 
1398  if(retVal < 0)
1399  {
1400  return SL_ERROR_BSD_SOC_ERROR;
1401  }
1402 
1403  return retVal;
1404 }
1405 
1406 /*******************************************************************************/
1407 /* to_Msec */
1408 /*******************************************************************************/
1409 static inline _u32 to_mSec(struct SlTimeval_t* timeout)
1410 {
1411  return (((slcb_GetTimestamp() / SL_TIMESTAMP_TICKS_IN_10_MILLISECONDS) * 10) + (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000));
1412 }
1413 
1414 /*******************************************************************************/
1415 /* _SlDrvUnRegisterForSelectAsync */
1416 /*******************************************************************************/
1417 static _i16 _SlDrvUnRegisterForSelectAsync(_SlSelectEntry_t* pEntry, _u8 SelectInProgress)
1418 {
1419  SL_DRV_OBJ_LOCK_FOREVER(&g_pCB->MultiSelectCB.SelectLockObj);
1420 
1421  /* Clear the global select fd lists */
1422  g_pCB->MultiSelectCB.readsds &= ~(pEntry->readlist);
1423  g_pCB->MultiSelectCB.writesds &= ~(pEntry->writelist);
1424 
1425  /* Empty the caller's table entry. */
1426  g_pCB->MultiSelectCB.SelectEntry[pEntry->ObjIdx] = NULL;
1427 
1428  if(g_pCB->MultiSelectCB.ActiveSelect == FALSE)
1429  {
1430  _SlDrvCloseCtrlSocket();
1431  }
1432 
1433  SL_DRV_OBJ_UNLOCK(&g_pCB->MultiSelectCB.SelectLockObj);
1434 
1435  /* Release it's pool object */
1436  _SlDrvReleasePoolObj(pEntry->ObjIdx);
1437 
1438  return SL_ERROR_BSD_SOC_ERROR;
1439 }
1440 
1441 /*******************************************************************************/
1442 /* _SlDrvRegisterForSelectAsync */
1443 /*******************************************************************************/
1444 static _i16 _SlDrvRegisterForSelectAsync(_SlSelectEntry_t* pEntry, _SlSelectMsg_u* pMsg, struct SlTimeval_t *timeout, _u8 SelectInProgress)
1445 {
1446  _SlReturnVal_t _RetVal = 0;
1447  _u8 dummyBuf[4] = {0};
1448 
1449  /* Register this caller's parameters */
1450  pEntry->readlist = pMsg->Cmd.ReadFds;
1451  pEntry->writelist = pMsg->Cmd.WriteFds;
1452 
1453  if((pMsg->Cmd.tv_sec != 0xFFFF) && (timeout != NULL))
1454  {
1455  pEntry->TimeStamp = to_mSec(timeout);
1456  }
1457  else
1458  {
1459  pEntry->TimeStamp = SELECT_NO_TIMEOUT;
1460  }
1461 
1462  g_pCB->MultiSelectCB.readsds |= pMsg->Cmd.ReadFds;
1463  g_pCB->MultiSelectCB.writesds |= pMsg->Cmd.WriteFds;
1464  g_pCB->MultiSelectCB.SelectEntry[pEntry->ObjIdx] = pEntry;
1465 
1466  SL_TRACE3(DBG_MSG, MSG_312, "\n\rRegistered: Objidx:%d, sec:%d, usec%d\n\r",
1467  pEntry->ObjIdx, pMsg->Cmd.tv_sec, pMsg->Cmd.tv_usec);
1468 
1469  if((!SelectInProgress) || (g_pCB->MultiSelectCB.ActiveSelect == FALSE))
1470  {
1471  /* Add ctrl socket to the read list for this 'select' call */
1472  pMsg->Cmd.ReadFds |= CTRL_SOCK_FD;
1473 
1474  SL_DRV_OBJ_UNLOCK(&g_pCB->MultiSelectCB.SelectLockObj);
1475 
1476  _RetVal = _SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSelectCmdCtrl, pMsg, NULL);
1477 
1478  if((_RetVal == SL_RET_CODE_OK) && (g_pCB->MultiSelectCB.CtrlSockFD != 0xFF))
1479  {
1480  /* Signal any waiting "Select" callers */
1481  SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->MultiSelectCB.SelectSyncObj);
1482  }
1483  }
1484  else
1485  {
1486  SL_DRV_OBJ_UNLOCK(&g_pCB->MultiSelectCB.SelectLockObj);
1487 #if (defined (SL_PLATFORM_MULTI_THREADED)) && (!defined (SL_PLATFORM_EXTERNAL_SPAWN))
1488  /* Wait here to be signaled by a successfully completed select caller */
1489  if (_SlDrvIsSpawnOwnGlobalLock())
1490  {
1491  while (TRUE)
1492  {
1493  /* If we are in spawn context, this is an API which was called from event handler,
1494  read any async event and check if we got signaled */
1495  _SlInternalSpawnWaitForEvent();
1496  /* is it mine? */
1497  if (0 == sl_SyncObjWait(&g_pCB->MultiSelectCB.SelectSyncObj, SL_OS_NO_WAIT))
1498  {
1499  break;
1500  }
1501  }
1502  }
1503  else
1504 #endif
1505  {
1506  SL_DRV_SYNC_OBJ_WAIT_FOREVER(&g_pCB->MultiSelectCB.SelectSyncObj);
1507  }
1508 
1509  _RetVal = sl_SendTo(g_pCB->MultiSelectCB.CtrlSockFD,
1510  &dummyBuf[0],
1511  sizeof(dummyBuf),
1512  0,
1513  (const SlSockAddr_t *)&_SlCtrlSockRelease,
1514  sizeof(SlSockAddrIn_t));
1515  }
1516 
1517  return _RetVal;
1518 }
1519 
1520 /********************************************************************************/
1521 /* sl_Select */
1522 /* ******************************************************************************/
1523 _i16 sl_Select(_i16 nfds, SlFdSet_t *readsds, SlFdSet_t *writesds, SlFdSet_t *exceptsds, struct SlTimeval_t *timeout)
1524 {
1525  _i16 ret;
1526  _u8 isCaller = FALSE;
1527  _SlSelectMsg_u Msg;
1528  _SlSelectEntry_t SelectParams;
1529  _u8 SelectInProgress = FALSE;
1530 
1531  /* verify that this API is allowed. if not allowed then
1532  ignore the API execution and return immediately with an error */
1533  VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
1534  _SlDrvMemZero(&Msg, sizeof(_SlSelectMsg_u));
1535  _SlDrvMemZero(&SelectParams, sizeof(_SlSelectEntry_t));
1536 
1537  Msg.Cmd.Nfds = (_u8)nfds;
1538 
1539  if(readsds)
1540  {
1541  Msg.Cmd.ReadFds = (_u16)readsds->fd_array[0];
1542  }
1543 
1544  if(writesds)
1545  {
1546  Msg.Cmd.WriteFds = (_u16)writesds->fd_array[0];
1547  }
1548 
1549  if(NULL == timeout)
1550  {
1551  Msg.Cmd.tv_sec = 0xffff;
1552  Msg.Cmd.tv_usec = 0xffff;
1553  }
1554  else
1555  {
1556  if(0xffff <= timeout->tv_sec)
1557  {
1558  Msg.Cmd.tv_sec = 0xffff;
1559  }
1560  else
1561  {
1562  Msg.Cmd.tv_sec = (_u16)timeout->tv_sec;
1563  }
1564 
1565  /* this divides by 1024 to fit the result in a int16_t.
1566  * Upon receiving, the NWP multiply this value by 1024. */
1567  timeout->tv_usec = (timeout->tv_usec >> 10);
1568 
1569  if(0xffff <= timeout->tv_usec)
1570  {
1571  Msg.Cmd.tv_usec = 0xffff;
1572  }
1573  else
1574  {
1575  Msg.Cmd.tv_usec = (_u16)timeout->tv_usec;
1576  }
1577  }
1578 
1579  while(FALSE == isCaller)
1580  {
1581  SelectParams.ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&SelectParams.Response, SELECT_ID, SL_MAX_SOCKETS);
1582 
1583  if(MAX_CONCURRENT_ACTIONS == SelectParams.ObjIdx)
1584  {
1585  return SL_POOL_IS_EMPTY;
1586  }
1587 
1588  SL_DRV_OBJ_LOCK_FOREVER(&g_pCB->MultiSelectCB.SelectLockObj);
1589 
1590  /* Check if no other 'Select' calls are in progress */
1591  if(FALSE == g_pCB->MultiSelectCB.ActiveSelect)
1592  {
1593  g_pCB->MultiSelectCB.ActiveSelect = TRUE;
1594  }
1595  else
1596  {
1597  SelectInProgress = TRUE;
1598  }
1599 
1600  if(!SelectInProgress)
1601  {
1602  ret = _SlDrvOpenCtrlSocket();
1603 
1604  if(ret < 0)
1605  {
1606  _SlDrvCloseCtrlSocket();
1607  g_pCB->MultiSelectCB.ActiveSelect = FALSE;
1608  SL_DRV_OBJ_UNLOCK(&g_pCB->MultiSelectCB.SelectLockObj);
1609  _SlDrvReleasePoolObj(SelectParams.ObjIdx);
1610  return ret;
1611  }
1612  else
1613  {
1614  /* All conditions are met for calling "Select" */
1615  isCaller = TRUE;
1616  }
1617  }
1618  else if(g_pCB->MultiSelectCB.CtrlSockFD == 0xFF)
1619  {
1620  _SlDrvReleasePoolObj(SelectParams.ObjIdx);
1621 
1622  /* This is not a first select caller and all sockets are open,
1623  * caller is expected to wait until select is inactive,
1624  * before trying to register again. */
1625  g_pCB->MultiSelectCB.ActiveWaiters++;
1626 
1627  SL_DRV_OBJ_UNLOCK(&g_pCB->MultiSelectCB.SelectLockObj);
1628 
1629  /* Wait here to be signaled by a successfully completed select caller */
1630 #if (defined (SL_PLATFORM_MULTI_THREADED)) && (!defined (SL_PLATFORM_EXTERNAL_SPAWN))
1631  if (_SlDrvIsSpawnOwnGlobalLock())
1632  {
1633  while (TRUE)
1634  {
1635  /* If we are in spawn context, this is an API which was called from event handler,
1636  read any async event and check if we got signaled */
1637  _SlInternalSpawnWaitForEvent();
1638  /* is it mine? */
1639  if (0 == sl_SyncObjWait(&g_pCB->MultiSelectCB.SelectSyncObj, SL_OS_NO_WAIT))
1640  {
1641  break;
1642  }
1643  }
1644  }
1645  else
1646 #endif
1647  {
1648  SL_DRV_SYNC_OBJ_WAIT_FOREVER(&g_pCB->MultiSelectCB.SelectSyncObj);
1649  }
1650 
1651 
1652  if((_i16)g_pCB->MultiSelectCB.SelectCmdResp.status != SL_RET_CODE_OK)
1653  {
1654  return (_i16)(g_pCB->MultiSelectCB.SelectCmdResp.status);
1655  }
1656 
1657  SelectInProgress = FALSE;
1658  }
1659  else
1660  {
1661  /* All conditions are met for calling "Select" */
1662  isCaller = TRUE;
1663  }
1664  }
1665 
1666  /* Register this caller details for an select Async event.
1667  * SelectLockObj is released inside this function,
1668  * right before sending 'Select' command. */
1669  ret = _SlDrvRegisterForSelectAsync(&SelectParams, &Msg, timeout, SelectInProgress);
1670 
1671  if(ret < 0)
1672  {
1673  return (_SlDrvUnRegisterForSelectAsync(&SelectParams, SelectInProgress));
1674  }
1675 
1676  /* Wait here for a Async event, or command response in case select fails.*/
1677  ret = _SlDrvWaitForInternalAsyncEvent(SelectParams.ObjIdx, 0, 0);
1678 
1679  _SlDrvReleasePoolObj(SelectParams.ObjIdx);
1680  if(ret < 0)
1681  {
1682  return ret;
1683  }
1684 
1685  ret = (_i16)g_pCB->MultiSelectCB.SelectCmdResp.status;
1686 
1687  if(ret == SL_RET_CODE_OK)
1688  {
1689  ret = (_i16)SelectParams.Response.Status;
1690 
1691  if(ret > SELECT_TIMEOUT)
1692  {
1693  if(readsds)
1694  {
1695  readsds->fd_array[0] = SelectParams.Response.ReadFds;
1696  }
1697 
1698  if(writesds)
1699  {
1700  writesds->fd_array[0] = SelectParams.Response.WriteFds;
1701  }
1702  }
1703  }
1704 
1705  return ret;
1706 }
1707 
1708 #else
1709 
1710 /*******************************************************************************/
1711 /* _SlSocketHandleAsync_Select */
1712 /*******************************************************************************/
1713 _SlReturnVal_t _SlSocketHandleAsync_Select(void *pVoidBuf)
1714 {
1715  SlSelectAsyncResponse_t *pMsgArgs = (SlSelectAsyncResponse_t *)_SL_RESP_ARGS_START(pVoidBuf);
1716 #if ((defined(SL_RUNTIME_EVENT_REGISTERATION) || defined(slcb_SocketTriggerEventHandler)))
1717  SlSockTriggerEvent_t SockTriggerEvent;
1718 #endif
1719 
1720  SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
1721 
1722  VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs);
1723 
1724  sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs, sizeof(SlSelectAsyncResponse_t));
1725 
1726 #if ((defined(SL_RUNTIME_EVENT_REGISTERATION) || defined(slcb_SocketTriggerEventHandler)))
1727  if(1 == _SlIsEventRegistered(SL_EVENT_HDL_SOCKET_TRIGGER))
1728  {
1729  if (g_pCB->SocketTriggerSelect.Info.State == SOCK_TRIGGER_WAITING_FOR_RESP)
1730  {
1731 
1732  SockTriggerEvent.Event = SL_SOCKET_TRIGGER_EVENT_SELECT;
1733  SockTriggerEvent.EventData = 0;
1734 
1735  g_pCB->SocketTriggerSelect.Info.State = SOCK_TRIGGER_RESP_RECEIVED;
1736 
1737  SL_DRV_PROTECTION_OBJ_UNLOCK();
1738 
1739  /* call the user handler */
1740  _SlDrvHandleSocketTriggerEvents(&SockTriggerEvent);
1741 
1742  return SL_OS_RET_CODE_OK;
1743  }
1744  else
1745  {
1746  SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj);
1747  }
1748  }
1749  else
1750 #endif
1751  {
1752 
1753  SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj);
1754  }
1755 
1756  SL_DRV_PROTECTION_OBJ_UNLOCK();
1757 
1758  return SL_OS_RET_CODE_OK;
1759 }
1760 
1761 _i16 sl_Select(_i16 nfds, SlFdSet_t *readsds, SlFdSet_t *writesds, SlFdSet_t *exceptsds, struct SlTimeval_t *timeout)
1762 {
1763  _SlSelectMsg_u Msg;
1764  SlSelectAsyncResponse_t AsyncRsp;
1765  _i16 ObjIdx = MAX_CONCURRENT_ACTIONS;
1766  _i16 ret = 0;
1767 #if ((defined(SL_RUNTIME_EVENT_REGISTERATION) || defined(slcb_SocketTriggerEventHandler)))
1768  _u8 IsNonBlocking = FALSE;
1769 #endif
1770 
1771  /* verify that this API is allowed. if not allowed then
1772  ignore the API execution and return immediately with an error */
1773  VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
1774 
1775 #if ((defined(SL_RUNTIME_EVENT_REGISTERATION) || defined(slcb_SocketTriggerEventHandler)))
1776  if(1 == _SlIsEventRegistered(SL_EVENT_HDL_SOCKET_TRIGGER))
1777  {
1778  if( NULL != timeout )
1779  {
1780  /* Set that we are in Non-Blocking mode */
1781  if ( (0 == timeout->tv_sec) && (0 == timeout->tv_usec) )
1782  {
1783  IsNonBlocking = TRUE;
1784  }
1785  else
1786  {
1787  SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
1788 
1789  /* If there is a trigger select running in the progress abort the new blocking request */
1790  if (g_pCB->SocketTriggerSelect.Info.State > SOCK_TRIGGER_READY)
1791  {
1792  SL_DRV_PROTECTION_OBJ_UNLOCK();
1793  return SL_RET_CODE_SOCKET_SELECT_IN_PROGRESS_ERROR;
1794  }
1795 
1796  SL_DRV_PROTECTION_OBJ_UNLOCK();
1797  }
1798 
1799  if (IsNonBlocking == TRUE)
1800  {
1801  /* return EAGAIN if we alreay have select trigger in progress */
1802  if (g_pCB->SocketTriggerSelect.Info.State == SOCK_TRIGGER_WAITING_FOR_RESP)
1803  {
1804  return SL_ERROR_BSD_EAGAIN;
1805  }
1806  /* return the stored response if already received */
1807  else if (g_pCB->SocketTriggerSelect.Info.State == SOCK_TRIGGER_RESP_RECEIVED)
1808  {
1809  if( ((_i16)g_pCB->SocketTriggerSelect.Resp.Status) >= 0 )
1810  {
1811  if( readsds )
1812  {
1813  readsds->fd_array[0] = g_pCB->SocketTriggerSelect.Resp.ReadFds;
1814  }
1815  if( writesds )
1816  {
1817  writesds->fd_array[0] = g_pCB->SocketTriggerSelect.Resp.WriteFds;
1818  }
1819  }
1820 
1821  /* Now relaese the pool object */
1822  _SlDrvReleasePoolObj(g_pCB->SocketTriggerSelect.Info.ObjPoolIdx);
1823 
1824  g_pCB->SocketTriggerSelect.Info.ObjPoolIdx = MAX_CONCURRENT_ACTIONS;
1825 
1826  /* Reset the socket select trigger object */
1827  g_pCB->SocketTriggerSelect.Info.State = SOCK_TRIGGER_READY;
1828 
1829  return (_i16)g_pCB->SocketTriggerSelect.Resp.Status;
1830  }
1831  }
1832  }
1833  }
1834 #endif
1835 
1836  Msg.Cmd.Nfds = (_u8)nfds;
1837  Msg.Cmd.ReadFdsCount = 0;
1838  Msg.Cmd.WriteFdsCount = 0;
1839 
1840  Msg.Cmd.ReadFds = 0;
1841  Msg.Cmd.WriteFds = 0;
1842 
1843 
1844  if( readsds )
1845  {
1846  Msg.Cmd.ReadFds = (_u16)readsds->fd_array[0];
1847  }
1848  if( writesds )
1849  {
1850  Msg.Cmd.WriteFds = (_u16)writesds->fd_array[0];
1851  }
1852  if( NULL == timeout )
1853  {
1854  Msg.Cmd.tv_sec = 0xffff;
1855  Msg.Cmd.tv_usec = 0xffff;
1856  }
1857  else
1858  {
1859  if( 0xffff <= timeout->tv_sec )
1860  {
1861  Msg.Cmd.tv_sec = 0xffff;
1862  }
1863  else
1864  {
1865  Msg.Cmd.tv_sec = (_u16)timeout->tv_sec;
1866  }
1867 
1868  /* convert to milliseconds */
1869  timeout->tv_usec = timeout->tv_usec >> 10;
1870 
1871  if( 0xffff <= timeout->tv_usec )
1872  {
1873  Msg.Cmd.tv_usec = 0xffff;
1874  }
1875  else
1876  {
1877  Msg.Cmd.tv_usec = (_u16)timeout->tv_usec;
1878  }
1879 
1880  }
1881 
1882  /* Use Obj to issue the command, if not available try later */
1883  ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&AsyncRsp, SELECT_ID, SL_MAX_SOCKETS);
1884 
1885  if (MAX_CONCURRENT_ACTIONS == ObjIdx)
1886  {
1887  return SL_POOL_IS_EMPTY;
1888  }
1889 
1890  /* send the command */
1891  VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSelectCmdCtrl, &Msg, NULL));
1892 
1893  if(SL_OS_RET_CODE_OK == (_i16)Msg.Rsp.status)
1894  {
1895  ret = _SlDrvWaitForInternalAsyncEvent(ObjIdx,0,0);
1896 
1897  Msg.Rsp.status = (_i16)AsyncRsp.Status;
1898 
1899  /* this code handles the socket trigger mode case */
1900 #if((defined(SL_RUNTIME_EVENT_REGISTERATION) || defined(slcb_SocketTriggerEventHandler)))
1901  if(1 == _SlIsEventRegistered(SL_EVENT_HDL_SOCKET_TRIGGER))
1902  {
1903  /* if no data returned and we are in trigger mode,
1904  send another select cmd but now with timeout infinite,
1905  and return immediately with EAGAIN to the user */
1906  if ((IsNonBlocking == TRUE) && (AsyncRsp.Status == 0))
1907  {
1908  /* set the select trigger-in-progress bit */
1909  g_pCB->SocketTriggerSelect.Info.State = SOCK_TRIGGER_WAITING_FOR_RESP;
1910 
1911  Msg.Cmd.tv_sec = 0xffff;
1912  Msg.Cmd.tv_usec = 0xffff;
1913 
1914  /* Release pool object and try to take another call */
1915  _SlDrvReleasePoolObj(ObjIdx);
1916 
1917  if(ret < 0)
1918  {
1919  return ret;
1920  }
1921 
1922  /* Use Obj to issue the command, if not available try later */
1923  ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&g_pCB->SocketTriggerSelect.Resp, SELECT_ID, SL_MAX_SOCKETS);
1924 
1925  if (MAX_CONCURRENT_ACTIONS == ObjIdx)
1926  {
1927  return SL_POOL_IS_EMPTY;
1928  }
1929 
1930  /* Save the pool index to be released only after the user read the response */
1931  g_pCB->SocketTriggerSelect.Info.ObjPoolIdx = ObjIdx;
1932 
1933  /* send the command */
1934  VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSelectCmdCtrl, &Msg, NULL));
1935  return SL_ERROR_BSD_EAGAIN;
1936 
1937  }
1938  }
1939 #endif
1940 
1941  if( ((_i16)Msg.Rsp.status) >= 0 )
1942  {
1943  if( readsds )
1944  {
1945  readsds->fd_array[0] = AsyncRsp.ReadFds;
1946  }
1947  if( writesds )
1948  {
1949  writesds->fd_array[0] = AsyncRsp.WriteFds;
1950  }
1951  }
1952  }
1953 
1954  _SlDrvReleasePoolObj(ObjIdx);
1955 
1956  if(ret < 0)
1957  {
1958  return ret;
1959  }
1960 
1961  return (_i16)Msg.Rsp.status;
1962 }
1963 
1964 #endif /* defined(SL_PLATFORM_MULTI_THREADED) || !defined(slcb_SocketTriggerEventHandler) */
1965 #endif /* _SL_INCLUDE_FUNC(sl_Select) */
1966 
1967 /*******************************************************************************/
1968 /* sl_StartTLS */
1969 /*******************************************************************************/
1970 #if _SL_INCLUDE_FUNC(sl_StartTLS)
1971 _i16 sl_StartTLS(_i16 sd)
1972 {
1973  _SlReturnVal_t RetVal;
1974  SlSocketAsyncEvent_t AsyncRsp;
1975  _u32 tempValue;
1976  _i16 ObjIdx = MAX_CONCURRENT_ACTIONS;
1977  _i8 ret;
1978  int ret_pool = 0; // for _SlDrvReleasePoolObj
1979  SlEventsListNode_t startTLS;
1980  _u8 ActionIndex;
1981 
1982  /* verify that this api is allowed. if not allowed then
1983  ignore the API execution and return immediately with an error */
1984  VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
1985  _SlDrvMemZero(&AsyncRsp, sizeof(SlSocketAsyncEvent_t));
1986 
1987  /* Check if there already Object with ActionID "startTLS" on the same socket */
1988  for (ActionIndex = 0; ActionIndex < MAX_CONCURRENT_ACTIONS; ++ActionIndex)
1989  {
1990  if(((g_pCB->ObjPool[ActionIndex].AdditionalData & 0x0F) == sd) && ((g_pCB->ObjPool[ActionIndex].ActionID) == START_TLS_ID))
1991  {
1992  return SL_RET_CODE_STARTTLS_IN_PROGRESS_ON_THIS_SD;
1993  }
1994 
1995  }
1996 
1997  ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&AsyncRsp, START_TLS_ID, (_u8)(sd & SL_BSD_SOCKET_ID_MASK));
1998 
1999  if (MAX_CONCURRENT_ACTIONS == ObjIdx)
2000  {
2001  return SL_POOL_IS_EMPTY;
2002  }
2003 
2004  startTLS.event = (void *)_SlSocketHandleAsync_StartTLS;
2005  sl_RegisterLibsEventHandler(SL_EVENT_HDL_SOCKET, &startTLS);
2006 
2007  /* send Start TLS to sl_SetSockOpt */
2008  RetVal = sl_SetSockOpt(sd, SL_SOL_SOCKET, SL_SO_STARTTLS, &tempValue, sizeof(tempValue));
2009 
2010  if(SL_RET_CODE_OK == RetVal)
2011  {
2012  /* wait for async and get Data Read parameters */
2013  ret_pool = _SlDrvWaitForInternalAsyncEvent(ObjIdx,0,0);
2014 
2015  VERIFY_PROTOCOL(AsyncRsp.Sd == (_u8)sd);
2016 
2017  RetVal = AsyncRsp.Val;
2018  }
2019 
2020  ret = sl_UnregisterLibsEventHandler(SL_EVENT_HDL_SOCKET, &startTLS);
2021  _SlDrvReleasePoolObj(ObjIdx);
2022  if(ret < 0)
2023  {
2024  return ret;
2025  }
2026 
2027  if(ret_pool < 0)
2028  {
2029  return ret_pool;
2030  }
2031 
2032  return RetVal;
2033 }
2034 
2035 /*******************************************************************************/
2036 /* _SlSocketHandleAsync_StartTLS */
2037 /*******************************************************************************/
2038 _SlReturnVal_t _SlSocketHandleAsync_StartTLS(void *pVoidBuf)
2039 {
2040  _u8 ActionIndex;
2041 
2042  SlSocketAsyncEvent_t *pMsgArgs = (SlSocketAsyncEvent_t *)((_u32)pVoidBuf+sizeof(_u32));
2043 
2044  SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
2045 
2046  VERIFY_PROTOCOL((pMsgArgs->Sd & SL_BSD_SOCKET_ID_MASK) <= SL_MAX_SOCKETS);
2047 
2048  /* Match the action index*/
2049  for (ActionIndex = 0; ActionIndex < MAX_CONCURRENT_ACTIONS; ++ActionIndex)
2050  {
2051  if((g_pCB->ObjPool[ActionIndex].AdditionalData & 0x0F) == pMsgArgs->Sd && ((g_pCB->ObjPool[ActionIndex].ActionID) == START_TLS_ID))
2052  {
2053  break;
2054  }
2055  }
2056 
2057  if(ActionIndex == MAX_CONCURRENT_ACTIONS)
2058  {
2059  return EVENT_PROPAGATION_CONTINUE;
2060  }
2061 
2062  VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[ActionIndex].pRespArgs);
2063 
2064  ((SlSocketAsyncEvent_t *)(g_pCB->ObjPool[ActionIndex].pRespArgs))->Sd = pMsgArgs->Sd;
2065  ((SlSocketAsyncEvent_t *)(g_pCB->ObjPool[ActionIndex].pRespArgs))->Type = pMsgArgs->Type;
2066  ((SlSocketAsyncEvent_t *)(g_pCB->ObjPool[ActionIndex].pRespArgs))->Val = pMsgArgs->Val;
2067 
2068 
2069  SL_DRV_PROTECTION_OBJ_UNLOCK();
2070  if ((SL_SSL_NOTIFICATION_HANDSHAKE_FAILED == pMsgArgs->Type || SL_SSL_NOTIFICATION_CONNECTED_SECURED == pMsgArgs->Type))
2071  {
2072  SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[ActionIndex].SyncObj);
2073  return EVENT_PROPAGATION_BLOCK;
2074  }
2075  else
2076  {
2077  return EVENT_PROPAGATION_CONTINUE;
2078  }
2079 }
2080 #endif
_i16 sl_Bind(_i16 sd, const SlSockAddr_t *addr, _i16 addrlen)
Assign a name to a socket.
Definition: sl_socket.c:237
_u32 sl_Htonl(_u32 val)
Reorder the bytes of a 32-bit unsigned value.
Definition: sl_socket.c:806
_i16 sl_Select(_i16 nfds, SlFdSet_t *readsds, SlFdSet_t *writesds, SlFdSet_t *exceptsds, struct SlTimeval_t *timeout)
Monitor socket activity.
Definition: sl_socket.c:1523
void slcb_SocketTriggerEventHandler(SlSockTriggerEvent_t *pSlSockTriggerEvent)
Socket trigger routine. This routine will notify the application that a netwrok activity has been com...
_u32 slcb_GetTimestamp(void)
Get the timer counter value (timestamp). The timer must count from zero to its MAX value...
_i16 sl_StartTLS(_i16 sd)
Initiate TLS connection on a socket.
Definition: sl_socket.c:1971
_u16 sl_Htons(_u16 val)
Reorder the bytes of a 16-bit unsigned value.
Definition: sl_socket.c:827
_i16 sl_Close(_i16 sd)
Gracefully close socket.
Definition: sl_socket.c:176
_i16 sl_Recv(_i16 sd, void *pBuf, _i16 Len, _i16 flags)
Read data from TCP socket.
Definition: sl_socket.c:881
_i16 sl_GetSockOpt(_i16 sd, _i16 level, _i16 optname, void *optval, SlSocklen_t *optlen)
Get socket options.
Definition: sl_socket.c:975
_i16 sl_Socket(_i16 Domain, _i16 Type, _i16 Protocol)
Create an endpoint for communication.
Definition: sl_socket.c:133
_i16 sl_RecvFrom(_i16 sd, void *buf, _i16 Len, _i16 flags, SlSockAddr_t *from, SlSocklen_t *fromlen)
Read data from socket.
Definition: sl_socket.c:360
_i16 sl_Accept(_i16 sd, SlSockAddr_t *addr, SlSocklen_t *addrlen)
Accept a connection on a socket.
Definition: sl_socket.c:692
Definition: driver.h:323
_i16 sl_Connect(_i16 sd, const SlSockAddr_t *addr, _i16 addrlen)
Initiate a connection on a socket.
Definition: sl_socket.c:449
_i16 sl_Listen(_i16 sd, _i16 backlog)
Listen for connections on a socket.
Definition: sl_socket.c:658
_i16 sl_SendTo(_i16 sd, const void *pBuf, _i16 Len, _i16 flags, const SlSockAddr_t *to, SlSocklen_t tolen)
Write data to socket.
Definition: sl_socket.c:283
_i16 sl_Send(_i16 sd, const void *pBuf, _i16 Len, _i16 flags)
Write data to TCP socket.
Definition: sl_socket.c:594