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