SimpleLink CC31xx/CC32xx Host Driver  Version 3.0.1.71
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 - 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 /* ******************************************************************************/
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 (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 {
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 (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 /*******************************************************************************/
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 (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 /*******************************************************************************/
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(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 /*******************************************************************************/
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 /*******************************************************************************/
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 /*******************************************************************************/
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 /*******************************************************************************/
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 /*******************************************************************************/
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 /*******************************************************************************/
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 /* ******************************************************************************/
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  if(0xffff <= (timeout->tv_usec >> 10))
1569  {
1570  Msg.Cmd.tv_usec = 0xffff;
1571  }
1572  else
1573  {
1574  /* this divides by 1024 to fit the result in a int16_t.
1575  * Upon receiving, the NWP multiply this value by 1024. */
1576  Msg.Cmd.tv_usec = (_u16)(timeout->tv_usec >> 10);
1577  }
1578  }
1579 
1580  while(FALSE == isCaller)
1581  {
1582  SelectParams.ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&SelectParams.Response, SELECT_ID, SL_MAX_SOCKETS);
1583 
1584  if (SelectParams.ObjIdx < 0)
1585  {
1586  return SelectParams.ObjIdx;
1587  }
1588 
1589  SL_DRV_OBJ_LOCK_FOREVER(&g_pCB->MultiSelectCB.SelectLockObj);
1590 
1591  /* Check if no other 'Select' calls are in progress */
1592  if(FALSE == g_pCB->MultiSelectCB.ActiveSelect)
1593  {
1594  g_pCB->MultiSelectCB.ActiveSelect = TRUE;
1595  }
1596  else
1597  {
1598  SelectInProgress = TRUE;
1599  }
1600 
1601  if(!SelectInProgress)
1602  {
1603  ret = _SlDrvOpenCtrlSocket();
1604 
1605  if(ret < 0)
1606  {
1607  _SlDrvCloseCtrlSocket();
1608  g_pCB->MultiSelectCB.ActiveSelect = FALSE;
1609  SL_DRV_OBJ_UNLOCK(&g_pCB->MultiSelectCB.SelectLockObj);
1610  _SlDrvReleasePoolObj(SelectParams.ObjIdx);
1611  return ret;
1612  }
1613  else
1614  {
1615  /* All conditions are met for calling "Select" */
1616  isCaller = TRUE;
1617  }
1618  }
1619  else if(g_pCB->MultiSelectCB.CtrlSockFD == 0xFF)
1620  {
1621  _SlDrvReleasePoolObj(SelectParams.ObjIdx);
1622 
1623  /* This is not a first select caller and all sockets are open,
1624  * caller is expected to wait until select is inactive,
1625  * before trying to register again. */
1626  g_pCB->MultiSelectCB.ActiveWaiters++;
1627 
1628  SL_DRV_OBJ_UNLOCK(&g_pCB->MultiSelectCB.SelectLockObj);
1629 
1630  /* Wait here to be signaled by a successfully completed select caller */
1631 #if (defined (SL_PLATFORM_MULTI_THREADED)) && (!defined (SL_PLATFORM_EXTERNAL_SPAWN))
1632  if (_SlDrvIsSpawnOwnGlobalLock())
1633  {
1634  while (TRUE)
1635  {
1636  /* If we are in spawn context, this is an API which was called from event handler,
1637  read any async event and check if we got signaled */
1638  _SlInternalSpawnWaitForEvent();
1639  /* is it mine? */
1640  if (0 == sl_SyncObjWait(&g_pCB->MultiSelectCB.SelectSyncObj, SL_OS_NO_WAIT))
1641  {
1642  break;
1643  }
1644  }
1645  }
1646  else
1647 #endif
1648  {
1649  SL_DRV_SYNC_OBJ_WAIT_FOREVER(&g_pCB->MultiSelectCB.SelectSyncObj);
1650  }
1651 
1652 
1653  if((_i16)g_pCB->MultiSelectCB.SelectCmdResp.status != SL_RET_CODE_OK)
1654  {
1655  return (_i16)(g_pCB->MultiSelectCB.SelectCmdResp.status);
1656  }
1657 
1658  SelectInProgress = FALSE;
1659  }
1660  else
1661  {
1662  /* All conditions are met for calling "Select" */
1663  isCaller = TRUE;
1664  }
1665  }
1666 
1667  /* Register this caller details for an select Async event.
1668  * SelectLockObj is released inside this function,
1669  * right before sending 'Select' command. */
1670  ret = _SlDrvRegisterForSelectAsync(&SelectParams, &Msg, timeout, SelectInProgress);
1671 
1672  if(ret < 0)
1673  {
1674  return (_SlDrvUnRegisterForSelectAsync(&SelectParams, SelectInProgress));
1675  }
1676 
1677  /* Wait here for a Async event, or command response in case select fails.*/
1678  ret = _SlDrvWaitForInternalAsyncEvent(SelectParams.ObjIdx, 0, 0);
1679 
1680  _SlDrvReleasePoolObj(SelectParams.ObjIdx);
1681  if(ret < 0)
1682  {
1683  return ret;
1684  }
1685 
1686  ret = (_i16)g_pCB->MultiSelectCB.SelectCmdResp.status;
1687 
1688  if(ret == SL_RET_CODE_OK)
1689  {
1690  ret = (_i16)SelectParams.Response.Status;
1691 
1692  if(ret > SELECT_TIMEOUT)
1693  {
1694  if(readsds)
1695  {
1696  readsds->fd_array[0] = SelectParams.Response.ReadFds;
1697  }
1698 
1699  if(writesds)
1700  {
1701  writesds->fd_array[0] = SelectParams.Response.WriteFds;
1702  }
1703  }
1704  }
1705 
1706  return ret;
1707 }
1708 
1709 #else
1710 
1711 /*******************************************************************************/
1712 /* _SlSocketHandleAsync_Select */
1713 /*******************************************************************************/
1714 _SlReturnVal_t _SlSocketHandleAsync_Select(void *pVoidBuf)
1715 {
1716  SlSelectAsyncResponse_t *pMsgArgs = (SlSelectAsyncResponse_t *)_SL_RESP_ARGS_START(pVoidBuf);
1717 #if ((defined(SL_RUNTIME_EVENT_REGISTERATION) || defined(slcb_SocketTriggerEventHandler)))
1718  SlSockTriggerEvent_t SockTriggerEvent;
1719 #endif
1720 
1721  SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
1722 
1723  VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs);
1724 
1725  sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs, sizeof(SlSelectAsyncResponse_t));
1726 
1727 #if ((defined(SL_RUNTIME_EVENT_REGISTERATION) || defined(slcb_SocketTriggerEventHandler)))
1728  if(1 == _SlIsEventRegistered(SL_EVENT_HDL_SOCKET_TRIGGER))
1729  {
1730  if (g_pCB->SocketTriggerSelect.Info.State == SOCK_TRIGGER_WAITING_FOR_RESP)
1731  {
1732 
1733  SockTriggerEvent.Event = SL_SOCKET_TRIGGER_EVENT_SELECT;
1734  SockTriggerEvent.EventData = 0;
1735 
1736  g_pCB->SocketTriggerSelect.Info.State = SOCK_TRIGGER_RESP_RECEIVED;
1737 
1738  SL_DRV_PROTECTION_OBJ_UNLOCK();
1739 
1740  /* call the user handler */
1741  _SlDrvHandleSocketTriggerEvents(&SockTriggerEvent);
1742 
1743  return SL_OS_RET_CODE_OK;
1744  }
1745  else
1746  {
1747  SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj);
1748  }
1749  }
1750  else
1751 #endif
1752  {
1753 
1754  SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj);
1755  }
1756 
1757  SL_DRV_PROTECTION_OBJ_UNLOCK();
1758 
1759  return SL_OS_RET_CODE_OK;
1760 }
1761 
1762 _i16 sl_Select(_i16 nfds, SlFdSet_t *readsds, SlFdSet_t *writesds, SlFdSet_t *exceptsds, struct SlTimeval_t *timeout)
1763 {
1764  _SlSelectMsg_u Msg;
1765  SlSelectAsyncResponse_t AsyncRsp;
1766  _i16 ObjIdx = MAX_CONCURRENT_ACTIONS;
1767  _i16 ret = 0;
1768 #if ((defined(SL_RUNTIME_EVENT_REGISTERATION) || defined(slcb_SocketTriggerEventHandler)))
1769  _u8 IsNonBlocking = FALSE;
1770 #endif
1771 
1772  /* verify that this API is allowed. if not allowed then
1773  ignore the API execution and return immediately with an error */
1774  VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
1775 
1776 #if ((defined(SL_RUNTIME_EVENT_REGISTERATION) || defined(slcb_SocketTriggerEventHandler)))
1777  if(1 == _SlIsEventRegistered(SL_EVENT_HDL_SOCKET_TRIGGER))
1778  {
1779  if( NULL != timeout )
1780  {
1781  /* Set that we are in Non-Blocking mode */
1782  if ( (0 == timeout->tv_sec) && (0 == timeout->tv_usec) )
1783  {
1784  IsNonBlocking = TRUE;
1785  }
1786  else
1787  {
1788  SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
1789 
1790  /* If there is a trigger select running in the progress abort the new blocking request */
1791  if (g_pCB->SocketTriggerSelect.Info.State > SOCK_TRIGGER_READY)
1792  {
1793  SL_DRV_PROTECTION_OBJ_UNLOCK();
1794  return SL_RET_CODE_SOCKET_SELECT_IN_PROGRESS_ERROR;
1795  }
1796 
1797  SL_DRV_PROTECTION_OBJ_UNLOCK();
1798  }
1799 
1800  if (IsNonBlocking == TRUE)
1801  {
1802  /* return EAGAIN if we alreay have select trigger in progress */
1803  if (g_pCB->SocketTriggerSelect.Info.State == SOCK_TRIGGER_WAITING_FOR_RESP)
1804  {
1805  return SL_ERROR_BSD_EAGAIN;
1806  }
1807  /* return the stored response if already received */
1808  else if (g_pCB->SocketTriggerSelect.Info.State == SOCK_TRIGGER_RESP_RECEIVED)
1809  {
1810  if( ((_i16)g_pCB->SocketTriggerSelect.Resp.Status) >= 0 )
1811  {
1812  if( readsds )
1813  {
1814  readsds->fd_array[0] = g_pCB->SocketTriggerSelect.Resp.ReadFds;
1815  }
1816  if( writesds )
1817  {
1818  writesds->fd_array[0] = g_pCB->SocketTriggerSelect.Resp.WriteFds;
1819  }
1820  }
1821 
1822  /* Now relaese the pool object */
1823  _SlDrvReleasePoolObj(g_pCB->SocketTriggerSelect.Info.ObjPoolIdx);
1824 
1825  g_pCB->SocketTriggerSelect.Info.ObjPoolIdx = MAX_CONCURRENT_ACTIONS;
1826 
1827  /* Reset the socket select trigger object */
1828  g_pCB->SocketTriggerSelect.Info.State = SOCK_TRIGGER_READY;
1829 
1830  return (_i16)g_pCB->SocketTriggerSelect.Resp.Status;
1831  }
1832  }
1833  }
1834  }
1835 #endif
1836 
1837  Msg.Cmd.Nfds = (_u8)nfds;
1838  Msg.Cmd.ReadFdsCount = 0;
1839  Msg.Cmd.WriteFdsCount = 0;
1840 
1841  Msg.Cmd.ReadFds = 0;
1842  Msg.Cmd.WriteFds = 0;
1843 
1844 
1845  if( readsds )
1846  {
1847  Msg.Cmd.ReadFds = (_u16)readsds->fd_array[0];
1848  }
1849  if( writesds )
1850  {
1851  Msg.Cmd.WriteFds = (_u16)writesds->fd_array[0];
1852  }
1853  if( NULL == timeout )
1854  {
1855  Msg.Cmd.tv_sec = 0xffff;
1856  Msg.Cmd.tv_usec = 0xffff;
1857  }
1858  else
1859  {
1860  if( 0xffff <= timeout->tv_sec )
1861  {
1862  Msg.Cmd.tv_sec = 0xffff;
1863  }
1864  else
1865  {
1866  Msg.Cmd.tv_sec = (_u16)timeout->tv_sec;
1867  }
1868 
1869  /* convert to milliseconds */
1870  timeout->tv_usec = timeout->tv_usec >> 10;
1871 
1872  if( 0xffff <= timeout->tv_usec )
1873  {
1874  Msg.Cmd.tv_usec = 0xffff;
1875  }
1876  else
1877  {
1878  Msg.Cmd.tv_usec = (_u16)timeout->tv_usec;
1879  }
1880 
1881  }
1882 
1883  /* Use Obj to issue the command, if not available try later */
1884  ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&AsyncRsp, SELECT_ID, SL_MAX_SOCKETS);
1885 
1886  if (ObjIdx < 0)
1887  {
1888  return ObjIdx;
1889  }
1890 
1891  /* send the command */
1892  VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSelectCmdCtrl, &Msg, NULL));
1893 
1894  if(SL_OS_RET_CODE_OK == (_i16)Msg.Rsp.status)
1895  {
1896  ret = _SlDrvWaitForInternalAsyncEvent(ObjIdx,0,0);
1897 
1898  Msg.Rsp.status = (_i16)AsyncRsp.Status;
1899 
1900  /* this code handles the socket trigger mode case */
1901 #if((defined(SL_RUNTIME_EVENT_REGISTERATION) || defined(slcb_SocketTriggerEventHandler)))
1902  if(1 == _SlIsEventRegistered(SL_EVENT_HDL_SOCKET_TRIGGER))
1903  {
1904  /* if no data returned and we are in trigger mode,
1905  send another select cmd but now with timeout infinite,
1906  and return immediately with EAGAIN to the user */
1907  if ((IsNonBlocking == TRUE) && (AsyncRsp.Status == 0))
1908  {
1909  /* set the select trigger-in-progress bit */
1910  g_pCB->SocketTriggerSelect.Info.State = SOCK_TRIGGER_WAITING_FOR_RESP;
1911 
1912  Msg.Cmd.tv_sec = 0xffff;
1913  Msg.Cmd.tv_usec = 0xffff;
1914 
1915  /* Release pool object and try to take another call */
1916  _SlDrvReleasePoolObj(ObjIdx);
1917 
1918  if(ret < 0)
1919  {
1920  return ret;
1921  }
1922 
1923  /* Use Obj to issue the command, if not available try later */
1924  ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&g_pCB->SocketTriggerSelect.Resp, SELECT_ID, SL_MAX_SOCKETS);
1925 
1926  if (MAX_CONCURRENT_ACTIONS == ObjIdx)
1927  {
1928  return SL_POOL_IS_EMPTY;
1929  }
1930 
1931  /* Save the pool index to be released only after the user read the response */
1932  g_pCB->SocketTriggerSelect.Info.ObjPoolIdx = ObjIdx;
1933 
1934  /* send the command */
1935  VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSelectCmdCtrl, &Msg, NULL));
1936  return SL_ERROR_BSD_EAGAIN;
1937 
1938  }
1939  }
1940 #endif
1941 
1942  if( ((_i16)Msg.Rsp.status) >= 0 )
1943  {
1944  if( readsds )
1945  {
1946  readsds->fd_array[0] = AsyncRsp.ReadFds;
1947  }
1948  if( writesds )
1949  {
1950  writesds->fd_array[0] = AsyncRsp.WriteFds;
1951  }
1952  }
1953  }
1954 
1955  _SlDrvReleasePoolObj(ObjIdx);
1956 
1957  if(ret < 0)
1958  {
1959  return ret;
1960  }
1961 
1962  return (_i16)Msg.Rsp.status;
1963 }
1964 
1965 #endif /* defined(SL_PLATFORM_MULTI_THREADED) || !defined(slcb_SocketTriggerEventHandler) */
1966 #endif /* _SL_INCLUDE_FUNC(sl_Select) */
1967 
1968 /*******************************************************************************/
1969 /* sl_StartTLS */
1970 /*******************************************************************************/
1971 #if _SL_INCLUDE_FUNC(sl_StartTLS)
1972 _i16 sl_StartTLS(_i16 sd)
1973 {
1974  _SlReturnVal_t RetVal;
1975  SlSocketAsyncEvent_t AsyncRsp;
1976  _u32 tempValue;
1977  _i16 ObjIdx = MAX_CONCURRENT_ACTIONS;
1978  _i8 ret;
1979  int ret_pool = 0; // for _SlDrvReleasePoolObj
1980  SlEventsListNode_t startTLS;
1981  _u8 ActionIndex;
1982 
1983  /* verify that this api is allowed. if not allowed then
1984  ignore the API execution and return immediately with an error */
1985  VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
1986  _SlDrvMemZero(&AsyncRsp, sizeof(SlSocketAsyncEvent_t));
1987 
1988  /* Check if there already Object with ActionID "startTLS" on the same socket */
1989  for (ActionIndex = 0; ActionIndex < MAX_CONCURRENT_ACTIONS; ++ActionIndex)
1990  {
1991  if(((g_pCB->ObjPool[ActionIndex].AdditionalData & 0x0F) == sd) && ((g_pCB->ObjPool[ActionIndex].ActionID) == START_TLS_ID))
1992  {
1993  return SL_RET_CODE_STARTTLS_IN_PROGRESS_ON_THIS_SD;
1994  }
1995 
1996  }
1997 
1998  ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&AsyncRsp, START_TLS_ID, (_u8)(sd & SL_BSD_SOCKET_ID_MASK));
1999 
2000  if (ObjIdx < 0)
2001  {
2002  return ObjIdx;
2003  }
2004 
2005  startTLS.event = (void *)_SlSocketHandleAsync_StartTLS;
2006  sl_RegisterLibsEventHandler(SL_EVENT_HDL_SOCKET, &startTLS);
2007 
2008  /* send Start TLS to sl_SetSockOpt */
2009  RetVal = sl_SetSockOpt(sd, SL_SOL_SOCKET, SL_SO_STARTTLS, &tempValue, sizeof(tempValue));
2010 
2011  if(SL_RET_CODE_OK == RetVal)
2012  {
2013  /* wait for async and get Data Read parameters */
2014  ret_pool = _SlDrvWaitForInternalAsyncEvent(ObjIdx,0,0);
2015 
2016  VERIFY_PROTOCOL(AsyncRsp.Sd == (_u8)sd);
2017 
2018  RetVal = AsyncRsp.Val;
2019  }
2020 
2021  ret = sl_UnregisterLibsEventHandler(SL_EVENT_HDL_SOCKET, &startTLS);
2022  _SlDrvReleasePoolObj(ObjIdx);
2023  if(ret < 0)
2024  {
2025  return ret;
2026  }
2027 
2028  if(ret_pool < 0)
2029  {
2030  return ret_pool;
2031  }
2032 
2033  return RetVal;
2034 }
2035 
2036 /*******************************************************************************/
2037 /* _SlSocketHandleAsync_StartTLS */
2038 /*******************************************************************************/
2039 _SlReturnVal_t _SlSocketHandleAsync_StartTLS(void *pVoidBuf)
2040 {
2041  _u8 ActionIndex;
2042 
2043  SlSocketAsyncEvent_t *pMsgArgs = (SlSocketAsyncEvent_t *)((_u32)pVoidBuf+sizeof(_u32));
2044 
2045  SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
2046 
2047  VERIFY_PROTOCOL((pMsgArgs->Sd & SL_BSD_SOCKET_ID_MASK) <= SL_MAX_SOCKETS);
2048 
2049  /* Match the action index*/
2050  for (ActionIndex = 0; ActionIndex < MAX_CONCURRENT_ACTIONS; ++ActionIndex)
2051  {
2052  if((g_pCB->ObjPool[ActionIndex].AdditionalData & 0x0F) == pMsgArgs->Sd && ((g_pCB->ObjPool[ActionIndex].ActionID) == START_TLS_ID))
2053  {
2054  break;
2055  }
2056  }
2057 
2058  if(ActionIndex == MAX_CONCURRENT_ACTIONS)
2059  {
2060  return EVENT_PROPAGATION_CONTINUE;
2061  }
2062 
2063  VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[ActionIndex].pRespArgs);
2064 
2065  ((SlSocketAsyncEvent_t *)(g_pCB->ObjPool[ActionIndex].pRespArgs))->Sd = pMsgArgs->Sd;
2066  ((SlSocketAsyncEvent_t *)(g_pCB->ObjPool[ActionIndex].pRespArgs))->Type = pMsgArgs->Type;
2067  ((SlSocketAsyncEvent_t *)(g_pCB->ObjPool[ActionIndex].pRespArgs))->Val = pMsgArgs->Val;
2068 
2069 
2070  SL_DRV_PROTECTION_OBJ_UNLOCK();
2071  if ((SL_SSL_NOTIFICATION_HANDSHAKE_FAILED == pMsgArgs->Type || SL_SSL_NOTIFICATION_CONNECTED_SECURED == pMsgArgs->Type))
2072  {
2073  SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[ActionIndex].SyncObj);
2074  return EVENT_PROPAGATION_BLOCK;
2075  }
2076  else
2077  {
2078  return EVENT_PROPAGATION_CONTINUE;
2079  }
2080 }
2081 #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:1526
void slcb_SocketTriggerEventHandler(SlSockTriggerEvent_t *pSlSockTriggerEvent)
Socket trigger routine. This routine will notify the application that a netwrok activity has been com...
_i16 sl_SetSockOpt(_i16 sd, _i16 level, _i16 optname, const void *optval, SlSocklen_t optlen)
Set socket options.
Definition: sl_socket.c:932
_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:1972
_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