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