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