]> git.sur5r.net Git - freertos/blob - FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/FreeRTOS_Sockets.c
Add the Labs projects provided in the V10.2.1_191129 zip file.
[freertos] / FreeRTOS-Labs / Source / FreeRTOS-Plus-TCP / FreeRTOS_Sockets.c
1 /*\r
2  * FreeRTOS+TCP 191100 experimental\r
3  * Copyright (C) 2018 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 ) || ( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK_WITH_CONTEXT != 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                         #if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK_WITH_CONTEXT != 0 )\r
1437                                 case FREERTOS_SO_WAKE_CALLBACK_CONTEXT:\r
1438                                 {\r
1439                                         /* Each socket wake callback may be passed a user context. */\r
1440                                         pxSocket->pvUserWakeCallbackContext = ( void * ) pvOptionValue;\r
1441                                         xReturn = 0;\r
1442                                 }\r
1443                                 break;\r
1444                         #endif /* ipconfigSOCKET_HAS_USER_WAKE_CALLBACK_WITH_CONTEXT */\r
1445 \r
1446                         case FREERTOS_SO_SET_LOW_HIGH_WATER:\r
1447                                 {\r
1448                                 LowHighWater_t *pxLowHighWater = ( LowHighWater_t * ) pvOptionValue;\r
1449 \r
1450                                         if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
1451                                         {\r
1452                                                 /* It is not allowed to access 'pxSocket->u.xTCP'. */\r
1453                                                 FreeRTOS_debug_printf( ( "FREERTOS_SO_SET_LOW_HIGH_WATER: wrong socket type\n" ) );\r
1454                                                 break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
1455                                         }\r
1456                                         if( ( pxLowHighWater->uxLittleSpace >= pxLowHighWater->uxEnoughSpace ) ||\r
1457                                                 ( pxLowHighWater->uxEnoughSpace > pxSocket->u.xTCP.uxRxStreamSize ) )\r
1458                                         {\r
1459                                                 /* Impossible values. */\r
1460                                                 FreeRTOS_debug_printf( ( "FREERTOS_SO_SET_LOW_HIGH_WATER: bad values\n" ) );\r
1461                                                 break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
1462                                         }\r
1463                                         /* Send a STOP when buffer space drops below 'uxLittleSpace' bytes. */\r
1464                                         pxSocket->u.xTCP.uxLittleSpace = pxLowHighWater->uxLittleSpace;\r
1465                                         /* Send a GO when buffer space grows above 'uxEnoughSpace' bytes. */\r
1466                                         pxSocket->u.xTCP.uxEnoughSpace = pxLowHighWater->uxEnoughSpace;\r
1467                                         xReturn = 0;\r
1468                                 }\r
1469                                 break;\r
1470 \r
1471                         case FREERTOS_SO_SNDBUF:        /* Set the size of the send buffer, in units of MSS (TCP only) */\r
1472                         case FREERTOS_SO_RCVBUF:        /* Set the size of the receive buffer, in units of MSS (TCP only) */\r
1473                                 {\r
1474                                         uint32_t ulNewValue;\r
1475 \r
1476                                         if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
1477                                         {\r
1478                                                 FreeRTOS_debug_printf( ( "Set SO_%sBUF: wrong socket type\n",\r
1479                                                         ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );\r
1480                                                 break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
1481                                         }\r
1482 \r
1483                                         if( ( ( lOptionName == FREERTOS_SO_SNDBUF ) && ( pxSocket->u.xTCP.txStream != NULL ) ) ||\r
1484                                                 ( ( lOptionName == FREERTOS_SO_RCVBUF ) && ( pxSocket->u.xTCP.rxStream != NULL ) ) )\r
1485                                         {\r
1486                                                 FreeRTOS_debug_printf( ( "Set SO_%sBUF: buffer already created\n",\r
1487                                                         ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );\r
1488                                                 break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
1489                                         }\r
1490 \r
1491                                         ulNewValue = *( ( uint32_t * ) pvOptionValue );\r
1492 \r
1493                                         if( lOptionName == FREERTOS_SO_SNDBUF )\r
1494                                         {\r
1495                                                 /* Round up to nearest MSS size */\r
1496                                                 ulNewValue = FreeRTOS_round_up( ulNewValue, ( uint32_t ) pxSocket->u.xTCP.usInitMSS );\r
1497                                                 pxSocket->u.xTCP.uxTxStreamSize = ulNewValue;\r
1498                                         }\r
1499                                         else\r
1500                                         {\r
1501                                                 pxSocket->u.xTCP.uxRxStreamSize = ulNewValue;\r
1502                                         }\r
1503                                 }\r
1504                                 xReturn = 0;\r
1505                                 break;\r
1506 \r
1507                         case FREERTOS_SO_WIN_PROPERTIES:        /* Set all buffer and window properties in one call, parameter is pointer to WinProperties_t */\r
1508                                 {\r
1509                                         WinProperties_t* pxProps;\r
1510 \r
1511                                         if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
1512                                         {\r
1513                                                 FreeRTOS_debug_printf( ( "Set SO_WIN_PROP: wrong socket type\n" ) );\r
1514                                                 break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
1515                                         }\r
1516 \r
1517                                         if( ( pxSocket->u.xTCP.txStream != NULL ) || ( pxSocket->u.xTCP.rxStream != NULL ) )\r
1518                                         {\r
1519                                                 FreeRTOS_debug_printf( ( "Set SO_WIN_PROP: buffer already created\n" ) );\r
1520                                                 break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
1521                                         }\r
1522 \r
1523                                         pxProps = ( ( WinProperties_t * ) pvOptionValue );\r
1524 \r
1525                                         if ( FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDBUF, &( pxProps->lTxBufSize ), sizeof( pxProps->lTxBufSize ) ) != 0 )\r
1526                                         {\r
1527                                                 break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
1528                                         }\r
1529 \r
1530                                         if ( FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVBUF, &( pxProps->lRxBufSize ), sizeof( pxProps->lRxBufSize ) ) != 0 )\r
1531                                         {\r
1532                                                 break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
1533                                         }\r
1534 \r
1535                                         #if( ipconfigUSE_TCP_WIN == 1 )\r
1536                                         {\r
1537                                                 pxSocket->u.xTCP.uxRxWinSize = ( uint32_t )pxProps->lRxWinSize; /* Fixed value: size of the TCP reception window */\r
1538                                                 pxSocket->u.xTCP.uxTxWinSize = ( uint32_t )pxProps->lTxWinSize; /* Fixed value: size of the TCP transmit window */\r
1539                                         }\r
1540                                         #else\r
1541                                         {\r
1542                                                 pxSocket->u.xTCP.uxRxWinSize = 1u;\r
1543                                                 pxSocket->u.xTCP.uxTxWinSize = 1u;\r
1544                                         }\r
1545                                         #endif\r
1546 \r
1547                                         /* In case the socket has already initialised its tcpWin,\r
1548                                         adapt the window size parameters */\r
1549                                         if( pxSocket->u.xTCP.xTCPWindow.u.bits.bHasInit != pdFALSE_UNSIGNED )\r
1550                                         {\r
1551                                                 pxSocket->u.xTCP.xTCPWindow.xSize.ulRxWindowLength = pxSocket->u.xTCP.uxRxWinSize * pxSocket->u.xTCP.usInitMSS;\r
1552                                                 pxSocket->u.xTCP.xTCPWindow.xSize.ulTxWindowLength = pxSocket->u.xTCP.uxTxWinSize * pxSocket->u.xTCP.usInitMSS;\r
1553                                         }\r
1554                                 }\r
1555 \r
1556                                 xReturn = 0;\r
1557                                 break;\r
1558 \r
1559                         case FREERTOS_SO_REUSE_LISTEN_SOCKET:   /* If true, the server-socket will turn into a connected socket */\r
1560                                 {\r
1561                                         if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
1562                                         {\r
1563                                                 break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
1564                                         }\r
1565                                         if( *( ( BaseType_t * ) pvOptionValue ) != 0 )\r
1566                                         {\r
1567                                                 pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE_UNSIGNED;\r
1568                                         }\r
1569                                         else\r
1570                                         {\r
1571                                                 pxSocket->u.xTCP.bits.bReuseSocket = pdFALSE_UNSIGNED;\r
1572                                         }\r
1573                                 }\r
1574                                 xReturn = 0;\r
1575                                 break;\r
1576 \r
1577                         case FREERTOS_SO_CLOSE_AFTER_SEND:              /* As soon as the last byte has been transmitted, finalise the connection */\r
1578                                 {\r
1579                                         if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
1580                                         {\r
1581                                                 break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
1582                                         }\r
1583 \r
1584                                         if( *( ( BaseType_t * ) pvOptionValue ) != 0 )\r
1585                                         {\r
1586                                                 pxSocket->u.xTCP.bits.bCloseAfterSend = pdTRUE_UNSIGNED;\r
1587                                         }\r
1588                                         else\r
1589                                         {\r
1590                                                 pxSocket->u.xTCP.bits.bCloseAfterSend = pdFALSE_UNSIGNED;\r
1591                                         }\r
1592                                 }\r
1593                                 xReturn = 0;\r
1594                                 break;\r
1595 \r
1596                         case FREERTOS_SO_SET_FULL_SIZE:         /* Refuse to send packets smaller than MSS  */\r
1597                                 {\r
1598                                         if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
1599                                         {\r
1600                                                 break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
1601                                         }\r
1602 \r
1603                                         if( *( ( BaseType_t * ) pvOptionValue ) != 0 )\r
1604                                         {\r
1605                                                 pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdTRUE_UNSIGNED;\r
1606                                         }\r
1607                                         else\r
1608                                         {\r
1609                                                 pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdFALSE_UNSIGNED;\r
1610                                         }\r
1611 \r
1612                                         if( ( pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize == pdFALSE_UNSIGNED ) &&\r
1613                                                 ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) &&\r
1614                                                 ( FreeRTOS_outstanding( pxSocket ) != 0 ) )\r
1615                                         {\r
1616                                                 pxSocket->u.xTCP.usTimeout = 1u; /* to set/clear bSendFullSize */\r
1617                                                 xSendEventToIPTask( eTCPTimerEvent );\r
1618                                         }\r
1619                                 }\r
1620                                 xReturn = 0;\r
1621                                 break;\r
1622 \r
1623                         case FREERTOS_SO_STOP_RX:               /* Refuse to receive more packts */\r
1624                                 {\r
1625                                         if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
1626                                         {\r
1627                                                 break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
1628                                         }\r
1629 \r
1630                                         if( *( ( BaseType_t * ) pvOptionValue ) != 0 )\r
1631                                         {\r
1632                                                 pxSocket->u.xTCP.bits.bRxStopped = pdTRUE_UNSIGNED;\r
1633                                         }\r
1634                                         else\r
1635                                         {\r
1636                                                 pxSocket->u.xTCP.bits.bRxStopped = pdFALSE_UNSIGNED;\r
1637                                         }\r
1638 \r
1639                                         pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;\r
1640                                         pxSocket->u.xTCP.usTimeout = 1u; /* to set/clear bRxStopped */\r
1641                                         xSendEventToIPTask( eTCPTimerEvent );\r
1642                                 }\r
1643                                 xReturn = 0;\r
1644                                 break;\r
1645 \r
1646                 #endif  /* ipconfigUSE_TCP == 1 */\r
1647 \r
1648                 default :\r
1649                         /* No other options are handled. */\r
1650                         xReturn = -pdFREERTOS_ERRNO_ENOPROTOOPT;\r
1651                         break;\r
1652         }\r
1653 \r
1654         return xReturn;\r
1655 } /* Tested */\r
1656 \r
1657 /*-----------------------------------------------------------*/\r
1658 \r
1659 /* Find an available port number per https://tools.ietf.org/html/rfc6056. */\r
1660 static uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol )\r
1661 {\r
1662 const uint16_t usEphemeralPortCount =\r
1663         socketAUTO_PORT_ALLOCATION_MAX_NUMBER - socketAUTO_PORT_ALLOCATION_START_NUMBER + 1;\r
1664 uint16_t usIterations = usEphemeralPortCount;\r
1665 uint32_t ulRandomSeed = 0;\r
1666 uint16_t usResult = 0;\r
1667 BaseType_t xGotZeroOnce = pdFALSE;\r
1668 const List_t *pxList;\r
1669 \r
1670 #if ipconfigUSE_TCP == 1\r
1671         if( xProtocol == ( BaseType_t ) FREERTOS_IPPROTO_TCP )\r
1672         {\r
1673                 pxList = &xBoundTCPSocketsList;\r
1674         }\r
1675         else\r
1676 #endif\r
1677         {\r
1678                 pxList = &xBoundUDPSocketsList;\r
1679         }\r
1680 \r
1681         /* Avoid compiler warnings if ipconfigUSE_TCP is not defined. */\r
1682         ( void ) xProtocol;\r
1683 \r
1684         /* Find the next available port using the random seed as a starting\r
1685         point. */\r
1686         do\r
1687         {\r
1688                 /* Generate a random seed. */\r
1689                 ulRandomSeed = ipconfigRAND32( );\r
1690 \r
1691                 /* Only proceed if the random number generator succeeded. */\r
1692                 if( 0 == ulRandomSeed )\r
1693                 {\r
1694                         if( pdFALSE == xGotZeroOnce )\r
1695                         {\r
1696                                 xGotZeroOnce = pdTRUE;\r
1697                                 continue;\r
1698                         }\r
1699                         else\r
1700                         {\r
1701                                 break;\r
1702                         }\r
1703                 }\r
1704 \r
1705                 /* Map the random to a candidate port. */\r
1706                 usResult =\r
1707                         socketAUTO_PORT_ALLOCATION_START_NUMBER +\r
1708                         ( ( ( uint16_t )ulRandomSeed ) % usEphemeralPortCount );\r
1709 \r
1710                 /* Check if there's already an open socket with the same protocol\r
1711                 and port. */\r
1712                 if( NULL == pxListFindListItemWithValue(\r
1713                         pxList,\r
1714                         ( TickType_t )FreeRTOS_htons( usResult ) ) )\r
1715                 {\r
1716                         usResult = FreeRTOS_htons( usResult );\r
1717                         break;\r
1718                 }\r
1719                 else\r
1720                 {\r
1721                         usResult = 0;\r
1722                 }\r
1723 \r
1724                 usIterations--;\r
1725         }\r
1726         while( usIterations > 0 );\r
1727 \r
1728         return usResult;\r
1729 }\r
1730 /*-----------------------------------------------------------*/\r
1731 \r
1732 /* pxListFindListItemWithValue: find a list item in a bound socket list\r
1733 'xWantedItemValue' refers to a port number */\r
1734 static const ListItem_t * pxListFindListItemWithValue( const List_t *pxList, TickType_t xWantedItemValue )\r
1735 {\r
1736 const ListItem_t * pxResult = NULL;\r
1737 \r
1738         if( ( xIPIsNetworkTaskReady() != pdFALSE ) && ( pxList != NULL ) )\r
1739         {\r
1740                 const ListItem_t *pxIterator;\r
1741                 const MiniListItem_t *pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( pxList );\r
1742                 for( pxIterator  = ( const ListItem_t * ) listGET_NEXT( pxEnd );\r
1743                          pxIterator != ( const ListItem_t * ) pxEnd;\r
1744                          pxIterator  = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )\r
1745                 {\r
1746                         if( listGET_LIST_ITEM_VALUE( pxIterator ) == xWantedItemValue )\r
1747                         {\r
1748                                 pxResult = pxIterator;\r
1749                                 break;\r
1750                         }\r
1751                 }\r
1752         }\r
1753 \r
1754         return pxResult;\r
1755 } /* Tested */\r
1756 \r
1757 /*-----------------------------------------------------------*/\r
1758 \r
1759 FreeRTOS_Socket_t *pxUDPSocketLookup( UBaseType_t uxLocalPort )\r
1760 {\r
1761 const ListItem_t *pxListItem;\r
1762 FreeRTOS_Socket_t *pxSocket = NULL;\r
1763 \r
1764         /* Looking up a socket is quite simple, find a match with the local port.\r
1765 \r
1766         See if there is a list item associated with the port number on the\r
1767         list of bound sockets. */\r
1768         pxListItem = pxListFindListItemWithValue( &xBoundUDPSocketsList, ( TickType_t ) uxLocalPort );\r
1769 \r
1770         if( pxListItem != NULL )\r
1771         {\r
1772                 /* The owner of the list item is the socket itself. */\r
1773                 pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxListItem );\r
1774                 configASSERT( pxSocket != NULL );\r
1775         }\r
1776         return pxSocket;\r
1777 }\r
1778 \r
1779 /*-----------------------------------------------------------*/\r
1780 \r
1781 #if ipconfigINCLUDE_FULL_INET_ADDR == 1\r
1782 \r
1783         uint32_t FreeRTOS_inet_addr( const char * pcIPAddress )\r
1784         {\r
1785         const uint32_t ulDecimalBase = 10u;\r
1786         uint8_t ucOctet[ socketMAX_IP_ADDRESS_OCTETS ];\r
1787         const char *pcPointerOnEntering;\r
1788         uint32_t ulReturn = 0UL, ulValue;\r
1789         UBaseType_t uxOctetNumber;\r
1790         BaseType_t xResult = pdPASS;\r
1791 \r
1792                 for( uxOctetNumber = 0u; uxOctetNumber < socketMAX_IP_ADDRESS_OCTETS; uxOctetNumber++ )\r
1793                 {\r
1794                         ulValue = 0ul;\r
1795                         pcPointerOnEntering = pcIPAddress;\r
1796 \r
1797                         while( ( *pcIPAddress >= '0' ) && ( *pcIPAddress <= '9' ) )\r
1798                         {\r
1799                                 /* Move previous read characters into the next decimal\r
1800                                 position. */\r
1801                                 ulValue *= ulDecimalBase;\r
1802 \r
1803                                 /* Add the binary value of the ascii character. */\r
1804                                 ulValue += ( ( uint32_t ) ( *pcIPAddress ) - ( uint32_t ) '0' );\r
1805 \r
1806                                 /* Move to next character in the string. */\r
1807                                 pcIPAddress++;\r
1808                         }\r
1809 \r
1810                         /* Check characters were read. */\r
1811                         if( pcIPAddress == pcPointerOnEntering )\r
1812                         {\r
1813                                 xResult = pdFAIL;\r
1814                         }\r
1815 \r
1816                         /* Check the value fits in an 8-bit number. */\r
1817                         if( ulValue > 0xffUL )\r
1818                         {\r
1819                                 xResult = pdFAIL;\r
1820                         }\r
1821                         else\r
1822                         {\r
1823                                 ucOctet[ uxOctetNumber ] = ( uint8_t ) ulValue;\r
1824 \r
1825                                 /* Check the next character is as expected. */\r
1826                                 if( uxOctetNumber < ( socketMAX_IP_ADDRESS_OCTETS - 1u ) )\r
1827                                 {\r
1828                                         if( *pcIPAddress != '.' )\r
1829                                         {\r
1830                                                 xResult = pdFAIL;\r
1831                                         }\r
1832                                         else\r
1833                                         {\r
1834                                                 /* Move past the dot. */\r
1835                                                 pcIPAddress++;\r
1836                                         }\r
1837                                 }\r
1838                         }\r
1839 \r
1840                         if( xResult == pdFAIL )\r
1841                         {\r
1842                                 /* No point going on. */\r
1843                                 break;\r
1844                         }\r
1845                 }\r
1846 \r
1847                 if( *pcIPAddress != ( char ) 0 )\r
1848                 {\r
1849                         /* Expected the end of the string. */\r
1850                         xResult = pdFAIL;\r
1851                 }\r
1852 \r
1853                 if( uxOctetNumber != socketMAX_IP_ADDRESS_OCTETS )\r
1854                 {\r
1855                         /* Didn't read enough octets. */\r
1856                         xResult = pdFAIL;\r
1857                 }\r
1858 \r
1859                 if( xResult == pdPASS )\r
1860                 {\r
1861                         ulReturn = FreeRTOS_inet_addr_quick( ucOctet[ 0 ], ucOctet[ 1 ], ucOctet[ 2 ], ucOctet[ 3 ] );\r
1862                 }\r
1863 \r
1864                 return ulReturn;\r
1865         }\r
1866 \r
1867 #endif /* ipconfigINCLUDE_FULL_INET_ADDR */\r
1868 \r
1869 /*-----------------------------------------------------------*/\r
1870 \r
1871 /* Function to get the local address and IP port */\r
1872 size_t FreeRTOS_GetLocalAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress )\r
1873 {\r
1874 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
1875 \r
1876         /* IP address of local machine. */\r
1877         pxAddress->sin_addr = *ipLOCAL_IP_ADDRESS_POINTER;\r
1878 \r
1879         /* Local port on this machine. */\r
1880         pxAddress->sin_port = FreeRTOS_htons( pxSocket->usLocalPort );\r
1881 \r
1882         return sizeof( *pxAddress );\r
1883 }\r
1884 \r
1885 /*-----------------------------------------------------------*/\r
1886 \r
1887 void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )\r
1888 {\r
1889 /* _HT_ must work this out, now vSocketWakeUpUser will be called for any important\r
1890  * event or transition */\r
1891         #if( ipconfigSOCKET_HAS_USER_SEMAPHORE == 1 )\r
1892         {\r
1893                 if( pxSocket->pxUserSemaphore != NULL )\r
1894                 {\r
1895                         xSemaphoreGive( pxSocket->pxUserSemaphore );\r
1896                 }\r
1897         }\r
1898         #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */\r
1899 \r
1900         #if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK == 1 )\r
1901         {\r
1902                 if( pxSocket->pxUserWakeCallback != NULL )\r
1903                 {\r
1904                         pxSocket->pxUserWakeCallback( pxSocket );\r
1905                 }\r
1906         }\r
1907         #endif /* ipconfigSOCKET_HAS_USER_WAKE_CALLBACK */\r
1908 \r
1909         #if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK_WITH_CONTEXT == 1 )\r
1910         {\r
1911                 if( pxSocket->pxUserWakeCallback != NULL )\r
1912                 {\r
1913                         pxSocket->pxUserWakeCallback( pxSocket, pxSocket->pvUserWakeCallbackContext );\r
1914                 }\r
1915         }\r
1916         #endif /* ipconfigSOCKET_HAS_USER_WAKE_CALLBACK_WITH_CONTEXT */\r
1917 \r
1918         #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
1919         {\r
1920                 if( pxSocket->pxSocketSet != NULL )\r
1921                 {\r
1922                         EventBits_t xSelectBits = ( pxSocket->xEventBits >> SOCKET_EVENT_BIT_COUNT ) & eSELECT_ALL;\r
1923                         if( xSelectBits != 0ul )\r
1924                         {\r
1925                                 pxSocket->xSocketBits |= xSelectBits;\r
1926                                 xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, xSelectBits );\r
1927                         }\r
1928                 }\r
1929 \r
1930                 pxSocket->xEventBits &= eSOCKET_ALL;\r
1931         }\r
1932         #endif /* ipconfigSUPPORT_SELECT_FUNCTION */\r
1933 \r
1934         if( ( pxSocket->xEventGroup != NULL ) && ( pxSocket->xEventBits != 0u ) )\r
1935         {\r
1936                 xEventGroupSetBits( pxSocket->xEventGroup, pxSocket->xEventBits );\r
1937         }\r
1938 \r
1939         pxSocket->xEventBits = 0ul;\r
1940 }\r
1941 \r
1942 /*-----------------------------------------------------------*/\r
1943 \r
1944 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )\r
1945 \r
1946         /* This define makes it possible for network-card drivers to inspect\r
1947          * UDP message and see if there is any UDP socket bound to a given port\r
1948          * number.\r
1949          * This is probably only usefull in systems with a minimum of RAM and\r
1950          * when lots of anonymous broadcast messages come in\r
1951          */\r
1952         BaseType_t xPortHasUDPSocket( uint16_t usPortNr )\r
1953         {\r
1954         BaseType_t xFound = pdFALSE;\r
1955 \r
1956                 vTaskSuspendAll();\r
1957                 {\r
1958                         if( ( pxListFindListItemWithValue( &xBoundUDPSocketsList, ( TickType_t ) usPortNr ) != NULL ) )\r
1959                         {\r
1960                                 xFound = pdTRUE;\r
1961                         }\r
1962                 }\r
1963                 xTaskResumeAll();\r
1964 \r
1965                 return xFound;\r
1966         }\r
1967 \r
1968 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */\r
1969 \r
1970 /*-----------------------------------------------------------*/\r
1971 \r
1972 #if( ipconfigUSE_TCP == 1 )\r
1973 \r
1974         static BaseType_t bMayConnect( FreeRTOS_Socket_t *pxSocket );\r
1975         static BaseType_t bMayConnect( FreeRTOS_Socket_t *pxSocket )\r
1976         {\r
1977                 switch( pxSocket->u.xTCP.ucTCPState )\r
1978                 {\r
1979                         case eCLOSED:\r
1980                         case eCLOSE_WAIT:       return 0;\r
1981                         case eCONNECT_SYN:      return -pdFREERTOS_ERRNO_EINPROGRESS;\r
1982                         default:                        return -pdFREERTOS_ERRNO_EAGAIN;\r
1983                 }\r
1984         }\r
1985 \r
1986 #endif /* ipconfigUSE_TCP */\r
1987 /*-----------------------------------------------------------*/\r
1988 \r
1989 #if( ipconfigUSE_TCP == 1 )\r
1990 \r
1991         static BaseType_t prvTCPConnectStart( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr *pxAddress )\r
1992         {\r
1993         BaseType_t xResult = 0;\r
1994 \r
1995                 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdFALSE )\r
1996                 {\r
1997                         /* Not a valid socket or wrong type */\r
1998                         xResult = -pdFREERTOS_ERRNO_EBADF;\r
1999                 }\r
2000                 else if( FreeRTOS_issocketconnected( pxSocket ) > 0 )\r
2001                 {\r
2002                         /* The socket is already connected. */\r
2003                         xResult = -pdFREERTOS_ERRNO_EISCONN;\r
2004                 }\r
2005                 else if( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE )\r
2006                 {\r
2007                         /* Bind the socket to the port that the client task will send from.\r
2008                         Non-standard, so the error returned is that returned by bind(). */\r
2009                         xResult = FreeRTOS_bind( ( Socket_t ) pxSocket, NULL, 0u );\r
2010                 }\r
2011 \r
2012                 if( xResult == 0 )\r
2013                 {\r
2014                         /* Check if it makes any sense to wait for a connect event, this condition\r
2015                         might change while sleeping, so it must be checked within each loop */\r
2016                         xResult = bMayConnect( pxSocket ); /* -EINPROGRESS, -EAGAIN, or 0 for OK */\r
2017 \r
2018                         /* Start the connect procedure, kernel will start working on it */\r
2019                         if( xResult == 0 )\r
2020                         {\r
2021                                 pxSocket->u.xTCP.bits.bConnPrepared = pdFALSE_UNSIGNED;\r
2022                                 pxSocket->u.xTCP.ucRepCount = 0u;\r
2023 \r
2024                                 FreeRTOS_debug_printf( ( "FreeRTOS_connect: %u to %lxip:%u\n",\r
2025                                         pxSocket->usLocalPort, FreeRTOS_ntohl( pxAddress->sin_addr ), FreeRTOS_ntohs( pxAddress->sin_port ) ) );\r
2026 \r
2027                                 /* Port on remote machine. */\r
2028                                 pxSocket->u.xTCP.usRemotePort = FreeRTOS_ntohs( pxAddress->sin_port );\r
2029 \r
2030                                 /* IP address of remote machine. */\r
2031                                 pxSocket->u.xTCP.ulRemoteIP = FreeRTOS_ntohl( pxAddress->sin_addr );\r
2032 \r
2033                                 /* (client) internal state: socket wants to send a connect. */\r
2034                                 vTCPStateChange( pxSocket, eCONNECT_SYN );\r
2035 \r
2036                                 /* To start an active connect. */\r
2037                                 pxSocket->u.xTCP.usTimeout = 1u;\r
2038 \r
2039                                 if( xSendEventToIPTask( eTCPTimerEvent ) != pdPASS )\r
2040                                 {\r
2041                                         xResult = -pdFREERTOS_ERRNO_ECANCELED;\r
2042                                 }\r
2043                         }\r
2044                 }\r
2045 \r
2046                 return xResult;\r
2047         }\r
2048 \r
2049 #endif /* ipconfigUSE_TCP */\r
2050 /*-----------------------------------------------------------*/\r
2051 \r
2052 #if( ipconfigUSE_TCP == 1 )\r
2053 \r
2054         /*\r
2055          * FreeRTOS_connect: socket wants to connect to a remote port\r
2056          */\r
2057         BaseType_t FreeRTOS_connect( Socket_t xClientSocket, struct freertos_sockaddr *pxAddress, socklen_t xAddressLength )\r
2058         {\r
2059         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t* ) xClientSocket;\r
2060         TickType_t xRemainingTime;\r
2061         BaseType_t xTimed = pdFALSE;\r
2062         BaseType_t xResult;\r
2063         TimeOut_t xTimeOut;\r
2064 \r
2065                 ( void ) xAddressLength;\r
2066 \r
2067                 xResult = prvTCPConnectStart( pxSocket, pxAddress );\r
2068 \r
2069                 if( xResult == 0 )\r
2070                 {\r
2071                         /* And wait for the result */\r
2072                         for( ;; )\r
2073                         {\r
2074                                 if( xTimed == pdFALSE )\r
2075                                 {\r
2076                                         /* Only in the first round, check for non-blocking */\r
2077                                         xRemainingTime = pxSocket->xReceiveBlockTime;\r
2078                                         if( xRemainingTime == ( TickType_t )0 )\r
2079                                         {\r
2080                                                 /* Not yet connected, correct state, non-blocking. */\r
2081                                                 xResult = -pdFREERTOS_ERRNO_EWOULDBLOCK;\r
2082                                                 break;\r
2083                                         }\r
2084 \r
2085                                         /* Don't get here a second time. */\r
2086                                         xTimed = pdTRUE;\r
2087 \r
2088                                         /* Fetch the current time */\r
2089                                         vTaskSetTimeOutState( &xTimeOut );\r
2090                                 }\r
2091 \r
2092                                 /* Did it get connected while sleeping ? */\r
2093                                 xResult = FreeRTOS_issocketconnected( pxSocket );\r
2094 \r
2095                                 /* Returns positive when connected, negative means an error */\r
2096                                 if( xResult < 0 )\r
2097                                 {\r
2098                                         /* Return the error */\r
2099                                         break;\r
2100                                 }\r
2101 \r
2102                                 if( xResult > 0 )\r
2103                                 {\r
2104                                         /* Socket now connected, return a zero */\r
2105                                         xResult = 0;\r
2106                                         break;\r
2107                                 }\r
2108 \r
2109                                 /* Is it allowed to sleep more? */\r
2110                                 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) )\r
2111                                 {\r
2112                                         xResult = -pdFREERTOS_ERRNO_ETIMEDOUT;\r
2113                                         break;\r
2114                                 }\r
2115 \r
2116                                 /* Go sleeping until we get any down-stream event */\r
2117                                 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_CONNECT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );\r
2118                         }\r
2119                 }\r
2120 \r
2121                 return xResult;\r
2122         }\r
2123 #endif /* ipconfigUSE_TCP */\r
2124 /*-----------------------------------------------------------*/\r
2125 \r
2126 #if( ipconfigUSE_TCP == 1 )\r
2127 \r
2128         /*\r
2129          * FreeRTOS_accept: can return a new connected socket\r
2130          * if the server socket is in listen mode and receives a connection request\r
2131          * The new socket will be bound already to the same port number as the listing\r
2132          * socket.\r
2133          */\r
2134         Socket_t FreeRTOS_accept( Socket_t xServerSocket, struct freertos_sockaddr *pxAddress, socklen_t *pxAddressLength )\r
2135         {\r
2136         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xServerSocket;\r
2137         FreeRTOS_Socket_t *pxClientSocket = NULL;\r
2138         TickType_t xRemainingTime;\r
2139         BaseType_t xTimed = pdFALSE, xAsk = pdFALSE;\r
2140         TimeOut_t xTimeOut;\r
2141         IPStackEvent_t xAskEvent;\r
2142 \r
2143                 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )\r
2144                 {\r
2145                         /* Not a valid socket or wrong type */\r
2146                         pxClientSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;\r
2147                 }\r
2148                 else if( ( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED ) &&\r
2149                                  ( pxSocket->u.xTCP.ucTCPState != eTCP_LISTEN ) )\r
2150                 {\r
2151                         /* Parent socket is not in listening mode */\r
2152                         pxClientSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;\r
2153                 }\r
2154                 else\r
2155                 {\r
2156                         /* Loop will stop with breaks. */\r
2157                         for( ; ; )\r
2158                         {\r
2159                                 /* Is there a new client? */\r
2160                                 vTaskSuspendAll();\r
2161                                 {\r
2162                                         if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED )\r
2163                                         {\r
2164                                                 pxClientSocket = pxSocket->u.xTCP.pxPeerSocket;\r
2165                                         }\r
2166                                         else\r
2167                                         {\r
2168                                                 pxClientSocket = pxSocket;\r
2169                                         }\r
2170                                         if( pxClientSocket != NULL )\r
2171                                         {\r
2172                                                 pxSocket->u.xTCP.pxPeerSocket = NULL;\r
2173 \r
2174                                                 /* Is it still not taken ? */\r
2175                                                 if( pxClientSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED )\r
2176                                                 {\r
2177                                                         pxClientSocket->u.xTCP.bits.bPassAccept = pdFALSE_UNSIGNED;\r
2178                                                 }\r
2179                                                 else\r
2180                                                 {\r
2181                                                         pxClientSocket = NULL;\r
2182                                                 }\r
2183                                         }\r
2184                                 }\r
2185                                 xTaskResumeAll();\r
2186 \r
2187                                 if( pxClientSocket != NULL )\r
2188                                 {\r
2189                                         if( pxAddress != NULL )\r
2190                                         {\r
2191                                                 /* IP address of remote machine. */\r
2192                                                 pxAddress->sin_addr = FreeRTOS_ntohl( pxClientSocket->u.xTCP.ulRemoteIP );\r
2193 \r
2194                                                 /* Port on remote machine. */\r
2195                                                 pxAddress->sin_port = FreeRTOS_ntohs( pxClientSocket->u.xTCP.usRemotePort );\r
2196                                         }\r
2197                                         if( pxAddressLength != NULL )\r
2198                                         {\r
2199                                                 *pxAddressLength = sizeof( *pxAddress );\r
2200                                         }\r
2201 \r
2202                                         if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED )\r
2203                                         {\r
2204                                                 xAsk = pdTRUE;\r
2205                                         }\r
2206                                 }\r
2207 \r
2208                                 if( xAsk != pdFALSE )\r
2209                                 {\r
2210                                         /* Ask to set an event in 'xEventGroup' as soon as a new\r
2211                                         client gets connected for this listening socket. */\r
2212                                         xAskEvent.eEventType = eTCPAcceptEvent;\r
2213                                         xAskEvent.pvData = ( void * ) pxSocket;\r
2214                                         xSendEventStructToIPTask( &xAskEvent, portMAX_DELAY );\r
2215                                 }\r
2216 \r
2217                                 if( pxClientSocket != NULL )\r
2218                                 {\r
2219                                         break;\r
2220                                 }\r
2221 \r
2222                                 if( xTimed == pdFALSE )\r
2223                                 {\r
2224                                         /* Only in the first round, check for non-blocking */\r
2225                                         xRemainingTime = pxSocket->xReceiveBlockTime;\r
2226                                         if( xRemainingTime == ( TickType_t ) 0 )\r
2227                                         {\r
2228                                                 break;\r
2229                                         }\r
2230 \r
2231                                         /* Don't get here a second time */\r
2232                                         xTimed = pdTRUE;\r
2233 \r
2234                                         /* Fetch the current time */\r
2235                                         vTaskSetTimeOutState( &xTimeOut );\r
2236                                 }\r
2237 \r
2238                                 /* Has the timeout been reached? */\r
2239                                 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )\r
2240                                 {\r
2241                                         break;\r
2242                                 }\r
2243 \r
2244                                 /* Go sleeping until we get any down-stream event */\r
2245                                 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_ACCEPT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );\r
2246                         }\r
2247                 }\r
2248 \r
2249                 return ( Socket_t ) pxClientSocket;\r
2250         }\r
2251 #endif /* ipconfigUSE_TCP */\r
2252 /*-----------------------------------------------------------*/\r
2253 \r
2254 #if( ipconfigUSE_TCP == 1 )\r
2255 \r
2256         /*\r
2257          * Read incoming data from a TCP socket\r
2258          * Only after the last byte has been read, a close error might be returned\r
2259          */\r
2260         BaseType_t FreeRTOS_recv( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags )\r
2261         {\r
2262         BaseType_t xByteCount;\r
2263         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
2264         TickType_t xRemainingTime;\r
2265         BaseType_t xTimed = pdFALSE;\r
2266         TimeOut_t xTimeOut;\r
2267         EventBits_t xEventBits = ( EventBits_t ) 0;\r
2268 \r
2269                 /* Check if the socket is valid, has type TCP and if it is bound to a\r
2270                 port. */\r
2271                 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )\r
2272                 {\r
2273                         xByteCount = -pdFREERTOS_ERRNO_EINVAL;\r
2274                 }\r
2275                 else\r
2276                 {\r
2277                         if( pxSocket->u.xTCP.rxStream != NULL )\r
2278                         {\r
2279                                 xByteCount = ( BaseType_t )uxStreamBufferGetSize ( pxSocket->u.xTCP.rxStream );\r
2280                         }\r
2281                         else\r
2282                         {\r
2283                                 xByteCount = 0;\r
2284                         }\r
2285 \r
2286                         while( xByteCount == 0 )\r
2287                         {\r
2288                                 switch( pxSocket->u.xTCP.ucTCPState )\r
2289                                 {\r
2290                                 case eCLOSED:\r
2291                                 case eCLOSE_WAIT:       /* (server + client) waiting for a connection termination request from the local user. */\r
2292                                 case eCLOSING:          /* (server + client) waiting for a connection termination request acknowledgement from the remote TCP. */\r
2293                                         if( pxSocket->u.xTCP.bits.bMallocError != pdFALSE_UNSIGNED )\r
2294                                         {\r
2295                                                 /* The no-memory error has priority above the non-connected error.\r
2296                                                 Both are fatal and will elad to closing the socket. */\r
2297                                                 xByteCount = -pdFREERTOS_ERRNO_ENOMEM;\r
2298                                         }\r
2299                                         else\r
2300                                         {\r
2301                                                 xByteCount = -pdFREERTOS_ERRNO_ENOTCONN;\r
2302                                         }\r
2303                                         /* Call continue to break out of the switch and also the while\r
2304                                         loop. */\r
2305                                         continue;\r
2306                                 default:\r
2307                                         break;\r
2308                                 }\r
2309 \r
2310                                 if( xTimed == pdFALSE )\r
2311                                 {\r
2312                                         /* Only in the first round, check for non-blocking. */\r
2313                                         xRemainingTime = pxSocket->xReceiveBlockTime;\r
2314 \r
2315                                         if( xRemainingTime == ( TickType_t ) 0 )\r
2316                                         {\r
2317                                                 #if( ipconfigSUPPORT_SIGNALS != 0 )\r
2318                                                 {\r
2319                                                         /* Just check for the interrupt flag. */\r
2320                                                         xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_INTR,\r
2321                                                                 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, socketDONT_BLOCK );\r
2322                                                 }\r
2323                                                 #endif /* ipconfigSUPPORT_SIGNALS */\r
2324                                                 break;\r
2325                                         }\r
2326 \r
2327                                         if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )\r
2328                                         {\r
2329                                                 break;\r
2330                                         }\r
2331 \r
2332                                         /* Don't get here a second time. */\r
2333                                         xTimed = pdTRUE;\r
2334 \r
2335                                         /* Fetch the current time. */\r
2336                                         vTaskSetTimeOutState( &xTimeOut );\r
2337                                 }\r
2338 \r
2339                                 /* Has the timeout been reached? */\r
2340                                 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )\r
2341                                 {\r
2342                                         break;\r
2343                                 }\r
2344 \r
2345                                 /* Block until there is a down-stream event. */\r
2346                                 xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup,\r
2347                                         eSOCKET_RECEIVE | eSOCKET_CLOSED | eSOCKET_INTR,\r
2348                                         pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );\r
2349                                 #if( ipconfigSUPPORT_SIGNALS != 0 )\r
2350                                 {\r
2351                                         if( ( xEventBits & eSOCKET_INTR ) != 0u )\r
2352                                         {\r
2353                                                 break;\r
2354                                         }\r
2355                                 }\r
2356                                 #else\r
2357                                 {\r
2358                                         ( void ) xEventBits;\r
2359                                 }\r
2360                                 #endif /* ipconfigSUPPORT_SIGNALS */\r
2361 \r
2362                                 if( pxSocket->u.xTCP.rxStream != NULL )\r
2363                                 {\r
2364                                         xByteCount = ( BaseType_t ) uxStreamBufferGetSize ( pxSocket->u.xTCP.rxStream );\r
2365                                 }\r
2366                                 else\r
2367                                 {\r
2368                                         xByteCount = 0;\r
2369                                 }\r
2370                         }\r
2371 \r
2372                 #if( ipconfigSUPPORT_SIGNALS != 0 )\r
2373                         if( ( xEventBits & eSOCKET_INTR ) != 0 )\r
2374                         {\r
2375                                 if( ( xEventBits & ( eSOCKET_RECEIVE | eSOCKET_CLOSED ) ) != 0 )\r
2376                                 {\r
2377                                         /* Shouldn't have cleared other flags. */\r
2378                                         xEventBits &= ~eSOCKET_INTR;\r
2379                                         xEventGroupSetBits( pxSocket->xEventGroup, xEventBits );\r
2380                                 }\r
2381                                 xByteCount = -pdFREERTOS_ERRNO_EINTR;\r
2382                         }\r
2383                         else\r
2384                 #endif /* ipconfigSUPPORT_SIGNALS */\r
2385                         if( xByteCount > 0 )\r
2386                         {\r
2387                                 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )\r
2388                                 {\r
2389                                         xByteCount = ( BaseType_t ) uxStreamBufferGet( pxSocket->u.xTCP.rxStream, 0ul, ( uint8_t * ) pvBuffer, ( size_t ) xBufferLength, ( xFlags & FREERTOS_MSG_PEEK ) != 0 );\r
2390                                         if( pxSocket->u.xTCP.bits.bLowWater != pdFALSE_UNSIGNED )\r
2391                                         {\r
2392                                                 /* We had reached the low-water mark, now see if the flag\r
2393                                                 can be cleared */\r
2394                                                 size_t uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );\r
2395 \r
2396                                                 if( uxFrontSpace >= pxSocket->u.xTCP.uxEnoughSpace )\r
2397                                                 {\r
2398                                                         pxSocket->u.xTCP.bits.bLowWater = pdFALSE_UNSIGNED;\r
2399                                                         pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;\r
2400                                                         pxSocket->u.xTCP.usTimeout = 1u; /* because bLowWater is cleared. */\r
2401                                                         xSendEventToIPTask( eTCPTimerEvent );\r
2402                                                 }\r
2403                                         }\r
2404                                 }\r
2405                                 else\r
2406                                 {\r
2407                                         /* Zero-copy reception of data: pvBuffer is a pointer to a pointer. */\r
2408                                         xByteCount = ( BaseType_t ) uxStreamBufferGetPtr( pxSocket->u.xTCP.rxStream, (uint8_t **)pvBuffer );\r
2409                                 }\r
2410                         }\r
2411                 } /* prvValidSocket() */\r
2412 \r
2413                 return xByteCount;\r
2414         }\r
2415 \r
2416 #endif /* ipconfigUSE_TCP */\r
2417 /*-----------------------------------------------------------*/\r
2418 \r
2419 #if( ipconfigUSE_TCP == 1 )\r
2420 \r
2421         static int32_t prvTCPSendCheck( FreeRTOS_Socket_t *pxSocket, size_t xDataLength )\r
2422         {\r
2423         int32_t xResult = 1;\r
2424 \r
2425                 /* Is this a socket of type TCP and is it already bound to a port number ? */\r
2426                 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )\r
2427                 {\r
2428                         xResult = -pdFREERTOS_ERRNO_EINVAL;\r
2429                 }\r
2430                 else if( pxSocket->u.xTCP.bits.bMallocError != pdFALSE_UNSIGNED )\r
2431                 {\r
2432                         xResult = -pdFREERTOS_ERRNO_ENOMEM;\r
2433                 }\r
2434                 else if( pxSocket->u.xTCP.ucTCPState == eCLOSED ||\r
2435                                  pxSocket->u.xTCP.ucTCPState == eCLOSE_WAIT ||\r
2436                                  pxSocket->u.xTCP.ucTCPState == eCLOSING )\r
2437                 {\r
2438                         xResult = -pdFREERTOS_ERRNO_ENOTCONN;\r
2439                 }\r
2440                 else if( pxSocket->u.xTCP.bits.bFinSent != pdFALSE_UNSIGNED )\r
2441                 {\r
2442                         /* This TCP connection is closing already, the FIN flag has been sent.\r
2443                         Maybe it is still delivering or receiving data.\r
2444                         Return OK in order not to get closed/deleted too quickly */\r
2445                         xResult = 0;\r
2446                 }\r
2447                 else if( xDataLength == 0ul )\r
2448                 {\r
2449                         /* send() is being called to send zero bytes */\r
2450                         xResult = 0;\r
2451                 }\r
2452                 else if( pxSocket->u.xTCP.txStream == NULL )\r
2453                 {\r
2454                         /* Create the outgoing stream only when it is needed */\r
2455                         prvTCPCreateStream( pxSocket, pdFALSE );\r
2456 \r
2457                         if( pxSocket->u.xTCP.txStream == NULL )\r
2458                         {\r
2459                                 xResult = -pdFREERTOS_ERRNO_ENOMEM;\r
2460                         }\r
2461                 }\r
2462 \r
2463                 return xResult;\r
2464         }\r
2465 \r
2466 #endif /* ipconfigUSE_TCP */\r
2467 /*-----------------------------------------------------------*/\r
2468 \r
2469 #if( ipconfigUSE_TCP == 1 )\r
2470 \r
2471         /* Get a direct pointer to the circular transmit buffer.\r
2472         '*pxLength' will contain the number of bytes that may be written. */\r
2473         uint8_t *FreeRTOS_get_tx_head( Socket_t xSocket, BaseType_t *pxLength )\r
2474         {\r
2475         uint8_t *pucReturn = NULL;\r
2476         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
2477         StreamBuffer_t *pxBuffer = NULL;\r
2478 \r
2479                 *pxLength = 0;\r
2480 \r
2481                 /* Confirm that this is a TCP socket before dereferencing structure\r
2482                 member pointers. */\r
2483                 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdTRUE )\r
2484                 {\r
2485                         pxBuffer = pxSocket->u.xTCP.txStream;\r
2486                         if( pxBuffer != NULL )\r
2487                         {\r
2488                         BaseType_t xSpace = ( BaseType_t )uxStreamBufferGetSpace( pxBuffer );\r
2489                         BaseType_t xRemain = ( BaseType_t )( pxBuffer->LENGTH - pxBuffer->uxHead );\r
2490 \r
2491                                 *pxLength = FreeRTOS_min_BaseType( xSpace, xRemain );\r
2492                                 pucReturn = pxBuffer->ucArray + pxBuffer->uxHead;\r
2493                         }\r
2494                 }\r
2495 \r
2496                 return pucReturn;\r
2497         }\r
2498 #endif /* ipconfigUSE_TCP */\r
2499 /*-----------------------------------------------------------*/\r
2500 \r
2501 #if( ipconfigUSE_TCP == 1 )\r
2502         /*\r
2503          * Send data using a TCP socket.  It is not necessary to have the socket\r
2504          * connected already.  Outgoing data will be stored and delivered as soon as\r
2505          * the socket gets connected.\r
2506          */\r
2507         BaseType_t FreeRTOS_send( Socket_t xSocket, const void *pvBuffer, size_t uxDataLength, BaseType_t xFlags )\r
2508         {\r
2509         BaseType_t xByteCount;\r
2510         BaseType_t xBytesLeft;\r
2511         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
2512         TickType_t xRemainingTime;\r
2513         BaseType_t xTimed = pdFALSE;\r
2514         TimeOut_t xTimeOut;\r
2515         BaseType_t xCloseAfterSend;\r
2516 \r
2517                 /* Prevent compiler warnings about unused parameters.  The parameter\r
2518                 may be used in future versions. */\r
2519                 ( void ) xFlags;\r
2520 \r
2521                 xByteCount = ( BaseType_t ) prvTCPSendCheck( pxSocket, uxDataLength );\r
2522 \r
2523                 if( xByteCount > 0 )\r
2524                 {\r
2525                         /* xBytesLeft is number of bytes to send, will count to zero. */\r
2526                         xBytesLeft = ( BaseType_t ) uxDataLength;\r
2527 \r
2528                         /* xByteCount is number of bytes that can be sent now. */\r
2529                         xByteCount = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );\r
2530 \r
2531                         /* While there are still bytes to be sent. */\r
2532                         while( xBytesLeft > 0 )\r
2533                         {\r
2534                                 /* If txStream has space. */\r
2535                                 if( xByteCount > 0 )\r
2536                                 {\r
2537                                         /* Don't send more than necessary. */\r
2538                                         if( xByteCount > xBytesLeft )\r
2539                                         {\r
2540                                                 xByteCount = xBytesLeft;\r
2541                                         }\r
2542 \r
2543                                         /* Is the close-after-send flag set and is this really the\r
2544                                         last transmission? */\r
2545                                         if( ( pxSocket->u.xTCP.bits.bCloseAfterSend != pdFALSE_UNSIGNED ) && ( xByteCount == xBytesLeft ) )\r
2546                                         {\r
2547                                                 xCloseAfterSend = pdTRUE;\r
2548                                         }\r
2549                                         else\r
2550                                         {\r
2551                                                 xCloseAfterSend = pdFALSE;\r
2552                                         }\r
2553 \r
2554                                         /* The flag 'bCloseAfterSend' can be set before sending data\r
2555                                         using setsockopt()\r
2556 \r
2557                                         When the last data packet is being sent out, a FIN flag will\r
2558                                         be included to let the peer know that no more data is to be\r
2559                                         expected.  The use of 'bCloseAfterSend' is not mandatory, it\r
2560                                         is just a faster way of transferring files (e.g. when using\r
2561                                         FTP). */\r
2562                                         if( xCloseAfterSend != pdFALSE )\r
2563                                         {\r
2564                                                 /* Now suspend the scheduler: sending the last data     and\r
2565                                                 setting bCloseRequested must be done together */\r
2566                                                 vTaskSuspendAll();\r
2567                                                 pxSocket->u.xTCP.bits.bCloseRequested = pdTRUE_UNSIGNED;\r
2568                                         }\r
2569 \r
2570                                         xByteCount = ( BaseType_t ) uxStreamBufferAdd( pxSocket->u.xTCP.txStream, 0ul, ( const uint8_t * ) pvBuffer, ( size_t ) xByteCount );\r
2571 \r
2572                                         if( xCloseAfterSend != pdFALSE )\r
2573                                         {\r
2574                                                 /* Now when the IP-task transmits the data, it will also\r
2575                                                 see     that bCloseRequested is true and include the FIN\r
2576                                                 flag to start closure of the connection. */\r
2577                                                 xTaskResumeAll();\r
2578                                         }\r
2579 \r
2580                                         /* Send a message to the IP-task so it can work on this\r
2581                                         socket.  Data is sent, let the IP-task work on it. */\r
2582                                         pxSocket->u.xTCP.usTimeout = 1u;\r
2583 \r
2584                                         if( xIsCallingFromIPTask() == pdFALSE )\r
2585                                         {\r
2586                                                 /* Only send a TCP timer event when not called from the\r
2587                                                 IP-task. */\r
2588                                                 xSendEventToIPTask( eTCPTimerEvent );\r
2589                                         }\r
2590 \r
2591                                         xBytesLeft -= xByteCount;\r
2592 \r
2593                                         if( xBytesLeft == 0 )\r
2594                                         {\r
2595                                                 break;\r
2596                                         }\r
2597 \r
2598                                         /* As there are still bytes left to be sent, increase the\r
2599                                         data pointer. */\r
2600                                         pvBuffer = ( void * ) ( ( ( const uint8_t * ) pvBuffer) + xByteCount );\r
2601                                 }\r
2602 \r
2603                                 /* Not all bytes have been sent. In case the socket is marked as\r
2604                                 blocking sleep for a while. */\r
2605                                 if( xTimed == pdFALSE )\r
2606                                 {\r
2607                                         /* Only in the first round, check for non-blocking. */\r
2608                                         xRemainingTime = pxSocket->xSendBlockTime;\r
2609 \r
2610                                         #if( ipconfigUSE_CALLBACKS != 0 )\r
2611                                         {\r
2612                                                 if( xIsCallingFromIPTask() != pdFALSE )\r
2613                                                 {\r
2614                                                         /* If this send function is called from within a\r
2615                                                         call-back handler it may not block, otherwise\r
2616                                                         chances would be big to get a deadlock: the IP-task\r
2617                                                         waiting for     itself. */\r
2618                                                         xRemainingTime = ( TickType_t ) 0;\r
2619                                                 }\r
2620                                         }\r
2621                                         #endif /* ipconfigUSE_CALLBACKS */\r
2622 \r
2623                                         if( xRemainingTime == ( TickType_t ) 0 )\r
2624                                         {\r
2625                                                 break;\r
2626                                         }\r
2627 \r
2628                                         if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )\r
2629                                         {\r
2630                                                 break;\r
2631                                         }\r
2632 \r
2633                                         /* Don't get here a second time. */\r
2634                                         xTimed = pdTRUE;\r
2635 \r
2636                                         /* Fetch the current time. */\r
2637                                         vTaskSetTimeOutState( &xTimeOut );\r
2638                                 }\r
2639                                 else\r
2640                                 {\r
2641                                         /* Has the timeout been reached? */\r
2642                                         if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )\r
2643                                         {\r
2644                                                 break;\r
2645                                         }\r
2646                                 }\r
2647 \r
2648                                 /* Go sleeping until down-stream events are received. */\r
2649                                 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_SEND | eSOCKET_CLOSED,\r
2650                                         pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );\r
2651 \r
2652                                 xByteCount = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );\r
2653                         }\r
2654 \r
2655                         /* How much was actually sent? */\r
2656                         xByteCount = ( ( BaseType_t ) uxDataLength ) - xBytesLeft;\r
2657 \r
2658                         if( xByteCount == 0 )\r
2659                         {\r
2660                                 if( pxSocket->u.xTCP.ucTCPState > eESTABLISHED )\r
2661                                 {\r
2662                                         xByteCount = ( BaseType_t ) -pdFREERTOS_ERRNO_ENOTCONN;\r
2663                                 }\r
2664                                 else\r
2665                                 {\r
2666                                         if( ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) != pdFALSE )\r
2667                                         {\r
2668                                                 FreeRTOS_debug_printf( ( "FreeRTOS_send: %u -> %lxip:%d: no space\n",\r
2669                                                         pxSocket->usLocalPort,\r
2670                                                         pxSocket->u.xTCP.ulRemoteIP,\r
2671                                                         pxSocket->u.xTCP.usRemotePort ) );\r
2672                                         }\r
2673 \r
2674                                         xByteCount = ( BaseType_t ) -pdFREERTOS_ERRNO_ENOSPC;\r
2675                                 }\r
2676                         }\r
2677                 }\r
2678 \r
2679                 return xByteCount;\r
2680         }\r
2681 \r
2682 #endif /* ipconfigUSE_TCP */\r
2683 /*-----------------------------------------------------------*/\r
2684 \r
2685 #if( ipconfigUSE_TCP == 1 )\r
2686 \r
2687         /*\r
2688          * Request to put a socket in listen mode\r
2689          */\r
2690         BaseType_t FreeRTOS_listen( Socket_t xSocket, BaseType_t xBacklog )\r
2691         {\r
2692         FreeRTOS_Socket_t *pxSocket;\r
2693         BaseType_t xResult = 0;\r
2694 \r
2695                 pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
2696 \r
2697                 /* listen() is allowed for a valid TCP socket in Closed state and already\r
2698                 bound. */\r
2699                 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )\r
2700                 {\r
2701                         xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;\r
2702                 }\r
2703                 else if( ( pxSocket->u.xTCP.ucTCPState != eCLOSED ) && ( pxSocket->u.xTCP.ucTCPState != eCLOSE_WAIT ) )\r
2704                 {\r
2705                         /* Socket is in a wrong state. */\r
2706                         xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;\r
2707                 }\r
2708                 else\r
2709                 {\r
2710                         /* Backlog is interpreted here as "the maximum number of child\r
2711                         sockets. */\r
2712                         pxSocket->u.xTCP.usBacklog = ( uint16_t )FreeRTOS_min_int32( ( int32_t ) 0xffff, ( int32_t ) xBacklog );\r
2713 \r
2714                         /* This cleaning is necessary only if a listening socket is being\r
2715                         reused as it might have had a previous connection. */\r
2716                         if( pxSocket->u.xTCP.bits.bReuseSocket )\r
2717                         {\r
2718                                 if( pxSocket->u.xTCP.rxStream != NULL )\r
2719                                 {\r
2720                                         vStreamBufferClear( pxSocket->u.xTCP.rxStream );\r
2721                                 }\r
2722 \r
2723                                 if( pxSocket->u.xTCP.txStream != NULL )\r
2724                                 {\r
2725                                         vStreamBufferClear( pxSocket->u.xTCP.txStream );\r
2726                                 }\r
2727 \r
2728                                 memset( pxSocket->u.xTCP.xPacket.u.ucLastPacket, '\0', sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket ) );\r
2729                                 memset( &pxSocket->u.xTCP.xTCPWindow, '\0', sizeof( pxSocket->u.xTCP.xTCPWindow ) );\r
2730                                 memset( &pxSocket->u.xTCP.bits, '\0', sizeof( pxSocket->u.xTCP.bits ) );\r
2731 \r
2732                                 /* Now set the bReuseSocket flag again, because the bits have\r
2733                                 just been cleared. */\r
2734                                 pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE_UNSIGNED;\r
2735                         }\r
2736 \r
2737                         vTCPStateChange( pxSocket, eTCP_LISTEN );\r
2738                 }\r
2739 \r
2740                 return xResult;\r
2741         }\r
2742 \r
2743 #endif /* ipconfigUSE_TCP */\r
2744 /*-----------------------------------------------------------*/\r
2745 \r
2746 #if( ipconfigUSE_TCP == 1 )\r
2747 \r
2748         /* shutdown - shut down part of a full-duplex connection */\r
2749         BaseType_t FreeRTOS_shutdown( Socket_t xSocket, BaseType_t xHow )\r
2750         {\r
2751         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
2752         BaseType_t xResult;\r
2753 \r
2754                 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )\r
2755                 {\r
2756                         /*_RB_ Is this comment correct?  The socket is not of a type that\r
2757                         supports the listen() operation. */\r
2758                         xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;\r
2759                 }\r
2760                 else if ( pxSocket->u.xTCP.ucTCPState != eESTABLISHED )\r
2761                 {\r
2762                         /*_RB_ Is this comment correct?  The socket is not of a type that\r
2763                         supports the listen() operation. */\r
2764                         xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;\r
2765                 }\r
2766                 else\r
2767                 {\r
2768                         pxSocket->u.xTCP.bits.bUserShutdown = pdTRUE_UNSIGNED;\r
2769 \r
2770                         /* Let the IP-task perform the shutdown of the connection. */\r
2771                         pxSocket->u.xTCP.usTimeout = 1u;\r
2772                         xSendEventToIPTask( eTCPTimerEvent );\r
2773                         xResult = 0;\r
2774                 }\r
2775                 (void) xHow;\r
2776 \r
2777                 return xResult;\r
2778         }\r
2779 \r
2780 #endif /* ipconfigUSE_TCP */\r
2781 /*-----------------------------------------------------------*/\r
2782 \r
2783 #if( ipconfigUSE_TCP == 1 )\r
2784 \r
2785         /*\r
2786          * A TCP timer has expired, now check all TCP sockets for:\r
2787          * - Active connect\r
2788          * - Send a delayed ACK\r
2789          * - Send new data\r
2790          * - Send a keep-alive packet\r
2791          * - Check for timeout (in non-connected states only)\r
2792          */\r
2793         TickType_t xTCPTimerCheck( BaseType_t xWillSleep )\r
2794         {\r
2795         FreeRTOS_Socket_t *pxSocket;\r
2796         TickType_t xShortest = pdMS_TO_TICKS( ( TickType_t ) ipTCP_TIMER_PERIOD_MS );\r
2797         TickType_t xNow = xTaskGetTickCount();\r
2798         static TickType_t xLastTime = 0u;\r
2799         TickType_t xDelta = xNow - xLastTime;\r
2800         ListItem_t* pxEnd = ( ListItem_t * ) listGET_END_MARKER( &xBoundTCPSocketsList );\r
2801         ListItem_t *pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );\r
2802 \r
2803                 xLastTime = xNow;\r
2804 \r
2805                 if( xDelta == 0u )\r
2806                 {\r
2807                         xDelta = 1u;\r
2808                 }\r
2809 \r
2810                 while( pxIterator != pxEnd )\r
2811                 {\r
2812                         pxSocket = ( FreeRTOS_Socket_t * )listGET_LIST_ITEM_OWNER( pxIterator );\r
2813                         pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator );\r
2814 \r
2815                         /* Sockets with 'tmout == 0' do not need any regular attention. */\r
2816                         if( pxSocket->u.xTCP.usTimeout == 0u )\r
2817                         {\r
2818                                 continue;\r
2819                         }\r
2820 \r
2821                         if( xDelta < ( TickType_t ) pxSocket->u.xTCP.usTimeout )\r
2822                         {\r
2823                                 pxSocket->u.xTCP.usTimeout = ( uint16_t ) ( ( ( TickType_t ) pxSocket->u.xTCP.usTimeout ) - xDelta );\r
2824                         }\r
2825                         else\r
2826                         {\r
2827                         int rc ;\r
2828                                 pxSocket->u.xTCP.usTimeout = 0u;\r
2829                                 rc = xTCPSocketCheck( pxSocket );\r
2830 \r
2831                                 /* Within this function, the socket might want to send a delayed\r
2832                                 ack or send out data or whatever it needs to do. */\r
2833                                 if( rc < 0 )\r
2834                                 {\r
2835                                         /* Continue because the socket was deleted. */\r
2836                                         continue;\r
2837                                 }\r
2838                         }\r
2839 \r
2840                         /* In xEventBits the driver may indicate that the socket has\r
2841                         important events for the user.  These are only done just before the\r
2842                         IP-task goes to sleep. */\r
2843                         if( pxSocket->xEventBits != 0u )\r
2844                         {\r
2845                                 if( xWillSleep != pdFALSE )\r
2846                                 {\r
2847                                         /* The IP-task is about to go to sleep, so messages can be\r
2848                                         sent to the socket owners. */\r
2849                                         vSocketWakeUpUser( pxSocket );\r
2850                                 }\r
2851                                 else\r
2852                                 {\r
2853                                         /* Or else make sure this will be called again to wake-up\r
2854                                         the sockets' owner. */\r
2855                                         xShortest = ( TickType_t ) 0;\r
2856                                 }\r
2857                         }\r
2858 \r
2859                         if( ( pxSocket->u.xTCP.usTimeout != 0u ) && ( xShortest > ( TickType_t ) pxSocket->u.xTCP.usTimeout ) )\r
2860                         {\r
2861                                 xShortest = ( TickType_t ) pxSocket->u.xTCP.usTimeout;\r
2862                         }\r
2863                 }\r
2864 \r
2865                 return xShortest;\r
2866         }\r
2867 \r
2868 #endif /* ipconfigUSE_TCP */\r
2869 /*-----------------------------------------------------------*/\r
2870 \r
2871 #if( ipconfigUSE_TCP == 1 )\r
2872 \r
2873         /*\r
2874          * TCP: as multiple sockets may be bound to the same local port number\r
2875          * looking up a socket is a little more complex:\r
2876          * Both a local port, and a remote port and IP address are being used\r
2877          * For a socket in listening mode, the remote port and IP address are both 0\r
2878          */\r
2879         FreeRTOS_Socket_t *pxTCPSocketLookup( uint32_t ulLocalIP, UBaseType_t uxLocalPort, uint32_t ulRemoteIP, UBaseType_t uxRemotePort )\r
2880         {\r
2881         ListItem_t *pxIterator;\r
2882         FreeRTOS_Socket_t *pxResult = NULL, *pxListenSocket = NULL;\r
2883         MiniListItem_t *pxEnd = ( MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );\r
2884 \r
2885                 /* Parameter not yet supported. */\r
2886                 ( void ) ulLocalIP;\r
2887 \r
2888                 for( pxIterator  = ( ListItem_t * ) listGET_NEXT( pxEnd );\r
2889                          pxIterator != ( ListItem_t * ) pxEnd;\r
2890                          pxIterator  = ( ListItem_t * ) listGET_NEXT( pxIterator ) )\r
2891                 {\r
2892                         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );\r
2893 \r
2894                         if( pxSocket->usLocalPort == ( uint16_t ) uxLocalPort )\r
2895                         {\r
2896                                 if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN )\r
2897                                 {\r
2898                                         /* If this is a socket listening to uxLocalPort, remember it\r
2899                                         in case there is no perfect match. */\r
2900                                         pxListenSocket = pxSocket;\r
2901                                 }\r
2902                                 else if( ( pxSocket->u.xTCP.usRemotePort == ( uint16_t ) uxRemotePort ) && ( pxSocket->u.xTCP.ulRemoteIP == ulRemoteIP ) )\r
2903                                 {\r
2904                                         /* For sockets not in listening mode, find a match with\r
2905                                         xLocalPort, ulRemoteIP AND xRemotePort. */\r
2906                                         pxResult = pxSocket;\r
2907                                         break;\r
2908                                 }\r
2909                         }\r
2910                 }\r
2911                 if( pxResult == NULL )\r
2912                 {\r
2913                         /* An exact match was not found, maybe a listening socket was\r
2914                         found. */\r
2915                         pxResult = pxListenSocket;\r
2916                 }\r
2917 \r
2918                 return pxResult;\r
2919         }\r
2920 \r
2921 #endif /* ipconfigUSE_TCP */\r
2922 /*-----------------------------------------------------------*/\r
2923 \r
2924 #if( ipconfigUSE_TCP == 1 )\r
2925 \r
2926         const struct xSTREAM_BUFFER *FreeRTOS_get_rx_buf( Socket_t xSocket )\r
2927         {\r
2928         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * )xSocket;\r
2929         struct xSTREAM_BUFFER *pxReturn = NULL;\r
2930 \r
2931                 /* Confirm that this is a TCP socket before dereferencing structure\r
2932                 member pointers. */\r
2933                 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdTRUE )\r
2934                 {\r
2935                         pxReturn = pxSocket->u.xTCP.rxStream;\r
2936                 }\r
2937 \r
2938                 return pxReturn;\r
2939         }\r
2940 \r
2941 #endif /* ipconfigUSE_TCP */\r
2942 /*-----------------------------------------------------------*/\r
2943 \r
2944 #if( ipconfigUSE_TCP == 1 )\r
2945 \r
2946         static StreamBuffer_t *prvTCPCreateStream ( FreeRTOS_Socket_t *pxSocket, BaseType_t xIsInputStream )\r
2947         {\r
2948         StreamBuffer_t *pxBuffer;\r
2949         size_t uxLength;\r
2950         size_t uxSize;\r
2951 \r
2952                 /* Now that a stream is created, the maximum size is fixed before\r
2953                 creation, it could still be changed with setsockopt(). */\r
2954                 if( xIsInputStream != pdFALSE )\r
2955                 {\r
2956                         uxLength = pxSocket->u.xTCP.uxRxStreamSize;\r
2957 \r
2958                         if( pxSocket->u.xTCP.uxLittleSpace == 0ul )\r
2959                         {\r
2960                                 pxSocket->u.xTCP.uxLittleSpace  = ( sock20_PERCENT * pxSocket->u.xTCP.uxRxStreamSize ) / sock100_PERCENT;\r
2961                         }\r
2962 \r
2963                         if( pxSocket->u.xTCP.uxEnoughSpace == 0ul )\r
2964                         {\r
2965                                 pxSocket->u.xTCP.uxEnoughSpace = ( sock80_PERCENT * pxSocket->u.xTCP.uxRxStreamSize ) / sock100_PERCENT;\r
2966                         }\r
2967                 }\r
2968                 else\r
2969                 {\r
2970                         uxLength = pxSocket->u.xTCP.uxTxStreamSize;\r
2971                 }\r
2972 \r
2973                 /* Add an extra 4 (or 8) bytes. */\r
2974                 uxLength += sizeof( size_t );\r
2975 \r
2976                 /* And make the length a multiple of sizeof( size_t ). */\r
2977                 uxLength &= ~( sizeof( size_t ) - 1u );\r
2978 \r
2979                 uxSize = sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) + uxLength;\r
2980 \r
2981                 pxBuffer = ( StreamBuffer_t * )pvPortMallocLarge( uxSize );\r
2982 \r
2983                 if( pxBuffer == NULL )\r
2984                 {\r
2985                         FreeRTOS_debug_printf( ( "prvTCPCreateStream: malloc failed\n" ) );\r
2986                         pxSocket->u.xTCP.bits.bMallocError = pdTRUE_UNSIGNED;\r
2987                         vTCPStateChange( pxSocket, eCLOSE_WAIT );\r
2988                 }\r
2989                 else\r
2990                 {\r
2991                         /* Clear the markers of the stream */\r
2992                         memset( pxBuffer, '\0', sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) );\r
2993                         pxBuffer->LENGTH = ( size_t ) uxLength ;\r
2994 \r
2995                         if( xTCPWindowLoggingLevel != 0 )\r
2996                         {\r
2997                                 FreeRTOS_debug_printf( ( "prvTCPCreateStream: %cxStream created %lu bytes (total %lu)\n", xIsInputStream ? 'R' : 'T', uxLength, uxSize ) );\r
2998                         }\r
2999 \r
3000                         if( xIsInputStream != 0 )\r
3001                         {\r
3002                                 pxSocket->u.xTCP.rxStream = pxBuffer;\r
3003                         }\r
3004                         else\r
3005                         {\r
3006                                 pxSocket->u.xTCP.txStream = pxBuffer;\r
3007                         }\r
3008                 }\r
3009 \r
3010                 return pxBuffer;\r
3011         }\r
3012 \r
3013 #endif /* ipconfigUSE_TCP */\r
3014 /*-----------------------------------------------------------*/\r
3015 \r
3016 #if( ipconfigUSE_TCP == 1 )\r
3017 \r
3018         /*\r
3019          * Add data to the RxStream.  When uxOffset > 0, data has come in out-of-order\r
3020          * and will be put in front of the head so it can not be popped by the user.\r
3021          */\r
3022         int32_t lTCPAddRxdata( FreeRTOS_Socket_t *pxSocket, size_t uxOffset, const uint8_t *pcData, uint32_t ulByteCount )\r
3023         {\r
3024         StreamBuffer_t *pxStream = pxSocket->u.xTCP.rxStream;\r
3025         int32_t xResult;\r
3026         #if( ipconfigUSE_CALLBACKS == 1 )\r
3027                 BaseType_t bHasHandler = ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xTCP.pxHandleReceive );\r
3028                 const uint8_t *pucBuffer = NULL;\r
3029         #endif /* ipconfigUSE_CALLBACKS */\r
3030 \r
3031                 /* int32_t uxStreamBufferAdd( pxBuffer, uxOffset, pucData, aCount )\r
3032                 if( pucData != NULL ) copy data the the buffer\r
3033                 if( pucData == NULL ) no copying, just advance rxHead\r
3034                 if( uxOffset != 0 ) Just store data which has come out-of-order\r
3035                 if( uxOffset == 0 ) Also advance rxHead */\r
3036                 if( pxStream == NULL )\r
3037                 {\r
3038                         pxStream = prvTCPCreateStream( pxSocket, pdTRUE );\r
3039                         if( pxStream == NULL )\r
3040                         {\r
3041                                 return -1;\r
3042                         }\r
3043                 }\r
3044 \r
3045                 #if( ipconfigUSE_CALLBACKS == 1 )\r
3046                 {\r
3047                         if( ( bHasHandler != pdFALSE ) && ( uxStreamBufferGetSize( pxStream ) == 0u ) && ( uxOffset == 0ul ) && ( pcData != NULL ) )\r
3048                         {\r
3049                                 /* Data can be passed directly to the user */\r
3050                                 pucBuffer = pcData;\r
3051 \r
3052                                 /* Zero-copy for call-back: no need to add the bytes to the\r
3053                                 stream, only the pointer will be advanced by uxStreamBufferAdd(). */\r
3054                                 pcData = NULL;\r
3055                         }\r
3056                 }\r
3057                 #endif /* ipconfigUSE_CALLBACKS */\r
3058 \r
3059                 xResult = ( int32_t ) uxStreamBufferAdd( pxStream, uxOffset, pcData, ( size_t ) ulByteCount );\r
3060 \r
3061                 #if( ipconfigHAS_DEBUG_PRINTF != 0 )\r
3062                 {\r
3063                         if( xResult != ( int32_t ) ulByteCount )\r
3064                         {\r
3065                                 FreeRTOS_debug_printf( ( "lTCPAddRxdata: at %ld: %ld/%lu bytes (tail %lu head %lu space %lu front %lu)\n",\r
3066                                         uxOffset, xResult, ulByteCount,\r
3067                                         pxStream->uxTail,\r
3068                                         pxStream->uxHead,\r
3069                                         uxStreamBufferFrontSpace( pxStream ),\r
3070                                         pxStream->uxFront ) );\r
3071                         }\r
3072                 }\r
3073                 #endif /* ipconfigHAS_DEBUG_PRINTF */\r
3074 \r
3075                 if( uxOffset == 0u )\r
3076                 {\r
3077                         /* Data is being added to rxStream at the head (offs = 0) */\r
3078                         #if( ipconfigUSE_CALLBACKS == 1 )\r
3079                                 if( bHasHandler != pdFALSE )\r
3080                                 {\r
3081                                         /* The socket owner has installed an OnReceive handler. Pass the\r
3082                                         Rx data, without copying from the rxStream, to the user. */\r
3083                                         for (;;)\r
3084                                         {\r
3085                                                 uint8_t *ucReadPtr = NULL;\r
3086                                                 uint32_t ulCount;\r
3087                                                 if( pucBuffer != NULL )\r
3088                                                 {\r
3089                                                         ucReadPtr = ( uint8_t * )pucBuffer;\r
3090                                                         ulCount = ulByteCount;\r
3091                                                         pucBuffer = NULL;\r
3092                                                 }\r
3093                                                 else\r
3094                                                 {\r
3095                                                         ulCount = ( uint32_t ) uxStreamBufferGetPtr( pxStream, &( ucReadPtr ) );\r
3096                                                 }\r
3097 \r
3098                                                 if( ulCount == 0ul )\r
3099                                                 {\r
3100                                                         break;\r
3101                                                 }\r
3102 \r
3103                                                 pxSocket->u.xTCP.pxHandleReceive( (Socket_t *)pxSocket, ( void* )ucReadPtr, ( size_t ) ulCount );\r
3104                                                 uxStreamBufferGet( pxStream, 0ul, NULL, ( size_t ) ulCount, pdFALSE );\r
3105                                         }\r
3106                                 } else\r
3107                         #endif /* ipconfigUSE_CALLBACKS */\r
3108                         {\r
3109                                 /* See if running out of space. */\r
3110                                 if( pxSocket->u.xTCP.bits.bLowWater == pdFALSE_UNSIGNED )\r
3111                                 {\r
3112                                         size_t uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );\r
3113                                         if( uxFrontSpace <= pxSocket->u.xTCP.uxLittleSpace  )\r
3114                                         {\r
3115                                                 pxSocket->u.xTCP.bits.bLowWater = pdTRUE_UNSIGNED;\r
3116                                                 pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;\r
3117 \r
3118                                                 /* bLowWater was reached, send the changed window size. */\r
3119                                                 pxSocket->u.xTCP.usTimeout = 1u;\r
3120                                                 xSendEventToIPTask( eTCPTimerEvent );\r
3121                                         }\r
3122                                 }\r
3123 \r
3124                                 /* New incoming data is available, wake up the user.   User's\r
3125                                 semaphores will be set just before the IP-task goes asleep. */\r
3126                                 pxSocket->xEventBits |= eSOCKET_RECEIVE;\r
3127 \r
3128                                 #if ipconfigSUPPORT_SELECT_FUNCTION == 1\r
3129                                 {\r
3130                                         if( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 )\r
3131                                         {\r
3132                                                 pxSocket->xEventBits |= ( eSELECT_READ << SOCKET_EVENT_BIT_COUNT );\r
3133                                         }\r
3134                                 }\r
3135                                 #endif\r
3136                         }\r
3137                 }\r
3138 \r
3139                 return xResult;\r
3140         }\r
3141 \r
3142 #endif /* ipconfigUSE_TCP */\r
3143 /*-----------------------------------------------------------*/\r
3144 \r
3145 #if( ipconfigUSE_TCP == 1 )\r
3146 \r
3147         /* Function to get the remote address and IP port */\r
3148         BaseType_t FreeRTOS_GetRemoteAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress )\r
3149         {\r
3150         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
3151         BaseType_t xResult;\r
3152 \r
3153                 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
3154                 {\r
3155                         xResult = -pdFREERTOS_ERRNO_EINVAL;\r
3156                 }\r
3157                 else\r
3158                 {\r
3159                         /* BSD style sockets communicate IP and port addresses in network\r
3160                         byte order.\r
3161 \r
3162                         IP address of remote machine. */\r
3163                         pxAddress->sin_addr = FreeRTOS_htonl ( pxSocket->u.xTCP.ulRemoteIP );\r
3164 \r
3165                         /* Port on remote machine. */\r
3166                         pxAddress->sin_port = FreeRTOS_htons ( pxSocket->u.xTCP.usRemotePort );\r
3167 \r
3168                         xResult = ( BaseType_t ) sizeof( ( *pxAddress ) );\r
3169                 }\r
3170 \r
3171                 return xResult;\r
3172         }\r
3173 \r
3174 #endif /* ipconfigUSE_TCP */\r
3175 \r
3176 /*-----------------------------------------------------------*/\r
3177 \r
3178 #if( ipconfigUSE_TCP == 1 )\r
3179 \r
3180         /* Returns the number of bytes that may be added to txStream */\r
3181         BaseType_t FreeRTOS_maywrite( Socket_t xSocket )\r
3182         {\r
3183         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
3184         BaseType_t xResult;\r
3185 \r
3186                 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
3187                 {\r
3188                         xResult = -pdFREERTOS_ERRNO_EINVAL;\r
3189                 }\r
3190                 else if( pxSocket->u.xTCP.ucTCPState != eESTABLISHED )\r
3191                 {\r
3192                         if( ( pxSocket->u.xTCP.ucTCPState < eCONNECT_SYN ) || ( pxSocket->u.xTCP.ucTCPState > eESTABLISHED ) )\r
3193                         {\r
3194                                 xResult = -1;\r
3195                         }\r
3196                         else\r
3197                         {\r
3198                                 xResult = 0;\r
3199                         }\r
3200                 }\r
3201                 else if( pxSocket->u.xTCP.txStream == NULL )\r
3202                 {\r
3203                         xResult = ( BaseType_t ) pxSocket->u.xTCP.uxTxStreamSize;\r
3204                 }\r
3205                 else\r
3206                 {\r
3207                         xResult = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );\r
3208                 }\r
3209 \r
3210                 return xResult;\r
3211         }\r
3212 \r
3213 #endif /* ipconfigUSE_TCP */\r
3214 /*-----------------------------------------------------------*/\r
3215 \r
3216 #if( ipconfigUSE_TCP ==1 )\r
3217 \r
3218         BaseType_t FreeRTOS_tx_space( Socket_t xSocket )\r
3219         {\r
3220         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
3221         BaseType_t xReturn;\r
3222 \r
3223                 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
3224                 {\r
3225                         xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
3226                 }\r
3227                 else\r
3228                 {\r
3229                         if( pxSocket->u.xTCP.txStream != NULL )\r
3230                         {\r
3231                                 xReturn = ( BaseType_t ) uxStreamBufferGetSpace ( pxSocket->u.xTCP.txStream );\r
3232                         }\r
3233                         else\r
3234                         {\r
3235                                 xReturn = ( BaseType_t ) pxSocket->u.xTCP.uxTxStreamSize;\r
3236                         }\r
3237                 }\r
3238 \r
3239                 return xReturn;\r
3240         }\r
3241 \r
3242 #endif /* ipconfigUSE_TCP */\r
3243 /*-----------------------------------------------------------*/\r
3244 \r
3245 #if( ipconfigUSE_TCP == 1 )\r
3246 \r
3247         BaseType_t FreeRTOS_tx_size( Socket_t xSocket )\r
3248         {\r
3249         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
3250         BaseType_t xReturn;\r
3251 \r
3252                 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
3253                 {\r
3254                         xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
3255                 }\r
3256                 else\r
3257                 {\r
3258                         if( pxSocket->u.xTCP.txStream != NULL )\r
3259                         {\r
3260                                 xReturn = ( BaseType_t ) uxStreamBufferGetSize ( pxSocket->u.xTCP.txStream );\r
3261                         }\r
3262                         else\r
3263                         {\r
3264                                 xReturn = 0;\r
3265                         }\r
3266                 }\r
3267 \r
3268                 return xReturn;\r
3269         }\r
3270 \r
3271 #endif /* ipconfigUSE_TCP */\r
3272 /*-----------------------------------------------------------*/\r
3273 \r
3274 #if( ipconfigUSE_TCP == 1 )\r
3275 \r
3276         /* Returns pdTRUE if TCP socket is connected. */\r
3277         BaseType_t FreeRTOS_issocketconnected( Socket_t xSocket )\r
3278         {\r
3279         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
3280         BaseType_t xReturn = pdFALSE;\r
3281 \r
3282                 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
3283                 {\r
3284                         xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
3285                 }\r
3286                 else\r
3287                 {\r
3288                         if( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED )\r
3289                         {\r
3290                                 if( pxSocket->u.xTCP.ucTCPState < eCLOSE_WAIT )\r
3291                                 {\r
3292                                         xReturn = pdTRUE;\r
3293                                 }\r
3294                         }\r
3295                 }\r
3296 \r
3297                 return xReturn;\r
3298         }\r
3299 \r
3300 #endif /* ipconfigUSE_TCP */\r
3301 /*-----------------------------------------------------------*/\r
3302 \r
3303 #if( ipconfigUSE_TCP == 1 )\r
3304 \r
3305         /* returns the actual size of MSS being used */\r
3306         BaseType_t FreeRTOS_mss( Socket_t xSocket )\r
3307         {\r
3308         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
3309         BaseType_t xReturn;\r
3310 \r
3311                 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
3312                 {\r
3313                         xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
3314                 }\r
3315                 else\r
3316                 {\r
3317                         /* usCurMSS is declared as uint16_t to save space.  FreeRTOS_mss()\r
3318                         will often be used in signed native-size expressions cast it to\r
3319                         BaseType_t. */\r
3320                         xReturn = ( BaseType_t ) ( pxSocket->u.xTCP.usCurMSS );\r
3321                 }\r
3322 \r
3323                 return xReturn;\r
3324         }\r
3325 \r
3326 #endif /* ipconfigUSE_TCP */\r
3327 /*-----------------------------------------------------------*/\r
3328 \r
3329 #if( ipconfigUSE_TCP == 1 )\r
3330 \r
3331         /* HT: for internal use only: return the connection status */\r
3332         BaseType_t FreeRTOS_connstatus( Socket_t xSocket )\r
3333         {\r
3334         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
3335         BaseType_t xReturn;\r
3336 \r
3337                 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
3338                 {\r
3339                         xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
3340                 }\r
3341                 else\r
3342                 {\r
3343                         /* Cast it to BaseType_t */\r
3344                         xReturn = ( BaseType_t ) ( pxSocket->u.xTCP.ucTCPState );\r
3345                 }\r
3346 \r
3347                 return xReturn;\r
3348         }\r
3349 \r
3350 #endif /* ipconfigUSE_TCP */\r
3351 /*-----------------------------------------------------------*/\r
3352 \r
3353 #if( ipconfigUSE_TCP == 1 )\r
3354 \r
3355         /*\r
3356          * Returns the number of bytes which can be read.\r
3357          */\r
3358         BaseType_t FreeRTOS_rx_size( Socket_t xSocket )\r
3359         {\r
3360         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
3361         BaseType_t xReturn;\r
3362 \r
3363                 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
3364                 {\r
3365                         xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
3366                 }\r
3367                 else if( pxSocket->u.xTCP.rxStream != NULL )\r
3368                 {\r
3369                         xReturn = ( BaseType_t ) uxStreamBufferGetSize( pxSocket->u.xTCP.rxStream );\r
3370                 }\r
3371                 else\r
3372                 {\r
3373                         xReturn = 0;\r
3374                 }\r
3375 \r
3376                 return xReturn;\r
3377         }\r
3378 \r
3379 #endif /* ipconfigUSE_TCP */\r
3380 /*-----------------------------------------------------------*/\r
3381 \r
3382 #if( ipconfigUSE_TCP == 1 )\r
3383 \r
3384         void FreeRTOS_netstat( void )\r
3385         {\r
3386         IPStackEvent_t xAskEvent;\r
3387 \r
3388                 /* Ask the IP-task to call vTCPNetStat()\r
3389                  * to avoid accessing xBoundTCPSocketsList\r
3390                  */\r
3391                 xAskEvent.eEventType = eTCPNetStat;\r
3392                 xAskEvent.pvData = ( void * ) NULL;\r
3393                 xSendEventStructToIPTask( &xAskEvent, 1000u );\r
3394         }\r
3395 \r
3396 #endif /* ipconfigUSE_TCP */\r
3397 /*-----------------------------------------------------------*/\r
3398 \r
3399 #if( ( ipconfigHAS_PRINTF != 0 ) && ( ipconfigUSE_TCP == 1 ) )\r
3400 \r
3401         void vTCPNetStat( void )\r
3402         {\r
3403         /* Show a simple listing of all created sockets and their connections */\r
3404         ListItem_t *pxIterator;\r
3405         BaseType_t count = 0;\r
3406 \r
3407                 if( listLIST_IS_INITIALISED( &xBoundTCPSocketsList ) == pdFALSE )\r
3408                 {\r
3409                         FreeRTOS_printf( ( "PLUS-TCP not initialized\n" ) );\r
3410                 }\r
3411                 else\r
3412                 {\r
3413                         FreeRTOS_printf( ( "Prot Port IP-Remote    : Port  R/T Status      Alive  tmout Child\n" ) );\r
3414                         for( pxIterator  = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );\r
3415                                  pxIterator != ( ListItem_t * ) listGET_END_MARKER( &xBoundTCPSocketsList );\r
3416                                  pxIterator  = ( ListItem_t * ) listGET_NEXT( pxIterator ) )\r
3417                         {\r
3418                                 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );\r
3419                                 #if( ipconfigTCP_KEEP_ALIVE == 1 )\r
3420                                         TickType_t age = xTaskGetTickCount() - pxSocket->u.xTCP.xLastAliveTime;\r
3421                                 #else\r
3422                                         TickType_t age = 0u;\r
3423                                 #endif\r
3424                                 #if( ipconfigUSE_CALLBACKS == 1 )\r
3425                                         void *pxHandleReceive = (void*)pxSocket->u.xTCP.pxHandleReceive;\r
3426                                 #else\r
3427                                         void *pxHandleReceive = (void*)NULL;\r
3428                                 #endif\r
3429                                 char ucChildText[16] = "";\r
3430                                 if (pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN)\r
3431                                 {\r
3432                                         const int32_t copied_len = snprintf( ucChildText, sizeof( ucChildText ), " %d/%d",\r
3433                                                 ( int ) pxSocket->u.xTCP.usChildCount,\r
3434                                                 ( int ) pxSocket->u.xTCP.usBacklog);\r
3435                                         /* These should never evaluate to false since the buffers are both shorter than 5-6 characters (<=65535) */\r
3436                                         configASSERT( copied_len >= 0 );\r
3437                                         configASSERT( copied_len < sizeof( ucChildText ) );\r
3438                                 }\r
3439                                 FreeRTOS_printf( ( "TCP %5d %-16lxip:%5d %d/%d %-13.13s %6lu %6u%s\n",\r
3440                                         pxSocket->usLocalPort,          /* Local port on this machine */\r
3441                                         pxSocket->u.xTCP.ulRemoteIP,    /* IP address of remote machine */\r
3442                                         pxSocket->u.xTCP.usRemotePort,  /* Port on remote machine */\r
3443                                         pxSocket->u.xTCP.rxStream != NULL,\r
3444                                         pxSocket->u.xTCP.txStream != NULL,\r
3445                                         FreeRTOS_GetTCPStateName( pxSocket->u.xTCP.ucTCPState ),\r
3446                                         (age > 999999 ? 999999 : age), /* Format 'age' for printing */\r
3447                                         pxSocket->u.xTCP.usTimeout,\r
3448                                         ucChildText ) );\r
3449                                         /* Remove compiler warnings if FreeRTOS_debug_printf() is not defined. */\r
3450                                         ( void ) pxHandleReceive;\r
3451                                 count++;\r
3452                         }\r
3453 \r
3454                         for( pxIterator  = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundUDPSocketsList );\r
3455                                  pxIterator != ( ListItem_t * ) listGET_END_MARKER( &xBoundUDPSocketsList );\r
3456                                  pxIterator  = ( ListItem_t * ) listGET_NEXT( pxIterator ) )\r
3457                         {\r
3458                                 /* Local port on this machine */\r
3459                                 FreeRTOS_printf( ( "UDP Port %5u\n",\r
3460                                         FreeRTOS_ntohs( listGET_LIST_ITEM_VALUE( pxIterator ) ) ) );\r
3461                                 count++;\r
3462                         }\r
3463 \r
3464                         FreeRTOS_printf( ( "FreeRTOS_netstat: %lu sockets %lu < %lu < %d buffers free\n",\r
3465                                 count,\r
3466                                 uxGetMinimumFreeNetworkBuffers( ),\r
3467                                 uxGetNumberOfFreeNetworkBuffers( ),\r
3468                                 ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ) );\r
3469                 }\r
3470         }\r
3471 \r
3472 #endif /* ( ( ipconfigHAS_PRINTF != 0 ) && ( ipconfigUSE_TCP == 1 ) ) */\r
3473 /*-----------------------------------------------------------*/\r
3474 \r
3475 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
3476 \r
3477         void vSocketSelect( SocketSelect_t *pxSocketSet )\r
3478         {\r
3479         BaseType_t xRound;\r
3480         EventBits_t xSocketBits, xBitsToClear;\r
3481         #if ipconfigUSE_TCP == 1\r
3482                 BaseType_t xLastRound = 1;\r
3483         #else\r
3484                 BaseType_t xLastRound = 0;\r
3485         #endif\r
3486 \r
3487                 /* These flags will be switched on after checking the socket status. */\r
3488                 EventBits_t xGroupBits = 0;\r
3489                 pxSocketSet->pxSocket = NULL;\r
3490 \r
3491                 for( xRound = 0; xRound <= xLastRound; xRound++ )\r
3492                 {\r
3493                         const ListItem_t *pxIterator;\r
3494                         const MiniListItem_t *pxEnd;\r
3495                         if( xRound == 0 )\r
3496                         {\r
3497                                 pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundUDPSocketsList );\r
3498                         }\r
3499                 #if ipconfigUSE_TCP == 1\r
3500                         else\r
3501                         {\r
3502                                 pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );\r
3503                         }\r
3504                 #endif /* ipconfigUSE_TCP == 1 */\r
3505                         for( pxIterator = ( const ListItem_t * ) ( listGET_NEXT( pxEnd ) );\r
3506                                  pxIterator != ( const ListItem_t * ) pxEnd;\r
3507                                  pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )\r
3508                         {\r
3509                                 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );\r
3510                                 if( pxSocket->pxSocketSet != pxSocketSet )\r
3511                                 {\r
3512                                         /* Socket does not belong to this select group. */\r
3513                                         continue;\r
3514                                 }\r
3515                                 xSocketBits = 0;\r
3516 \r
3517                                 #if( ipconfigUSE_TCP == 1 )\r
3518                                         if( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP )\r
3519                                         {\r
3520                                                 /* Check if the socket has already been accepted by the\r
3521                                                 owner.  If not, it is useless to return it from a\r
3522                                                 select(). */\r
3523                                                 BaseType_t bAccepted = pdFALSE;\r
3524 \r
3525                                                 if( pxSocket->u.xTCP.bits.bPassQueued == pdFALSE_UNSIGNED )\r
3526                                                 {\r
3527                                                         if( pxSocket->u.xTCP.bits.bPassAccept == pdFALSE_UNSIGNED )\r
3528                                                         {\r
3529                                                                 bAccepted = pdTRUE;\r
3530                                                         }\r
3531                                                 }\r
3532 \r
3533                                                 /* Is the set owner interested in READ events? */\r
3534                                                 if( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 )\r
3535                                                 {\r
3536                                                         if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN )\r
3537                                                         {\r
3538                                                                 if( ( pxSocket->u.xTCP.pxPeerSocket != NULL ) && ( pxSocket->u.xTCP.pxPeerSocket->u.xTCP.bits.bPassAccept != 0 ) )\r
3539                                                                 {\r
3540                                                                         xSocketBits |= eSELECT_READ;\r
3541                                                                 }\r
3542                                                         }\r
3543                                                         else if( ( pxSocket->u.xTCP.bits.bReuseSocket != pdFALSE_UNSIGNED ) && ( pxSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED ) )\r
3544                                                         {\r
3545                                                                 /* This socket has the re-use flag. After connecting it turns into\r
3546                                                                 aconnected socket. Set the READ event, so that accept() will be called. */\r
3547                                                                 xSocketBits |= eSELECT_READ;\r
3548                                                         }\r
3549                                                         else if( ( bAccepted != 0 ) && ( FreeRTOS_recvcount( pxSocket ) > 0 ) )\r
3550                                                         {\r
3551                                                                 xSocketBits |= eSELECT_READ;\r
3552                                                         }\r
3553                                                 }\r
3554                                                 /* Is the set owner interested in EXCEPTION events? */\r
3555                                                 if( ( pxSocket->xSelectBits & eSELECT_EXCEPT ) != 0 )\r
3556                                                 {\r
3557                                                         if( ( pxSocket->u.xTCP.ucTCPState == eCLOSE_WAIT ) || ( pxSocket->u.xTCP.ucTCPState == eCLOSED ) )\r
3558                                                         {\r
3559                                                                 xSocketBits |= eSELECT_EXCEPT;\r
3560                                                         }\r
3561                                                 }\r
3562 \r
3563                                                 /* Is the set owner interested in WRITE events? */\r
3564                                                 if( ( pxSocket->xSelectBits & eSELECT_WRITE ) != 0 )\r
3565                                                 {\r
3566                                                         BaseType_t bMatch = pdFALSE;\r
3567 \r
3568                                                         if( bAccepted != 0 )\r
3569                                                         {\r
3570                                                                 if( FreeRTOS_tx_space( pxSocket ) > 0 )\r
3571                                                                 {\r
3572                                                                         bMatch = pdTRUE;\r
3573                                                                 }\r
3574                                                         }\r
3575 \r
3576                                                         if( bMatch == pdFALSE )\r
3577                                                         {\r
3578                                                                 if( ( pxSocket->u.xTCP.bits.bConnPrepared != pdFALSE_UNSIGNED ) &&\r
3579                                                                         ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) &&\r
3580                                                                         ( pxSocket->u.xTCP.bits.bConnPassed == pdFALSE_UNSIGNED ) )\r
3581                                                                 {\r
3582                                                                         pxSocket->u.xTCP.bits.bConnPassed = pdTRUE_UNSIGNED;\r
3583                                                                         bMatch = pdTRUE;\r
3584                                                                 }\r
3585                                                         }\r
3586 \r
3587                                                         if( bMatch != pdFALSE )\r
3588                                                         {\r
3589                                                                 xSocketBits |= eSELECT_WRITE;\r
3590                                                         }\r
3591                                                 }\r
3592                                         }\r
3593                                         else\r
3594                                 #endif /* ipconfigUSE_TCP == 1 */\r
3595                                 {\r
3596                                         /* Select events for UDP are simpler. */\r
3597                                         if( ( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 ) &&\r
3598                                                 ( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) > 0U ) )\r
3599                                         {\r
3600                                                 xSocketBits |= eSELECT_READ;\r
3601                                         }\r
3602                                         /* The WRITE and EXCEPT bits are not used for UDP */\r
3603                                 }       /* if( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP ) */\r
3604 \r
3605                                 /* Each socket keeps its own event flags, which are looked-up\r
3606                                 by FreeRTOS_FD_ISSSET() */\r
3607                                 pxSocket->xSocketBits = xSocketBits;\r
3608 \r
3609                                 /* The ORed value will be used to set the bits in the event\r
3610                                 group. */\r
3611                                 xGroupBits |= xSocketBits;\r
3612 \r
3613                         }       /* for( pxIterator ... ) */\r
3614                 }       /* for( xRound = 0; xRound <= xLastRound; xRound++ ) */\r
3615 \r
3616                 xBitsToClear = xEventGroupGetBits( pxSocketSet->xSelectGroup );\r
3617 \r
3618                 /* Now set the necessary bits. */\r
3619                 xBitsToClear = ( xBitsToClear & ~xGroupBits ) & eSELECT_ALL;\r
3620 \r
3621                 #if( ipconfigSUPPORT_SIGNALS != 0 )\r
3622                 {\r
3623                         /* Maybe the socketset was signalled, but don't\r
3624                         clear the 'eSELECT_INTR' bit here, as it will be used\r
3625                         and cleared in FreeRTOS_select(). */\r
3626                         xBitsToClear &= ( EventBits_t ) ~eSELECT_INTR;\r
3627                 }\r
3628                 #endif /* ipconfigSUPPORT_SIGNALS */\r
3629 \r
3630                 if( xBitsToClear != 0 )\r
3631                 {\r
3632                         xEventGroupClearBits( pxSocketSet->xSelectGroup, xBitsToClear );\r
3633                 }\r
3634 \r
3635                 /* Now include eSELECT_CALL_IP to wakeup the caller. */\r
3636                 xEventGroupSetBits( pxSocketSet->xSelectGroup, xGroupBits | eSELECT_CALL_IP );\r
3637         }\r
3638 \r
3639 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */\r
3640 /*-----------------------------------------------------------*/\r
3641 \r
3642 #if( ipconfigSUPPORT_SIGNALS != 0 )\r
3643 \r
3644         /* Send a signal to the task which reads from this socket. */\r
3645         BaseType_t FreeRTOS_SignalSocket( Socket_t xSocket )\r
3646         {\r
3647         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
3648         BaseType_t xReturn;\r
3649 \r
3650                 if( pxSocket == NULL )\r
3651                 {\r
3652                         xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
3653                 }\r
3654                 else\r
3655         #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
3656                 if( ( pxSocket->pxSocketSet != NULL ) && ( pxSocket->pxSocketSet->xSelectGroup != NULL ) )\r
3657                 {\r
3658                         xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, eSELECT_INTR );\r
3659                         xReturn = 0;\r
3660                 }\r
3661                 else\r
3662         #endif /* ipconfigSUPPORT_SELECT_FUNCTION */\r
3663                 if( pxSocket->xEventGroup != NULL )\r
3664                 {\r
3665                         xEventGroupSetBits( pxSocket->xEventGroup, eSOCKET_INTR );\r
3666                         xReturn = 0;\r
3667                 }\r
3668                 else\r
3669                 {\r
3670                         xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
3671                 }\r
3672 \r
3673                 return xReturn;\r
3674         }\r
3675 \r
3676 #endif /* ipconfigSUPPORT_SIGNALS */\r
3677 /*-----------------------------------------------------------*/\r
3678 \r
3679 #if( ipconfigSUPPORT_SIGNALS != 0 )\r
3680 \r
3681         /* Send a signal to the task which reads from this socket (FromISR version). */\r
3682         BaseType_t FreeRTOS_SignalSocketFromISR( Socket_t xSocket, BaseType_t *pxHigherPriorityTaskWoken )\r
3683         {\r
3684         FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
3685         BaseType_t xReturn;\r
3686         IPStackEvent_t xEvent;\r
3687         extern QueueHandle_t xNetworkEventQueue;\r
3688 \r
3689                 configASSERT( pxSocket != NULL );\r
3690                 configASSERT( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP );\r
3691                 configASSERT( pxSocket->xEventGroup );\r
3692 \r
3693                 xEvent.eEventType = eSocketSignalEvent;\r
3694                 xEvent.pvData = ( void * )pxSocket;\r
3695 \r
3696                 /* The IP-task will call FreeRTOS_SignalSocket for this socket. */\r
3697                 xReturn = xQueueSendToBackFromISR( xNetworkEventQueue, &xEvent, pxHigherPriorityTaskWoken );\r
3698 \r
3699                 return xReturn;\r
3700         }\r
3701 \r
3702 #endif /* ipconfigSUPPORT_SIGNALS */\r
3703 /*-----------------------------------------------------------*/\r