]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_Sockets.c
Very minor formatting changes, and remove legacy link to V8 upgrade information.
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-TCP / FreeRTOS_Sockets.c
1 /*\r
2  * FreeRTOS+TCP V2.0.7\r
3  * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
6  * this software and associated documentation files (the "Software"), to deal in\r
7  * the Software without restriction, including without limitation the rights to\r
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
9  * the Software, and to permit persons to whom the Software is furnished to do so,\r
10  * subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be included in all\r
13  * copies or substantial portions of the Software.\r
14  *\r
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
21  *\r
22  * http://aws.amazon.com/freertos\r
23  * http://www.FreeRTOS.org\r
24  */\r
25 \r
26 /* Standard includes. */\r
27 #include <stdint.h>\r
28 #include <stdio.h>\r
29 \r
30 /* FreeRTOS includes. */\r
31 #include "FreeRTOS.h"\r
32 #include "task.h"\r
33 #include "queue.h"\r
34 #include "semphr.h"\r
35 \r
36 /* FreeRTOS+TCP includes. */\r
37 #include "FreeRTOS_UDP_IP.h"\r
38 #include "FreeRTOS_IP.h"\r
39 #include "FreeRTOS_Sockets.h"\r
40 #include "FreeRTOS_IP_Private.h"\r
41 #include "FreeRTOS_DNS.h"\r
42 #include "NetworkBufferManagement.h"\r
43 \r
44 /* The ItemValue of the sockets xBoundSocketListItem member holds the socket's\r
45 port number. */\r
46 #define socketSET_SOCKET_PORT( pxSocket, usPort ) listSET_LIST_ITEM_VALUE( ( &( ( pxSocket )->xBoundSocketListItem ) ), ( usPort ) )\r
47 #define socketGET_SOCKET_PORT( pxSocket ) listGET_LIST_ITEM_VALUE( ( &( ( pxSocket )->xBoundSocketListItem ) ) )\r
48 \r
49 /* Test if a socket it bound which means it is either included in\r
50 xBoundUDPSocketsList or xBoundTCPSocketsList */\r
51 #define socketSOCKET_IS_BOUND( pxSocket )         ( listLIST_ITEM_CONTAINER( & ( pxSocket )->xBoundSocketListItem ) != NULL )\r
52 \r
53 /* If FreeRTOS_sendto() is called on a socket that is not bound to a port\r
54 number then, depending on the FreeRTOSIPConfig.h settings, it might be that a\r
55 port number is automatically generated for the socket.  Automatically generated\r
56 port numbers will be between socketAUTO_PORT_ALLOCATION_START_NUMBER and\r
57 0xffff.\r
58 \r
59 Per https://tools.ietf.org/html/rfc6056, "the dynamic ports consist of the range\r
60 49152-65535. However, ephemeral port selection algorithms should use the whole\r
61 range 1024-65535" excluding those already in use (inbound or outbound). */\r
62 #if !defined( socketAUTO_PORT_ALLOCATION_START_NUMBER )\r
63         #define socketAUTO_PORT_ALLOCATION_START_NUMBER ( ( uint16_t ) 0x0400 )\r
64 #endif\r
65 \r
66 #define socketAUTO_PORT_ALLOCATION_MAX_NUMBER   ( ( uint16_t ) 0xffff )\r
67 \r
68 /* The number of octets that make up an IP address. */\r
69 #define socketMAX_IP_ADDRESS_OCTETS             4u\r
70 \r
71 /* A block time of 0 simply means "don't block". */\r
72 #define socketDONT_BLOCK                                ( ( TickType_t ) 0 )\r
73 \r
74 #if( ( ipconfigUSE_TCP == 1 ) && !defined( ipTCP_TIMER_PERIOD_MS ) )\r
75         #define ipTCP_TIMER_PERIOD_MS   ( 1000 )\r
76 #endif\r
77 \r
78 /* The next private port number to use when binding a client socket is stored in\r
79 the usNextPortToUse[] array - which has either 1 or two indexes depending on\r
80 whether TCP is being supported. */\r
81 #if( ipconfigUSE_TCP == 1 )\r
82         #define socketPROTOCOL_COUNT            2\r
83 #else\r
84         #define socketPROTOCOL_COUNT            1\r
85 #endif\r
86 \r
87 /* Indexes into the usNextPortToUse[] array for UDP and TCP sockets\r
88 respectively. */\r
89 #define socketNEXT_UDP_PORT_NUMBER_INDEX        0\r
90 #define socketNEXT_TCP_PORT_NUMBER_INDEX        1\r
91 \r
92 \r
93 /*-----------------------------------------------------------*/\r
94 \r
95 /*\r
96  * Allocate the next port number from the private allocation range.\r
97  * TCP and UDP each have their own series of port numbers\r
98  * ulProtocol is either ipPROTOCOL_UDP or ipPROTOCOL_TCP\r
99  */\r
100 static uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol );\r
101 \r
102 /*\r
103  * Return the list item from within pxList that has an item value of\r
104  * xWantedItemValue.  If there is no such list item return NULL.\r
105  */\r
106 static const ListItem_t * pxListFindListItemWithValue( const List_t *pxList, TickType_t xWantedItemValue );\r
107 \r
108 /*\r
109  * Return pdTRUE only if pxSocket is valid and bound, as far as can be\r
110  * determined.\r
111  */\r
112 static BaseType_t prvValidSocket( FreeRTOS_Socket_t *pxSocket, BaseType_t xProtocol, BaseType_t xIsBound );\r
113 \r
114 /*\r
115  * Before creating a socket, check the validity of the parameters used\r
116  * and find the size of the socket space, which is different for UDP and TCP\r
117  */\r
118 static BaseType_t prvDetermineSocketSize( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol, size_t *pxSocketSize );\r
119 \r
120 #if( ipconfigUSE_TCP == 1 )\r
121         /*\r
122          * Create a txStream or a rxStream, depending on the parameter 'xIsInputStream'\r
123          */\r
124         static StreamBuffer_t *prvTCPCreateStream (FreeRTOS_Socket_t *pxSocket, BaseType_t xIsInputStream );\r
125 #endif /* ipconfigUSE_TCP == 1 */\r
126 \r
127 #if( ipconfigUSE_TCP == 1 )\r
128         /*\r
129          * Called from FreeRTOS_send(): some checks which will be done before\r
130          * sending a TCP packed.\r
131          */\r
132         static int32_t prvTCPSendCheck( FreeRTOS_Socket_t *pxSocket, size_t xDataLength );\r
133 #endif /* ipconfigUSE_TCP */\r
134 \r
135 #if( ipconfigUSE_TCP == 1 )\r
136         /*\r
137          * When a child socket gets closed, make sure to update the child-count of the parent\r
138          */\r
139         static void prvTCPSetSocketCount( FreeRTOS_Socket_t *pxSocketToDelete );\r
140 #endif  /* ipconfigUSE_TCP == 1 */\r
141 \r
142 #if( ipconfigUSE_TCP == 1 )\r
143         /*\r
144          * Called from FreeRTOS_connect(): make some checks and if allowed, send a\r
145          * message to the IP-task to start connecting to a remote socket\r
146          */\r
147         static BaseType_t prvTCPConnectStart( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr *pxAddress );\r
148 #endif /* ipconfigUSE_TCP */\r
149 \r
150 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
151 \r
152         /* Executed by the IP-task, it will check all sockets belonging to a set */\r
153         static FreeRTOS_Socket_t *prvFindSelectedSocket( SocketSelect_t *pxSocketSet );\r
154 \r
155 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */\r
156 /*-----------------------------------------------------------*/\r
157 \r
158 /* The list that contains mappings between sockets and port numbers.  Accesses\r
159 to this list must be protected by critical sections of one kind or another. */\r
160 List_t xBoundUDPSocketsList;\r
161 \r
162 #if ipconfigUSE_TCP == 1\r
163         List_t xBoundTCPSocketsList;\r
164 #endif /* ipconfigUSE_TCP == 1 */\r
165 \r
166 /*-----------------------------------------------------------*/\r
167 \r
168 static BaseType_t prvValidSocket( FreeRTOS_Socket_t *pxSocket, BaseType_t xProtocol, BaseType_t xIsBound )\r
169 {\r
170 BaseType_t xReturn = pdTRUE;\r
171 \r
172         if( ( pxSocket == NULL ) || ( pxSocket == FREERTOS_INVALID_SOCKET ) )\r
173         {\r
174                 xReturn = pdFALSE;\r
175         }\r
176         else if( ( xIsBound != pdFALSE ) && ( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE ) )\r
177         {\r
178                 /* The caller expects the socket to be bound, but it isn't. */\r
179                 xReturn = pdFALSE;\r
180         }\r
181         else if( pxSocket->ucProtocol != ( uint8_t ) xProtocol )\r
182         {\r
183                 /* Socket has a wrong type (UDP != TCP). */\r
184                 xReturn = pdFALSE;\r
185         }\r
186 \r
187         return xReturn;\r
188 }\r
189 /*-----------------------------------------------------------*/\r
190 \r
191 BaseType_t vNetworkSocketsInit( void )\r
192 {\r
193         vListInitialise( &xBoundUDPSocketsList );\r
194 \r
195         #if( ipconfigUSE_TCP == 1 )\r
196         {\r
197                 vListInitialise( &xBoundTCPSocketsList );\r
198         }\r
199         #endif  /* ipconfigUSE_TCP == 1 */\r
200 \r
201         return pdTRUE;\r
202 }\r
203 /*-----------------------------------------------------------*/\r
204 \r
205 static BaseType_t prvDetermineSocketSize( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol, size_t *pxSocketSize )\r
206 {\r
207 BaseType_t xReturn = pdPASS;\r
208 FreeRTOS_Socket_t *pxSocket;\r
209 \r
210         /* Asserts must not appear before it has been determined that the network\r
211         task is ready - otherwise the asserts will fail. */\r
212         if( xIPIsNetworkTaskReady() == pdFALSE )\r
213         {\r
214                 xReturn = pdFAIL;\r
215         }\r
216         else\r
217         {\r
218                 /* Only Ethernet is currently supported. */\r
219                 configASSERT( xDomain == FREERTOS_AF_INET );\r
220 \r
221                 /* Check if the UDP socket-list has been initialised. */\r
222                 configASSERT( listLIST_IS_INITIALISED( &xBoundUDPSocketsList ) );\r
223                 #if( ipconfigUSE_TCP == 1 )\r
224                 {\r
225                         /* Check if the TCP socket-list has been initialised. */\r
226                         configASSERT( listLIST_IS_INITIALISED( &xBoundTCPSocketsList ) );\r
227                 }\r
228                 #endif  /* ipconfigUSE_TCP == 1 */\r
229 \r
230                 if( xProtocol == FREERTOS_IPPROTO_UDP )\r
231                 {\r
232                         if( xType != FREERTOS_SOCK_DGRAM )\r
233                         {\r
234                                 xReturn = pdFAIL;\r
235                                 configASSERT( xReturn );\r
236                         }\r
237                         /* In case a UDP socket is created, do not allocate space for TCP data. */\r
238                         *pxSocketSize = ( sizeof( *pxSocket ) - sizeof( pxSocket->u ) ) + sizeof( pxSocket->u.xUDP );\r
239                 }\r
240 #if( ipconfigUSE_TCP == 1 )\r
241                 else if( xProtocol == FREERTOS_IPPROTO_TCP )\r
242                 {\r
243                         if( xType != FREERTOS_SOCK_STREAM )\r
244                         {\r
245                                 xReturn = pdFAIL;\r
246                                 configASSERT( xReturn );\r
247                         }\r
248 \r
249                         *pxSocketSize = ( sizeof( *pxSocket ) - sizeof( pxSocket->u ) ) + sizeof( pxSocket->u.xTCP );\r
250                 }\r
251 #endif  /* ipconfigUSE_TCP == 1 */\r
252                 else\r
253                 {\r
254                         xReturn = pdFAIL;\r
255                         configASSERT( xReturn );\r
256                 }\r
257         }\r
258         /* In case configASSERT() is not used */\r
259         ( void )xDomain;\r
260         return xReturn;\r
261 }\r
262 /*-----------------------------------------------------------*/\r
263 \r
264 /* FreeRTOS_socket() allocates and initiates a socket */\r
265 Socket_t FreeRTOS_socket( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol )\r
266 {\r
267 FreeRTOS_Socket_t *pxSocket;\r
268 size_t uxSocketSize;\r
269 EventGroupHandle_t xEventGroup;\r
270 Socket_t xReturn;\r
271 \r
272         if( prvDetermineSocketSize( xDomain, xType, xProtocol, &uxSocketSize ) == pdFAIL )\r
273         {\r
274                 xReturn = FREERTOS_INVALID_SOCKET;\r
275         }\r
276         else\r
277         {\r
278                 /* Allocate the structure that will hold the socket information.  The\r
279                 size depends on the type of socket: UDP sockets need less space.  A\r
280                 define 'pvPortMallocSocket' will used to allocate the necessary space.\r
281                 By default it points to the FreeRTOS function 'pvPortMalloc()'. */\r
282                 pxSocket = ( FreeRTOS_Socket_t * ) pvPortMallocSocket( uxSocketSize );\r
283 \r
284                 if( pxSocket == NULL )\r
285                 {\r
286                         pxSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;\r
287                         iptraceFAILED_TO_CREATE_SOCKET();\r
288                 }\r
289                 else if( ( xEventGroup = xEventGroupCreate() ) == NULL )\r
290                 {\r
291                         vPortFreeSocket( pxSocket );\r
292                         pxSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;\r
293                         iptraceFAILED_TO_CREATE_EVENT_GROUP();\r
294                 }\r
295                 else\r
296                 {\r
297                         /* Clear the entire space to avoid nulling individual entries */\r
298                         memset( pxSocket, '\0', uxSocketSize );\r
299 \r
300                         pxSocket->xEventGroup = xEventGroup;\r
301 \r
302                         /* Initialise the socket's members.  The semaphore will be created\r
303                         if the socket is bound to an address, for now the pointer to the\r
304                         semaphore is just set to NULL to show it has not been created. */\r
305                         if( xProtocol == FREERTOS_IPPROTO_UDP )\r
306                         {\r
307                                 vListInitialise( &( pxSocket->u.xUDP.xWaitingPacketsList ) );\r
308 \r
309                                 #if( ipconfigUDP_MAX_RX_PACKETS > 0 )\r
310                                 {\r
311                                         pxSocket->u.xUDP.uxMaxPackets = ( UBaseType_t ) ipconfigUDP_MAX_RX_PACKETS;\r
312                                 }\r
313                                 #endif /* ipconfigUDP_MAX_RX_PACKETS > 0 */\r
314                         }\r
315 \r
316                         vListInitialiseItem( &( pxSocket->xBoundSocketListItem ) );\r
317                         listSET_LIST_ITEM_OWNER( &( pxSocket->xBoundSocketListItem ), ( void * ) pxSocket );\r
318 \r
319                         pxSocket->xReceiveBlockTime = ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME;\r
320                         pxSocket->xSendBlockTime        = ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME;\r
321                         pxSocket->ucSocketOptions   = ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT;\r
322                         pxSocket->ucProtocol            = ( uint8_t ) xProtocol; /* protocol: UDP or TCP */\r
323 \r
324                         #if( ipconfigUSE_TCP == 1 )\r
325                         {\r
326                                 if( xProtocol == FREERTOS_IPPROTO_TCP )\r
327                                 {\r
328                                         /* StreamSize is expressed in number of bytes */\r
329                                         /* Round up buffer sizes to nearest multiple of MSS */\r
330                                         pxSocket->u.xTCP.usInitMSS      = pxSocket->u.xTCP.usCurMSS = ipconfigTCP_MSS;\r
331                                         pxSocket->u.xTCP.uxRxStreamSize = ( size_t ) ipconfigTCP_RX_BUFFER_LENGTH;\r
332                                         pxSocket->u.xTCP.uxTxStreamSize = ( size_t ) FreeRTOS_round_up( ipconfigTCP_TX_BUFFER_LENGTH, ipconfigTCP_MSS );\r
333                                         /* Use half of the buffer size of the TCP windows */\r
334                                         #if ( ipconfigUSE_TCP_WIN == 1 )\r
335                                         {\r
336                                                 pxSocket->u.xTCP.uxRxWinSize  = FreeRTOS_max_uint32( 1UL, ( uint32_t ) ( pxSocket->u.xTCP.uxRxStreamSize / 2 ) / ipconfigTCP_MSS );\r
337                                                 pxSocket->u.xTCP.uxTxWinSize  = FreeRTOS_max_uint32( 1UL, ( uint32_t ) ( pxSocket->u.xTCP.uxTxStreamSize / 2 ) / ipconfigTCP_MSS );\r
338                                         }\r
339                                         #else\r
340                                         {\r
341                                                 pxSocket->u.xTCP.uxRxWinSize  = 1u;\r
342                                                 pxSocket->u.xTCP.uxTxWinSize  = 1u;\r
343                                         }\r
344                                         #endif\r
345                                         /* The above values are just defaults, and can be overridden by\r
346                                         calling FreeRTOS_setsockopt().  No buffers will be allocated until a\r
347                                         socket is connected and data is exchanged. */\r
348                                 }\r
349                         }\r
350                         #endif  /* ipconfigUSE_TCP == 1 */\r
351                 }\r
352 \r
353                 xReturn = ( Socket_t ) pxSocket;\r
354         }\r
355 \r
356         /* Remove compiler warnings in the case the configASSERT() is not defined. */\r
357         ( void ) xDomain;\r
358 \r
359         return xReturn;\r
360 }\r
361 /*-----------------------------------------------------------*/\r
362 \r
363 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
364 \r
365         SocketSet_t FreeRTOS_CreateSocketSet( void )\r
366         {\r
367         SocketSelect_t *pxSocketSet;\r
368 \r
369                 pxSocketSet = ( SocketSelect_t * ) pvPortMalloc( sizeof( *pxSocketSet ) );\r
370 \r
371                 if( pxSocketSet != NULL )\r
372                 {\r
373                         memset( pxSocketSet, '\0', sizeof( *pxSocketSet ) );\r
374                         pxSocketSet->xSelectGroup = xEventGroupCreate();\r
375 \r
376                         if( pxSocketSet->xSelectGroup == NULL )\r
377                         {\r
378                                 vPortFree( ( void* ) pxSocketSet );\r
379                                 pxSocketSet = NULL;\r
380                         }\r
381                 }\r
382 \r
383                 return ( SocketSet_t * ) pxSocketSet;\r
384         }\r
385 \r
386 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */\r
387 /*-----------------------------------------------------------*/\r
388 \r
389 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
390 \r
391         void FreeRTOS_DeleteSocketSet( SocketSet_t xSocketSet )\r
392         {\r
393                 SocketSelect_t *pxSocketSet = ( SocketSelect_t*) xSocketSet;\r
394 \r
395                 vEventGroupDelete( pxSocketSet->xSelectGroup );\r
396                 vPortFree( ( void* ) pxSocketSet );\r
397         }\r
398 \r
399 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */\r
400 /*-----------------------------------------------------------*/\r
401 \r
402 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
403 \r
404         /* Add a socket to a set */\r
405         void FreeRTOS_FD_SET( Socket_t xSocket, SocketSet_t xSocketSet, EventBits_t xSelectBits )\r
406         {\r
407         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
408         SocketSelect_t *pxSocketSet = ( SocketSelect_t * ) xSocketSet;\r
409 \r
410                 configASSERT( pxSocket != NULL );\r
411                 configASSERT( xSocketSet != NULL );\r
412 \r
413                 /* Make sure we're not adding bits which are reserved for internal use,\r
414                 such as eSELECT_CALL_IP */\r
415                 pxSocket->xSelectBits |= ( xSelectBits & eSELECT_ALL );\r
416 \r
417                 if( ( pxSocket->xSelectBits & eSELECT_ALL ) != 0 )\r
418                 {\r
419                         /* Adding a socket to a socket set. */\r
420                         pxSocket->pxSocketSet = ( SocketSelect_t * ) xSocketSet;\r
421 \r
422                         /* Now have the IP-task call vSocketSelect() to see if the set contains\r
423                         any sockets which are 'ready' and set the proper bits.\r
424                         By setting 'bApiCalled = false', vSocketSelect() knows that it was\r
425                         not called from a user API */\r
426                         pxSocketSet->bApiCalled = pdFALSE;\r
427                         prvFindSelectedSocket( pxSocketSet );\r
428                 }\r
429         }\r
430 \r
431 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */\r
432 /*-----------------------------------------------------------*/\r
433 \r
434 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
435         /* Clear select bits for a socket\r
436         If the mask becomes 0, remove the socket from the set */\r
437         void FreeRTOS_FD_CLR( Socket_t xSocket, SocketSet_t xSocketSet, EventBits_t xSelectBits )\r
438         {\r
439         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
440 \r
441                 configASSERT( pxSocket != NULL );\r
442                 configASSERT( xSocketSet != NULL );\r
443 \r
444                 pxSocket->xSelectBits &= ~( xSelectBits & eSELECT_ALL );\r
445                 if( ( pxSocket->xSelectBits & eSELECT_ALL ) != 0 )\r
446                 {\r
447                         pxSocket->pxSocketSet = ( SocketSelect_t *)xSocketSet;\r
448                 }\r
449                 else\r
450                 {\r
451                         /* disconnect it from the socket set */\r
452                         pxSocket->pxSocketSet = ( SocketSelect_t *)NULL;\r
453                 }\r
454         }\r
455 \r
456 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */\r
457 /*-----------------------------------------------------------*/\r
458 \r
459 \r
460 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
461 \r
462         /* Test if a socket belongs to a socket-set */\r
463         EventBits_t FreeRTOS_FD_ISSET( Socket_t xSocket, SocketSet_t xSocketSet )\r
464         {\r
465         EventBits_t xReturn;\r
466         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
467 \r
468                 configASSERT( pxSocket != NULL );\r
469                 configASSERT( xSocketSet != NULL );\r
470 \r
471                 if( xSocketSet == ( SocketSet_t ) pxSocket->pxSocketSet )\r
472                 {\r
473                         /* Make sure we're not adding bits which are reserved for internal\r
474                         use. */\r
475                         xReturn = pxSocket->xSocketBits & eSELECT_ALL;\r
476                 }\r
477                 else\r
478                 {\r
479                         xReturn = 0;\r
480                 }\r
481 \r
482                 return xReturn;\r
483         }\r
484 \r
485 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */\r
486 /*-----------------------------------------------------------*/\r
487 \r
488 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
489 \r
490         /* The select() statement: wait for an event to occur on any of the sockets\r
491         included in a socket set */\r
492         BaseType_t FreeRTOS_select( SocketSet_t xSocketSet, TickType_t xBlockTimeTicks )\r
493         {\r
494         TimeOut_t xTimeOut;\r
495         TickType_t xRemainingTime;\r
496         SocketSelect_t *pxSocketSet = ( SocketSelect_t*) xSocketSet;\r
497         BaseType_t xResult;\r
498 \r
499                 configASSERT( xSocketSet != NULL );\r
500 \r
501                 /* Only in the first round, check for non-blocking */\r
502                 xRemainingTime = xBlockTimeTicks;\r
503 \r
504                 /* Fetch the current time */\r
505                 vTaskSetTimeOutState( &xTimeOut );\r
506 \r
507                 for( ;; )\r
508                 {\r
509                         /* Find a socket which might have triggered the bit\r
510                         This function might return immediately or block for a limited time */\r
511                         xResult = ( BaseType_t ) xEventGroupWaitBits( pxSocketSet->xSelectGroup, eSELECT_ALL, pdFALSE, pdFALSE, xRemainingTime );\r
512 \r
513                         #if( ipconfigSUPPORT_SIGNALS != 0 )\r
514                         {\r
515                                 if( ( xResult & eSELECT_INTR ) != 0u )\r
516                                 {\r
517                                         xEventGroupClearBits( pxSocketSet->xSelectGroup, eSELECT_INTR );\r
518                                         FreeRTOS_debug_printf( ( "FreeRTOS_select: interrupted\n" ) );\r
519                                         break;\r
520                                 }\r
521                         }\r
522                         #endif /* ipconfigSUPPORT_SIGNALS */\r
523 \r
524                         /* Have the IP-task find the socket which had an event */\r
525                         pxSocketSet->bApiCalled = pdTRUE;\r
526                         prvFindSelectedSocket( pxSocketSet );\r
527 \r
528                         xResult = ( BaseType_t ) xEventGroupGetBits( pxSocketSet->xSelectGroup );\r
529 \r
530                         if( xResult != 0 )\r
531                         {\r
532                                 break;\r
533                         }\r
534 \r
535                         /* Has the timeout been reached? */\r
536                         if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )\r
537                         {\r
538                                 break;\r
539                         }\r
540                 }\r
541 \r
542                 return xResult;\r
543         }\r
544 \r
545 #endif /* ipconfigSUPPORT_SELECT_FUNCTION */\r
546 /*-----------------------------------------------------------*/\r
547 \r
548 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
549 \r
550         /* Send a message to the IP-task to have it check all sockets belonging to\r
551         'pxSocketSet' */\r
552         static FreeRTOS_Socket_t *prvFindSelectedSocket( SocketSelect_t *pxSocketSet )\r
553         {\r
554         IPStackEvent_t xSelectEvent;\r
555         FreeRTOS_Socket_t *xReturn;\r
556 \r
557                 xSelectEvent.eEventType = eSocketSelectEvent;\r
558                 xSelectEvent.pvData = ( void * ) pxSocketSet;\r
559 \r
560                 /* while the IP-task works on the request, the API will block on\r
561                 'eSELECT_CALL_IP'.  So clear it first. */\r
562                 xEventGroupClearBits( pxSocketSet->xSelectGroup, eSELECT_CALL_IP );\r
563 \r
564                 /* Now send the socket select event */\r
565                 if( xSendEventStructToIPTask( &xSelectEvent, ( TickType_t ) portMAX_DELAY ) == pdFAIL )\r
566                 {\r
567                         /* Oops, we failed to wake-up the IP task. No use to wait for it. */\r
568                         FreeRTOS_debug_printf( ( "prvFindSelectedSocket: failed\n" ) );\r
569                         xReturn = NULL;\r
570                 }\r
571                 else\r
572                 {\r
573                         /* As soon as the IP-task is ready, it will set 'eSELECT_CALL_IP' to\r
574                         wakeup the calling API */\r
575                         xEventGroupWaitBits( pxSocketSet->xSelectGroup, eSELECT_CALL_IP, pdTRUE, pdFALSE, portMAX_DELAY );\r
576 \r
577                         /* Return 'pxSocket' which is set by the IP-task */\r
578                         xReturn = pxSocketSet->pxSocket;\r
579                 }\r
580 \r
581                 return xReturn;\r
582         }\r
583 \r
584 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */\r
585 /*-----------------------------------------------------------*/\r
586 \r
587 /*\r
588  * FreeRTOS_recvfrom: receive data from a bound socket\r
589  * In this library, the function can only be used with connectionsless sockets\r
590  * (UDP)\r
591  */\r
592 int32_t FreeRTOS_recvfrom( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags, struct freertos_sockaddr *pxSourceAddress, socklen_t *pxSourceAddressLength )\r
593 {\r
594 BaseType_t lPacketCount = 0;\r
595 NetworkBufferDescriptor_t *pxNetworkBuffer;\r
596 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
597 TickType_t xRemainingTime = ( TickType_t ) 0; /* Obsolete assignment, but some compilers output a warning if its not done. */\r
598 BaseType_t xTimed = pdFALSE;\r
599 TimeOut_t xTimeOut;\r
600 int32_t lReturn;\r
601 EventBits_t xEventBits = ( EventBits_t ) 0;\r
602 \r
603         if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_UDP, pdTRUE ) == pdFALSE )\r
604         {\r
605                 return -pdFREERTOS_ERRNO_EINVAL;\r
606         }\r
607 \r
608         lPacketCount = ( BaseType_t ) listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) );\r
609 \r
610         /* The function prototype is designed to maintain the expected Berkeley\r
611         sockets standard, but this implementation does not use all the parameters. */\r
612         ( void ) pxSourceAddressLength;\r
613 \r
614         while( lPacketCount == 0 )\r
615         {\r
616                 if( xTimed == pdFALSE )\r
617                 {\r
618                         /* Check to see if the socket is non blocking on the first\r
619                         iteration.  */\r
620                         xRemainingTime = pxSocket->xReceiveBlockTime;\r
621 \r
622                         if( xRemainingTime == ( TickType_t ) 0 )\r
623                         {\r
624                                 #if( ipconfigSUPPORT_SIGNALS != 0 )\r
625                                 {\r
626                                         /* Just check for the interrupt flag. */\r
627                                         xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_INTR,\r
628                                                 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, socketDONT_BLOCK );\r
629                                 }\r
630                                 #endif /* ipconfigSUPPORT_SIGNALS */\r
631                                 break;\r
632                         }\r
633 \r
634                         if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )\r
635                         {\r
636                                 break;\r
637                         }\r
638 \r
639                         /* To ensure this part only executes once. */\r
640                         xTimed = pdTRUE;\r
641 \r
642                         /* Fetch the current time. */\r
643                         vTaskSetTimeOutState( &xTimeOut );\r
644                 }\r
645 \r
646                 /* Wait for arrival of data.  While waiting, the IP-task may set the\r
647                 'eSOCKET_RECEIVE' bit in 'xEventGroup', if it receives data for this\r
648                 socket, thus unblocking this API call. */\r
649                 xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_RECEIVE | eSOCKET_INTR,\r
650                         pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );\r
651 \r
652                 #if( ipconfigSUPPORT_SIGNALS != 0 )\r
653                 {\r
654                         if( ( xEventBits & eSOCKET_INTR ) != 0 )\r
655                         {\r
656                                 if( ( xEventBits & eSOCKET_RECEIVE ) != 0 )\r
657                                 {\r
658                                         /* Shouldn't have cleared the eSOCKET_RECEIVE flag. */\r
659                                         xEventGroupSetBits( pxSocket->xEventGroup, eSOCKET_RECEIVE );\r
660                                 }\r
661                                 break;\r
662                         }\r
663                 }\r
664                 #else\r
665                 {\r
666                         ( void ) xEventBits;\r
667                 }\r
668                 #endif /* ipconfigSUPPORT_SIGNALS */\r
669 \r
670                 lPacketCount = ( BaseType_t ) listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) );\r
671 \r
672                 if( lPacketCount != 0 )\r
673                 {\r
674                         break;\r
675                 }\r
676 \r
677                 /* Has the timeout been reached ? */\r
678                 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) )\r
679                 {\r
680                         break;\r
681                 }\r
682         } /* while( lPacketCount == 0 ) */\r
683 \r
684         if( lPacketCount != 0 )\r
685         {\r
686                 taskENTER_CRITICAL();\r
687                 {\r
688                         /* The owner of the list item is the network buffer. */\r
689                         pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &( pxSocket->u.xUDP.xWaitingPacketsList ) );\r
690 \r
691                         if( ( xFlags & FREERTOS_MSG_PEEK ) == 0 )\r
692                         {\r
693                                 /* Remove the network buffer from the list of buffers waiting to\r
694                                 be processed by the socket. */\r
695                                 uxListRemove( &( pxNetworkBuffer->xBufferListItem ) );\r
696                         }\r
697                 }\r
698                 taskEXIT_CRITICAL();\r
699 \r
700                 /* The returned value is the data length, which may have been capped to\r
701                 the receive buffer size. */\r
702                 lReturn = ( int32_t ) pxNetworkBuffer->xDataLength;\r
703 \r
704                 if( pxSourceAddress != NULL )\r
705                 {\r
706                         pxSourceAddress->sin_port = pxNetworkBuffer->usPort;\r
707                         pxSourceAddress->sin_addr = pxNetworkBuffer->ulIPAddress;\r
708                 }\r
709 \r
710                 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )\r
711                 {\r
712                         /* The zero copy flag is not set.  Truncate the length if it won't\r
713                         fit in the provided buffer. */\r
714                         if( lReturn > ( int32_t ) xBufferLength )\r
715                         {\r
716                                 iptraceRECVFROM_DISCARDING_BYTES( ( xBufferLength - lReturn ) );\r
717                                 lReturn = ( int32_t )xBufferLength;\r
718                         }\r
719 \r
720                         /* Copy the received data into the provided buffer, then release the\r
721                         network buffer. */\r
722                         memcpy( pvBuffer, ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ), ( size_t )lReturn );\r
723 \r
724                         if( ( xFlags & FREERTOS_MSG_PEEK ) == 0 )\r
725                         {\r
726                                 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
727                         }\r
728                 }\r
729                 else\r
730                 {\r
731                         /* The zero copy flag was set.  pvBuffer is not a buffer into which\r
732                         the received data can be copied, but a pointer that must be set to\r
733                         point to the buffer in which the received data has already been\r
734                         placed. */\r
735                         *( ( void** ) pvBuffer ) = ( void * ) ( &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ) );\r
736                 }\r
737 \r
738         }\r
739 #if( ipconfigSUPPORT_SIGNALS != 0 )\r
740         else if( ( xEventBits & eSOCKET_INTR ) != 0 )\r
741         {\r
742                 lReturn = -pdFREERTOS_ERRNO_EINTR;\r
743                 iptraceRECVFROM_INTERRUPTED();\r
744         }\r
745 #endif /* ipconfigSUPPORT_SIGNALS */\r
746         else\r
747         {\r
748                 lReturn = -pdFREERTOS_ERRNO_EWOULDBLOCK;\r
749                 iptraceRECVFROM_TIMEOUT();\r
750         }\r
751 \r
752         return lReturn;\r
753 }\r
754 /*-----------------------------------------------------------*/\r
755 \r
756 int32_t FreeRTOS_sendto( Socket_t xSocket, const void *pvBuffer, size_t xTotalDataLength, BaseType_t xFlags, const struct freertos_sockaddr *pxDestinationAddress, socklen_t xDestinationAddressLength )\r
757 {\r
758 NetworkBufferDescriptor_t *pxNetworkBuffer;\r
759 IPStackEvent_t xStackTxEvent = { eStackTxEvent, NULL };\r
760 TimeOut_t xTimeOut;\r
761 TickType_t xTicksToWait;\r
762 int32_t lReturn = 0;\r
763 FreeRTOS_Socket_t *pxSocket;\r
764 \r
765         pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
766 \r
767         /* The function prototype is designed to maintain the expected Berkeley\r
768         sockets standard, but this implementation does not use all the\r
769         parameters. */\r
770         ( void ) xDestinationAddressLength;\r
771         configASSERT( pvBuffer );\r
772 \r
773         if( xTotalDataLength <= ( size_t ) ipMAX_UDP_PAYLOAD_LENGTH )\r
774         {\r
775                 /* If the socket is not already bound to an address, bind it now.\r
776                 Passing NULL as the address parameter tells FreeRTOS_bind() to select\r
777                 the address to bind to. */\r
778                 if( ( socketSOCKET_IS_BOUND( pxSocket ) != pdFALSE ) ||\r
779                         ( FreeRTOS_bind( xSocket, NULL, 0u ) == 0 ) )\r
780                 {\r
781                         xTicksToWait = pxSocket->xSendBlockTime;\r
782 \r
783                         #if( ipconfigUSE_CALLBACKS != 0 )\r
784                         {\r
785                                 if( xIsCallingFromIPTask() != pdFALSE )\r
786                                 {\r
787                                         /* If this send function is called from within a call-back\r
788                                         handler it may not block, otherwise chances would be big to\r
789                                         get a deadlock: the IP-task waiting for itself. */\r
790                                         xTicksToWait = ( TickType_t )0;\r
791                                 }\r
792                         }\r
793                         #endif /* ipconfigUSE_CALLBACKS */\r
794 \r
795                         if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )\r
796                         {\r
797                                 xTicksToWait = ( TickType_t ) 0;\r
798                         }\r
799 \r
800                         if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )\r
801                         {\r
802                                 /* Zero copy is not set, so obtain a network buffer into\r
803                                 which the payload will be copied. */\r
804                                 vTaskSetTimeOutState( &xTimeOut );\r
805 \r
806                                 /* Block until a buffer becomes available, or until a\r
807                                 timeout has been reached */\r
808                                 pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( xTotalDataLength + sizeof( UDPPacket_t ), xTicksToWait );\r
809 \r
810                                 if( pxNetworkBuffer != NULL )\r
811                                 {\r
812                                         memcpy( ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ), ( void * ) pvBuffer, xTotalDataLength );\r
813 \r
814                                         if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdTRUE )\r
815                                         {\r
816                                                 /* The entire block time has been used up. */\r
817                                                 xTicksToWait = ( TickType_t ) 0;\r
818                                         }\r
819                                 }\r
820                         }\r
821                         else\r
822                         {\r
823                                 /* When zero copy is used, pvBuffer is a pointer to the\r
824                                 payload of a buffer that has already been obtained from the\r
825                                 stack.  Obtain the network buffer pointer from the buffer. */\r
826                                 pxNetworkBuffer = pxUDPPayloadBuffer_to_NetworkBuffer( (void*)pvBuffer );\r
827                         }\r
828 \r
829                         if( pxNetworkBuffer != NULL )\r
830                         {\r
831                                 pxNetworkBuffer->xDataLength = xTotalDataLength;\r
832                                 pxNetworkBuffer->usPort = pxDestinationAddress->sin_port;\r
833                                 pxNetworkBuffer->usBoundPort = ( uint16_t ) socketGET_SOCKET_PORT( pxSocket );\r
834                                 pxNetworkBuffer->ulIPAddress = pxDestinationAddress->sin_addr;\r
835 \r
836                                 /* The socket options are passed to the IP layer in the\r
837                                 space that will eventually get used by the Ethernet header. */\r
838                                 pxNetworkBuffer->pucEthernetBuffer[ ipSOCKET_OPTIONS_OFFSET ] = pxSocket->ucSocketOptions;\r
839 \r
840                                 /* Tell the networking task that the packet needs sending. */\r
841                                 xStackTxEvent.pvData = pxNetworkBuffer;\r
842 \r
843                                 /* Ask the IP-task to send this packet */\r
844                                 if( xSendEventStructToIPTask( &xStackTxEvent, xTicksToWait ) == pdPASS )\r
845                                 {\r
846                                         /* The packet was successfully sent to the IP task. */\r
847                                         lReturn = ( int32_t ) xTotalDataLength;\r
848                                         #if( ipconfigUSE_CALLBACKS == 1 )\r
849                                         {\r
850                                                 if( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xUDP.pxHandleSent ) )\r
851                                                 {\r
852                                                         pxSocket->u.xUDP.pxHandleSent( (Socket_t *)pxSocket, xTotalDataLength );\r
853                                                 }\r
854                                         }\r
855                                         #endif /* ipconfigUSE_CALLBACKS */\r
856                                 }\r
857                                 else\r
858                                 {\r
859                                         /* If the buffer was allocated in this function, release\r
860                                         it. */\r
861                                         if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )\r
862                                         {\r
863                                                 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
864                                         }\r
865                                         iptraceSTACK_TX_EVENT_LOST( ipSTACK_TX_EVENT );\r
866                                 }\r
867                         }\r
868                         else\r
869                         {\r
870                                 /* If errno was available, errno would be set to\r
871                                 FREERTOS_ENOPKTS.  As it is, the function must return the\r
872                                 number of transmitted bytes, so the calling function knows\r
873                                 how     much data was actually sent. */\r
874                                 iptraceNO_BUFFER_FOR_SENDTO();\r
875                         }\r
876                 }\r
877                 else\r
878                 {\r
879                         iptraceSENDTO_SOCKET_NOT_BOUND();\r
880                 }\r
881         }\r
882         else\r
883         {\r
884                 /* The data is longer than the available buffer space. */\r
885                 iptraceSENDTO_DATA_TOO_LONG();\r
886         }\r
887 \r
888         return lReturn;\r
889 } /* Tested */\r
890 /*-----------------------------------------------------------*/\r
891 \r
892 /*\r
893  * FreeRTOS_bind() : binds a sockt to a local port number.  If port 0 is\r
894  * provided, a system provided port number will be assigned.  This function can\r
895  * be used for both UDP and TCP sockets.  The actual binding will be performed\r
896  * by the IP-task to avoid mutual access to the bound-socket-lists\r
897  * (xBoundUDPSocketsList or xBoundTCPSocketsList).\r
898  */\r
899 BaseType_t FreeRTOS_bind( Socket_t xSocket, struct freertos_sockaddr * pxAddress, socklen_t xAddressLength )\r
900 {\r
901 IPStackEvent_t xBindEvent;\r
902 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
903 BaseType_t xReturn = 0;\r
904 \r
905         ( void ) xAddressLength;\r
906 \r
907         if( ( pxSocket == NULL ) || ( pxSocket == FREERTOS_INVALID_SOCKET ) )\r
908         {\r
909                 xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
910         }\r
911         /* Once a socket is bound to a port, it can not be bound to a different\r
912         port number */\r
913         else if( socketSOCKET_IS_BOUND( pxSocket) != pdFALSE )\r
914         {\r
915                 /* The socket is already bound. */\r
916                 FreeRTOS_debug_printf( ( "vSocketBind: Socket already bound to %d\n", pxSocket->usLocalPort ) );\r
917                 xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
918         }\r
919         else\r
920         {\r
921                 /* Prepare a messages to the IP-task in order to perform the binding.\r
922                 The desired port number will be passed in usLocalPort. */\r
923                 xBindEvent.eEventType = eSocketBindEvent;\r
924                 xBindEvent.pvData = ( void * ) xSocket;\r
925                 if( pxAddress != NULL )\r
926                 {\r
927                         pxSocket->usLocalPort = FreeRTOS_ntohs( pxAddress->sin_port );\r
928                 }\r
929                 else\r
930                 {\r
931                         /* Caller wants to bind to a random port number. */\r
932                         pxSocket->usLocalPort = 0u;\r
933                 }\r
934 \r
935                 /* portMAX_DELAY is used as a the time-out parameter, as binding *must*\r
936                 succeed before the socket can be used.  _RB_ The use of an infinite\r
937                 block time needs be changed as it could result in the task hanging. */\r
938                 if( xSendEventStructToIPTask( &xBindEvent, ( TickType_t ) portMAX_DELAY ) == pdFAIL )\r
939                 {\r
940                         /* Failed to wake-up the IP-task, no use to wait for it */\r
941                         FreeRTOS_debug_printf( ( "FreeRTOS_bind: send event failed\n" ) );\r
942                         xReturn = -pdFREERTOS_ERRNO_ECANCELED;\r
943                 }\r
944                 else\r
945                 {\r
946                         /* The IP-task will set the 'eSOCKET_BOUND' bit when it has done its\r
947                         job. */\r
948                         xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_BOUND, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, portMAX_DELAY );\r
949                         if( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE )\r
950                         {\r
951                                 xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
952                         }\r
953                 }\r
954         }\r
955 \r
956         return xReturn;\r
957 }\r
958 \r
959 /*\r
960  * vSocketBind(): internal version of bind() that should not be called directly.\r
961  * 'xInternal' is used for TCP sockets only: it allows to have several\r
962  * (connected) child sockets bound to the same server port.\r
963  */\r
964 BaseType_t vSocketBind( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr * pxAddress, size_t uxAddressLength, BaseType_t xInternal )\r
965 {\r
966 BaseType_t xReturn = 0; /* In Berkeley sockets, 0 means pass for bind(). */\r
967 List_t *pxSocketList;\r
968 #if( ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 )\r
969         struct freertos_sockaddr xAddress;\r
970 #endif /* ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND */\r
971 \r
972 #if( ipconfigUSE_TCP == 1 )\r
973         if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
974         {\r
975                 pxSocketList = &xBoundTCPSocketsList;\r
976         }\r
977         else\r
978 #endif  /* ipconfigUSE_TCP == 1 */\r
979         {\r
980                 pxSocketList = &xBoundUDPSocketsList;\r
981         }\r
982 \r
983         /* The function prototype is designed to maintain the expected Berkeley\r
984         sockets standard, but this implementation does not use all the parameters. */\r
985         ( void ) uxAddressLength;\r
986 \r
987         configASSERT( pxSocket );\r
988         configASSERT( pxSocket != FREERTOS_INVALID_SOCKET );\r
989 \r
990         #if( ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 )\r
991         {\r
992                 /* pxAddress will be NULL if sendto() was called on a socket without the\r
993                 socket being bound to an address. In this case, automatically allocate\r
994                 an address and port to the socket. */\r
995                 if( pxAddress == NULL )\r
996                 {\r
997                         pxAddress = &xAddress;\r
998                         /* Put the port to zero to be assigned later. */\r
999                         pxAddress->sin_port = 0u;\r
1000                 }\r
1001         }\r
1002         #endif /* ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 */\r
1003 \r
1004         /* Sockets must be bound before calling FreeRTOS_sendto() if\r
1005         ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is not set to 1. */\r
1006         configASSERT( pxAddress );\r
1007 \r
1008         if( pxAddress != NULL )\r
1009         {\r
1010                 if( pxAddress->sin_port == 0u )\r
1011                 {\r
1012                         pxAddress->sin_port = prvGetPrivatePortNumber( ( BaseType_t )pxSocket->ucProtocol );\r
1013                         if( 0 == pxAddress->sin_port )\r
1014                         {\r
1015                                 return -pdFREERTOS_ERRNO_EADDRNOTAVAIL;\r
1016                         }\r
1017                 }\r
1018 \r
1019                 /* If vSocketBind() is called from the API FreeRTOS_bind() it has been\r
1020                 confirmed that the socket was not yet bound to a port.  If it is called\r
1021                 from the IP-task, no such check is necessary. */\r
1022 \r
1023                 /* Check to ensure the port is not already in use.  If the bind is\r
1024                 called internally, a port MAY be used by more than one socket. */\r
1025                 if( ( ( xInternal == pdFALSE ) || ( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP ) ) &&\r
1026                         ( pxListFindListItemWithValue( pxSocketList, ( TickType_t ) pxAddress->sin_port ) != NULL ) )\r
1027                 {\r
1028                         FreeRTOS_debug_printf( ( "vSocketBind: %sP port %d in use\n",\r
1029                                 pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP ? "TC" : "UD",\r
1030                                 FreeRTOS_ntohs( pxAddress->sin_port ) ) );\r
1031                         xReturn = -pdFREERTOS_ERRNO_EADDRINUSE;\r
1032                 }\r
1033                 else\r
1034                 {\r
1035                         /* Allocate the port number to the socket.\r
1036                         This macro will set 'xBoundSocketListItem->xItemValue' */\r
1037                         socketSET_SOCKET_PORT( pxSocket, pxAddress->sin_port );\r
1038 \r
1039                         /* And also store it in a socket field 'usLocalPort' in host-byte-order,\r
1040                         mostly used for logging and debugging purposes */\r
1041                         pxSocket->usLocalPort = FreeRTOS_ntohs( pxAddress->sin_port );\r
1042 \r
1043                         /* Add the socket to the list of bound ports. */\r
1044                         {\r
1045                                 /* If the network driver can iterate through 'xBoundUDPSocketsList',\r
1046                                 by calling xPortHasUDPSocket() then the IP-task must temporarily\r
1047                                 suspend the scheduler to keep the list in a consistent state. */\r
1048                                 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )\r
1049                                 {\r
1050                                         vTaskSuspendAll();\r
1051                                 }\r
1052                                 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */\r
1053 \r
1054                                 /* Add the socket to 'xBoundUDPSocketsList' or 'xBoundTCPSocketsList' */\r
1055                                 vListInsertEnd( pxSocketList, &( pxSocket->xBoundSocketListItem ) );\r
1056 \r
1057                                 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )\r
1058                                 {\r
1059                                         xTaskResumeAll();\r
1060                                 }\r
1061                                 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */\r
1062                         }\r
1063                 }\r
1064         }\r
1065         else\r
1066         {\r
1067                 xReturn = -pdFREERTOS_ERRNO_EADDRNOTAVAIL;\r
1068                 FreeRTOS_debug_printf( ( "vSocketBind: Socket no addr\n" ) );\r
1069         }\r
1070 \r
1071         if( xReturn != 0 )\r
1072         {\r
1073                 iptraceBIND_FAILED( xSocket, ( FreeRTOS_ntohs( pxAddress->sin_port ) ) );\r
1074         }\r
1075 \r
1076         return xReturn;\r
1077 } /* Tested */\r
1078 /*-----------------------------------------------------------*/\r
1079 \r
1080 /*\r
1081  * Close a socket and free the allocated space\r
1082  * In case of a TCP socket: the connection will not be closed automatically\r
1083  * Subsequent messages for the closed socket will be responded to with a RST\r
1084  * The IP-task will actually close the socket, after receiving a 'eSocketCloseEvent' message\r
1085  */\r
1086 BaseType_t FreeRTOS_closesocket( Socket_t xSocket )\r
1087 {\r
1088 BaseType_t xResult;\r
1089 #if( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 )\r
1090         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * )xSocket;\r
1091 #endif\r
1092 IPStackEvent_t xCloseEvent;\r
1093 xCloseEvent.eEventType = eSocketCloseEvent;\r
1094 xCloseEvent.pvData = ( void * ) xSocket;\r
1095 \r
1096         if( ( xSocket == NULL ) || ( xSocket == FREERTOS_INVALID_SOCKET ) )\r
1097         {\r
1098                 xResult = 0;\r
1099         }\r
1100         else\r
1101         {\r
1102                 #if( ( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 ) )\r
1103                 {\r
1104                         if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
1105                         {\r
1106                                 /* Make sure that IP-task won't call the user callback's anymore */\r
1107                                 pxSocket->u.xTCP.pxHandleConnected = NULL;\r
1108                                 pxSocket->u.xTCP.pxHandleReceive = NULL;\r
1109                                 pxSocket->u.xTCP.pxHandleSent = NULL;\r
1110                         }\r
1111                 }\r
1112                 #endif  /* ( ( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 ) ) */\r
1113 \r
1114                 /* Let the IP task close the socket to keep it synchronised     with the\r
1115                 packet handling. */\r
1116 \r
1117                 /* Note when changing the time-out value below, it must be checked who is calling\r
1118                 this function. If it is called by the IP-task, a deadlock could occur.\r
1119                 The IP-task would only call it in case of a user call-back */\r
1120                 if( xSendEventStructToIPTask( &xCloseEvent, ( TickType_t ) 0 ) == pdFAIL )\r
1121                 {\r
1122                         FreeRTOS_debug_printf( ( "FreeRTOS_closesocket: failed\n" ) );\r
1123                         xResult = -1;\r
1124                 }\r
1125                 else\r
1126                 {\r
1127                         xResult = 1;\r
1128                 }\r
1129         }\r
1130 \r
1131         return xResult;\r
1132 }\r
1133 \r
1134 /* This is the internal version of FreeRTOS_closesocket()\r
1135  * It will be called by the IPtask only to avoid problems with synchronicity\r
1136  */\r
1137 void *vSocketClose( FreeRTOS_Socket_t *pxSocket )\r
1138 {\r
1139 NetworkBufferDescriptor_t *pxNetworkBuffer;\r
1140 \r
1141         #if( ipconfigUSE_TCP == 1 )\r
1142         {\r
1143                 /* For TCP: clean up a little more. */\r
1144                 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
1145                 {\r
1146                         #if( ipconfigUSE_TCP_WIN == 1 )\r
1147                         {\r
1148                                 if( pxSocket->u.xTCP.pxAckMessage != NULL )\r
1149                                 {\r
1150                                         vReleaseNetworkBufferAndDescriptor( pxSocket->u.xTCP.pxAckMessage );\r
1151                                 }\r
1152                                 /* Free the resources which were claimed by the tcpWin member */\r
1153                                 vTCPWindowDestroy( &pxSocket->u.xTCP.xTCPWindow );\r
1154                         }\r
1155                         #endif /* ipconfigUSE_TCP_WIN */\r
1156 \r
1157                         /* Free the input and output streams */\r
1158                         if( pxSocket->u.xTCP.rxStream != NULL )\r
1159                         {\r
1160                                 vPortFreeLarge( pxSocket->u.xTCP.rxStream );\r
1161                         }\r
1162 \r
1163                         if( pxSocket->u.xTCP.txStream != NULL )\r
1164                         {\r
1165                                 vPortFreeLarge( pxSocket->u.xTCP.txStream );\r
1166                         }\r
1167 \r
1168                         /* In case this is a child socket, make sure the child-count of the\r
1169                         parent socket is decreased. */\r
1170                         prvTCPSetSocketCount( pxSocket );\r
1171                 }\r
1172         }\r
1173         #endif  /* ipconfigUSE_TCP == 1 */\r
1174 \r
1175         /* Socket must be unbound first, to ensure no more packets are queued on\r
1176         it. */\r
1177         if( socketSOCKET_IS_BOUND( pxSocket ) != pdFALSE )\r
1178         {\r
1179                 /* If the network driver can iterate through 'xBoundUDPSocketsList',\r
1180                 by calling xPortHasUDPSocket(), then the IP-task must temporarily\r
1181                 suspend the scheduler to keep the list in a consistent state. */\r
1182                 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )\r
1183                 {\r
1184                         vTaskSuspendAll();\r
1185                 }\r
1186                 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */\r
1187 \r
1188                 uxListRemove( &( pxSocket->xBoundSocketListItem ) );\r
1189 \r
1190                 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )\r
1191                 {\r
1192                         xTaskResumeAll();\r
1193                 }\r
1194                 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */\r
1195         }\r
1196 \r
1197         /* Now the socket is not bound the list of waiting packets can be\r
1198         drained. */\r
1199         if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_UDP )\r
1200         {\r
1201                 while( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) > 0U )\r
1202                 {\r
1203                         pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &( pxSocket->u.xUDP.xWaitingPacketsList ) );\r
1204                         uxListRemove( &( pxNetworkBuffer->xBufferListItem ) );\r
1205                         vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
1206                 }\r
1207         }\r
1208 \r
1209         if( pxSocket->xEventGroup )\r
1210         {\r
1211                 vEventGroupDelete( pxSocket->xEventGroup );\r
1212         }\r
1213 \r
1214         #if( ipconfigUSE_TCP == 1 ) && ( ipconfigHAS_DEBUG_PRINTF != 0 )\r
1215         {\r
1216                 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
1217                 {\r
1218                         FreeRTOS_debug_printf( ( "FreeRTOS_closesocket[%u to %lxip:%u]: buffers %lu socks %lu\n",\r
1219                                 pxSocket->usLocalPort,\r
1220                                 pxSocket->u.xTCP.ulRemoteIP,\r
1221                                 pxSocket->u.xTCP.usRemotePort,\r
1222                                 uxGetNumberOfFreeNetworkBuffers(),\r
1223                                 listCURRENT_LIST_LENGTH( &xBoundTCPSocketsList ) ) );\r
1224                 }\r
1225         }\r
1226         #endif /* ( ipconfigUSE_TCP == 1 ) && ( ipconfigHAS_DEBUG_PRINTF != 0 ) */\r
1227 \r
1228         /* Anf finally, after all resources have been freed, free the socket space */\r
1229         vPortFreeSocket( pxSocket );\r
1230 \r
1231         return 0;\r
1232 } /* Tested */\r
1233 \r
1234 /*-----------------------------------------------------------*/\r
1235 \r
1236 #if ipconfigUSE_TCP == 1\r
1237 \r
1238         /*\r
1239          * When a child socket gets closed, make sure to update the child-count of the\r
1240          * parent.  When a listening parent socket is closed, make sure no child-sockets\r
1241          * keep a pointer to it.\r
1242          */\r
1243         static void prvTCPSetSocketCount( FreeRTOS_Socket_t *pxSocketToDelete )\r
1244         {\r
1245         const ListItem_t *pxIterator;\r
1246         const MiniListItem_t *pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );\r
1247         FreeRTOS_Socket_t *pxOtherSocket;\r
1248         uint16_t usLocalPort = pxSocketToDelete->usLocalPort;\r
1249 \r
1250                 for( pxIterator  = ( const ListItem_t * ) listGET_NEXT( pxEnd );\r
1251                          pxIterator != ( const ListItem_t * ) pxEnd;\r
1252                          pxIterator  = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )\r
1253                 {\r
1254                         pxOtherSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );\r
1255                         if( ( pxOtherSocket->u.xTCP.ucTCPState == eTCP_LISTEN ) &&\r
1256                                 ( pxOtherSocket->usLocalPort == usLocalPort ) &&\r
1257                                 ( pxOtherSocket->u.xTCP.usChildCount ) )\r
1258                         {\r
1259                                 pxOtherSocket->u.xTCP.usChildCount--;\r
1260                                 FreeRTOS_debug_printf( ( "Lost: Socket %u now has %u / %u child%s\n",\r
1261                                         pxOtherSocket->usLocalPort,\r
1262                                         pxOtherSocket->u.xTCP.usChildCount,\r
1263                                         pxOtherSocket->u.xTCP.usBacklog,\r
1264                                         pxOtherSocket->u.xTCP.usChildCount == 1u ? "" : "ren" ) );\r
1265                                 break;\r
1266                         }\r
1267                 }\r
1268         }\r
1269 \r
1270 #endif /* ipconfigUSE_TCP == 1 */\r
1271 \r
1272 /*-----------------------------------------------------------*/\r
1273 \r
1274 BaseType_t FreeRTOS_setsockopt( Socket_t xSocket, int32_t lLevel, int32_t lOptionName, const void *pvOptionValue, size_t xOptionLength )\r
1275 {\r
1276 /* The standard Berkeley function returns 0 for success. */\r
1277 BaseType_t xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
1278 BaseType_t lOptionValue;\r
1279 FreeRTOS_Socket_t *pxSocket;\r
1280 \r
1281         pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
1282 \r
1283         /* The function prototype is designed to maintain the expected Berkeley\r
1284         sockets standard, but this implementation does not use all the parameters. */\r
1285         ( void ) lLevel;\r
1286         ( void ) xOptionLength;\r
1287 \r
1288         configASSERT( xSocket );\r
1289 \r
1290         switch( lOptionName )\r
1291         {\r
1292                 case FREERTOS_SO_RCVTIMEO       :\r
1293                         /* Receive time out. */\r
1294                         pxSocket->xReceiveBlockTime = *( ( TickType_t * ) pvOptionValue );\r
1295                         xReturn = 0;\r
1296                         break;\r
1297 \r
1298                 case FREERTOS_SO_SNDTIMEO       :\r
1299                         pxSocket->xSendBlockTime = *( ( TickType_t * ) pvOptionValue );\r
1300                         if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_UDP )\r
1301                         {\r
1302                                 /* The send time out is capped for the reason stated in the\r
1303                                 comments where ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS is defined\r
1304                                 in FreeRTOSIPConfig.h (assuming an official configuration file\r
1305                                 is being used. */\r
1306                                 if( pxSocket->xSendBlockTime > ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS )\r
1307                                 {\r
1308                                         pxSocket->xSendBlockTime = ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS;\r
1309                                 }\r
1310                         }\r
1311                         else\r
1312                         {\r
1313                                 /* For TCP socket, it isn't necessary to limit the blocking time\r
1314                                 because the FreeRTOS_send() function does not wait for a network\r
1315                                 buffer to become available. */\r
1316                         }\r
1317                         xReturn = 0;\r
1318                         break;\r
1319                 #if( ipconfigUDP_MAX_RX_PACKETS > 0 )\r
1320                         case FREERTOS_SO_UDP_MAX_RX_PACKETS:\r
1321                                 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_UDP )\r
1322                                 {\r
1323                                         break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
1324                                 }\r
1325                                 pxSocket->u.xUDP.uxMaxPackets = *( ( UBaseType_t * ) pvOptionValue );\r
1326                                 xReturn = 0;\r
1327                                 break;\r
1328                 #endif /* ipconfigUDP_MAX_RX_PACKETS */\r
1329 \r
1330                 case FREERTOS_SO_UDPCKSUM_OUT :\r
1331                         /* Turn calculating of the UDP checksum on/off for this socket. */\r
1332                         lOptionValue = ( BaseType_t ) pvOptionValue;\r
1333 \r
1334                         if( lOptionValue == 0 )\r
1335                         {\r
1336                                 pxSocket->ucSocketOptions &= ( uint8_t ) ~FREERTOS_SO_UDPCKSUM_OUT;\r
1337                         }\r
1338                         else\r
1339                         {\r
1340                                 pxSocket->ucSocketOptions |= ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT;\r
1341                         }\r
1342                         xReturn = 0;\r
1343                         break;\r
1344 \r
1345                 #if( ipconfigUSE_CALLBACKS == 1 )\r
1346                         #if( ipconfigUSE_TCP == 1 )\r
1347                                 case FREERTOS_SO_TCP_CONN_HANDLER:      /* Set a callback for (dis)connection events */\r
1348                                 case FREERTOS_SO_TCP_RECV_HANDLER:      /* Install a callback for receiving TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */\r
1349                                 case FREERTOS_SO_TCP_SENT_HANDLER:      /* Install a callback for sending TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */\r
1350                         #endif /* ipconfigUSE_TCP */\r
1351                                 case FREERTOS_SO_UDP_RECV_HANDLER:      /* Install a callback for receiving UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */\r
1352                                 case FREERTOS_SO_UDP_SENT_HANDLER:      /* Install a callback for sending UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */\r
1353                                         {\r
1354                                                 #if( ipconfigUSE_TCP == 1 )\r
1355                                                 {\r
1356                                                         UBaseType_t uxProtocol;\r
1357                                                         if( ( lOptionName == FREERTOS_SO_UDP_RECV_HANDLER ) ||\r
1358                                                                 ( lOptionName == FREERTOS_SO_UDP_SENT_HANDLER ) )\r
1359                                                         {\r
1360                                                                 uxProtocol = ( UBaseType_t ) FREERTOS_IPPROTO_UDP;\r
1361                                                         }\r
1362                                                         else\r
1363                                                         {\r
1364                                                                 uxProtocol = ( UBaseType_t ) FREERTOS_IPPROTO_TCP;\r
1365                                                         }\r
1366 \r
1367                                                         if( pxSocket->ucProtocol != ( uint8_t ) uxProtocol )\r
1368                                                         {\r
1369                                                                 break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
1370                                                         }\r
1371                                                 }\r
1372                                                 #else\r
1373                                                 {\r
1374                                                         /* No need to check if the socket has the right\r
1375                                                         protocol, because only UDP socket can be created. */\r
1376                                                 }\r
1377                                                 #endif /* ipconfigUSE_TCP */\r
1378 \r
1379                                                 switch( lOptionName )\r
1380                                                 {\r
1381                                                 #if ipconfigUSE_TCP == 1\r
1382                                                         case FREERTOS_SO_TCP_CONN_HANDLER:\r
1383                                                                 pxSocket->u.xTCP.pxHandleConnected = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPConnected;\r
1384                                                                 break;\r
1385                                                         case FREERTOS_SO_TCP_RECV_HANDLER:\r
1386                                                                 pxSocket->u.xTCP.pxHandleReceive = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPReceive;\r
1387                                                                 break;\r
1388                                                         case FREERTOS_SO_TCP_SENT_HANDLER:\r
1389                                                                 pxSocket->u.xTCP.pxHandleSent = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPSent;\r
1390                                                                 break;\r
1391                                                 #endif /* ipconfigUSE_TCP */\r
1392                                                 case FREERTOS_SO_UDP_RECV_HANDLER:\r
1393                                                         pxSocket->u.xUDP.pxHandleReceive = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnUDPReceive;\r
1394                                                         break;\r
1395                                                 case FREERTOS_SO_UDP_SENT_HANDLER:\r
1396                                                         pxSocket->u.xUDP.pxHandleSent = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnUDPSent;\r
1397                                                         break;\r
1398                                                 default:\r
1399                                                         break;\r
1400                                                 }\r
1401                                         }\r
1402 \r
1403                                         xReturn = 0;\r
1404                                         break;\r
1405                 #endif /* ipconfigUSE_CALLBACKS */\r
1406 \r
1407                 #if( ipconfigUSE_TCP != 0 )\r
1408                         #if( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 )\r
1409                                 /* Each socket has a semaphore on which the using task normally\r
1410                                 sleeps. */\r
1411                                 case FREERTOS_SO_SET_SEMAPHORE:\r
1412                                         {\r
1413                                                 pxSocket->pxUserSemaphore = *( ( SemaphoreHandle_t * ) pvOptionValue );\r
1414                                                 xReturn = 0;\r
1415                                         }\r
1416                                         break;\r
1417                         #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */\r
1418 \r
1419                         #if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK != 0 )\r
1420                                 case FREERTOS_SO_WAKEUP_CALLBACK:\r
1421                                 {\r
1422                                         /* Each socket can have a callback function that is executed\r
1423                                         when there is an event the socket's owner might want to\r
1424                                         process. */\r
1425                                         pxSocket->pxUserWakeCallback = ( SocketWakeupCallback_t ) pvOptionValue;\r
1426                                         xReturn = 0;\r
1427                                 }\r
1428                                 break;\r
1429                         #endif /* ipconfigSOCKET_HAS_USER_WAKE_CALLBACK */\r
1430 \r
1431                         case FREERTOS_SO_SNDBUF:        /* Set the size of the send buffer, in units of MSS (TCP only) */\r
1432                         case FREERTOS_SO_RCVBUF:        /* Set the size of the receive buffer, in units of MSS (TCP only) */\r
1433                                 {\r
1434                                         uint32_t ulNewValue;\r
1435 \r
1436                                         if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
1437                                         {\r
1438                                                 FreeRTOS_debug_printf( ( "Set SO_%sBUF: wrong socket type\n",\r
1439                                                         ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );\r
1440                                                 break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
1441                                         }\r
1442 \r
1443                                         if( ( ( lOptionName == FREERTOS_SO_SNDBUF ) && ( pxSocket->u.xTCP.txStream != NULL ) ) ||\r
1444                                                 ( ( lOptionName == FREERTOS_SO_RCVBUF ) && ( pxSocket->u.xTCP.rxStream != NULL ) ) )\r
1445                                         {\r
1446                                                 FreeRTOS_debug_printf( ( "Set SO_%sBUF: buffer already created\n",\r
1447                                                         ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );\r
1448                                                 break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
1449                                         }\r
1450 \r
1451                                         ulNewValue = *( ( uint32_t * ) pvOptionValue );\r
1452 \r
1453                                         if( lOptionName == FREERTOS_SO_SNDBUF )\r
1454                                         {\r
1455                                                 /* Round up to nearest MSS size */\r
1456                                                 ulNewValue = FreeRTOS_round_up( ulNewValue, ( uint32_t ) pxSocket->u.xTCP.usInitMSS );\r
1457                                                 pxSocket->u.xTCP.uxTxStreamSize = ulNewValue;\r
1458                                         }\r
1459                                         else\r
1460                                         {\r
1461                                                 pxSocket->u.xTCP.uxRxStreamSize = ulNewValue;\r
1462                                         }\r
1463                                 }\r
1464                                 xReturn = 0;\r
1465                                 break;\r
1466 \r
1467                         case FREERTOS_SO_WIN_PROPERTIES:        /* Set all buffer and window properties in one call, parameter is pointer to WinProperties_t */\r
1468                                 {\r
1469                                         WinProperties_t* pxProps;\r
1470 \r
1471                                         if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
1472                                         {\r
1473                                                 FreeRTOS_debug_printf( ( "Set SO_WIN_PROP: wrong socket type\n" ) );\r
1474                                                 break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
1475                                         }\r
1476 \r
1477                                         if( ( pxSocket->u.xTCP.txStream != NULL ) || ( pxSocket->u.xTCP.rxStream != NULL ) )\r
1478                                         {\r
1479                                                 FreeRTOS_debug_printf( ( "Set SO_WIN_PROP: buffer already created\n" ) );\r
1480                                                 break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
1481                                         }\r
1482 \r
1483                                         pxProps = ( ( WinProperties_t * ) pvOptionValue );\r
1484                                         FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDBUF, &( pxProps->lTxBufSize ), sizeof( pxProps->lTxBufSize ) );\r
1485                                         FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVBUF, &( pxProps->lRxBufSize ), sizeof( pxProps->lRxBufSize ) );\r
1486                                         #if( ipconfigUSE_TCP_WIN == 1 )\r
1487                                         {\r
1488                                                 pxSocket->u.xTCP.uxRxWinSize = ( uint32_t )pxProps->lRxWinSize; /* Fixed value: size of the TCP reception window */\r
1489                                                 pxSocket->u.xTCP.uxTxWinSize = ( uint32_t )pxProps->lTxWinSize; /* Fixed value: size of the TCP transmit window */\r
1490                                         }\r
1491                                         #else\r
1492                                         {\r
1493                                                 pxSocket->u.xTCP.uxRxWinSize = 1u;\r
1494                                                 pxSocket->u.xTCP.uxTxWinSize = 1u;\r
1495                                         }\r
1496                                         #endif\r
1497 \r
1498                                         /* In case the socket has already initialised its tcpWin,\r
1499                                         adapt the window size parameters */\r
1500                                         if( pxSocket->u.xTCP.xTCPWindow.u.bits.bHasInit != pdFALSE_UNSIGNED )\r
1501                                         {\r
1502                                                 pxSocket->u.xTCP.xTCPWindow.xSize.ulRxWindowLength = pxSocket->u.xTCP.uxRxWinSize * pxSocket->u.xTCP.usInitMSS;\r
1503                                                 pxSocket->u.xTCP.xTCPWindow.xSize.ulTxWindowLength = pxSocket->u.xTCP.uxTxWinSize * pxSocket->u.xTCP.usInitMSS;\r
1504                                         }\r
1505                                 }\r
1506 \r
1507                                 xReturn = 0;\r
1508                                 break;\r
1509 \r
1510                         case FREERTOS_SO_REUSE_LISTEN_SOCKET:   /* If true, the server-socket will turn into a connected socket */\r
1511                                 {\r
1512                                         if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
1513                                         {\r
1514                                                 break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
1515                                         }\r
1516                                         if( *( ( BaseType_t * ) pvOptionValue ) != 0 )\r
1517                                         {\r
1518                                                 pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE_UNSIGNED;\r
1519                                         }\r
1520                                         else\r
1521                                         {\r
1522                                                 pxSocket->u.xTCP.bits.bReuseSocket = pdFALSE_UNSIGNED;\r
1523                                         }\r
1524                                 }\r
1525                                 xReturn = 0;\r
1526                                 break;\r
1527 \r
1528                         case FREERTOS_SO_CLOSE_AFTER_SEND:              /* As soon as the last byte has been transmitted, finalise the connection */\r
1529                                 {\r
1530                                         if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
1531                                         {\r
1532                                                 break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
1533                                         }\r
1534 \r
1535                                         if( *( ( BaseType_t * ) pvOptionValue ) != 0 )\r
1536                                         {\r
1537                                                 pxSocket->u.xTCP.bits.bCloseAfterSend = pdTRUE_UNSIGNED;\r
1538                                         }\r
1539                                         else\r
1540                                         {\r
1541                                                 pxSocket->u.xTCP.bits.bCloseAfterSend = pdFALSE_UNSIGNED;\r
1542                                         }\r
1543                                 }\r
1544                                 xReturn = 0;\r
1545                                 break;\r
1546 \r
1547                         case FREERTOS_SO_SET_FULL_SIZE:         /* Refuse to send packets smaller than MSS  */\r
1548                                 {\r
1549                                         if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
1550                                         {\r
1551                                                 break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
1552                                         }\r
1553 \r
1554                                         if( *( ( BaseType_t * ) pvOptionValue ) != 0 )\r
1555                                         {\r
1556                                                 pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdTRUE_UNSIGNED;\r
1557                                         }\r
1558                                         else\r
1559                                         {\r
1560                                                 pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdFALSE_UNSIGNED;\r
1561                                         }\r
1562 \r
1563                                         if( ( pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize == pdFALSE_UNSIGNED ) &&\r
1564                                                 ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) &&\r
1565                                                 ( FreeRTOS_outstanding( pxSocket ) != 0 ) )\r
1566                                         {\r
1567                                                 pxSocket->u.xTCP.usTimeout = 1u; /* to set/clear bSendFullSize */\r
1568                                                 xSendEventToIPTask( eTCPTimerEvent );\r
1569                                         }\r
1570                                 }\r
1571                                 xReturn = 0;\r
1572                                 break;\r
1573 \r
1574                         case FREERTOS_SO_STOP_RX:               /* Refuse to receive more packts */\r
1575                                 {\r
1576                                         if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
1577                                         {\r
1578                                                 break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
1579                                         }\r
1580 \r
1581                                         if( *( ( BaseType_t * ) pvOptionValue ) != 0 )\r
1582                                         {\r
1583                                                 pxSocket->u.xTCP.bits.bRxStopped = pdTRUE_UNSIGNED;\r
1584                                         }\r
1585                                         else\r
1586                                         {\r
1587                                                 pxSocket->u.xTCP.bits.bRxStopped = pdFALSE_UNSIGNED;\r
1588                                         }\r
1589 \r
1590                                         pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;\r
1591                                         pxSocket->u.xTCP.usTimeout = 1u; /* to set/clear bRxStopped */\r
1592                                         xSendEventToIPTask( eTCPTimerEvent );\r
1593                                 }\r
1594                                 xReturn = 0;\r
1595                                 break;\r
1596 \r
1597                 #endif  /* ipconfigUSE_TCP == 1 */\r
1598 \r
1599                 default :\r
1600                         /* No other options are handled. */\r
1601                         xReturn = -pdFREERTOS_ERRNO_ENOPROTOOPT;\r
1602                         break;\r
1603         }\r
1604 \r
1605         return xReturn;\r
1606 } /* Tested */\r
1607 \r
1608 /*-----------------------------------------------------------*/\r
1609 \r
1610 /* Find an available port number per https://tools.ietf.org/html/rfc6056. */\r
1611 static uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol )\r
1612 {\r
1613 const uint16_t usEphemeralPortCount =\r
1614         socketAUTO_PORT_ALLOCATION_MAX_NUMBER - socketAUTO_PORT_ALLOCATION_START_NUMBER + 1;\r
1615 uint16_t usIterations = usEphemeralPortCount;\r
1616 uint32_t ulRandomSeed = 0;\r
1617 uint16_t usResult = 0;\r
1618 BaseType_t xGotZeroOnce = pdFALSE;\r
1619 const List_t *pxList;\r
1620 \r
1621 #if ipconfigUSE_TCP == 1\r
1622         if( xProtocol == ( BaseType_t ) FREERTOS_IPPROTO_TCP )\r
1623         {\r
1624                 pxList = &xBoundTCPSocketsList;\r
1625         }\r
1626         else\r
1627 #endif\r
1628         {\r
1629                 pxList = &xBoundUDPSocketsList;\r
1630         }\r
1631 \r
1632         /* Avoid compiler warnings if ipconfigUSE_TCP is not defined. */\r
1633         ( void ) xProtocol;\r
1634 \r
1635         /* Find the next available port using the random seed as a starting\r
1636         point. */\r
1637         do\r
1638         {\r
1639                 /* Generate a random seed. */\r
1640                 ulRandomSeed = ipconfigRAND32( );\r
1641 \r
1642                 /* Only proceed if the random number generator succeeded. */\r
1643                 if( 0 == ulRandomSeed )\r
1644                 {\r
1645                         if( pdFALSE == xGotZeroOnce )\r
1646                         {\r
1647                                 xGotZeroOnce = pdTRUE;\r
1648                                 continue;\r
1649                         }\r
1650                         else\r
1651                         {\r
1652                                 break;\r
1653                         }\r
1654                 }\r
1655 \r
1656                 /* Map the random to a candidate port. */\r
1657                 usResult =\r
1658                         socketAUTO_PORT_ALLOCATION_START_NUMBER +\r
1659                         ( ( ( uint16_t )ulRandomSeed ) % usEphemeralPortCount );\r
1660 \r
1661                 /* Check if there's already an open socket with the same protocol\r
1662                 and port. */\r
1663                 if( NULL == pxListFindListItemWithValue(\r
1664                         pxList,\r
1665                         ( TickType_t )FreeRTOS_htons( usResult ) ) )\r
1666                 {\r
1667                         usResult = FreeRTOS_htons( usResult );\r
1668                         break;\r
1669                 }\r
1670                 else\r
1671                 {\r
1672                         usResult = 0;\r
1673                 }\r
1674 \r
1675                 usIterations--;\r
1676         }\r
1677         while( usIterations > 0 );\r
1678 \r
1679         return usResult;\r
1680 }\r
1681 /*-----------------------------------------------------------*/\r
1682 \r
1683 /* pxListFindListItemWithValue: find a list item in a bound socket list\r
1684 'xWantedItemValue' refers to a port number */\r
1685 static const ListItem_t * pxListFindListItemWithValue( const List_t *pxList, TickType_t xWantedItemValue )\r
1686 {\r
1687 const ListItem_t * pxResult = NULL;\r
1688 \r
1689         if( ( xIPIsNetworkTaskReady() != pdFALSE ) && ( pxList != NULL ) )\r
1690         {\r
1691                 const ListItem_t *pxIterator;\r
1692                 const MiniListItem_t *pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( pxList );\r
1693                 for( pxIterator  = ( const ListItem_t * ) listGET_NEXT( pxEnd );\r
1694                          pxIterator != ( const ListItem_t * ) pxEnd;\r
1695                          pxIterator  = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )\r
1696                 {\r
1697                         if( listGET_LIST_ITEM_VALUE( pxIterator ) == xWantedItemValue )\r
1698                         {\r
1699                                 pxResult = pxIterator;\r
1700                                 break;\r
1701                         }\r
1702                 }\r
1703         }\r
1704 \r
1705         return pxResult;\r
1706 } /* Tested */\r
1707 \r
1708 /*-----------------------------------------------------------*/\r
1709 \r
1710 FreeRTOS_Socket_t *pxUDPSocketLookup( UBaseType_t uxLocalPort )\r
1711 {\r
1712 const ListItem_t *pxListItem;\r
1713 FreeRTOS_Socket_t *pxSocket = NULL;\r
1714 \r
1715         /* Looking up a socket is quite simple, find a match with the local port.\r
1716 \r
1717         See if there is a list item associated with the port number on the\r
1718         list of bound sockets. */\r
1719         pxListItem = pxListFindListItemWithValue( &xBoundUDPSocketsList, ( TickType_t ) uxLocalPort );\r
1720 \r
1721         if( pxListItem != NULL )\r
1722         {\r
1723                 /* The owner of the list item is the socket itself. */\r
1724                 pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxListItem );\r
1725                 configASSERT( pxSocket != NULL );\r
1726         }\r
1727         return pxSocket;\r
1728 }\r
1729 \r
1730 /*-----------------------------------------------------------*/\r
1731 \r
1732 #if ipconfigINCLUDE_FULL_INET_ADDR == 1\r
1733 \r
1734         uint32_t FreeRTOS_inet_addr( const char * pcIPAddress )\r
1735         {\r
1736         const uint32_t ulDecimalBase = 10u;\r
1737         uint8_t ucOctet[ socketMAX_IP_ADDRESS_OCTETS ];\r
1738         const char *pcPointerOnEntering;\r
1739         uint32_t ulReturn = 0UL, ulValue;\r
1740         UBaseType_t uxOctetNumber;\r
1741         BaseType_t xResult = pdPASS;\r
1742 \r
1743                 for( uxOctetNumber = 0u; uxOctetNumber < socketMAX_IP_ADDRESS_OCTETS; uxOctetNumber++ )\r
1744                 {\r
1745                         ulValue = 0ul;\r
1746                         pcPointerOnEntering = pcIPAddress;\r
1747 \r
1748                         while( ( *pcIPAddress >= '0' ) && ( *pcIPAddress <= '9' ) )\r
1749                         {\r
1750                                 /* Move previous read characters into the next decimal\r
1751                                 position. */\r
1752                                 ulValue *= ulDecimalBase;\r
1753 \r
1754                                 /* Add the binary value of the ascii character. */\r
1755                                 ulValue += ( ( uint32_t ) ( *pcIPAddress ) - ( uint32_t ) '0' );\r
1756 \r
1757                                 /* Move to next character in the string. */\r
1758                                 pcIPAddress++;\r
1759                         }\r
1760 \r
1761                         /* Check characters were read. */\r
1762                         if( pcIPAddress == pcPointerOnEntering )\r
1763                         {\r
1764                                 xResult = pdFAIL;\r
1765                         }\r
1766 \r
1767                         /* Check the value fits in an 8-bit number. */\r
1768                         if( ulValue > 0xffUL )\r
1769                         {\r
1770                                 xResult = pdFAIL;\r
1771                         }\r
1772                         else\r
1773                         {\r
1774                                 ucOctet[ uxOctetNumber ] = ( uint8_t ) ulValue;\r
1775 \r
1776                                 /* Check the next character is as expected. */\r
1777                                 if( uxOctetNumber < ( socketMAX_IP_ADDRESS_OCTETS - 1u ) )\r
1778                                 {\r
1779                                         if( *pcIPAddress != '.' )\r
1780                                         {\r
1781                                                 xResult = pdFAIL;\r
1782                                         }\r
1783                                         else\r
1784                                         {\r
1785                                                 /* Move past the dot. */\r
1786                                                 pcIPAddress++;\r
1787                                         }\r
1788                                 }\r
1789                         }\r
1790 \r
1791                         if( xResult == pdFAIL )\r
1792                         {\r
1793                                 /* No point going on. */\r
1794                                 break;\r
1795                         }\r
1796                 }\r
1797 \r
1798                 if( *pcIPAddress != ( char ) 0 )\r
1799                 {\r
1800                         /* Expected the end of the string. */\r
1801                         xResult = pdFAIL;\r
1802                 }\r
1803 \r
1804                 if( uxOctetNumber != socketMAX_IP_ADDRESS_OCTETS )\r
1805                 {\r
1806                         /* Didn't read enough octets. */\r
1807                         xResult = pdFAIL;\r
1808                 }\r
1809 \r
1810                 if( xResult == pdPASS )\r
1811                 {\r
1812                         ulReturn = FreeRTOS_inet_addr_quick( ucOctet[ 0 ], ucOctet[ 1 ], ucOctet[ 2 ], ucOctet[ 3 ] );\r
1813                 }\r
1814 \r
1815                 return ulReturn;\r
1816         }\r
1817 \r
1818 #endif /* ipconfigINCLUDE_FULL_INET_ADDR */\r
1819 \r
1820 /*-----------------------------------------------------------*/\r
1821 \r
1822 /* Function to get the local address and IP port */\r
1823 size_t FreeRTOS_GetLocalAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress )\r
1824 {\r
1825 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
1826 \r
1827         /* IP address of local machine. */\r
1828         pxAddress->sin_addr = *ipLOCAL_IP_ADDRESS_POINTER;\r
1829 \r
1830         /* Local port on this machine. */\r
1831         pxAddress->sin_port = FreeRTOS_htons( pxSocket->usLocalPort );\r
1832 \r
1833         return sizeof( *pxAddress );\r
1834 }\r
1835 \r
1836 /*-----------------------------------------------------------*/\r
1837 \r
1838 void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )\r
1839 {\r
1840 /* _HT_ must work this out, now vSocketWakeUpUser will be called for any important\r
1841  * event or transition */\r
1842         #if( ipconfigSOCKET_HAS_USER_SEMAPHORE == 1 )\r
1843         {\r
1844                 if( pxSocket->pxUserSemaphore != NULL )\r
1845                 {\r
1846                         xSemaphoreGive( pxSocket->pxUserSemaphore );\r
1847                 }\r
1848         }\r
1849         #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */\r
1850 \r
1851         #if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK == 1 )\r
1852         {\r
1853                 if( pxSocket->pxUserWakeCallback != NULL )\r
1854                 {\r
1855                         pxSocket->pxUserWakeCallback( pxSocket );\r
1856                 }\r
1857         }\r
1858         #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */\r
1859 \r
1860         #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
1861         {\r
1862                 if( pxSocket->pxSocketSet != NULL )\r
1863                 {\r
1864                         EventBits_t xSelectBits = ( pxSocket->xEventBits >> SOCKET_EVENT_BIT_COUNT ) & eSELECT_ALL;\r
1865                         if( xSelectBits != 0ul )\r
1866                         {\r
1867                                 pxSocket->xSocketBits |= xSelectBits;\r
1868                                 xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, xSelectBits );\r
1869                         }\r
1870                 }\r
1871 \r
1872                 pxSocket->xEventBits &= eSOCKET_ALL;\r
1873         }\r
1874         #endif /* ipconfigSUPPORT_SELECT_FUNCTION */\r
1875 \r
1876         if( ( pxSocket->xEventGroup != NULL ) && ( pxSocket->xEventBits != 0u ) )\r
1877         {\r
1878                 xEventGroupSetBits( pxSocket->xEventGroup, pxSocket->xEventBits );\r
1879         }\r
1880 \r
1881         pxSocket->xEventBits = 0ul;\r
1882 }\r
1883 \r
1884 /*-----------------------------------------------------------*/\r
1885 \r
1886 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )\r
1887 \r
1888         /* This define makes it possible for network-card drivers to inspect\r
1889          * UDP message and see if there is any UDP socket bound to a given port\r
1890          * number.\r
1891          * This is probably only usefull in systems with a minimum of RAM and\r
1892          * when lots of anonymous broadcast messages come in\r
1893          */\r
1894         BaseType_t xPortHasUDPSocket( uint16_t usPortNr )\r
1895         {\r
1896         BaseType_t xFound = pdFALSE;\r
1897 \r
1898                 vTaskSuspendAll();\r
1899                 {\r
1900                         if( ( pxListFindListItemWithValue( &xBoundUDPSocketsList, ( TickType_t ) usPortNr ) != NULL ) )\r
1901                         {\r
1902                                 xFound = pdTRUE;\r
1903                         }\r
1904                 }\r
1905                 xTaskResumeAll();\r
1906 \r
1907                 return xFound;\r
1908         }\r
1909 \r
1910 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */\r
1911 \r
1912 /*-----------------------------------------------------------*/\r
1913 \r
1914 #if( ipconfigUSE_TCP == 1 )\r
1915 \r
1916         static BaseType_t bMayConnect( FreeRTOS_Socket_t *pxSocket );\r
1917         static BaseType_t bMayConnect( FreeRTOS_Socket_t *pxSocket )\r
1918         {\r
1919                 switch( pxSocket->u.xTCP.ucTCPState )\r
1920                 {\r
1921                         case eCLOSED:\r
1922                         case eCLOSE_WAIT:       return 0;\r
1923                         case eCONNECT_SYN:      return -pdFREERTOS_ERRNO_EINPROGRESS;\r
1924                         default:                        return -pdFREERTOS_ERRNO_EAGAIN;\r
1925                 }\r
1926         }\r
1927 \r
1928 #endif /* ipconfigUSE_TCP */\r
1929 /*-----------------------------------------------------------*/\r
1930 \r
1931 #if( ipconfigUSE_TCP == 1 )\r
1932 \r
1933         static BaseType_t prvTCPConnectStart( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr *pxAddress )\r
1934         {\r
1935         BaseType_t xResult = 0;\r
1936 \r
1937                 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdFALSE )\r
1938                 {\r
1939                         /* Not a valid socket or wrong type */\r
1940                         xResult = -pdFREERTOS_ERRNO_EBADF;\r
1941                 }\r
1942                 else if( FreeRTOS_issocketconnected( pxSocket ) > 0 )\r
1943                 {\r
1944                         /* The socket is already connected. */\r
1945                         xResult = -pdFREERTOS_ERRNO_EISCONN;\r
1946                 }\r
1947                 else if( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE )\r
1948                 {\r
1949                         /* Bind the socket to the port that the client task will send from.\r
1950                         Non-standard, so the error returned is that returned by bind(). */\r
1951                         xResult = FreeRTOS_bind( ( Socket_t ) pxSocket, NULL, 0u );\r
1952                 }\r
1953 \r
1954                 if( xResult == 0 )\r
1955                 {\r
1956                         /* Check if it makes any sense to wait for a connect event, this condition\r
1957                         might change while sleeping, so it must be checked within each loop */\r
1958                         xResult = bMayConnect( pxSocket ); /* -EINPROGRESS, -EAGAIN, or 0 for OK */\r
1959 \r
1960                         /* Start the connect procedure, kernel will start working on it */\r
1961                         if( xResult == 0 )\r
1962                         {\r
1963                                 pxSocket->u.xTCP.bits.bConnPrepared = pdFALSE_UNSIGNED;\r
1964                                 pxSocket->u.xTCP.ucRepCount = 0u;\r
1965 \r
1966                                 FreeRTOS_debug_printf( ( "FreeRTOS_connect: %u to %lxip:%u\n",\r
1967                                         pxSocket->usLocalPort, FreeRTOS_ntohl( pxAddress->sin_addr ), FreeRTOS_ntohs( pxAddress->sin_port ) ) );\r
1968 \r
1969                                 /* Port on remote machine. */\r
1970                                 pxSocket->u.xTCP.usRemotePort = FreeRTOS_ntohs( pxAddress->sin_port );\r
1971 \r
1972                                 /* IP address of remote machine. */\r
1973                                 pxSocket->u.xTCP.ulRemoteIP = FreeRTOS_ntohl( pxAddress->sin_addr );\r
1974 \r
1975                                 /* (client) internal state: socket wants to send a connect. */\r
1976                                 vTCPStateChange( pxSocket, eCONNECT_SYN );\r
1977 \r
1978                                 /* To start an active connect. */\r
1979                                 pxSocket->u.xTCP.usTimeout = 1u;\r
1980 \r
1981                                 if( xSendEventToIPTask( eTCPTimerEvent ) != pdPASS )\r
1982                                 {\r
1983                                         xResult = -pdFREERTOS_ERRNO_ECANCELED;\r
1984                                 }\r
1985                         }\r
1986                 }\r
1987 \r
1988                 return xResult;\r
1989         }\r
1990 \r
1991 #endif /* ipconfigUSE_TCP */\r
1992 /*-----------------------------------------------------------*/\r
1993 \r
1994 #if( ipconfigUSE_TCP == 1 )\r
1995 \r
1996         /*\r
1997          * FreeRTOS_connect: socket wants to connect to a remote port\r
1998          */\r
1999         BaseType_t FreeRTOS_connect( Socket_t xClientSocket, struct freertos_sockaddr *pxAddress, socklen_t xAddressLength )\r
2000         {\r
2001         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t* ) xClientSocket;\r
2002         TickType_t xRemainingTime;\r
2003         BaseType_t xTimed = pdFALSE;\r
2004         BaseType_t xResult;\r
2005         TimeOut_t xTimeOut;\r
2006 \r
2007                 ( void ) xAddressLength;\r
2008 \r
2009                 xResult = prvTCPConnectStart( pxSocket, pxAddress );\r
2010 \r
2011                 if( xResult == 0 )\r
2012                 {\r
2013                         /* And wait for the result */\r
2014                         for( ;; )\r
2015                         {\r
2016                                 if( xTimed == pdFALSE )\r
2017                                 {\r
2018                                         /* Only in the first round, check for non-blocking */\r
2019                                         xRemainingTime = pxSocket->xReceiveBlockTime;\r
2020                                         if( xRemainingTime == ( TickType_t )0 )\r
2021                                         {\r
2022                                                 /* Not yet connected, correct state, non-blocking. */\r
2023                                                 xResult = -pdFREERTOS_ERRNO_EWOULDBLOCK;\r
2024                                                 break;\r
2025                                         }\r
2026 \r
2027                                         /* Don't get here a second time. */\r
2028                                         xTimed = pdTRUE;\r
2029 \r
2030                                         /* Fetch the current time */\r
2031                                         vTaskSetTimeOutState( &xTimeOut );\r
2032                                 }\r
2033 \r
2034                                 /* Did it get connected while sleeping ? */\r
2035                                 xResult = FreeRTOS_issocketconnected( pxSocket );\r
2036 \r
2037                                 /* Returns positive when connected, negative means an error */\r
2038                                 if( xResult < 0 )\r
2039                                 {\r
2040                                         /* Return the error */\r
2041                                         break;\r
2042                                 }\r
2043 \r
2044                                 if( xResult > 0 )\r
2045                                 {\r
2046                                         /* Socket now connected, return a zero */\r
2047                                         xResult = 0;\r
2048                                         break;\r
2049                                 }\r
2050 \r
2051                                 /* Is it allowed to sleep more? */\r
2052                                 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) )\r
2053                                 {\r
2054                                         xResult = -pdFREERTOS_ERRNO_ETIMEDOUT;\r
2055                                         break;\r
2056                                 }\r
2057 \r
2058                                 /* Go sleeping until we get any down-stream event */\r
2059                                 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_CONNECT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );\r
2060                         }\r
2061                 }\r
2062 \r
2063                 return xResult;\r
2064         }\r
2065 #endif /* ipconfigUSE_TCP */\r
2066 /*-----------------------------------------------------------*/\r
2067 \r
2068 #if( ipconfigUSE_TCP == 1 )\r
2069 \r
2070         /*\r
2071          * FreeRTOS_accept: can return a new connected socket\r
2072          * if the server socket is in listen mode and receives a connection request\r
2073          * The new socket will be bound already to the same port number as the listing\r
2074          * socket.\r
2075          */\r
2076         Socket_t FreeRTOS_accept( Socket_t xServerSocket, struct freertos_sockaddr *pxAddress, socklen_t *pxAddressLength )\r
2077         {\r
2078         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xServerSocket;\r
2079         FreeRTOS_Socket_t *pxClientSocket = NULL;\r
2080         TickType_t xRemainingTime;\r
2081         BaseType_t xTimed = pdFALSE, xAsk = pdFALSE;\r
2082         TimeOut_t xTimeOut;\r
2083         IPStackEvent_t xAskEvent;\r
2084 \r
2085                 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )\r
2086                 {\r
2087                         /* Not a valid socket or wrong type */\r
2088                         pxClientSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;\r
2089                 }\r
2090                 else if( ( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED ) &&\r
2091                                  ( pxSocket->u.xTCP.ucTCPState != eTCP_LISTEN ) )\r
2092                 {\r
2093                         /* Parent socket is not in listening mode */\r
2094                         pxClientSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;\r
2095                 }\r
2096                 else\r
2097                 {\r
2098                         /* Loop will stop with breaks. */\r
2099                         for( ; ; )\r
2100                         {\r
2101                                 /* Is there a new client? */\r
2102                                 vTaskSuspendAll();\r
2103                                 {\r
2104                                         if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED )\r
2105                                         {\r
2106                                                 pxClientSocket = pxSocket->u.xTCP.pxPeerSocket;\r
2107                                         }\r
2108                                         else\r
2109                                         {\r
2110                                                 pxClientSocket = pxSocket;\r
2111                                         }\r
2112                                         if( pxClientSocket != NULL )\r
2113                                         {\r
2114                                                 pxSocket->u.xTCP.pxPeerSocket = NULL;\r
2115 \r
2116                                                 /* Is it still not taken ? */\r
2117                                                 if( pxClientSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED )\r
2118                                                 {\r
2119                                                         pxClientSocket->u.xTCP.bits.bPassAccept = pdFALSE_UNSIGNED;\r
2120                                                 }\r
2121                                                 else\r
2122                                                 {\r
2123                                                         pxClientSocket = NULL;\r
2124                                                 }\r
2125                                         }\r
2126                                 }\r
2127                                 xTaskResumeAll();\r
2128 \r
2129                                 if( pxClientSocket != NULL )\r
2130                                 {\r
2131                                         if( pxAddress != NULL )\r
2132                                         {\r
2133                                                 /* IP address of remote machine. */\r
2134                                                 pxAddress->sin_addr = FreeRTOS_ntohl( pxClientSocket->u.xTCP.ulRemoteIP );\r
2135 \r
2136                                                 /* Port on remote machine. */\r
2137                                                 pxAddress->sin_port = FreeRTOS_ntohs( pxClientSocket->u.xTCP.usRemotePort );\r
2138                                         }\r
2139                                         if( pxAddressLength != NULL )\r
2140                                         {\r
2141                                                 *pxAddressLength = sizeof( *pxAddress );\r
2142                                         }\r
2143 \r
2144                                         if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED )\r
2145                                         {\r
2146                                                 xAsk = pdTRUE;\r
2147                                         }\r
2148                                 }\r
2149 \r
2150                                 if( xAsk != pdFALSE )\r
2151                                 {\r
2152                                         /* Ask to set an event in 'xEventGroup' as soon as a new\r
2153                                         client gets connected for this listening socket. */\r
2154                                         xAskEvent.eEventType = eTCPAcceptEvent;\r
2155                                         xAskEvent.pvData = ( void * ) pxSocket;\r
2156                                         xSendEventStructToIPTask( &xAskEvent, portMAX_DELAY );\r
2157                                 }\r
2158 \r
2159                                 if( pxClientSocket != NULL )\r
2160                                 {\r
2161                                         break;\r
2162                                 }\r
2163 \r
2164                                 if( xTimed == pdFALSE )\r
2165                                 {\r
2166                                         /* Only in the first round, check for non-blocking */\r
2167                                         xRemainingTime = pxSocket->xReceiveBlockTime;\r
2168                                         if( xRemainingTime == ( TickType_t ) 0 )\r
2169                                         {\r
2170                                                 break;\r
2171                                         }\r
2172 \r
2173                                         /* Don't get here a second time */\r
2174                                         xTimed = pdTRUE;\r
2175 \r
2176                                         /* Fetch the current time */\r
2177                                         vTaskSetTimeOutState( &xTimeOut );\r
2178                                 }\r
2179 \r
2180                                 /* Has the timeout been reached? */\r
2181                                 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )\r
2182                                 {\r
2183                                         break;\r
2184                                 }\r
2185 \r
2186                                 /* Go sleeping until we get any down-stream event */\r
2187                                 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_ACCEPT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );\r
2188                         }\r
2189                 }\r
2190 \r
2191                 return ( Socket_t ) pxClientSocket;\r
2192         }\r
2193 #endif /* ipconfigUSE_TCP */\r
2194 /*-----------------------------------------------------------*/\r
2195 \r
2196 #if( ipconfigUSE_TCP == 1 )\r
2197 \r
2198         /*\r
2199          * Read incoming data from a TCP socket\r
2200          * Only after the last byte has been read, a close error might be returned\r
2201          */\r
2202         BaseType_t FreeRTOS_recv( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags )\r
2203         {\r
2204         BaseType_t xByteCount;\r
2205         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
2206         TickType_t xRemainingTime;\r
2207         BaseType_t xTimed = pdFALSE;\r
2208         TimeOut_t xTimeOut;\r
2209         EventBits_t xEventBits = ( EventBits_t ) 0;\r
2210 \r
2211                 /* Check if the socket is valid, has type TCP and if it is bound to a\r
2212                 port. */\r
2213                 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )\r
2214                 {\r
2215                         xByteCount = -pdFREERTOS_ERRNO_EINVAL;\r
2216                 }\r
2217                 else\r
2218                 {\r
2219                         if( pxSocket->u.xTCP.rxStream != NULL )\r
2220                         {\r
2221                                 xByteCount = ( BaseType_t )uxStreamBufferGetSize ( pxSocket->u.xTCP.rxStream );\r
2222                         }\r
2223                         else\r
2224                         {\r
2225                                 xByteCount = 0;\r
2226                         }\r
2227 \r
2228                         while( xByteCount == 0 )\r
2229                         {\r
2230                                 switch( pxSocket->u.xTCP.ucTCPState )\r
2231                                 {\r
2232                                 case eCLOSED:\r
2233                                 case eCLOSE_WAIT:       /* (server + client) waiting for a connection termination request from the local user. */\r
2234                                 case eCLOSING:          /* (server + client) waiting for a connection termination request acknowledgement from the remote TCP. */\r
2235                                         if( pxSocket->u.xTCP.bits.bMallocError != pdFALSE_UNSIGNED )\r
2236                                         {\r
2237                                                 /* The no-memory error has priority above the non-connected error.\r
2238                                                 Both are fatal and will elad to closing the socket. */\r
2239                                                 xByteCount = -pdFREERTOS_ERRNO_ENOMEM;\r
2240                                         }\r
2241                                         else\r
2242                                         {\r
2243                                                 xByteCount = -pdFREERTOS_ERRNO_ENOTCONN;\r
2244                                         }\r
2245                                         /* Call continue to break out of the switch and also the while\r
2246                                         loop. */\r
2247                                         continue;\r
2248                                 default:\r
2249                                         break;\r
2250                                 }\r
2251 \r
2252                                 if( xTimed == pdFALSE )\r
2253                                 {\r
2254                                         /* Only in the first round, check for non-blocking. */\r
2255                                         xRemainingTime = pxSocket->xReceiveBlockTime;\r
2256 \r
2257                                         if( xRemainingTime == ( TickType_t ) 0 )\r
2258                                         {\r
2259                                                 #if( ipconfigSUPPORT_SIGNALS != 0 )\r
2260                                                 {\r
2261                                                         /* Just check for the interrupt flag. */\r
2262                                                         xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_INTR,\r
2263                                                                 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, socketDONT_BLOCK );\r
2264                                                 }\r
2265                                                 #endif /* ipconfigSUPPORT_SIGNALS */\r
2266                                                 break;\r
2267                                         }\r
2268 \r
2269                                         if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )\r
2270                                         {\r
2271                                                 break;\r
2272                                         }\r
2273 \r
2274                                         /* Don't get here a second time. */\r
2275                                         xTimed = pdTRUE;\r
2276 \r
2277                                         /* Fetch the current time. */\r
2278                                         vTaskSetTimeOutState( &xTimeOut );\r
2279                                 }\r
2280 \r
2281                                 /* Has the timeout been reached? */\r
2282                                 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )\r
2283                                 {\r
2284                                         break;\r
2285                                 }\r
2286 \r
2287                                 /* Block until there is a down-stream event. */\r
2288                                 xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup,\r
2289                                         eSOCKET_RECEIVE | eSOCKET_CLOSED | eSOCKET_INTR,\r
2290                                         pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );\r
2291                                 #if( ipconfigSUPPORT_SIGNALS != 0 )\r
2292                                 {\r
2293                                         if( ( xEventBits & eSOCKET_INTR ) != 0u )\r
2294                                         {\r
2295                                                 break;\r
2296                                         }\r
2297                                 }\r
2298                                 #else\r
2299                                 {\r
2300                                         ( void ) xEventBits;\r
2301                                 }\r
2302                                 #endif /* ipconfigSUPPORT_SIGNALS */\r
2303 \r
2304                                 if( pxSocket->u.xTCP.rxStream != NULL )\r
2305                                 {\r
2306                                         xByteCount = ( BaseType_t ) uxStreamBufferGetSize ( pxSocket->u.xTCP.rxStream );\r
2307                                 }\r
2308                                 else\r
2309                                 {\r
2310                                         xByteCount = 0;\r
2311                                 }\r
2312                         }\r
2313 \r
2314                 #if( ipconfigSUPPORT_SIGNALS != 0 )\r
2315                         if( ( xEventBits & eSOCKET_INTR ) != 0 )\r
2316                         {\r
2317                                 if( ( xEventBits & ( eSOCKET_RECEIVE | eSOCKET_CLOSED ) ) != 0 )\r
2318                                 {\r
2319                                         /* Shouldn't have cleared other flags. */\r
2320                                         xEventBits &= ~eSOCKET_INTR;\r
2321                                         xEventGroupSetBits( pxSocket->xEventGroup, xEventBits );\r
2322                                 }\r
2323                                 xByteCount = -pdFREERTOS_ERRNO_EINTR;\r
2324                         }\r
2325                         else\r
2326                 #endif /* ipconfigSUPPORT_SIGNALS */\r
2327                         if( xByteCount > 0 )\r
2328                         {\r
2329                                 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )\r
2330                                 {\r
2331                                         xByteCount = ( BaseType_t ) uxStreamBufferGet( pxSocket->u.xTCP.rxStream, 0ul, ( uint8_t * ) pvBuffer, ( size_t ) xBufferLength, ( xFlags & FREERTOS_MSG_PEEK ) != 0 );\r
2332                                         if( pxSocket->u.xTCP.bits.bLowWater != pdFALSE_UNSIGNED )\r
2333                                         {\r
2334                                                 /* We had reached the low-water mark, now see if the flag\r
2335                                                 can be cleared */\r
2336                                                 size_t uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );\r
2337 \r
2338                                                 if( uxFrontSpace >= pxSocket->u.xTCP.uxEnoughSpace )\r
2339                                                 {\r
2340                                                         pxSocket->u.xTCP.bits.bLowWater = pdFALSE_UNSIGNED;\r
2341                                                         pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;\r
2342                                                         pxSocket->u.xTCP.usTimeout = 1u; /* because bLowWater is cleared. */\r
2343                                                         xSendEventToIPTask( eTCPTimerEvent );\r
2344                                                 }\r
2345                                         }\r
2346                                 }\r
2347                                 else\r
2348                                 {\r
2349                                         /* Zero-copy reception of data: pvBuffer is a pointer to a pointer. */\r
2350                                         xByteCount = ( BaseType_t ) uxStreamBufferGetPtr( pxSocket->u.xTCP.rxStream, (uint8_t **)pvBuffer );\r
2351                                 }\r
2352                         }\r
2353                 } /* prvValidSocket() */\r
2354 \r
2355                 return xByteCount;\r
2356         }\r
2357 \r
2358 #endif /* ipconfigUSE_TCP */\r
2359 /*-----------------------------------------------------------*/\r
2360 \r
2361 #if( ipconfigUSE_TCP == 1 )\r
2362 \r
2363         static int32_t prvTCPSendCheck( FreeRTOS_Socket_t *pxSocket, size_t xDataLength )\r
2364         {\r
2365         int32_t xResult = 1;\r
2366 \r
2367                 /* Is this a socket of type TCP and is it already bound to a port number ? */\r
2368                 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )\r
2369                 {\r
2370                         xResult = -pdFREERTOS_ERRNO_EINVAL;\r
2371                 }\r
2372                 else if( pxSocket->u.xTCP.bits.bMallocError != pdFALSE_UNSIGNED )\r
2373                 {\r
2374                         xResult = -pdFREERTOS_ERRNO_ENOMEM;\r
2375                 }\r
2376                 else if( pxSocket->u.xTCP.ucTCPState == eCLOSED )\r
2377                 {\r
2378                         xResult = -pdFREERTOS_ERRNO_ENOTCONN;\r
2379                 }\r
2380                 else if( pxSocket->u.xTCP.bits.bFinSent != pdFALSE_UNSIGNED )\r
2381                 {\r
2382                         /* This TCP connection is closing already, the FIN flag has been sent.\r
2383                         Maybe it is still delivering or receiving data.\r
2384                         Return OK in order not to get closed/deleted too quickly */\r
2385                         xResult = 0;\r
2386                 }\r
2387                 else if( xDataLength == 0ul )\r
2388                 {\r
2389                         /* send() is being called to send zero bytes */\r
2390                         xResult = 0;\r
2391                 }\r
2392                 else if( pxSocket->u.xTCP.txStream == NULL )\r
2393                 {\r
2394                         /* Create the outgoing stream only when it is needed */\r
2395                         prvTCPCreateStream( pxSocket, pdFALSE );\r
2396 \r
2397                         if( pxSocket->u.xTCP.txStream == NULL )\r
2398                         {\r
2399                                 xResult = -pdFREERTOS_ERRNO_ENOMEM;\r
2400                         }\r
2401                 }\r
2402 \r
2403                 return xResult;\r
2404         }\r
2405 \r
2406 #endif /* ipconfigUSE_TCP */\r
2407 /*-----------------------------------------------------------*/\r
2408 \r
2409 #if( ipconfigUSE_TCP == 1 )\r
2410 \r
2411         /* Get a direct pointer to the circular transmit buffer.\r
2412         '*pxLength' will contain the number of bytes that may be written. */\r
2413         uint8_t *FreeRTOS_get_tx_head( Socket_t xSocket, BaseType_t *pxLength )\r
2414         {\r
2415         uint8_t *pucReturn;\r
2416         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
2417         StreamBuffer_t *pxBuffer = pxSocket->u.xTCP.txStream;\r
2418 \r
2419                 if( pxBuffer != NULL )\r
2420                 {\r
2421                 BaseType_t xSpace = ( BaseType_t ) uxStreamBufferGetSpace( pxBuffer );\r
2422                 BaseType_t xRemain = ( BaseType_t ) ( pxBuffer->LENGTH - pxBuffer->uxHead );\r
2423 \r
2424                         *pxLength = FreeRTOS_min_BaseType( xSpace, xRemain );\r
2425                         pucReturn = pxBuffer->ucArray + pxBuffer->uxHead;\r
2426                 }\r
2427                 else\r
2428                 {\r
2429                         *pxLength = 0;\r
2430                         pucReturn = NULL;\r
2431                 }\r
2432 \r
2433                 return pucReturn;\r
2434         }\r
2435 #endif /* ipconfigUSE_TCP */\r
2436 /*-----------------------------------------------------------*/\r
2437 \r
2438 #if( ipconfigUSE_TCP == 1 )\r
2439         /*\r
2440          * Send data using a TCP socket.  It is not necessary to have the socket\r
2441          * connected already.  Outgoing data will be stored and delivered as soon as\r
2442          * the socket gets connected.\r
2443          */\r
2444         BaseType_t FreeRTOS_send( Socket_t xSocket, const void *pvBuffer, size_t uxDataLength, BaseType_t xFlags )\r
2445         {\r
2446         BaseType_t xByteCount;\r
2447         BaseType_t xBytesLeft;\r
2448         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
2449         TickType_t xRemainingTime;\r
2450         BaseType_t xTimed = pdFALSE;\r
2451         TimeOut_t xTimeOut;\r
2452         BaseType_t xCloseAfterSend;\r
2453 \r
2454                 /* Prevent compiler warnings about unused parameters.  The parameter\r
2455                 may be used in future versions. */\r
2456                 ( void ) xFlags;\r
2457 \r
2458                 xByteCount = ( BaseType_t ) prvTCPSendCheck( pxSocket, uxDataLength );\r
2459 \r
2460                 if( xByteCount > 0 )\r
2461                 {\r
2462                         /* xBytesLeft is number of bytes to send, will count to zero. */\r
2463                         xBytesLeft = ( BaseType_t ) uxDataLength;\r
2464 \r
2465                         /* xByteCount is number of bytes that can be sent now. */\r
2466                         xByteCount = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );\r
2467 \r
2468                         /* While there are still bytes to be sent. */\r
2469                         while( xBytesLeft > 0 )\r
2470                         {\r
2471                                 /* If txStream has space. */\r
2472                                 if( xByteCount > 0 )\r
2473                                 {\r
2474                                         /* Don't send more than necessary. */\r
2475                                         if( xByteCount > xBytesLeft )\r
2476                                         {\r
2477                                                 xByteCount = xBytesLeft;\r
2478                                         }\r
2479 \r
2480                                         /* Is the close-after-send flag set and is this really the\r
2481                                         last transmission? */\r
2482                                         if( ( pxSocket->u.xTCP.bits.bCloseAfterSend != pdFALSE_UNSIGNED ) && ( xByteCount == xBytesLeft ) )\r
2483                                         {\r
2484                                                 xCloseAfterSend = pdTRUE;\r
2485                                         }\r
2486                                         else\r
2487                                         {\r
2488                                                 xCloseAfterSend = pdFALSE;\r
2489                                         }\r
2490 \r
2491                                         /* The flag 'bCloseAfterSend' can be set before sending data\r
2492                                         using setsockopt()\r
2493 \r
2494                                         When the last data packet is being sent out, a FIN flag will\r
2495                                         be included to let the peer know that no more data is to be\r
2496                                         expected.  The use of 'bCloseAfterSend' is not mandatory, it\r
2497                                         is just a faster way of transferring files (e.g. when using\r
2498                                         FTP). */\r
2499                                         if( xCloseAfterSend != pdFALSE )\r
2500                                         {\r
2501                                                 /* Now suspend the scheduler: sending the last data     and\r
2502                                                 setting bCloseRequested must be done together */\r
2503                                                 vTaskSuspendAll();\r
2504                                                 pxSocket->u.xTCP.bits.bCloseRequested = pdTRUE_UNSIGNED;\r
2505                                         }\r
2506 \r
2507                                         xByteCount = ( BaseType_t ) uxStreamBufferAdd( pxSocket->u.xTCP.txStream, 0ul, ( const uint8_t * ) pvBuffer, ( size_t ) xByteCount );\r
2508 \r
2509                                         if( xCloseAfterSend != pdFALSE )\r
2510                                         {\r
2511                                                 /* Now when the IP-task transmits the data, it will also\r
2512                                                 see     that bCloseRequested is true and include the FIN\r
2513                                                 flag to start closure of the connection. */\r
2514                                                 xTaskResumeAll();\r
2515                                         }\r
2516 \r
2517                                         /* Send a message to the IP-task so it can work on this\r
2518                                         socket.  Data is sent, let the IP-task work on it. */\r
2519                                         pxSocket->u.xTCP.usTimeout = 1u;\r
2520 \r
2521                                         if( xIsCallingFromIPTask() == pdFALSE )\r
2522                                         {\r
2523                                                 /* Only send a TCP timer event when not called from the\r
2524                                                 IP-task. */\r
2525                                                 xSendEventToIPTask( eTCPTimerEvent );\r
2526                                         }\r
2527 \r
2528                                         xBytesLeft -= xByteCount;\r
2529 \r
2530                                         if( xBytesLeft == 0 )\r
2531                                         {\r
2532                                                 break;\r
2533                                         }\r
2534 \r
2535                                         /* As there are still bytes left to be sent, increase the\r
2536                                         data pointer. */\r
2537                                         pvBuffer = ( void * ) ( ( ( const uint8_t * ) pvBuffer) + xByteCount );\r
2538                                 }\r
2539 \r
2540                                 /* Not all bytes have been sent. In case the socket is marked as\r
2541                                 blocking sleep for a while. */\r
2542                                 if( xTimed == pdFALSE )\r
2543                                 {\r
2544                                         /* Only in the first round, check for non-blocking. */\r
2545                                         xRemainingTime = pxSocket->xSendBlockTime;\r
2546 \r
2547                                         #if( ipconfigUSE_CALLBACKS != 0 )\r
2548                                         {\r
2549                                                 if( xIsCallingFromIPTask() != pdFALSE )\r
2550                                                 {\r
2551                                                         /* If this send function is called from within a\r
2552                                                         call-back handler it may not block, otherwise\r
2553                                                         chances would be big to get a deadlock: the IP-task\r
2554                                                         waiting for     itself. */\r
2555                                                         xRemainingTime = ( TickType_t ) 0;\r
2556                                                 }\r
2557                                         }\r
2558                                         #endif /* ipconfigUSE_CALLBACKS */\r
2559 \r
2560                                         if( xRemainingTime == ( TickType_t ) 0 )\r
2561                                         {\r
2562                                                 break;\r
2563                                         }\r
2564 \r
2565                                         if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )\r
2566                                         {\r
2567                                                 break;\r
2568                                         }\r
2569 \r
2570                                         /* Don't get here a second time. */\r
2571                                         xTimed = pdTRUE;\r
2572 \r
2573                                         /* Fetch the current time. */\r
2574                                         vTaskSetTimeOutState( &xTimeOut );\r
2575                                 }\r
2576                                 else\r
2577                                 {\r
2578                                         /* Has the timeout been reached? */\r
2579                                         if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )\r
2580                                         {\r
2581                                                 break;\r
2582                                         }\r
2583                                 }\r
2584 \r
2585                                 /* Go sleeping until down-stream events are received. */\r
2586                                 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_SEND | eSOCKET_CLOSED,\r
2587                                         pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );\r
2588 \r
2589                                 xByteCount = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );\r
2590                         }\r
2591 \r
2592                         /* How much was actually sent? */\r
2593                         xByteCount = ( ( BaseType_t ) uxDataLength ) - xBytesLeft;\r
2594 \r
2595                         if( xByteCount == 0 )\r
2596                         {\r
2597                                 if( pxSocket->u.xTCP.ucTCPState > eESTABLISHED )\r
2598                                 {\r
2599                                         xByteCount = ( BaseType_t ) -pdFREERTOS_ERRNO_ENOTCONN;\r
2600                                 }\r
2601                                 else\r
2602                                 {\r
2603                                         if( ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) != pdFALSE )\r
2604                                         {\r
2605                                                 FreeRTOS_debug_printf( ( "FreeRTOS_send: %u -> %lxip:%d: no space\n",\r
2606                                                         pxSocket->usLocalPort,\r
2607                                                         pxSocket->u.xTCP.ulRemoteIP,\r
2608                                                         pxSocket->u.xTCP.usRemotePort ) );\r
2609                                         }\r
2610 \r
2611                                         xByteCount = ( BaseType_t ) -pdFREERTOS_ERRNO_ENOSPC;\r
2612                                 }\r
2613                         }\r
2614                 }\r
2615 \r
2616                 return xByteCount;\r
2617         }\r
2618 \r
2619 #endif /* ipconfigUSE_TCP */\r
2620 /*-----------------------------------------------------------*/\r
2621 \r
2622 #if( ipconfigUSE_TCP == 1 )\r
2623 \r
2624         /*\r
2625          * Request to put a socket in listen mode\r
2626          */\r
2627         BaseType_t FreeRTOS_listen( Socket_t xSocket, BaseType_t xBacklog )\r
2628         {\r
2629         FreeRTOS_Socket_t *pxSocket;\r
2630         BaseType_t xResult = 0;\r
2631 \r
2632                 pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
2633 \r
2634                 /* listen() is allowed for a valid TCP socket in Closed state and already\r
2635                 bound. */\r
2636                 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )\r
2637                 {\r
2638                         xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;\r
2639                 }\r
2640                 else if( ( pxSocket->u.xTCP.ucTCPState != eCLOSED ) && ( pxSocket->u.xTCP.ucTCPState != eCLOSE_WAIT ) )\r
2641                 {\r
2642                         /* Socket is in a wrong state. */\r
2643                         xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;\r
2644                 }\r
2645                 else\r
2646                 {\r
2647                         /* Backlog is interpreted here as "the maximum number of child\r
2648                         sockets. */\r
2649                         pxSocket->u.xTCP.usBacklog = ( uint16_t )FreeRTOS_min_int32( ( int32_t ) 0xffff, ( int32_t ) xBacklog );\r
2650 \r
2651                         /* This cleaning is necessary only if a listening socket is being\r
2652                         reused as it might have had a previous connection. */\r
2653                         if( pxSocket->u.xTCP.bits.bReuseSocket )\r
2654                         {\r
2655                                 if( pxSocket->u.xTCP.rxStream != NULL )\r
2656                                 {\r
2657                                         vStreamBufferClear( pxSocket->u.xTCP.rxStream );\r
2658                                 }\r
2659 \r
2660                                 if( pxSocket->u.xTCP.txStream != NULL )\r
2661                                 {\r
2662                                         vStreamBufferClear( pxSocket->u.xTCP.txStream );\r
2663                                 }\r
2664 \r
2665                                 memset( pxSocket->u.xTCP.xPacket.u.ucLastPacket, '\0', sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket ) );\r
2666                                 memset( &pxSocket->u.xTCP.xTCPWindow, '\0', sizeof( pxSocket->u.xTCP.xTCPWindow ) );\r
2667                                 memset( &pxSocket->u.xTCP.bits, '\0', sizeof( pxSocket->u.xTCP.bits ) );\r
2668 \r
2669                                 /* Now set the bReuseSocket flag again, because the bits have\r
2670                                 just been cleared. */\r
2671                                 pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE_UNSIGNED;\r
2672                         }\r
2673 \r
2674                         vTCPStateChange( pxSocket, eTCP_LISTEN );\r
2675                 }\r
2676 \r
2677                 return xResult;\r
2678         }\r
2679 \r
2680 #endif /* ipconfigUSE_TCP */\r
2681 /*-----------------------------------------------------------*/\r
2682 \r
2683 #if( ipconfigUSE_TCP == 1 )\r
2684 \r
2685         /* shutdown - shut down part of a full-duplex connection */\r
2686         BaseType_t FreeRTOS_shutdown( Socket_t xSocket, BaseType_t xHow )\r
2687         {\r
2688         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
2689         BaseType_t xResult;\r
2690 \r
2691                 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )\r
2692                 {\r
2693                         /*_RB_ Is this comment correct?  The socket is not of a type that\r
2694                         supports the listen() operation. */\r
2695                         xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;\r
2696                 }\r
2697                 else if ( pxSocket->u.xTCP.ucTCPState != eESTABLISHED )\r
2698                 {\r
2699                         /*_RB_ Is this comment correct?  The socket is not of a type that\r
2700                         supports the listen() operation. */\r
2701                         xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;\r
2702                 }\r
2703                 else\r
2704                 {\r
2705                         pxSocket->u.xTCP.bits.bUserShutdown = pdTRUE_UNSIGNED;\r
2706 \r
2707                         /* Let the IP-task perform the shutdown of the connection. */\r
2708                         pxSocket->u.xTCP.usTimeout = 1u;\r
2709                         xSendEventToIPTask( eTCPTimerEvent );\r
2710                         xResult = 0;\r
2711                 }\r
2712                 (void) xHow;\r
2713 \r
2714                 return xResult;\r
2715         }\r
2716 \r
2717 #endif /* ipconfigUSE_TCP */\r
2718 /*-----------------------------------------------------------*/\r
2719 \r
2720 #if( ipconfigUSE_TCP == 1 )\r
2721 \r
2722         /*\r
2723          * A TCP timer has expired, now check all TCP sockets for:\r
2724          * - Active connect\r
2725          * - Send a delayed ACK\r
2726          * - Send new data\r
2727          * - Send a keep-alive packet\r
2728          * - Check for timeout (in non-connected states only)\r
2729          */\r
2730         TickType_t xTCPTimerCheck( BaseType_t xWillSleep )\r
2731         {\r
2732         FreeRTOS_Socket_t *pxSocket;\r
2733         TickType_t xShortest = pdMS_TO_TICKS( ( TickType_t ) ipTCP_TIMER_PERIOD_MS );\r
2734         TickType_t xNow = xTaskGetTickCount();\r
2735         static TickType_t xLastTime = 0u;\r
2736         TickType_t xDelta = xNow - xLastTime;\r
2737         ListItem_t* pxEnd = ( ListItem_t * ) listGET_END_MARKER( &xBoundTCPSocketsList );\r
2738         ListItem_t *pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );\r
2739 \r
2740                 xLastTime = xNow;\r
2741 \r
2742                 if( xDelta == 0u )\r
2743                 {\r
2744                         xDelta = 1u;\r
2745                 }\r
2746 \r
2747                 while( pxIterator != pxEnd )\r
2748                 {\r
2749                         pxSocket = ( FreeRTOS_Socket_t * )listGET_LIST_ITEM_OWNER( pxIterator );\r
2750                         pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator );\r
2751 \r
2752                         /* Sockets with 'tmout == 0' do not need any regular attention. */\r
2753                         if( pxSocket->u.xTCP.usTimeout == 0u )\r
2754                         {\r
2755                                 continue;\r
2756                         }\r
2757 \r
2758                         if( xDelta < ( TickType_t ) pxSocket->u.xTCP.usTimeout )\r
2759                         {\r
2760                                 pxSocket->u.xTCP.usTimeout = ( uint16_t ) ( ( ( TickType_t ) pxSocket->u.xTCP.usTimeout ) - xDelta );\r
2761                         }\r
2762                         else\r
2763                         {\r
2764                         int rc ;\r
2765                                 pxSocket->u.xTCP.usTimeout = 0u;\r
2766                                 rc = xTCPSocketCheck( pxSocket );\r
2767 \r
2768                                 /* Within this function, the socket might want to send a delayed\r
2769                                 ack or send out data or whatever it needs to do. */\r
2770                                 if( rc < 0 )\r
2771                                 {\r
2772                                         /* Continue because the socket was deleted. */\r
2773                                         continue;\r
2774                                 }\r
2775                         }\r
2776 \r
2777                         /* In xEventBits the driver may indicate that the socket has\r
2778                         important events for the user.  These are only done just before the\r
2779                         IP-task goes to sleep. */\r
2780                         if( pxSocket->xEventBits != 0u )\r
2781                         {\r
2782                                 if( xWillSleep != pdFALSE )\r
2783                                 {\r
2784                                         /* The IP-task is about to go to sleep, so messages can be\r
2785                                         sent to the socket owners. */\r
2786                                         vSocketWakeUpUser( pxSocket );\r
2787                                 }\r
2788                                 else\r
2789                                 {\r
2790                                         /* Or else make sure this will be called again to wake-up\r
2791                                         the sockets' owner. */\r
2792                                         xShortest = ( TickType_t ) 0;\r
2793                                 }\r
2794                         }\r
2795 \r
2796                         if( ( pxSocket->u.xTCP.usTimeout != 0u ) && ( xShortest > ( TickType_t ) pxSocket->u.xTCP.usTimeout ) )\r
2797                         {\r
2798                                 xShortest = ( TickType_t ) pxSocket->u.xTCP.usTimeout;\r
2799                         }\r
2800                 }\r
2801 \r
2802                 return xShortest;\r
2803         }\r
2804 \r
2805 #endif /* ipconfigUSE_TCP */\r
2806 /*-----------------------------------------------------------*/\r
2807 \r
2808 #if( ipconfigUSE_TCP == 1 )\r
2809 \r
2810         /*\r
2811          * TCP: as multiple sockets may be bound to the same local port number\r
2812          * looking up a socket is a little more complex:\r
2813          * Both a local port, and a remote port and IP address are being used\r
2814          * For a socket in listening mode, the remote port and IP address are both 0\r
2815          */\r
2816         FreeRTOS_Socket_t *pxTCPSocketLookup( uint32_t ulLocalIP, UBaseType_t uxLocalPort, uint32_t ulRemoteIP, UBaseType_t uxRemotePort )\r
2817         {\r
2818         ListItem_t *pxIterator;\r
2819         FreeRTOS_Socket_t *pxResult = NULL, *pxListenSocket = NULL;\r
2820         MiniListItem_t *pxEnd = ( MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );\r
2821 \r
2822                 /* Parameter not yet supported. */\r
2823                 ( void ) ulLocalIP;\r
2824 \r
2825                 for( pxIterator  = ( ListItem_t * ) listGET_NEXT( pxEnd );\r
2826                          pxIterator != ( ListItem_t * ) pxEnd;\r
2827                          pxIterator  = ( ListItem_t * ) listGET_NEXT( pxIterator ) )\r
2828                 {\r
2829                         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );\r
2830 \r
2831                         if( pxSocket->usLocalPort == ( uint16_t ) uxLocalPort )\r
2832                         {\r
2833                                 if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN )\r
2834                                 {\r
2835                                         /* If this is a socket listening to uxLocalPort, remember it\r
2836                                         in case there is no perfect match. */\r
2837                                         pxListenSocket = pxSocket;\r
2838                                 }\r
2839                                 else if( ( pxSocket->u.xTCP.usRemotePort == ( uint16_t ) uxRemotePort ) && ( pxSocket->u.xTCP.ulRemoteIP == ulRemoteIP ) )\r
2840                                 {\r
2841                                         /* For sockets not in listening mode, find a match with\r
2842                                         xLocalPort, ulRemoteIP AND xRemotePort. */\r
2843                                         pxResult = pxSocket;\r
2844                                         break;\r
2845                                 }\r
2846                         }\r
2847                 }\r
2848                 if( pxResult == NULL )\r
2849                 {\r
2850                         /* An exact match was not found, maybe a listening socket was\r
2851                         found. */\r
2852                         pxResult = pxListenSocket;\r
2853                 }\r
2854 \r
2855                 return pxResult;\r
2856         }\r
2857 \r
2858 #endif /* ipconfigUSE_TCP */\r
2859 /*-----------------------------------------------------------*/\r
2860 \r
2861 #if( ipconfigUSE_TCP == 1 )\r
2862 \r
2863         const struct xSTREAM_BUFFER *FreeRTOS_get_rx_buf( Socket_t xSocket )\r
2864         {\r
2865         FreeRTOS_Socket_t *pxSocket = (FreeRTOS_Socket_t *)xSocket;\r
2866 \r
2867                 return pxSocket->u.xTCP.rxStream;\r
2868         }\r
2869 \r
2870 #endif /* ipconfigUSE_TCP */\r
2871 /*-----------------------------------------------------------*/\r
2872 \r
2873 #if( ipconfigUSE_TCP == 1 )\r
2874 \r
2875         static StreamBuffer_t *prvTCPCreateStream ( FreeRTOS_Socket_t *pxSocket, BaseType_t xIsInputStream )\r
2876         {\r
2877         StreamBuffer_t *pxBuffer;\r
2878         size_t uxLength;\r
2879         size_t uxSize;\r
2880 \r
2881                 /* Now that a stream is created, the maximum size is fixed before\r
2882                 creation, it could still be changed with setsockopt(). */\r
2883                 if( xIsInputStream != pdFALSE )\r
2884                 {\r
2885                         uxLength = pxSocket->u.xTCP.uxRxStreamSize;\r
2886 \r
2887                         if( pxSocket->u.xTCP.uxLittleSpace == 0ul )\r
2888                         {\r
2889                                 pxSocket->u.xTCP.uxLittleSpace  = ( 1ul * pxSocket->u.xTCP.uxRxStreamSize ) / 5u; /*_RB_ Why divide by 5?  Can this be changed to a #define? */\r
2890                         }\r
2891 \r
2892                         if( pxSocket->u.xTCP.uxEnoughSpace == 0ul )\r
2893                         {\r
2894                                 pxSocket->u.xTCP.uxEnoughSpace = ( 4ul * pxSocket->u.xTCP.uxRxStreamSize ) / 5u; /*_RB_ Why multiply by 4?  Maybe sock80_PERCENT?*/\r
2895                         }\r
2896                 }\r
2897                 else\r
2898                 {\r
2899                         uxLength = pxSocket->u.xTCP.uxTxStreamSize;\r
2900                 }\r
2901 \r
2902                 /* Add an extra 4 (or 8) bytes. */\r
2903                 uxLength += sizeof( size_t );\r
2904 \r
2905                 /* And make the length a multiple of sizeof( size_t ). */\r
2906                 uxLength &= ~( sizeof( size_t ) - 1u );\r
2907 \r
2908                 uxSize = sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) + uxLength;\r
2909 \r
2910                 pxBuffer = ( StreamBuffer_t * )pvPortMallocLarge( uxSize );\r
2911 \r
2912                 if( pxBuffer == NULL )\r
2913                 {\r
2914                         FreeRTOS_debug_printf( ( "prvTCPCreateStream: malloc failed\n" ) );\r
2915                         pxSocket->u.xTCP.bits.bMallocError = pdTRUE_UNSIGNED;\r
2916                         vTCPStateChange( pxSocket, eCLOSE_WAIT );\r
2917                 }\r
2918                 else\r
2919                 {\r
2920                         /* Clear the markers of the stream */\r
2921                         memset( pxBuffer, '\0', sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) );\r
2922                         pxBuffer->LENGTH = ( size_t ) uxLength ;\r
2923 \r
2924                         if( xTCPWindowLoggingLevel != 0 )\r
2925                         {\r
2926                                 FreeRTOS_debug_printf( ( "prvTCPCreateStream: %cxStream created %lu bytes (total %lu)\n", xIsInputStream ? 'R' : 'T', uxLength, uxSize ) );\r
2927                         }\r
2928 \r
2929                         if( xIsInputStream != 0 )\r
2930                         {\r
2931                                 pxSocket->u.xTCP.rxStream = pxBuffer;\r
2932                         }\r
2933                         else\r
2934                         {\r
2935                                 pxSocket->u.xTCP.txStream = pxBuffer;\r
2936                         }\r
2937                 }\r
2938 \r
2939                 return pxBuffer;\r
2940         }\r
2941 \r
2942 #endif /* ipconfigUSE_TCP */\r
2943 /*-----------------------------------------------------------*/\r
2944 \r
2945 #if( ipconfigUSE_TCP == 1 )\r
2946 \r
2947         /*\r
2948          * Add data to the RxStream.  When uxOffset > 0, data has come in out-of-order\r
2949          * and will be put in front of the head so it can not be popped by the user.\r
2950          */\r
2951         int32_t lTCPAddRxdata( FreeRTOS_Socket_t *pxSocket, size_t uxOffset, const uint8_t *pcData, uint32_t ulByteCount )\r
2952         {\r
2953         StreamBuffer_t *pxStream = pxSocket->u.xTCP.rxStream;\r
2954         int32_t xResult;\r
2955         #if( ipconfigUSE_CALLBACKS == 1 )\r
2956                 BaseType_t bHasHandler = ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xTCP.pxHandleReceive );\r
2957                 const uint8_t *pucBuffer = NULL;\r
2958         #endif /* ipconfigUSE_CALLBACKS */\r
2959 \r
2960                 /* int32_t uxStreamBufferAdd( pxBuffer, uxOffset, pucData, aCount )\r
2961                 if( pucData != NULL ) copy data the the buffer\r
2962                 if( pucData == NULL ) no copying, just advance rxHead\r
2963                 if( uxOffset != 0 ) Just store data which has come out-of-order\r
2964                 if( uxOffset == 0 ) Also advance rxHead */\r
2965                 if( pxStream == NULL )\r
2966                 {\r
2967                         pxStream = prvTCPCreateStream( pxSocket, pdTRUE );\r
2968                         if( pxStream == NULL )\r
2969                         {\r
2970                                 return -1;\r
2971                         }\r
2972                 }\r
2973 \r
2974                 #if( ipconfigUSE_CALLBACKS == 1 )\r
2975                 {\r
2976                         if( ( bHasHandler != pdFALSE ) && ( uxStreamBufferGetSize( pxStream ) == 0u ) && ( uxOffset == 0ul ) && ( pcData != NULL ) )\r
2977                         {\r
2978                                 /* Data can be passed directly to the user */\r
2979                                 pucBuffer = pcData;\r
2980 \r
2981                                 /* Zero-copy for call-back: no need to add the bytes to the\r
2982                                 stream, only the pointer will be advanced by uxStreamBufferAdd(). */\r
2983                                 pcData = NULL;\r
2984                         }\r
2985                 }\r
2986                 #endif /* ipconfigUSE_CALLBACKS */\r
2987 \r
2988                 xResult = ( int32_t ) uxStreamBufferAdd( pxStream, uxOffset, pcData, ( size_t ) ulByteCount );\r
2989 \r
2990                 #if( ipconfigHAS_DEBUG_PRINTF != 0 )\r
2991                 {\r
2992                         if( xResult != ( int32_t ) ulByteCount )\r
2993                         {\r
2994                                 FreeRTOS_debug_printf( ( "lTCPAddRxdata: at %ld: %ld/%lu bytes (tail %lu head %lu space %lu front %lu)\n",\r
2995                                         uxOffset, xResult, ulByteCount,\r
2996                                         pxStream->uxTail,\r
2997                                         pxStream->uxHead,\r
2998                                         uxStreamBufferFrontSpace( pxStream ),\r
2999                                         pxStream->uxFront ) );\r
3000                         }\r
3001                 }\r
3002                 #endif /* ipconfigHAS_DEBUG_PRINTF */\r
3003 \r
3004                 if( uxOffset == 0u )\r
3005                 {\r
3006                         /* Data is being added to rxStream at the head (offs = 0) */\r
3007                         #if( ipconfigUSE_CALLBACKS == 1 )\r
3008                                 if( bHasHandler != pdFALSE )\r
3009                                 {\r
3010                                         /* The socket owner has installed an OnReceive handler. Pass the\r
3011                                         Rx data, without copying from the rxStream, to the user. */\r
3012                                         for (;;)\r
3013                                         {\r
3014                                                 uint8_t *ucReadPtr = NULL;\r
3015                                                 uint32_t ulCount;\r
3016                                                 if( pucBuffer != NULL )\r
3017                                                 {\r
3018                                                         ucReadPtr = ( uint8_t * )pucBuffer;\r
3019                                                         ulCount = ulByteCount;\r
3020                                                         pucBuffer = NULL;\r
3021                                                 }\r
3022                                                 else\r
3023                                                 {\r
3024                                                         ulCount = ( uint32_t ) uxStreamBufferGetPtr( pxStream, &( ucReadPtr ) );\r
3025                                                 }\r
3026 \r
3027                                                 if( ulCount == 0ul )\r
3028                                                 {\r
3029                                                         break;\r
3030                                                 }\r
3031 \r
3032                                                 pxSocket->u.xTCP.pxHandleReceive( (Socket_t *)pxSocket, ( void* )ucReadPtr, ( size_t ) ulCount );\r
3033                                                 uxStreamBufferGet( pxStream, 0ul, NULL, ( size_t ) ulCount, pdFALSE );\r
3034                                         }\r
3035                                 } else\r
3036                         #endif /* ipconfigUSE_CALLBACKS */\r
3037                         {\r
3038                                 /* See if running out of space. */\r
3039                                 if( pxSocket->u.xTCP.bits.bLowWater == pdFALSE_UNSIGNED )\r
3040                                 {\r
3041                                         size_t uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );\r
3042                                         if( uxFrontSpace <= pxSocket->u.xTCP.uxLittleSpace  )\r
3043                                         {\r
3044                                                 pxSocket->u.xTCP.bits.bLowWater = pdTRUE_UNSIGNED;\r
3045                                                 pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;\r
3046 \r
3047                                                 /* bLowWater was reached, send the changed window size. */\r
3048                                                 pxSocket->u.xTCP.usTimeout = 1u;\r
3049                                                 xSendEventToIPTask( eTCPTimerEvent );\r
3050                                         }\r
3051                                 }\r
3052 \r
3053                                 /* New incoming data is available, wake up the user.   User's\r
3054                                 semaphores will be set just before the IP-task goes asleep. */\r
3055                                 pxSocket->xEventBits |= eSOCKET_RECEIVE;\r
3056 \r
3057                                 #if ipconfigSUPPORT_SELECT_FUNCTION == 1\r
3058                                 {\r
3059                                         if( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 )\r
3060                                         {\r
3061                                                 pxSocket->xEventBits |= ( eSELECT_READ << SOCKET_EVENT_BIT_COUNT );\r
3062                                         }\r
3063                                 }\r
3064                                 #endif\r
3065                         }\r
3066                 }\r
3067 \r
3068                 return xResult;\r
3069         }\r
3070 \r
3071 #endif /* ipconfigUSE_TCP */\r
3072 /*-----------------------------------------------------------*/\r
3073 \r
3074 #if( ipconfigUSE_TCP == 1 )\r
3075 \r
3076         /* Function to get the remote address and IP port */\r
3077         BaseType_t FreeRTOS_GetRemoteAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress )\r
3078         {\r
3079         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
3080         BaseType_t xResult;\r
3081 \r
3082                 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
3083                 {\r
3084                         xResult = -pdFREERTOS_ERRNO_EINVAL;\r
3085                 }\r
3086                 else\r
3087                 {\r
3088                         /* BSD style sockets communicate IP and port addresses in network\r
3089                         byte order.\r
3090 \r
3091                         IP address of remote machine. */\r
3092                         pxAddress->sin_addr = FreeRTOS_htonl ( pxSocket->u.xTCP.ulRemoteIP );\r
3093 \r
3094                         /* Port on remote machine. */\r
3095                         pxAddress->sin_port = FreeRTOS_htons ( pxSocket->u.xTCP.usRemotePort );\r
3096 \r
3097                         xResult = ( BaseType_t ) sizeof( ( *pxAddress ) );\r
3098                 }\r
3099 \r
3100                 return xResult;\r
3101         }\r
3102 \r
3103 #endif /* ipconfigUSE_TCP */\r
3104 \r
3105 /*-----------------------------------------------------------*/\r
3106 \r
3107 #if( ipconfigUSE_TCP == 1 )\r
3108 \r
3109         /* Returns the number of bytes that may be added to txStream */\r
3110         BaseType_t FreeRTOS_maywrite( Socket_t xSocket )\r
3111         {\r
3112         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
3113         BaseType_t xResult;\r
3114 \r
3115                 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
3116                 {\r
3117                         xResult = -pdFREERTOS_ERRNO_EINVAL;\r
3118                 }\r
3119                 else if( pxSocket->u.xTCP.ucTCPState != eESTABLISHED )\r
3120                 {\r
3121                         if( ( pxSocket->u.xTCP.ucTCPState < eCONNECT_SYN ) || ( pxSocket->u.xTCP.ucTCPState > eESTABLISHED ) )\r
3122                         {\r
3123                                 xResult = -1;\r
3124                         }\r
3125                         else\r
3126                         {\r
3127                                 xResult = 0;\r
3128                         }\r
3129                 }\r
3130                 else if( pxSocket->u.xTCP.txStream == NULL )\r
3131                 {\r
3132                         xResult = ( BaseType_t ) pxSocket->u.xTCP.uxTxStreamSize;\r
3133                 }\r
3134                 else\r
3135                 {\r
3136                         xResult = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );\r
3137                 }\r
3138 \r
3139                 return xResult;\r
3140         }\r
3141 \r
3142 #endif /* ipconfigUSE_TCP */\r
3143 /*-----------------------------------------------------------*/\r
3144 \r
3145 #if( ipconfigUSE_TCP ==1 )\r
3146 \r
3147         BaseType_t FreeRTOS_tx_space( Socket_t xSocket )\r
3148         {\r
3149         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
3150         BaseType_t xReturn;\r
3151 \r
3152                 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
3153                 {\r
3154                         xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
3155                 }\r
3156                 else\r
3157                 {\r
3158                         if( pxSocket->u.xTCP.txStream != NULL )\r
3159                         {\r
3160                                 xReturn = ( BaseType_t ) uxStreamBufferGetSpace ( pxSocket->u.xTCP.txStream );\r
3161                         }\r
3162                         else\r
3163                         {\r
3164                                 xReturn = ( BaseType_t ) pxSocket->u.xTCP.uxTxStreamSize;\r
3165                         }\r
3166                 }\r
3167 \r
3168                 return xReturn;\r
3169         }\r
3170 \r
3171 #endif /* ipconfigUSE_TCP */\r
3172 /*-----------------------------------------------------------*/\r
3173 \r
3174 #if( ipconfigUSE_TCP == 1 )\r
3175 \r
3176         BaseType_t FreeRTOS_tx_size( Socket_t xSocket )\r
3177         {\r
3178         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
3179         BaseType_t xReturn;\r
3180 \r
3181                 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
3182                 {\r
3183                         xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
3184                 }\r
3185                 else\r
3186                 {\r
3187                         if( pxSocket->u.xTCP.txStream != NULL )\r
3188                         {\r
3189                                 xReturn = ( BaseType_t ) uxStreamBufferGetSize ( pxSocket->u.xTCP.txStream );\r
3190                         }\r
3191                         else\r
3192                         {\r
3193                                 xReturn = 0;\r
3194                         }\r
3195                 }\r
3196 \r
3197                 return xReturn;\r
3198         }\r
3199 \r
3200 #endif /* ipconfigUSE_TCP */\r
3201 /*-----------------------------------------------------------*/\r
3202 \r
3203 #if( ipconfigUSE_TCP == 1 )\r
3204 \r
3205         /* Returns pdTRUE if TCP socket is connected. */\r
3206         BaseType_t FreeRTOS_issocketconnected( Socket_t xSocket )\r
3207         {\r
3208         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
3209         BaseType_t xReturn = pdFALSE;\r
3210 \r
3211                 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
3212                 {\r
3213                         xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
3214                 }\r
3215                 else\r
3216                 {\r
3217                         if( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED )\r
3218                         {\r
3219                                 if( pxSocket->u.xTCP.ucTCPState < eCLOSE_WAIT )\r
3220                                 {\r
3221                                         xReturn = pdTRUE;\r
3222                                 }\r
3223                         }\r
3224                 }\r
3225 \r
3226                 return xReturn;\r
3227         }\r
3228 \r
3229 #endif /* ipconfigUSE_TCP */\r
3230 /*-----------------------------------------------------------*/\r
3231 \r
3232 #if( ipconfigUSE_TCP == 1 )\r
3233 \r
3234         /* returns the actual size of MSS being used */\r
3235         BaseType_t FreeRTOS_mss( Socket_t xSocket )\r
3236         {\r
3237         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
3238         BaseType_t xReturn;\r
3239 \r
3240                 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
3241                 {\r
3242                         xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
3243                 }\r
3244                 else\r
3245                 {\r
3246                         /* usCurMSS is declared as uint16_t to save space.  FreeRTOS_mss()\r
3247                         will often be used in signed native-size expressions cast it to\r
3248                         BaseType_t. */\r
3249                         xReturn = ( BaseType_t ) ( pxSocket->u.xTCP.usCurMSS );\r
3250                 }\r
3251 \r
3252                 return xReturn;\r
3253         }\r
3254 \r
3255 #endif /* ipconfigUSE_TCP */\r
3256 /*-----------------------------------------------------------*/\r
3257 \r
3258 #if( ipconfigUSE_TCP == 1 )\r
3259 \r
3260         /* HT: for internal use only: return the connection status */\r
3261         BaseType_t FreeRTOS_connstatus( Socket_t xSocket )\r
3262         {\r
3263         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
3264         BaseType_t xReturn;\r
3265 \r
3266                 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
3267                 {\r
3268                         xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
3269                 }\r
3270                 else\r
3271                 {\r
3272                         /* Cast it to BaseType_t */\r
3273                         xReturn = ( BaseType_t ) ( pxSocket->u.xTCP.ucTCPState );\r
3274                 }\r
3275 \r
3276                 return xReturn;\r
3277         }\r
3278 \r
3279 #endif /* ipconfigUSE_TCP */\r
3280 /*-----------------------------------------------------------*/\r
3281 \r
3282 #if( ipconfigUSE_TCP == 1 )\r
3283 \r
3284         /*\r
3285          * Returns the number of bytes which can be read.\r
3286          */\r
3287         BaseType_t FreeRTOS_rx_size( Socket_t xSocket )\r
3288         {\r
3289         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
3290         BaseType_t xReturn;\r
3291 \r
3292                 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
3293                 {\r
3294                         xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
3295                 }\r
3296                 else if( pxSocket->u.xTCP.rxStream != NULL )\r
3297                 {\r
3298                         xReturn = ( BaseType_t ) uxStreamBufferGetSize( pxSocket->u.xTCP.rxStream );\r
3299                 }\r
3300                 else\r
3301                 {\r
3302                         xReturn = 0;\r
3303                 }\r
3304 \r
3305                 return xReturn;\r
3306         }\r
3307 \r
3308 #endif /* ipconfigUSE_TCP */\r
3309 /*-----------------------------------------------------------*/\r
3310 \r
3311 #if( ipconfigUSE_TCP == 1 )\r
3312 \r
3313         void FreeRTOS_netstat( void )\r
3314         {\r
3315         IPStackEvent_t xAskEvent;\r
3316 \r
3317                 /* Ask the IP-task to call vTCPNetStat()\r
3318                  * to avoid accessing xBoundTCPSocketsList\r
3319                  */\r
3320                 xAskEvent.eEventType = eTCPNetStat;\r
3321                 xAskEvent.pvData = ( void * ) NULL;\r
3322                 xSendEventStructToIPTask( &xAskEvent, 1000u );\r
3323         }\r
3324 \r
3325 #endif /* ipconfigUSE_TCP */\r
3326 /*-----------------------------------------------------------*/\r
3327 \r
3328 #if( ( ipconfigHAS_PRINTF != 0 ) && ( ipconfigUSE_TCP == 1 ) )\r
3329 \r
3330         void vTCPNetStat( void )\r
3331         {\r
3332         /* Show a simple listing of all created sockets and their connections */\r
3333         ListItem_t *pxIterator;\r
3334         BaseType_t count = 0;\r
3335 \r
3336                 if( listLIST_IS_INITIALISED( &xBoundTCPSocketsList ) == pdFALSE )\r
3337                 {\r
3338                         FreeRTOS_printf( ( "PLUS-TCP not initialized\n" ) );\r
3339                 }\r
3340                 else\r
3341                 {\r
3342                         FreeRTOS_printf( ( "Prot Port IP-Remote       : Port  R/T Status       Alive  tmout Child\n" ) );\r
3343                         for( pxIterator  = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );\r
3344                                  pxIterator != ( ListItem_t * ) listGET_END_MARKER( &xBoundTCPSocketsList );\r
3345                                  pxIterator  = ( ListItem_t * ) listGET_NEXT( pxIterator ) )\r
3346                         {\r
3347                                 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );\r
3348                                 #if( ipconfigTCP_KEEP_ALIVE == 1 )\r
3349                                         TickType_t age = xTaskGetTickCount() - pxSocket->u.xTCP.xLastAliveTime;\r
3350                                 #else\r
3351                                         TickType_t age = 0u;\r
3352                                 #endif\r
3353                                 #if( ipconfigUSE_CALLBACKS == 1 )\r
3354                                         void *pxHandleReceive = (void*)pxSocket->u.xTCP.pxHandleReceive;\r
3355                                 #else\r
3356                                         void *pxHandleReceive = (void*)NULL;\r
3357                                 #endif\r
3358                                 char ucChildText[16] = "";\r
3359                                 if (pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN)\r
3360                                 {\r
3361                                         const int32_t copied_len = snprintf( ucChildText, sizeof( ucChildText ), " %d/%d",\r
3362                                                 ( int ) pxSocket->u.xTCP.usChildCount,\r
3363                                                 ( int ) pxSocket->u.xTCP.usBacklog);\r
3364                                         /* These should never evaluate to false since the buffers are both shorter than 5-6 characters (<=65535) */\r
3365                                         configASSERT( copied_len >= 0 );\r
3366                                         configASSERT( copied_len < sizeof( ucChildText ) );\r
3367                                 }\r
3368                                 FreeRTOS_printf( ( "TCP %5d %-16lxip:%5d %d/%d %-13.13s %6lu %6u%s\n",\r
3369                                         pxSocket->usLocalPort,          /* Local port on this machine */\r
3370                                         pxSocket->u.xTCP.ulRemoteIP,    /* IP address of remote machine */\r
3371                                         pxSocket->u.xTCP.usRemotePort,  /* Port on remote machine */\r
3372                                         pxSocket->u.xTCP.rxStream != NULL,\r
3373                                         pxSocket->u.xTCP.txStream != NULL,\r
3374                                         FreeRTOS_GetTCPStateName( pxSocket->u.xTCP.ucTCPState ),\r
3375                                         (age > 999999 ? 999999 : age), /* Format 'age' for printing */\r
3376                                         pxSocket->u.xTCP.usTimeout,\r
3377                                         ucChildText ) );\r
3378                                         /* Remove compiler warnings if FreeRTOS_debug_printf() is not defined. */\r
3379                                         ( void ) pxHandleReceive;\r
3380                                 count++;\r
3381                         }\r
3382 \r
3383                         for( pxIterator  = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundUDPSocketsList );\r
3384                                  pxIterator != ( ListItem_t * ) listGET_END_MARKER( &xBoundUDPSocketsList );\r
3385                                  pxIterator  = ( ListItem_t * ) listGET_NEXT( pxIterator ) )\r
3386                         {\r
3387                                 /* Local port on this machine */\r
3388                                 FreeRTOS_printf( ( "UDP Port %5u\n",\r
3389                                         FreeRTOS_ntohs( listGET_LIST_ITEM_VALUE( pxIterator ) ) ) );\r
3390                                 count++;\r
3391                         }\r
3392 \r
3393                         FreeRTOS_printf( ( "FreeRTOS_netstat: %lu sockets %lu < %lu < %d buffers free\n",\r
3394                                 count,\r
3395                                 uxGetMinimumFreeNetworkBuffers( ),\r
3396                                 uxGetNumberOfFreeNetworkBuffers( ),\r
3397                                 ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ) );\r
3398                 }\r
3399         }\r
3400 \r
3401 #endif /* ( ( ipconfigHAS_PRINTF != 0 ) && ( ipconfigUSE_TCP == 1 ) ) */\r
3402 /*-----------------------------------------------------------*/\r
3403 \r
3404 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
3405 \r
3406         void vSocketSelect( SocketSelect_t *pxSocketSet )\r
3407         {\r
3408         BaseType_t xRound;\r
3409         EventBits_t xSocketBits, xBitsToClear;\r
3410         #if ipconfigUSE_TCP == 1\r
3411                 BaseType_t xLastRound = 1;\r
3412         #else\r
3413                 BaseType_t xLastRound = 0;\r
3414         #endif\r
3415 \r
3416                 /* These flags will be switched on after checking the socket status. */\r
3417                 EventBits_t xGroupBits = 0;\r
3418                 pxSocketSet->pxSocket = NULL;\r
3419 \r
3420                 for( xRound = 0; xRound <= xLastRound; xRound++ )\r
3421                 {\r
3422                         const ListItem_t *pxIterator;\r
3423                         const MiniListItem_t *pxEnd;\r
3424                         if( xRound == 0 )\r
3425                         {\r
3426                                 pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundUDPSocketsList );\r
3427                         }\r
3428                 #if ipconfigUSE_TCP == 1\r
3429                         else\r
3430                         {\r
3431                                 pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );\r
3432                         }\r
3433                 #endif /* ipconfigUSE_TCP == 1 */\r
3434                         for( pxIterator = ( const ListItem_t * ) ( listGET_NEXT( pxEnd ) );\r
3435                                  pxIterator != ( const ListItem_t * ) pxEnd;\r
3436                                  pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )\r
3437                         {\r
3438                                 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );\r
3439                                 if( pxSocket->pxSocketSet != pxSocketSet )\r
3440                                 {\r
3441                                         /* Socket does not belong to this select group. */\r
3442                                         continue;\r
3443                                 }\r
3444                                 xSocketBits = 0;\r
3445 \r
3446                                 #if( ipconfigUSE_TCP == 1 )\r
3447                                         if( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP )\r
3448                                         {\r
3449                                                 /* Check if the socket has already been accepted by the\r
3450                                                 owner.  If not, it is useless to return it from a\r
3451                                                 select(). */\r
3452                                                 BaseType_t bAccepted = pdFALSE;\r
3453 \r
3454                                                 if( pxSocket->u.xTCP.bits.bPassQueued == pdFALSE_UNSIGNED )\r
3455                                                 {\r
3456                                                         if( pxSocket->u.xTCP.bits.bPassAccept == pdFALSE_UNSIGNED )\r
3457                                                         {\r
3458                                                                 bAccepted = pdTRUE;\r
3459                                                         }\r
3460                                                 }\r
3461 \r
3462                                                 /* Is the set owner interested in READ events? */\r
3463                                                 if( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 )\r
3464                                                 {\r
3465                                                         if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN )\r
3466                                                         {\r
3467                                                                 if( ( pxSocket->u.xTCP.pxPeerSocket != NULL ) && ( pxSocket->u.xTCP.pxPeerSocket->u.xTCP.bits.bPassAccept != 0 ) )\r
3468                                                                 {\r
3469                                                                         xSocketBits |= eSELECT_READ;\r
3470                                                                 }\r
3471                                                         }\r
3472                                                         else if( ( pxSocket->u.xTCP.bits.bReuseSocket != pdFALSE_UNSIGNED ) && ( pxSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED ) )\r
3473                                                         {\r
3474                                                                 /* This socket has the re-use flag. After connecting it turns into\r
3475                                                                 aconnected socket. Set the READ event, so that accept() will be called. */\r
3476                                                                 xSocketBits |= eSELECT_READ;\r
3477                                                         }\r
3478                                                         else if( ( bAccepted != 0 ) && ( FreeRTOS_recvcount( pxSocket ) > 0 ) )\r
3479                                                         {\r
3480                                                                 xSocketBits |= eSELECT_READ;\r
3481                                                         }\r
3482                                                 }\r
3483                                                 /* Is the set owner interested in EXCEPTION events? */\r
3484                                                 if( ( pxSocket->xSelectBits & eSELECT_EXCEPT ) != 0 )\r
3485                                                 {\r
3486                                                         if( ( pxSocket->u.xTCP.ucTCPState == eCLOSE_WAIT ) || ( pxSocket->u.xTCP.ucTCPState == eCLOSED ) )\r
3487                                                         {\r
3488                                                                 xSocketBits |= eSELECT_EXCEPT;\r
3489                                                         }\r
3490                                                 }\r
3491 \r
3492                                                 /* Is the set owner interested in WRITE events? */\r
3493                                                 if( ( pxSocket->xSelectBits & eSELECT_WRITE ) != 0 )\r
3494                                                 {\r
3495                                                         BaseType_t bMatch = pdFALSE;\r
3496 \r
3497                                                         if( bAccepted != 0 )\r
3498                                                         {\r
3499                                                                 if( FreeRTOS_tx_space( pxSocket ) > 0 )\r
3500                                                                 {\r
3501                                                                         bMatch = pdTRUE;\r
3502                                                                 }\r
3503                                                         }\r
3504 \r
3505                                                         if( bMatch == pdFALSE )\r
3506                                                         {\r
3507                                                                 if( ( pxSocket->u.xTCP.bits.bConnPrepared != pdFALSE_UNSIGNED ) &&\r
3508                                                                         ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) &&\r
3509                                                                         ( pxSocket->u.xTCP.bits.bConnPassed == pdFALSE_UNSIGNED ) )\r
3510                                                                 {\r
3511                                                                         pxSocket->u.xTCP.bits.bConnPassed = pdTRUE_UNSIGNED;\r
3512                                                                         bMatch = pdTRUE;\r
3513                                                                 }\r
3514                                                         }\r
3515 \r
3516                                                         if( bMatch != pdFALSE )\r
3517                                                         {\r
3518                                                                 xSocketBits |= eSELECT_WRITE;\r
3519                                                         }\r
3520                                                 }\r
3521                                         }\r
3522                                         else\r
3523                                 #endif /* ipconfigUSE_TCP == 1 */\r
3524                                 {\r
3525                                         /* Select events for UDP are simpler. */\r
3526                                         if( ( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 ) &&\r
3527                                                 ( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) > 0U ) )\r
3528                                         {\r
3529                                                 xSocketBits |= eSELECT_READ;\r
3530                                         }\r
3531                                         /* The WRITE and EXCEPT bits are not used for UDP */\r
3532                                 }       /* if( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP ) */\r
3533 \r
3534                                 /* Each socket keeps its own event flags, which are looked-up\r
3535                                 by FreeRTOS_FD_ISSSET() */\r
3536                                 pxSocket->xSocketBits = xSocketBits;\r
3537 \r
3538                                 /* The ORed value will be used to set the bits in the event\r
3539                                 group. */\r
3540                                 xGroupBits |= xSocketBits;\r
3541 \r
3542                         }       /* for( pxIterator ... ) */\r
3543                 }       /* for( xRound = 0; xRound <= xLastRound; xRound++ ) */\r
3544 \r
3545                 xBitsToClear = xEventGroupGetBits( pxSocketSet->xSelectGroup );\r
3546 \r
3547                 /* Now set the necessary bits. */\r
3548                 xBitsToClear = ( xBitsToClear & ~xGroupBits ) & eSELECT_ALL;\r
3549 \r
3550                 #if( ipconfigSUPPORT_SIGNALS != 0 )\r
3551                 {\r
3552                         /* Maybe the socketset was signalled, but don't\r
3553                         clear the 'eSELECT_INTR' bit here, as it will be used\r
3554                         and cleared in FreeRTOS_select(). */\r
3555                         xBitsToClear &= ( EventBits_t ) ~eSELECT_INTR;\r
3556                 }\r
3557                 #endif /* ipconfigSUPPORT_SIGNALS */\r
3558 \r
3559                 if( xBitsToClear != 0 )\r
3560                 {\r
3561                         xEventGroupClearBits( pxSocketSet->xSelectGroup, xBitsToClear );\r
3562                 }\r
3563 \r
3564                 /* Now include eSELECT_CALL_IP to wakeup the caller. */\r
3565                 xEventGroupSetBits( pxSocketSet->xSelectGroup, xGroupBits | eSELECT_CALL_IP );\r
3566         }\r
3567 \r
3568 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */\r
3569 /*-----------------------------------------------------------*/\r
3570 \r
3571 #if( ipconfigSUPPORT_SIGNALS != 0 )\r
3572 \r
3573         /* Send a signal to the task which reads from this socket. */\r
3574         BaseType_t FreeRTOS_SignalSocket( Socket_t xSocket )\r
3575         {\r
3576         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
3577         BaseType_t xReturn;\r
3578 \r
3579                 if( pxSocket == NULL )\r
3580                 {\r
3581                         xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
3582                 }\r
3583                 else\r
3584         #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
3585                 if( ( pxSocket->pxSocketSet != NULL ) && ( pxSocket->pxSocketSet->xSelectGroup != NULL ) )\r
3586                 {\r
3587                         xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, eSELECT_INTR );\r
3588                         xReturn = 0;\r
3589                 }\r
3590                 else\r
3591         #endif /* ipconfigSUPPORT_SELECT_FUNCTION */\r
3592                 if( pxSocket->xEventGroup != NULL )\r
3593                 {\r
3594                         xEventGroupSetBits( pxSocket->xEventGroup, eSOCKET_INTR );\r
3595                         xReturn = 0;\r
3596                 }\r
3597                 else\r
3598                 {\r
3599                         xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
3600                 }\r
3601 \r
3602                 return xReturn;\r
3603         }\r
3604 \r
3605 #endif /* ipconfigSUPPORT_SIGNALS */\r
3606 /*-----------------------------------------------------------*/\r
3607 \r
3608 #if( ipconfigSUPPORT_SIGNALS != 0 )\r
3609 \r
3610         /* Send a signal to the task which reads from this socket (FromISR version). */\r
3611         BaseType_t FreeRTOS_SignalSocketFromISR( Socket_t xSocket, BaseType_t *pxHigherPriorityTaskWoken )\r
3612         {\r
3613         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
3614         BaseType_t xReturn;\r
3615         IPStackEvent_t xEvent;\r
3616         extern QueueHandle_t xNetworkEventQueue;\r
3617 \r
3618                 configASSERT( pxSocket != NULL );\r
3619                 configASSERT( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP );\r
3620                 configASSERT( pxSocket->xEventGroup );\r
3621 \r
3622                 xEvent.eEventType = eSocketSignalEvent;\r
3623                 xEvent.pvData = ( void * )pxSocket;\r
3624 \r
3625                 /* The IP-task will call FreeRTOS_SignalSocket for this socket. */\r
3626                 xReturn = xQueueSendToBackFromISR( xNetworkEventQueue, &xEvent, pxHigherPriorityTaskWoken );\r
3627 \r
3628                 return xReturn;\r
3629         }\r
3630 \r
3631 #endif /* ipconfigSUPPORT_SIGNALS */\r
3632 /*-----------------------------------------------------------*/\r