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