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