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