]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_Sockets.c
Update version number in readiness for V10.3.0 release. Sync SVN with reviewed releas...
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-TCP / FreeRTOS_Sockets.c
index e15834849ef2dd590f8671223d17e3d639a13dc8..87099ecf15abf9076bfb92609ed49a83ea6632e3 100644 (file)
-/*\r
- * FreeRTOS+TCP V2.2.0\r
- * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
- *\r
- * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
- * this software and associated documentation files (the "Software"), to deal in\r
- * the Software without restriction, including without limitation the rights to\r
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
- * the Software, and to permit persons to whom the Software is furnished to do so,\r
- * subject to the following conditions:\r
- *\r
- * The above copyright notice and this permission notice shall be included in all\r
- * copies or substantial portions of the Software.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
- *\r
- * http://aws.amazon.com/freertos\r
- * http://www.FreeRTOS.org\r
- */\r
-\r
-/* Standard includes. */\r
-#include <stdint.h>\r
-#include <stdio.h>\r
-\r
-/* FreeRTOS includes. */\r
-#include "FreeRTOS.h"\r
-#include "task.h"\r
-#include "queue.h"\r
-#include "semphr.h"\r
-\r
-/* FreeRTOS+TCP includes. */\r
-#include "FreeRTOS_UDP_IP.h"\r
-#include "FreeRTOS_IP.h"\r
-#include "FreeRTOS_Sockets.h"\r
-#include "FreeRTOS_IP_Private.h"\r
-#include "FreeRTOS_DNS.h"\r
-#include "NetworkBufferManagement.h"\r
-\r
-/* The ItemValue of the sockets xBoundSocketListItem member holds the socket's\r
-port number. */\r
-#define socketSET_SOCKET_PORT( pxSocket, usPort ) listSET_LIST_ITEM_VALUE( ( &( ( pxSocket )->xBoundSocketListItem ) ), ( usPort ) )\r
-#define socketGET_SOCKET_PORT( pxSocket ) listGET_LIST_ITEM_VALUE( ( &( ( pxSocket )->xBoundSocketListItem ) ) )\r
-\r
-/* Test if a socket it bound which means it is either included in\r
-xBoundUDPSocketsList or xBoundTCPSocketsList */\r
-#define socketSOCKET_IS_BOUND( pxSocket )        ( listLIST_ITEM_CONTAINER( & ( pxSocket )->xBoundSocketListItem ) != NULL )\r
-\r
-/* If FreeRTOS_sendto() is called on a socket that is not bound to a port\r
-number then, depending on the FreeRTOSIPConfig.h settings, it might be that a\r
-port number is automatically generated for the socket.  Automatically generated\r
-port numbers will be between socketAUTO_PORT_ALLOCATION_START_NUMBER and\r
-0xffff.\r
-\r
-Per https://tools.ietf.org/html/rfc6056, "the dynamic ports consist of the range\r
-49152-65535. However, ephemeral port selection algorithms should use the whole\r
-range 1024-65535" excluding those already in use (inbound or outbound). */\r
-#if !defined( socketAUTO_PORT_ALLOCATION_START_NUMBER )\r
-       #define socketAUTO_PORT_ALLOCATION_START_NUMBER ( ( uint16_t ) 0x0400 )\r
-#endif\r
-\r
-#define socketAUTO_PORT_ALLOCATION_MAX_NUMBER   ( ( uint16_t ) 0xffff )\r
-\r
-/* The number of octets that make up an IP address. */\r
-#define socketMAX_IP_ADDRESS_OCTETS            4u\r
-\r
-/* A block time of 0 simply means "don't block". */\r
-#define socketDONT_BLOCK                               ( ( TickType_t ) 0 )\r
-\r
-#if( ( ipconfigUSE_TCP == 1 ) && !defined( ipTCP_TIMER_PERIOD_MS ) )\r
-       #define ipTCP_TIMER_PERIOD_MS   ( 1000 )\r
-#endif\r
-\r
-/* The next private port number to use when binding a client socket is stored in\r
-the usNextPortToUse[] array - which has either 1 or two indexes depending on\r
-whether TCP is being supported. */\r
-#if( ipconfigUSE_TCP == 1 )\r
-       #define socketPROTOCOL_COUNT            2\r
-#else\r
-       #define socketPROTOCOL_COUNT            1\r
-#endif\r
-\r
-/* Indexes into the usNextPortToUse[] array for UDP and TCP sockets\r
-respectively. */\r
-#define socketNEXT_UDP_PORT_NUMBER_INDEX       0\r
-#define socketNEXT_TCP_PORT_NUMBER_INDEX       1\r
-\r
-/* Some helper macro's for defining the 20/80 % limits of uxLittleSpace / uxEnoughSpace. */\r
-#define sock20_PERCENT                                         20\r
-#define sock80_PERCENT                                         80\r
-#define sock100_PERCENT                                                100\r
-\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-/*\r
- * Allocate the next port number from the private allocation range.\r
- * TCP and UDP each have their own series of port numbers\r
- * ulProtocol is either ipPROTOCOL_UDP or ipPROTOCOL_TCP\r
- */\r
-static uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol );\r
-\r
-/*\r
- * Return the list item from within pxList that has an item value of\r
- * xWantedItemValue.  If there is no such list item return NULL.\r
- */\r
-static const ListItem_t * pxListFindListItemWithValue( const List_t *pxList, TickType_t xWantedItemValue );\r
-\r
-/*\r
- * Return pdTRUE only if pxSocket is valid and bound, as far as can be\r
- * determined.\r
- */\r
-static BaseType_t prvValidSocket( FreeRTOS_Socket_t *pxSocket, BaseType_t xProtocol, BaseType_t xIsBound );\r
-\r
-/*\r
- * Before creating a socket, check the validity of the parameters used\r
- * and find the size of the socket space, which is different for UDP and TCP\r
- */\r
-static BaseType_t prvDetermineSocketSize( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol, size_t *pxSocketSize );\r
-\r
-#if( ipconfigUSE_TCP == 1 )\r
-       /*\r
-        * Create a txStream or a rxStream, depending on the parameter 'xIsInputStream'\r
-        */\r
-       static StreamBuffer_t *prvTCPCreateStream (FreeRTOS_Socket_t *pxSocket, BaseType_t xIsInputStream );\r
-#endif /* ipconfigUSE_TCP == 1 */\r
-\r
-#if( ipconfigUSE_TCP == 1 )\r
-       /*\r
-        * Called from FreeRTOS_send(): some checks which will be done before\r
-        * sending a TCP packed.\r
-        */\r
-       static int32_t prvTCPSendCheck( FreeRTOS_Socket_t *pxSocket, size_t xDataLength );\r
-#endif /* ipconfigUSE_TCP */\r
-\r
-#if( ipconfigUSE_TCP == 1 )\r
-       /*\r
-        * When a child socket gets closed, make sure to update the child-count of the parent\r
-        */\r
-       static void prvTCPSetSocketCount( FreeRTOS_Socket_t *pxSocketToDelete );\r
-#endif  /* ipconfigUSE_TCP == 1 */\r
-\r
-#if( ipconfigUSE_TCP == 1 )\r
-       /*\r
-        * Called from FreeRTOS_connect(): make some checks and if allowed, send a\r
-        * message to the IP-task to start connecting to a remote socket\r
-        */\r
-       static BaseType_t prvTCPConnectStart( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr *pxAddress );\r
-#endif /* ipconfigUSE_TCP */\r
-\r
-#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
-\r
-       /* Executed by the IP-task, it will check all sockets belonging to a set */\r
-       static FreeRTOS_Socket_t *prvFindSelectedSocket( SocketSelect_t *pxSocketSet );\r
-\r
-#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */\r
-/*-----------------------------------------------------------*/\r
-\r
-/* The list that contains mappings between sockets and port numbers.  Accesses\r
-to this list must be protected by critical sections of one kind or another. */\r
-List_t xBoundUDPSocketsList;\r
-\r
-#if ipconfigUSE_TCP == 1\r
-       List_t xBoundTCPSocketsList;\r
-#endif /* ipconfigUSE_TCP == 1 */\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-static BaseType_t prvValidSocket( FreeRTOS_Socket_t *pxSocket, BaseType_t xProtocol, BaseType_t xIsBound )\r
-{\r
-BaseType_t xReturn = pdTRUE;\r
-\r
-       if( ( pxSocket == NULL ) || ( pxSocket == FREERTOS_INVALID_SOCKET ) )\r
-       {\r
-               xReturn = pdFALSE;\r
-       }\r
-       else if( ( xIsBound != pdFALSE ) && ( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE ) )\r
-       {\r
-               /* The caller expects the socket to be bound, but it isn't. */\r
-               xReturn = pdFALSE;\r
-       }\r
-       else if( pxSocket->ucProtocol != ( uint8_t ) xProtocol )\r
-       {\r
-               /* Socket has a wrong type (UDP != TCP). */\r
-               xReturn = pdFALSE;\r
-       }\r
-\r
-       return xReturn;\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-BaseType_t vNetworkSocketsInit( void )\r
-{\r
-       vListInitialise( &xBoundUDPSocketsList );\r
-\r
-       #if( ipconfigUSE_TCP == 1 )\r
-       {\r
-               vListInitialise( &xBoundTCPSocketsList );\r
-       }\r
-       #endif  /* ipconfigUSE_TCP == 1 */\r
-\r
-       return pdTRUE;\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-static BaseType_t prvDetermineSocketSize( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol, size_t *pxSocketSize )\r
-{\r
-BaseType_t xReturn = pdPASS;\r
-FreeRTOS_Socket_t *pxSocket;\r
-\r
-       /* Asserts must not appear before it has been determined that the network\r
-       task is ready - otherwise the asserts will fail. */\r
-       if( xIPIsNetworkTaskReady() == pdFALSE )\r
-       {\r
-               xReturn = pdFAIL;\r
-       }\r
-       else\r
-       {\r
-               /* Only Ethernet is currently supported. */\r
-               configASSERT( xDomain == FREERTOS_AF_INET );\r
-\r
-               /* Check if the UDP socket-list has been initialised. */\r
-               configASSERT( listLIST_IS_INITIALISED( &xBoundUDPSocketsList ) );\r
-               #if( ipconfigUSE_TCP == 1 )\r
-               {\r
-                       /* Check if the TCP socket-list has been initialised. */\r
-                       configASSERT( listLIST_IS_INITIALISED( &xBoundTCPSocketsList ) );\r
-               }\r
-               #endif  /* ipconfigUSE_TCP == 1 */\r
-\r
-               if( xProtocol == FREERTOS_IPPROTO_UDP )\r
-               {\r
-                       if( xType != FREERTOS_SOCK_DGRAM )\r
-                       {\r
-                               xReturn = pdFAIL;\r
-                               configASSERT( xReturn );\r
-                       }\r
-                       /* In case a UDP socket is created, do not allocate space for TCP data. */\r
-                       *pxSocketSize = ( sizeof( *pxSocket ) - sizeof( pxSocket->u ) ) + sizeof( pxSocket->u.xUDP );\r
-               }\r
-#if( ipconfigUSE_TCP == 1 )\r
-               else if( xProtocol == FREERTOS_IPPROTO_TCP )\r
-               {\r
-                       if( xType != FREERTOS_SOCK_STREAM )\r
-                       {\r
-                               xReturn = pdFAIL;\r
-                               configASSERT( xReturn );\r
-                       }\r
-\r
-                       *pxSocketSize = ( sizeof( *pxSocket ) - sizeof( pxSocket->u ) ) + sizeof( pxSocket->u.xTCP );\r
-               }\r
-#endif  /* ipconfigUSE_TCP == 1 */\r
-               else\r
-               {\r
-                       xReturn = pdFAIL;\r
-                       configASSERT( xReturn );\r
-               }\r
-       }\r
-       /* In case configASSERT() is not used */\r
-       ( void )xDomain;\r
-       return xReturn;\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-/* FreeRTOS_socket() allocates and initiates a socket */\r
-Socket_t FreeRTOS_socket( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol )\r
-{\r
-FreeRTOS_Socket_t *pxSocket;\r
-size_t uxSocketSize;\r
-EventGroupHandle_t xEventGroup;\r
-Socket_t xReturn;\r
-\r
-       if( prvDetermineSocketSize( xDomain, xType, xProtocol, &uxSocketSize ) == pdFAIL )\r
-       {\r
-               xReturn = FREERTOS_INVALID_SOCKET;\r
-       }\r
-       else\r
-       {\r
-               /* Allocate the structure that will hold the socket information.  The\r
-               size depends on the type of socket: UDP sockets need less space.  A\r
-               define 'pvPortMallocSocket' will used to allocate the necessary space.\r
-               By default it points to the FreeRTOS function 'pvPortMalloc()'. */\r
-               pxSocket = ( FreeRTOS_Socket_t * ) pvPortMallocSocket( uxSocketSize );\r
-\r
-               if( pxSocket == NULL )\r
-               {\r
-                       pxSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;\r
-                       iptraceFAILED_TO_CREATE_SOCKET();\r
-               }\r
-               else if( ( xEventGroup = xEventGroupCreate() ) == NULL )\r
-               {\r
-                       vPortFreeSocket( pxSocket );\r
-                       pxSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;\r
-                       iptraceFAILED_TO_CREATE_EVENT_GROUP();\r
-               }\r
-               else\r
-               {\r
-                       /* Clear the entire space to avoid nulling individual entries */\r
-                       memset( pxSocket, '\0', uxSocketSize );\r
-\r
-                       pxSocket->xEventGroup = xEventGroup;\r
-\r
-                       /* Initialise the socket's members.  The semaphore will be created\r
-                       if the socket is bound to an address, for now the pointer to the\r
-                       semaphore is just set to NULL to show it has not been created. */\r
-                       if( xProtocol == FREERTOS_IPPROTO_UDP )\r
-                       {\r
-                               vListInitialise( &( pxSocket->u.xUDP.xWaitingPacketsList ) );\r
-\r
-                               #if( ipconfigUDP_MAX_RX_PACKETS > 0 )\r
-                               {\r
-                                       pxSocket->u.xUDP.uxMaxPackets = ( UBaseType_t ) ipconfigUDP_MAX_RX_PACKETS;\r
-                               }\r
-                               #endif /* ipconfigUDP_MAX_RX_PACKETS > 0 */\r
-                       }\r
-\r
-                       vListInitialiseItem( &( pxSocket->xBoundSocketListItem ) );\r
-                       listSET_LIST_ITEM_OWNER( &( pxSocket->xBoundSocketListItem ), ( void * ) pxSocket );\r
-\r
-                       pxSocket->xReceiveBlockTime = ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME;\r
-                       pxSocket->xSendBlockTime        = ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME;\r
-                       pxSocket->ucSocketOptions   = ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT;\r
-                       pxSocket->ucProtocol            = ( uint8_t ) xProtocol; /* protocol: UDP or TCP */\r
-\r
-                       #if( ipconfigUSE_TCP == 1 )\r
-                       {\r
-                               if( xProtocol == FREERTOS_IPPROTO_TCP )\r
-                               {\r
-                                       /* StreamSize is expressed in number of bytes */\r
-                                       /* Round up buffer sizes to nearest multiple of MSS */\r
-                                       pxSocket->u.xTCP.usInitMSS      = pxSocket->u.xTCP.usCurMSS = ipconfigTCP_MSS;\r
-                                       pxSocket->u.xTCP.uxRxStreamSize = ( size_t ) ipconfigTCP_RX_BUFFER_LENGTH;\r
-                                       pxSocket->u.xTCP.uxTxStreamSize = ( size_t ) FreeRTOS_round_up( ipconfigTCP_TX_BUFFER_LENGTH, ipconfigTCP_MSS );\r
-                                       /* Use half of the buffer size of the TCP windows */\r
-                                       #if ( ipconfigUSE_TCP_WIN == 1 )\r
-                                       {\r
-                                               pxSocket->u.xTCP.uxRxWinSize  = FreeRTOS_max_uint32( 1UL, ( uint32_t ) ( pxSocket->u.xTCP.uxRxStreamSize / 2 ) / ipconfigTCP_MSS );\r
-                                               pxSocket->u.xTCP.uxTxWinSize  = FreeRTOS_max_uint32( 1UL, ( uint32_t ) ( pxSocket->u.xTCP.uxTxStreamSize / 2 ) / ipconfigTCP_MSS );\r
-                                       }\r
-                                       #else\r
-                                       {\r
-                                               pxSocket->u.xTCP.uxRxWinSize  = 1u;\r
-                                               pxSocket->u.xTCP.uxTxWinSize  = 1u;\r
-                                       }\r
-                                       #endif\r
-                                       /* The above values are just defaults, and can be overridden by\r
-                                       calling FreeRTOS_setsockopt().  No buffers will be allocated until a\r
-                                       socket is connected and data is exchanged. */\r
-                               }\r
-                       }\r
-                       #endif  /* ipconfigUSE_TCP == 1 */\r
-               }\r
-\r
-               xReturn = ( Socket_t ) pxSocket;\r
-       }\r
-\r
-       /* Remove compiler warnings in the case the configASSERT() is not defined. */\r
-       ( void ) xDomain;\r
-\r
-       return xReturn;\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
-\r
-       SocketSet_t FreeRTOS_CreateSocketSet( void )\r
-       {\r
-       SocketSelect_t *pxSocketSet;\r
-\r
-               pxSocketSet = ( SocketSelect_t * ) pvPortMalloc( sizeof( *pxSocketSet ) );\r
-\r
-               if( pxSocketSet != NULL )\r
-               {\r
-                       memset( pxSocketSet, '\0', sizeof( *pxSocketSet ) );\r
-                       pxSocketSet->xSelectGroup = xEventGroupCreate();\r
-\r
-                       if( pxSocketSet->xSelectGroup == NULL )\r
-                       {\r
-                               vPortFree( ( void* ) pxSocketSet );\r
-                               pxSocketSet = NULL;\r
-                       }\r
-               }\r
-\r
-               return ( SocketSet_t ) pxSocketSet;\r
-       }\r
-\r
-#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
-\r
-       void FreeRTOS_DeleteSocketSet( SocketSet_t xSocketSet )\r
-       {\r
-               SocketSelect_t *pxSocketSet = ( SocketSelect_t*) xSocketSet;\r
-\r
-               vEventGroupDelete( pxSocketSet->xSelectGroup );\r
-               vPortFree( ( void* ) pxSocketSet );\r
-       }\r
-\r
-#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
-\r
-       /* Add a socket to a set */\r
-       void FreeRTOS_FD_SET( Socket_t xSocket, SocketSet_t xSocketSet, EventBits_t xSelectBits )\r
-       {\r
-       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
-       SocketSelect_t *pxSocketSet = ( SocketSelect_t * ) xSocketSet;\r
-\r
-               configASSERT( pxSocket != NULL );\r
-               configASSERT( xSocketSet != NULL );\r
-\r
-               /* Make sure we're not adding bits which are reserved for internal use,\r
-               such as eSELECT_CALL_IP */\r
-               pxSocket->xSelectBits |= ( xSelectBits & eSELECT_ALL );\r
-\r
-               if( ( pxSocket->xSelectBits & eSELECT_ALL ) != 0 )\r
-               {\r
-                       /* Adding a socket to a socket set. */\r
-                       pxSocket->pxSocketSet = ( SocketSelect_t * ) xSocketSet;\r
-\r
-                       /* Now have the IP-task call vSocketSelect() to see if the set contains\r
-                       any sockets which are 'ready' and set the proper bits.\r
-                       By setting 'bApiCalled = false', vSocketSelect() knows that it was\r
-                       not called from a user API */\r
-                       pxSocketSet->bApiCalled = pdFALSE;\r
-                       prvFindSelectedSocket( pxSocketSet );\r
-               }\r
-       }\r
-\r
-#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
-       /* Clear select bits for a socket\r
-       If the mask becomes 0, remove the socket from the set */\r
-       void FreeRTOS_FD_CLR( Socket_t xSocket, SocketSet_t xSocketSet, EventBits_t xSelectBits )\r
-       {\r
-       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
-\r
-               configASSERT( pxSocket != NULL );\r
-               configASSERT( xSocketSet != NULL );\r
-\r
-               pxSocket->xSelectBits &= ~( xSelectBits & eSELECT_ALL );\r
-               if( ( pxSocket->xSelectBits & eSELECT_ALL ) != 0 )\r
-               {\r
-                       pxSocket->pxSocketSet = ( SocketSelect_t *)xSocketSet;\r
-               }\r
-               else\r
-               {\r
-                       /* disconnect it from the socket set */\r
-                       pxSocket->pxSocketSet = ( SocketSelect_t *)NULL;\r
-               }\r
-       }\r
-\r
-#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */\r
-/*-----------------------------------------------------------*/\r
-\r
-\r
-#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
-\r
-       /* Test if a socket belongs to a socket-set */\r
-       EventBits_t FreeRTOS_FD_ISSET( Socket_t xSocket, SocketSet_t xSocketSet )\r
-       {\r
-       EventBits_t xReturn;\r
-       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
-\r
-               configASSERT( pxSocket != NULL );\r
-               configASSERT( xSocketSet != NULL );\r
-\r
-               if( xSocketSet == ( SocketSet_t ) pxSocket->pxSocketSet )\r
-               {\r
-                       /* Make sure we're not adding bits which are reserved for internal\r
-                       use. */\r
-                       xReturn = pxSocket->xSocketBits & eSELECT_ALL;\r
-               }\r
-               else\r
-               {\r
-                       xReturn = 0;\r
-               }\r
-\r
-               return xReturn;\r
-       }\r
-\r
-#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
-\r
-       /* The select() statement: wait for an event to occur on any of the sockets\r
-       included in a socket set */\r
-       BaseType_t FreeRTOS_select( SocketSet_t xSocketSet, TickType_t xBlockTimeTicks )\r
-       {\r
-       TimeOut_t xTimeOut;\r
-       TickType_t xRemainingTime;\r
-       SocketSelect_t *pxSocketSet = ( SocketSelect_t*) xSocketSet;\r
-       BaseType_t xResult;\r
-\r
-               configASSERT( xSocketSet != NULL );\r
-\r
-               /* Only in the first round, check for non-blocking */\r
-               xRemainingTime = xBlockTimeTicks;\r
-\r
-               /* Fetch the current time */\r
-               vTaskSetTimeOutState( &xTimeOut );\r
-\r
-               for( ;; )\r
-               {\r
-                       /* Find a socket which might have triggered the bit\r
-                       This function might return immediately or block for a limited time */\r
-                       xResult = ( BaseType_t ) xEventGroupWaitBits( pxSocketSet->xSelectGroup, eSELECT_ALL, pdFALSE, pdFALSE, xRemainingTime );\r
-\r
-                       #if( ipconfigSUPPORT_SIGNALS != 0 )\r
-                       {\r
-                               if( ( xResult & eSELECT_INTR ) != 0u )\r
-                               {\r
-                                       xEventGroupClearBits( pxSocketSet->xSelectGroup, eSELECT_INTR );\r
-                                       FreeRTOS_debug_printf( ( "FreeRTOS_select: interrupted\n" ) );\r
-                                       break;\r
-                               }\r
-                       }\r
-                       #endif /* ipconfigSUPPORT_SIGNALS */\r
-\r
-                       /* Have the IP-task find the socket which had an event */\r
-                       pxSocketSet->bApiCalled = pdTRUE;\r
-                       prvFindSelectedSocket( pxSocketSet );\r
-\r
-                       xResult = ( BaseType_t ) xEventGroupGetBits( pxSocketSet->xSelectGroup );\r
-\r
-                       if( xResult != 0 )\r
-                       {\r
-                               break;\r
-                       }\r
-\r
-                       /* Has the timeout been reached? */\r
-                       if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )\r
-                       {\r
-                               break;\r
-                       }\r
-               }\r
-\r
-               return xResult;\r
-       }\r
-\r
-#endif /* ipconfigSUPPORT_SELECT_FUNCTION */\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
-\r
-       /* Send a message to the IP-task to have it check all sockets belonging to\r
-       'pxSocketSet' */\r
-       static FreeRTOS_Socket_t *prvFindSelectedSocket( SocketSelect_t *pxSocketSet )\r
-       {\r
-       IPStackEvent_t xSelectEvent;\r
-       FreeRTOS_Socket_t *xReturn;\r
-\r
-               xSelectEvent.eEventType = eSocketSelectEvent;\r
-               xSelectEvent.pvData = ( void * ) pxSocketSet;\r
-\r
-               /* while the IP-task works on the request, the API will block on\r
-               'eSELECT_CALL_IP'.  So clear it first. */\r
-               xEventGroupClearBits( pxSocketSet->xSelectGroup, eSELECT_CALL_IP );\r
-\r
-               /* Now send the socket select event */\r
-               if( xSendEventStructToIPTask( &xSelectEvent, ( TickType_t ) portMAX_DELAY ) == pdFAIL )\r
-               {\r
-                       /* Oops, we failed to wake-up the IP task. No use to wait for it. */\r
-                       FreeRTOS_debug_printf( ( "prvFindSelectedSocket: failed\n" ) );\r
-                       xReturn = NULL;\r
-               }\r
-               else\r
-               {\r
-                       /* As soon as the IP-task is ready, it will set 'eSELECT_CALL_IP' to\r
-                       wakeup the calling API */\r
-                       xEventGroupWaitBits( pxSocketSet->xSelectGroup, eSELECT_CALL_IP, pdTRUE, pdFALSE, portMAX_DELAY );\r
-\r
-                       /* Return 'pxSocket' which is set by the IP-task */\r
-                       xReturn = pxSocketSet->pxSocket;\r
-               }\r
-\r
-               return xReturn;\r
-       }\r
-\r
-#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */\r
-/*-----------------------------------------------------------*/\r
-\r
-/*\r
- * FreeRTOS_recvfrom: receive data from a bound socket\r
- * In this library, the function can only be used with connectionsless sockets\r
- * (UDP)\r
- */\r
-int32_t FreeRTOS_recvfrom( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags, struct freertos_sockaddr *pxSourceAddress, socklen_t *pxSourceAddressLength )\r
-{\r
-BaseType_t lPacketCount = 0;\r
-NetworkBufferDescriptor_t *pxNetworkBuffer;\r
-FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
-TickType_t xRemainingTime = ( TickType_t ) 0; /* Obsolete assignment, but some compilers output a warning if its not done. */\r
-BaseType_t xTimed = pdFALSE;\r
-TimeOut_t xTimeOut;\r
-int32_t lReturn;\r
-EventBits_t xEventBits = ( EventBits_t ) 0;\r
-\r
-       if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_UDP, pdTRUE ) == pdFALSE )\r
-       {\r
-               return -pdFREERTOS_ERRNO_EINVAL;\r
-       }\r
-\r
-       lPacketCount = ( BaseType_t ) listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) );\r
-\r
-       /* The function prototype is designed to maintain the expected Berkeley\r
-       sockets standard, but this implementation does not use all the parameters. */\r
-       ( void ) pxSourceAddressLength;\r
-\r
-       while( lPacketCount == 0 )\r
-       {\r
-               if( xTimed == pdFALSE )\r
-               {\r
-                       /* Check to see if the socket is non blocking on the first\r
-                       iteration.  */\r
-                       xRemainingTime = pxSocket->xReceiveBlockTime;\r
-\r
-                       if( xRemainingTime == ( TickType_t ) 0 )\r
-                       {\r
-                               #if( ipconfigSUPPORT_SIGNALS != 0 )\r
-                               {\r
-                                       /* Just check for the interrupt flag. */\r
-                                       xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_INTR,\r
-                                               pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, socketDONT_BLOCK );\r
-                               }\r
-                               #endif /* ipconfigSUPPORT_SIGNALS */\r
-                               break;\r
-                       }\r
-\r
-                       if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )\r
-                       {\r
-                               break;\r
-                       }\r
-\r
-                       /* To ensure this part only executes once. */\r
-                       xTimed = pdTRUE;\r
-\r
-                       /* Fetch the current time. */\r
-                       vTaskSetTimeOutState( &xTimeOut );\r
-               }\r
-\r
-               /* Wait for arrival of data.  While waiting, the IP-task may set the\r
-               'eSOCKET_RECEIVE' bit in 'xEventGroup', if it receives data for this\r
-               socket, thus unblocking this API call. */\r
-               xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_RECEIVE | eSOCKET_INTR,\r
-                       pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );\r
-\r
-               #if( ipconfigSUPPORT_SIGNALS != 0 )\r
-               {\r
-                       if( ( xEventBits & eSOCKET_INTR ) != 0 )\r
-                       {\r
-                               if( ( xEventBits & eSOCKET_RECEIVE ) != 0 )\r
-                               {\r
-                                       /* Shouldn't have cleared the eSOCKET_RECEIVE flag. */\r
-                                       xEventGroupSetBits( pxSocket->xEventGroup, eSOCKET_RECEIVE );\r
-                               }\r
-                               break;\r
-                       }\r
-               }\r
-               #else\r
-               {\r
-                       ( void ) xEventBits;\r
-               }\r
-               #endif /* ipconfigSUPPORT_SIGNALS */\r
-\r
-               lPacketCount = ( BaseType_t ) listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) );\r
-\r
-               if( lPacketCount != 0 )\r
-               {\r
-                       break;\r
-               }\r
-\r
-               /* Has the timeout been reached ? */\r
-               if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) )\r
-               {\r
-                       break;\r
-               }\r
-       } /* while( lPacketCount == 0 ) */\r
-\r
-       if( lPacketCount != 0 )\r
-       {\r
-               taskENTER_CRITICAL();\r
-               {\r
-                       /* The owner of the list item is the network buffer. */\r
-                       pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &( pxSocket->u.xUDP.xWaitingPacketsList ) );\r
-\r
-                       if( ( xFlags & FREERTOS_MSG_PEEK ) == 0 )\r
-                       {\r
-                               /* Remove the network buffer from the list of buffers waiting to\r
-                               be processed by the socket. */\r
-                               uxListRemove( &( pxNetworkBuffer->xBufferListItem ) );\r
-                       }\r
-               }\r
-               taskEXIT_CRITICAL();\r
-\r
-               /* The returned value is the length of the payload data, which is\r
-               calculated at the total packet size minus the headers.\r
-               The validity of `xDataLength` prvProcessIPPacket has been confirmed\r
-               in 'prvProcessIPPacket()'. */\r
-               lReturn = ( int32_t ) ( pxNetworkBuffer->xDataLength - sizeof( UDPPacket_t ) );\r
-\r
-               if( pxSourceAddress != NULL )\r
-               {\r
-                       pxSourceAddress->sin_port = pxNetworkBuffer->usPort;\r
-                       pxSourceAddress->sin_addr = pxNetworkBuffer->ulIPAddress;\r
-               }\r
-\r
-               if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )\r
-               {\r
-                       /* The zero copy flag is not set.  Truncate the length if it won't\r
-                       fit in the provided buffer. */\r
-                       if( lReturn > ( int32_t ) xBufferLength )\r
-                       {\r
-                               iptraceRECVFROM_DISCARDING_BYTES( ( xBufferLength - lReturn ) );\r
-                               lReturn = ( int32_t )xBufferLength;\r
-                       }\r
-\r
-                       /* Copy the received data into the provided buffer, then release the\r
-                       network buffer. */\r
-                       memcpy( pvBuffer, ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ), ( size_t )lReturn );\r
-\r
-                       if( ( xFlags & FREERTOS_MSG_PEEK ) == 0 )\r
-                       {\r
-                               vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
-                       }\r
-               }\r
-               else\r
-               {\r
-                       /* The zero copy flag was set.  pvBuffer is not a buffer into which\r
-                       the received data can be copied, but a pointer that must be set to\r
-                       point to the buffer in which the received data has already been\r
-                       placed. */\r
-                       *( ( void** ) pvBuffer ) = ( void * ) ( &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ) );\r
-               }\r
-\r
-       }\r
-#if( ipconfigSUPPORT_SIGNALS != 0 )\r
-       else if( ( xEventBits & eSOCKET_INTR ) != 0 )\r
-       {\r
-               lReturn = -pdFREERTOS_ERRNO_EINTR;\r
-               iptraceRECVFROM_INTERRUPTED();\r
-       }\r
-#endif /* ipconfigSUPPORT_SIGNALS */\r
-       else\r
-       {\r
-               lReturn = -pdFREERTOS_ERRNO_EWOULDBLOCK;\r
-               iptraceRECVFROM_TIMEOUT();\r
-       }\r
-\r
-       return lReturn;\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-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
-{\r
-NetworkBufferDescriptor_t *pxNetworkBuffer;\r
-IPStackEvent_t xStackTxEvent = { eStackTxEvent, NULL };\r
-TimeOut_t xTimeOut;\r
-TickType_t xTicksToWait;\r
-int32_t lReturn = 0;\r
-FreeRTOS_Socket_t *pxSocket;\r
-\r
-       pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
-\r
-       /* The function prototype is designed to maintain the expected Berkeley\r
-       sockets standard, but this implementation does not use all the\r
-       parameters. */\r
-       ( void ) xDestinationAddressLength;\r
-       configASSERT( pvBuffer );\r
-\r
-       if( xTotalDataLength <= ( size_t ) ipMAX_UDP_PAYLOAD_LENGTH )\r
-       {\r
-               /* If the socket is not already bound to an address, bind it now.\r
-               Passing NULL as the address parameter tells FreeRTOS_bind() to select\r
-               the address to bind to. */\r
-               if( ( socketSOCKET_IS_BOUND( pxSocket ) != pdFALSE ) ||\r
-                       ( FreeRTOS_bind( xSocket, NULL, 0u ) == 0 ) )\r
-               {\r
-                       xTicksToWait = pxSocket->xSendBlockTime;\r
-\r
-                       #if( ipconfigUSE_CALLBACKS != 0 )\r
-                       {\r
-                               if( xIsCallingFromIPTask() != pdFALSE )\r
-                               {\r
-                                       /* If this send function is called from within a call-back\r
-                                       handler it may not block, otherwise chances would be big to\r
-                                       get a deadlock: the IP-task waiting for itself. */\r
-                                       xTicksToWait = ( TickType_t )0;\r
-                               }\r
-                       }\r
-                       #endif /* ipconfigUSE_CALLBACKS */\r
-\r
-                       if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )\r
-                       {\r
-                               xTicksToWait = ( TickType_t ) 0;\r
-                       }\r
-\r
-                       if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )\r
-                       {\r
-                               /* Zero copy is not set, so obtain a network buffer into\r
-                               which the payload will be copied. */\r
-                               vTaskSetTimeOutState( &xTimeOut );\r
-\r
-                               /* Block until a buffer becomes available, or until a\r
-                               timeout has been reached */\r
-                               pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( xTotalDataLength + sizeof( UDPPacket_t ), xTicksToWait );\r
-\r
-                               if( pxNetworkBuffer != NULL )\r
-                               {\r
-                                       memcpy( ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ), ( void * ) pvBuffer, xTotalDataLength );\r
-\r
-                                       if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdTRUE )\r
-                                       {\r
-                                               /* The entire block time has been used up. */\r
-                                               xTicksToWait = ( TickType_t ) 0;\r
-                                       }\r
-                               }\r
-                       }\r
-                       else\r
-                       {\r
-                               /* When zero copy is used, pvBuffer is a pointer to the\r
-                               payload of a buffer that has already been obtained from the\r
-                               stack.  Obtain the network buffer pointer from the buffer. */\r
-                               pxNetworkBuffer = pxUDPPayloadBuffer_to_NetworkBuffer( (void*)pvBuffer );\r
-                       }\r
-\r
-                       if( pxNetworkBuffer != NULL )\r
-                       {\r
-                               /* xDataLength is the size of the total packet, including the Ethernet header. */\r
-                               pxNetworkBuffer->xDataLength = xTotalDataLength + sizeof( UDPPacket_t );\r
-                               pxNetworkBuffer->usPort = pxDestinationAddress->sin_port;\r
-                               pxNetworkBuffer->usBoundPort = ( uint16_t ) socketGET_SOCKET_PORT( pxSocket );\r
-                               pxNetworkBuffer->ulIPAddress = pxDestinationAddress->sin_addr;\r
-\r
-                               /* The socket options are passed to the IP layer in the\r
-                               space that will eventually get used by the Ethernet header. */\r
-                               pxNetworkBuffer->pucEthernetBuffer[ ipSOCKET_OPTIONS_OFFSET ] = pxSocket->ucSocketOptions;\r
-\r
-                               /* Tell the networking task that the packet needs sending. */\r
-                               xStackTxEvent.pvData = pxNetworkBuffer;\r
-\r
-                               /* Ask the IP-task to send this packet */\r
-                               if( xSendEventStructToIPTask( &xStackTxEvent, xTicksToWait ) == pdPASS )\r
-                               {\r
-                                       /* The packet was successfully sent to the IP task. */\r
-                                       lReturn = ( int32_t ) xTotalDataLength;\r
-                                       #if( ipconfigUSE_CALLBACKS == 1 )\r
-                                       {\r
-                                               if( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xUDP.pxHandleSent ) )\r
-                                               {\r
-                                                       pxSocket->u.xUDP.pxHandleSent( ( Socket_t )pxSocket, xTotalDataLength );\r
-                                               }\r
-                                       }\r
-                                       #endif /* ipconfigUSE_CALLBACKS */\r
-                               }\r
-                               else\r
-                               {\r
-                                       /* If the buffer was allocated in this function, release\r
-                                       it. */\r
-                                       if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )\r
-                                       {\r
-                                               vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
-                                       }\r
-                                       iptraceSTACK_TX_EVENT_LOST( ipSTACK_TX_EVENT );\r
-                               }\r
-                       }\r
-                       else\r
-                       {\r
-                               /* If errno was available, errno would be set to\r
-                               FREERTOS_ENOPKTS.  As it is, the function must return the\r
-                               number of transmitted bytes, so the calling function knows\r
-                               how     much data was actually sent. */\r
-                               iptraceNO_BUFFER_FOR_SENDTO();\r
-                       }\r
-               }\r
-               else\r
-               {\r
-                       iptraceSENDTO_SOCKET_NOT_BOUND();\r
-               }\r
-       }\r
-       else\r
-       {\r
-               /* The data is longer than the available buffer space. */\r
-               iptraceSENDTO_DATA_TOO_LONG();\r
-       }\r
-\r
-       return lReturn;\r
-} /* Tested */\r
-/*-----------------------------------------------------------*/\r
-\r
-/*\r
- * FreeRTOS_bind() : binds a sockt to a local port number.  If port 0 is\r
- * provided, a system provided port number will be assigned.  This function can\r
- * be used for both UDP and TCP sockets.  The actual binding will be performed\r
- * by the IP-task to avoid mutual access to the bound-socket-lists\r
- * (xBoundUDPSocketsList or xBoundTCPSocketsList).\r
- */\r
-BaseType_t FreeRTOS_bind( Socket_t xSocket, struct freertos_sockaddr * pxAddress, socklen_t xAddressLength )\r
-{\r
-IPStackEvent_t xBindEvent;\r
-FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
-BaseType_t xReturn = 0;\r
-\r
-       ( void ) xAddressLength;\r
-\r
-       if( ( pxSocket == NULL ) || ( pxSocket == FREERTOS_INVALID_SOCKET ) )\r
-       {\r
-               xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
-       }\r
-       /* Once a socket is bound to a port, it can not be bound to a different\r
-       port number */\r
-       else if( socketSOCKET_IS_BOUND( pxSocket) != pdFALSE )\r
-       {\r
-               /* The socket is already bound. */\r
-               FreeRTOS_debug_printf( ( "vSocketBind: Socket already bound to %d\n", pxSocket->usLocalPort ) );\r
-               xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
-       }\r
-       else\r
-       {\r
-               /* Prepare a messages to the IP-task in order to perform the binding.\r
-               The desired port number will be passed in usLocalPort. */\r
-               xBindEvent.eEventType = eSocketBindEvent;\r
-               xBindEvent.pvData = ( void * ) xSocket;\r
-               if( pxAddress != NULL )\r
-               {\r
-                       pxSocket->usLocalPort = FreeRTOS_ntohs( pxAddress->sin_port );\r
-               }\r
-               else\r
-               {\r
-                       /* Caller wants to bind to a random port number. */\r
-                       pxSocket->usLocalPort = 0u;\r
-               }\r
-\r
-               /* portMAX_DELAY is used as a the time-out parameter, as binding *must*\r
-               succeed before the socket can be used.  _RB_ The use of an infinite\r
-               block time needs be changed as it could result in the task hanging. */\r
-               if( xSendEventStructToIPTask( &xBindEvent, ( TickType_t ) portMAX_DELAY ) == pdFAIL )\r
-               {\r
-                       /* Failed to wake-up the IP-task, no use to wait for it */\r
-                       FreeRTOS_debug_printf( ( "FreeRTOS_bind: send event failed\n" ) );\r
-                       xReturn = -pdFREERTOS_ERRNO_ECANCELED;\r
-               }\r
-               else\r
-               {\r
-                       /* The IP-task will set the 'eSOCKET_BOUND' bit when it has done its\r
-                       job. */\r
-                       xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_BOUND, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, portMAX_DELAY );\r
-                       if( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE )\r
-                       {\r
-                               xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
-                       }\r
-               }\r
-       }\r
-\r
-       return xReturn;\r
-}\r
-\r
-/*\r
- * vSocketBind(): internal version of bind() that should not be called directly.\r
- * 'xInternal' is used for TCP sockets only: it allows to have several\r
- * (connected) child sockets bound to the same server port.\r
- */\r
-BaseType_t vSocketBind( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr * pxAddress, size_t uxAddressLength, BaseType_t xInternal )\r
-{\r
-BaseType_t xReturn = 0; /* In Berkeley sockets, 0 means pass for bind(). */\r
-List_t *pxSocketList;\r
-#if( ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 )\r
-       struct freertos_sockaddr xAddress;\r
-#endif /* ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND */\r
-\r
-#if( ipconfigUSE_TCP == 1 )\r
-       if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
-       {\r
-               pxSocketList = &xBoundTCPSocketsList;\r
-       }\r
-       else\r
-#endif  /* ipconfigUSE_TCP == 1 */\r
-       {\r
-               pxSocketList = &xBoundUDPSocketsList;\r
-       }\r
-\r
-       /* The function prototype is designed to maintain the expected Berkeley\r
-       sockets standard, but this implementation does not use all the parameters. */\r
-       ( void ) uxAddressLength;\r
-\r
-       configASSERT( pxSocket );\r
-       configASSERT( pxSocket != FREERTOS_INVALID_SOCKET );\r
-\r
-       #if( ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 )\r
-       {\r
-               /* pxAddress will be NULL if sendto() was called on a socket without the\r
-               socket being bound to an address. In this case, automatically allocate\r
-               an address and port to the socket. */\r
-               if( pxAddress == NULL )\r
-               {\r
-                       pxAddress = &xAddress;\r
-                       /* Put the port to zero to be assigned later. */\r
-                       pxAddress->sin_port = 0u;\r
-               }\r
-       }\r
-       #endif /* ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 */\r
-\r
-       /* Sockets must be bound before calling FreeRTOS_sendto() if\r
-       ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is not set to 1. */\r
-       configASSERT( pxAddress );\r
-\r
-       if( pxAddress != NULL )\r
-       {\r
-               if( pxAddress->sin_port == 0u )\r
-               {\r
-                       pxAddress->sin_port = prvGetPrivatePortNumber( ( BaseType_t )pxSocket->ucProtocol );\r
-                       if( 0 == pxAddress->sin_port )\r
-                       {\r
-                               return -pdFREERTOS_ERRNO_EADDRNOTAVAIL;\r
-                       }\r
-               }\r
-\r
-               /* If vSocketBind() is called from the API FreeRTOS_bind() it has been\r
-               confirmed that the socket was not yet bound to a port.  If it is called\r
-               from the IP-task, no such check is necessary. */\r
-\r
-               /* Check to ensure the port is not already in use.  If the bind is\r
-               called internally, a port MAY be used by more than one socket. */\r
-               if( ( ( xInternal == pdFALSE ) || ( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP ) ) &&\r
-                       ( pxListFindListItemWithValue( pxSocketList, ( TickType_t ) pxAddress->sin_port ) != NULL ) )\r
-               {\r
-                       FreeRTOS_debug_printf( ( "vSocketBind: %sP port %d in use\n",\r
-                               pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP ? "TC" : "UD",\r
-                               FreeRTOS_ntohs( pxAddress->sin_port ) ) );\r
-                       xReturn = -pdFREERTOS_ERRNO_EADDRINUSE;\r
-               }\r
-               else\r
-               {\r
-                       /* Allocate the port number to the socket.\r
-                       This macro will set 'xBoundSocketListItem->xItemValue' */\r
-                       socketSET_SOCKET_PORT( pxSocket, pxAddress->sin_port );\r
-\r
-                       /* And also store it in a socket field 'usLocalPort' in host-byte-order,\r
-                       mostly used for logging and debugging purposes */\r
-                       pxSocket->usLocalPort = FreeRTOS_ntohs( pxAddress->sin_port );\r
-\r
-                       /* Add the socket to the list of bound ports. */\r
-                       {\r
-                               /* If the network driver can iterate through 'xBoundUDPSocketsList',\r
-                               by calling xPortHasUDPSocket() then the IP-task must temporarily\r
-                               suspend the scheduler to keep the list in a consistent state. */\r
-                               #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )\r
-                               {\r
-                                       vTaskSuspendAll();\r
-                               }\r
-                               #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */\r
-\r
-                               /* Add the socket to 'xBoundUDPSocketsList' or 'xBoundTCPSocketsList' */\r
-                               vListInsertEnd( pxSocketList, &( pxSocket->xBoundSocketListItem ) );\r
-\r
-                               #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )\r
-                               {\r
-                                       xTaskResumeAll();\r
-                               }\r
-                               #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */\r
-                       }\r
-               }\r
-       }\r
-       else\r
-       {\r
-               xReturn = -pdFREERTOS_ERRNO_EADDRNOTAVAIL;\r
-               FreeRTOS_debug_printf( ( "vSocketBind: Socket no addr\n" ) );\r
-       }\r
-\r
-       if( xReturn != 0 )\r
-       {\r
-               iptraceBIND_FAILED( xSocket, ( FreeRTOS_ntohs( pxAddress->sin_port ) ) );\r
-       }\r
-\r
-       return xReturn;\r
-} /* Tested */\r
-/*-----------------------------------------------------------*/\r
-\r
-/*\r
- * Close a socket and free the allocated space\r
- * In case of a TCP socket: the connection will not be closed automatically\r
- * Subsequent messages for the closed socket will be responded to with a RST\r
- * The IP-task will actually close the socket, after receiving a 'eSocketCloseEvent' message\r
- */\r
-BaseType_t FreeRTOS_closesocket( Socket_t xSocket )\r
-{\r
-BaseType_t xResult;\r
-#if( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 )\r
-       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * )xSocket;\r
-#endif\r
-IPStackEvent_t xCloseEvent;\r
-xCloseEvent.eEventType = eSocketCloseEvent;\r
-xCloseEvent.pvData = ( void * ) xSocket;\r
-\r
-       if( ( xSocket == NULL ) || ( xSocket == FREERTOS_INVALID_SOCKET ) )\r
-       {\r
-               xResult = 0;\r
-       }\r
-       else\r
-       {\r
-               #if( ( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 ) )\r
-               {\r
-                       if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
-                       {\r
-                               /* Make sure that IP-task won't call the user callback's anymore */\r
-                               pxSocket->u.xTCP.pxHandleConnected = NULL;\r
-                               pxSocket->u.xTCP.pxHandleReceive = NULL;\r
-                               pxSocket->u.xTCP.pxHandleSent = NULL;\r
-                       }\r
-               }\r
-               #endif  /* ( ( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 ) ) */\r
-\r
-               /* Let the IP task close the socket to keep it synchronised     with the\r
-               packet handling. */\r
-\r
-               /* Note when changing the time-out value below, it must be checked who is calling\r
-               this function. If it is called by the IP-task, a deadlock could occur.\r
-               The IP-task would only call it in case of a user call-back */\r
-               if( xSendEventStructToIPTask( &xCloseEvent, ( TickType_t ) 0 ) == pdFAIL )\r
-               {\r
-                       FreeRTOS_debug_printf( ( "FreeRTOS_closesocket: failed\n" ) );\r
-                       xResult = -1;\r
-               }\r
-               else\r
-               {\r
-                       xResult = 1;\r
-               }\r
-       }\r
-\r
-       return xResult;\r
-}\r
-\r
-/* This is the internal version of FreeRTOS_closesocket()\r
- * It will be called by the IPtask only to avoid problems with synchronicity\r
- */\r
-void *vSocketClose( FreeRTOS_Socket_t *pxSocket )\r
-{\r
-NetworkBufferDescriptor_t *pxNetworkBuffer;\r
-\r
-       #if( ipconfigUSE_TCP == 1 )\r
-       {\r
-               /* For TCP: clean up a little more. */\r
-               if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
-               {\r
-                       #if( ipconfigUSE_TCP_WIN == 1 )\r
-                       {\r
-                               if( pxSocket->u.xTCP.pxAckMessage != NULL )\r
-                               {\r
-                                       vReleaseNetworkBufferAndDescriptor( pxSocket->u.xTCP.pxAckMessage );\r
-                               }\r
-                               /* Free the resources which were claimed by the tcpWin member */\r
-                               vTCPWindowDestroy( &pxSocket->u.xTCP.xTCPWindow );\r
-                       }\r
-                       #endif /* ipconfigUSE_TCP_WIN */\r
-\r
-                       /* Free the input and output streams */\r
-                       if( pxSocket->u.xTCP.rxStream != NULL )\r
-                       {\r
-                               vPortFreeLarge( pxSocket->u.xTCP.rxStream );\r
-                       }\r
-\r
-                       if( pxSocket->u.xTCP.txStream != NULL )\r
-                       {\r
-                               vPortFreeLarge( pxSocket->u.xTCP.txStream );\r
-                       }\r
-\r
-                       /* In case this is a child socket, make sure the child-count of the\r
-                       parent socket is decreased. */\r
-                       prvTCPSetSocketCount( pxSocket );\r
-               }\r
-       }\r
-       #endif  /* ipconfigUSE_TCP == 1 */\r
-\r
-       /* Socket must be unbound first, to ensure no more packets are queued on\r
-       it. */\r
-       if( socketSOCKET_IS_BOUND( pxSocket ) != pdFALSE )\r
-       {\r
-               /* If the network driver can iterate through 'xBoundUDPSocketsList',\r
-               by calling xPortHasUDPSocket(), then the IP-task must temporarily\r
-               suspend the scheduler to keep the list in a consistent state. */\r
-               #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )\r
-               {\r
-                       vTaskSuspendAll();\r
-               }\r
-               #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */\r
-\r
-               uxListRemove( &( pxSocket->xBoundSocketListItem ) );\r
-\r
-               #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )\r
-               {\r
-                       xTaskResumeAll();\r
-               }\r
-               #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */\r
-       }\r
-\r
-       /* Now the socket is not bound the list of waiting packets can be\r
-       drained. */\r
-       if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_UDP )\r
-       {\r
-               while( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) > 0U )\r
-               {\r
-                       pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &( pxSocket->u.xUDP.xWaitingPacketsList ) );\r
-                       uxListRemove( &( pxNetworkBuffer->xBufferListItem ) );\r
-                       vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
-               }\r
-       }\r
-\r
-       if( pxSocket->xEventGroup )\r
-       {\r
-               vEventGroupDelete( pxSocket->xEventGroup );\r
-       }\r
-\r
-       #if( ipconfigUSE_TCP == 1 ) && ( ipconfigHAS_DEBUG_PRINTF != 0 )\r
-       {\r
-               if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
-               {\r
-                       FreeRTOS_debug_printf( ( "FreeRTOS_closesocket[%u to %lxip:%u]: buffers %lu socks %lu\n",\r
-                               pxSocket->usLocalPort,\r
-                               pxSocket->u.xTCP.ulRemoteIP,\r
-                               pxSocket->u.xTCP.usRemotePort,\r
-                               uxGetNumberOfFreeNetworkBuffers(),\r
-                               listCURRENT_LIST_LENGTH( &xBoundTCPSocketsList ) ) );\r
-               }\r
-       }\r
-       #endif /* ( ipconfigUSE_TCP == 1 ) && ( ipconfigHAS_DEBUG_PRINTF != 0 ) */\r
-\r
-       /* Anf finally, after all resources have been freed, free the socket space */\r
-       vPortFreeSocket( pxSocket );\r
-\r
-       return 0;\r
-} /* Tested */\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-#if ipconfigUSE_TCP == 1\r
-\r
-       /*\r
-        * When a child socket gets closed, make sure to update the child-count of the\r
-        * parent.  When a listening parent socket is closed, make sure no child-sockets\r
-        * keep a pointer to it.\r
-        */\r
-       static void prvTCPSetSocketCount( FreeRTOS_Socket_t *pxSocketToDelete )\r
-       {\r
-       const ListItem_t *pxIterator;\r
-       const MiniListItem_t *pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );\r
-       FreeRTOS_Socket_t *pxOtherSocket;\r
-       uint16_t usLocalPort = pxSocketToDelete->usLocalPort;\r
-\r
-               for( pxIterator  = ( const ListItem_t * ) listGET_NEXT( pxEnd );\r
-                        pxIterator != ( const ListItem_t * ) pxEnd;\r
-                        pxIterator  = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )\r
-               {\r
-                       pxOtherSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );\r
-                       if( ( pxOtherSocket->u.xTCP.ucTCPState == eTCP_LISTEN ) &&\r
-                               ( pxOtherSocket->usLocalPort == usLocalPort ) &&\r
-                               ( pxOtherSocket->u.xTCP.usChildCount ) )\r
-                       {\r
-                               pxOtherSocket->u.xTCP.usChildCount--;\r
-                               FreeRTOS_debug_printf( ( "Lost: Socket %u now has %u / %u child%s\n",\r
-                                       pxOtherSocket->usLocalPort,\r
-                                       pxOtherSocket->u.xTCP.usChildCount,\r
-                                       pxOtherSocket->u.xTCP.usBacklog,\r
-                                       pxOtherSocket->u.xTCP.usChildCount == 1u ? "" : "ren" ) );\r
-                               break;\r
-                       }\r
-               }\r
-       }\r
-\r
-#endif /* ipconfigUSE_TCP == 1 */\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-BaseType_t FreeRTOS_setsockopt( Socket_t xSocket, int32_t lLevel, int32_t lOptionName, const void *pvOptionValue, size_t xOptionLength )\r
-{\r
-/* The standard Berkeley function returns 0 for success. */\r
-BaseType_t xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
-BaseType_t lOptionValue;\r
-FreeRTOS_Socket_t *pxSocket;\r
-\r
-       pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
-\r
-       /* The function prototype is designed to maintain the expected Berkeley\r
-       sockets standard, but this implementation does not use all the parameters. */\r
-       ( void ) lLevel;\r
-       ( void ) xOptionLength;\r
-\r
-       configASSERT( xSocket );\r
-\r
-       switch( lOptionName )\r
-       {\r
-               case FREERTOS_SO_RCVTIMEO       :\r
-                       /* Receive time out. */\r
-                       pxSocket->xReceiveBlockTime = *( ( TickType_t * ) pvOptionValue );\r
-                       xReturn = 0;\r
-                       break;\r
-\r
-               case FREERTOS_SO_SNDTIMEO       :\r
-                       pxSocket->xSendBlockTime = *( ( TickType_t * ) pvOptionValue );\r
-                       if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_UDP )\r
-                       {\r
-                               /* The send time out is capped for the reason stated in the\r
-                               comments where ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS is defined\r
-                               in FreeRTOSIPConfig.h (assuming an official configuration file\r
-                               is being used. */\r
-                               if( pxSocket->xSendBlockTime > ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS )\r
-                               {\r
-                                       pxSocket->xSendBlockTime = ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS;\r
-                               }\r
-                       }\r
-                       else\r
-                       {\r
-                               /* For TCP socket, it isn't necessary to limit the blocking time\r
-                               because the FreeRTOS_send() function does not wait for a network\r
-                               buffer to become available. */\r
-                       }\r
-                       xReturn = 0;\r
-                       break;\r
-               #if( ipconfigUDP_MAX_RX_PACKETS > 0 )\r
-                       case FREERTOS_SO_UDP_MAX_RX_PACKETS:\r
-                               if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_UDP )\r
-                               {\r
-                                       break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
-                               }\r
-                               pxSocket->u.xUDP.uxMaxPackets = *( ( UBaseType_t * ) pvOptionValue );\r
-                               xReturn = 0;\r
-                               break;\r
-               #endif /* ipconfigUDP_MAX_RX_PACKETS */\r
-\r
-               case FREERTOS_SO_UDPCKSUM_OUT :\r
-                       /* Turn calculating of the UDP checksum on/off for this socket. */\r
-                       lOptionValue = ( BaseType_t ) pvOptionValue;\r
-\r
-                       if( lOptionValue == 0 )\r
-                       {\r
-                               pxSocket->ucSocketOptions &= ( uint8_t ) ~FREERTOS_SO_UDPCKSUM_OUT;\r
-                       }\r
-                       else\r
-                       {\r
-                               pxSocket->ucSocketOptions |= ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT;\r
-                       }\r
-                       xReturn = 0;\r
-                       break;\r
-\r
-               #if( ipconfigUSE_CALLBACKS == 1 )\r
-                       #if( ipconfigUSE_TCP == 1 )\r
-                               case FREERTOS_SO_TCP_CONN_HANDLER:      /* Set a callback for (dis)connection events */\r
-                               case FREERTOS_SO_TCP_RECV_HANDLER:      /* Install a callback for receiving TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */\r
-                               case FREERTOS_SO_TCP_SENT_HANDLER:      /* Install a callback for sending TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */\r
-                       #endif /* ipconfigUSE_TCP */\r
-                               case FREERTOS_SO_UDP_RECV_HANDLER:      /* Install a callback for receiving UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */\r
-                               case FREERTOS_SO_UDP_SENT_HANDLER:      /* Install a callback for sending UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */\r
-                                       {\r
-                                               #if( ipconfigUSE_TCP == 1 )\r
-                                               {\r
-                                                       UBaseType_t uxProtocol;\r
-                                                       if( ( lOptionName == FREERTOS_SO_UDP_RECV_HANDLER ) ||\r
-                                                               ( lOptionName == FREERTOS_SO_UDP_SENT_HANDLER ) )\r
-                                                       {\r
-                                                               uxProtocol = ( UBaseType_t ) FREERTOS_IPPROTO_UDP;\r
-                                                       }\r
-                                                       else\r
-                                                       {\r
-                                                               uxProtocol = ( UBaseType_t ) FREERTOS_IPPROTO_TCP;\r
-                                                       }\r
-\r
-                                                       if( pxSocket->ucProtocol != ( uint8_t ) uxProtocol )\r
-                                                       {\r
-                                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
-                                                       }\r
-                                               }\r
-                                               #else\r
-                                               {\r
-                                                       /* No need to check if the socket has the right\r
-                                                       protocol, because only UDP socket can be created. */\r
-                                               }\r
-                                               #endif /* ipconfigUSE_TCP */\r
-\r
-                                               switch( lOptionName )\r
-                                               {\r
-                                               #if ipconfigUSE_TCP == 1\r
-                                                       case FREERTOS_SO_TCP_CONN_HANDLER:\r
-                                                               pxSocket->u.xTCP.pxHandleConnected = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPConnected;\r
-                                                               break;\r
-                                                       case FREERTOS_SO_TCP_RECV_HANDLER:\r
-                                                               pxSocket->u.xTCP.pxHandleReceive = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPReceive;\r
-                                                               break;\r
-                                                       case FREERTOS_SO_TCP_SENT_HANDLER:\r
-                                                               pxSocket->u.xTCP.pxHandleSent = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPSent;\r
-                                                               break;\r
-                                               #endif /* ipconfigUSE_TCP */\r
-                                               case FREERTOS_SO_UDP_RECV_HANDLER:\r
-                                                       pxSocket->u.xUDP.pxHandleReceive = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnUDPReceive;\r
-                                                       break;\r
-                                               case FREERTOS_SO_UDP_SENT_HANDLER:\r
-                                                       pxSocket->u.xUDP.pxHandleSent = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnUDPSent;\r
-                                                       break;\r
-                                               default:\r
-                                                       break;\r
-                                               }\r
-                                       }\r
-\r
-                                       xReturn = 0;\r
-                                       break;\r
-               #endif /* ipconfigUSE_CALLBACKS */\r
-\r
-               #if( ipconfigUSE_TCP != 0 )\r
-                       #if( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 )\r
-                               /* Each socket has a semaphore on which the using task normally\r
-                               sleeps. */\r
-                               case FREERTOS_SO_SET_SEMAPHORE:\r
-                                       {\r
-                                               pxSocket->pxUserSemaphore = *( ( SemaphoreHandle_t * ) pvOptionValue );\r
-                                               xReturn = 0;\r
-                                       }\r
-                                       break;\r
-                       #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */\r
-\r
-                       #if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK != 0 )\r
-                               case FREERTOS_SO_WAKEUP_CALLBACK:\r
-                               {\r
-                                       /* Each socket can have a callback function that is executed\r
-                                       when there is an event the socket's owner might want to\r
-                                       process. */\r
-                                       pxSocket->pxUserWakeCallback = ( SocketWakeupCallback_t ) pvOptionValue;\r
-                                       xReturn = 0;\r
-                               }\r
-                               break;\r
-                       #endif /* ipconfigSOCKET_HAS_USER_WAKE_CALLBACK */\r
-\r
-                       case FREERTOS_SO_SET_LOW_HIGH_WATER:\r
-                               {\r
-                               LowHighWater_t *pxLowHighWater = ( LowHighWater_t * ) pvOptionValue;\r
-\r
-                                       if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
-                                       {\r
-                                               /* It is not allowed to access 'pxSocket->u.xTCP'. */\r
-                                               FreeRTOS_debug_printf( ( "FREERTOS_SO_SET_LOW_HIGH_WATER: wrong socket type\n" ) );\r
-                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
-                                       }\r
-                                       if( ( pxLowHighWater->uxLittleSpace >= pxLowHighWater->uxEnoughSpace ) ||\r
-                                               ( pxLowHighWater->uxEnoughSpace > pxSocket->u.xTCP.uxRxStreamSize ) )\r
-                                       {\r
-                                               /* Impossible values. */\r
-                                               FreeRTOS_debug_printf( ( "FREERTOS_SO_SET_LOW_HIGH_WATER: bad values\n" ) );\r
-                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
-                                       }\r
-                                       /* Send a STOP when buffer space drops below 'uxLittleSpace' bytes. */\r
-                                       pxSocket->u.xTCP.uxLittleSpace = pxLowHighWater->uxLittleSpace;\r
-                                       /* Send a GO when buffer space grows above 'uxEnoughSpace' bytes. */\r
-                                       pxSocket->u.xTCP.uxEnoughSpace = pxLowHighWater->uxEnoughSpace;\r
-                                       xReturn = 0;\r
-                               }\r
-                               break;\r
-\r
-                       case FREERTOS_SO_SNDBUF:        /* Set the size of the send buffer, in units of MSS (TCP only) */\r
-                       case FREERTOS_SO_RCVBUF:        /* Set the size of the receive buffer, in units of MSS (TCP only) */\r
-                               {\r
-                                       uint32_t ulNewValue;\r
-\r
-                                       if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
-                                       {\r
-                                               FreeRTOS_debug_printf( ( "Set SO_%sBUF: wrong socket type\n",\r
-                                                       ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );\r
-                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
-                                       }\r
-\r
-                                       if( ( ( lOptionName == FREERTOS_SO_SNDBUF ) && ( pxSocket->u.xTCP.txStream != NULL ) ) ||\r
-                                               ( ( lOptionName == FREERTOS_SO_RCVBUF ) && ( pxSocket->u.xTCP.rxStream != NULL ) ) )\r
-                                       {\r
-                                               FreeRTOS_debug_printf( ( "Set SO_%sBUF: buffer already created\n",\r
-                                                       ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );\r
-                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
-                                       }\r
-\r
-                                       ulNewValue = *( ( uint32_t * ) pvOptionValue );\r
-\r
-                                       if( lOptionName == FREERTOS_SO_SNDBUF )\r
-                                       {\r
-                                               /* Round up to nearest MSS size */\r
-                                               ulNewValue = FreeRTOS_round_up( ulNewValue, ( uint32_t ) pxSocket->u.xTCP.usInitMSS );\r
-                                               pxSocket->u.xTCP.uxTxStreamSize = ulNewValue;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               pxSocket->u.xTCP.uxRxStreamSize = ulNewValue;\r
-                                       }\r
-                               }\r
-                               xReturn = 0;\r
-                               break;\r
-\r
-                       case FREERTOS_SO_WIN_PROPERTIES:        /* Set all buffer and window properties in one call, parameter is pointer to WinProperties_t */\r
-                               {\r
-                                       WinProperties_t* pxProps;\r
-\r
-                                       if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
-                                       {\r
-                                               FreeRTOS_debug_printf( ( "Set SO_WIN_PROP: wrong socket type\n" ) );\r
-                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
-                                       }\r
-\r
-                                       if( ( pxSocket->u.xTCP.txStream != NULL ) || ( pxSocket->u.xTCP.rxStream != NULL ) )\r
-                                       {\r
-                                               FreeRTOS_debug_printf( ( "Set SO_WIN_PROP: buffer already created\n" ) );\r
-                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
-                                       }\r
-\r
-                                       pxProps = ( ( WinProperties_t * ) pvOptionValue );\r
-\r
-                                       if ( FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDBUF, &( pxProps->lTxBufSize ), sizeof( pxProps->lTxBufSize ) ) != 0 )\r
-                                       {\r
-                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
-                                       }\r
-\r
-                                       if ( FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVBUF, &( pxProps->lRxBufSize ), sizeof( pxProps->lRxBufSize ) ) != 0 )\r
-                                       {\r
-                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
-                                       }\r
-\r
-                                       #if( ipconfigUSE_TCP_WIN == 1 )\r
-                                       {\r
-                                               pxSocket->u.xTCP.uxRxWinSize = ( uint32_t )pxProps->lRxWinSize; /* Fixed value: size of the TCP reception window */\r
-                                               pxSocket->u.xTCP.uxTxWinSize = ( uint32_t )pxProps->lTxWinSize; /* Fixed value: size of the TCP transmit window */\r
-                                       }\r
-                                       #else\r
-                                       {\r
-                                               pxSocket->u.xTCP.uxRxWinSize = 1u;\r
-                                               pxSocket->u.xTCP.uxTxWinSize = 1u;\r
-                                       }\r
-                                       #endif\r
-\r
-                                       /* In case the socket has already initialised its tcpWin,\r
-                                       adapt the window size parameters */\r
-                                       if( pxSocket->u.xTCP.xTCPWindow.u.bits.bHasInit != pdFALSE_UNSIGNED )\r
-                                       {\r
-                                               pxSocket->u.xTCP.xTCPWindow.xSize.ulRxWindowLength = pxSocket->u.xTCP.uxRxWinSize * pxSocket->u.xTCP.usInitMSS;\r
-                                               pxSocket->u.xTCP.xTCPWindow.xSize.ulTxWindowLength = pxSocket->u.xTCP.uxTxWinSize * pxSocket->u.xTCP.usInitMSS;\r
-                                       }\r
-                               }\r
-\r
-                               xReturn = 0;\r
-                               break;\r
-\r
-                       case FREERTOS_SO_REUSE_LISTEN_SOCKET:   /* If true, the server-socket will turn into a connected socket */\r
-                               {\r
-                                       if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
-                                       {\r
-                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
-                                       }\r
-                                       if( *( ( BaseType_t * ) pvOptionValue ) != 0 )\r
-                                       {\r
-                                               pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE_UNSIGNED;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               pxSocket->u.xTCP.bits.bReuseSocket = pdFALSE_UNSIGNED;\r
-                                       }\r
-                               }\r
-                               xReturn = 0;\r
-                               break;\r
-\r
-                       case FREERTOS_SO_CLOSE_AFTER_SEND:              /* As soon as the last byte has been transmitted, finalise the connection */\r
-                               {\r
-                                       if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
-                                       {\r
-                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
-                                       }\r
-\r
-                                       if( *( ( BaseType_t * ) pvOptionValue ) != 0 )\r
-                                       {\r
-                                               pxSocket->u.xTCP.bits.bCloseAfterSend = pdTRUE_UNSIGNED;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               pxSocket->u.xTCP.bits.bCloseAfterSend = pdFALSE_UNSIGNED;\r
-                                       }\r
-                               }\r
-                               xReturn = 0;\r
-                               break;\r
-\r
-                       case FREERTOS_SO_SET_FULL_SIZE:         /* Refuse to send packets smaller than MSS  */\r
-                               {\r
-                                       if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
-                                       {\r
-                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
-                                       }\r
-\r
-                                       if( *( ( BaseType_t * ) pvOptionValue ) != 0 )\r
-                                       {\r
-                                               pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdTRUE_UNSIGNED;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdFALSE_UNSIGNED;\r
-                                       }\r
-\r
-                                       if( ( pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize == pdFALSE_UNSIGNED ) &&\r
-                                               ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) &&\r
-                                               ( FreeRTOS_outstanding( pxSocket ) != 0 ) )\r
-                                       {\r
-                                               pxSocket->u.xTCP.usTimeout = 1u; /* to set/clear bSendFullSize */\r
-                                               xSendEventToIPTask( eTCPTimerEvent );\r
-                                       }\r
-                               }\r
-                               xReturn = 0;\r
-                               break;\r
-\r
-                       case FREERTOS_SO_STOP_RX:               /* Refuse to receive more packts */\r
-                               {\r
-                                       if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
-                                       {\r
-                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
-                                       }\r
-\r
-                                       if( *( ( BaseType_t * ) pvOptionValue ) != 0 )\r
-                                       {\r
-                                               pxSocket->u.xTCP.bits.bRxStopped = pdTRUE_UNSIGNED;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               pxSocket->u.xTCP.bits.bRxStopped = pdFALSE_UNSIGNED;\r
-                                       }\r
-\r
-                                       pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;\r
-                                       pxSocket->u.xTCP.usTimeout = 1u; /* to set/clear bRxStopped */\r
-                                       xSendEventToIPTask( eTCPTimerEvent );\r
-                               }\r
-                               xReturn = 0;\r
-                               break;\r
-\r
-               #endif  /* ipconfigUSE_TCP == 1 */\r
-\r
-               default :\r
-                       /* No other options are handled. */\r
-                       xReturn = -pdFREERTOS_ERRNO_ENOPROTOOPT;\r
-                       break;\r
-       }\r
-\r
-       return xReturn;\r
-} /* Tested */\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-/* Find an available port number per https://tools.ietf.org/html/rfc6056. */\r
-static uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol )\r
-{\r
-const uint16_t usEphemeralPortCount =\r
-       socketAUTO_PORT_ALLOCATION_MAX_NUMBER - socketAUTO_PORT_ALLOCATION_START_NUMBER + 1;\r
-uint16_t usIterations = usEphemeralPortCount;\r
-uint32_t ulRandomSeed = 0;\r
-uint16_t usResult = 0;\r
-const List_t *pxList;\r
-\r
-#if ipconfigUSE_TCP == 1\r
-       if( xProtocol == ( BaseType_t ) FREERTOS_IPPROTO_TCP )\r
-       {\r
-               pxList = &xBoundTCPSocketsList;\r
-       }\r
-       else\r
-#endif\r
-       {\r
-               pxList = &xBoundUDPSocketsList;\r
-       }\r
-\r
-       /* Avoid compiler warnings if ipconfigUSE_TCP is not defined. */\r
-       ( void ) xProtocol;\r
-\r
-       /* Find the next available port using the random seed as a starting\r
-       point. */\r
-       do\r
-       {\r
-               /* Only proceed if the random number generator succeeded. */\r
-               if( xApplicationGetRandomNumber( &( ulRandomSeed ) ) == pdFALSE )\r
-               {\r
-                       break;\r
-               }\r
-\r
-               /* Map the random to a candidate port. */\r
-               usResult =\r
-                       socketAUTO_PORT_ALLOCATION_START_NUMBER +\r
-                       ( ( ( uint16_t )ulRandomSeed ) % usEphemeralPortCount );\r
-\r
-               /* Check if there's already an open socket with the same protocol\r
-               and port. */\r
-               if( NULL == pxListFindListItemWithValue(\r
-                       pxList,\r
-                       ( TickType_t )FreeRTOS_htons( usResult ) ) )\r
-               {\r
-                       usResult = FreeRTOS_htons( usResult );\r
-                       break;\r
-               }\r
-               else\r
-               {\r
-                       usResult = 0;\r
-               }\r
-\r
-               usIterations--;\r
-       }\r
-       while( usIterations > 0 );\r
-\r
-       return usResult;\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-/* pxListFindListItemWithValue: find a list item in a bound socket list\r
-'xWantedItemValue' refers to a port number */\r
-static const ListItem_t * pxListFindListItemWithValue( const List_t *pxList, TickType_t xWantedItemValue )\r
-{\r
-const ListItem_t * pxResult = NULL;\r
-\r
-       if( ( xIPIsNetworkTaskReady() != pdFALSE ) && ( pxList != NULL ) )\r
-       {\r
-               const ListItem_t *pxIterator;\r
-               const MiniListItem_t *pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( pxList );\r
-               for( pxIterator  = ( const ListItem_t * ) listGET_NEXT( pxEnd );\r
-                        pxIterator != ( const ListItem_t * ) pxEnd;\r
-                        pxIterator  = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )\r
-               {\r
-                       if( listGET_LIST_ITEM_VALUE( pxIterator ) == xWantedItemValue )\r
-                       {\r
-                               pxResult = pxIterator;\r
-                               break;\r
-                       }\r
-               }\r
-       }\r
-\r
-       return pxResult;\r
-} /* Tested */\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-FreeRTOS_Socket_t *pxUDPSocketLookup( UBaseType_t uxLocalPort )\r
-{\r
-const ListItem_t *pxListItem;\r
-FreeRTOS_Socket_t *pxSocket = NULL;\r
-\r
-       /* Looking up a socket is quite simple, find a match with the local port.\r
-\r
-       See if there is a list item associated with the port number on the\r
-       list of bound sockets. */\r
-       pxListItem = pxListFindListItemWithValue( &xBoundUDPSocketsList, ( TickType_t ) uxLocalPort );\r
-\r
-       if( pxListItem != NULL )\r
-       {\r
-               /* The owner of the list item is the socket itself. */\r
-               pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxListItem );\r
-               configASSERT( pxSocket != NULL );\r
-       }\r
-       return pxSocket;\r
-}\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-#if ipconfigINCLUDE_FULL_INET_ADDR == 1\r
-\r
-       uint32_t FreeRTOS_inet_addr( const char * pcIPAddress )\r
-       {\r
-       const uint32_t ulDecimalBase = 10u;\r
-       uint8_t ucOctet[ socketMAX_IP_ADDRESS_OCTETS ];\r
-       const char *pcPointerOnEntering;\r
-       uint32_t ulReturn = 0UL, ulValue;\r
-       UBaseType_t uxOctetNumber;\r
-       BaseType_t xResult = pdPASS;\r
-\r
-               for( uxOctetNumber = 0u; uxOctetNumber < socketMAX_IP_ADDRESS_OCTETS; uxOctetNumber++ )\r
-               {\r
-                       ulValue = 0ul;\r
-                       pcPointerOnEntering = pcIPAddress;\r
-\r
-                       while( ( *pcIPAddress >= '0' ) && ( *pcIPAddress <= '9' ) )\r
-                       {\r
-                               /* Move previous read characters into the next decimal\r
-                               position. */\r
-                               ulValue *= ulDecimalBase;\r
-\r
-                               /* Add the binary value of the ascii character. */\r
-                               ulValue += ( ( uint32_t ) ( *pcIPAddress ) - ( uint32_t ) '0' );\r
-\r
-                               /* Move to next character in the string. */\r
-                               pcIPAddress++;\r
-                       }\r
-\r
-                       /* Check characters were read. */\r
-                       if( pcIPAddress == pcPointerOnEntering )\r
-                       {\r
-                               xResult = pdFAIL;\r
-                       }\r
-\r
-                       /* Check the value fits in an 8-bit number. */\r
-                       if( ulValue > 0xffUL )\r
-                       {\r
-                               xResult = pdFAIL;\r
-                       }\r
-                       else\r
-                       {\r
-                               ucOctet[ uxOctetNumber ] = ( uint8_t ) ulValue;\r
-\r
-                               /* Check the next character is as expected. */\r
-                               if( uxOctetNumber < ( socketMAX_IP_ADDRESS_OCTETS - 1u ) )\r
-                               {\r
-                                       if( *pcIPAddress != '.' )\r
-                                       {\r
-                                               xResult = pdFAIL;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               /* Move past the dot. */\r
-                                               pcIPAddress++;\r
-                                       }\r
-                               }\r
-                       }\r
-\r
-                       if( xResult == pdFAIL )\r
-                       {\r
-                               /* No point going on. */\r
-                               break;\r
-                       }\r
-               }\r
-\r
-               if( *pcIPAddress != ( char ) 0 )\r
-               {\r
-                       /* Expected the end of the string. */\r
-                       xResult = pdFAIL;\r
-               }\r
-\r
-               if( uxOctetNumber != socketMAX_IP_ADDRESS_OCTETS )\r
-               {\r
-                       /* Didn't read enough octets. */\r
-                       xResult = pdFAIL;\r
-               }\r
-\r
-               if( xResult == pdPASS )\r
-               {\r
-                       ulReturn = FreeRTOS_inet_addr_quick( ucOctet[ 0 ], ucOctet[ 1 ], ucOctet[ 2 ], ucOctet[ 3 ] );\r
-               }\r
-\r
-               return ulReturn;\r
-       }\r
-\r
-#endif /* ipconfigINCLUDE_FULL_INET_ADDR */\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-/* Function to get the local address and IP port */\r
-size_t FreeRTOS_GetLocalAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress )\r
-{\r
-FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
-\r
-       /* IP address of local machine. */\r
-       pxAddress->sin_addr = *ipLOCAL_IP_ADDRESS_POINTER;\r
-\r
-       /* Local port on this machine. */\r
-       pxAddress->sin_port = FreeRTOS_htons( pxSocket->usLocalPort );\r
-\r
-       return sizeof( *pxAddress );\r
-}\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )\r
-{\r
-/* _HT_ must work this out, now vSocketWakeUpUser will be called for any important\r
- * event or transition */\r
-       #if( ipconfigSOCKET_HAS_USER_SEMAPHORE == 1 )\r
-       {\r
-               if( pxSocket->pxUserSemaphore != NULL )\r
-               {\r
-                       xSemaphoreGive( pxSocket->pxUserSemaphore );\r
-               }\r
-       }\r
-       #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */\r
-\r
-       #if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK == 1 )\r
-       {\r
-               if( pxSocket->pxUserWakeCallback != NULL )\r
-               {\r
-                       pxSocket->pxUserWakeCallback( pxSocket );\r
-               }\r
-       }\r
-       #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */\r
-\r
-       #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
-       {\r
-               if( pxSocket->pxSocketSet != NULL )\r
-               {\r
-                       EventBits_t xSelectBits = ( pxSocket->xEventBits >> SOCKET_EVENT_BIT_COUNT ) & eSELECT_ALL;\r
-                       if( xSelectBits != 0ul )\r
-                       {\r
-                               pxSocket->xSocketBits |= xSelectBits;\r
-                               xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, xSelectBits );\r
-                       }\r
-               }\r
-\r
-               pxSocket->xEventBits &= eSOCKET_ALL;\r
-       }\r
-       #endif /* ipconfigSUPPORT_SELECT_FUNCTION */\r
-\r
-       if( ( pxSocket->xEventGroup != NULL ) && ( pxSocket->xEventBits != 0u ) )\r
-       {\r
-               xEventGroupSetBits( pxSocket->xEventGroup, pxSocket->xEventBits );\r
-       }\r
-\r
-       pxSocket->xEventBits = 0ul;\r
-}\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )\r
-\r
-       /* This define makes it possible for network-card drivers to inspect\r
-        * UDP message and see if there is any UDP socket bound to a given port\r
-        * number.\r
-        * This is probably only usefull in systems with a minimum of RAM and\r
-        * when lots of anonymous broadcast messages come in\r
-        */\r
-       BaseType_t xPortHasUDPSocket( uint16_t usPortNr )\r
-       {\r
-       BaseType_t xFound = pdFALSE;\r
-\r
-               vTaskSuspendAll();\r
-               {\r
-                       if( ( pxListFindListItemWithValue( &xBoundUDPSocketsList, ( TickType_t ) usPortNr ) != NULL ) )\r
-                       {\r
-                               xFound = pdTRUE;\r
-                       }\r
-               }\r
-               xTaskResumeAll();\r
-\r
-               return xFound;\r
-       }\r
-\r
-#endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigUSE_TCP == 1 )\r
-\r
-       static BaseType_t bMayConnect( FreeRTOS_Socket_t *pxSocket );\r
-       static BaseType_t bMayConnect( FreeRTOS_Socket_t *pxSocket )\r
-       {\r
-               switch( pxSocket->u.xTCP.ucTCPState )\r
-               {\r
-                       case eCLOSED:\r
-                       case eCLOSE_WAIT:       return 0;\r
-                       case eCONNECT_SYN:      return -pdFREERTOS_ERRNO_EINPROGRESS;\r
-                       default:                        return -pdFREERTOS_ERRNO_EAGAIN;\r
-               }\r
-       }\r
-\r
-#endif /* ipconfigUSE_TCP */\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigUSE_TCP == 1 )\r
-\r
-       static BaseType_t prvTCPConnectStart( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr *pxAddress )\r
-       {\r
-       BaseType_t xResult = 0;\r
-\r
-               if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdFALSE )\r
-               {\r
-                       /* Not a valid socket or wrong type */\r
-                       xResult = -pdFREERTOS_ERRNO_EBADF;\r
-               }\r
-               else if( FreeRTOS_issocketconnected( pxSocket ) > 0 )\r
-               {\r
-                       /* The socket is already connected. */\r
-                       xResult = -pdFREERTOS_ERRNO_EISCONN;\r
-               }\r
-               else if( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE )\r
-               {\r
-                       /* Bind the socket to the port that the client task will send from.\r
-                       Non-standard, so the error returned is that returned by bind(). */\r
-                       xResult = FreeRTOS_bind( ( Socket_t ) pxSocket, NULL, 0u );\r
-               }\r
-\r
-               if( xResult == 0 )\r
-               {\r
-                       /* Check if it makes any sense to wait for a connect event, this condition\r
-                       might change while sleeping, so it must be checked within each loop */\r
-                       xResult = bMayConnect( pxSocket ); /* -EINPROGRESS, -EAGAIN, or 0 for OK */\r
-\r
-                       /* Start the connect procedure, kernel will start working on it */\r
-                       if( xResult == 0 )\r
-                       {\r
-                               pxSocket->u.xTCP.bits.bConnPrepared = pdFALSE_UNSIGNED;\r
-                               pxSocket->u.xTCP.ucRepCount = 0u;\r
-\r
-                               FreeRTOS_debug_printf( ( "FreeRTOS_connect: %u to %lxip:%u\n",\r
-                                       pxSocket->usLocalPort, FreeRTOS_ntohl( pxAddress->sin_addr ), FreeRTOS_ntohs( pxAddress->sin_port ) ) );\r
-\r
-                               /* Port on remote machine. */\r
-                               pxSocket->u.xTCP.usRemotePort = FreeRTOS_ntohs( pxAddress->sin_port );\r
-\r
-                               /* IP address of remote machine. */\r
-                               pxSocket->u.xTCP.ulRemoteIP = FreeRTOS_ntohl( pxAddress->sin_addr );\r
-\r
-                               /* (client) internal state: socket wants to send a connect. */\r
-                               vTCPStateChange( pxSocket, eCONNECT_SYN );\r
-\r
-                               /* To start an active connect. */\r
-                               pxSocket->u.xTCP.usTimeout = 1u;\r
-\r
-                               if( xSendEventToIPTask( eTCPTimerEvent ) != pdPASS )\r
-                               {\r
-                                       xResult = -pdFREERTOS_ERRNO_ECANCELED;\r
-                               }\r
-                       }\r
-               }\r
-\r
-               return xResult;\r
-       }\r
-\r
-#endif /* ipconfigUSE_TCP */\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigUSE_TCP == 1 )\r
-\r
-       /*\r
-        * FreeRTOS_connect: socket wants to connect to a remote port\r
-        */\r
-       BaseType_t FreeRTOS_connect( Socket_t xClientSocket, struct freertos_sockaddr *pxAddress, socklen_t xAddressLength )\r
-       {\r
-       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t* ) xClientSocket;\r
-       TickType_t xRemainingTime;\r
-       BaseType_t xTimed = pdFALSE;\r
-       BaseType_t xResult;\r
-       TimeOut_t xTimeOut;\r
-\r
-               ( void ) xAddressLength;\r
-\r
-               xResult = prvTCPConnectStart( pxSocket, pxAddress );\r
-\r
-               if( xResult == 0 )\r
-               {\r
-                       /* And wait for the result */\r
-                       for( ;; )\r
-                       {\r
-                               if( xTimed == pdFALSE )\r
-                               {\r
-                                       /* Only in the first round, check for non-blocking */\r
-                                       xRemainingTime = pxSocket->xReceiveBlockTime;\r
-                                       if( xRemainingTime == ( TickType_t )0 )\r
-                                       {\r
-                                               /* Not yet connected, correct state, non-blocking. */\r
-                                               xResult = -pdFREERTOS_ERRNO_EWOULDBLOCK;\r
-                                               break;\r
-                                       }\r
-\r
-                                       /* Don't get here a second time. */\r
-                                       xTimed = pdTRUE;\r
-\r
-                                       /* Fetch the current time */\r
-                                       vTaskSetTimeOutState( &xTimeOut );\r
-                               }\r
-\r
-                               /* Did it get connected while sleeping ? */\r
-                               xResult = FreeRTOS_issocketconnected( pxSocket );\r
-\r
-                               /* Returns positive when connected, negative means an error */\r
-                               if( xResult < 0 )\r
-                               {\r
-                                       /* Return the error */\r
-                                       break;\r
-                               }\r
-\r
-                               if( xResult > 0 )\r
-                               {\r
-                                       /* Socket now connected, return a zero */\r
-                                       xResult = 0;\r
-                                       break;\r
-                               }\r
-\r
-                               /* Is it allowed to sleep more? */\r
-                               if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) )\r
-                               {\r
-                                       xResult = -pdFREERTOS_ERRNO_ETIMEDOUT;\r
-                                       break;\r
-                               }\r
-\r
-                               /* Go sleeping until we get any down-stream event */\r
-                               xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_CONNECT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );\r
-                       }\r
-               }\r
-\r
-               return xResult;\r
-       }\r
-#endif /* ipconfigUSE_TCP */\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigUSE_TCP == 1 )\r
-\r
-       /*\r
-        * FreeRTOS_accept: can return a new connected socket\r
-        * if the server socket is in listen mode and receives a connection request\r
-        * The new socket will be bound already to the same port number as the listing\r
-        * socket.\r
-        */\r
-       Socket_t FreeRTOS_accept( Socket_t xServerSocket, struct freertos_sockaddr *pxAddress, socklen_t *pxAddressLength )\r
-       {\r
-       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xServerSocket;\r
-       FreeRTOS_Socket_t *pxClientSocket = NULL;\r
-       TickType_t xRemainingTime;\r
-       BaseType_t xTimed = pdFALSE, xAsk = pdFALSE;\r
-       TimeOut_t xTimeOut;\r
-       IPStackEvent_t xAskEvent;\r
-\r
-               if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )\r
-               {\r
-                       /* Not a valid socket or wrong type */\r
-                       pxClientSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;\r
-               }\r
-               else if( ( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED ) &&\r
-                                ( pxSocket->u.xTCP.ucTCPState != eTCP_LISTEN ) )\r
-               {\r
-                       /* Parent socket is not in listening mode */\r
-                       pxClientSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;\r
-               }\r
-               else\r
-               {\r
-                       /* Loop will stop with breaks. */\r
-                       for( ; ; )\r
-                       {\r
-                               /* Is there a new client? */\r
-                               vTaskSuspendAll();\r
-                               {\r
-                                       if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED )\r
-                                       {\r
-                                               pxClientSocket = pxSocket->u.xTCP.pxPeerSocket;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               pxClientSocket = pxSocket;\r
-                                       }\r
-                                       if( pxClientSocket != NULL )\r
-                                       {\r
-                                               pxSocket->u.xTCP.pxPeerSocket = NULL;\r
-\r
-                                               /* Is it still not taken ? */\r
-                                               if( pxClientSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED )\r
-                                               {\r
-                                                       pxClientSocket->u.xTCP.bits.bPassAccept = pdFALSE_UNSIGNED;\r
-                                               }\r
-                                               else\r
-                                               {\r
-                                                       pxClientSocket = NULL;\r
-                                               }\r
-                                       }\r
-                               }\r
-                               xTaskResumeAll();\r
-\r
-                               if( pxClientSocket != NULL )\r
-                               {\r
-                                       if( pxAddress != NULL )\r
-                                       {\r
-                                               /* IP address of remote machine. */\r
-                                               pxAddress->sin_addr = FreeRTOS_ntohl( pxClientSocket->u.xTCP.ulRemoteIP );\r
-\r
-                                               /* Port on remote machine. */\r
-                                               pxAddress->sin_port = FreeRTOS_ntohs( pxClientSocket->u.xTCP.usRemotePort );\r
-                                       }\r
-                                       if( pxAddressLength != NULL )\r
-                                       {\r
-                                               *pxAddressLength = sizeof( *pxAddress );\r
-                                       }\r
-\r
-                                       if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED )\r
-                                       {\r
-                                               xAsk = pdTRUE;\r
-                                       }\r
-                               }\r
-\r
-                               if( xAsk != pdFALSE )\r
-                               {\r
-                                       /* Ask to set an event in 'xEventGroup' as soon as a new\r
-                                       client gets connected for this listening socket. */\r
-                                       xAskEvent.eEventType = eTCPAcceptEvent;\r
-                                       xAskEvent.pvData = ( void * ) pxSocket;\r
-                                       xSendEventStructToIPTask( &xAskEvent, portMAX_DELAY );\r
-                               }\r
-\r
-                               if( pxClientSocket != NULL )\r
-                               {\r
-                                       break;\r
-                               }\r
-\r
-                               if( xTimed == pdFALSE )\r
-                               {\r
-                                       /* Only in the first round, check for non-blocking */\r
-                                       xRemainingTime = pxSocket->xReceiveBlockTime;\r
-                                       if( xRemainingTime == ( TickType_t ) 0 )\r
-                                       {\r
-                                               break;\r
-                                       }\r
-\r
-                                       /* Don't get here a second time */\r
-                                       xTimed = pdTRUE;\r
-\r
-                                       /* Fetch the current time */\r
-                                       vTaskSetTimeOutState( &xTimeOut );\r
-                               }\r
-\r
-                               /* Has the timeout been reached? */\r
-                               if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )\r
-                               {\r
-                                       break;\r
-                               }\r
-\r
-                               /* Go sleeping until we get any down-stream event */\r
-                               xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_ACCEPT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );\r
-                       }\r
-               }\r
-\r
-               return ( Socket_t ) pxClientSocket;\r
-       }\r
-#endif /* ipconfigUSE_TCP */\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigUSE_TCP == 1 )\r
-\r
-       /*\r
-        * Read incoming data from a TCP socket\r
-        * Only after the last byte has been read, a close error might be returned\r
-        */\r
-       BaseType_t FreeRTOS_recv( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags )\r
-       {\r
-       BaseType_t xByteCount;\r
-       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
-       TickType_t xRemainingTime;\r
-       BaseType_t xTimed = pdFALSE;\r
-       TimeOut_t xTimeOut;\r
-       EventBits_t xEventBits = ( EventBits_t ) 0;\r
-\r
-               /* Check if the socket is valid, has type TCP and if it is bound to a\r
-               port. */\r
-               if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )\r
-               {\r
-                       xByteCount = -pdFREERTOS_ERRNO_EINVAL;\r
-               }\r
-               else\r
-               {\r
-                       if( pxSocket->u.xTCP.rxStream != NULL )\r
-                       {\r
-                               xByteCount = ( BaseType_t )uxStreamBufferGetSize ( pxSocket->u.xTCP.rxStream );\r
-                       }\r
-                       else\r
-                       {\r
-                               xByteCount = 0;\r
-                       }\r
-\r
-                       while( xByteCount == 0 )\r
-                       {\r
-                               switch( pxSocket->u.xTCP.ucTCPState )\r
-                               {\r
-                               case eCLOSED:\r
-                               case eCLOSE_WAIT:       /* (server + client) waiting for a connection termination request from the local user. */\r
-                               case eCLOSING:          /* (server + client) waiting for a connection termination request acknowledgement from the remote TCP. */\r
-                                       if( pxSocket->u.xTCP.bits.bMallocError != pdFALSE_UNSIGNED )\r
-                                       {\r
-                                               /* The no-memory error has priority above the non-connected error.\r
-                                               Both are fatal and will elad to closing the socket. */\r
-                                               xByteCount = -pdFREERTOS_ERRNO_ENOMEM;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               xByteCount = -pdFREERTOS_ERRNO_ENOTCONN;\r
-                                       }\r
-                                       /* Call continue to break out of the switch and also the while\r
-                                       loop. */\r
-                                       continue;\r
-                               default:\r
-                                       break;\r
-                               }\r
-\r
-                               if( xTimed == pdFALSE )\r
-                               {\r
-                                       /* Only in the first round, check for non-blocking. */\r
-                                       xRemainingTime = pxSocket->xReceiveBlockTime;\r
-\r
-                                       if( xRemainingTime == ( TickType_t ) 0 )\r
-                                       {\r
-                                               #if( ipconfigSUPPORT_SIGNALS != 0 )\r
-                                               {\r
-                                                       /* Just check for the interrupt flag. */\r
-                                                       xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_INTR,\r
-                                                               pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, socketDONT_BLOCK );\r
-                                               }\r
-                                               #endif /* ipconfigSUPPORT_SIGNALS */\r
-                                               break;\r
-                                       }\r
-\r
-                                       if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )\r
-                                       {\r
-                                               break;\r
-                                       }\r
-\r
-                                       /* Don't get here a second time. */\r
-                                       xTimed = pdTRUE;\r
-\r
-                                       /* Fetch the current time. */\r
-                                       vTaskSetTimeOutState( &xTimeOut );\r
-                               }\r
-\r
-                               /* Has the timeout been reached? */\r
-                               if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )\r
-                               {\r
-                                       break;\r
-                               }\r
-\r
-                               /* Block until there is a down-stream event. */\r
-                               xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup,\r
-                                       eSOCKET_RECEIVE | eSOCKET_CLOSED | eSOCKET_INTR,\r
-                                       pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );\r
-                               #if( ipconfigSUPPORT_SIGNALS != 0 )\r
-                               {\r
-                                       if( ( xEventBits & eSOCKET_INTR ) != 0u )\r
-                                       {\r
-                                               break;\r
-                                       }\r
-                               }\r
-                               #else\r
-                               {\r
-                                       ( void ) xEventBits;\r
-                               }\r
-                               #endif /* ipconfigSUPPORT_SIGNALS */\r
-\r
-                               if( pxSocket->u.xTCP.rxStream != NULL )\r
-                               {\r
-                                       xByteCount = ( BaseType_t ) uxStreamBufferGetSize ( pxSocket->u.xTCP.rxStream );\r
-                               }\r
-                               else\r
-                               {\r
-                                       xByteCount = 0;\r
-                               }\r
-                       }\r
-\r
-               #if( ipconfigSUPPORT_SIGNALS != 0 )\r
-                       if( ( xEventBits & eSOCKET_INTR ) != 0 )\r
-                       {\r
-                               if( ( xEventBits & ( eSOCKET_RECEIVE | eSOCKET_CLOSED ) ) != 0 )\r
-                               {\r
-                                       /* Shouldn't have cleared other flags. */\r
-                                       xEventBits &= ~eSOCKET_INTR;\r
-                                       xEventGroupSetBits( pxSocket->xEventGroup, xEventBits );\r
-                               }\r
-                               xByteCount = -pdFREERTOS_ERRNO_EINTR;\r
-                       }\r
-                       else\r
-               #endif /* ipconfigSUPPORT_SIGNALS */\r
-                       if( xByteCount > 0 )\r
-                       {\r
-                               if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )\r
-                               {\r
-                                       xByteCount = ( BaseType_t ) uxStreamBufferGet( pxSocket->u.xTCP.rxStream, 0ul, ( uint8_t * ) pvBuffer, ( size_t ) xBufferLength, ( xFlags & FREERTOS_MSG_PEEK ) != 0 );\r
-                                       if( pxSocket->u.xTCP.bits.bLowWater != pdFALSE_UNSIGNED )\r
-                                       {\r
-                                               /* We had reached the low-water mark, now see if the flag\r
-                                               can be cleared */\r
-                                               size_t uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );\r
-\r
-                                               if( uxFrontSpace >= pxSocket->u.xTCP.uxEnoughSpace )\r
-                                               {\r
-                                                       pxSocket->u.xTCP.bits.bLowWater = pdFALSE_UNSIGNED;\r
-                                                       pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;\r
-                                                       pxSocket->u.xTCP.usTimeout = 1u; /* because bLowWater is cleared. */\r
-                                                       xSendEventToIPTask( eTCPTimerEvent );\r
-                                               }\r
-                                       }\r
-                               }\r
-                               else\r
-                               {\r
-                                       /* Zero-copy reception of data: pvBuffer is a pointer to a pointer. */\r
-                                       xByteCount = ( BaseType_t ) uxStreamBufferGetPtr( pxSocket->u.xTCP.rxStream, (uint8_t **)pvBuffer );\r
-                               }\r
-                       }\r
-               } /* prvValidSocket() */\r
-\r
-               return xByteCount;\r
-       }\r
-\r
-#endif /* ipconfigUSE_TCP */\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigUSE_TCP == 1 )\r
-\r
-       static int32_t prvTCPSendCheck( FreeRTOS_Socket_t *pxSocket, size_t xDataLength )\r
-       {\r
-       int32_t xResult = 1;\r
-\r
-               /* Is this a socket of type TCP and is it already bound to a port number ? */\r
-               if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )\r
-               {\r
-                       xResult = -pdFREERTOS_ERRNO_EINVAL;\r
-               }\r
-               else if( pxSocket->u.xTCP.bits.bMallocError != pdFALSE_UNSIGNED )\r
-               {\r
-                       xResult = -pdFREERTOS_ERRNO_ENOMEM;\r
-               }\r
-               else if( pxSocket->u.xTCP.ucTCPState == eCLOSED ||\r
-                 pxSocket->u.xTCP.ucTCPState == eCLOSE_WAIT ||\r
-                 pxSocket->u.xTCP.ucTCPState == eCLOSING )\r
-               {\r
-                       xResult = -pdFREERTOS_ERRNO_ENOTCONN;\r
-               }\r
-               else if( pxSocket->u.xTCP.bits.bFinSent != pdFALSE_UNSIGNED )\r
-               {\r
-                       /* This TCP connection is closing already, the FIN flag has been sent.\r
-                       Maybe it is still delivering or receiving data.\r
-                       Return OK in order not to get closed/deleted too quickly */\r
-                       xResult = 0;\r
-               }\r
-               else if( xDataLength == 0ul )\r
-               {\r
-                       /* send() is being called to send zero bytes */\r
-                       xResult = 0;\r
-               }\r
-               else if( pxSocket->u.xTCP.txStream == NULL )\r
-               {\r
-                       /* Create the outgoing stream only when it is needed */\r
-                       prvTCPCreateStream( pxSocket, pdFALSE );\r
-\r
-                       if( pxSocket->u.xTCP.txStream == NULL )\r
-                       {\r
-                               xResult = -pdFREERTOS_ERRNO_ENOMEM;\r
-                       }\r
-               }\r
-\r
-               return xResult;\r
-       }\r
-\r
-#endif /* ipconfigUSE_TCP */\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigUSE_TCP == 1 )\r
-\r
-       /* Get a direct pointer to the circular transmit buffer.\r
-       '*pxLength' will contain the number of bytes that may be written. */\r
-       uint8_t *FreeRTOS_get_tx_head( Socket_t xSocket, BaseType_t *pxLength )\r
-       {\r
-    uint8_t *pucReturn = NULL;\r
-       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
-       StreamBuffer_t *pxBuffer = NULL;\r
-\r
-        *pxLength = 0;\r
-\r
-        /* Confirm that this is a TCP socket before dereferencing structure\r
-        member pointers. */\r
-        if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdTRUE )\r
-        {\r
-            pxBuffer = pxSocket->u.xTCP.txStream;\r
-            if( pxBuffer != NULL )\r
-            {\r
-            BaseType_t xSpace = ( BaseType_t )uxStreamBufferGetSpace( pxBuffer );\r
-            BaseType_t xRemain = ( BaseType_t )( pxBuffer->LENGTH - pxBuffer->uxHead );\r
-\r
-                *pxLength = FreeRTOS_min_BaseType( xSpace, xRemain );\r
-                pucReturn = pxBuffer->ucArray + pxBuffer->uxHead;\r
-            }\r
-               }\r
-\r
-               return pucReturn;\r
-       }\r
-#endif /* ipconfigUSE_TCP */\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigUSE_TCP == 1 )\r
-       /*\r
-        * Send data using a TCP socket.  It is not necessary to have the socket\r
-        * connected already.  Outgoing data will be stored and delivered as soon as\r
-        * the socket gets connected.\r
-        */\r
-       BaseType_t FreeRTOS_send( Socket_t xSocket, const void *pvBuffer, size_t uxDataLength, BaseType_t xFlags )\r
-       {\r
-       BaseType_t xByteCount;\r
-       BaseType_t xBytesLeft;\r
-       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
-       TickType_t xRemainingTime;\r
-       BaseType_t xTimed = pdFALSE;\r
-       TimeOut_t xTimeOut;\r
-       BaseType_t xCloseAfterSend;\r
-\r
-               /* Prevent compiler warnings about unused parameters.  The parameter\r
-               may be used in future versions. */\r
-               ( void ) xFlags;\r
-\r
-               xByteCount = ( BaseType_t ) prvTCPSendCheck( pxSocket, uxDataLength );\r
-\r
-               if( xByteCount > 0 )\r
-               {\r
-                       /* xBytesLeft is number of bytes to send, will count to zero. */\r
-                       xBytesLeft = ( BaseType_t ) uxDataLength;\r
-\r
-                       /* xByteCount is number of bytes that can be sent now. */\r
-                       xByteCount = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );\r
-\r
-                       /* While there are still bytes to be sent. */\r
-                       while( xBytesLeft > 0 )\r
-                       {\r
-                               /* If txStream has space. */\r
-                               if( xByteCount > 0 )\r
-                               {\r
-                                       /* Don't send more than necessary. */\r
-                                       if( xByteCount > xBytesLeft )\r
-                                       {\r
-                                               xByteCount = xBytesLeft;\r
-                                       }\r
-\r
-                                       /* Is the close-after-send flag set and is this really the\r
-                                       last transmission? */\r
-                                       if( ( pxSocket->u.xTCP.bits.bCloseAfterSend != pdFALSE_UNSIGNED ) && ( xByteCount == xBytesLeft ) )\r
-                                       {\r
-                                               xCloseAfterSend = pdTRUE;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               xCloseAfterSend = pdFALSE;\r
-                                       }\r
-\r
-                                       /* The flag 'bCloseAfterSend' can be set before sending data\r
-                                       using setsockopt()\r
-\r
-                                       When the last data packet is being sent out, a FIN flag will\r
-                                       be included to let the peer know that no more data is to be\r
-                                       expected.  The use of 'bCloseAfterSend' is not mandatory, it\r
-                                       is just a faster way of transferring files (e.g. when using\r
-                                       FTP). */\r
-                                       if( xCloseAfterSend != pdFALSE )\r
-                                       {\r
-                                               /* Now suspend the scheduler: sending the last data     and\r
-                                               setting bCloseRequested must be done together */\r
-                                               vTaskSuspendAll();\r
-                                               pxSocket->u.xTCP.bits.bCloseRequested = pdTRUE_UNSIGNED;\r
-                                       }\r
-\r
-                                       xByteCount = ( BaseType_t ) uxStreamBufferAdd( pxSocket->u.xTCP.txStream, 0ul, ( const uint8_t * ) pvBuffer, ( size_t ) xByteCount );\r
-\r
-                                       if( xCloseAfterSend != pdFALSE )\r
-                                       {\r
-                                               /* Now when the IP-task transmits the data, it will also\r
-                                               see     that bCloseRequested is true and include the FIN\r
-                                               flag to start closure of the connection. */\r
-                                               xTaskResumeAll();\r
-                                       }\r
-\r
-                                       /* Send a message to the IP-task so it can work on this\r
-                                       socket.  Data is sent, let the IP-task work on it. */\r
-                                       pxSocket->u.xTCP.usTimeout = 1u;\r
-\r
-                                       if( xIsCallingFromIPTask() == pdFALSE )\r
-                                       {\r
-                                               /* Only send a TCP timer event when not called from the\r
-                                               IP-task. */\r
-                                               xSendEventToIPTask( eTCPTimerEvent );\r
-                                       }\r
-\r
-                                       xBytesLeft -= xByteCount;\r
-\r
-                                       if( xBytesLeft == 0 )\r
-                                       {\r
-                                               break;\r
-                                       }\r
-\r
-                                       /* As there are still bytes left to be sent, increase the\r
-                                       data pointer. */\r
-                                       pvBuffer = ( void * ) ( ( ( const uint8_t * ) pvBuffer) + xByteCount );\r
-                               }\r
-\r
-                               /* Not all bytes have been sent. In case the socket is marked as\r
-                               blocking sleep for a while. */\r
-                               if( xTimed == pdFALSE )\r
-                               {\r
-                                       /* Only in the first round, check for non-blocking. */\r
-                                       xRemainingTime = pxSocket->xSendBlockTime;\r
-\r
-                                       #if( ipconfigUSE_CALLBACKS != 0 )\r
-                                       {\r
-                                               if( xIsCallingFromIPTask() != pdFALSE )\r
-                                               {\r
-                                                       /* If this send function is called from within a\r
-                                                       call-back handler it may not block, otherwise\r
-                                                       chances would be big to get a deadlock: the IP-task\r
-                                                       waiting for     itself. */\r
-                                                       xRemainingTime = ( TickType_t ) 0;\r
-                                               }\r
-                                       }\r
-                                       #endif /* ipconfigUSE_CALLBACKS */\r
-\r
-                                       if( xRemainingTime == ( TickType_t ) 0 )\r
-                                       {\r
-                                               break;\r
-                                       }\r
-\r
-                                       if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )\r
-                                       {\r
-                                               break;\r
-                                       }\r
-\r
-                                       /* Don't get here a second time. */\r
-                                       xTimed = pdTRUE;\r
-\r
-                                       /* Fetch the current time. */\r
-                                       vTaskSetTimeOutState( &xTimeOut );\r
-                               }\r
-                               else\r
-                               {\r
-                                       /* Has the timeout been reached? */\r
-                                       if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )\r
-                                       {\r
-                                               break;\r
-                                       }\r
-                               }\r
-\r
-                               /* Go sleeping until down-stream events are received. */\r
-                               xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_SEND | eSOCKET_CLOSED,\r
-                                       pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );\r
-\r
-                               xByteCount = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );\r
-                       }\r
-\r
-                       /* How much was actually sent? */\r
-                       xByteCount = ( ( BaseType_t ) uxDataLength ) - xBytesLeft;\r
-\r
-                       if( xByteCount == 0 )\r
-                       {\r
-                               if( pxSocket->u.xTCP.ucTCPState > eESTABLISHED )\r
-                               {\r
-                                       xByteCount = ( BaseType_t ) -pdFREERTOS_ERRNO_ENOTCONN;\r
-                               }\r
-                               else\r
-                               {\r
-                                       if( ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) != pdFALSE )\r
-                                       {\r
-                                               FreeRTOS_debug_printf( ( "FreeRTOS_send: %u -> %lxip:%d: no space\n",\r
-                                                       pxSocket->usLocalPort,\r
-                                                       pxSocket->u.xTCP.ulRemoteIP,\r
-                                                       pxSocket->u.xTCP.usRemotePort ) );\r
-                                       }\r
-\r
-                                       xByteCount = ( BaseType_t ) -pdFREERTOS_ERRNO_ENOSPC;\r
-                               }\r
-                       }\r
-               }\r
-\r
-               return xByteCount;\r
-       }\r
-\r
-#endif /* ipconfigUSE_TCP */\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigUSE_TCP == 1 )\r
-\r
-       /*\r
-        * Request to put a socket in listen mode\r
-        */\r
-       BaseType_t FreeRTOS_listen( Socket_t xSocket, BaseType_t xBacklog )\r
-       {\r
-       FreeRTOS_Socket_t *pxSocket;\r
-       BaseType_t xResult = 0;\r
-\r
-               pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
-\r
-               /* listen() is allowed for a valid TCP socket in Closed state and already\r
-               bound. */\r
-               if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )\r
-               {\r
-                       xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;\r
-               }\r
-               else if( ( pxSocket->u.xTCP.ucTCPState != eCLOSED ) && ( pxSocket->u.xTCP.ucTCPState != eCLOSE_WAIT ) )\r
-               {\r
-                       /* Socket is in a wrong state. */\r
-                       xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;\r
-               }\r
-               else\r
-               {\r
-                       /* Backlog is interpreted here as "the maximum number of child\r
-                       sockets. */\r
-                       pxSocket->u.xTCP.usBacklog = ( uint16_t )FreeRTOS_min_int32( ( int32_t ) 0xffff, ( int32_t ) xBacklog );\r
-\r
-                       /* This cleaning is necessary only if a listening socket is being\r
-                       reused as it might have had a previous connection. */\r
-                       if( pxSocket->u.xTCP.bits.bReuseSocket )\r
-                       {\r
-                               if( pxSocket->u.xTCP.rxStream != NULL )\r
-                               {\r
-                                       vStreamBufferClear( pxSocket->u.xTCP.rxStream );\r
-                               }\r
-\r
-                               if( pxSocket->u.xTCP.txStream != NULL )\r
-                               {\r
-                                       vStreamBufferClear( pxSocket->u.xTCP.txStream );\r
-                               }\r
-\r
-                               memset( pxSocket->u.xTCP.xPacket.u.ucLastPacket, '\0', sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket ) );\r
-                               memset( &pxSocket->u.xTCP.xTCPWindow, '\0', sizeof( pxSocket->u.xTCP.xTCPWindow ) );\r
-                               memset( &pxSocket->u.xTCP.bits, '\0', sizeof( pxSocket->u.xTCP.bits ) );\r
-\r
-                               /* Now set the bReuseSocket flag again, because the bits have\r
-                               just been cleared. */\r
-                               pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE_UNSIGNED;\r
-                       }\r
-\r
-                       vTCPStateChange( pxSocket, eTCP_LISTEN );\r
-               }\r
-\r
-               return xResult;\r
-       }\r
-\r
-#endif /* ipconfigUSE_TCP */\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigUSE_TCP == 1 )\r
-\r
-       /* shutdown - shut down part of a full-duplex connection */\r
-       BaseType_t FreeRTOS_shutdown( Socket_t xSocket, BaseType_t xHow )\r
-       {\r
-       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
-       BaseType_t xResult;\r
-\r
-               if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )\r
-               {\r
-                       /*_RB_ Is this comment correct?  The socket is not of a type that\r
-                       supports the listen() operation. */\r
-                       xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;\r
-               }\r
-               else if ( pxSocket->u.xTCP.ucTCPState != eESTABLISHED )\r
-               {\r
-                       /*_RB_ Is this comment correct?  The socket is not of a type that\r
-                       supports the listen() operation. */\r
-                       xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;\r
-               }\r
-               else\r
-               {\r
-                       pxSocket->u.xTCP.bits.bUserShutdown = pdTRUE_UNSIGNED;\r
-\r
-                       /* Let the IP-task perform the shutdown of the connection. */\r
-                       pxSocket->u.xTCP.usTimeout = 1u;\r
-                       xSendEventToIPTask( eTCPTimerEvent );\r
-                       xResult = 0;\r
-               }\r
-               (void) xHow;\r
-\r
-               return xResult;\r
-       }\r
-\r
-#endif /* ipconfigUSE_TCP */\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigUSE_TCP == 1 )\r
-\r
-       /*\r
-        * A TCP timer has expired, now check all TCP sockets for:\r
-        * - Active connect\r
-        * - Send a delayed ACK\r
-        * - Send new data\r
-        * - Send a keep-alive packet\r
-        * - Check for timeout (in non-connected states only)\r
-        */\r
-       TickType_t xTCPTimerCheck( BaseType_t xWillSleep )\r
-       {\r
-       FreeRTOS_Socket_t *pxSocket;\r
-       TickType_t xShortest = pdMS_TO_TICKS( ( TickType_t ) ipTCP_TIMER_PERIOD_MS );\r
-       TickType_t xNow = xTaskGetTickCount();\r
-       static TickType_t xLastTime = 0u;\r
-       TickType_t xDelta = xNow - xLastTime;\r
-       ListItem_t* pxEnd = ( ListItem_t * ) listGET_END_MARKER( &xBoundTCPSocketsList );\r
-       ListItem_t *pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );\r
-\r
-               xLastTime = xNow;\r
-\r
-               if( xDelta == 0u )\r
-               {\r
-                       xDelta = 1u;\r
-               }\r
-\r
-               while( pxIterator != pxEnd )\r
-               {\r
-                       pxSocket = ( FreeRTOS_Socket_t * )listGET_LIST_ITEM_OWNER( pxIterator );\r
-                       pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator );\r
-\r
-                       /* Sockets with 'tmout == 0' do not need any regular attention. */\r
-                       if( pxSocket->u.xTCP.usTimeout == 0u )\r
-                       {\r
-                               continue;\r
-                       }\r
-\r
-                       if( xDelta < ( TickType_t ) pxSocket->u.xTCP.usTimeout )\r
-                       {\r
-                               pxSocket->u.xTCP.usTimeout = ( uint16_t ) ( ( ( TickType_t ) pxSocket->u.xTCP.usTimeout ) - xDelta );\r
-                       }\r
-                       else\r
-                       {\r
-                       int rc ;\r
-                               pxSocket->u.xTCP.usTimeout = 0u;\r
-                               rc = xTCPSocketCheck( pxSocket );\r
-\r
-                               /* Within this function, the socket might want to send a delayed\r
-                               ack or send out data or whatever it needs to do. */\r
-                               if( rc < 0 )\r
-                               {\r
-                                       /* Continue because the socket was deleted. */\r
-                                       continue;\r
-                               }\r
-                       }\r
-\r
-                       /* In xEventBits the driver may indicate that the socket has\r
-                       important events for the user.  These are only done just before the\r
-                       IP-task goes to sleep. */\r
-                       if( pxSocket->xEventBits != 0u )\r
-                       {\r
-                               if( xWillSleep != pdFALSE )\r
-                               {\r
-                                       /* The IP-task is about to go to sleep, so messages can be\r
-                                       sent to the socket owners. */\r
-                                       vSocketWakeUpUser( pxSocket );\r
-                               }\r
-                               else\r
-                               {\r
-                                       /* Or else make sure this will be called again to wake-up\r
-                                       the sockets' owner. */\r
-                                       xShortest = ( TickType_t ) 0;\r
-                               }\r
-                       }\r
-\r
-                       if( ( pxSocket->u.xTCP.usTimeout != 0u ) && ( xShortest > ( TickType_t ) pxSocket->u.xTCP.usTimeout ) )\r
-                       {\r
-                               xShortest = ( TickType_t ) pxSocket->u.xTCP.usTimeout;\r
-                       }\r
-               }\r
-\r
-               return xShortest;\r
-       }\r
-\r
-#endif /* ipconfigUSE_TCP */\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigUSE_TCP == 1 )\r
-\r
-       /*\r
-        * TCP: as multiple sockets may be bound to the same local port number\r
-        * looking up a socket is a little more complex:\r
-        * Both a local port, and a remote port and IP address are being used\r
-        * For a socket in listening mode, the remote port and IP address are both 0\r
-        */\r
-       FreeRTOS_Socket_t *pxTCPSocketLookup( uint32_t ulLocalIP, UBaseType_t uxLocalPort, uint32_t ulRemoteIP, UBaseType_t uxRemotePort )\r
-       {\r
-       ListItem_t *pxIterator;\r
-       FreeRTOS_Socket_t *pxResult = NULL, *pxListenSocket = NULL;\r
-       MiniListItem_t *pxEnd = ( MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );\r
-\r
-               /* Parameter not yet supported. */\r
-               ( void ) ulLocalIP;\r
-\r
-               for( pxIterator  = ( ListItem_t * ) listGET_NEXT( pxEnd );\r
-                        pxIterator != ( ListItem_t * ) pxEnd;\r
-                        pxIterator  = ( ListItem_t * ) listGET_NEXT( pxIterator ) )\r
-               {\r
-                       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );\r
-\r
-                       if( pxSocket->usLocalPort == ( uint16_t ) uxLocalPort )\r
-                       {\r
-                               if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN )\r
-                               {\r
-                                       /* If this is a socket listening to uxLocalPort, remember it\r
-                                       in case there is no perfect match. */\r
-                                       pxListenSocket = pxSocket;\r
-                               }\r
-                               else if( ( pxSocket->u.xTCP.usRemotePort == ( uint16_t ) uxRemotePort ) && ( pxSocket->u.xTCP.ulRemoteIP == ulRemoteIP ) )\r
-                               {\r
-                                       /* For sockets not in listening mode, find a match with\r
-                                       xLocalPort, ulRemoteIP AND xRemotePort. */\r
-                                       pxResult = pxSocket;\r
-                                       break;\r
-                               }\r
-                       }\r
-               }\r
-               if( pxResult == NULL )\r
-               {\r
-                       /* An exact match was not found, maybe a listening socket was\r
-                       found. */\r
-                       pxResult = pxListenSocket;\r
-               }\r
-\r
-               return pxResult;\r
-       }\r
-\r
-#endif /* ipconfigUSE_TCP */\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigUSE_TCP == 1 )\r
-\r
-    const struct xSTREAM_BUFFER *FreeRTOS_get_rx_buf( Socket_t xSocket )\r
-    {\r
-    FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * )xSocket;\r
-    struct xSTREAM_BUFFER *pxReturn = NULL;\r
-\r
-        /* Confirm that this is a TCP socket before dereferencing structure\r
-        member pointers. */\r
-        if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdTRUE )\r
-        {\r
-            pxReturn = pxSocket->u.xTCP.rxStream;\r
-        }\r
-\r
-        return pxReturn;\r
-    }\r
-\r
-#endif /* ipconfigUSE_TCP */\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigUSE_TCP == 1 )\r
-\r
-       static StreamBuffer_t *prvTCPCreateStream ( FreeRTOS_Socket_t *pxSocket, BaseType_t xIsInputStream )\r
-       {\r
-       StreamBuffer_t *pxBuffer;\r
-       size_t uxLength;\r
-       size_t uxSize;\r
-\r
-               /* Now that a stream is created, the maximum size is fixed before\r
-               creation, it could still be changed with setsockopt(). */\r
-               if( xIsInputStream != pdFALSE )\r
-               {\r
-                       uxLength = pxSocket->u.xTCP.uxRxStreamSize;\r
-\r
-                       if( pxSocket->u.xTCP.uxLittleSpace == 0ul )\r
-                       {\r
-                               pxSocket->u.xTCP.uxLittleSpace  = ( sock20_PERCENT * pxSocket->u.xTCP.uxRxStreamSize ) / sock100_PERCENT;\r
-                       }\r
-\r
-                       if( pxSocket->u.xTCP.uxEnoughSpace == 0ul )\r
-                       {\r
-                               pxSocket->u.xTCP.uxEnoughSpace = ( sock80_PERCENT * pxSocket->u.xTCP.uxRxStreamSize ) / sock100_PERCENT;\r
-                       }\r
-               }\r
-               else\r
-               {\r
-                       uxLength = pxSocket->u.xTCP.uxTxStreamSize;\r
-               }\r
-\r
-               /* Add an extra 4 (or 8) bytes. */\r
-               uxLength += sizeof( size_t );\r
-\r
-               /* And make the length a multiple of sizeof( size_t ). */\r
-               uxLength &= ~( sizeof( size_t ) - 1u );\r
-\r
-               uxSize = sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) + uxLength;\r
-\r
-               pxBuffer = ( StreamBuffer_t * )pvPortMallocLarge( uxSize );\r
-\r
-               if( pxBuffer == NULL )\r
-               {\r
-                       FreeRTOS_debug_printf( ( "prvTCPCreateStream: malloc failed\n" ) );\r
-                       pxSocket->u.xTCP.bits.bMallocError = pdTRUE_UNSIGNED;\r
-                       vTCPStateChange( pxSocket, eCLOSE_WAIT );\r
-               }\r
-               else\r
-               {\r
-                       /* Clear the markers of the stream */\r
-                       memset( pxBuffer, '\0', sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) );\r
-                       pxBuffer->LENGTH = ( size_t ) uxLength ;\r
-\r
-                       if( xTCPWindowLoggingLevel != 0 )\r
-                       {\r
-                               FreeRTOS_debug_printf( ( "prvTCPCreateStream: %cxStream created %lu bytes (total %lu)\n", xIsInputStream ? 'R' : 'T', uxLength, uxSize ) );\r
-                       }\r
-\r
-                       if( xIsInputStream != 0 )\r
-                       {\r
-                               pxSocket->u.xTCP.rxStream = pxBuffer;\r
-                       }\r
-                       else\r
-                       {\r
-                               pxSocket->u.xTCP.txStream = pxBuffer;\r
-                       }\r
-               }\r
-\r
-               return pxBuffer;\r
-       }\r
-\r
-#endif /* ipconfigUSE_TCP */\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigUSE_TCP == 1 )\r
-\r
-       /*\r
-        * Add data to the RxStream.  When uxOffset > 0, data has come in out-of-order\r
-        * and will be put in front of the head so it can not be popped by the user.\r
-        */\r
-       int32_t lTCPAddRxdata( FreeRTOS_Socket_t *pxSocket, size_t uxOffset, const uint8_t *pcData, uint32_t ulByteCount )\r
-       {\r
-       StreamBuffer_t *pxStream = pxSocket->u.xTCP.rxStream;\r
-       int32_t xResult;\r
-       #if( ipconfigUSE_CALLBACKS == 1 )\r
-               BaseType_t bHasHandler = ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xTCP.pxHandleReceive );\r
-               const uint8_t *pucBuffer = NULL;\r
-       #endif /* ipconfigUSE_CALLBACKS */\r
-\r
-               /* int32_t uxStreamBufferAdd( pxBuffer, uxOffset, pucData, aCount )\r
-               if( pucData != NULL ) copy data the the buffer\r
-               if( pucData == NULL ) no copying, just advance rxHead\r
-               if( uxOffset != 0 ) Just store data which has come out-of-order\r
-               if( uxOffset == 0 ) Also advance rxHead */\r
-               if( pxStream == NULL )\r
-               {\r
-                       pxStream = prvTCPCreateStream( pxSocket, pdTRUE );\r
-                       if( pxStream == NULL )\r
-                       {\r
-                               return -1;\r
-                       }\r
-               }\r
-\r
-               #if( ipconfigUSE_CALLBACKS == 1 )\r
-               {\r
-                       if( ( bHasHandler != pdFALSE ) && ( uxStreamBufferGetSize( pxStream ) == 0u ) && ( uxOffset == 0ul ) && ( pcData != NULL ) )\r
-                       {\r
-                               /* Data can be passed directly to the user */\r
-                               pucBuffer = pcData;\r
-\r
-                               /* Zero-copy for call-back: no need to add the bytes to the\r
-                               stream, only the pointer will be advanced by uxStreamBufferAdd(). */\r
-                               pcData = NULL;\r
-                       }\r
-               }\r
-               #endif /* ipconfigUSE_CALLBACKS */\r
-\r
-               xResult = ( int32_t ) uxStreamBufferAdd( pxStream, uxOffset, pcData, ( size_t ) ulByteCount );\r
-\r
-               #if( ipconfigHAS_DEBUG_PRINTF != 0 )\r
-               {\r
-                       if( xResult != ( int32_t ) ulByteCount )\r
-                       {\r
-                               FreeRTOS_debug_printf( ( "lTCPAddRxdata: at %ld: %ld/%lu bytes (tail %lu head %lu space %lu front %lu)\n",\r
-                                       uxOffset, xResult, ulByteCount,\r
-                                       pxStream->uxTail,\r
-                                       pxStream->uxHead,\r
-                                       uxStreamBufferFrontSpace( pxStream ),\r
-                                       pxStream->uxFront ) );\r
-                       }\r
-               }\r
-               #endif /* ipconfigHAS_DEBUG_PRINTF */\r
-\r
-               if( uxOffset == 0u )\r
-               {\r
-                       /* Data is being added to rxStream at the head (offs = 0) */\r
-                       #if( ipconfigUSE_CALLBACKS == 1 )\r
-                               if( bHasHandler != pdFALSE )\r
-                               {\r
-                                       /* The socket owner has installed an OnReceive handler. Pass the\r
-                                       Rx data, without copying from the rxStream, to the user. */\r
-                                       for (;;)\r
-                                       {\r
-                                               uint8_t *ucReadPtr = NULL;\r
-                                               uint32_t ulCount;\r
-                                               if( pucBuffer != NULL )\r
-                                               {\r
-                                                       ucReadPtr = ( uint8_t * )pucBuffer;\r
-                                                       ulCount = ulByteCount;\r
-                                                       pucBuffer = NULL;\r
-                                               }\r
-                                               else\r
-                                               {\r
-                                                       ulCount = ( uint32_t ) uxStreamBufferGetPtr( pxStream, &( ucReadPtr ) );\r
-                                               }\r
-\r
-                                               if( ulCount == 0ul )\r
-                                               {\r
-                                                       break;\r
-                                               }\r
-\r
-                                               pxSocket->u.xTCP.pxHandleReceive( ( Socket_t )pxSocket, ( void* )ucReadPtr, ( size_t ) ulCount );\r
-                                               uxStreamBufferGet( pxStream, 0ul, NULL, ( size_t ) ulCount, pdFALSE );\r
-                                       }\r
-                               } else\r
-                       #endif /* ipconfigUSE_CALLBACKS */\r
-                       {\r
-                               /* See if running out of space. */\r
-                               if( pxSocket->u.xTCP.bits.bLowWater == pdFALSE_UNSIGNED )\r
-                               {\r
-                                       size_t uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );\r
-                                       if( uxFrontSpace <= pxSocket->u.xTCP.uxLittleSpace  )\r
-                                       {\r
-                                               pxSocket->u.xTCP.bits.bLowWater = pdTRUE_UNSIGNED;\r
-                                               pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;\r
-\r
-                                               /* bLowWater was reached, send the changed window size. */\r
-                                               pxSocket->u.xTCP.usTimeout = 1u;\r
-                                               xSendEventToIPTask( eTCPTimerEvent );\r
-                                       }\r
-                               }\r
-\r
-                               /* New incoming data is available, wake up the user.   User's\r
-                               semaphores will be set just before the IP-task goes asleep. */\r
-                               pxSocket->xEventBits |= eSOCKET_RECEIVE;\r
-\r
-                               #if ipconfigSUPPORT_SELECT_FUNCTION == 1\r
-                               {\r
-                                       if( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 )\r
-                                       {\r
-                                               pxSocket->xEventBits |= ( eSELECT_READ << SOCKET_EVENT_BIT_COUNT );\r
-                                       }\r
-                               }\r
-                               #endif\r
-                       }\r
-               }\r
-\r
-               return xResult;\r
-       }\r
-\r
-#endif /* ipconfigUSE_TCP */\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigUSE_TCP == 1 )\r
-\r
-       /* Function to get the remote address and IP port */\r
-       BaseType_t FreeRTOS_GetRemoteAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress )\r
-       {\r
-       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
-       BaseType_t xResult;\r
-\r
-               if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
-               {\r
-                       xResult = -pdFREERTOS_ERRNO_EINVAL;\r
-               }\r
-               else\r
-               {\r
-                       /* BSD style sockets communicate IP and port addresses in network\r
-                       byte order.\r
-\r
-                       IP address of remote machine. */\r
-                       pxAddress->sin_addr = FreeRTOS_htonl ( pxSocket->u.xTCP.ulRemoteIP );\r
-\r
-                       /* Port on remote machine. */\r
-                       pxAddress->sin_port = FreeRTOS_htons ( pxSocket->u.xTCP.usRemotePort );\r
-\r
-                       xResult = ( BaseType_t ) sizeof( ( *pxAddress ) );\r
-               }\r
-\r
-               return xResult;\r
-       }\r
-\r
-#endif /* ipconfigUSE_TCP */\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigUSE_TCP == 1 )\r
-\r
-       /* Returns the number of bytes that may be added to txStream */\r
-       BaseType_t FreeRTOS_maywrite( Socket_t xSocket )\r
-       {\r
-       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
-       BaseType_t xResult;\r
-\r
-               if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
-               {\r
-                       xResult = -pdFREERTOS_ERRNO_EINVAL;\r
-               }\r
-               else if( pxSocket->u.xTCP.ucTCPState != eESTABLISHED )\r
-               {\r
-                       if( ( pxSocket->u.xTCP.ucTCPState < eCONNECT_SYN ) || ( pxSocket->u.xTCP.ucTCPState > eESTABLISHED ) )\r
-                       {\r
-                               xResult = -1;\r
-                       }\r
-                       else\r
-                       {\r
-                               xResult = 0;\r
-                       }\r
-               }\r
-               else if( pxSocket->u.xTCP.txStream == NULL )\r
-               {\r
-                       xResult = ( BaseType_t ) pxSocket->u.xTCP.uxTxStreamSize;\r
-               }\r
-               else\r
-               {\r
-                       xResult = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );\r
-               }\r
-\r
-               return xResult;\r
-       }\r
-\r
-#endif /* ipconfigUSE_TCP */\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigUSE_TCP ==1 )\r
-\r
-       BaseType_t FreeRTOS_tx_space( Socket_t xSocket )\r
-       {\r
-       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
-       BaseType_t xReturn;\r
-\r
-               if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
-               {\r
-                       xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
-               }\r
-               else\r
-               {\r
-                       if( pxSocket->u.xTCP.txStream != NULL )\r
-                       {\r
-                               xReturn = ( BaseType_t ) uxStreamBufferGetSpace ( pxSocket->u.xTCP.txStream );\r
-                       }\r
-                       else\r
-                       {\r
-                               xReturn = ( BaseType_t ) pxSocket->u.xTCP.uxTxStreamSize;\r
-                       }\r
-               }\r
-\r
-               return xReturn;\r
-       }\r
-\r
-#endif /* ipconfigUSE_TCP */\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigUSE_TCP == 1 )\r
-\r
-       BaseType_t FreeRTOS_tx_size( Socket_t xSocket )\r
-       {\r
-       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
-       BaseType_t xReturn;\r
-\r
-               if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
-               {\r
-                       xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
-               }\r
-               else\r
-               {\r
-                       if( pxSocket->u.xTCP.txStream != NULL )\r
-                       {\r
-                               xReturn = ( BaseType_t ) uxStreamBufferGetSize ( pxSocket->u.xTCP.txStream );\r
-                       }\r
-                       else\r
-                       {\r
-                               xReturn = 0;\r
-                       }\r
-               }\r
-\r
-               return xReturn;\r
-       }\r
-\r
-#endif /* ipconfigUSE_TCP */\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigUSE_TCP == 1 )\r
-\r
-       /* Returns pdTRUE if TCP socket is connected. */\r
-       BaseType_t FreeRTOS_issocketconnected( Socket_t xSocket )\r
-       {\r
-       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
-       BaseType_t xReturn = pdFALSE;\r
-\r
-               if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
-               {\r
-                       xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
-               }\r
-               else\r
-               {\r
-                       if( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED )\r
-                       {\r
-                               if( pxSocket->u.xTCP.ucTCPState < eCLOSE_WAIT )\r
-                               {\r
-                                       xReturn = pdTRUE;\r
-                               }\r
-                       }\r
-               }\r
-\r
-               return xReturn;\r
-       }\r
-\r
-#endif /* ipconfigUSE_TCP */\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigUSE_TCP == 1 )\r
-\r
-       /* returns the actual size of MSS being used */\r
-       BaseType_t FreeRTOS_mss( Socket_t xSocket )\r
-       {\r
-       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
-       BaseType_t xReturn;\r
-\r
-               if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
-               {\r
-                       xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
-               }\r
-               else\r
-               {\r
-                       /* usCurMSS is declared as uint16_t to save space.  FreeRTOS_mss()\r
-                       will often be used in signed native-size expressions cast it to\r
-                       BaseType_t. */\r
-                       xReturn = ( BaseType_t ) ( pxSocket->u.xTCP.usCurMSS );\r
-               }\r
-\r
-               return xReturn;\r
-       }\r
-\r
-#endif /* ipconfigUSE_TCP */\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigUSE_TCP == 1 )\r
-\r
-       /* HT: for internal use only: return the connection status */\r
-       BaseType_t FreeRTOS_connstatus( Socket_t xSocket )\r
-       {\r
-       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
-       BaseType_t xReturn;\r
-\r
-               if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
-               {\r
-                       xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
-               }\r
-               else\r
-               {\r
-                       /* Cast it to BaseType_t */\r
-                       xReturn = ( BaseType_t ) ( pxSocket->u.xTCP.ucTCPState );\r
-               }\r
-\r
-               return xReturn;\r
-       }\r
-\r
-#endif /* ipconfigUSE_TCP */\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigUSE_TCP == 1 )\r
-\r
-       /*\r
-        * Returns the number of bytes which can be read.\r
-        */\r
-       BaseType_t FreeRTOS_rx_size( Socket_t xSocket )\r
-       {\r
-       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
-       BaseType_t xReturn;\r
-\r
-               if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
-               {\r
-                       xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
-               }\r
-               else if( pxSocket->u.xTCP.rxStream != NULL )\r
-               {\r
-                       xReturn = ( BaseType_t ) uxStreamBufferGetSize( pxSocket->u.xTCP.rxStream );\r
-               }\r
-               else\r
-               {\r
-                       xReturn = 0;\r
-               }\r
-\r
-               return xReturn;\r
-       }\r
-\r
-#endif /* ipconfigUSE_TCP */\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigUSE_TCP == 1 )\r
-\r
-       void FreeRTOS_netstat( void )\r
-       {\r
-       IPStackEvent_t xAskEvent;\r
-\r
-               /* Ask the IP-task to call vTCPNetStat()\r
-                * to avoid accessing xBoundTCPSocketsList\r
-                */\r
-               xAskEvent.eEventType = eTCPNetStat;\r
-               xAskEvent.pvData = ( void * ) NULL;\r
-               xSendEventStructToIPTask( &xAskEvent, 1000u );\r
-       }\r
-\r
-#endif /* ipconfigUSE_TCP */\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ( ipconfigHAS_PRINTF != 0 ) && ( ipconfigUSE_TCP == 1 ) )\r
-\r
-       void vTCPNetStat( void )\r
-       {\r
-       /* Show a simple listing of all created sockets and their connections */\r
-       ListItem_t *pxIterator;\r
-       BaseType_t count = 0;\r
-\r
-               if( listLIST_IS_INITIALISED( &xBoundTCPSocketsList ) == pdFALSE )\r
-               {\r
-                       FreeRTOS_printf( ( "PLUS-TCP not initialized\n" ) );\r
-               }\r
-               else\r
-               {\r
-                       FreeRTOS_printf( ( "Prot Port IP-Remote    : Port  R/T Status      Alive  tmout Child\n" ) );\r
-                       for( pxIterator  = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );\r
-                                pxIterator != ( ListItem_t * ) listGET_END_MARKER( &xBoundTCPSocketsList );\r
-                                pxIterator  = ( ListItem_t * ) listGET_NEXT( pxIterator ) )\r
-                       {\r
-                               FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );\r
-                               #if( ipconfigTCP_KEEP_ALIVE == 1 )\r
-                                       TickType_t age = xTaskGetTickCount() - pxSocket->u.xTCP.xLastAliveTime;\r
-                               #else\r
-                                       TickType_t age = 0u;\r
-                               #endif\r
-                               #if( ipconfigUSE_CALLBACKS == 1 )\r
-                                       void *pxHandleReceive = (void*)pxSocket->u.xTCP.pxHandleReceive;\r
-                               #else\r
-                                       void *pxHandleReceive = (void*)NULL;\r
-                               #endif\r
-                               char ucChildText[16] = "";\r
-                               if (pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN)\r
-                               {\r
-                                       const int32_t copied_len = snprintf( ucChildText, sizeof( ucChildText ), " %d/%d",\r
-                                               ( int ) pxSocket->u.xTCP.usChildCount,\r
-                                               ( int ) pxSocket->u.xTCP.usBacklog);\r
-                                       /* These should never evaluate to false since the buffers are both shorter than 5-6 characters (<=65535) */\r
-                                       configASSERT( copied_len >= 0 );\r
-                                       configASSERT( copied_len < sizeof( ucChildText ) );\r
-                               }\r
-                               FreeRTOS_printf( ( "TCP %5d %-16lxip:%5d %d/%d %-13.13s %6lu %6u%s\n",\r
-                                       pxSocket->usLocalPort,          /* Local port on this machine */\r
-                                       pxSocket->u.xTCP.ulRemoteIP,    /* IP address of remote machine */\r
-                                       pxSocket->u.xTCP.usRemotePort,  /* Port on remote machine */\r
-                                       pxSocket->u.xTCP.rxStream != NULL,\r
-                                       pxSocket->u.xTCP.txStream != NULL,\r
-                                       FreeRTOS_GetTCPStateName( pxSocket->u.xTCP.ucTCPState ),\r
-                                       (age > 999999 ? 999999 : age), /* Format 'age' for printing */\r
-                                       pxSocket->u.xTCP.usTimeout,\r
-                                       ucChildText ) );\r
-                                       /* Remove compiler warnings if FreeRTOS_debug_printf() is not defined. */\r
-                                       ( void ) pxHandleReceive;\r
-                               count++;\r
-                       }\r
-\r
-                       for( pxIterator  = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundUDPSocketsList );\r
-                                pxIterator != ( ListItem_t * ) listGET_END_MARKER( &xBoundUDPSocketsList );\r
-                                pxIterator  = ( ListItem_t * ) listGET_NEXT( pxIterator ) )\r
-                       {\r
-                               /* Local port on this machine */\r
-                               FreeRTOS_printf( ( "UDP Port %5u\n",\r
-                                       FreeRTOS_ntohs( listGET_LIST_ITEM_VALUE( pxIterator ) ) ) );\r
-                               count++;\r
-                       }\r
-\r
-                       FreeRTOS_printf( ( "FreeRTOS_netstat: %lu sockets %lu < %lu < %d buffers free\n",\r
-                               count,\r
-                               uxGetMinimumFreeNetworkBuffers( ),\r
-                               uxGetNumberOfFreeNetworkBuffers( ),\r
-                               ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ) );\r
-               }\r
-       }\r
-\r
-#endif /* ( ( ipconfigHAS_PRINTF != 0 ) && ( ipconfigUSE_TCP == 1 ) ) */\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
-\r
-       void vSocketSelect( SocketSelect_t *pxSocketSet )\r
-       {\r
-       BaseType_t xRound;\r
-       EventBits_t xSocketBits, xBitsToClear;\r
-       #if ipconfigUSE_TCP == 1\r
-               BaseType_t xLastRound = 1;\r
-       #else\r
-               BaseType_t xLastRound = 0;\r
-       #endif\r
-\r
-               /* These flags will be switched on after checking the socket status. */\r
-               EventBits_t xGroupBits = 0;\r
-               pxSocketSet->pxSocket = NULL;\r
-\r
-               for( xRound = 0; xRound <= xLastRound; xRound++ )\r
-               {\r
-                       const ListItem_t *pxIterator;\r
-                       const MiniListItem_t *pxEnd;\r
-                       if( xRound == 0 )\r
-                       {\r
-                               pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundUDPSocketsList );\r
-                       }\r
-               #if ipconfigUSE_TCP == 1\r
-                       else\r
-                       {\r
-                               pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );\r
-                       }\r
-               #endif /* ipconfigUSE_TCP == 1 */\r
-                       for( pxIterator = ( const ListItem_t * ) ( listGET_NEXT( pxEnd ) );\r
-                                pxIterator != ( const ListItem_t * ) pxEnd;\r
-                                pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )\r
-                       {\r
-                               FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );\r
-                               if( pxSocket->pxSocketSet != pxSocketSet )\r
-                               {\r
-                                       /* Socket does not belong to this select group. */\r
-                                       continue;\r
-                               }\r
-                               xSocketBits = 0;\r
-\r
-                               #if( ipconfigUSE_TCP == 1 )\r
-                                       if( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP )\r
-                                       {\r
-                                               /* Check if the socket has already been accepted by the\r
-                                               owner.  If not, it is useless to return it from a\r
-                                               select(). */\r
-                                               BaseType_t bAccepted = pdFALSE;\r
-\r
-                                               if( pxSocket->u.xTCP.bits.bPassQueued == pdFALSE_UNSIGNED )\r
-                                               {\r
-                                                       if( pxSocket->u.xTCP.bits.bPassAccept == pdFALSE_UNSIGNED )\r
-                                                       {\r
-                                                               bAccepted = pdTRUE;\r
-                                                       }\r
-                                               }\r
-\r
-                                               /* Is the set owner interested in READ events? */\r
-                                               if( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 )\r
-                                               {\r
-                                                       if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN )\r
-                                                       {\r
-                                                               if( ( pxSocket->u.xTCP.pxPeerSocket != NULL ) && ( pxSocket->u.xTCP.pxPeerSocket->u.xTCP.bits.bPassAccept != 0 ) )\r
-                                                               {\r
-                                                                       xSocketBits |= eSELECT_READ;\r
-                                                               }\r
-                                                       }\r
-                                                       else if( ( pxSocket->u.xTCP.bits.bReuseSocket != pdFALSE_UNSIGNED ) && ( pxSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED ) )\r
-                                                       {\r
-                                                               /* This socket has the re-use flag. After connecting it turns into\r
-                                                               aconnected socket. Set the READ event, so that accept() will be called. */\r
-                                                               xSocketBits |= eSELECT_READ;\r
-                                                       }\r
-                                                       else if( ( bAccepted != 0 ) && ( FreeRTOS_recvcount( pxSocket ) > 0 ) )\r
-                                                       {\r
-                                                               xSocketBits |= eSELECT_READ;\r
-                                                       }\r
-                                               }\r
-                                               /* Is the set owner interested in EXCEPTION events? */\r
-                                               if( ( pxSocket->xSelectBits & eSELECT_EXCEPT ) != 0 )\r
-                                               {\r
-                                                       if( ( pxSocket->u.xTCP.ucTCPState == eCLOSE_WAIT ) || ( pxSocket->u.xTCP.ucTCPState == eCLOSED ) )\r
-                                                       {\r
-                                                               xSocketBits |= eSELECT_EXCEPT;\r
-                                                       }\r
-                                               }\r
-\r
-                                               /* Is the set owner interested in WRITE events? */\r
-                                               if( ( pxSocket->xSelectBits & eSELECT_WRITE ) != 0 )\r
-                                               {\r
-                                                       BaseType_t bMatch = pdFALSE;\r
-\r
-                                                       if( bAccepted != 0 )\r
-                                                       {\r
-                                                               if( FreeRTOS_tx_space( pxSocket ) > 0 )\r
-                                                               {\r
-                                                                       bMatch = pdTRUE;\r
-                                                               }\r
-                                                       }\r
-\r
-                                                       if( bMatch == pdFALSE )\r
-                                                       {\r
-                                                               if( ( pxSocket->u.xTCP.bits.bConnPrepared != pdFALSE_UNSIGNED ) &&\r
-                                                                       ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) &&\r
-                                                                       ( pxSocket->u.xTCP.bits.bConnPassed == pdFALSE_UNSIGNED ) )\r
-                                                               {\r
-                                                                       pxSocket->u.xTCP.bits.bConnPassed = pdTRUE_UNSIGNED;\r
-                                                                       bMatch = pdTRUE;\r
-                                                               }\r
-                                                       }\r
-\r
-                                                       if( bMatch != pdFALSE )\r
-                                                       {\r
-                                                               xSocketBits |= eSELECT_WRITE;\r
-                                                       }\r
-                                               }\r
-                                       }\r
-                                       else\r
-                               #endif /* ipconfigUSE_TCP == 1 */\r
-                               {\r
-                                       /* Select events for UDP are simpler. */\r
-                                       if( ( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 ) &&\r
-                                               ( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) > 0U ) )\r
-                                       {\r
-                                               xSocketBits |= eSELECT_READ;\r
-                                       }\r
-                                       /* The WRITE and EXCEPT bits are not used for UDP */\r
-                               }       /* if( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP ) */\r
-\r
-                               /* Each socket keeps its own event flags, which are looked-up\r
-                               by FreeRTOS_FD_ISSSET() */\r
-                               pxSocket->xSocketBits = xSocketBits;\r
-\r
-                               /* The ORed value will be used to set the bits in the event\r
-                               group. */\r
-                               xGroupBits |= xSocketBits;\r
-\r
-                       }       /* for( pxIterator ... ) */\r
-               }       /* for( xRound = 0; xRound <= xLastRound; xRound++ ) */\r
-\r
-               xBitsToClear = xEventGroupGetBits( pxSocketSet->xSelectGroup );\r
-\r
-               /* Now set the necessary bits. */\r
-               xBitsToClear = ( xBitsToClear & ~xGroupBits ) & eSELECT_ALL;\r
-\r
-               #if( ipconfigSUPPORT_SIGNALS != 0 )\r
-               {\r
-                       /* Maybe the socketset was signalled, but don't\r
-                       clear the 'eSELECT_INTR' bit here, as it will be used\r
-                       and cleared in FreeRTOS_select(). */\r
-                       xBitsToClear &= ( EventBits_t ) ~eSELECT_INTR;\r
-               }\r
-               #endif /* ipconfigSUPPORT_SIGNALS */\r
-\r
-               if( xBitsToClear != 0 )\r
-               {\r
-                       xEventGroupClearBits( pxSocketSet->xSelectGroup, xBitsToClear );\r
-               }\r
-\r
-               /* Now include eSELECT_CALL_IP to wakeup the caller. */\r
-               xEventGroupSetBits( pxSocketSet->xSelectGroup, xGroupBits | eSELECT_CALL_IP );\r
-       }\r
-\r
-#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigSUPPORT_SIGNALS != 0 )\r
-\r
-       /* Send a signal to the task which reads from this socket. */\r
-       BaseType_t FreeRTOS_SignalSocket( Socket_t xSocket )\r
-       {\r
-       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
-       BaseType_t xReturn;\r
-\r
-               if( pxSocket == NULL )\r
-               {\r
-                       xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
-               }\r
-               else\r
-       #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
-               if( ( pxSocket->pxSocketSet != NULL ) && ( pxSocket->pxSocketSet->xSelectGroup != NULL ) )\r
-               {\r
-                       xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, eSELECT_INTR );\r
-                       xReturn = 0;\r
-               }\r
-               else\r
-       #endif /* ipconfigSUPPORT_SELECT_FUNCTION */\r
-               if( pxSocket->xEventGroup != NULL )\r
-               {\r
-                       xEventGroupSetBits( pxSocket->xEventGroup, eSOCKET_INTR );\r
-                       xReturn = 0;\r
-               }\r
-               else\r
-               {\r
-                       xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
-               }\r
-\r
-               return xReturn;\r
-       }\r
-\r
-#endif /* ipconfigSUPPORT_SIGNALS */\r
-/*-----------------------------------------------------------*/\r
-\r
-#if( ipconfigSUPPORT_SIGNALS != 0 )\r
-\r
-       /* Send a signal to the task which reads from this socket (FromISR version). */\r
-       BaseType_t FreeRTOS_SignalSocketFromISR( Socket_t xSocket, BaseType_t *pxHigherPriorityTaskWoken )\r
-       {\r
-       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
-       BaseType_t xReturn;\r
-       IPStackEvent_t xEvent;\r
-       extern QueueHandle_t xNetworkEventQueue;\r
-\r
-               configASSERT( pxSocket != NULL );\r
-               configASSERT( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP );\r
-               configASSERT( pxSocket->xEventGroup );\r
-\r
-               xEvent.eEventType = eSocketSignalEvent;\r
-               xEvent.pvData = ( void * )pxSocket;\r
-\r
-               /* The IP-task will call FreeRTOS_SignalSocket for this socket. */\r
-               xReturn = xQueueSendToBackFromISR( xNetworkEventQueue, &xEvent, pxHigherPriorityTaskWoken );\r
-\r
-               return xReturn;\r
-       }\r
-\r
-#endif /* ipconfigSUPPORT_SIGNALS */\r
-/*-----------------------------------------------------------*/\r
+/*
+ * FreeRTOS+TCP V2.2.0
+ * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * http://aws.amazon.com/freertos
+ * http://www.FreeRTOS.org
+ */
+
+/* Standard includes. */
+#include <stdint.h>
+#include <stdio.h>
+
+/* FreeRTOS includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+#include "semphr.h"
+
+/* FreeRTOS+TCP includes. */
+#include "FreeRTOS_UDP_IP.h"
+#include "FreeRTOS_IP.h"
+#include "FreeRTOS_Sockets.h"
+#include "FreeRTOS_IP_Private.h"
+#include "FreeRTOS_DNS.h"
+#include "NetworkBufferManagement.h"
+
+/* The ItemValue of the sockets xBoundSocketListItem member holds the socket's
+port number. */
+#define socketSET_SOCKET_PORT( pxSocket, usPort ) listSET_LIST_ITEM_VALUE( ( &( ( pxSocket )->xBoundSocketListItem ) ), ( usPort ) )
+#define socketGET_SOCKET_PORT( pxSocket ) listGET_LIST_ITEM_VALUE( ( &( ( pxSocket )->xBoundSocketListItem ) ) )
+
+/* Test if a socket it bound which means it is either included in
+xBoundUDPSocketsList or xBoundTCPSocketsList */
+#define socketSOCKET_IS_BOUND( pxSocket )        ( listLIST_ITEM_CONTAINER( & ( pxSocket )->xBoundSocketListItem ) != NULL )
+
+/* If FreeRTOS_sendto() is called on a socket that is not bound to a port
+number then, depending on the FreeRTOSIPConfig.h settings, it might be that a
+port number is automatically generated for the socket.  Automatically generated
+port numbers will be between socketAUTO_PORT_ALLOCATION_START_NUMBER and
+0xffff.
+
+Per https://tools.ietf.org/html/rfc6056, "the dynamic ports consist of the range
+49152-65535. However, ephemeral port selection algorithms should use the whole
+range 1024-65535" excluding those already in use (inbound or outbound). */
+#if !defined( socketAUTO_PORT_ALLOCATION_START_NUMBER )
+       #define socketAUTO_PORT_ALLOCATION_START_NUMBER ( ( uint16_t ) 0x0400 )
+#endif
+
+#define socketAUTO_PORT_ALLOCATION_MAX_NUMBER   ( ( uint16_t ) 0xffff )
+
+/* The number of octets that make up an IP address. */
+#define socketMAX_IP_ADDRESS_OCTETS            4u
+
+/* A block time of 0 simply means "don't block". */
+#define socketDONT_BLOCK                               ( ( TickType_t ) 0 )
+
+#if( ( ipconfigUSE_TCP == 1 ) && !defined( ipTCP_TIMER_PERIOD_MS ) )
+       #define ipTCP_TIMER_PERIOD_MS   ( 1000 )
+#endif
+
+/* The next private port number to use when binding a client socket is stored in
+the usNextPortToUse[] array - which has either 1 or two indexes depending on
+whether TCP is being supported. */
+#if( ipconfigUSE_TCP == 1 )
+       #define socketPROTOCOL_COUNT            2
+#else
+       #define socketPROTOCOL_COUNT            1
+#endif
+
+/* Indexes into the usNextPortToUse[] array for UDP and TCP sockets
+respectively. */
+#define socketNEXT_UDP_PORT_NUMBER_INDEX       0
+#define socketNEXT_TCP_PORT_NUMBER_INDEX       1
+
+/* Some helper macro's for defining the 20/80 % limits of uxLittleSpace / uxEnoughSpace. */
+#define sock20_PERCENT                                         20
+#define sock80_PERCENT                                         80
+#define sock100_PERCENT                                                100
+
+
+/*-----------------------------------------------------------*/
+
+/*
+ * Allocate the next port number from the private allocation range.
+ * TCP and UDP each have their own series of port numbers
+ * ulProtocol is either ipPROTOCOL_UDP or ipPROTOCOL_TCP
+ */
+static uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol );
+
+/*
+ * Return the list item from within pxList that has an item value of
+ * xWantedItemValue.  If there is no such list item return NULL.
+ */
+static const ListItem_t * pxListFindListItemWithValue( const List_t *pxList, TickType_t xWantedItemValue );
+
+/*
+ * Return pdTRUE only if pxSocket is valid and bound, as far as can be
+ * determined.
+ */
+static BaseType_t prvValidSocket( FreeRTOS_Socket_t *pxSocket, BaseType_t xProtocol, BaseType_t xIsBound );
+
+/*
+ * Before creating a socket, check the validity of the parameters used
+ * and find the size of the socket space, which is different for UDP and TCP
+ */
+static BaseType_t prvDetermineSocketSize( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol, size_t *pxSocketSize );
+
+#if( ipconfigUSE_TCP == 1 )
+       /*
+        * Create a txStream or a rxStream, depending on the parameter 'xIsInputStream'
+        */
+       static StreamBuffer_t *prvTCPCreateStream (FreeRTOS_Socket_t *pxSocket, BaseType_t xIsInputStream );
+#endif /* ipconfigUSE_TCP == 1 */
+
+#if( ipconfigUSE_TCP == 1 )
+       /*
+        * Called from FreeRTOS_send(): some checks which will be done before
+        * sending a TCP packed.
+        */
+       static int32_t prvTCPSendCheck( FreeRTOS_Socket_t *pxSocket, size_t xDataLength );
+#endif /* ipconfigUSE_TCP */
+
+#if( ipconfigUSE_TCP == 1 )
+       /*
+        * When a child socket gets closed, make sure to update the child-count of the parent
+        */
+       static void prvTCPSetSocketCount( FreeRTOS_Socket_t *pxSocketToDelete );
+#endif  /* ipconfigUSE_TCP == 1 */
+
+#if( ipconfigUSE_TCP == 1 )
+       /*
+        * Called from FreeRTOS_connect(): make some checks and if allowed, send a
+        * message to the IP-task to start connecting to a remote socket
+        */
+       static BaseType_t prvTCPConnectStart( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr *pxAddress );
+#endif /* ipconfigUSE_TCP */
+
+#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
+
+       /* Executed by the IP-task, it will check all sockets belonging to a set */
+       static FreeRTOS_Socket_t *prvFindSelectedSocket( SocketSelect_t *pxSocketSet );
+
+#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
+/*-----------------------------------------------------------*/
+
+/* The list that contains mappings between sockets and port numbers.  Accesses
+to this list must be protected by critical sections of one kind or another. */
+List_t xBoundUDPSocketsList;
+
+#if ipconfigUSE_TCP == 1
+       List_t xBoundTCPSocketsList;
+#endif /* ipconfigUSE_TCP == 1 */
+
+/*-----------------------------------------------------------*/
+
+static BaseType_t prvValidSocket( FreeRTOS_Socket_t *pxSocket, BaseType_t xProtocol, BaseType_t xIsBound )
+{
+BaseType_t xReturn = pdTRUE;
+
+       if( ( pxSocket == NULL ) || ( pxSocket == FREERTOS_INVALID_SOCKET ) )
+       {
+               xReturn = pdFALSE;
+       }
+       else if( ( xIsBound != pdFALSE ) && ( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE ) )
+       {
+               /* The caller expects the socket to be bound, but it isn't. */
+               xReturn = pdFALSE;
+       }
+       else if( pxSocket->ucProtocol != ( uint8_t ) xProtocol )
+       {
+               /* Socket has a wrong type (UDP != TCP). */
+               xReturn = pdFALSE;
+       }
+
+       return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t vNetworkSocketsInit( void )
+{
+       vListInitialise( &xBoundUDPSocketsList );
+
+       #if( ipconfigUSE_TCP == 1 )
+       {
+               vListInitialise( &xBoundTCPSocketsList );
+       }
+       #endif  /* ipconfigUSE_TCP == 1 */
+
+       return pdTRUE;
+}
+/*-----------------------------------------------------------*/
+
+static BaseType_t prvDetermineSocketSize( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol, size_t *pxSocketSize )
+{
+BaseType_t xReturn = pdPASS;
+FreeRTOS_Socket_t *pxSocket;
+
+       /* Asserts must not appear before it has been determined that the network
+       task is ready - otherwise the asserts will fail. */
+       if( xIPIsNetworkTaskReady() == pdFALSE )
+       {
+               xReturn = pdFAIL;
+       }
+       else
+       {
+               /* Only Ethernet is currently supported. */
+               configASSERT( xDomain == FREERTOS_AF_INET );
+
+               /* Check if the UDP socket-list has been initialised. */
+               configASSERT( listLIST_IS_INITIALISED( &xBoundUDPSocketsList ) );
+               #if( ipconfigUSE_TCP == 1 )
+               {
+                       /* Check if the TCP socket-list has been initialised. */
+                       configASSERT( listLIST_IS_INITIALISED( &xBoundTCPSocketsList ) );
+               }
+               #endif  /* ipconfigUSE_TCP == 1 */
+
+               if( xProtocol == FREERTOS_IPPROTO_UDP )
+               {
+                       if( xType != FREERTOS_SOCK_DGRAM )
+                       {
+                               xReturn = pdFAIL;
+                               configASSERT( xReturn );
+                       }
+                       /* In case a UDP socket is created, do not allocate space for TCP data. */
+                       *pxSocketSize = ( sizeof( *pxSocket ) - sizeof( pxSocket->u ) ) + sizeof( pxSocket->u.xUDP );
+               }
+#if( ipconfigUSE_TCP == 1 )
+               else if( xProtocol == FREERTOS_IPPROTO_TCP )
+               {
+                       if( xType != FREERTOS_SOCK_STREAM )
+                       {
+                               xReturn = pdFAIL;
+                               configASSERT( xReturn );
+                       }
+
+                       *pxSocketSize = ( sizeof( *pxSocket ) - sizeof( pxSocket->u ) ) + sizeof( pxSocket->u.xTCP );
+               }
+#endif  /* ipconfigUSE_TCP == 1 */
+               else
+               {
+                       xReturn = pdFAIL;
+                       configASSERT( xReturn );
+               }
+       }
+       /* In case configASSERT() is not used */
+       ( void )xDomain;
+       return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+/* FreeRTOS_socket() allocates and initiates a socket */
+Socket_t FreeRTOS_socket( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol )
+{
+FreeRTOS_Socket_t *pxSocket;
+size_t uxSocketSize;
+EventGroupHandle_t xEventGroup;
+Socket_t xReturn;
+
+       if( prvDetermineSocketSize( xDomain, xType, xProtocol, &uxSocketSize ) == pdFAIL )
+       {
+               xReturn = FREERTOS_INVALID_SOCKET;
+       }
+       else
+       {
+               /* Allocate the structure that will hold the socket information.  The
+               size depends on the type of socket: UDP sockets need less space.  A
+               define 'pvPortMallocSocket' will used to allocate the necessary space.
+               By default it points to the FreeRTOS function 'pvPortMalloc()'. */
+               pxSocket = ( FreeRTOS_Socket_t * ) pvPortMallocSocket( uxSocketSize );
+
+               if( pxSocket == NULL )
+               {
+                       pxSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
+                       iptraceFAILED_TO_CREATE_SOCKET();
+               }
+               else if( ( xEventGroup = xEventGroupCreate() ) == NULL )
+               {
+                       vPortFreeSocket( pxSocket );
+                       pxSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
+                       iptraceFAILED_TO_CREATE_EVENT_GROUP();
+               }
+               else
+               {
+                       /* Clear the entire space to avoid nulling individual entries */
+                       memset( pxSocket, '\0', uxSocketSize );
+
+                       pxSocket->xEventGroup = xEventGroup;
+
+                       /* Initialise the socket's members.  The semaphore will be created
+                       if the socket is bound to an address, for now the pointer to the
+                       semaphore is just set to NULL to show it has not been created. */
+                       if( xProtocol == FREERTOS_IPPROTO_UDP )
+                       {
+                               vListInitialise( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
+
+                               #if( ipconfigUDP_MAX_RX_PACKETS > 0 )
+                               {
+                                       pxSocket->u.xUDP.uxMaxPackets = ( UBaseType_t ) ipconfigUDP_MAX_RX_PACKETS;
+                               }
+                               #endif /* ipconfigUDP_MAX_RX_PACKETS > 0 */
+                       }
+
+                       vListInitialiseItem( &( pxSocket->xBoundSocketListItem ) );
+                       listSET_LIST_ITEM_OWNER( &( pxSocket->xBoundSocketListItem ), ( void * ) pxSocket );
+
+                       pxSocket->xReceiveBlockTime = ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME;
+                       pxSocket->xSendBlockTime        = ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME;
+                       pxSocket->ucSocketOptions   = ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT;
+                       pxSocket->ucProtocol            = ( uint8_t ) xProtocol; /* protocol: UDP or TCP */
+
+                       #if( ipconfigUSE_TCP == 1 )
+                       {
+                               if( xProtocol == FREERTOS_IPPROTO_TCP )
+                               {
+                                       /* StreamSize is expressed in number of bytes */
+                                       /* Round up buffer sizes to nearest multiple of MSS */
+                                       pxSocket->u.xTCP.usInitMSS      = pxSocket->u.xTCP.usCurMSS = ipconfigTCP_MSS;
+                                       pxSocket->u.xTCP.uxRxStreamSize = ( size_t ) ipconfigTCP_RX_BUFFER_LENGTH;
+                                       pxSocket->u.xTCP.uxTxStreamSize = ( size_t ) FreeRTOS_round_up( ipconfigTCP_TX_BUFFER_LENGTH, ipconfigTCP_MSS );
+                                       /* Use half of the buffer size of the TCP windows */
+                                       #if ( ipconfigUSE_TCP_WIN == 1 )
+                                       {
+                                               pxSocket->u.xTCP.uxRxWinSize  = FreeRTOS_max_uint32( 1UL, ( uint32_t ) ( pxSocket->u.xTCP.uxRxStreamSize / 2 ) / ipconfigTCP_MSS );
+                                               pxSocket->u.xTCP.uxTxWinSize  = FreeRTOS_max_uint32( 1UL, ( uint32_t ) ( pxSocket->u.xTCP.uxTxStreamSize / 2 ) / ipconfigTCP_MSS );
+                                       }
+                                       #else
+                                       {
+                                               pxSocket->u.xTCP.uxRxWinSize  = 1u;
+                                               pxSocket->u.xTCP.uxTxWinSize  = 1u;
+                                       }
+                                       #endif
+                                       /* The above values are just defaults, and can be overridden by
+                                       calling FreeRTOS_setsockopt().  No buffers will be allocated until a
+                                       socket is connected and data is exchanged. */
+                               }
+                       }
+                       #endif  /* ipconfigUSE_TCP == 1 */
+               }
+
+               xReturn = ( Socket_t ) pxSocket;
+       }
+
+       /* Remove compiler warnings in the case the configASSERT() is not defined. */
+       ( void ) xDomain;
+
+       return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
+
+       SocketSet_t FreeRTOS_CreateSocketSet( void )
+       {
+       SocketSelect_t *pxSocketSet;
+
+               pxSocketSet = ( SocketSelect_t * ) pvPortMalloc( sizeof( *pxSocketSet ) );
+
+               if( pxSocketSet != NULL )
+               {
+                       memset( pxSocketSet, '\0', sizeof( *pxSocketSet ) );
+                       pxSocketSet->xSelectGroup = xEventGroupCreate();
+
+                       if( pxSocketSet->xSelectGroup == NULL )
+                       {
+                               vPortFree( ( void* ) pxSocketSet );
+                               pxSocketSet = NULL;
+                       }
+               }
+
+               return ( SocketSet_t ) pxSocketSet;
+       }
+
+#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
+/*-----------------------------------------------------------*/
+
+#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
+
+       void FreeRTOS_DeleteSocketSet( SocketSet_t xSocketSet )
+       {
+               SocketSelect_t *pxSocketSet = ( SocketSelect_t*) xSocketSet;
+
+               vEventGroupDelete( pxSocketSet->xSelectGroup );
+               vPortFree( ( void* ) pxSocketSet );
+       }
+
+#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
+/*-----------------------------------------------------------*/
+
+#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
+
+       /* Add a socket to a set */
+       void FreeRTOS_FD_SET( Socket_t xSocket, SocketSet_t xSocketSet, EventBits_t xSelectBits )
+       {
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+       SocketSelect_t *pxSocketSet = ( SocketSelect_t * ) xSocketSet;
+
+               configASSERT( pxSocket != NULL );
+               configASSERT( xSocketSet != NULL );
+
+               /* Make sure we're not adding bits which are reserved for internal use,
+               such as eSELECT_CALL_IP */
+               pxSocket->xSelectBits |= ( xSelectBits & eSELECT_ALL );
+
+               if( ( pxSocket->xSelectBits & eSELECT_ALL ) != 0 )
+               {
+                       /* Adding a socket to a socket set. */
+                       pxSocket->pxSocketSet = ( SocketSelect_t * ) xSocketSet;
+
+                       /* Now have the IP-task call vSocketSelect() to see if the set contains
+                       any sockets which are 'ready' and set the proper bits.
+                       By setting 'bApiCalled = false', vSocketSelect() knows that it was
+                       not called from a user API */
+                       pxSocketSet->bApiCalled = pdFALSE;
+                       prvFindSelectedSocket( pxSocketSet );
+               }
+       }
+
+#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
+/*-----------------------------------------------------------*/
+
+#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
+       /* Clear select bits for a socket
+       If the mask becomes 0, remove the socket from the set */
+       void FreeRTOS_FD_CLR( Socket_t xSocket, SocketSet_t xSocketSet, EventBits_t xSelectBits )
+       {
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+
+               configASSERT( pxSocket != NULL );
+               configASSERT( xSocketSet != NULL );
+
+               pxSocket->xSelectBits &= ~( xSelectBits & eSELECT_ALL );
+               if( ( pxSocket->xSelectBits & eSELECT_ALL ) != 0 )
+               {
+                       pxSocket->pxSocketSet = ( SocketSelect_t *)xSocketSet;
+               }
+               else
+               {
+                       /* disconnect it from the socket set */
+                       pxSocket->pxSocketSet = ( SocketSelect_t *)NULL;
+               }
+       }
+
+#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
+/*-----------------------------------------------------------*/
+
+
+#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
+
+       /* Test if a socket belongs to a socket-set */
+       EventBits_t FreeRTOS_FD_ISSET( Socket_t xSocket, SocketSet_t xSocketSet )
+       {
+       EventBits_t xReturn;
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+
+               configASSERT( pxSocket != NULL );
+               configASSERT( xSocketSet != NULL );
+
+               if( xSocketSet == ( SocketSet_t ) pxSocket->pxSocketSet )
+               {
+                       /* Make sure we're not adding bits which are reserved for internal
+                       use. */
+                       xReturn = pxSocket->xSocketBits & eSELECT_ALL;
+               }
+               else
+               {
+                       xReturn = 0;
+               }
+
+               return xReturn;
+       }
+
+#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
+/*-----------------------------------------------------------*/
+
+#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
+
+       /* The select() statement: wait for an event to occur on any of the sockets
+       included in a socket set */
+       BaseType_t FreeRTOS_select( SocketSet_t xSocketSet, TickType_t xBlockTimeTicks )
+       {
+       TimeOut_t xTimeOut;
+       TickType_t xRemainingTime;
+       SocketSelect_t *pxSocketSet = ( SocketSelect_t*) xSocketSet;
+       BaseType_t xResult;
+
+               configASSERT( xSocketSet != NULL );
+
+               /* Only in the first round, check for non-blocking */
+               xRemainingTime = xBlockTimeTicks;
+
+               /* Fetch the current time */
+               vTaskSetTimeOutState( &xTimeOut );
+
+               for( ;; )
+               {
+                       /* Find a socket which might have triggered the bit
+                       This function might return immediately or block for a limited time */
+                       xResult = ( BaseType_t ) xEventGroupWaitBits( pxSocketSet->xSelectGroup, eSELECT_ALL, pdFALSE, pdFALSE, xRemainingTime );
+
+                       #if( ipconfigSUPPORT_SIGNALS != 0 )
+                       {
+                               if( ( xResult & eSELECT_INTR ) != 0u )
+                               {
+                                       xEventGroupClearBits( pxSocketSet->xSelectGroup, eSELECT_INTR );
+                                       FreeRTOS_debug_printf( ( "FreeRTOS_select: interrupted\n" ) );
+                                       break;
+                               }
+                       }
+                       #endif /* ipconfigSUPPORT_SIGNALS */
+
+                       /* Have the IP-task find the socket which had an event */
+                       pxSocketSet->bApiCalled = pdTRUE;
+                       prvFindSelectedSocket( pxSocketSet );
+
+                       xResult = ( BaseType_t ) xEventGroupGetBits( pxSocketSet->xSelectGroup );
+
+                       if( xResult != 0 )
+                       {
+                               break;
+                       }
+
+                       /* Has the timeout been reached? */
+                       if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
+                       {
+                               break;
+                       }
+               }
+
+               return xResult;
+       }
+
+#endif /* ipconfigSUPPORT_SELECT_FUNCTION */
+/*-----------------------------------------------------------*/
+
+#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
+
+       /* Send a message to the IP-task to have it check all sockets belonging to
+       'pxSocketSet' */
+       static FreeRTOS_Socket_t *prvFindSelectedSocket( SocketSelect_t *pxSocketSet )
+       {
+       IPStackEvent_t xSelectEvent;
+       FreeRTOS_Socket_t *xReturn;
+
+               xSelectEvent.eEventType = eSocketSelectEvent;
+               xSelectEvent.pvData = ( void * ) pxSocketSet;
+
+               /* while the IP-task works on the request, the API will block on
+               'eSELECT_CALL_IP'.  So clear it first. */
+               xEventGroupClearBits( pxSocketSet->xSelectGroup, eSELECT_CALL_IP );
+
+               /* Now send the socket select event */
+               if( xSendEventStructToIPTask( &xSelectEvent, ( TickType_t ) portMAX_DELAY ) == pdFAIL )
+               {
+                       /* Oops, we failed to wake-up the IP task. No use to wait for it. */
+                       FreeRTOS_debug_printf( ( "prvFindSelectedSocket: failed\n" ) );
+                       xReturn = NULL;
+               }
+               else
+               {
+                       /* As soon as the IP-task is ready, it will set 'eSELECT_CALL_IP' to
+                       wakeup the calling API */
+                       xEventGroupWaitBits( pxSocketSet->xSelectGroup, eSELECT_CALL_IP, pdTRUE, pdFALSE, portMAX_DELAY );
+
+                       /* Return 'pxSocket' which is set by the IP-task */
+                       xReturn = pxSocketSet->pxSocket;
+               }
+
+               return xReturn;
+       }
+
+#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
+/*-----------------------------------------------------------*/
+
+/*
+ * FreeRTOS_recvfrom: receive data from a bound socket
+ * In this library, the function can only be used with connectionsless sockets
+ * (UDP)
+ */
+int32_t FreeRTOS_recvfrom( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags, struct freertos_sockaddr *pxSourceAddress, socklen_t *pxSourceAddressLength )
+{
+BaseType_t lPacketCount = 0;
+NetworkBufferDescriptor_t *pxNetworkBuffer;
+FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+TickType_t xRemainingTime = ( TickType_t ) 0; /* Obsolete assignment, but some compilers output a warning if its not done. */
+BaseType_t xTimed = pdFALSE;
+TimeOut_t xTimeOut;
+int32_t lReturn;
+EventBits_t xEventBits = ( EventBits_t ) 0;
+
+       if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_UDP, pdTRUE ) == pdFALSE )
+       {
+               return -pdFREERTOS_ERRNO_EINVAL;
+       }
+
+       lPacketCount = ( BaseType_t ) listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
+
+       /* The function prototype is designed to maintain the expected Berkeley
+       sockets standard, but this implementation does not use all the parameters. */
+       ( void ) pxSourceAddressLength;
+
+       while( lPacketCount == 0 )
+       {
+               if( xTimed == pdFALSE )
+               {
+                       /* Check to see if the socket is non blocking on the first
+                       iteration.  */
+                       xRemainingTime = pxSocket->xReceiveBlockTime;
+
+                       if( xRemainingTime == ( TickType_t ) 0 )
+                       {
+                               #if( ipconfigSUPPORT_SIGNALS != 0 )
+                               {
+                                       /* Just check for the interrupt flag. */
+                                       xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_INTR,
+                                               pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, socketDONT_BLOCK );
+                               }
+                               #endif /* ipconfigSUPPORT_SIGNALS */
+                               break;
+                       }
+
+                       if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
+                       {
+                               break;
+                       }
+
+                       /* To ensure this part only executes once. */
+                       xTimed = pdTRUE;
+
+                       /* Fetch the current time. */
+                       vTaskSetTimeOutState( &xTimeOut );
+               }
+
+               /* Wait for arrival of data.  While waiting, the IP-task may set the
+               'eSOCKET_RECEIVE' bit in 'xEventGroup', if it receives data for this
+               socket, thus unblocking this API call. */
+               xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_RECEIVE | eSOCKET_INTR,
+                       pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
+
+               #if( ipconfigSUPPORT_SIGNALS != 0 )
+               {
+                       if( ( xEventBits & eSOCKET_INTR ) != 0 )
+                       {
+                               if( ( xEventBits & eSOCKET_RECEIVE ) != 0 )
+                               {
+                                       /* Shouldn't have cleared the eSOCKET_RECEIVE flag. */
+                                       xEventGroupSetBits( pxSocket->xEventGroup, eSOCKET_RECEIVE );
+                               }
+                               break;
+                       }
+               }
+               #else
+               {
+                       ( void ) xEventBits;
+               }
+               #endif /* ipconfigSUPPORT_SIGNALS */
+
+               lPacketCount = ( BaseType_t ) listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
+
+               if( lPacketCount != 0 )
+               {
+                       break;
+               }
+
+               /* Has the timeout been reached ? */
+               if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) )
+               {
+                       break;
+               }
+       } /* while( lPacketCount == 0 ) */
+
+       if( lPacketCount != 0 )
+       {
+               taskENTER_CRITICAL();
+               {
+                       /* The owner of the list item is the network buffer. */
+                       pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
+
+                       if( ( xFlags & FREERTOS_MSG_PEEK ) == 0 )
+                       {
+                               /* Remove the network buffer from the list of buffers waiting to
+                               be processed by the socket. */
+                               uxListRemove( &( pxNetworkBuffer->xBufferListItem ) );
+                       }
+               }
+               taskEXIT_CRITICAL();
+
+               /* The returned value is the length of the payload data, which is
+               calculated at the total packet size minus the headers.
+               The validity of `xDataLength` prvProcessIPPacket has been confirmed
+               in 'prvProcessIPPacket()'. */
+               lReturn = ( int32_t ) ( pxNetworkBuffer->xDataLength - sizeof( UDPPacket_t ) );
+
+               if( pxSourceAddress != NULL )
+               {
+                       pxSourceAddress->sin_port = pxNetworkBuffer->usPort;
+                       pxSourceAddress->sin_addr = pxNetworkBuffer->ulIPAddress;
+               }
+
+               if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
+               {
+                       /* The zero copy flag is not set.  Truncate the length if it won't
+                       fit in the provided buffer. */
+                       if( lReturn > ( int32_t ) xBufferLength )
+                       {
+                               iptraceRECVFROM_DISCARDING_BYTES( ( xBufferLength - lReturn ) );
+                               lReturn = ( int32_t )xBufferLength;
+                       }
+
+                       /* Copy the received data into the provided buffer, then release the
+                       network buffer. */
+                       memcpy( pvBuffer, ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ), ( size_t )lReturn );
+
+                       if( ( xFlags & FREERTOS_MSG_PEEK ) == 0 )
+                       {
+                               vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
+                       }
+               }
+               else
+               {
+                       /* The zero copy flag was set.  pvBuffer is not a buffer into which
+                       the received data can be copied, but a pointer that must be set to
+                       point to the buffer in which the received data has already been
+                       placed. */
+                       *( ( void** ) pvBuffer ) = ( void * ) ( &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ) );
+               }
+
+       }
+#if( ipconfigSUPPORT_SIGNALS != 0 )
+       else if( ( xEventBits & eSOCKET_INTR ) != 0 )
+       {
+               lReturn = -pdFREERTOS_ERRNO_EINTR;
+               iptraceRECVFROM_INTERRUPTED();
+       }
+#endif /* ipconfigSUPPORT_SIGNALS */
+       else
+       {
+               lReturn = -pdFREERTOS_ERRNO_EWOULDBLOCK;
+               iptraceRECVFROM_TIMEOUT();
+       }
+
+       return lReturn;
+}
+/*-----------------------------------------------------------*/
+
+int32_t FreeRTOS_sendto( Socket_t xSocket, const void *pvBuffer, size_t xTotalDataLength, BaseType_t xFlags, const struct freertos_sockaddr *pxDestinationAddress, socklen_t xDestinationAddressLength )
+{
+NetworkBufferDescriptor_t *pxNetworkBuffer;
+IPStackEvent_t xStackTxEvent = { eStackTxEvent, NULL };
+TimeOut_t xTimeOut;
+TickType_t xTicksToWait;
+int32_t lReturn = 0;
+FreeRTOS_Socket_t *pxSocket;
+
+       pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+
+       /* The function prototype is designed to maintain the expected Berkeley
+       sockets standard, but this implementation does not use all the
+       parameters. */
+       ( void ) xDestinationAddressLength;
+       configASSERT( pvBuffer );
+
+       if( xTotalDataLength <= ( size_t ) ipMAX_UDP_PAYLOAD_LENGTH )
+       {
+               /* If the socket is not already bound to an address, bind it now.
+               Passing NULL as the address parameter tells FreeRTOS_bind() to select
+               the address to bind to. */
+               if( ( socketSOCKET_IS_BOUND( pxSocket ) != pdFALSE ) ||
+                       ( FreeRTOS_bind( xSocket, NULL, 0u ) == 0 ) )
+               {
+                       xTicksToWait = pxSocket->xSendBlockTime;
+
+                       #if( ipconfigUSE_CALLBACKS != 0 )
+                       {
+                               if( xIsCallingFromIPTask() != pdFALSE )
+                               {
+                                       /* If this send function is called from within a call-back
+                                       handler it may not block, otherwise chances would be big to
+                                       get a deadlock: the IP-task waiting for itself. */
+                                       xTicksToWait = ( TickType_t )0;
+                               }
+                       }
+                       #endif /* ipconfigUSE_CALLBACKS */
+
+                       if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
+                       {
+                               xTicksToWait = ( TickType_t ) 0;
+                       }
+
+                       if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
+                       {
+                               /* Zero copy is not set, so obtain a network buffer into
+                               which the payload will be copied. */
+                               vTaskSetTimeOutState( &xTimeOut );
+
+                               /* Block until a buffer becomes available, or until a
+                               timeout has been reached */
+                               pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( xTotalDataLength + sizeof( UDPPacket_t ), xTicksToWait );
+
+                               if( pxNetworkBuffer != NULL )
+                               {
+                                       memcpy( ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ), ( void * ) pvBuffer, xTotalDataLength );
+
+                                       if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdTRUE )
+                                       {
+                                               /* The entire block time has been used up. */
+                                               xTicksToWait = ( TickType_t ) 0;
+                                       }
+                               }
+                       }
+                       else
+                       {
+                               /* When zero copy is used, pvBuffer is a pointer to the
+                               payload of a buffer that has already been obtained from the
+                               stack.  Obtain the network buffer pointer from the buffer. */
+                               pxNetworkBuffer = pxUDPPayloadBuffer_to_NetworkBuffer( (void*)pvBuffer );
+                       }
+
+                       if( pxNetworkBuffer != NULL )
+                       {
+                               /* xDataLength is the size of the total packet, including the Ethernet header. */
+                               pxNetworkBuffer->xDataLength = xTotalDataLength + sizeof( UDPPacket_t );
+                               pxNetworkBuffer->usPort = pxDestinationAddress->sin_port;
+                               pxNetworkBuffer->usBoundPort = ( uint16_t ) socketGET_SOCKET_PORT( pxSocket );
+                               pxNetworkBuffer->ulIPAddress = pxDestinationAddress->sin_addr;
+
+                               /* The socket options are passed to the IP layer in the
+                               space that will eventually get used by the Ethernet header. */
+                               pxNetworkBuffer->pucEthernetBuffer[ ipSOCKET_OPTIONS_OFFSET ] = pxSocket->ucSocketOptions;
+
+                               /* Tell the networking task that the packet needs sending. */
+                               xStackTxEvent.pvData = pxNetworkBuffer;
+
+                               /* Ask the IP-task to send this packet */
+                               if( xSendEventStructToIPTask( &xStackTxEvent, xTicksToWait ) == pdPASS )
+                               {
+                                       /* The packet was successfully sent to the IP task. */
+                                       lReturn = ( int32_t ) xTotalDataLength;
+                                       #if( ipconfigUSE_CALLBACKS == 1 )
+                                       {
+                                               if( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xUDP.pxHandleSent ) )
+                                               {
+                                                       pxSocket->u.xUDP.pxHandleSent( ( Socket_t )pxSocket, xTotalDataLength );
+                                               }
+                                       }
+                                       #endif /* ipconfigUSE_CALLBACKS */
+                               }
+                               else
+                               {
+                                       /* If the buffer was allocated in this function, release
+                                       it. */
+                                       if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
+                                       {
+                                               vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
+                                       }
+                                       iptraceSTACK_TX_EVENT_LOST( ipSTACK_TX_EVENT );
+                               }
+                       }
+                       else
+                       {
+                               /* If errno was available, errno would be set to
+                               FREERTOS_ENOPKTS.  As it is, the function must return the
+                               number of transmitted bytes, so the calling function knows
+                               how     much data was actually sent. */
+                               iptraceNO_BUFFER_FOR_SENDTO();
+                       }
+               }
+               else
+               {
+                       iptraceSENDTO_SOCKET_NOT_BOUND();
+               }
+       }
+       else
+       {
+               /* The data is longer than the available buffer space. */
+               iptraceSENDTO_DATA_TOO_LONG();
+       }
+
+       return lReturn;
+} /* Tested */
+/*-----------------------------------------------------------*/
+
+/*
+ * FreeRTOS_bind() : binds a sockt to a local port number.  If port 0 is
+ * provided, a system provided port number will be assigned.  This function can
+ * be used for both UDP and TCP sockets.  The actual binding will be performed
+ * by the IP-task to avoid mutual access to the bound-socket-lists
+ * (xBoundUDPSocketsList or xBoundTCPSocketsList).
+ */
+BaseType_t FreeRTOS_bind( Socket_t xSocket, struct freertos_sockaddr * pxAddress, socklen_t xAddressLength )
+{
+IPStackEvent_t xBindEvent;
+FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+BaseType_t xReturn = 0;
+
+       ( void ) xAddressLength;
+
+       if( ( pxSocket == NULL ) || ( pxSocket == FREERTOS_INVALID_SOCKET ) )
+       {
+               xReturn = -pdFREERTOS_ERRNO_EINVAL;
+       }
+       /* Once a socket is bound to a port, it can not be bound to a different
+       port number */
+       else if( socketSOCKET_IS_BOUND( pxSocket) != pdFALSE )
+       {
+               /* The socket is already bound. */
+               FreeRTOS_debug_printf( ( "vSocketBind: Socket already bound to %d\n", pxSocket->usLocalPort ) );
+               xReturn = -pdFREERTOS_ERRNO_EINVAL;
+       }
+       else
+       {
+               /* Prepare a messages to the IP-task in order to perform the binding.
+               The desired port number will be passed in usLocalPort. */
+               xBindEvent.eEventType = eSocketBindEvent;
+               xBindEvent.pvData = ( void * ) xSocket;
+               if( pxAddress != NULL )
+               {
+                       pxSocket->usLocalPort = FreeRTOS_ntohs( pxAddress->sin_port );
+               }
+               else
+               {
+                       /* Caller wants to bind to a random port number. */
+                       pxSocket->usLocalPort = 0u;
+               }
+
+               /* portMAX_DELAY is used as a the time-out parameter, as binding *must*
+               succeed before the socket can be used.  _RB_ The use of an infinite
+               block time needs be changed as it could result in the task hanging. */
+               if( xSendEventStructToIPTask( &xBindEvent, ( TickType_t ) portMAX_DELAY ) == pdFAIL )
+               {
+                       /* Failed to wake-up the IP-task, no use to wait for it */
+                       FreeRTOS_debug_printf( ( "FreeRTOS_bind: send event failed\n" ) );
+                       xReturn = -pdFREERTOS_ERRNO_ECANCELED;
+               }
+               else
+               {
+                       /* The IP-task will set the 'eSOCKET_BOUND' bit when it has done its
+                       job. */
+                       xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_BOUND, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, portMAX_DELAY );
+                       if( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE )
+                       {
+                               xReturn = -pdFREERTOS_ERRNO_EINVAL;
+                       }
+               }
+       }
+
+       return xReturn;
+}
+
+/*
+ * vSocketBind(): internal version of bind() that should not be called directly.
+ * 'xInternal' is used for TCP sockets only: it allows to have several
+ * (connected) child sockets bound to the same server port.
+ */
+BaseType_t vSocketBind( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr * pxAddress, size_t uxAddressLength, BaseType_t xInternal )
+{
+BaseType_t xReturn = 0; /* In Berkeley sockets, 0 means pass for bind(). */
+List_t *pxSocketList;
+#if( ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 )
+       struct freertos_sockaddr xAddress;
+#endif /* ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND */
+
+#if( ipconfigUSE_TCP == 1 )
+       if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
+       {
+               pxSocketList = &xBoundTCPSocketsList;
+       }
+       else
+#endif  /* ipconfigUSE_TCP == 1 */
+       {
+               pxSocketList = &xBoundUDPSocketsList;
+       }
+
+       /* The function prototype is designed to maintain the expected Berkeley
+       sockets standard, but this implementation does not use all the parameters. */
+       ( void ) uxAddressLength;
+
+       configASSERT( pxSocket );
+       configASSERT( pxSocket != FREERTOS_INVALID_SOCKET );
+
+       #if( ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 )
+       {
+               /* pxAddress will be NULL if sendto() was called on a socket without the
+               socket being bound to an address. In this case, automatically allocate
+               an address and port to the socket. */
+               if( pxAddress == NULL )
+               {
+                       pxAddress = &xAddress;
+                       /* Put the port to zero to be assigned later. */
+                       pxAddress->sin_port = 0u;
+               }
+       }
+       #endif /* ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 */
+
+       /* Sockets must be bound before calling FreeRTOS_sendto() if
+       ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is not set to 1. */
+       configASSERT( pxAddress );
+
+       if( pxAddress != NULL )
+       {
+               if( pxAddress->sin_port == 0u )
+               {
+                       pxAddress->sin_port = prvGetPrivatePortNumber( ( BaseType_t )pxSocket->ucProtocol );
+                       if( 0 == pxAddress->sin_port )
+                       {
+                               return -pdFREERTOS_ERRNO_EADDRNOTAVAIL;
+                       }
+               }
+
+               /* If vSocketBind() is called from the API FreeRTOS_bind() it has been
+               confirmed that the socket was not yet bound to a port.  If it is called
+               from the IP-task, no such check is necessary. */
+
+               /* Check to ensure the port is not already in use.  If the bind is
+               called internally, a port MAY be used by more than one socket. */
+               if( ( ( xInternal == pdFALSE ) || ( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP ) ) &&
+                       ( pxListFindListItemWithValue( pxSocketList, ( TickType_t ) pxAddress->sin_port ) != NULL ) )
+               {
+                       FreeRTOS_debug_printf( ( "vSocketBind: %sP port %d in use\n",
+                               pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP ? "TC" : "UD",
+                               FreeRTOS_ntohs( pxAddress->sin_port ) ) );
+                       xReturn = -pdFREERTOS_ERRNO_EADDRINUSE;
+               }
+               else
+               {
+                       /* Allocate the port number to the socket.
+                       This macro will set 'xBoundSocketListItem->xItemValue' */
+                       socketSET_SOCKET_PORT( pxSocket, pxAddress->sin_port );
+
+                       /* And also store it in a socket field 'usLocalPort' in host-byte-order,
+                       mostly used for logging and debugging purposes */
+                       pxSocket->usLocalPort = FreeRTOS_ntohs( pxAddress->sin_port );
+
+                       /* Add the socket to the list of bound ports. */
+                       {
+                               /* If the network driver can iterate through 'xBoundUDPSocketsList',
+                               by calling xPortHasUDPSocket() then the IP-task must temporarily
+                               suspend the scheduler to keep the list in a consistent state. */
+                               #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
+                               {
+                                       vTaskSuspendAll();
+                               }
+                               #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
+
+                               /* Add the socket to 'xBoundUDPSocketsList' or 'xBoundTCPSocketsList' */
+                               vListInsertEnd( pxSocketList, &( pxSocket->xBoundSocketListItem ) );
+
+                               #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
+                               {
+                                       xTaskResumeAll();
+                               }
+                               #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
+                       }
+               }
+       }
+       else
+       {
+               xReturn = -pdFREERTOS_ERRNO_EADDRNOTAVAIL;
+               FreeRTOS_debug_printf( ( "vSocketBind: Socket no addr\n" ) );
+       }
+
+       if( xReturn != 0 )
+       {
+               iptraceBIND_FAILED( xSocket, ( FreeRTOS_ntohs( pxAddress->sin_port ) ) );
+       }
+
+       return xReturn;
+} /* Tested */
+/*-----------------------------------------------------------*/
+
+/*
+ * Close a socket and free the allocated space
+ * In case of a TCP socket: the connection will not be closed automatically
+ * Subsequent messages for the closed socket will be responded to with a RST
+ * The IP-task will actually close the socket, after receiving a 'eSocketCloseEvent' message
+ */
+BaseType_t FreeRTOS_closesocket( Socket_t xSocket )
+{
+BaseType_t xResult;
+#if( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 )
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * )xSocket;
+#endif
+IPStackEvent_t xCloseEvent;
+xCloseEvent.eEventType = eSocketCloseEvent;
+xCloseEvent.pvData = ( void * ) xSocket;
+
+       if( ( xSocket == NULL ) || ( xSocket == FREERTOS_INVALID_SOCKET ) )
+       {
+               xResult = 0;
+       }
+       else
+       {
+               #if( ( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 ) )
+               {
+                       if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
+                       {
+                               /* Make sure that IP-task won't call the user callback's anymore */
+                               pxSocket->u.xTCP.pxHandleConnected = NULL;
+                               pxSocket->u.xTCP.pxHandleReceive = NULL;
+                               pxSocket->u.xTCP.pxHandleSent = NULL;
+                       }
+               }
+               #endif  /* ( ( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 ) ) */
+
+               /* Let the IP task close the socket to keep it synchronised     with the
+               packet handling. */
+
+               /* Note when changing the time-out value below, it must be checked who is calling
+               this function. If it is called by the IP-task, a deadlock could occur.
+               The IP-task would only call it in case of a user call-back */
+               if( xSendEventStructToIPTask( &xCloseEvent, ( TickType_t ) 0 ) == pdFAIL )
+               {
+                       FreeRTOS_debug_printf( ( "FreeRTOS_closesocket: failed\n" ) );
+                       xResult = -1;
+               }
+               else
+               {
+                       xResult = 1;
+               }
+       }
+
+       return xResult;
+}
+
+/* This is the internal version of FreeRTOS_closesocket()
+ * It will be called by the IPtask only to avoid problems with synchronicity
+ */
+void *vSocketClose( FreeRTOS_Socket_t *pxSocket )
+{
+NetworkBufferDescriptor_t *pxNetworkBuffer;
+
+       #if( ipconfigUSE_TCP == 1 )
+       {
+               /* For TCP: clean up a little more. */
+               if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
+               {
+                       #if( ipconfigUSE_TCP_WIN == 1 )
+                       {
+                               if( pxSocket->u.xTCP.pxAckMessage != NULL )
+                               {
+                                       vReleaseNetworkBufferAndDescriptor( pxSocket->u.xTCP.pxAckMessage );
+                               }
+                               /* Free the resources which were claimed by the tcpWin member */
+                               vTCPWindowDestroy( &pxSocket->u.xTCP.xTCPWindow );
+                       }
+                       #endif /* ipconfigUSE_TCP_WIN */
+
+                       /* Free the input and output streams */
+                       if( pxSocket->u.xTCP.rxStream != NULL )
+                       {
+                               vPortFreeLarge( pxSocket->u.xTCP.rxStream );
+                       }
+
+                       if( pxSocket->u.xTCP.txStream != NULL )
+                       {
+                               vPortFreeLarge( pxSocket->u.xTCP.txStream );
+                       }
+
+                       /* In case this is a child socket, make sure the child-count of the
+                       parent socket is decreased. */
+                       prvTCPSetSocketCount( pxSocket );
+               }
+       }
+       #endif  /* ipconfigUSE_TCP == 1 */
+
+       /* Socket must be unbound first, to ensure no more packets are queued on
+       it. */
+       if( socketSOCKET_IS_BOUND( pxSocket ) != pdFALSE )
+       {
+               /* If the network driver can iterate through 'xBoundUDPSocketsList',
+               by calling xPortHasUDPSocket(), then the IP-task must temporarily
+               suspend the scheduler to keep the list in a consistent state. */
+               #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
+               {
+                       vTaskSuspendAll();
+               }
+               #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
+
+               uxListRemove( &( pxSocket->xBoundSocketListItem ) );
+
+               #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
+               {
+                       xTaskResumeAll();
+               }
+               #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
+       }
+
+       /* Now the socket is not bound the list of waiting packets can be
+       drained. */
+       if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_UDP )
+       {
+               while( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) > 0U )
+               {
+                       pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
+                       uxListRemove( &( pxNetworkBuffer->xBufferListItem ) );
+                       vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
+               }
+       }
+
+       if( pxSocket->xEventGroup )
+       {
+               vEventGroupDelete( pxSocket->xEventGroup );
+       }
+
+       #if( ipconfigUSE_TCP == 1 ) && ( ipconfigHAS_DEBUG_PRINTF != 0 )
+       {
+               if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
+               {
+                       FreeRTOS_debug_printf( ( "FreeRTOS_closesocket[%u to %lxip:%u]: buffers %lu socks %lu\n",
+                               pxSocket->usLocalPort,
+                               pxSocket->u.xTCP.ulRemoteIP,
+                               pxSocket->u.xTCP.usRemotePort,
+                               uxGetNumberOfFreeNetworkBuffers(),
+                               listCURRENT_LIST_LENGTH( &xBoundTCPSocketsList ) ) );
+               }
+       }
+       #endif /* ( ipconfigUSE_TCP == 1 ) && ( ipconfigHAS_DEBUG_PRINTF != 0 ) */
+
+       /* Anf finally, after all resources have been freed, free the socket space */
+       vPortFreeSocket( pxSocket );
+
+       return 0;
+} /* Tested */
+
+/*-----------------------------------------------------------*/
+
+#if ipconfigUSE_TCP == 1
+
+       /*
+        * When a child socket gets closed, make sure to update the child-count of the
+        * parent.  When a listening parent socket is closed, make sure no child-sockets
+        * keep a pointer to it.
+        */
+       static void prvTCPSetSocketCount( FreeRTOS_Socket_t *pxSocketToDelete )
+       {
+       const ListItem_t *pxIterator;
+       const MiniListItem_t *pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );
+       FreeRTOS_Socket_t *pxOtherSocket;
+       uint16_t usLocalPort = pxSocketToDelete->usLocalPort;
+
+               for( pxIterator  = ( const ListItem_t * ) listGET_NEXT( pxEnd );
+                        pxIterator != ( const ListItem_t * ) pxEnd;
+                        pxIterator  = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
+               {
+                       pxOtherSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
+                       if( ( pxOtherSocket->u.xTCP.ucTCPState == eTCP_LISTEN ) &&
+                               ( pxOtherSocket->usLocalPort == usLocalPort ) &&
+                               ( pxOtherSocket->u.xTCP.usChildCount ) )
+                       {
+                               pxOtherSocket->u.xTCP.usChildCount--;
+                               FreeRTOS_debug_printf( ( "Lost: Socket %u now has %u / %u child%s\n",
+                                       pxOtherSocket->usLocalPort,
+                                       pxOtherSocket->u.xTCP.usChildCount,
+                                       pxOtherSocket->u.xTCP.usBacklog,
+                                       pxOtherSocket->u.xTCP.usChildCount == 1u ? "" : "ren" ) );
+                               break;
+                       }
+               }
+       }
+
+#endif /* ipconfigUSE_TCP == 1 */
+
+/*-----------------------------------------------------------*/
+
+BaseType_t FreeRTOS_setsockopt( Socket_t xSocket, int32_t lLevel, int32_t lOptionName, const void *pvOptionValue, size_t xOptionLength )
+{
+/* The standard Berkeley function returns 0 for success. */
+BaseType_t xReturn = -pdFREERTOS_ERRNO_EINVAL;
+BaseType_t lOptionValue;
+FreeRTOS_Socket_t *pxSocket;
+
+       pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+
+       /* The function prototype is designed to maintain the expected Berkeley
+       sockets standard, but this implementation does not use all the parameters. */
+       ( void ) lLevel;
+       ( void ) xOptionLength;
+
+       configASSERT( xSocket );
+
+       switch( lOptionName )
+       {
+               case FREERTOS_SO_RCVTIMEO       :
+                       /* Receive time out. */
+                       pxSocket->xReceiveBlockTime = *( ( TickType_t * ) pvOptionValue );
+                       xReturn = 0;
+                       break;
+
+               case FREERTOS_SO_SNDTIMEO       :
+                       pxSocket->xSendBlockTime = *( ( TickType_t * ) pvOptionValue );
+                       if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_UDP )
+                       {
+                               /* The send time out is capped for the reason stated in the
+                               comments where ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS is defined
+                               in FreeRTOSIPConfig.h (assuming an official configuration file
+                               is being used. */
+                               if( pxSocket->xSendBlockTime > ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS )
+                               {
+                                       pxSocket->xSendBlockTime = ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS;
+                               }
+                       }
+                       else
+                       {
+                               /* For TCP socket, it isn't necessary to limit the blocking time
+                               because the FreeRTOS_send() function does not wait for a network
+                               buffer to become available. */
+                       }
+                       xReturn = 0;
+                       break;
+               #if( ipconfigUDP_MAX_RX_PACKETS > 0 )
+                       case FREERTOS_SO_UDP_MAX_RX_PACKETS:
+                               if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_UDP )
+                               {
+                                       break;  /* will return -pdFREERTOS_ERRNO_EINVAL */
+                               }
+                               pxSocket->u.xUDP.uxMaxPackets = *( ( UBaseType_t * ) pvOptionValue );
+                               xReturn = 0;
+                               break;
+               #endif /* ipconfigUDP_MAX_RX_PACKETS */
+
+               case FREERTOS_SO_UDPCKSUM_OUT :
+                       /* Turn calculating of the UDP checksum on/off for this socket. */
+                       lOptionValue = ( BaseType_t ) pvOptionValue;
+
+                       if( lOptionValue == 0 )
+                       {
+                               pxSocket->ucSocketOptions &= ( uint8_t ) ~FREERTOS_SO_UDPCKSUM_OUT;
+                       }
+                       else
+                       {
+                               pxSocket->ucSocketOptions |= ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT;
+                       }
+                       xReturn = 0;
+                       break;
+
+               #if( ipconfigUSE_CALLBACKS == 1 )
+                       #if( ipconfigUSE_TCP == 1 )
+                               case FREERTOS_SO_TCP_CONN_HANDLER:      /* Set a callback for (dis)connection events */
+                               case FREERTOS_SO_TCP_RECV_HANDLER:      /* Install a callback for receiving TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
+                               case FREERTOS_SO_TCP_SENT_HANDLER:      /* Install a callback for sending TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
+                       #endif /* ipconfigUSE_TCP */
+                               case FREERTOS_SO_UDP_RECV_HANDLER:      /* Install a callback for receiving UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
+                               case FREERTOS_SO_UDP_SENT_HANDLER:      /* Install a callback for sending UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
+                                       {
+                                               #if( ipconfigUSE_TCP == 1 )
+                                               {
+                                                       UBaseType_t uxProtocol;
+                                                       if( ( lOptionName == FREERTOS_SO_UDP_RECV_HANDLER ) ||
+                                                               ( lOptionName == FREERTOS_SO_UDP_SENT_HANDLER ) )
+                                                       {
+                                                               uxProtocol = ( UBaseType_t ) FREERTOS_IPPROTO_UDP;
+                                                       }
+                                                       else
+                                                       {
+                                                               uxProtocol = ( UBaseType_t ) FREERTOS_IPPROTO_TCP;
+                                                       }
+
+                                                       if( pxSocket->ucProtocol != ( uint8_t ) uxProtocol )
+                                                       {
+                                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */
+                                                       }
+                                               }
+                                               #else
+                                               {
+                                                       /* No need to check if the socket has the right
+                                                       protocol, because only UDP socket can be created. */
+                                               }
+                                               #endif /* ipconfigUSE_TCP */
+
+                                               switch( lOptionName )
+                                               {
+                                               #if ipconfigUSE_TCP == 1
+                                                       case FREERTOS_SO_TCP_CONN_HANDLER:
+                                                               pxSocket->u.xTCP.pxHandleConnected = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPConnected;
+                                                               break;
+                                                       case FREERTOS_SO_TCP_RECV_HANDLER:
+                                                               pxSocket->u.xTCP.pxHandleReceive = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPReceive;
+                                                               break;
+                                                       case FREERTOS_SO_TCP_SENT_HANDLER:
+                                                               pxSocket->u.xTCP.pxHandleSent = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPSent;
+                                                               break;
+                                               #endif /* ipconfigUSE_TCP */
+                                               case FREERTOS_SO_UDP_RECV_HANDLER:
+                                                       pxSocket->u.xUDP.pxHandleReceive = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnUDPReceive;
+                                                       break;
+                                               case FREERTOS_SO_UDP_SENT_HANDLER:
+                                                       pxSocket->u.xUDP.pxHandleSent = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnUDPSent;
+                                                       break;
+                                               default:
+                                                       break;
+                                               }
+                                       }
+
+                                       xReturn = 0;
+                                       break;
+               #endif /* ipconfigUSE_CALLBACKS */
+
+               #if( ipconfigUSE_TCP != 0 )
+                       #if( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 )
+                               /* Each socket has a semaphore on which the using task normally
+                               sleeps. */
+                               case FREERTOS_SO_SET_SEMAPHORE:
+                                       {
+                                               pxSocket->pxUserSemaphore = *( ( SemaphoreHandle_t * ) pvOptionValue );
+                                               xReturn = 0;
+                                       }
+                                       break;
+                       #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
+
+                       #if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK != 0 )
+                               case FREERTOS_SO_WAKEUP_CALLBACK:
+                               {
+                                       /* Each socket can have a callback function that is executed
+                                       when there is an event the socket's owner might want to
+                                       process. */
+                                       pxSocket->pxUserWakeCallback = ( SocketWakeupCallback_t ) pvOptionValue;
+                                       xReturn = 0;
+                               }
+                               break;
+                       #endif /* ipconfigSOCKET_HAS_USER_WAKE_CALLBACK */
+
+                       case FREERTOS_SO_SET_LOW_HIGH_WATER:
+                               {
+                               LowHighWater_t *pxLowHighWater = ( LowHighWater_t * ) pvOptionValue;
+
+                                       if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
+                                       {
+                                               /* It is not allowed to access 'pxSocket->u.xTCP'. */
+                                               FreeRTOS_debug_printf( ( "FREERTOS_SO_SET_LOW_HIGH_WATER: wrong socket type\n" ) );
+                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */
+                                       }
+                                       if( ( pxLowHighWater->uxLittleSpace >= pxLowHighWater->uxEnoughSpace ) ||
+                                               ( pxLowHighWater->uxEnoughSpace > pxSocket->u.xTCP.uxRxStreamSize ) )
+                                       {
+                                               /* Impossible values. */
+                                               FreeRTOS_debug_printf( ( "FREERTOS_SO_SET_LOW_HIGH_WATER: bad values\n" ) );
+                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */
+                                       }
+                                       /* Send a STOP when buffer space drops below 'uxLittleSpace' bytes. */
+                                       pxSocket->u.xTCP.uxLittleSpace = pxLowHighWater->uxLittleSpace;
+                                       /* Send a GO when buffer space grows above 'uxEnoughSpace' bytes. */
+                                       pxSocket->u.xTCP.uxEnoughSpace = pxLowHighWater->uxEnoughSpace;
+                                       xReturn = 0;
+                               }
+                               break;
+
+                       case FREERTOS_SO_SNDBUF:        /* Set the size of the send buffer, in units of MSS (TCP only) */
+                       case FREERTOS_SO_RCVBUF:        /* Set the size of the receive buffer, in units of MSS (TCP only) */
+                               {
+                                       uint32_t ulNewValue;
+
+                                       if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
+                                       {
+                                               FreeRTOS_debug_printf( ( "Set SO_%sBUF: wrong socket type\n",
+                                                       ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );
+                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */
+                                       }
+
+                                       if( ( ( lOptionName == FREERTOS_SO_SNDBUF ) && ( pxSocket->u.xTCP.txStream != NULL ) ) ||
+                                               ( ( lOptionName == FREERTOS_SO_RCVBUF ) && ( pxSocket->u.xTCP.rxStream != NULL ) ) )
+                                       {
+                                               FreeRTOS_debug_printf( ( "Set SO_%sBUF: buffer already created\n",
+                                                       ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );
+                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */
+                                       }
+
+                                       ulNewValue = *( ( uint32_t * ) pvOptionValue );
+
+                                       if( lOptionName == FREERTOS_SO_SNDBUF )
+                                       {
+                                               /* Round up to nearest MSS size */
+                                               ulNewValue = FreeRTOS_round_up( ulNewValue, ( uint32_t ) pxSocket->u.xTCP.usInitMSS );
+                                               pxSocket->u.xTCP.uxTxStreamSize = ulNewValue;
+                                       }
+                                       else
+                                       {
+                                               pxSocket->u.xTCP.uxRxStreamSize = ulNewValue;
+                                       }
+                               }
+                               xReturn = 0;
+                               break;
+
+                       case FREERTOS_SO_WIN_PROPERTIES:        /* Set all buffer and window properties in one call, parameter is pointer to WinProperties_t */
+                               {
+                                       WinProperties_t* pxProps;
+
+                                       if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
+                                       {
+                                               FreeRTOS_debug_printf( ( "Set SO_WIN_PROP: wrong socket type\n" ) );
+                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */
+                                       }
+
+                                       if( ( pxSocket->u.xTCP.txStream != NULL ) || ( pxSocket->u.xTCP.rxStream != NULL ) )
+                                       {
+                                               FreeRTOS_debug_printf( ( "Set SO_WIN_PROP: buffer already created\n" ) );
+                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */
+                                       }
+
+                                       pxProps = ( ( WinProperties_t * ) pvOptionValue );
+
+                                       if ( FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDBUF, &( pxProps->lTxBufSize ), sizeof( pxProps->lTxBufSize ) ) != 0 )
+                                       {
+                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */
+                                       }
+
+                                       if ( FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVBUF, &( pxProps->lRxBufSize ), sizeof( pxProps->lRxBufSize ) ) != 0 )
+                                       {
+                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */
+                                       }
+
+                                       #if( ipconfigUSE_TCP_WIN == 1 )
+                                       {
+                                               pxSocket->u.xTCP.uxRxWinSize = ( uint32_t )pxProps->lRxWinSize; /* Fixed value: size of the TCP reception window */
+                                               pxSocket->u.xTCP.uxTxWinSize = ( uint32_t )pxProps->lTxWinSize; /* Fixed value: size of the TCP transmit window */
+                                       }
+                                       #else
+                                       {
+                                               pxSocket->u.xTCP.uxRxWinSize = 1u;
+                                               pxSocket->u.xTCP.uxTxWinSize = 1u;
+                                       }
+                                       #endif
+
+                                       /* In case the socket has already initialised its tcpWin,
+                                       adapt the window size parameters */
+                                       if( pxSocket->u.xTCP.xTCPWindow.u.bits.bHasInit != pdFALSE_UNSIGNED )
+                                       {
+                                               pxSocket->u.xTCP.xTCPWindow.xSize.ulRxWindowLength = pxSocket->u.xTCP.uxRxWinSize * pxSocket->u.xTCP.usInitMSS;
+                                               pxSocket->u.xTCP.xTCPWindow.xSize.ulTxWindowLength = pxSocket->u.xTCP.uxTxWinSize * pxSocket->u.xTCP.usInitMSS;
+                                       }
+                               }
+
+                               xReturn = 0;
+                               break;
+
+                       case FREERTOS_SO_REUSE_LISTEN_SOCKET:   /* If true, the server-socket will turn into a connected socket */
+                               {
+                                       if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
+                                       {
+                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */
+                                       }
+                                       if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
+                                       {
+                                               pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE_UNSIGNED;
+                                       }
+                                       else
+                                       {
+                                               pxSocket->u.xTCP.bits.bReuseSocket = pdFALSE_UNSIGNED;
+                                       }
+                               }
+                               xReturn = 0;
+                               break;
+
+                       case FREERTOS_SO_CLOSE_AFTER_SEND:              /* As soon as the last byte has been transmitted, finalise the connection */
+                               {
+                                       if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
+                                       {
+                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */
+                                       }
+
+                                       if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
+                                       {
+                                               pxSocket->u.xTCP.bits.bCloseAfterSend = pdTRUE_UNSIGNED;
+                                       }
+                                       else
+                                       {
+                                               pxSocket->u.xTCP.bits.bCloseAfterSend = pdFALSE_UNSIGNED;
+                                       }
+                               }
+                               xReturn = 0;
+                               break;
+
+                       case FREERTOS_SO_SET_FULL_SIZE:         /* Refuse to send packets smaller than MSS  */
+                               {
+                                       if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
+                                       {
+                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */
+                                       }
+
+                                       if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
+                                       {
+                                               pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdTRUE_UNSIGNED;
+                                       }
+                                       else
+                                       {
+                                               pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdFALSE_UNSIGNED;
+                                       }
+
+                                       if( ( pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize == pdFALSE_UNSIGNED ) &&
+                                               ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) &&
+                                               ( FreeRTOS_outstanding( pxSocket ) != 0 ) )
+                                       {
+                                               pxSocket->u.xTCP.usTimeout = 1u; /* to set/clear bSendFullSize */
+                                               xSendEventToIPTask( eTCPTimerEvent );
+                                       }
+                               }
+                               xReturn = 0;
+                               break;
+
+                       case FREERTOS_SO_STOP_RX:               /* Refuse to receive more packts */
+                               {
+                                       if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
+                                       {
+                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */
+                                       }
+
+                                       if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
+                                       {
+                                               pxSocket->u.xTCP.bits.bRxStopped = pdTRUE_UNSIGNED;
+                                       }
+                                       else
+                                       {
+                                               pxSocket->u.xTCP.bits.bRxStopped = pdFALSE_UNSIGNED;
+                                       }
+
+                                       pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
+                                       pxSocket->u.xTCP.usTimeout = 1u; /* to set/clear bRxStopped */
+                                       xSendEventToIPTask( eTCPTimerEvent );
+                               }
+                               xReturn = 0;
+                               break;
+
+               #endif  /* ipconfigUSE_TCP == 1 */
+
+               default :
+                       /* No other options are handled. */
+                       xReturn = -pdFREERTOS_ERRNO_ENOPROTOOPT;
+                       break;
+       }
+
+       return xReturn;
+} /* Tested */
+
+/*-----------------------------------------------------------*/
+
+/* Find an available port number per https://tools.ietf.org/html/rfc6056. */
+static uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol )
+{
+const uint16_t usEphemeralPortCount =
+       socketAUTO_PORT_ALLOCATION_MAX_NUMBER - socketAUTO_PORT_ALLOCATION_START_NUMBER + 1;
+uint16_t usIterations = usEphemeralPortCount;
+uint32_t ulRandomSeed = 0;
+uint16_t usResult = 0;
+const List_t *pxList;
+
+#if ipconfigUSE_TCP == 1
+       if( xProtocol == ( BaseType_t ) FREERTOS_IPPROTO_TCP )
+       {
+               pxList = &xBoundTCPSocketsList;
+       }
+       else
+#endif
+       {
+               pxList = &xBoundUDPSocketsList;
+       }
+
+       /* Avoid compiler warnings if ipconfigUSE_TCP is not defined. */
+       ( void ) xProtocol;
+
+       /* Find the next available port using the random seed as a starting
+       point. */
+       do
+       {
+               /* Only proceed if the random number generator succeeded. */
+               if( xApplicationGetRandomNumber( &( ulRandomSeed ) ) == pdFALSE )
+               {
+                       break;
+               }
+
+               /* Map the random to a candidate port. */
+               usResult =
+                       socketAUTO_PORT_ALLOCATION_START_NUMBER +
+                       ( ( ( uint16_t )ulRandomSeed ) % usEphemeralPortCount );
+
+               /* Check if there's already an open socket with the same protocol
+               and port. */
+               if( NULL == pxListFindListItemWithValue(
+                       pxList,
+                       ( TickType_t )FreeRTOS_htons( usResult ) ) )
+               {
+                       usResult = FreeRTOS_htons( usResult );
+                       break;
+               }
+               else
+               {
+                       usResult = 0;
+               }
+
+               usIterations--;
+       }
+       while( usIterations > 0 );
+
+       return usResult;
+}
+/*-----------------------------------------------------------*/
+
+/* pxListFindListItemWithValue: find a list item in a bound socket list
+'xWantedItemValue' refers to a port number */
+static const ListItem_t * pxListFindListItemWithValue( const List_t *pxList, TickType_t xWantedItemValue )
+{
+const ListItem_t * pxResult = NULL;
+
+       if( ( xIPIsNetworkTaskReady() != pdFALSE ) && ( pxList != NULL ) )
+       {
+               const ListItem_t *pxIterator;
+               const MiniListItem_t *pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( pxList );
+               for( pxIterator  = ( const ListItem_t * ) listGET_NEXT( pxEnd );
+                        pxIterator != ( const ListItem_t * ) pxEnd;
+                        pxIterator  = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
+               {
+                       if( listGET_LIST_ITEM_VALUE( pxIterator ) == xWantedItemValue )
+                       {
+                               pxResult = pxIterator;
+                               break;
+                       }
+               }
+       }
+
+       return pxResult;
+} /* Tested */
+
+/*-----------------------------------------------------------*/
+
+FreeRTOS_Socket_t *pxUDPSocketLookup( UBaseType_t uxLocalPort )
+{
+const ListItem_t *pxListItem;
+FreeRTOS_Socket_t *pxSocket = NULL;
+
+       /* Looking up a socket is quite simple, find a match with the local port.
+
+       See if there is a list item associated with the port number on the
+       list of bound sockets. */
+       pxListItem = pxListFindListItemWithValue( &xBoundUDPSocketsList, ( TickType_t ) uxLocalPort );
+
+       if( pxListItem != NULL )
+       {
+               /* The owner of the list item is the socket itself. */
+               pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxListItem );
+               configASSERT( pxSocket != NULL );
+       }
+       return pxSocket;
+}
+
+/*-----------------------------------------------------------*/
+
+#if ipconfigINCLUDE_FULL_INET_ADDR == 1
+
+       uint32_t FreeRTOS_inet_addr( const char * pcIPAddress )
+       {
+       const uint32_t ulDecimalBase = 10u;
+       uint8_t ucOctet[ socketMAX_IP_ADDRESS_OCTETS ];
+       const char *pcPointerOnEntering;
+       uint32_t ulReturn = 0UL, ulValue;
+       UBaseType_t uxOctetNumber;
+       BaseType_t xResult = pdPASS;
+
+               for( uxOctetNumber = 0u; uxOctetNumber < socketMAX_IP_ADDRESS_OCTETS; uxOctetNumber++ )
+               {
+                       ulValue = 0ul;
+                       pcPointerOnEntering = pcIPAddress;
+
+                       while( ( *pcIPAddress >= '0' ) && ( *pcIPAddress <= '9' ) )
+                       {
+                               /* Move previous read characters into the next decimal
+                               position. */
+                               ulValue *= ulDecimalBase;
+
+                               /* Add the binary value of the ascii character. */
+                               ulValue += ( ( uint32_t ) ( *pcIPAddress ) - ( uint32_t ) '0' );
+
+                               /* Move to next character in the string. */
+                               pcIPAddress++;
+                       }
+
+                       /* Check characters were read. */
+                       if( pcIPAddress == pcPointerOnEntering )
+                       {
+                               xResult = pdFAIL;
+                       }
+
+                       /* Check the value fits in an 8-bit number. */
+                       if( ulValue > 0xffUL )
+                       {
+                               xResult = pdFAIL;
+                       }
+                       else
+                       {
+                               ucOctet[ uxOctetNumber ] = ( uint8_t ) ulValue;
+
+                               /* Check the next character is as expected. */
+                               if( uxOctetNumber < ( socketMAX_IP_ADDRESS_OCTETS - 1u ) )
+                               {
+                                       if( *pcIPAddress != '.' )
+                                       {
+                                               xResult = pdFAIL;
+                                       }
+                                       else
+                                       {
+                                               /* Move past the dot. */
+                                               pcIPAddress++;
+                                       }
+                               }
+                       }
+
+                       if( xResult == pdFAIL )
+                       {
+                               /* No point going on. */
+                               break;
+                       }
+               }
+
+               if( *pcIPAddress != ( char ) 0 )
+               {
+                       /* Expected the end of the string. */
+                       xResult = pdFAIL;
+               }
+
+               if( uxOctetNumber != socketMAX_IP_ADDRESS_OCTETS )
+               {
+                       /* Didn't read enough octets. */
+                       xResult = pdFAIL;
+               }
+
+               if( xResult == pdPASS )
+               {
+                       ulReturn = FreeRTOS_inet_addr_quick( ucOctet[ 0 ], ucOctet[ 1 ], ucOctet[ 2 ], ucOctet[ 3 ] );
+               }
+
+               return ulReturn;
+       }
+
+#endif /* ipconfigINCLUDE_FULL_INET_ADDR */
+
+/*-----------------------------------------------------------*/
+
+/* Function to get the local address and IP port */
+size_t FreeRTOS_GetLocalAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress )
+{
+FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+
+       /* IP address of local machine. */
+       pxAddress->sin_addr = *ipLOCAL_IP_ADDRESS_POINTER;
+
+       /* Local port on this machine. */
+       pxAddress->sin_port = FreeRTOS_htons( pxSocket->usLocalPort );
+
+       return sizeof( *pxAddress );
+}
+
+/*-----------------------------------------------------------*/
+
+void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
+{
+/* _HT_ must work this out, now vSocketWakeUpUser will be called for any important
+ * event or transition */
+       #if( ipconfigSOCKET_HAS_USER_SEMAPHORE == 1 )
+       {
+               if( pxSocket->pxUserSemaphore != NULL )
+               {
+                       xSemaphoreGive( pxSocket->pxUserSemaphore );
+               }
+       }
+       #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
+
+       #if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK == 1 )
+       {
+               if( pxSocket->pxUserWakeCallback != NULL )
+               {
+                       pxSocket->pxUserWakeCallback( pxSocket );
+               }
+       }
+       #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
+
+       #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
+       {
+               if( pxSocket->pxSocketSet != NULL )
+               {
+                       EventBits_t xSelectBits = ( pxSocket->xEventBits >> SOCKET_EVENT_BIT_COUNT ) & eSELECT_ALL;
+                       if( xSelectBits != 0ul )
+                       {
+                               pxSocket->xSocketBits |= xSelectBits;
+                               xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, xSelectBits );
+                       }
+               }
+
+               pxSocket->xEventBits &= eSOCKET_ALL;
+       }
+       #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
+
+       if( ( pxSocket->xEventGroup != NULL ) && ( pxSocket->xEventBits != 0u ) )
+       {
+               xEventGroupSetBits( pxSocket->xEventGroup, pxSocket->xEventBits );
+       }
+
+       pxSocket->xEventBits = 0ul;
+}
+
+/*-----------------------------------------------------------*/
+
+#if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
+
+       /* This define makes it possible for network-card drivers to inspect
+        * UDP message and see if there is any UDP socket bound to a given port
+        * number.
+        * This is probably only usefull in systems with a minimum of RAM and
+        * when lots of anonymous broadcast messages come in
+        */
+       BaseType_t xPortHasUDPSocket( uint16_t usPortNr )
+       {
+       BaseType_t xFound = pdFALSE;
+
+               vTaskSuspendAll();
+               {
+                       if( ( pxListFindListItemWithValue( &xBoundUDPSocketsList, ( TickType_t ) usPortNr ) != NULL ) )
+                       {
+                               xFound = pdTRUE;
+                       }
+               }
+               xTaskResumeAll();
+
+               return xFound;
+       }
+
+#endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
+
+/*-----------------------------------------------------------*/
+
+#if( ipconfigUSE_TCP == 1 )
+
+       static BaseType_t bMayConnect( FreeRTOS_Socket_t *pxSocket );
+       static BaseType_t bMayConnect( FreeRTOS_Socket_t *pxSocket )
+       {
+               switch( pxSocket->u.xTCP.ucTCPState )
+               {
+                       case eCLOSED:
+                       case eCLOSE_WAIT:       return 0;
+                       case eCONNECT_SYN:      return -pdFREERTOS_ERRNO_EINPROGRESS;
+                       default:                        return -pdFREERTOS_ERRNO_EAGAIN;
+               }
+       }
+
+#endif /* ipconfigUSE_TCP */
+/*-----------------------------------------------------------*/
+
+#if( ipconfigUSE_TCP == 1 )
+
+       static BaseType_t prvTCPConnectStart( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr *pxAddress )
+       {
+       BaseType_t xResult = 0;
+
+               if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdFALSE )
+               {
+                       /* Not a valid socket or wrong type */
+                       xResult = -pdFREERTOS_ERRNO_EBADF;
+               }
+               else if( FreeRTOS_issocketconnected( pxSocket ) > 0 )
+               {
+                       /* The socket is already connected. */
+                       xResult = -pdFREERTOS_ERRNO_EISCONN;
+               }
+               else if( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE )
+               {
+                       /* Bind the socket to the port that the client task will send from.
+                       Non-standard, so the error returned is that returned by bind(). */
+                       xResult = FreeRTOS_bind( ( Socket_t ) pxSocket, NULL, 0u );
+               }
+
+               if( xResult == 0 )
+               {
+                       /* Check if it makes any sense to wait for a connect event, this condition
+                       might change while sleeping, so it must be checked within each loop */
+                       xResult = bMayConnect( pxSocket ); /* -EINPROGRESS, -EAGAIN, or 0 for OK */
+
+                       /* Start the connect procedure, kernel will start working on it */
+                       if( xResult == 0 )
+                       {
+                               pxSocket->u.xTCP.bits.bConnPrepared = pdFALSE_UNSIGNED;
+                               pxSocket->u.xTCP.ucRepCount = 0u;
+
+                               FreeRTOS_debug_printf( ( "FreeRTOS_connect: %u to %lxip:%u\n",
+                                       pxSocket->usLocalPort, FreeRTOS_ntohl( pxAddress->sin_addr ), FreeRTOS_ntohs( pxAddress->sin_port ) ) );
+
+                               /* Port on remote machine. */
+                               pxSocket->u.xTCP.usRemotePort = FreeRTOS_ntohs( pxAddress->sin_port );
+
+                               /* IP address of remote machine. */
+                               pxSocket->u.xTCP.ulRemoteIP = FreeRTOS_ntohl( pxAddress->sin_addr );
+
+                               /* (client) internal state: socket wants to send a connect. */
+                               vTCPStateChange( pxSocket, eCONNECT_SYN );
+
+                               /* To start an active connect. */
+                               pxSocket->u.xTCP.usTimeout = 1u;
+
+                               if( xSendEventToIPTask( eTCPTimerEvent ) != pdPASS )
+                               {
+                                       xResult = -pdFREERTOS_ERRNO_ECANCELED;
+                               }
+                       }
+               }
+
+               return xResult;
+       }
+
+#endif /* ipconfigUSE_TCP */
+/*-----------------------------------------------------------*/
+
+#if( ipconfigUSE_TCP == 1 )
+
+       /*
+        * FreeRTOS_connect: socket wants to connect to a remote port
+        */
+       BaseType_t FreeRTOS_connect( Socket_t xClientSocket, struct freertos_sockaddr *pxAddress, socklen_t xAddressLength )
+       {
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t* ) xClientSocket;
+       TickType_t xRemainingTime;
+       BaseType_t xTimed = pdFALSE;
+       BaseType_t xResult;
+       TimeOut_t xTimeOut;
+
+               ( void ) xAddressLength;
+
+               xResult = prvTCPConnectStart( pxSocket, pxAddress );
+
+               if( xResult == 0 )
+               {
+                       /* And wait for the result */
+                       for( ;; )
+                       {
+                               if( xTimed == pdFALSE )
+                               {
+                                       /* Only in the first round, check for non-blocking */
+                                       xRemainingTime = pxSocket->xReceiveBlockTime;
+                                       if( xRemainingTime == ( TickType_t )0 )
+                                       {
+                                               /* Not yet connected, correct state, non-blocking. */
+                                               xResult = -pdFREERTOS_ERRNO_EWOULDBLOCK;
+                                               break;
+                                       }
+
+                                       /* Don't get here a second time. */
+                                       xTimed = pdTRUE;
+
+                                       /* Fetch the current time */
+                                       vTaskSetTimeOutState( &xTimeOut );
+                               }
+
+                               /* Did it get connected while sleeping ? */
+                               xResult = FreeRTOS_issocketconnected( pxSocket );
+
+                               /* Returns positive when connected, negative means an error */
+                               if( xResult < 0 )
+                               {
+                                       /* Return the error */
+                                       break;
+                               }
+
+                               if( xResult > 0 )
+                               {
+                                       /* Socket now connected, return a zero */
+                                       xResult = 0;
+                                       break;
+                               }
+
+                               /* Is it allowed to sleep more? */
+                               if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) )
+                               {
+                                       xResult = -pdFREERTOS_ERRNO_ETIMEDOUT;
+                                       break;
+                               }
+
+                               /* Go sleeping until we get any down-stream event */
+                               xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_CONNECT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
+                       }
+               }
+
+               return xResult;
+       }
+#endif /* ipconfigUSE_TCP */
+/*-----------------------------------------------------------*/
+
+#if( ipconfigUSE_TCP == 1 )
+
+       /*
+        * FreeRTOS_accept: can return a new connected socket
+        * if the server socket is in listen mode and receives a connection request
+        * The new socket will be bound already to the same port number as the listing
+        * socket.
+        */
+       Socket_t FreeRTOS_accept( Socket_t xServerSocket, struct freertos_sockaddr *pxAddress, socklen_t *pxAddressLength )
+       {
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xServerSocket;
+       FreeRTOS_Socket_t *pxClientSocket = NULL;
+       TickType_t xRemainingTime;
+       BaseType_t xTimed = pdFALSE, xAsk = pdFALSE;
+       TimeOut_t xTimeOut;
+       IPStackEvent_t xAskEvent;
+
+               if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
+               {
+                       /* Not a valid socket or wrong type */
+                       pxClientSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
+               }
+               else if( ( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED ) &&
+                                ( pxSocket->u.xTCP.ucTCPState != eTCP_LISTEN ) )
+               {
+                       /* Parent socket is not in listening mode */
+                       pxClientSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
+               }
+               else
+               {
+                       /* Loop will stop with breaks. */
+                       for( ; ; )
+                       {
+                               /* Is there a new client? */
+                               vTaskSuspendAll();
+                               {
+                                       if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED )
+                                       {
+                                               pxClientSocket = pxSocket->u.xTCP.pxPeerSocket;
+                                       }
+                                       else
+                                       {
+                                               pxClientSocket = pxSocket;
+                                       }
+                                       if( pxClientSocket != NULL )
+                                       {
+                                               pxSocket->u.xTCP.pxPeerSocket = NULL;
+
+                                               /* Is it still not taken ? */
+                                               if( pxClientSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED )
+                                               {
+                                                       pxClientSocket->u.xTCP.bits.bPassAccept = pdFALSE_UNSIGNED;
+                                               }
+                                               else
+                                               {
+                                                       pxClientSocket = NULL;
+                                               }
+                                       }
+                               }
+                               xTaskResumeAll();
+
+                               if( pxClientSocket != NULL )
+                               {
+                                       if( pxAddress != NULL )
+                                       {
+                                               /* IP address of remote machine. */
+                                               pxAddress->sin_addr = FreeRTOS_ntohl( pxClientSocket->u.xTCP.ulRemoteIP );
+
+                                               /* Port on remote machine. */
+                                               pxAddress->sin_port = FreeRTOS_ntohs( pxClientSocket->u.xTCP.usRemotePort );
+                                       }
+                                       if( pxAddressLength != NULL )
+                                       {
+                                               *pxAddressLength = sizeof( *pxAddress );
+                                       }
+
+                                       if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED )
+                                       {
+                                               xAsk = pdTRUE;
+                                       }
+                               }
+
+                               if( xAsk != pdFALSE )
+                               {
+                                       /* Ask to set an event in 'xEventGroup' as soon as a new
+                                       client gets connected for this listening socket. */
+                                       xAskEvent.eEventType = eTCPAcceptEvent;
+                                       xAskEvent.pvData = ( void * ) pxSocket;
+                                       xSendEventStructToIPTask( &xAskEvent, portMAX_DELAY );
+                               }
+
+                               if( pxClientSocket != NULL )
+                               {
+                                       break;
+                               }
+
+                               if( xTimed == pdFALSE )
+                               {
+                                       /* Only in the first round, check for non-blocking */
+                                       xRemainingTime = pxSocket->xReceiveBlockTime;
+                                       if( xRemainingTime == ( TickType_t ) 0 )
+                                       {
+                                               break;
+                                       }
+
+                                       /* Don't get here a second time */
+                                       xTimed = pdTRUE;
+
+                                       /* Fetch the current time */
+                                       vTaskSetTimeOutState( &xTimeOut );
+                               }
+
+                               /* Has the timeout been reached? */
+                               if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
+                               {
+                                       break;
+                               }
+
+                               /* Go sleeping until we get any down-stream event */
+                               xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_ACCEPT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
+                       }
+               }
+
+               return ( Socket_t ) pxClientSocket;
+       }
+#endif /* ipconfigUSE_TCP */
+/*-----------------------------------------------------------*/
+
+#if( ipconfigUSE_TCP == 1 )
+
+       /*
+        * Read incoming data from a TCP socket
+        * Only after the last byte has been read, a close error might be returned
+        */
+       BaseType_t FreeRTOS_recv( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags )
+       {
+       BaseType_t xByteCount;
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+       TickType_t xRemainingTime;
+       BaseType_t xTimed = pdFALSE;
+       TimeOut_t xTimeOut;
+       EventBits_t xEventBits = ( EventBits_t ) 0;
+
+               /* Check if the socket is valid, has type TCP and if it is bound to a
+               port. */
+               if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
+               {
+                       xByteCount = -pdFREERTOS_ERRNO_EINVAL;
+               }
+               else
+               {
+                       if( pxSocket->u.xTCP.rxStream != NULL )
+                       {
+                               xByteCount = ( BaseType_t )uxStreamBufferGetSize ( pxSocket->u.xTCP.rxStream );
+                       }
+                       else
+                       {
+                               xByteCount = 0;
+                       }
+
+                       while( xByteCount == 0 )
+                       {
+                               switch( pxSocket->u.xTCP.ucTCPState )
+                               {
+                               case eCLOSED:
+                               case eCLOSE_WAIT:       /* (server + client) waiting for a connection termination request from the local user. */
+                               case eCLOSING:          /* (server + client) waiting for a connection termination request acknowledgement from the remote TCP. */
+                                       if( pxSocket->u.xTCP.bits.bMallocError != pdFALSE_UNSIGNED )
+                                       {
+                                               /* The no-memory error has priority above the non-connected error.
+                                               Both are fatal and will elad to closing the socket. */
+                                               xByteCount = -pdFREERTOS_ERRNO_ENOMEM;
+                                       }
+                                       else
+                                       {
+                                               xByteCount = -pdFREERTOS_ERRNO_ENOTCONN;
+                                       }
+                                       /* Call continue to break out of the switch and also the while
+                                       loop. */
+                                       continue;
+                               default:
+                                       break;
+                               }
+
+                               if( xTimed == pdFALSE )
+                               {
+                                       /* Only in the first round, check for non-blocking. */
+                                       xRemainingTime = pxSocket->xReceiveBlockTime;
+
+                                       if( xRemainingTime == ( TickType_t ) 0 )
+                                       {
+                                               #if( ipconfigSUPPORT_SIGNALS != 0 )
+                                               {
+                                                       /* Just check for the interrupt flag. */
+                                                       xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_INTR,
+                                                               pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, socketDONT_BLOCK );
+                                               }
+                                               #endif /* ipconfigSUPPORT_SIGNALS */
+                                               break;
+                                       }
+
+                                       if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
+                                       {
+                                               break;
+                                       }
+
+                                       /* Don't get here a second time. */
+                                       xTimed = pdTRUE;
+
+                                       /* Fetch the current time. */
+                                       vTaskSetTimeOutState( &xTimeOut );
+                               }
+
+                               /* Has the timeout been reached? */
+                               if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
+                               {
+                                       break;
+                               }
+
+                               /* Block until there is a down-stream event. */
+                               xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup,
+                                       eSOCKET_RECEIVE | eSOCKET_CLOSED | eSOCKET_INTR,
+                                       pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
+                               #if( ipconfigSUPPORT_SIGNALS != 0 )
+                               {
+                                       if( ( xEventBits & eSOCKET_INTR ) != 0u )
+                                       {
+                                               break;
+                                       }
+                               }
+                               #else
+                               {
+                                       ( void ) xEventBits;
+                               }
+                               #endif /* ipconfigSUPPORT_SIGNALS */
+
+                               if( pxSocket->u.xTCP.rxStream != NULL )
+                               {
+                                       xByteCount = ( BaseType_t ) uxStreamBufferGetSize ( pxSocket->u.xTCP.rxStream );
+                               }
+                               else
+                               {
+                                       xByteCount = 0;
+                               }
+                       }
+
+               #if( ipconfigSUPPORT_SIGNALS != 0 )
+                       if( ( xEventBits & eSOCKET_INTR ) != 0 )
+                       {
+                               if( ( xEventBits & ( eSOCKET_RECEIVE | eSOCKET_CLOSED ) ) != 0 )
+                               {
+                                       /* Shouldn't have cleared other flags. */
+                                       xEventBits &= ~eSOCKET_INTR;
+                                       xEventGroupSetBits( pxSocket->xEventGroup, xEventBits );
+                               }
+                               xByteCount = -pdFREERTOS_ERRNO_EINTR;
+                       }
+                       else
+               #endif /* ipconfigSUPPORT_SIGNALS */
+                       if( xByteCount > 0 )
+                       {
+                               if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
+                               {
+                                       xByteCount = ( BaseType_t ) uxStreamBufferGet( pxSocket->u.xTCP.rxStream, 0ul, ( uint8_t * ) pvBuffer, ( size_t ) xBufferLength, ( xFlags & FREERTOS_MSG_PEEK ) != 0 );
+                                       if( pxSocket->u.xTCP.bits.bLowWater != pdFALSE_UNSIGNED )
+                                       {
+                                               /* We had reached the low-water mark, now see if the flag
+                                               can be cleared */
+                                               size_t uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );
+
+                                               if( uxFrontSpace >= pxSocket->u.xTCP.uxEnoughSpace )
+                                               {
+                                                       pxSocket->u.xTCP.bits.bLowWater = pdFALSE_UNSIGNED;
+                                                       pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
+                                                       pxSocket->u.xTCP.usTimeout = 1u; /* because bLowWater is cleared. */
+                                                       xSendEventToIPTask( eTCPTimerEvent );
+                                               }
+                                       }
+                               }
+                               else
+                               {
+                                       /* Zero-copy reception of data: pvBuffer is a pointer to a pointer. */
+                                       xByteCount = ( BaseType_t ) uxStreamBufferGetPtr( pxSocket->u.xTCP.rxStream, (uint8_t **)pvBuffer );
+                               }
+                       }
+               } /* prvValidSocket() */
+
+               return xByteCount;
+       }
+
+#endif /* ipconfigUSE_TCP */
+/*-----------------------------------------------------------*/
+
+#if( ipconfigUSE_TCP == 1 )
+
+       static int32_t prvTCPSendCheck( FreeRTOS_Socket_t *pxSocket, size_t xDataLength )
+       {
+       int32_t xResult = 1;
+
+               /* Is this a socket of type TCP and is it already bound to a port number ? */
+               if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
+               {
+                       xResult = -pdFREERTOS_ERRNO_EINVAL;
+               }
+               else if( pxSocket->u.xTCP.bits.bMallocError != pdFALSE_UNSIGNED )
+               {
+                       xResult = -pdFREERTOS_ERRNO_ENOMEM;
+               }
+               else if( pxSocket->u.xTCP.ucTCPState == eCLOSED ||
+                 pxSocket->u.xTCP.ucTCPState == eCLOSE_WAIT ||
+                 pxSocket->u.xTCP.ucTCPState == eCLOSING )
+               {
+                       xResult = -pdFREERTOS_ERRNO_ENOTCONN;
+               }
+               else if( pxSocket->u.xTCP.bits.bFinSent != pdFALSE_UNSIGNED )
+               {
+                       /* This TCP connection is closing already, the FIN flag has been sent.
+                       Maybe it is still delivering or receiving data.
+                       Return OK in order not to get closed/deleted too quickly */
+                       xResult = 0;
+               }
+               else if( xDataLength == 0ul )
+               {
+                       /* send() is being called to send zero bytes */
+                       xResult = 0;
+               }
+               else if( pxSocket->u.xTCP.txStream == NULL )
+               {
+                       /* Create the outgoing stream only when it is needed */
+                       prvTCPCreateStream( pxSocket, pdFALSE );
+
+                       if( pxSocket->u.xTCP.txStream == NULL )
+                       {
+                               xResult = -pdFREERTOS_ERRNO_ENOMEM;
+                       }
+               }
+
+               return xResult;
+       }
+
+#endif /* ipconfigUSE_TCP */
+/*-----------------------------------------------------------*/
+
+#if( ipconfigUSE_TCP == 1 )
+
+       /* Get a direct pointer to the circular transmit buffer.
+       '*pxLength' will contain the number of bytes that may be written. */
+       uint8_t *FreeRTOS_get_tx_head( Socket_t xSocket, BaseType_t *pxLength )
+       {
+    uint8_t *pucReturn = NULL;
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+       StreamBuffer_t *pxBuffer = NULL;
+
+        *pxLength = 0;
+
+        /* Confirm that this is a TCP socket before dereferencing structure
+        member pointers. */
+        if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdTRUE )
+        {
+            pxBuffer = pxSocket->u.xTCP.txStream;
+            if( pxBuffer != NULL )
+            {
+            BaseType_t xSpace = ( BaseType_t )uxStreamBufferGetSpace( pxBuffer );
+            BaseType_t xRemain = ( BaseType_t )( pxBuffer->LENGTH - pxBuffer->uxHead );
+
+                *pxLength = FreeRTOS_min_BaseType( xSpace, xRemain );
+                pucReturn = pxBuffer->ucArray + pxBuffer->uxHead;
+            }
+               }
+
+               return pucReturn;
+       }
+#endif /* ipconfigUSE_TCP */
+/*-----------------------------------------------------------*/
+
+#if( ipconfigUSE_TCP == 1 )
+       /*
+        * Send data using a TCP socket.  It is not necessary to have the socket
+        * connected already.  Outgoing data will be stored and delivered as soon as
+        * the socket gets connected.
+        */
+       BaseType_t FreeRTOS_send( Socket_t xSocket, const void *pvBuffer, size_t uxDataLength, BaseType_t xFlags )
+       {
+       BaseType_t xByteCount;
+       BaseType_t xBytesLeft;
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+       TickType_t xRemainingTime;
+       BaseType_t xTimed = pdFALSE;
+       TimeOut_t xTimeOut;
+       BaseType_t xCloseAfterSend;
+
+               /* Prevent compiler warnings about unused parameters.  The parameter
+               may be used in future versions. */
+               ( void ) xFlags;
+
+               xByteCount = ( BaseType_t ) prvTCPSendCheck( pxSocket, uxDataLength );
+
+               if( xByteCount > 0 )
+               {
+                       /* xBytesLeft is number of bytes to send, will count to zero. */
+                       xBytesLeft = ( BaseType_t ) uxDataLength;
+
+                       /* xByteCount is number of bytes that can be sent now. */
+                       xByteCount = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
+
+                       /* While there are still bytes to be sent. */
+                       while( xBytesLeft > 0 )
+                       {
+                               /* If txStream has space. */
+                               if( xByteCount > 0 )
+                               {
+                                       /* Don't send more than necessary. */
+                                       if( xByteCount > xBytesLeft )
+                                       {
+                                               xByteCount = xBytesLeft;
+                                       }
+
+                                       /* Is the close-after-send flag set and is this really the
+                                       last transmission? */
+                                       if( ( pxSocket->u.xTCP.bits.bCloseAfterSend != pdFALSE_UNSIGNED ) && ( xByteCount == xBytesLeft ) )
+                                       {
+                                               xCloseAfterSend = pdTRUE;
+                                       }
+                                       else
+                                       {
+                                               xCloseAfterSend = pdFALSE;
+                                       }
+
+                                       /* The flag 'bCloseAfterSend' can be set before sending data
+                                       using setsockopt()
+
+                                       When the last data packet is being sent out, a FIN flag will
+                                       be included to let the peer know that no more data is to be
+                                       expected.  The use of 'bCloseAfterSend' is not mandatory, it
+                                       is just a faster way of transferring files (e.g. when using
+                                       FTP). */
+                                       if( xCloseAfterSend != pdFALSE )
+                                       {
+                                               /* Now suspend the scheduler: sending the last data     and
+                                               setting bCloseRequested must be done together */
+                                               vTaskSuspendAll();
+                                               pxSocket->u.xTCP.bits.bCloseRequested = pdTRUE_UNSIGNED;
+                                       }
+
+                                       xByteCount = ( BaseType_t ) uxStreamBufferAdd( pxSocket->u.xTCP.txStream, 0ul, ( const uint8_t * ) pvBuffer, ( size_t ) xByteCount );
+
+                                       if( xCloseAfterSend != pdFALSE )
+                                       {
+                                               /* Now when the IP-task transmits the data, it will also
+                                               see     that bCloseRequested is true and include the FIN
+                                               flag to start closure of the connection. */
+                                               xTaskResumeAll();
+                                       }
+
+                                       /* Send a message to the IP-task so it can work on this
+                                       socket.  Data is sent, let the IP-task work on it. */
+                                       pxSocket->u.xTCP.usTimeout = 1u;
+
+                                       if( xIsCallingFromIPTask() == pdFALSE )
+                                       {
+                                               /* Only send a TCP timer event when not called from the
+                                               IP-task. */
+                                               xSendEventToIPTask( eTCPTimerEvent );
+                                       }
+
+                                       xBytesLeft -= xByteCount;
+
+                                       if( xBytesLeft == 0 )
+                                       {
+                                               break;
+                                       }
+
+                                       /* As there are still bytes left to be sent, increase the
+                                       data pointer. */
+                                       pvBuffer = ( void * ) ( ( ( const uint8_t * ) pvBuffer) + xByteCount );
+                               }
+
+                               /* Not all bytes have been sent. In case the socket is marked as
+                               blocking sleep for a while. */
+                               if( xTimed == pdFALSE )
+                               {
+                                       /* Only in the first round, check for non-blocking. */
+                                       xRemainingTime = pxSocket->xSendBlockTime;
+
+                                       #if( ipconfigUSE_CALLBACKS != 0 )
+                                       {
+                                               if( xIsCallingFromIPTask() != pdFALSE )
+                                               {
+                                                       /* If this send function is called from within a
+                                                       call-back handler it may not block, otherwise
+                                                       chances would be big to get a deadlock: the IP-task
+                                                       waiting for     itself. */
+                                                       xRemainingTime = ( TickType_t ) 0;
+                                               }
+                                       }
+                                       #endif /* ipconfigUSE_CALLBACKS */
+
+                                       if( xRemainingTime == ( TickType_t ) 0 )
+                                       {
+                                               break;
+                                       }
+
+                                       if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
+                                       {
+                                               break;
+                                       }
+
+                                       /* Don't get here a second time. */
+                                       xTimed = pdTRUE;
+
+                                       /* Fetch the current time. */
+                                       vTaskSetTimeOutState( &xTimeOut );
+                               }
+                               else
+                               {
+                                       /* Has the timeout been reached? */
+                                       if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
+                                       {
+                                               break;
+                                       }
+                               }
+
+                               /* Go sleeping until down-stream events are received. */
+                               xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_SEND | eSOCKET_CLOSED,
+                                       pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
+
+                               xByteCount = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
+                       }
+
+                       /* How much was actually sent? */
+                       xByteCount = ( ( BaseType_t ) uxDataLength ) - xBytesLeft;
+
+                       if( xByteCount == 0 )
+                       {
+                               if( pxSocket->u.xTCP.ucTCPState > eESTABLISHED )
+                               {
+                                       xByteCount = ( BaseType_t ) -pdFREERTOS_ERRNO_ENOTCONN;
+                               }
+                               else
+                               {
+                                       if( ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) != pdFALSE )
+                                       {
+                                               FreeRTOS_debug_printf( ( "FreeRTOS_send: %u -> %lxip:%d: no space\n",
+                                                       pxSocket->usLocalPort,
+                                                       pxSocket->u.xTCP.ulRemoteIP,
+                                                       pxSocket->u.xTCP.usRemotePort ) );
+                                       }
+
+                                       xByteCount = ( BaseType_t ) -pdFREERTOS_ERRNO_ENOSPC;
+                               }
+                       }
+               }
+
+               return xByteCount;
+       }
+
+#endif /* ipconfigUSE_TCP */
+/*-----------------------------------------------------------*/
+
+#if( ipconfigUSE_TCP == 1 )
+
+       /*
+        * Request to put a socket in listen mode
+        */
+       BaseType_t FreeRTOS_listen( Socket_t xSocket, BaseType_t xBacklog )
+       {
+       FreeRTOS_Socket_t *pxSocket;
+       BaseType_t xResult = 0;
+
+               pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+
+               /* listen() is allowed for a valid TCP socket in Closed state and already
+               bound. */
+               if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
+               {
+                       xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
+               }
+               else if( ( pxSocket->u.xTCP.ucTCPState != eCLOSED ) && ( pxSocket->u.xTCP.ucTCPState != eCLOSE_WAIT ) )
+               {
+                       /* Socket is in a wrong state. */
+                       xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
+               }
+               else
+               {
+                       /* Backlog is interpreted here as "the maximum number of child
+                       sockets. */
+                       pxSocket->u.xTCP.usBacklog = ( uint16_t )FreeRTOS_min_int32( ( int32_t ) 0xffff, ( int32_t ) xBacklog );
+
+                       /* This cleaning is necessary only if a listening socket is being
+                       reused as it might have had a previous connection. */
+                       if( pxSocket->u.xTCP.bits.bReuseSocket )
+                       {
+                               if( pxSocket->u.xTCP.rxStream != NULL )
+                               {
+                                       vStreamBufferClear( pxSocket->u.xTCP.rxStream );
+                               }
+
+                               if( pxSocket->u.xTCP.txStream != NULL )
+                               {
+                                       vStreamBufferClear( pxSocket->u.xTCP.txStream );
+                               }
+
+                               memset( pxSocket->u.xTCP.xPacket.u.ucLastPacket, '\0', sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket ) );
+                               memset( &pxSocket->u.xTCP.xTCPWindow, '\0', sizeof( pxSocket->u.xTCP.xTCPWindow ) );
+                               memset( &pxSocket->u.xTCP.bits, '\0', sizeof( pxSocket->u.xTCP.bits ) );
+
+                               /* Now set the bReuseSocket flag again, because the bits have
+                               just been cleared. */
+                               pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE_UNSIGNED;
+                       }
+
+                       vTCPStateChange( pxSocket, eTCP_LISTEN );
+               }
+
+               return xResult;
+       }
+
+#endif /* ipconfigUSE_TCP */
+/*-----------------------------------------------------------*/
+
+#if( ipconfigUSE_TCP == 1 )
+
+       /* shutdown - shut down part of a full-duplex connection */
+       BaseType_t FreeRTOS_shutdown( Socket_t xSocket, BaseType_t xHow )
+       {
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+       BaseType_t xResult;
+
+               if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
+               {
+                       /*_RB_ Is this comment correct?  The socket is not of a type that
+                       supports the listen() operation. */
+                       xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
+               }
+               else if ( pxSocket->u.xTCP.ucTCPState != eESTABLISHED )
+               {
+                       /*_RB_ Is this comment correct?  The socket is not of a type that
+                       supports the listen() operation. */
+                       xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
+               }
+               else
+               {
+                       pxSocket->u.xTCP.bits.bUserShutdown = pdTRUE_UNSIGNED;
+
+                       /* Let the IP-task perform the shutdown of the connection. */
+                       pxSocket->u.xTCP.usTimeout = 1u;
+                       xSendEventToIPTask( eTCPTimerEvent );
+                       xResult = 0;
+               }
+               (void) xHow;
+
+               return xResult;
+       }
+
+#endif /* ipconfigUSE_TCP */
+/*-----------------------------------------------------------*/
+
+#if( ipconfigUSE_TCP == 1 )
+
+       /*
+        * A TCP timer has expired, now check all TCP sockets for:
+        * - Active connect
+        * - Send a delayed ACK
+        * - Send new data
+        * - Send a keep-alive packet
+        * - Check for timeout (in non-connected states only)
+        */
+       TickType_t xTCPTimerCheck( BaseType_t xWillSleep )
+       {
+       FreeRTOS_Socket_t *pxSocket;
+       TickType_t xShortest = pdMS_TO_TICKS( ( TickType_t ) ipTCP_TIMER_PERIOD_MS );
+       TickType_t xNow = xTaskGetTickCount();
+       static TickType_t xLastTime = 0u;
+       TickType_t xDelta = xNow - xLastTime;
+       ListItem_t* pxEnd = ( ListItem_t * ) listGET_END_MARKER( &xBoundTCPSocketsList );
+       ListItem_t *pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );
+
+               xLastTime = xNow;
+
+               if( xDelta == 0u )
+               {
+                       xDelta = 1u;
+               }
+
+               while( pxIterator != pxEnd )
+               {
+                       pxSocket = ( FreeRTOS_Socket_t * )listGET_LIST_ITEM_OWNER( pxIterator );
+                       pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator );
+
+                       /* Sockets with 'tmout == 0' do not need any regular attention. */
+                       if( pxSocket->u.xTCP.usTimeout == 0u )
+                       {
+                               continue;
+                       }
+
+                       if( xDelta < ( TickType_t ) pxSocket->u.xTCP.usTimeout )
+                       {
+                               pxSocket->u.xTCP.usTimeout = ( uint16_t ) ( ( ( TickType_t ) pxSocket->u.xTCP.usTimeout ) - xDelta );
+                       }
+                       else
+                       {
+                       int rc ;
+                               pxSocket->u.xTCP.usTimeout = 0u;
+                               rc = xTCPSocketCheck( pxSocket );
+
+                               /* Within this function, the socket might want to send a delayed
+                               ack or send out data or whatever it needs to do. */
+                               if( rc < 0 )
+                               {
+                                       /* Continue because the socket was deleted. */
+                                       continue;
+                               }
+                       }
+
+                       /* In xEventBits the driver may indicate that the socket has
+                       important events for the user.  These are only done just before the
+                       IP-task goes to sleep. */
+                       if( pxSocket->xEventBits != 0u )
+                       {
+                               if( xWillSleep != pdFALSE )
+                               {
+                                       /* The IP-task is about to go to sleep, so messages can be
+                                       sent to the socket owners. */
+                                       vSocketWakeUpUser( pxSocket );
+                               }
+                               else
+                               {
+                                       /* Or else make sure this will be called again to wake-up
+                                       the sockets' owner. */
+                                       xShortest = ( TickType_t ) 0;
+                               }
+                       }
+
+                       if( ( pxSocket->u.xTCP.usTimeout != 0u ) && ( xShortest > ( TickType_t ) pxSocket->u.xTCP.usTimeout ) )
+                       {
+                               xShortest = ( TickType_t ) pxSocket->u.xTCP.usTimeout;
+                       }
+               }
+
+               return xShortest;
+       }
+
+#endif /* ipconfigUSE_TCP */
+/*-----------------------------------------------------------*/
+
+#if( ipconfigUSE_TCP == 1 )
+
+       /*
+        * TCP: as multiple sockets may be bound to the same local port number
+        * looking up a socket is a little more complex:
+        * Both a local port, and a remote port and IP address are being used
+        * For a socket in listening mode, the remote port and IP address are both 0
+        */
+       FreeRTOS_Socket_t *pxTCPSocketLookup( uint32_t ulLocalIP, UBaseType_t uxLocalPort, uint32_t ulRemoteIP, UBaseType_t uxRemotePort )
+       {
+       ListItem_t *pxIterator;
+       FreeRTOS_Socket_t *pxResult = NULL, *pxListenSocket = NULL;
+       MiniListItem_t *pxEnd = ( MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );
+
+               /* Parameter not yet supported. */
+               ( void ) ulLocalIP;
+
+               for( pxIterator  = ( ListItem_t * ) listGET_NEXT( pxEnd );
+                        pxIterator != ( ListItem_t * ) pxEnd;
+                        pxIterator  = ( ListItem_t * ) listGET_NEXT( pxIterator ) )
+               {
+                       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
+
+                       if( pxSocket->usLocalPort == ( uint16_t ) uxLocalPort )
+                       {
+                               if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN )
+                               {
+                                       /* If this is a socket listening to uxLocalPort, remember it
+                                       in case there is no perfect match. */
+                                       pxListenSocket = pxSocket;
+                               }
+                               else if( ( pxSocket->u.xTCP.usRemotePort == ( uint16_t ) uxRemotePort ) && ( pxSocket->u.xTCP.ulRemoteIP == ulRemoteIP ) )
+                               {
+                                       /* For sockets not in listening mode, find a match with
+                                       xLocalPort, ulRemoteIP AND xRemotePort. */
+                                       pxResult = pxSocket;
+                                       break;
+                               }
+                       }
+               }
+               if( pxResult == NULL )
+               {
+                       /* An exact match was not found, maybe a listening socket was
+                       found. */
+                       pxResult = pxListenSocket;
+               }
+
+               return pxResult;
+       }
+
+#endif /* ipconfigUSE_TCP */
+/*-----------------------------------------------------------*/
+
+#if( ipconfigUSE_TCP == 1 )
+
+    const struct xSTREAM_BUFFER *FreeRTOS_get_rx_buf( Socket_t xSocket )
+    {
+    FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * )xSocket;
+    struct xSTREAM_BUFFER *pxReturn = NULL;
+
+        /* Confirm that this is a TCP socket before dereferencing structure
+        member pointers. */
+        if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdTRUE )
+        {
+            pxReturn = pxSocket->u.xTCP.rxStream;
+        }
+
+        return pxReturn;
+    }
+
+#endif /* ipconfigUSE_TCP */
+/*-----------------------------------------------------------*/
+
+#if( ipconfigUSE_TCP == 1 )
+
+       static StreamBuffer_t *prvTCPCreateStream ( FreeRTOS_Socket_t *pxSocket, BaseType_t xIsInputStream )
+       {
+       StreamBuffer_t *pxBuffer;
+       size_t uxLength;
+       size_t uxSize;
+
+               /* Now that a stream is created, the maximum size is fixed before
+               creation, it could still be changed with setsockopt(). */
+               if( xIsInputStream != pdFALSE )
+               {
+                       uxLength = pxSocket->u.xTCP.uxRxStreamSize;
+
+                       if( pxSocket->u.xTCP.uxLittleSpace == 0ul )
+                       {
+                               pxSocket->u.xTCP.uxLittleSpace  = ( sock20_PERCENT * pxSocket->u.xTCP.uxRxStreamSize ) / sock100_PERCENT;
+                       }
+
+                       if( pxSocket->u.xTCP.uxEnoughSpace == 0ul )
+                       {
+                               pxSocket->u.xTCP.uxEnoughSpace = ( sock80_PERCENT * pxSocket->u.xTCP.uxRxStreamSize ) / sock100_PERCENT;
+                       }
+               }
+               else
+               {
+                       uxLength = pxSocket->u.xTCP.uxTxStreamSize;
+               }
+
+               /* Add an extra 4 (or 8) bytes. */
+               uxLength += sizeof( size_t );
+
+               /* And make the length a multiple of sizeof( size_t ). */
+               uxLength &= ~( sizeof( size_t ) - 1u );
+
+               uxSize = sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) + uxLength;
+
+               pxBuffer = ( StreamBuffer_t * )pvPortMallocLarge( uxSize );
+
+               if( pxBuffer == NULL )
+               {
+                       FreeRTOS_debug_printf( ( "prvTCPCreateStream: malloc failed\n" ) );
+                       pxSocket->u.xTCP.bits.bMallocError = pdTRUE_UNSIGNED;
+                       vTCPStateChange( pxSocket, eCLOSE_WAIT );
+               }
+               else
+               {
+                       /* Clear the markers of the stream */
+                       memset( pxBuffer, '\0', sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) );
+                       pxBuffer->LENGTH = ( size_t ) uxLength ;
+
+                       if( xTCPWindowLoggingLevel != 0 )
+                       {
+                               FreeRTOS_debug_printf( ( "prvTCPCreateStream: %cxStream created %lu bytes (total %lu)\n", xIsInputStream ? 'R' : 'T', uxLength, uxSize ) );
+                       }
+
+                       if( xIsInputStream != 0 )
+                       {
+                               pxSocket->u.xTCP.rxStream = pxBuffer;
+                       }
+                       else
+                       {
+                               pxSocket->u.xTCP.txStream = pxBuffer;
+                       }
+               }
+
+               return pxBuffer;
+       }
+
+#endif /* ipconfigUSE_TCP */
+/*-----------------------------------------------------------*/
+
+#if( ipconfigUSE_TCP == 1 )
+
+       /*
+        * Add data to the RxStream.  When uxOffset > 0, data has come in out-of-order
+        * and will be put in front of the head so it can not be popped by the user.
+        */
+       int32_t lTCPAddRxdata( FreeRTOS_Socket_t *pxSocket, size_t uxOffset, const uint8_t *pcData, uint32_t ulByteCount )
+       {
+       StreamBuffer_t *pxStream = pxSocket->u.xTCP.rxStream;
+       int32_t xResult;
+       #if( ipconfigUSE_CALLBACKS == 1 )
+               BaseType_t bHasHandler = ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xTCP.pxHandleReceive );
+               const uint8_t *pucBuffer = NULL;
+       #endif /* ipconfigUSE_CALLBACKS */
+
+               /* int32_t uxStreamBufferAdd( pxBuffer, uxOffset, pucData, aCount )
+               if( pucData != NULL ) copy data the the buffer
+               if( pucData == NULL ) no copying, just advance rxHead
+               if( uxOffset != 0 ) Just store data which has come out-of-order
+               if( uxOffset == 0 ) Also advance rxHead */
+               if( pxStream == NULL )
+               {
+                       pxStream = prvTCPCreateStream( pxSocket, pdTRUE );
+                       if( pxStream == NULL )
+                       {
+                               return -1;
+                       }
+               }
+
+               #if( ipconfigUSE_CALLBACKS == 1 )
+               {
+                       if( ( bHasHandler != pdFALSE ) && ( uxStreamBufferGetSize( pxStream ) == 0u ) && ( uxOffset == 0ul ) && ( pcData != NULL ) )
+                       {
+                               /* Data can be passed directly to the user */
+                               pucBuffer = pcData;
+
+                               /* Zero-copy for call-back: no need to add the bytes to the
+                               stream, only the pointer will be advanced by uxStreamBufferAdd(). */
+                               pcData = NULL;
+                       }
+               }
+               #endif /* ipconfigUSE_CALLBACKS */
+
+               xResult = ( int32_t ) uxStreamBufferAdd( pxStream, uxOffset, pcData, ( size_t ) ulByteCount );
+
+               #if( ipconfigHAS_DEBUG_PRINTF != 0 )
+               {
+                       if( xResult != ( int32_t ) ulByteCount )
+                       {
+                               FreeRTOS_debug_printf( ( "lTCPAddRxdata: at %ld: %ld/%lu bytes (tail %lu head %lu space %lu front %lu)\n",
+                                       uxOffset, xResult, ulByteCount,
+                                       pxStream->uxTail,
+                                       pxStream->uxHead,
+                                       uxStreamBufferFrontSpace( pxStream ),
+                                       pxStream->uxFront ) );
+                       }
+               }
+               #endif /* ipconfigHAS_DEBUG_PRINTF */
+
+               if( uxOffset == 0u )
+               {
+                       /* Data is being added to rxStream at the head (offs = 0) */
+                       #if( ipconfigUSE_CALLBACKS == 1 )
+                               if( bHasHandler != pdFALSE )
+                               {
+                                       /* The socket owner has installed an OnReceive handler. Pass the
+                                       Rx data, without copying from the rxStream, to the user. */
+                                       for (;;)
+                                       {
+                                               uint8_t *ucReadPtr = NULL;
+                                               uint32_t ulCount;
+                                               if( pucBuffer != NULL )
+                                               {
+                                                       ucReadPtr = ( uint8_t * )pucBuffer;
+                                                       ulCount = ulByteCount;
+                                                       pucBuffer = NULL;
+                                               }
+                                               else
+                                               {
+                                                       ulCount = ( uint32_t ) uxStreamBufferGetPtr( pxStream, &( ucReadPtr ) );
+                                               }
+
+                                               if( ulCount == 0ul )
+                                               {
+                                                       break;
+                                               }
+
+                                               pxSocket->u.xTCP.pxHandleReceive( ( Socket_t )pxSocket, ( void* )ucReadPtr, ( size_t ) ulCount );
+                                               uxStreamBufferGet( pxStream, 0ul, NULL, ( size_t ) ulCount, pdFALSE );
+                                       }
+                               } else
+                       #endif /* ipconfigUSE_CALLBACKS */
+                       {
+                               /* See if running out of space. */
+                               if( pxSocket->u.xTCP.bits.bLowWater == pdFALSE_UNSIGNED )
+                               {
+                                       size_t uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );
+                                       if( uxFrontSpace <= pxSocket->u.xTCP.uxLittleSpace  )
+                                       {
+                                               pxSocket->u.xTCP.bits.bLowWater = pdTRUE_UNSIGNED;
+                                               pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
+
+                                               /* bLowWater was reached, send the changed window size. */
+                                               pxSocket->u.xTCP.usTimeout = 1u;
+                                               xSendEventToIPTask( eTCPTimerEvent );
+                                       }
+                               }
+
+                               /* New incoming data is available, wake up the user.   User's
+                               semaphores will be set just before the IP-task goes asleep. */
+                               pxSocket->xEventBits |= eSOCKET_RECEIVE;
+
+                               #if ipconfigSUPPORT_SELECT_FUNCTION == 1
+                               {
+                                       if( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 )
+                                       {
+                                               pxSocket->xEventBits |= ( eSELECT_READ << SOCKET_EVENT_BIT_COUNT );
+                                       }
+                               }
+                               #endif
+                       }
+               }
+
+               return xResult;
+       }
+
+#endif /* ipconfigUSE_TCP */
+/*-----------------------------------------------------------*/
+
+#if( ipconfigUSE_TCP == 1 )
+
+       /* Function to get the remote address and IP port */
+       BaseType_t FreeRTOS_GetRemoteAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress )
+       {
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+       BaseType_t xResult;
+
+               if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
+               {
+                       xResult = -pdFREERTOS_ERRNO_EINVAL;
+               }
+               else
+               {
+                       /* BSD style sockets communicate IP and port addresses in network
+                       byte order.
+
+                       IP address of remote machine. */
+                       pxAddress->sin_addr = FreeRTOS_htonl ( pxSocket->u.xTCP.ulRemoteIP );
+
+                       /* Port on remote machine. */
+                       pxAddress->sin_port = FreeRTOS_htons ( pxSocket->u.xTCP.usRemotePort );
+
+                       xResult = ( BaseType_t ) sizeof( ( *pxAddress ) );
+               }
+
+               return xResult;
+       }
+
+#endif /* ipconfigUSE_TCP */
+
+/*-----------------------------------------------------------*/
+
+#if( ipconfigUSE_TCP == 1 )
+
+       /* Returns the number of bytes that may be added to txStream */
+       BaseType_t FreeRTOS_maywrite( Socket_t xSocket )
+       {
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+       BaseType_t xResult;
+
+               if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
+               {
+                       xResult = -pdFREERTOS_ERRNO_EINVAL;
+               }
+               else if( pxSocket->u.xTCP.ucTCPState != eESTABLISHED )
+               {
+                       if( ( pxSocket->u.xTCP.ucTCPState < eCONNECT_SYN ) || ( pxSocket->u.xTCP.ucTCPState > eESTABLISHED ) )
+                       {
+                               xResult = -1;
+                       }
+                       else
+                       {
+                               xResult = 0;
+                       }
+               }
+               else if( pxSocket->u.xTCP.txStream == NULL )
+               {
+                       xResult = ( BaseType_t ) pxSocket->u.xTCP.uxTxStreamSize;
+               }
+               else
+               {
+                       xResult = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
+               }
+
+               return xResult;
+       }
+
+#endif /* ipconfigUSE_TCP */
+/*-----------------------------------------------------------*/
+
+#if( ipconfigUSE_TCP ==1 )
+
+       BaseType_t FreeRTOS_tx_space( Socket_t xSocket )
+       {
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+       BaseType_t xReturn;
+
+               if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
+               {
+                       xReturn = -pdFREERTOS_ERRNO_EINVAL;
+               }
+               else
+               {
+                       if( pxSocket->u.xTCP.txStream != NULL )
+                       {
+                               xReturn = ( BaseType_t ) uxStreamBufferGetSpace ( pxSocket->u.xTCP.txStream );
+                       }
+                       else
+                       {
+                               xReturn = ( BaseType_t ) pxSocket->u.xTCP.uxTxStreamSize;
+                       }
+               }
+
+               return xReturn;
+       }
+
+#endif /* ipconfigUSE_TCP */
+/*-----------------------------------------------------------*/
+
+#if( ipconfigUSE_TCP == 1 )
+
+       BaseType_t FreeRTOS_tx_size( Socket_t xSocket )
+       {
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+       BaseType_t xReturn;
+
+               if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
+               {
+                       xReturn = -pdFREERTOS_ERRNO_EINVAL;
+               }
+               else
+               {
+                       if( pxSocket->u.xTCP.txStream != NULL )
+                       {
+                               xReturn = ( BaseType_t ) uxStreamBufferGetSize ( pxSocket->u.xTCP.txStream );
+                       }
+                       else
+                       {
+                               xReturn = 0;
+                       }
+               }
+
+               return xReturn;
+       }
+
+#endif /* ipconfigUSE_TCP */
+/*-----------------------------------------------------------*/
+
+#if( ipconfigUSE_TCP == 1 )
+
+       /* Returns pdTRUE if TCP socket is connected. */
+       BaseType_t FreeRTOS_issocketconnected( Socket_t xSocket )
+       {
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+       BaseType_t xReturn = pdFALSE;
+
+               if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
+               {
+                       xReturn = -pdFREERTOS_ERRNO_EINVAL;
+               }
+               else
+               {
+                       if( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED )
+                       {
+                               if( pxSocket->u.xTCP.ucTCPState < eCLOSE_WAIT )
+                               {
+                                       xReturn = pdTRUE;
+                               }
+                       }
+               }
+
+               return xReturn;
+       }
+
+#endif /* ipconfigUSE_TCP */
+/*-----------------------------------------------------------*/
+
+#if( ipconfigUSE_TCP == 1 )
+
+       /* returns the actual size of MSS being used */
+       BaseType_t FreeRTOS_mss( Socket_t xSocket )
+       {
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+       BaseType_t xReturn;
+
+               if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
+               {
+                       xReturn = -pdFREERTOS_ERRNO_EINVAL;
+               }
+               else
+               {
+                       /* usCurMSS is declared as uint16_t to save space.  FreeRTOS_mss()
+                       will often be used in signed native-size expressions cast it to
+                       BaseType_t. */
+                       xReturn = ( BaseType_t ) ( pxSocket->u.xTCP.usCurMSS );
+               }
+
+               return xReturn;
+       }
+
+#endif /* ipconfigUSE_TCP */
+/*-----------------------------------------------------------*/
+
+#if( ipconfigUSE_TCP == 1 )
+
+       /* HT: for internal use only: return the connection status */
+       BaseType_t FreeRTOS_connstatus( Socket_t xSocket )
+       {
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+       BaseType_t xReturn;
+
+               if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
+               {
+                       xReturn = -pdFREERTOS_ERRNO_EINVAL;
+               }
+               else
+               {
+                       /* Cast it to BaseType_t */
+                       xReturn = ( BaseType_t ) ( pxSocket->u.xTCP.ucTCPState );
+               }
+
+               return xReturn;
+       }
+
+#endif /* ipconfigUSE_TCP */
+/*-----------------------------------------------------------*/
+
+#if( ipconfigUSE_TCP == 1 )
+
+       /*
+        * Returns the number of bytes which can be read.
+        */
+       BaseType_t FreeRTOS_rx_size( Socket_t xSocket )
+       {
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+       BaseType_t xReturn;
+
+               if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
+               {
+                       xReturn = -pdFREERTOS_ERRNO_EINVAL;
+               }
+               else if( pxSocket->u.xTCP.rxStream != NULL )
+               {
+                       xReturn = ( BaseType_t ) uxStreamBufferGetSize( pxSocket->u.xTCP.rxStream );
+               }
+               else
+               {
+                       xReturn = 0;
+               }
+
+               return xReturn;
+       }
+
+#endif /* ipconfigUSE_TCP */
+/*-----------------------------------------------------------*/
+
+#if( ipconfigUSE_TCP == 1 )
+
+       void FreeRTOS_netstat( void )
+       {
+       IPStackEvent_t xAskEvent;
+
+               /* Ask the IP-task to call vTCPNetStat()
+                * to avoid accessing xBoundTCPSocketsList
+                */
+               xAskEvent.eEventType = eTCPNetStat;
+               xAskEvent.pvData = ( void * ) NULL;
+               xSendEventStructToIPTask( &xAskEvent, 1000u );
+       }
+
+#endif /* ipconfigUSE_TCP */
+/*-----------------------------------------------------------*/
+
+#if( ( ipconfigHAS_PRINTF != 0 ) && ( ipconfigUSE_TCP == 1 ) )
+
+       void vTCPNetStat( void )
+       {
+       /* Show a simple listing of all created sockets and their connections */
+       ListItem_t *pxIterator;
+       BaseType_t count = 0;
+
+               if( listLIST_IS_INITIALISED( &xBoundTCPSocketsList ) == pdFALSE )
+               {
+                       FreeRTOS_printf( ( "PLUS-TCP not initialized\n" ) );
+               }
+               else
+               {
+                       FreeRTOS_printf( ( "Prot Port IP-Remote    : Port  R/T Status      Alive  tmout Child\n" ) );
+                       for( pxIterator  = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );
+                                pxIterator != ( ListItem_t * ) listGET_END_MARKER( &xBoundTCPSocketsList );
+                                pxIterator  = ( ListItem_t * ) listGET_NEXT( pxIterator ) )
+                       {
+                               FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
+                               #if( ipconfigTCP_KEEP_ALIVE == 1 )
+                                       TickType_t age = xTaskGetTickCount() - pxSocket->u.xTCP.xLastAliveTime;
+                               #else
+                                       TickType_t age = 0u;
+                               #endif
+                               #if( ipconfigUSE_CALLBACKS == 1 )
+                                       void *pxHandleReceive = (void*)pxSocket->u.xTCP.pxHandleReceive;
+                               #else
+                                       void *pxHandleReceive = (void*)NULL;
+                               #endif
+                               char ucChildText[16] = "";
+                               if (pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN)
+                               {
+                                       const int32_t copied_len = snprintf( ucChildText, sizeof( ucChildText ), " %d/%d",
+                                               ( int ) pxSocket->u.xTCP.usChildCount,
+                                               ( int ) pxSocket->u.xTCP.usBacklog);
+                                       /* These should never evaluate to false since the buffers are both shorter than 5-6 characters (<=65535) */
+                                       configASSERT( copied_len >= 0 );
+                                       configASSERT( copied_len < sizeof( ucChildText ) );
+                               }
+                               FreeRTOS_printf( ( "TCP %5d %-16lxip:%5d %d/%d %-13.13s %6lu %6u%s\n",
+                                       pxSocket->usLocalPort,          /* Local port on this machine */
+                                       pxSocket->u.xTCP.ulRemoteIP,    /* IP address of remote machine */
+                                       pxSocket->u.xTCP.usRemotePort,  /* Port on remote machine */
+                                       pxSocket->u.xTCP.rxStream != NULL,
+                                       pxSocket->u.xTCP.txStream != NULL,
+                                       FreeRTOS_GetTCPStateName( pxSocket->u.xTCP.ucTCPState ),
+                                       (age > 999999 ? 999999 : age), /* Format 'age' for printing */
+                                       pxSocket->u.xTCP.usTimeout,
+                                       ucChildText ) );
+                                       /* Remove compiler warnings if FreeRTOS_debug_printf() is not defined. */
+                                       ( void ) pxHandleReceive;
+                               count++;
+                       }
+
+                       for( pxIterator  = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundUDPSocketsList );
+                                pxIterator != ( ListItem_t * ) listGET_END_MARKER( &xBoundUDPSocketsList );
+                                pxIterator  = ( ListItem_t * ) listGET_NEXT( pxIterator ) )
+                       {
+                               /* Local port on this machine */
+                               FreeRTOS_printf( ( "UDP Port %5u\n",
+                                       FreeRTOS_ntohs( listGET_LIST_ITEM_VALUE( pxIterator ) ) ) );
+                               count++;
+                       }
+
+                       FreeRTOS_printf( ( "FreeRTOS_netstat: %lu sockets %lu < %lu < %d buffers free\n",
+                               count,
+                               uxGetMinimumFreeNetworkBuffers( ),
+                               uxGetNumberOfFreeNetworkBuffers( ),
+                               ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ) );
+               }
+       }
+
+#endif /* ( ( ipconfigHAS_PRINTF != 0 ) && ( ipconfigUSE_TCP == 1 ) ) */
+/*-----------------------------------------------------------*/
+
+#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
+
+       void vSocketSelect( SocketSelect_t *pxSocketSet )
+       {
+       BaseType_t xRound;
+       EventBits_t xSocketBits, xBitsToClear;
+       #if ipconfigUSE_TCP == 1
+               BaseType_t xLastRound = 1;
+       #else
+               BaseType_t xLastRound = 0;
+       #endif
+
+               /* These flags will be switched on after checking the socket status. */
+               EventBits_t xGroupBits = 0;
+               pxSocketSet->pxSocket = NULL;
+
+               for( xRound = 0; xRound <= xLastRound; xRound++ )
+               {
+                       const ListItem_t *pxIterator;
+                       const MiniListItem_t *pxEnd;
+                       if( xRound == 0 )
+                       {
+                               pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundUDPSocketsList );
+                       }
+               #if ipconfigUSE_TCP == 1
+                       else
+                       {
+                               pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );
+                       }
+               #endif /* ipconfigUSE_TCP == 1 */
+                       for( pxIterator = ( const ListItem_t * ) ( listGET_NEXT( pxEnd ) );
+                                pxIterator != ( const ListItem_t * ) pxEnd;
+                                pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
+                       {
+                               FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
+                               if( pxSocket->pxSocketSet != pxSocketSet )
+                               {
+                                       /* Socket does not belong to this select group. */
+                                       continue;
+                               }
+                               xSocketBits = 0;
+
+                               #if( ipconfigUSE_TCP == 1 )
+                                       if( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP )
+                                       {
+                                               /* Check if the socket has already been accepted by the
+                                               owner.  If not, it is useless to return it from a
+                                               select(). */
+                                               BaseType_t bAccepted = pdFALSE;
+
+                                               if( pxSocket->u.xTCP.bits.bPassQueued == pdFALSE_UNSIGNED )
+                                               {
+                                                       if( pxSocket->u.xTCP.bits.bPassAccept == pdFALSE_UNSIGNED )
+                                                       {
+                                                               bAccepted = pdTRUE;
+                                                       }
+                                               }
+
+                                               /* Is the set owner interested in READ events? */
+                                               if( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 )
+                                               {
+                                                       if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN )
+                                                       {
+                                                               if( ( pxSocket->u.xTCP.pxPeerSocket != NULL ) && ( pxSocket->u.xTCP.pxPeerSocket->u.xTCP.bits.bPassAccept != 0 ) )
+                                                               {
+                                                                       xSocketBits |= eSELECT_READ;
+                                                               }
+                                                       }
+                                                       else if( ( pxSocket->u.xTCP.bits.bReuseSocket != pdFALSE_UNSIGNED ) && ( pxSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED ) )
+                                                       {
+                                                               /* This socket has the re-use flag. After connecting it turns into
+                                                               aconnected socket. Set the READ event, so that accept() will be called. */
+                                                               xSocketBits |= eSELECT_READ;
+                                                       }
+                                                       else if( ( bAccepted != 0 ) && ( FreeRTOS_recvcount( pxSocket ) > 0 ) )
+                                                       {
+                                                               xSocketBits |= eSELECT_READ;
+                                                       }
+                                               }
+                                               /* Is the set owner interested in EXCEPTION events? */
+                                               if( ( pxSocket->xSelectBits & eSELECT_EXCEPT ) != 0 )
+                                               {
+                                                       if( ( pxSocket->u.xTCP.ucTCPState == eCLOSE_WAIT ) || ( pxSocket->u.xTCP.ucTCPState == eCLOSED ) )
+                                                       {
+                                                               xSocketBits |= eSELECT_EXCEPT;
+                                                       }
+                                               }
+
+                                               /* Is the set owner interested in WRITE events? */
+                                               if( ( pxSocket->xSelectBits & eSELECT_WRITE ) != 0 )
+                                               {
+                                                       BaseType_t bMatch = pdFALSE;
+
+                                                       if( bAccepted != 0 )
+                                                       {
+                                                               if( FreeRTOS_tx_space( pxSocket ) > 0 )
+                                                               {
+                                                                       bMatch = pdTRUE;
+                                                               }
+                                                       }
+
+                                                       if( bMatch == pdFALSE )
+                                                       {
+                                                               if( ( pxSocket->u.xTCP.bits.bConnPrepared != pdFALSE_UNSIGNED ) &&
+                                                                       ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) &&
+                                                                       ( pxSocket->u.xTCP.bits.bConnPassed == pdFALSE_UNSIGNED ) )
+                                                               {
+                                                                       pxSocket->u.xTCP.bits.bConnPassed = pdTRUE_UNSIGNED;
+                                                                       bMatch = pdTRUE;
+                                                               }
+                                                       }
+
+                                                       if( bMatch != pdFALSE )
+                                                       {
+                                                               xSocketBits |= eSELECT_WRITE;
+                                                       }
+                                               }
+                                       }
+                                       else
+                               #endif /* ipconfigUSE_TCP == 1 */
+                               {
+                                       /* Select events for UDP are simpler. */
+                                       if( ( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 ) &&
+                                               ( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) > 0U ) )
+                                       {
+                                               xSocketBits |= eSELECT_READ;
+                                       }
+                                       /* The WRITE and EXCEPT bits are not used for UDP */
+                               }       /* if( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP ) */
+
+                               /* Each socket keeps its own event flags, which are looked-up
+                               by FreeRTOS_FD_ISSSET() */
+                               pxSocket->xSocketBits = xSocketBits;
+
+                               /* The ORed value will be used to set the bits in the event
+                               group. */
+                               xGroupBits |= xSocketBits;
+
+                       }       /* for( pxIterator ... ) */
+               }       /* for( xRound = 0; xRound <= xLastRound; xRound++ ) */
+
+               xBitsToClear = xEventGroupGetBits( pxSocketSet->xSelectGroup );
+
+               /* Now set the necessary bits. */
+               xBitsToClear = ( xBitsToClear & ~xGroupBits ) & eSELECT_ALL;
+
+               #if( ipconfigSUPPORT_SIGNALS != 0 )
+               {
+                       /* Maybe the socketset was signalled, but don't
+                       clear the 'eSELECT_INTR' bit here, as it will be used
+                       and cleared in FreeRTOS_select(). */
+                       xBitsToClear &= ( EventBits_t ) ~eSELECT_INTR;
+               }
+               #endif /* ipconfigSUPPORT_SIGNALS */
+
+               if( xBitsToClear != 0 )
+               {
+                       xEventGroupClearBits( pxSocketSet->xSelectGroup, xBitsToClear );
+               }
+
+               /* Now include eSELECT_CALL_IP to wakeup the caller. */
+               xEventGroupSetBits( pxSocketSet->xSelectGroup, xGroupBits | eSELECT_CALL_IP );
+       }
+
+#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
+/*-----------------------------------------------------------*/
+
+#if( ipconfigSUPPORT_SIGNALS != 0 )
+
+       /* Send a signal to the task which reads from this socket. */
+       BaseType_t FreeRTOS_SignalSocket( Socket_t xSocket )
+       {
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+       BaseType_t xReturn;
+
+               if( pxSocket == NULL )
+               {
+                       xReturn = -pdFREERTOS_ERRNO_EINVAL;
+               }
+               else
+       #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
+               if( ( pxSocket->pxSocketSet != NULL ) && ( pxSocket->pxSocketSet->xSelectGroup != NULL ) )
+               {
+                       xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, eSELECT_INTR );
+                       xReturn = 0;
+               }
+               else
+       #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
+               if( pxSocket->xEventGroup != NULL )
+               {
+                       xEventGroupSetBits( pxSocket->xEventGroup, eSOCKET_INTR );
+                       xReturn = 0;
+               }
+               else
+               {
+                       xReturn = -pdFREERTOS_ERRNO_EINVAL;
+               }
+
+               return xReturn;
+       }
+
+#endif /* ipconfigSUPPORT_SIGNALS */
+/*-----------------------------------------------------------*/
+
+#if( ipconfigSUPPORT_SIGNALS != 0 )
+
+       /* Send a signal to the task which reads from this socket (FromISR version). */
+       BaseType_t FreeRTOS_SignalSocketFromISR( Socket_t xSocket, BaseType_t *pxHigherPriorityTaskWoken )
+       {
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+       BaseType_t xReturn;
+       IPStackEvent_t xEvent;
+       extern QueueHandle_t xNetworkEventQueue;
+
+               configASSERT( pxSocket != NULL );
+               configASSERT( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP );
+               configASSERT( pxSocket->xEventGroup );
+
+               xEvent.eEventType = eSocketSignalEvent;
+               xEvent.pvData = ( void * )pxSocket;
+
+               /* The IP-task will call FreeRTOS_SignalSocket for this socket. */
+               xReturn = xQueueSendToBackFromISR( xNetworkEventQueue, &xEvent, pxHigherPriorityTaskWoken );
+
+               return xReturn;
+       }
+
+#endif /* ipconfigSUPPORT_SIGNALS */
+/*-----------------------------------------------------------*/