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