2 * FreeRTOS+TCP V2.0.7
\r
3 * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\r
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
\r
6 * this software and associated documentation files (the "Software"), to deal in
\r
7 * the Software without restriction, including without limitation the rights to
\r
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
\r
9 * the Software, and to permit persons to whom the Software is furnished to do so,
\r
10 * subject to the following conditions:
\r
12 * The above copyright notice and this permission notice shall be included in all
\r
13 * copies or substantial portions of the Software.
\r
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
\r
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
\r
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
\r
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
22 * http://aws.amazon.com/freertos
\r
23 * http://www.FreeRTOS.org
\r
26 /* Standard includes. */
\r
30 /* FreeRTOS includes. */
\r
31 #include "FreeRTOS.h"
\r
36 /* FreeRTOS+TCP includes. */
\r
37 #include "FreeRTOS_UDP_IP.h"
\r
38 #include "FreeRTOS_IP.h"
\r
39 #include "FreeRTOS_Sockets.h"
\r
40 #include "FreeRTOS_IP_Private.h"
\r
41 #include "FreeRTOS_DNS.h"
\r
42 #include "NetworkBufferManagement.h"
\r
44 /* The ItemValue of the sockets xBoundSocketListItem member holds the socket's
\r
46 #define socketSET_SOCKET_PORT( pxSocket, usPort ) listSET_LIST_ITEM_VALUE( ( &( ( pxSocket )->xBoundSocketListItem ) ), ( usPort ) )
\r
47 #define socketGET_SOCKET_PORT( pxSocket ) listGET_LIST_ITEM_VALUE( ( &( ( pxSocket )->xBoundSocketListItem ) ) )
\r
49 /* Test if a socket it bound which means it is either included in
\r
50 xBoundUDPSocketsList or xBoundTCPSocketsList */
\r
51 #define socketSOCKET_IS_BOUND( pxSocket ) ( listLIST_ITEM_CONTAINER( & ( pxSocket )->xBoundSocketListItem ) != NULL )
\r
53 /* If FreeRTOS_sendto() is called on a socket that is not bound to a port
\r
54 number then, depending on the FreeRTOSIPConfig.h settings, it might be that a
\r
55 port number is automatically generated for the socket. Automatically generated
\r
56 port numbers will be between socketAUTO_PORT_ALLOCATION_START_NUMBER and
\r
59 Per https://tools.ietf.org/html/rfc6056, "the dynamic ports consist of the range
\r
60 49152-65535. However, ephemeral port selection algorithms should use the whole
\r
61 range 1024-65535" excluding those already in use (inbound or outbound). */
\r
62 #if !defined( socketAUTO_PORT_ALLOCATION_START_NUMBER )
\r
63 #define socketAUTO_PORT_ALLOCATION_START_NUMBER ( ( uint16_t ) 0x0400 )
\r
66 #define socketAUTO_PORT_ALLOCATION_MAX_NUMBER ( ( uint16_t ) 0xffff )
\r
68 /* The number of octets that make up an IP address. */
\r
69 #define socketMAX_IP_ADDRESS_OCTETS 4u
\r
71 /* A block time of 0 simply means "don't block". */
\r
72 #define socketDONT_BLOCK ( ( TickType_t ) 0 )
\r
74 #if( ( ipconfigUSE_TCP == 1 ) && !defined( ipTCP_TIMER_PERIOD_MS ) )
\r
75 #define ipTCP_TIMER_PERIOD_MS ( 1000 )
\r
78 /* The next private port number to use when binding a client socket is stored in
\r
79 the usNextPortToUse[] array - which has either 1 or two indexes depending on
\r
80 whether TCP is being supported. */
\r
81 #if( ipconfigUSE_TCP == 1 )
\r
82 #define socketPROTOCOL_COUNT 2
\r
84 #define socketPROTOCOL_COUNT 1
\r
87 /* Indexes into the usNextPortToUse[] array for UDP and TCP sockets
\r
89 #define socketNEXT_UDP_PORT_NUMBER_INDEX 0
\r
90 #define socketNEXT_TCP_PORT_NUMBER_INDEX 1
\r
93 /*-----------------------------------------------------------*/
\r
96 * Allocate the next port number from the private allocation range.
\r
97 * TCP and UDP each have their own series of port numbers
\r
98 * ulProtocol is either ipPROTOCOL_UDP or ipPROTOCOL_TCP
\r
100 static uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol );
\r
103 * Return the list item from within pxList that has an item value of
\r
104 * xWantedItemValue. If there is no such list item return NULL.
\r
106 static const ListItem_t * pxListFindListItemWithValue( const List_t *pxList, TickType_t xWantedItemValue );
\r
109 * Return pdTRUE only if pxSocket is valid and bound, as far as can be
\r
112 static BaseType_t prvValidSocket( FreeRTOS_Socket_t *pxSocket, BaseType_t xProtocol, BaseType_t xIsBound );
\r
115 * Before creating a socket, check the validity of the parameters used
\r
116 * and find the size of the socket space, which is different for UDP and TCP
\r
118 static BaseType_t prvDetermineSocketSize( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol, size_t *pxSocketSize );
\r
120 #if( ipconfigUSE_TCP == 1 )
\r
122 * Create a txStream or a rxStream, depending on the parameter 'xIsInputStream'
\r
124 static StreamBuffer_t *prvTCPCreateStream (FreeRTOS_Socket_t *pxSocket, BaseType_t xIsInputStream );
\r
125 #endif /* ipconfigUSE_TCP == 1 */
\r
127 #if( ipconfigUSE_TCP == 1 )
\r
129 * Called from FreeRTOS_send(): some checks which will be done before
\r
130 * sending a TCP packed.
\r
132 static int32_t prvTCPSendCheck( FreeRTOS_Socket_t *pxSocket, size_t xDataLength );
\r
133 #endif /* ipconfigUSE_TCP */
\r
135 #if( ipconfigUSE_TCP == 1 )
\r
137 * When a child socket gets closed, make sure to update the child-count of the parent
\r
139 static void prvTCPSetSocketCount( FreeRTOS_Socket_t *pxSocketToDelete );
\r
140 #endif /* ipconfigUSE_TCP == 1 */
\r
142 #if( ipconfigUSE_TCP == 1 )
\r
144 * Called from FreeRTOS_connect(): make some checks and if allowed, send a
\r
145 * message to the IP-task to start connecting to a remote socket
\r
147 static BaseType_t prvTCPConnectStart( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr *pxAddress );
\r
148 #endif /* ipconfigUSE_TCP */
\r
150 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
152 /* Executed by the IP-task, it will check all sockets belonging to a set */
\r
153 static FreeRTOS_Socket_t *prvFindSelectedSocket( SocketSelect_t *pxSocketSet );
\r
155 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
156 /*-----------------------------------------------------------*/
\r
158 /* The list that contains mappings between sockets and port numbers. Accesses
\r
159 to this list must be protected by critical sections of one kind or another. */
\r
160 List_t xBoundUDPSocketsList;
\r
162 #if ipconfigUSE_TCP == 1
\r
163 List_t xBoundTCPSocketsList;
\r
164 #endif /* ipconfigUSE_TCP == 1 */
\r
166 /*-----------------------------------------------------------*/
\r
168 static BaseType_t prvValidSocket( FreeRTOS_Socket_t *pxSocket, BaseType_t xProtocol, BaseType_t xIsBound )
\r
170 BaseType_t xReturn = pdTRUE;
\r
172 if( ( pxSocket == NULL ) || ( pxSocket == FREERTOS_INVALID_SOCKET ) )
\r
176 else if( ( xIsBound != pdFALSE ) && ( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE ) )
\r
178 /* The caller expects the socket to be bound, but it isn't. */
\r
181 else if( pxSocket->ucProtocol != ( uint8_t ) xProtocol )
\r
183 /* Socket has a wrong type (UDP != TCP). */
\r
189 /*-----------------------------------------------------------*/
\r
191 BaseType_t vNetworkSocketsInit( void )
\r
193 vListInitialise( &xBoundUDPSocketsList );
\r
195 #if( ipconfigUSE_TCP == 1 )
\r
197 vListInitialise( &xBoundTCPSocketsList );
\r
199 #endif /* ipconfigUSE_TCP == 1 */
\r
203 /*-----------------------------------------------------------*/
\r
205 static BaseType_t prvDetermineSocketSize( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol, size_t *pxSocketSize )
\r
207 BaseType_t xReturn = pdPASS;
\r
208 FreeRTOS_Socket_t *pxSocket;
\r
210 /* Asserts must not appear before it has been determined that the network
\r
211 task is ready - otherwise the asserts will fail. */
\r
212 if( xIPIsNetworkTaskReady() == pdFALSE )
\r
218 /* Only Ethernet is currently supported. */
\r
219 configASSERT( xDomain == FREERTOS_AF_INET );
\r
221 /* Check if the UDP socket-list has been initialised. */
\r
222 configASSERT( listLIST_IS_INITIALISED( &xBoundUDPSocketsList ) );
\r
223 #if( ipconfigUSE_TCP == 1 )
\r
225 /* Check if the TCP socket-list has been initialised. */
\r
226 configASSERT( listLIST_IS_INITIALISED( &xBoundTCPSocketsList ) );
\r
228 #endif /* ipconfigUSE_TCP == 1 */
\r
230 if( xProtocol == FREERTOS_IPPROTO_UDP )
\r
232 if( xType != FREERTOS_SOCK_DGRAM )
\r
235 configASSERT( xReturn );
\r
237 /* In case a UDP socket is created, do not allocate space for TCP data. */
\r
238 *pxSocketSize = ( sizeof( *pxSocket ) - sizeof( pxSocket->u ) ) + sizeof( pxSocket->u.xUDP );
\r
240 #if( ipconfigUSE_TCP == 1 )
\r
241 else if( xProtocol == FREERTOS_IPPROTO_TCP )
\r
243 if( xType != FREERTOS_SOCK_STREAM )
\r
246 configASSERT( xReturn );
\r
249 *pxSocketSize = ( sizeof( *pxSocket ) - sizeof( pxSocket->u ) ) + sizeof( pxSocket->u.xTCP );
\r
251 #endif /* ipconfigUSE_TCP == 1 */
\r
255 configASSERT( xReturn );
\r
258 /* In case configASSERT() is not used */
\r
262 /*-----------------------------------------------------------*/
\r
264 /* FreeRTOS_socket() allocates and initiates a socket */
\r
265 Socket_t FreeRTOS_socket( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol )
\r
267 FreeRTOS_Socket_t *pxSocket;
\r
268 size_t uxSocketSize;
\r
269 EventGroupHandle_t xEventGroup;
\r
272 if( prvDetermineSocketSize( xDomain, xType, xProtocol, &uxSocketSize ) == pdFAIL )
\r
274 xReturn = FREERTOS_INVALID_SOCKET;
\r
278 /* Allocate the structure that will hold the socket information. The
\r
279 size depends on the type of socket: UDP sockets need less space. A
\r
280 define 'pvPortMallocSocket' will used to allocate the necessary space.
\r
281 By default it points to the FreeRTOS function 'pvPortMalloc()'. */
\r
282 pxSocket = ( FreeRTOS_Socket_t * ) pvPortMallocSocket( uxSocketSize );
\r
284 if( pxSocket == NULL )
\r
286 pxSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
\r
287 iptraceFAILED_TO_CREATE_SOCKET();
\r
289 else if( ( xEventGroup = xEventGroupCreate() ) == NULL )
\r
291 vPortFreeSocket( pxSocket );
\r
292 pxSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
\r
293 iptraceFAILED_TO_CREATE_EVENT_GROUP();
\r
297 /* Clear the entire space to avoid nulling individual entries */
\r
298 memset( pxSocket, '\0', uxSocketSize );
\r
300 pxSocket->xEventGroup = xEventGroup;
\r
302 /* Initialise the socket's members. The semaphore will be created
\r
303 if the socket is bound to an address, for now the pointer to the
\r
304 semaphore is just set to NULL to show it has not been created. */
\r
305 if( xProtocol == FREERTOS_IPPROTO_UDP )
\r
307 vListInitialise( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
\r
309 #if( ipconfigUDP_MAX_RX_PACKETS > 0 )
\r
311 pxSocket->u.xUDP.uxMaxPackets = ( UBaseType_t ) ipconfigUDP_MAX_RX_PACKETS;
\r
313 #endif /* ipconfigUDP_MAX_RX_PACKETS > 0 */
\r
316 vListInitialiseItem( &( pxSocket->xBoundSocketListItem ) );
\r
317 listSET_LIST_ITEM_OWNER( &( pxSocket->xBoundSocketListItem ), ( void * ) pxSocket );
\r
319 pxSocket->xReceiveBlockTime = ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME;
\r
320 pxSocket->xSendBlockTime = ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME;
\r
321 pxSocket->ucSocketOptions = ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT;
\r
322 pxSocket->ucProtocol = ( uint8_t ) xProtocol; /* protocol: UDP or TCP */
\r
324 #if( ipconfigUSE_TCP == 1 )
\r
326 if( xProtocol == FREERTOS_IPPROTO_TCP )
\r
328 /* StreamSize is expressed in number of bytes */
\r
329 /* Round up buffer sizes to nearest multiple of MSS */
\r
330 pxSocket->u.xTCP.usInitMSS = pxSocket->u.xTCP.usCurMSS = ipconfigTCP_MSS;
\r
331 pxSocket->u.xTCP.uxRxStreamSize = ( size_t ) ipconfigTCP_RX_BUFFER_LENGTH;
\r
332 pxSocket->u.xTCP.uxTxStreamSize = ( size_t ) FreeRTOS_round_up( ipconfigTCP_TX_BUFFER_LENGTH, ipconfigTCP_MSS );
\r
333 /* Use half of the buffer size of the TCP windows */
\r
334 #if ( ipconfigUSE_TCP_WIN == 1 )
\r
336 pxSocket->u.xTCP.uxRxWinSize = FreeRTOS_max_uint32( 1UL, ( uint32_t ) ( pxSocket->u.xTCP.uxRxStreamSize / 2 ) / ipconfigTCP_MSS );
\r
337 pxSocket->u.xTCP.uxTxWinSize = FreeRTOS_max_uint32( 1UL, ( uint32_t ) ( pxSocket->u.xTCP.uxTxStreamSize / 2 ) / ipconfigTCP_MSS );
\r
341 pxSocket->u.xTCP.uxRxWinSize = 1u;
\r
342 pxSocket->u.xTCP.uxTxWinSize = 1u;
\r
345 /* The above values are just defaults, and can be overridden by
\r
346 calling FreeRTOS_setsockopt(). No buffers will be allocated until a
\r
347 socket is connected and data is exchanged. */
\r
350 #endif /* ipconfigUSE_TCP == 1 */
\r
353 xReturn = ( Socket_t ) pxSocket;
\r
356 /* Remove compiler warnings in the case the configASSERT() is not defined. */
\r
361 /*-----------------------------------------------------------*/
\r
363 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
365 SocketSet_t FreeRTOS_CreateSocketSet( void )
\r
367 SocketSelect_t *pxSocketSet;
\r
369 pxSocketSet = ( SocketSelect_t * ) pvPortMalloc( sizeof( *pxSocketSet ) );
\r
371 if( pxSocketSet != NULL )
\r
373 memset( pxSocketSet, '\0', sizeof( *pxSocketSet ) );
\r
374 pxSocketSet->xSelectGroup = xEventGroupCreate();
\r
376 if( pxSocketSet->xSelectGroup == NULL )
\r
378 vPortFree( ( void* ) pxSocketSet );
\r
379 pxSocketSet = NULL;
\r
383 return ( SocketSet_t * ) pxSocketSet;
\r
386 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
387 /*-----------------------------------------------------------*/
\r
389 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
391 void FreeRTOS_DeleteSocketSet( SocketSet_t xSocketSet )
\r
393 SocketSelect_t *pxSocketSet = ( SocketSelect_t*) xSocketSet;
\r
395 vEventGroupDelete( pxSocketSet->xSelectGroup );
\r
396 vPortFree( ( void* ) pxSocketSet );
\r
399 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
400 /*-----------------------------------------------------------*/
\r
402 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
404 /* Add a socket to a set */
\r
405 void FreeRTOS_FD_SET( Socket_t xSocket, SocketSet_t xSocketSet, EventBits_t xSelectBits )
\r
407 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
408 SocketSelect_t *pxSocketSet = ( SocketSelect_t * ) xSocketSet;
\r
410 configASSERT( pxSocket != NULL );
\r
411 configASSERT( xSocketSet != NULL );
\r
413 /* Make sure we're not adding bits which are reserved for internal use,
\r
414 such as eSELECT_CALL_IP */
\r
415 pxSocket->xSelectBits |= ( xSelectBits & eSELECT_ALL );
\r
417 if( ( pxSocket->xSelectBits & eSELECT_ALL ) != 0 )
\r
419 /* Adding a socket to a socket set. */
\r
420 pxSocket->pxSocketSet = ( SocketSelect_t * ) xSocketSet;
\r
422 /* Now have the IP-task call vSocketSelect() to see if the set contains
\r
423 any sockets which are 'ready' and set the proper bits.
\r
424 By setting 'bApiCalled = false', vSocketSelect() knows that it was
\r
425 not called from a user API */
\r
426 pxSocketSet->bApiCalled = pdFALSE;
\r
427 prvFindSelectedSocket( pxSocketSet );
\r
431 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
432 /*-----------------------------------------------------------*/
\r
434 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
435 /* Clear select bits for a socket
\r
436 If the mask becomes 0, remove the socket from the set */
\r
437 void FreeRTOS_FD_CLR( Socket_t xSocket, SocketSet_t xSocketSet, EventBits_t xSelectBits )
\r
439 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
441 configASSERT( pxSocket != NULL );
\r
442 configASSERT( xSocketSet != NULL );
\r
444 pxSocket->xSelectBits &= ~( xSelectBits & eSELECT_ALL );
\r
445 if( ( pxSocket->xSelectBits & eSELECT_ALL ) != 0 )
\r
447 pxSocket->pxSocketSet = ( SocketSelect_t *)xSocketSet;
\r
451 /* disconnect it from the socket set */
\r
452 pxSocket->pxSocketSet = ( SocketSelect_t *)NULL;
\r
456 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
457 /*-----------------------------------------------------------*/
\r
460 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
462 /* Test if a socket belongs to a socket-set */
\r
463 EventBits_t FreeRTOS_FD_ISSET( Socket_t xSocket, SocketSet_t xSocketSet )
\r
465 EventBits_t xReturn;
\r
466 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
468 configASSERT( pxSocket != NULL );
\r
469 configASSERT( xSocketSet != NULL );
\r
471 if( xSocketSet == ( SocketSet_t ) pxSocket->pxSocketSet )
\r
473 /* Make sure we're not adding bits which are reserved for internal
\r
475 xReturn = pxSocket->xSocketBits & eSELECT_ALL;
\r
485 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
486 /*-----------------------------------------------------------*/
\r
488 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
490 /* The select() statement: wait for an event to occur on any of the sockets
\r
491 included in a socket set */
\r
492 BaseType_t FreeRTOS_select( SocketSet_t xSocketSet, TickType_t xBlockTimeTicks )
\r
494 TimeOut_t xTimeOut;
\r
495 TickType_t xRemainingTime;
\r
496 SocketSelect_t *pxSocketSet = ( SocketSelect_t*) xSocketSet;
\r
497 BaseType_t xResult;
\r
499 configASSERT( xSocketSet != NULL );
\r
501 /* Only in the first round, check for non-blocking */
\r
502 xRemainingTime = xBlockTimeTicks;
\r
504 /* Fetch the current time */
\r
505 vTaskSetTimeOutState( &xTimeOut );
\r
509 /* Find a socket which might have triggered the bit
\r
510 This function might return immediately or block for a limited time */
\r
511 xResult = ( BaseType_t ) xEventGroupWaitBits( pxSocketSet->xSelectGroup, eSELECT_ALL, pdFALSE, pdFALSE, xRemainingTime );
\r
513 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
515 if( ( xResult & eSELECT_INTR ) != 0u )
\r
517 xEventGroupClearBits( pxSocketSet->xSelectGroup, eSELECT_INTR );
\r
518 FreeRTOS_debug_printf( ( "FreeRTOS_select: interrupted\n" ) );
\r
522 #endif /* ipconfigSUPPORT_SIGNALS */
\r
524 /* Have the IP-task find the socket which had an event */
\r
525 pxSocketSet->bApiCalled = pdTRUE;
\r
526 prvFindSelectedSocket( pxSocketSet );
\r
528 xResult = ( BaseType_t ) xEventGroupGetBits( pxSocketSet->xSelectGroup );
\r
535 /* Has the timeout been reached? */
\r
536 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
\r
545 #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
\r
546 /*-----------------------------------------------------------*/
\r
548 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
550 /* Send a message to the IP-task to have it check all sockets belonging to
\r
552 static FreeRTOS_Socket_t *prvFindSelectedSocket( SocketSelect_t *pxSocketSet )
\r
554 IPStackEvent_t xSelectEvent;
\r
555 FreeRTOS_Socket_t *xReturn;
\r
557 xSelectEvent.eEventType = eSocketSelectEvent;
\r
558 xSelectEvent.pvData = ( void * ) pxSocketSet;
\r
560 /* while the IP-task works on the request, the API will block on
\r
561 'eSELECT_CALL_IP'. So clear it first. */
\r
562 xEventGroupClearBits( pxSocketSet->xSelectGroup, eSELECT_CALL_IP );
\r
564 /* Now send the socket select event */
\r
565 if( xSendEventStructToIPTask( &xSelectEvent, ( TickType_t ) portMAX_DELAY ) == pdFAIL )
\r
567 /* Oops, we failed to wake-up the IP task. No use to wait for it. */
\r
568 FreeRTOS_debug_printf( ( "prvFindSelectedSocket: failed\n" ) );
\r
573 /* As soon as the IP-task is ready, it will set 'eSELECT_CALL_IP' to
\r
574 wakeup the calling API */
\r
575 xEventGroupWaitBits( pxSocketSet->xSelectGroup, eSELECT_CALL_IP, pdTRUE, pdFALSE, portMAX_DELAY );
\r
577 /* Return 'pxSocket' which is set by the IP-task */
\r
578 xReturn = pxSocketSet->pxSocket;
\r
584 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
585 /*-----------------------------------------------------------*/
\r
588 * FreeRTOS_recvfrom: receive data from a bound socket
\r
589 * In this library, the function can only be used with connectionsless sockets
\r
592 int32_t FreeRTOS_recvfrom( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags, struct freertos_sockaddr *pxSourceAddress, socklen_t *pxSourceAddressLength )
\r
594 BaseType_t lPacketCount = 0;
\r
595 NetworkBufferDescriptor_t *pxNetworkBuffer;
\r
596 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
597 TickType_t xRemainingTime = ( TickType_t ) 0; /* Obsolete assignment, but some compilers output a warning if its not done. */
\r
598 BaseType_t xTimed = pdFALSE;
\r
599 TimeOut_t xTimeOut;
\r
601 EventBits_t xEventBits = ( EventBits_t ) 0;
\r
603 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_UDP, pdTRUE ) == pdFALSE )
\r
605 return -pdFREERTOS_ERRNO_EINVAL;
\r
608 lPacketCount = ( BaseType_t ) listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
\r
610 /* The function prototype is designed to maintain the expected Berkeley
\r
611 sockets standard, but this implementation does not use all the parameters. */
\r
612 ( void ) pxSourceAddressLength;
\r
614 while( lPacketCount == 0 )
\r
616 if( xTimed == pdFALSE )
\r
618 /* Check to see if the socket is non blocking on the first
\r
620 xRemainingTime = pxSocket->xReceiveBlockTime;
\r
622 if( xRemainingTime == ( TickType_t ) 0 )
\r
624 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
626 /* Just check for the interrupt flag. */
\r
627 xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_INTR,
\r
628 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, socketDONT_BLOCK );
\r
630 #endif /* ipconfigSUPPORT_SIGNALS */
\r
634 if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
\r
639 /* To ensure this part only executes once. */
\r
642 /* Fetch the current time. */
\r
643 vTaskSetTimeOutState( &xTimeOut );
\r
646 /* Wait for arrival of data. While waiting, the IP-task may set the
\r
647 'eSOCKET_RECEIVE' bit in 'xEventGroup', if it receives data for this
\r
648 socket, thus unblocking this API call. */
\r
649 xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_RECEIVE | eSOCKET_INTR,
\r
650 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
652 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
654 if( ( xEventBits & eSOCKET_INTR ) != 0 )
\r
656 if( ( xEventBits & eSOCKET_RECEIVE ) != 0 )
\r
658 /* Shouldn't have cleared the eSOCKET_RECEIVE flag. */
\r
659 xEventGroupSetBits( pxSocket->xEventGroup, eSOCKET_RECEIVE );
\r
666 ( void ) xEventBits;
\r
668 #endif /* ipconfigSUPPORT_SIGNALS */
\r
670 lPacketCount = ( BaseType_t ) listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
\r
672 if( lPacketCount != 0 )
\r
677 /* Has the timeout been reached ? */
\r
678 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) )
\r
682 } /* while( lPacketCount == 0 ) */
\r
684 if( lPacketCount != 0 )
\r
686 taskENTER_CRITICAL();
\r
688 /* The owner of the list item is the network buffer. */
\r
689 pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
\r
691 if( ( xFlags & FREERTOS_MSG_PEEK ) == 0 )
\r
693 /* Remove the network buffer from the list of buffers waiting to
\r
694 be processed by the socket. */
\r
695 uxListRemove( &( pxNetworkBuffer->xBufferListItem ) );
\r
698 taskEXIT_CRITICAL();
\r
700 /* The returned value is the data length, which may have been capped to
\r
701 the receive buffer size. */
\r
702 lReturn = ( int32_t ) pxNetworkBuffer->xDataLength;
\r
704 if( pxSourceAddress != NULL )
\r
706 pxSourceAddress->sin_port = pxNetworkBuffer->usPort;
\r
707 pxSourceAddress->sin_addr = pxNetworkBuffer->ulIPAddress;
\r
710 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
\r
712 /* The zero copy flag is not set. Truncate the length if it won't
\r
713 fit in the provided buffer. */
\r
714 if( lReturn > ( int32_t ) xBufferLength )
\r
716 iptraceRECVFROM_DISCARDING_BYTES( ( xBufferLength - lReturn ) );
\r
717 lReturn = ( int32_t )xBufferLength;
\r
720 /* Copy the received data into the provided buffer, then release the
\r
722 memcpy( pvBuffer, ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ), ( size_t )lReturn );
\r
724 if( ( xFlags & FREERTOS_MSG_PEEK ) == 0 )
\r
726 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
\r
731 /* The zero copy flag was set. pvBuffer is not a buffer into which
\r
732 the received data can be copied, but a pointer that must be set to
\r
733 point to the buffer in which the received data has already been
\r
735 *( ( void** ) pvBuffer ) = ( void * ) ( &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ) );
\r
739 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
740 else if( ( xEventBits & eSOCKET_INTR ) != 0 )
\r
742 lReturn = -pdFREERTOS_ERRNO_EINTR;
\r
743 iptraceRECVFROM_INTERRUPTED();
\r
745 #endif /* ipconfigSUPPORT_SIGNALS */
\r
748 lReturn = -pdFREERTOS_ERRNO_EWOULDBLOCK;
\r
749 iptraceRECVFROM_TIMEOUT();
\r
754 /*-----------------------------------------------------------*/
\r
756 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
758 NetworkBufferDescriptor_t *pxNetworkBuffer;
\r
759 IPStackEvent_t xStackTxEvent = { eStackTxEvent, NULL };
\r
760 TimeOut_t xTimeOut;
\r
761 TickType_t xTicksToWait;
\r
762 int32_t lReturn = 0;
\r
763 FreeRTOS_Socket_t *pxSocket;
\r
765 pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
767 /* The function prototype is designed to maintain the expected Berkeley
\r
768 sockets standard, but this implementation does not use all the
\r
770 ( void ) xDestinationAddressLength;
\r
771 configASSERT( pvBuffer );
\r
773 if( xTotalDataLength <= ( size_t ) ipMAX_UDP_PAYLOAD_LENGTH )
\r
775 /* If the socket is not already bound to an address, bind it now.
\r
776 Passing NULL as the address parameter tells FreeRTOS_bind() to select
\r
777 the address to bind to. */
\r
778 if( ( socketSOCKET_IS_BOUND( pxSocket ) != pdFALSE ) ||
\r
779 ( FreeRTOS_bind( xSocket, NULL, 0u ) == 0 ) )
\r
781 xTicksToWait = pxSocket->xSendBlockTime;
\r
783 #if( ipconfigUSE_CALLBACKS != 0 )
\r
785 if( xIsCallingFromIPTask() != pdFALSE )
\r
787 /* If this send function is called from within a call-back
\r
788 handler it may not block, otherwise chances would be big to
\r
789 get a deadlock: the IP-task waiting for itself. */
\r
790 xTicksToWait = ( TickType_t )0;
\r
793 #endif /* ipconfigUSE_CALLBACKS */
\r
795 if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
\r
797 xTicksToWait = ( TickType_t ) 0;
\r
800 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
\r
802 /* Zero copy is not set, so obtain a network buffer into
\r
803 which the payload will be copied. */
\r
804 vTaskSetTimeOutState( &xTimeOut );
\r
806 /* Block until a buffer becomes available, or until a
\r
807 timeout has been reached */
\r
808 pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( xTotalDataLength + sizeof( UDPPacket_t ), xTicksToWait );
\r
810 if( pxNetworkBuffer != NULL )
\r
812 memcpy( ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ), ( void * ) pvBuffer, xTotalDataLength );
\r
814 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdTRUE )
\r
816 /* The entire block time has been used up. */
\r
817 xTicksToWait = ( TickType_t ) 0;
\r
823 /* When zero copy is used, pvBuffer is a pointer to the
\r
824 payload of a buffer that has already been obtained from the
\r
825 stack. Obtain the network buffer pointer from the buffer. */
\r
826 pxNetworkBuffer = pxUDPPayloadBuffer_to_NetworkBuffer( (void*)pvBuffer );
\r
829 if( pxNetworkBuffer != NULL )
\r
831 pxNetworkBuffer->xDataLength = xTotalDataLength;
\r
832 pxNetworkBuffer->usPort = pxDestinationAddress->sin_port;
\r
833 pxNetworkBuffer->usBoundPort = ( uint16_t ) socketGET_SOCKET_PORT( pxSocket );
\r
834 pxNetworkBuffer->ulIPAddress = pxDestinationAddress->sin_addr;
\r
836 /* The socket options are passed to the IP layer in the
\r
837 space that will eventually get used by the Ethernet header. */
\r
838 pxNetworkBuffer->pucEthernetBuffer[ ipSOCKET_OPTIONS_OFFSET ] = pxSocket->ucSocketOptions;
\r
840 /* Tell the networking task that the packet needs sending. */
\r
841 xStackTxEvent.pvData = pxNetworkBuffer;
\r
843 /* Ask the IP-task to send this packet */
\r
844 if( xSendEventStructToIPTask( &xStackTxEvent, xTicksToWait ) == pdPASS )
\r
846 /* The packet was successfully sent to the IP task. */
\r
847 lReturn = ( int32_t ) xTotalDataLength;
\r
848 #if( ipconfigUSE_CALLBACKS == 1 )
\r
850 if( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xUDP.pxHandleSent ) )
\r
852 pxSocket->u.xUDP.pxHandleSent( (Socket_t *)pxSocket, xTotalDataLength );
\r
855 #endif /* ipconfigUSE_CALLBACKS */
\r
859 /* If the buffer was allocated in this function, release
\r
861 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
\r
863 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
\r
865 iptraceSTACK_TX_EVENT_LOST( ipSTACK_TX_EVENT );
\r
870 /* If errno was available, errno would be set to
\r
871 FREERTOS_ENOPKTS. As it is, the function must return the
\r
872 number of transmitted bytes, so the calling function knows
\r
873 how much data was actually sent. */
\r
874 iptraceNO_BUFFER_FOR_SENDTO();
\r
879 iptraceSENDTO_SOCKET_NOT_BOUND();
\r
884 /* The data is longer than the available buffer space. */
\r
885 iptraceSENDTO_DATA_TOO_LONG();
\r
890 /*-----------------------------------------------------------*/
\r
893 * FreeRTOS_bind() : binds a sockt to a local port number. If port 0 is
\r
894 * provided, a system provided port number will be assigned. This function can
\r
895 * be used for both UDP and TCP sockets. The actual binding will be performed
\r
896 * by the IP-task to avoid mutual access to the bound-socket-lists
\r
897 * (xBoundUDPSocketsList or xBoundTCPSocketsList).
\r
899 BaseType_t FreeRTOS_bind( Socket_t xSocket, struct freertos_sockaddr * pxAddress, socklen_t xAddressLength )
\r
901 IPStackEvent_t xBindEvent;
\r
902 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
903 BaseType_t xReturn = 0;
\r
905 ( void ) xAddressLength;
\r
907 if( ( pxSocket == NULL ) || ( pxSocket == FREERTOS_INVALID_SOCKET ) )
\r
909 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
911 /* Once a socket is bound to a port, it can not be bound to a different
\r
913 else if( socketSOCKET_IS_BOUND( pxSocket) != pdFALSE )
\r
915 /* The socket is already bound. */
\r
916 FreeRTOS_debug_printf( ( "vSocketBind: Socket already bound to %d\n", pxSocket->usLocalPort ) );
\r
917 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
921 /* Prepare a messages to the IP-task in order to perform the binding.
\r
922 The desired port number will be passed in usLocalPort. */
\r
923 xBindEvent.eEventType = eSocketBindEvent;
\r
924 xBindEvent.pvData = ( void * ) xSocket;
\r
925 if( pxAddress != NULL )
\r
927 pxSocket->usLocalPort = FreeRTOS_ntohs( pxAddress->sin_port );
\r
931 /* Caller wants to bind to a random port number. */
\r
932 pxSocket->usLocalPort = 0u;
\r
935 /* portMAX_DELAY is used as a the time-out parameter, as binding *must*
\r
936 succeed before the socket can be used. _RB_ The use of an infinite
\r
937 block time needs be changed as it could result in the task hanging. */
\r
938 if( xSendEventStructToIPTask( &xBindEvent, ( TickType_t ) portMAX_DELAY ) == pdFAIL )
\r
940 /* Failed to wake-up the IP-task, no use to wait for it */
\r
941 FreeRTOS_debug_printf( ( "FreeRTOS_bind: send event failed\n" ) );
\r
942 xReturn = -pdFREERTOS_ERRNO_ECANCELED;
\r
946 /* The IP-task will set the 'eSOCKET_BOUND' bit when it has done its
\r
948 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_BOUND, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, portMAX_DELAY );
\r
949 if( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE )
\r
951 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
960 * vSocketBind(): internal version of bind() that should not be called directly.
\r
961 * 'xInternal' is used for TCP sockets only: it allows to have several
\r
962 * (connected) child sockets bound to the same server port.
\r
964 BaseType_t vSocketBind( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr * pxAddress, size_t uxAddressLength, BaseType_t xInternal )
\r
966 BaseType_t xReturn = 0; /* In Berkeley sockets, 0 means pass for bind(). */
\r
967 List_t *pxSocketList;
\r
968 #if( ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 )
\r
969 struct freertos_sockaddr xAddress;
\r
970 #endif /* ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND */
\r
972 #if( ipconfigUSE_TCP == 1 )
\r
973 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
975 pxSocketList = &xBoundTCPSocketsList;
\r
978 #endif /* ipconfigUSE_TCP == 1 */
\r
980 pxSocketList = &xBoundUDPSocketsList;
\r
983 /* The function prototype is designed to maintain the expected Berkeley
\r
984 sockets standard, but this implementation does not use all the parameters. */
\r
985 ( void ) uxAddressLength;
\r
987 configASSERT( pxSocket );
\r
988 configASSERT( pxSocket != FREERTOS_INVALID_SOCKET );
\r
990 #if( ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 )
\r
992 /* pxAddress will be NULL if sendto() was called on a socket without the
\r
993 socket being bound to an address. In this case, automatically allocate
\r
994 an address and port to the socket. */
\r
995 if( pxAddress == NULL )
\r
997 pxAddress = &xAddress;
\r
998 /* Put the port to zero to be assigned later. */
\r
999 pxAddress->sin_port = 0u;
\r
1002 #endif /* ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 */
\r
1004 /* Sockets must be bound before calling FreeRTOS_sendto() if
\r
1005 ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is not set to 1. */
\r
1006 configASSERT( pxAddress );
\r
1008 if( pxAddress != NULL )
\r
1010 if( pxAddress->sin_port == 0u )
\r
1012 pxAddress->sin_port = prvGetPrivatePortNumber( ( BaseType_t )pxSocket->ucProtocol );
\r
1013 if( 0 == pxAddress->sin_port )
\r
1015 return -pdFREERTOS_ERRNO_EADDRNOTAVAIL;
\r
1019 /* If vSocketBind() is called from the API FreeRTOS_bind() it has been
\r
1020 confirmed that the socket was not yet bound to a port. If it is called
\r
1021 from the IP-task, no such check is necessary. */
\r
1023 /* Check to ensure the port is not already in use. If the bind is
\r
1024 called internally, a port MAY be used by more than one socket. */
\r
1025 if( ( ( xInternal == pdFALSE ) || ( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP ) ) &&
\r
1026 ( pxListFindListItemWithValue( pxSocketList, ( TickType_t ) pxAddress->sin_port ) != NULL ) )
\r
1028 FreeRTOS_debug_printf( ( "vSocketBind: %sP port %d in use\n",
\r
1029 pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP ? "TC" : "UD",
\r
1030 FreeRTOS_ntohs( pxAddress->sin_port ) ) );
\r
1031 xReturn = -pdFREERTOS_ERRNO_EADDRINUSE;
\r
1035 /* Allocate the port number to the socket.
\r
1036 This macro will set 'xBoundSocketListItem->xItemValue' */
\r
1037 socketSET_SOCKET_PORT( pxSocket, pxAddress->sin_port );
\r
1039 /* And also store it in a socket field 'usLocalPort' in host-byte-order,
\r
1040 mostly used for logging and debugging purposes */
\r
1041 pxSocket->usLocalPort = FreeRTOS_ntohs( pxAddress->sin_port );
\r
1043 /* Add the socket to the list of bound ports. */
\r
1045 /* If the network driver can iterate through 'xBoundUDPSocketsList',
\r
1046 by calling xPortHasUDPSocket() then the IP-task must temporarily
\r
1047 suspend the scheduler to keep the list in a consistent state. */
\r
1048 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1050 vTaskSuspendAll();
\r
1052 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1054 /* Add the socket to 'xBoundUDPSocketsList' or 'xBoundTCPSocketsList' */
\r
1055 vListInsertEnd( pxSocketList, &( pxSocket->xBoundSocketListItem ) );
\r
1057 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1061 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1067 xReturn = -pdFREERTOS_ERRNO_EADDRNOTAVAIL;
\r
1068 FreeRTOS_debug_printf( ( "vSocketBind: Socket no addr\n" ) );
\r
1071 if( xReturn != 0 )
\r
1073 iptraceBIND_FAILED( xSocket, ( FreeRTOS_ntohs( pxAddress->sin_port ) ) );
\r
1078 /*-----------------------------------------------------------*/
\r
1081 * Close a socket and free the allocated space
\r
1082 * In case of a TCP socket: the connection will not be closed automatically
\r
1083 * Subsequent messages for the closed socket will be responded to with a RST
\r
1084 * The IP-task will actually close the socket, after receiving a 'eSocketCloseEvent' message
\r
1086 BaseType_t FreeRTOS_closesocket( Socket_t xSocket )
\r
1088 BaseType_t xResult;
\r
1089 #if( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 )
\r
1090 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * )xSocket;
\r
1092 IPStackEvent_t xCloseEvent;
\r
1093 xCloseEvent.eEventType = eSocketCloseEvent;
\r
1094 xCloseEvent.pvData = ( void * ) xSocket;
\r
1096 if( ( xSocket == NULL ) || ( xSocket == FREERTOS_INVALID_SOCKET ) )
\r
1102 #if( ( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 ) )
\r
1104 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1106 /* Make sure that IP-task won't call the user callback's anymore */
\r
1107 pxSocket->u.xTCP.pxHandleConnected = NULL;
\r
1108 pxSocket->u.xTCP.pxHandleReceive = NULL;
\r
1109 pxSocket->u.xTCP.pxHandleSent = NULL;
\r
1112 #endif /* ( ( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 ) ) */
\r
1114 /* Let the IP task close the socket to keep it synchronised with the
\r
1115 packet handling. */
\r
1117 /* Note when changing the time-out value below, it must be checked who is calling
\r
1118 this function. If it is called by the IP-task, a deadlock could occur.
\r
1119 The IP-task would only call it in case of a user call-back */
\r
1120 if( xSendEventStructToIPTask( &xCloseEvent, ( TickType_t ) 0 ) == pdFAIL )
\r
1122 FreeRTOS_debug_printf( ( "FreeRTOS_closesocket: failed\n" ) );
\r
1134 /* This is the internal version of FreeRTOS_closesocket()
\r
1135 * It will be called by the IPtask only to avoid problems with synchronicity
\r
1137 void *vSocketClose( FreeRTOS_Socket_t *pxSocket )
\r
1139 NetworkBufferDescriptor_t *pxNetworkBuffer;
\r
1141 #if( ipconfigUSE_TCP == 1 )
\r
1143 /* For TCP: clean up a little more. */
\r
1144 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1146 #if( ipconfigUSE_TCP_WIN == 1 )
\r
1148 if( pxSocket->u.xTCP.pxAckMessage != NULL )
\r
1150 vReleaseNetworkBufferAndDescriptor( pxSocket->u.xTCP.pxAckMessage );
\r
1152 /* Free the resources which were claimed by the tcpWin member */
\r
1153 vTCPWindowDestroy( &pxSocket->u.xTCP.xTCPWindow );
\r
1155 #endif /* ipconfigUSE_TCP_WIN */
\r
1157 /* Free the input and output streams */
\r
1158 if( pxSocket->u.xTCP.rxStream != NULL )
\r
1160 vPortFreeLarge( pxSocket->u.xTCP.rxStream );
\r
1163 if( pxSocket->u.xTCP.txStream != NULL )
\r
1165 vPortFreeLarge( pxSocket->u.xTCP.txStream );
\r
1168 /* In case this is a child socket, make sure the child-count of the
\r
1169 parent socket is decreased. */
\r
1170 prvTCPSetSocketCount( pxSocket );
\r
1173 #endif /* ipconfigUSE_TCP == 1 */
\r
1175 /* Socket must be unbound first, to ensure no more packets are queued on
\r
1177 if( socketSOCKET_IS_BOUND( pxSocket ) != pdFALSE )
\r
1179 /* If the network driver can iterate through 'xBoundUDPSocketsList',
\r
1180 by calling xPortHasUDPSocket(), then the IP-task must temporarily
\r
1181 suspend the scheduler to keep the list in a consistent state. */
\r
1182 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1184 vTaskSuspendAll();
\r
1186 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1188 uxListRemove( &( pxSocket->xBoundSocketListItem ) );
\r
1190 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1194 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1197 /* Now the socket is not bound the list of waiting packets can be
\r
1199 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_UDP )
\r
1201 while( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) > 0U )
\r
1203 pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
\r
1204 uxListRemove( &( pxNetworkBuffer->xBufferListItem ) );
\r
1205 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
\r
1209 if( pxSocket->xEventGroup )
\r
1211 vEventGroupDelete( pxSocket->xEventGroup );
\r
1214 #if( ipconfigUSE_TCP == 1 ) && ( ipconfigHAS_DEBUG_PRINTF != 0 )
\r
1216 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1218 FreeRTOS_debug_printf( ( "FreeRTOS_closesocket[%u to %lxip:%u]: buffers %lu socks %lu\n",
\r
1219 pxSocket->usLocalPort,
\r
1220 pxSocket->u.xTCP.ulRemoteIP,
\r
1221 pxSocket->u.xTCP.usRemotePort,
\r
1222 uxGetNumberOfFreeNetworkBuffers(),
\r
1223 listCURRENT_LIST_LENGTH( &xBoundTCPSocketsList ) ) );
\r
1226 #endif /* ( ipconfigUSE_TCP == 1 ) && ( ipconfigHAS_DEBUG_PRINTF != 0 ) */
\r
1228 /* Anf finally, after all resources have been freed, free the socket space */
\r
1229 vPortFreeSocket( pxSocket );
\r
1234 /*-----------------------------------------------------------*/
\r
1236 #if ipconfigUSE_TCP == 1
\r
1239 * When a child socket gets closed, make sure to update the child-count of the
\r
1240 * parent. When a listening parent socket is closed, make sure no child-sockets
\r
1241 * keep a pointer to it.
\r
1243 static void prvTCPSetSocketCount( FreeRTOS_Socket_t *pxSocketToDelete )
\r
1245 const ListItem_t *pxIterator;
\r
1246 const MiniListItem_t *pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );
\r
1247 FreeRTOS_Socket_t *pxOtherSocket;
\r
1248 uint16_t usLocalPort = pxSocketToDelete->usLocalPort;
\r
1250 for( pxIterator = ( const ListItem_t * ) listGET_NEXT( pxEnd );
\r
1251 pxIterator != ( const ListItem_t * ) pxEnd;
\r
1252 pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
1254 pxOtherSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
\r
1255 if( ( pxOtherSocket->u.xTCP.ucTCPState == eTCP_LISTEN ) &&
\r
1256 ( pxOtherSocket->usLocalPort == usLocalPort ) &&
\r
1257 ( pxOtherSocket->u.xTCP.usChildCount ) )
\r
1259 pxOtherSocket->u.xTCP.usChildCount--;
\r
1260 FreeRTOS_debug_printf( ( "Lost: Socket %u now has %u / %u child%s\n",
\r
1261 pxOtherSocket->usLocalPort,
\r
1262 pxOtherSocket->u.xTCP.usChildCount,
\r
1263 pxOtherSocket->u.xTCP.usBacklog,
\r
1264 pxOtherSocket->u.xTCP.usChildCount == 1u ? "" : "ren" ) );
\r
1270 #endif /* ipconfigUSE_TCP == 1 */
\r
1272 /*-----------------------------------------------------------*/
\r
1274 BaseType_t FreeRTOS_setsockopt( Socket_t xSocket, int32_t lLevel, int32_t lOptionName, const void *pvOptionValue, size_t xOptionLength )
\r
1276 /* The standard Berkeley function returns 0 for success. */
\r
1277 BaseType_t xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
1278 BaseType_t lOptionValue;
\r
1279 FreeRTOS_Socket_t *pxSocket;
\r
1281 pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
1283 /* The function prototype is designed to maintain the expected Berkeley
\r
1284 sockets standard, but this implementation does not use all the parameters. */
\r
1286 ( void ) xOptionLength;
\r
1288 configASSERT( xSocket );
\r
1290 switch( lOptionName )
\r
1292 case FREERTOS_SO_RCVTIMEO :
\r
1293 /* Receive time out. */
\r
1294 pxSocket->xReceiveBlockTime = *( ( TickType_t * ) pvOptionValue );
\r
1298 case FREERTOS_SO_SNDTIMEO :
\r
1299 pxSocket->xSendBlockTime = *( ( TickType_t * ) pvOptionValue );
\r
1300 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_UDP )
\r
1302 /* The send time out is capped for the reason stated in the
\r
1303 comments where ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS is defined
\r
1304 in FreeRTOSIPConfig.h (assuming an official configuration file
\r
1306 if( pxSocket->xSendBlockTime > ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS )
\r
1308 pxSocket->xSendBlockTime = ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS;
\r
1313 /* For TCP socket, it isn't necessary to limit the blocking time
\r
1314 because the FreeRTOS_send() function does not wait for a network
\r
1315 buffer to become available. */
\r
1319 #if( ipconfigUDP_MAX_RX_PACKETS > 0 )
\r
1320 case FREERTOS_SO_UDP_MAX_RX_PACKETS:
\r
1321 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_UDP )
\r
1323 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1325 pxSocket->u.xUDP.uxMaxPackets = *( ( UBaseType_t * ) pvOptionValue );
\r
1328 #endif /* ipconfigUDP_MAX_RX_PACKETS */
\r
1330 case FREERTOS_SO_UDPCKSUM_OUT :
\r
1331 /* Turn calculating of the UDP checksum on/off for this socket. */
\r
1332 lOptionValue = ( BaseType_t ) pvOptionValue;
\r
1334 if( lOptionValue == 0 )
\r
1336 pxSocket->ucSocketOptions &= ( uint8_t ) ~FREERTOS_SO_UDPCKSUM_OUT;
\r
1340 pxSocket->ucSocketOptions |= ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT;
\r
1345 #if( ipconfigUSE_CALLBACKS == 1 )
\r
1346 #if( ipconfigUSE_TCP == 1 )
\r
1347 case FREERTOS_SO_TCP_CONN_HANDLER: /* Set a callback for (dis)connection events */
\r
1348 case FREERTOS_SO_TCP_RECV_HANDLER: /* Install a callback for receiving TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
\r
1349 case FREERTOS_SO_TCP_SENT_HANDLER: /* Install a callback for sending TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
\r
1350 #endif /* ipconfigUSE_TCP */
\r
1351 case FREERTOS_SO_UDP_RECV_HANDLER: /* Install a callback for receiving UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
\r
1352 case FREERTOS_SO_UDP_SENT_HANDLER: /* Install a callback for sending UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
\r
1354 #if( ipconfigUSE_TCP == 1 )
\r
1356 UBaseType_t uxProtocol;
\r
1357 if( ( lOptionName == FREERTOS_SO_UDP_RECV_HANDLER ) ||
\r
1358 ( lOptionName == FREERTOS_SO_UDP_SENT_HANDLER ) )
\r
1360 uxProtocol = ( UBaseType_t ) FREERTOS_IPPROTO_UDP;
\r
1364 uxProtocol = ( UBaseType_t ) FREERTOS_IPPROTO_TCP;
\r
1367 if( pxSocket->ucProtocol != ( uint8_t ) uxProtocol )
\r
1369 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1374 /* No need to check if the socket has the right
\r
1375 protocol, because only UDP socket can be created. */
\r
1377 #endif /* ipconfigUSE_TCP */
\r
1379 switch( lOptionName )
\r
1381 #if ipconfigUSE_TCP == 1
\r
1382 case FREERTOS_SO_TCP_CONN_HANDLER:
\r
1383 pxSocket->u.xTCP.pxHandleConnected = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPConnected;
\r
1385 case FREERTOS_SO_TCP_RECV_HANDLER:
\r
1386 pxSocket->u.xTCP.pxHandleReceive = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPReceive;
\r
1388 case FREERTOS_SO_TCP_SENT_HANDLER:
\r
1389 pxSocket->u.xTCP.pxHandleSent = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPSent;
\r
1391 #endif /* ipconfigUSE_TCP */
\r
1392 case FREERTOS_SO_UDP_RECV_HANDLER:
\r
1393 pxSocket->u.xUDP.pxHandleReceive = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnUDPReceive;
\r
1395 case FREERTOS_SO_UDP_SENT_HANDLER:
\r
1396 pxSocket->u.xUDP.pxHandleSent = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnUDPSent;
\r
1405 #endif /* ipconfigUSE_CALLBACKS */
\r
1407 #if( ipconfigUSE_TCP != 0 )
\r
1408 #if( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 )
\r
1409 /* Each socket has a semaphore on which the using task normally
\r
1411 case FREERTOS_SO_SET_SEMAPHORE:
\r
1413 pxSocket->pxUserSemaphore = *( ( SemaphoreHandle_t * ) pvOptionValue );
\r
1417 #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
\r
1419 #if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK != 0 )
\r
1420 case FREERTOS_SO_WAKEUP_CALLBACK:
\r
1422 /* Each socket can have a callback function that is executed
\r
1423 when there is an event the socket's owner might want to
\r
1425 pxSocket->pxUserWakeCallback = ( SocketWakeupCallback_t ) pvOptionValue;
\r
1429 #endif /* ipconfigSOCKET_HAS_USER_WAKE_CALLBACK */
\r
1431 case FREERTOS_SO_SNDBUF: /* Set the size of the send buffer, in units of MSS (TCP only) */
\r
1432 case FREERTOS_SO_RCVBUF: /* Set the size of the receive buffer, in units of MSS (TCP only) */
\r
1434 uint32_t ulNewValue;
\r
1436 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1438 FreeRTOS_debug_printf( ( "Set SO_%sBUF: wrong socket type\n",
\r
1439 ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );
\r
1440 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1443 if( ( ( lOptionName == FREERTOS_SO_SNDBUF ) && ( pxSocket->u.xTCP.txStream != NULL ) ) ||
\r
1444 ( ( lOptionName == FREERTOS_SO_RCVBUF ) && ( pxSocket->u.xTCP.rxStream != NULL ) ) )
\r
1446 FreeRTOS_debug_printf( ( "Set SO_%sBUF: buffer already created\n",
\r
1447 ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );
\r
1448 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1451 ulNewValue = *( ( uint32_t * ) pvOptionValue );
\r
1453 if( lOptionName == FREERTOS_SO_SNDBUF )
\r
1455 /* Round up to nearest MSS size */
\r
1456 ulNewValue = FreeRTOS_round_up( ulNewValue, ( uint32_t ) pxSocket->u.xTCP.usInitMSS );
\r
1457 pxSocket->u.xTCP.uxTxStreamSize = ulNewValue;
\r
1461 pxSocket->u.xTCP.uxRxStreamSize = ulNewValue;
\r
1467 case FREERTOS_SO_WIN_PROPERTIES: /* Set all buffer and window properties in one call, parameter is pointer to WinProperties_t */
\r
1469 WinProperties_t* pxProps;
\r
1471 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1473 FreeRTOS_debug_printf( ( "Set SO_WIN_PROP: wrong socket type\n" ) );
\r
1474 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1477 if( ( pxSocket->u.xTCP.txStream != NULL ) || ( pxSocket->u.xTCP.rxStream != NULL ) )
\r
1479 FreeRTOS_debug_printf( ( "Set SO_WIN_PROP: buffer already created\n" ) );
\r
1480 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1483 pxProps = ( ( WinProperties_t * ) pvOptionValue );
\r
1484 FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDBUF, &( pxProps->lTxBufSize ), sizeof( pxProps->lTxBufSize ) );
\r
1485 FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVBUF, &( pxProps->lRxBufSize ), sizeof( pxProps->lRxBufSize ) );
\r
1486 #if( ipconfigUSE_TCP_WIN == 1 )
\r
1488 pxSocket->u.xTCP.uxRxWinSize = ( uint32_t )pxProps->lRxWinSize; /* Fixed value: size of the TCP reception window */
\r
1489 pxSocket->u.xTCP.uxTxWinSize = ( uint32_t )pxProps->lTxWinSize; /* Fixed value: size of the TCP transmit window */
\r
1493 pxSocket->u.xTCP.uxRxWinSize = 1u;
\r
1494 pxSocket->u.xTCP.uxTxWinSize = 1u;
\r
1498 /* In case the socket has already initialised its tcpWin,
\r
1499 adapt the window size parameters */
\r
1500 if( pxSocket->u.xTCP.xTCPWindow.u.bits.bHasInit != pdFALSE_UNSIGNED )
\r
1502 pxSocket->u.xTCP.xTCPWindow.xSize.ulRxWindowLength = pxSocket->u.xTCP.uxRxWinSize * pxSocket->u.xTCP.usInitMSS;
\r
1503 pxSocket->u.xTCP.xTCPWindow.xSize.ulTxWindowLength = pxSocket->u.xTCP.uxTxWinSize * pxSocket->u.xTCP.usInitMSS;
\r
1510 case FREERTOS_SO_REUSE_LISTEN_SOCKET: /* If true, the server-socket will turn into a connected socket */
\r
1512 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1514 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1516 if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
\r
1518 pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE_UNSIGNED;
\r
1522 pxSocket->u.xTCP.bits.bReuseSocket = pdFALSE_UNSIGNED;
\r
1528 case FREERTOS_SO_CLOSE_AFTER_SEND: /* As soon as the last byte has been transmitted, finalise the connection */
\r
1530 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1532 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1535 if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
\r
1537 pxSocket->u.xTCP.bits.bCloseAfterSend = pdTRUE_UNSIGNED;
\r
1541 pxSocket->u.xTCP.bits.bCloseAfterSend = pdFALSE_UNSIGNED;
\r
1547 case FREERTOS_SO_SET_FULL_SIZE: /* Refuse to send packets smaller than MSS */
\r
1549 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1551 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1554 if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
\r
1556 pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdTRUE_UNSIGNED;
\r
1560 pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdFALSE_UNSIGNED;
\r
1563 if( ( pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize == pdFALSE_UNSIGNED ) &&
\r
1564 ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) &&
\r
1565 ( FreeRTOS_outstanding( pxSocket ) != 0 ) )
\r
1567 pxSocket->u.xTCP.usTimeout = 1u; /* to set/clear bSendFullSize */
\r
1568 xSendEventToIPTask( eTCPTimerEvent );
\r
1574 case FREERTOS_SO_STOP_RX: /* Refuse to receive more packts */
\r
1576 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1578 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1581 if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
\r
1583 pxSocket->u.xTCP.bits.bRxStopped = pdTRUE_UNSIGNED;
\r
1587 pxSocket->u.xTCP.bits.bRxStopped = pdFALSE_UNSIGNED;
\r
1590 pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
\r
1591 pxSocket->u.xTCP.usTimeout = 1u; /* to set/clear bRxStopped */
\r
1592 xSendEventToIPTask( eTCPTimerEvent );
\r
1597 #endif /* ipconfigUSE_TCP == 1 */
\r
1600 /* No other options are handled. */
\r
1601 xReturn = -pdFREERTOS_ERRNO_ENOPROTOOPT;
\r
1608 /*-----------------------------------------------------------*/
\r
1610 /* Find an available port number per https://tools.ietf.org/html/rfc6056. */
\r
1611 static uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol )
\r
1613 const uint16_t usEphemeralPortCount =
\r
1614 socketAUTO_PORT_ALLOCATION_MAX_NUMBER - socketAUTO_PORT_ALLOCATION_START_NUMBER + 1;
\r
1615 uint16_t usIterations = usEphemeralPortCount;
\r
1616 uint32_t ulRandomSeed = 0;
\r
1617 uint16_t usResult = 0;
\r
1618 BaseType_t xGotZeroOnce = pdFALSE;
\r
1619 const List_t *pxList;
\r
1621 #if ipconfigUSE_TCP == 1
\r
1622 if( xProtocol == ( BaseType_t ) FREERTOS_IPPROTO_TCP )
\r
1624 pxList = &xBoundTCPSocketsList;
\r
1629 pxList = &xBoundUDPSocketsList;
\r
1632 /* Avoid compiler warnings if ipconfigUSE_TCP is not defined. */
\r
1633 ( void ) xProtocol;
\r
1635 /* Find the next available port using the random seed as a starting
\r
1639 /* Generate a random seed. */
\r
1640 ulRandomSeed = ipconfigRAND32( );
\r
1642 /* Only proceed if the random number generator succeeded. */
\r
1643 if( 0 == ulRandomSeed )
\r
1645 if( pdFALSE == xGotZeroOnce )
\r
1647 xGotZeroOnce = pdTRUE;
\r
1656 /* Map the random to a candidate port. */
\r
1658 socketAUTO_PORT_ALLOCATION_START_NUMBER +
\r
1659 ( ( ( uint16_t )ulRandomSeed ) % usEphemeralPortCount );
\r
1661 /* Check if there's already an open socket with the same protocol
\r
1663 if( NULL == pxListFindListItemWithValue(
\r
1665 ( TickType_t )FreeRTOS_htons( usResult ) ) )
\r
1667 usResult = FreeRTOS_htons( usResult );
\r
1677 while( usIterations > 0 );
\r
1681 /*-----------------------------------------------------------*/
\r
1683 /* pxListFindListItemWithValue: find a list item in a bound socket list
\r
1684 'xWantedItemValue' refers to a port number */
\r
1685 static const ListItem_t * pxListFindListItemWithValue( const List_t *pxList, TickType_t xWantedItemValue )
\r
1687 const ListItem_t * pxResult = NULL;
\r
1689 if( ( xIPIsNetworkTaskReady() != pdFALSE ) && ( pxList != NULL ) )
\r
1691 const ListItem_t *pxIterator;
\r
1692 const MiniListItem_t *pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( pxList );
\r
1693 for( pxIterator = ( const ListItem_t * ) listGET_NEXT( pxEnd );
\r
1694 pxIterator != ( const ListItem_t * ) pxEnd;
\r
1695 pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
1697 if( listGET_LIST_ITEM_VALUE( pxIterator ) == xWantedItemValue )
\r
1699 pxResult = pxIterator;
\r
1708 /*-----------------------------------------------------------*/
\r
1710 FreeRTOS_Socket_t *pxUDPSocketLookup( UBaseType_t uxLocalPort )
\r
1712 const ListItem_t *pxListItem;
\r
1713 FreeRTOS_Socket_t *pxSocket = NULL;
\r
1715 /* Looking up a socket is quite simple, find a match with the local port.
\r
1717 See if there is a list item associated with the port number on the
\r
1718 list of bound sockets. */
\r
1719 pxListItem = pxListFindListItemWithValue( &xBoundUDPSocketsList, ( TickType_t ) uxLocalPort );
\r
1721 if( pxListItem != NULL )
\r
1723 /* The owner of the list item is the socket itself. */
\r
1724 pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxListItem );
\r
1725 configASSERT( pxSocket != NULL );
\r
1730 /*-----------------------------------------------------------*/
\r
1732 #if ipconfigINCLUDE_FULL_INET_ADDR == 1
\r
1734 uint32_t FreeRTOS_inet_addr( const char * pcIPAddress )
\r
1736 const uint32_t ulDecimalBase = 10u;
\r
1737 uint8_t ucOctet[ socketMAX_IP_ADDRESS_OCTETS ];
\r
1738 const char *pcPointerOnEntering;
\r
1739 uint32_t ulReturn = 0UL, ulValue;
\r
1740 UBaseType_t uxOctetNumber;
\r
1741 BaseType_t xResult = pdPASS;
\r
1743 for( uxOctetNumber = 0u; uxOctetNumber < socketMAX_IP_ADDRESS_OCTETS; uxOctetNumber++ )
\r
1746 pcPointerOnEntering = pcIPAddress;
\r
1748 while( ( *pcIPAddress >= '0' ) && ( *pcIPAddress <= '9' ) )
\r
1750 /* Move previous read characters into the next decimal
\r
1752 ulValue *= ulDecimalBase;
\r
1754 /* Add the binary value of the ascii character. */
\r
1755 ulValue += ( ( uint32_t ) ( *pcIPAddress ) - ( uint32_t ) '0' );
\r
1757 /* Move to next character in the string. */
\r
1761 /* Check characters were read. */
\r
1762 if( pcIPAddress == pcPointerOnEntering )
\r
1767 /* Check the value fits in an 8-bit number. */
\r
1768 if( ulValue > 0xffUL )
\r
1774 ucOctet[ uxOctetNumber ] = ( uint8_t ) ulValue;
\r
1776 /* Check the next character is as expected. */
\r
1777 if( uxOctetNumber < ( socketMAX_IP_ADDRESS_OCTETS - 1u ) )
\r
1779 if( *pcIPAddress != '.' )
\r
1785 /* Move past the dot. */
\r
1791 if( xResult == pdFAIL )
\r
1793 /* No point going on. */
\r
1798 if( *pcIPAddress != ( char ) 0 )
\r
1800 /* Expected the end of the string. */
\r
1804 if( uxOctetNumber != socketMAX_IP_ADDRESS_OCTETS )
\r
1806 /* Didn't read enough octets. */
\r
1810 if( xResult == pdPASS )
\r
1812 ulReturn = FreeRTOS_inet_addr_quick( ucOctet[ 0 ], ucOctet[ 1 ], ucOctet[ 2 ], ucOctet[ 3 ] );
\r
1818 #endif /* ipconfigINCLUDE_FULL_INET_ADDR */
\r
1820 /*-----------------------------------------------------------*/
\r
1822 /* Function to get the local address and IP port */
\r
1823 size_t FreeRTOS_GetLocalAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress )
\r
1825 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
1827 /* IP address of local machine. */
\r
1828 pxAddress->sin_addr = *ipLOCAL_IP_ADDRESS_POINTER;
\r
1830 /* Local port on this machine. */
\r
1831 pxAddress->sin_port = FreeRTOS_htons( pxSocket->usLocalPort );
\r
1833 return sizeof( *pxAddress );
\r
1836 /*-----------------------------------------------------------*/
\r
1838 void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
\r
1840 /* _HT_ must work this out, now vSocketWakeUpUser will be called for any important
\r
1841 * event or transition */
\r
1842 #if( ipconfigSOCKET_HAS_USER_SEMAPHORE == 1 )
\r
1844 if( pxSocket->pxUserSemaphore != NULL )
\r
1846 xSemaphoreGive( pxSocket->pxUserSemaphore );
\r
1849 #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
\r
1851 #if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK == 1 )
\r
1853 if( pxSocket->pxUserWakeCallback != NULL )
\r
1855 pxSocket->pxUserWakeCallback( pxSocket );
\r
1858 #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
\r
1860 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
1862 if( pxSocket->pxSocketSet != NULL )
\r
1864 EventBits_t xSelectBits = ( pxSocket->xEventBits >> SOCKET_EVENT_BIT_COUNT ) & eSELECT_ALL;
\r
1865 if( xSelectBits != 0ul )
\r
1867 pxSocket->xSocketBits |= xSelectBits;
\r
1868 xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, xSelectBits );
\r
1872 pxSocket->xEventBits &= eSOCKET_ALL;
\r
1874 #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
\r
1876 if( ( pxSocket->xEventGroup != NULL ) && ( pxSocket->xEventBits != 0u ) )
\r
1878 xEventGroupSetBits( pxSocket->xEventGroup, pxSocket->xEventBits );
\r
1881 pxSocket->xEventBits = 0ul;
\r
1884 /*-----------------------------------------------------------*/
\r
1886 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1888 /* This define makes it possible for network-card drivers to inspect
\r
1889 * UDP message and see if there is any UDP socket bound to a given port
\r
1891 * This is probably only usefull in systems with a minimum of RAM and
\r
1892 * when lots of anonymous broadcast messages come in
\r
1894 BaseType_t xPortHasUDPSocket( uint16_t usPortNr )
\r
1896 BaseType_t xFound = pdFALSE;
\r
1898 vTaskSuspendAll();
\r
1900 if( ( pxListFindListItemWithValue( &xBoundUDPSocketsList, ( TickType_t ) usPortNr ) != NULL ) )
\r
1910 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1912 /*-----------------------------------------------------------*/
\r
1914 #if( ipconfigUSE_TCP == 1 )
\r
1916 static BaseType_t bMayConnect( FreeRTOS_Socket_t *pxSocket );
\r
1917 static BaseType_t bMayConnect( FreeRTOS_Socket_t *pxSocket )
\r
1919 switch( pxSocket->u.xTCP.ucTCPState )
\r
1922 case eCLOSE_WAIT: return 0;
\r
1923 case eCONNECT_SYN: return -pdFREERTOS_ERRNO_EINPROGRESS;
\r
1924 default: return -pdFREERTOS_ERRNO_EAGAIN;
\r
1928 #endif /* ipconfigUSE_TCP */
\r
1929 /*-----------------------------------------------------------*/
\r
1931 #if( ipconfigUSE_TCP == 1 )
\r
1933 static BaseType_t prvTCPConnectStart( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr *pxAddress )
\r
1935 BaseType_t xResult = 0;
\r
1937 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdFALSE )
\r
1939 /* Not a valid socket or wrong type */
\r
1940 xResult = -pdFREERTOS_ERRNO_EBADF;
\r
1942 else if( FreeRTOS_issocketconnected( pxSocket ) > 0 )
\r
1944 /* The socket is already connected. */
\r
1945 xResult = -pdFREERTOS_ERRNO_EISCONN;
\r
1947 else if( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE )
\r
1949 /* Bind the socket to the port that the client task will send from.
\r
1950 Non-standard, so the error returned is that returned by bind(). */
\r
1951 xResult = FreeRTOS_bind( ( Socket_t ) pxSocket, NULL, 0u );
\r
1954 if( xResult == 0 )
\r
1956 /* Check if it makes any sense to wait for a connect event, this condition
\r
1957 might change while sleeping, so it must be checked within each loop */
\r
1958 xResult = bMayConnect( pxSocket ); /* -EINPROGRESS, -EAGAIN, or 0 for OK */
\r
1960 /* Start the connect procedure, kernel will start working on it */
\r
1961 if( xResult == 0 )
\r
1963 pxSocket->u.xTCP.bits.bConnPrepared = pdFALSE_UNSIGNED;
\r
1964 pxSocket->u.xTCP.ucRepCount = 0u;
\r
1966 FreeRTOS_debug_printf( ( "FreeRTOS_connect: %u to %lxip:%u\n",
\r
1967 pxSocket->usLocalPort, FreeRTOS_ntohl( pxAddress->sin_addr ), FreeRTOS_ntohs( pxAddress->sin_port ) ) );
\r
1969 /* Port on remote machine. */
\r
1970 pxSocket->u.xTCP.usRemotePort = FreeRTOS_ntohs( pxAddress->sin_port );
\r
1972 /* IP address of remote machine. */
\r
1973 pxSocket->u.xTCP.ulRemoteIP = FreeRTOS_ntohl( pxAddress->sin_addr );
\r
1975 /* (client) internal state: socket wants to send a connect. */
\r
1976 vTCPStateChange( pxSocket, eCONNECT_SYN );
\r
1978 /* To start an active connect. */
\r
1979 pxSocket->u.xTCP.usTimeout = 1u;
\r
1981 if( xSendEventToIPTask( eTCPTimerEvent ) != pdPASS )
\r
1983 xResult = -pdFREERTOS_ERRNO_ECANCELED;
\r
1991 #endif /* ipconfigUSE_TCP */
\r
1992 /*-----------------------------------------------------------*/
\r
1994 #if( ipconfigUSE_TCP == 1 )
\r
1997 * FreeRTOS_connect: socket wants to connect to a remote port
\r
1999 BaseType_t FreeRTOS_connect( Socket_t xClientSocket, struct freertos_sockaddr *pxAddress, socklen_t xAddressLength )
\r
2001 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t* ) xClientSocket;
\r
2002 TickType_t xRemainingTime;
\r
2003 BaseType_t xTimed = pdFALSE;
\r
2004 BaseType_t xResult;
\r
2005 TimeOut_t xTimeOut;
\r
2007 ( void ) xAddressLength;
\r
2009 xResult = prvTCPConnectStart( pxSocket, pxAddress );
\r
2011 if( xResult == 0 )
\r
2013 /* And wait for the result */
\r
2016 if( xTimed == pdFALSE )
\r
2018 /* Only in the first round, check for non-blocking */
\r
2019 xRemainingTime = pxSocket->xReceiveBlockTime;
\r
2020 if( xRemainingTime == ( TickType_t )0 )
\r
2022 /* Not yet connected, correct state, non-blocking. */
\r
2023 xResult = -pdFREERTOS_ERRNO_EWOULDBLOCK;
\r
2027 /* Don't get here a second time. */
\r
2030 /* Fetch the current time */
\r
2031 vTaskSetTimeOutState( &xTimeOut );
\r
2034 /* Did it get connected while sleeping ? */
\r
2035 xResult = FreeRTOS_issocketconnected( pxSocket );
\r
2037 /* Returns positive when connected, negative means an error */
\r
2040 /* Return the error */
\r
2046 /* Socket now connected, return a zero */
\r
2051 /* Is it allowed to sleep more? */
\r
2052 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) )
\r
2054 xResult = -pdFREERTOS_ERRNO_ETIMEDOUT;
\r
2058 /* Go sleeping until we get any down-stream event */
\r
2059 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_CONNECT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2065 #endif /* ipconfigUSE_TCP */
\r
2066 /*-----------------------------------------------------------*/
\r
2068 #if( ipconfigUSE_TCP == 1 )
\r
2071 * FreeRTOS_accept: can return a new connected socket
\r
2072 * if the server socket is in listen mode and receives a connection request
\r
2073 * The new socket will be bound already to the same port number as the listing
\r
2076 Socket_t FreeRTOS_accept( Socket_t xServerSocket, struct freertos_sockaddr *pxAddress, socklen_t *pxAddressLength )
\r
2078 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xServerSocket;
\r
2079 FreeRTOS_Socket_t *pxClientSocket = NULL;
\r
2080 TickType_t xRemainingTime;
\r
2081 BaseType_t xTimed = pdFALSE, xAsk = pdFALSE;
\r
2082 TimeOut_t xTimeOut;
\r
2083 IPStackEvent_t xAskEvent;
\r
2085 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2087 /* Not a valid socket or wrong type */
\r
2088 pxClientSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
\r
2090 else if( ( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED ) &&
\r
2091 ( pxSocket->u.xTCP.ucTCPState != eTCP_LISTEN ) )
\r
2093 /* Parent socket is not in listening mode */
\r
2094 pxClientSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
\r
2098 /* Loop will stop with breaks. */
\r
2101 /* Is there a new client? */
\r
2102 vTaskSuspendAll();
\r
2104 if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED )
\r
2106 pxClientSocket = pxSocket->u.xTCP.pxPeerSocket;
\r
2110 pxClientSocket = pxSocket;
\r
2112 if( pxClientSocket != NULL )
\r
2114 pxSocket->u.xTCP.pxPeerSocket = NULL;
\r
2116 /* Is it still not taken ? */
\r
2117 if( pxClientSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED )
\r
2119 pxClientSocket->u.xTCP.bits.bPassAccept = pdFALSE_UNSIGNED;
\r
2123 pxClientSocket = NULL;
\r
2129 if( pxClientSocket != NULL )
\r
2131 if( pxAddress != NULL )
\r
2133 /* IP address of remote machine. */
\r
2134 pxAddress->sin_addr = FreeRTOS_ntohl( pxClientSocket->u.xTCP.ulRemoteIP );
\r
2136 /* Port on remote machine. */
\r
2137 pxAddress->sin_port = FreeRTOS_ntohs( pxClientSocket->u.xTCP.usRemotePort );
\r
2139 if( pxAddressLength != NULL )
\r
2141 *pxAddressLength = sizeof( *pxAddress );
\r
2144 if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED )
\r
2150 if( xAsk != pdFALSE )
\r
2152 /* Ask to set an event in 'xEventGroup' as soon as a new
\r
2153 client gets connected for this listening socket. */
\r
2154 xAskEvent.eEventType = eTCPAcceptEvent;
\r
2155 xAskEvent.pvData = ( void * ) pxSocket;
\r
2156 xSendEventStructToIPTask( &xAskEvent, portMAX_DELAY );
\r
2159 if( pxClientSocket != NULL )
\r
2164 if( xTimed == pdFALSE )
\r
2166 /* Only in the first round, check for non-blocking */
\r
2167 xRemainingTime = pxSocket->xReceiveBlockTime;
\r
2168 if( xRemainingTime == ( TickType_t ) 0 )
\r
2173 /* Don't get here a second time */
\r
2176 /* Fetch the current time */
\r
2177 vTaskSetTimeOutState( &xTimeOut );
\r
2180 /* Has the timeout been reached? */
\r
2181 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
\r
2186 /* Go sleeping until we get any down-stream event */
\r
2187 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_ACCEPT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2191 return ( Socket_t ) pxClientSocket;
\r
2193 #endif /* ipconfigUSE_TCP */
\r
2194 /*-----------------------------------------------------------*/
\r
2196 #if( ipconfigUSE_TCP == 1 )
\r
2199 * Read incoming data from a TCP socket
\r
2200 * Only after the last byte has been read, a close error might be returned
\r
2202 BaseType_t FreeRTOS_recv( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags )
\r
2204 BaseType_t xByteCount;
\r
2205 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2206 TickType_t xRemainingTime;
\r
2207 BaseType_t xTimed = pdFALSE;
\r
2208 TimeOut_t xTimeOut;
\r
2209 EventBits_t xEventBits = ( EventBits_t ) 0;
\r
2211 /* Check if the socket is valid, has type TCP and if it is bound to a
\r
2213 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2215 xByteCount = -pdFREERTOS_ERRNO_EINVAL;
\r
2219 if( pxSocket->u.xTCP.rxStream != NULL )
\r
2221 xByteCount = ( BaseType_t )uxStreamBufferGetSize ( pxSocket->u.xTCP.rxStream );
\r
2228 while( xByteCount == 0 )
\r
2230 switch( pxSocket->u.xTCP.ucTCPState )
\r
2233 case eCLOSE_WAIT: /* (server + client) waiting for a connection termination request from the local user. */
\r
2234 case eCLOSING: /* (server + client) waiting for a connection termination request acknowledgement from the remote TCP. */
\r
2235 if( pxSocket->u.xTCP.bits.bMallocError != pdFALSE_UNSIGNED )
\r
2237 /* The no-memory error has priority above the non-connected error.
\r
2238 Both are fatal and will elad to closing the socket. */
\r
2239 xByteCount = -pdFREERTOS_ERRNO_ENOMEM;
\r
2243 xByteCount = -pdFREERTOS_ERRNO_ENOTCONN;
\r
2245 /* Call continue to break out of the switch and also the while
\r
2252 if( xTimed == pdFALSE )
\r
2254 /* Only in the first round, check for non-blocking. */
\r
2255 xRemainingTime = pxSocket->xReceiveBlockTime;
\r
2257 if( xRemainingTime == ( TickType_t ) 0 )
\r
2259 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
2261 /* Just check for the interrupt flag. */
\r
2262 xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_INTR,
\r
2263 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, socketDONT_BLOCK );
\r
2265 #endif /* ipconfigSUPPORT_SIGNALS */
\r
2269 if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
\r
2274 /* Don't get here a second time. */
\r
2277 /* Fetch the current time. */
\r
2278 vTaskSetTimeOutState( &xTimeOut );
\r
2281 /* Has the timeout been reached? */
\r
2282 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
\r
2287 /* Block until there is a down-stream event. */
\r
2288 xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup,
\r
2289 eSOCKET_RECEIVE | eSOCKET_CLOSED | eSOCKET_INTR,
\r
2290 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2291 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
2293 if( ( xEventBits & eSOCKET_INTR ) != 0u )
\r
2300 ( void ) xEventBits;
\r
2302 #endif /* ipconfigSUPPORT_SIGNALS */
\r
2304 if( pxSocket->u.xTCP.rxStream != NULL )
\r
2306 xByteCount = ( BaseType_t ) uxStreamBufferGetSize ( pxSocket->u.xTCP.rxStream );
\r
2314 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
2315 if( ( xEventBits & eSOCKET_INTR ) != 0 )
\r
2317 if( ( xEventBits & ( eSOCKET_RECEIVE | eSOCKET_CLOSED ) ) != 0 )
\r
2319 /* Shouldn't have cleared other flags. */
\r
2320 xEventBits &= ~eSOCKET_INTR;
\r
2321 xEventGroupSetBits( pxSocket->xEventGroup, xEventBits );
\r
2323 xByteCount = -pdFREERTOS_ERRNO_EINTR;
\r
2326 #endif /* ipconfigSUPPORT_SIGNALS */
\r
2327 if( xByteCount > 0 )
\r
2329 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
\r
2331 xByteCount = ( BaseType_t ) uxStreamBufferGet( pxSocket->u.xTCP.rxStream, 0ul, ( uint8_t * ) pvBuffer, ( size_t ) xBufferLength, ( xFlags & FREERTOS_MSG_PEEK ) != 0 );
\r
2332 if( pxSocket->u.xTCP.bits.bLowWater != pdFALSE_UNSIGNED )
\r
2334 /* We had reached the low-water mark, now see if the flag
\r
2336 size_t uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );
\r
2338 if( uxFrontSpace >= pxSocket->u.xTCP.uxEnoughSpace )
\r
2340 pxSocket->u.xTCP.bits.bLowWater = pdFALSE_UNSIGNED;
\r
2341 pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
\r
2342 pxSocket->u.xTCP.usTimeout = 1u; /* because bLowWater is cleared. */
\r
2343 xSendEventToIPTask( eTCPTimerEvent );
\r
2349 /* Zero-copy reception of data: pvBuffer is a pointer to a pointer. */
\r
2350 xByteCount = ( BaseType_t ) uxStreamBufferGetPtr( pxSocket->u.xTCP.rxStream, (uint8_t **)pvBuffer );
\r
2353 } /* prvValidSocket() */
\r
2355 return xByteCount;
\r
2358 #endif /* ipconfigUSE_TCP */
\r
2359 /*-----------------------------------------------------------*/
\r
2361 #if( ipconfigUSE_TCP == 1 )
\r
2363 static int32_t prvTCPSendCheck( FreeRTOS_Socket_t *pxSocket, size_t xDataLength )
\r
2365 int32_t xResult = 1;
\r
2367 /* Is this a socket of type TCP and is it already bound to a port number ? */
\r
2368 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2370 xResult = -pdFREERTOS_ERRNO_EINVAL;
\r
2372 else if( pxSocket->u.xTCP.bits.bMallocError != pdFALSE_UNSIGNED )
\r
2374 xResult = -pdFREERTOS_ERRNO_ENOMEM;
\r
2376 else if( pxSocket->u.xTCP.ucTCPState == eCLOSED )
\r
2378 xResult = -pdFREERTOS_ERRNO_ENOTCONN;
\r
2380 else if( pxSocket->u.xTCP.bits.bFinSent != pdFALSE_UNSIGNED )
\r
2382 /* This TCP connection is closing already, the FIN flag has been sent.
\r
2383 Maybe it is still delivering or receiving data.
\r
2384 Return OK in order not to get closed/deleted too quickly */
\r
2387 else if( xDataLength == 0ul )
\r
2389 /* send() is being called to send zero bytes */
\r
2392 else if( pxSocket->u.xTCP.txStream == NULL )
\r
2394 /* Create the outgoing stream only when it is needed */
\r
2395 prvTCPCreateStream( pxSocket, pdFALSE );
\r
2397 if( pxSocket->u.xTCP.txStream == NULL )
\r
2399 xResult = -pdFREERTOS_ERRNO_ENOMEM;
\r
2406 #endif /* ipconfigUSE_TCP */
\r
2407 /*-----------------------------------------------------------*/
\r
2409 #if( ipconfigUSE_TCP == 1 )
\r
2411 /* Get a direct pointer to the circular transmit buffer.
\r
2412 '*pxLength' will contain the number of bytes that may be written. */
\r
2413 uint8_t *FreeRTOS_get_tx_head( Socket_t xSocket, BaseType_t *pxLength )
\r
2415 uint8_t *pucReturn;
\r
2416 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2417 StreamBuffer_t *pxBuffer = pxSocket->u.xTCP.txStream;
\r
2419 if( pxBuffer != NULL )
\r
2421 BaseType_t xSpace = ( BaseType_t ) uxStreamBufferGetSpace( pxBuffer );
\r
2422 BaseType_t xRemain = ( BaseType_t ) ( pxBuffer->LENGTH - pxBuffer->uxHead );
\r
2424 *pxLength = FreeRTOS_min_BaseType( xSpace, xRemain );
\r
2425 pucReturn = pxBuffer->ucArray + pxBuffer->uxHead;
\r
2435 #endif /* ipconfigUSE_TCP */
\r
2436 /*-----------------------------------------------------------*/
\r
2438 #if( ipconfigUSE_TCP == 1 )
\r
2440 * Send data using a TCP socket. It is not necessary to have the socket
\r
2441 * connected already. Outgoing data will be stored and delivered as soon as
\r
2442 * the socket gets connected.
\r
2444 BaseType_t FreeRTOS_send( Socket_t xSocket, const void *pvBuffer, size_t uxDataLength, BaseType_t xFlags )
\r
2446 BaseType_t xByteCount;
\r
2447 BaseType_t xBytesLeft;
\r
2448 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2449 TickType_t xRemainingTime;
\r
2450 BaseType_t xTimed = pdFALSE;
\r
2451 TimeOut_t xTimeOut;
\r
2452 BaseType_t xCloseAfterSend;
\r
2454 /* Prevent compiler warnings about unused parameters. The parameter
\r
2455 may be used in future versions. */
\r
2458 xByteCount = ( BaseType_t ) prvTCPSendCheck( pxSocket, uxDataLength );
\r
2460 if( xByteCount > 0 )
\r
2462 /* xBytesLeft is number of bytes to send, will count to zero. */
\r
2463 xBytesLeft = ( BaseType_t ) uxDataLength;
\r
2465 /* xByteCount is number of bytes that can be sent now. */
\r
2466 xByteCount = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
\r
2468 /* While there are still bytes to be sent. */
\r
2469 while( xBytesLeft > 0 )
\r
2471 /* If txStream has space. */
\r
2472 if( xByteCount > 0 )
\r
2474 /* Don't send more than necessary. */
\r
2475 if( xByteCount > xBytesLeft )
\r
2477 xByteCount = xBytesLeft;
\r
2480 /* Is the close-after-send flag set and is this really the
\r
2481 last transmission? */
\r
2482 if( ( pxSocket->u.xTCP.bits.bCloseAfterSend != pdFALSE_UNSIGNED ) && ( xByteCount == xBytesLeft ) )
\r
2484 xCloseAfterSend = pdTRUE;
\r
2488 xCloseAfterSend = pdFALSE;
\r
2491 /* The flag 'bCloseAfterSend' can be set before sending data
\r
2492 using setsockopt()
\r
2494 When the last data packet is being sent out, a FIN flag will
\r
2495 be included to let the peer know that no more data is to be
\r
2496 expected. The use of 'bCloseAfterSend' is not mandatory, it
\r
2497 is just a faster way of transferring files (e.g. when using
\r
2499 if( xCloseAfterSend != pdFALSE )
\r
2501 /* Now suspend the scheduler: sending the last data and
\r
2502 setting bCloseRequested must be done together */
\r
2503 vTaskSuspendAll();
\r
2504 pxSocket->u.xTCP.bits.bCloseRequested = pdTRUE_UNSIGNED;
\r
2507 xByteCount = ( BaseType_t ) uxStreamBufferAdd( pxSocket->u.xTCP.txStream, 0ul, ( const uint8_t * ) pvBuffer, ( size_t ) xByteCount );
\r
2509 if( xCloseAfterSend != pdFALSE )
\r
2511 /* Now when the IP-task transmits the data, it will also
\r
2512 see that bCloseRequested is true and include the FIN
\r
2513 flag to start closure of the connection. */
\r
2517 /* Send a message to the IP-task so it can work on this
\r
2518 socket. Data is sent, let the IP-task work on it. */
\r
2519 pxSocket->u.xTCP.usTimeout = 1u;
\r
2521 if( xIsCallingFromIPTask() == pdFALSE )
\r
2523 /* Only send a TCP timer event when not called from the
\r
2525 xSendEventToIPTask( eTCPTimerEvent );
\r
2528 xBytesLeft -= xByteCount;
\r
2530 if( xBytesLeft == 0 )
\r
2535 /* As there are still bytes left to be sent, increase the
\r
2537 pvBuffer = ( void * ) ( ( ( const uint8_t * ) pvBuffer) + xByteCount );
\r
2540 /* Not all bytes have been sent. In case the socket is marked as
\r
2541 blocking sleep for a while. */
\r
2542 if( xTimed == pdFALSE )
\r
2544 /* Only in the first round, check for non-blocking. */
\r
2545 xRemainingTime = pxSocket->xSendBlockTime;
\r
2547 #if( ipconfigUSE_CALLBACKS != 0 )
\r
2549 if( xIsCallingFromIPTask() != pdFALSE )
\r
2551 /* If this send function is called from within a
\r
2552 call-back handler it may not block, otherwise
\r
2553 chances would be big to get a deadlock: the IP-task
\r
2554 waiting for itself. */
\r
2555 xRemainingTime = ( TickType_t ) 0;
\r
2558 #endif /* ipconfigUSE_CALLBACKS */
\r
2560 if( xRemainingTime == ( TickType_t ) 0 )
\r
2565 if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
\r
2570 /* Don't get here a second time. */
\r
2573 /* Fetch the current time. */
\r
2574 vTaskSetTimeOutState( &xTimeOut );
\r
2578 /* Has the timeout been reached? */
\r
2579 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
\r
2585 /* Go sleeping until down-stream events are received. */
\r
2586 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_SEND | eSOCKET_CLOSED,
\r
2587 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2589 xByteCount = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
\r
2592 /* How much was actually sent? */
\r
2593 xByteCount = ( ( BaseType_t ) uxDataLength ) - xBytesLeft;
\r
2595 if( xByteCount == 0 )
\r
2597 if( pxSocket->u.xTCP.ucTCPState > eESTABLISHED )
\r
2599 xByteCount = ( BaseType_t ) -pdFREERTOS_ERRNO_ENOTCONN;
\r
2603 if( ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) != pdFALSE )
\r
2605 FreeRTOS_debug_printf( ( "FreeRTOS_send: %u -> %lxip:%d: no space\n",
\r
2606 pxSocket->usLocalPort,
\r
2607 pxSocket->u.xTCP.ulRemoteIP,
\r
2608 pxSocket->u.xTCP.usRemotePort ) );
\r
2611 xByteCount = ( BaseType_t ) -pdFREERTOS_ERRNO_ENOSPC;
\r
2616 return xByteCount;
\r
2619 #endif /* ipconfigUSE_TCP */
\r
2620 /*-----------------------------------------------------------*/
\r
2622 #if( ipconfigUSE_TCP == 1 )
\r
2625 * Request to put a socket in listen mode
\r
2627 BaseType_t FreeRTOS_listen( Socket_t xSocket, BaseType_t xBacklog )
\r
2629 FreeRTOS_Socket_t *pxSocket;
\r
2630 BaseType_t xResult = 0;
\r
2632 pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2634 /* listen() is allowed for a valid TCP socket in Closed state and already
\r
2636 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2638 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2640 else if( ( pxSocket->u.xTCP.ucTCPState != eCLOSED ) && ( pxSocket->u.xTCP.ucTCPState != eCLOSE_WAIT ) )
\r
2642 /* Socket is in a wrong state. */
\r
2643 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2647 /* Backlog is interpreted here as "the maximum number of child
\r
2649 pxSocket->u.xTCP.usBacklog = ( uint16_t )FreeRTOS_min_int32( ( int32_t ) 0xffff, ( int32_t ) xBacklog );
\r
2651 /* This cleaning is necessary only if a listening socket is being
\r
2652 reused as it might have had a previous connection. */
\r
2653 if( pxSocket->u.xTCP.bits.bReuseSocket )
\r
2655 if( pxSocket->u.xTCP.rxStream != NULL )
\r
2657 vStreamBufferClear( pxSocket->u.xTCP.rxStream );
\r
2660 if( pxSocket->u.xTCP.txStream != NULL )
\r
2662 vStreamBufferClear( pxSocket->u.xTCP.txStream );
\r
2665 memset( pxSocket->u.xTCP.xPacket.u.ucLastPacket, '\0', sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket ) );
\r
2666 memset( &pxSocket->u.xTCP.xTCPWindow, '\0', sizeof( pxSocket->u.xTCP.xTCPWindow ) );
\r
2667 memset( &pxSocket->u.xTCP.bits, '\0', sizeof( pxSocket->u.xTCP.bits ) );
\r
2669 /* Now set the bReuseSocket flag again, because the bits have
\r
2670 just been cleared. */
\r
2671 pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE_UNSIGNED;
\r
2674 vTCPStateChange( pxSocket, eTCP_LISTEN );
\r
2680 #endif /* ipconfigUSE_TCP */
\r
2681 /*-----------------------------------------------------------*/
\r
2683 #if( ipconfigUSE_TCP == 1 )
\r
2685 /* shutdown - shut down part of a full-duplex connection */
\r
2686 BaseType_t FreeRTOS_shutdown( Socket_t xSocket, BaseType_t xHow )
\r
2688 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2689 BaseType_t xResult;
\r
2691 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2693 /*_RB_ Is this comment correct? The socket is not of a type that
\r
2694 supports the listen() operation. */
\r
2695 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2697 else if ( pxSocket->u.xTCP.ucTCPState != eESTABLISHED )
\r
2699 /*_RB_ Is this comment correct? The socket is not of a type that
\r
2700 supports the listen() operation. */
\r
2701 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2705 pxSocket->u.xTCP.bits.bUserShutdown = pdTRUE_UNSIGNED;
\r
2707 /* Let the IP-task perform the shutdown of the connection. */
\r
2708 pxSocket->u.xTCP.usTimeout = 1u;
\r
2709 xSendEventToIPTask( eTCPTimerEvent );
\r
2717 #endif /* ipconfigUSE_TCP */
\r
2718 /*-----------------------------------------------------------*/
\r
2720 #if( ipconfigUSE_TCP == 1 )
\r
2723 * A TCP timer has expired, now check all TCP sockets for:
\r
2724 * - Active connect
\r
2725 * - Send a delayed ACK
\r
2727 * - Send a keep-alive packet
\r
2728 * - Check for timeout (in non-connected states only)
\r
2730 TickType_t xTCPTimerCheck( BaseType_t xWillSleep )
\r
2732 FreeRTOS_Socket_t *pxSocket;
\r
2733 TickType_t xShortest = pdMS_TO_TICKS( ( TickType_t ) ipTCP_TIMER_PERIOD_MS );
\r
2734 TickType_t xNow = xTaskGetTickCount();
\r
2735 static TickType_t xLastTime = 0u;
\r
2736 TickType_t xDelta = xNow - xLastTime;
\r
2737 ListItem_t* pxEnd = ( ListItem_t * ) listGET_END_MARKER( &xBoundTCPSocketsList );
\r
2738 ListItem_t *pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );
\r
2742 if( xDelta == 0u )
\r
2747 while( pxIterator != pxEnd )
\r
2749 pxSocket = ( FreeRTOS_Socket_t * )listGET_LIST_ITEM_OWNER( pxIterator );
\r
2750 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator );
\r
2752 /* Sockets with 'tmout == 0' do not need any regular attention. */
\r
2753 if( pxSocket->u.xTCP.usTimeout == 0u )
\r
2758 if( xDelta < ( TickType_t ) pxSocket->u.xTCP.usTimeout )
\r
2760 pxSocket->u.xTCP.usTimeout = ( uint16_t ) ( ( ( TickType_t ) pxSocket->u.xTCP.usTimeout ) - xDelta );
\r
2765 pxSocket->u.xTCP.usTimeout = 0u;
\r
2766 rc = xTCPSocketCheck( pxSocket );
\r
2768 /* Within this function, the socket might want to send a delayed
\r
2769 ack or send out data or whatever it needs to do. */
\r
2772 /* Continue because the socket was deleted. */
\r
2777 /* In xEventBits the driver may indicate that the socket has
\r
2778 important events for the user. These are only done just before the
\r
2779 IP-task goes to sleep. */
\r
2780 if( pxSocket->xEventBits != 0u )
\r
2782 if( xWillSleep != pdFALSE )
\r
2784 /* The IP-task is about to go to sleep, so messages can be
\r
2785 sent to the socket owners. */
\r
2786 vSocketWakeUpUser( pxSocket );
\r
2790 /* Or else make sure this will be called again to wake-up
\r
2791 the sockets' owner. */
\r
2792 xShortest = ( TickType_t ) 0;
\r
2796 if( ( pxSocket->u.xTCP.usTimeout != 0u ) && ( xShortest > ( TickType_t ) pxSocket->u.xTCP.usTimeout ) )
\r
2798 xShortest = ( TickType_t ) pxSocket->u.xTCP.usTimeout;
\r
2805 #endif /* ipconfigUSE_TCP */
\r
2806 /*-----------------------------------------------------------*/
\r
2808 #if( ipconfigUSE_TCP == 1 )
\r
2811 * TCP: as multiple sockets may be bound to the same local port number
\r
2812 * looking up a socket is a little more complex:
\r
2813 * Both a local port, and a remote port and IP address are being used
\r
2814 * For a socket in listening mode, the remote port and IP address are both 0
\r
2816 FreeRTOS_Socket_t *pxTCPSocketLookup( uint32_t ulLocalIP, UBaseType_t uxLocalPort, uint32_t ulRemoteIP, UBaseType_t uxRemotePort )
\r
2818 ListItem_t *pxIterator;
\r
2819 FreeRTOS_Socket_t *pxResult = NULL, *pxListenSocket = NULL;
\r
2820 MiniListItem_t *pxEnd = ( MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );
\r
2822 /* Parameter not yet supported. */
\r
2823 ( void ) ulLocalIP;
\r
2825 for( pxIterator = ( ListItem_t * ) listGET_NEXT( pxEnd );
\r
2826 pxIterator != ( ListItem_t * ) pxEnd;
\r
2827 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
2829 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
\r
2831 if( pxSocket->usLocalPort == ( uint16_t ) uxLocalPort )
\r
2833 if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN )
\r
2835 /* If this is a socket listening to uxLocalPort, remember it
\r
2836 in case there is no perfect match. */
\r
2837 pxListenSocket = pxSocket;
\r
2839 else if( ( pxSocket->u.xTCP.usRemotePort == ( uint16_t ) uxRemotePort ) && ( pxSocket->u.xTCP.ulRemoteIP == ulRemoteIP ) )
\r
2841 /* For sockets not in listening mode, find a match with
\r
2842 xLocalPort, ulRemoteIP AND xRemotePort. */
\r
2843 pxResult = pxSocket;
\r
2848 if( pxResult == NULL )
\r
2850 /* An exact match was not found, maybe a listening socket was
\r
2852 pxResult = pxListenSocket;
\r
2858 #endif /* ipconfigUSE_TCP */
\r
2859 /*-----------------------------------------------------------*/
\r
2861 #if( ipconfigUSE_TCP == 1 )
\r
2863 const struct xSTREAM_BUFFER *FreeRTOS_get_rx_buf( Socket_t xSocket )
\r
2865 FreeRTOS_Socket_t *pxSocket = (FreeRTOS_Socket_t *)xSocket;
\r
2867 return pxSocket->u.xTCP.rxStream;
\r
2870 #endif /* ipconfigUSE_TCP */
\r
2871 /*-----------------------------------------------------------*/
\r
2873 #if( ipconfigUSE_TCP == 1 )
\r
2875 static StreamBuffer_t *prvTCPCreateStream ( FreeRTOS_Socket_t *pxSocket, BaseType_t xIsInputStream )
\r
2877 StreamBuffer_t *pxBuffer;
\r
2881 /* Now that a stream is created, the maximum size is fixed before
\r
2882 creation, it could still be changed with setsockopt(). */
\r
2883 if( xIsInputStream != pdFALSE )
\r
2885 uxLength = pxSocket->u.xTCP.uxRxStreamSize;
\r
2887 if( pxSocket->u.xTCP.uxLittleSpace == 0ul )
\r
2889 pxSocket->u.xTCP.uxLittleSpace = ( 1ul * pxSocket->u.xTCP.uxRxStreamSize ) / 5u; /*_RB_ Why divide by 5? Can this be changed to a #define? */
\r
2892 if( pxSocket->u.xTCP.uxEnoughSpace == 0ul )
\r
2894 pxSocket->u.xTCP.uxEnoughSpace = ( 4ul * pxSocket->u.xTCP.uxRxStreamSize ) / 5u; /*_RB_ Why multiply by 4? Maybe sock80_PERCENT?*/
\r
2899 uxLength = pxSocket->u.xTCP.uxTxStreamSize;
\r
2902 /* Add an extra 4 (or 8) bytes. */
\r
2903 uxLength += sizeof( size_t );
\r
2905 /* And make the length a multiple of sizeof( size_t ). */
\r
2906 uxLength &= ~( sizeof( size_t ) - 1u );
\r
2908 uxSize = sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) + uxLength;
\r
2910 pxBuffer = ( StreamBuffer_t * )pvPortMallocLarge( uxSize );
\r
2912 if( pxBuffer == NULL )
\r
2914 FreeRTOS_debug_printf( ( "prvTCPCreateStream: malloc failed\n" ) );
\r
2915 pxSocket->u.xTCP.bits.bMallocError = pdTRUE_UNSIGNED;
\r
2916 vTCPStateChange( pxSocket, eCLOSE_WAIT );
\r
2920 /* Clear the markers of the stream */
\r
2921 memset( pxBuffer, '\0', sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) );
\r
2922 pxBuffer->LENGTH = ( size_t ) uxLength ;
\r
2924 if( xTCPWindowLoggingLevel != 0 )
\r
2926 FreeRTOS_debug_printf( ( "prvTCPCreateStream: %cxStream created %lu bytes (total %lu)\n", xIsInputStream ? 'R' : 'T', uxLength, uxSize ) );
\r
2929 if( xIsInputStream != 0 )
\r
2931 pxSocket->u.xTCP.rxStream = pxBuffer;
\r
2935 pxSocket->u.xTCP.txStream = pxBuffer;
\r
2942 #endif /* ipconfigUSE_TCP */
\r
2943 /*-----------------------------------------------------------*/
\r
2945 #if( ipconfigUSE_TCP == 1 )
\r
2948 * Add data to the RxStream. When uxOffset > 0, data has come in out-of-order
\r
2949 * and will be put in front of the head so it can not be popped by the user.
\r
2951 int32_t lTCPAddRxdata( FreeRTOS_Socket_t *pxSocket, size_t uxOffset, const uint8_t *pcData, uint32_t ulByteCount )
\r
2953 StreamBuffer_t *pxStream = pxSocket->u.xTCP.rxStream;
\r
2955 #if( ipconfigUSE_CALLBACKS == 1 )
\r
2956 BaseType_t bHasHandler = ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xTCP.pxHandleReceive );
\r
2957 const uint8_t *pucBuffer = NULL;
\r
2958 #endif /* ipconfigUSE_CALLBACKS */
\r
2960 /* int32_t uxStreamBufferAdd( pxBuffer, uxOffset, pucData, aCount )
\r
2961 if( pucData != NULL ) copy data the the buffer
\r
2962 if( pucData == NULL ) no copying, just advance rxHead
\r
2963 if( uxOffset != 0 ) Just store data which has come out-of-order
\r
2964 if( uxOffset == 0 ) Also advance rxHead */
\r
2965 if( pxStream == NULL )
\r
2967 pxStream = prvTCPCreateStream( pxSocket, pdTRUE );
\r
2968 if( pxStream == NULL )
\r
2974 #if( ipconfigUSE_CALLBACKS == 1 )
\r
2976 if( ( bHasHandler != pdFALSE ) && ( uxStreamBufferGetSize( pxStream ) == 0u ) && ( uxOffset == 0ul ) && ( pcData != NULL ) )
\r
2978 /* Data can be passed directly to the user */
\r
2979 pucBuffer = pcData;
\r
2981 /* Zero-copy for call-back: no need to add the bytes to the
\r
2982 stream, only the pointer will be advanced by uxStreamBufferAdd(). */
\r
2986 #endif /* ipconfigUSE_CALLBACKS */
\r
2988 xResult = ( int32_t ) uxStreamBufferAdd( pxStream, uxOffset, pcData, ( size_t ) ulByteCount );
\r
2990 #if( ipconfigHAS_DEBUG_PRINTF != 0 )
\r
2992 if( xResult != ( int32_t ) ulByteCount )
\r
2994 FreeRTOS_debug_printf( ( "lTCPAddRxdata: at %ld: %ld/%lu bytes (tail %lu head %lu space %lu front %lu)\n",
\r
2995 uxOffset, xResult, ulByteCount,
\r
2998 uxStreamBufferFrontSpace( pxStream ),
\r
2999 pxStream->uxFront ) );
\r
3002 #endif /* ipconfigHAS_DEBUG_PRINTF */
\r
3004 if( uxOffset == 0u )
\r
3006 /* Data is being added to rxStream at the head (offs = 0) */
\r
3007 #if( ipconfigUSE_CALLBACKS == 1 )
\r
3008 if( bHasHandler != pdFALSE )
\r
3010 /* The socket owner has installed an OnReceive handler. Pass the
\r
3011 Rx data, without copying from the rxStream, to the user. */
\r
3014 uint8_t *ucReadPtr = NULL;
\r
3016 if( pucBuffer != NULL )
\r
3018 ucReadPtr = ( uint8_t * )pucBuffer;
\r
3019 ulCount = ulByteCount;
\r
3024 ulCount = ( uint32_t ) uxStreamBufferGetPtr( pxStream, &( ucReadPtr ) );
\r
3027 if( ulCount == 0ul )
\r
3032 pxSocket->u.xTCP.pxHandleReceive( (Socket_t *)pxSocket, ( void* )ucReadPtr, ( size_t ) ulCount );
\r
3033 uxStreamBufferGet( pxStream, 0ul, NULL, ( size_t ) ulCount, pdFALSE );
\r
3036 #endif /* ipconfigUSE_CALLBACKS */
\r
3038 /* See if running out of space. */
\r
3039 if( pxSocket->u.xTCP.bits.bLowWater == pdFALSE_UNSIGNED )
\r
3041 size_t uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );
\r
3042 if( uxFrontSpace <= pxSocket->u.xTCP.uxLittleSpace )
\r
3044 pxSocket->u.xTCP.bits.bLowWater = pdTRUE_UNSIGNED;
\r
3045 pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
\r
3047 /* bLowWater was reached, send the changed window size. */
\r
3048 pxSocket->u.xTCP.usTimeout = 1u;
\r
3049 xSendEventToIPTask( eTCPTimerEvent );
\r
3053 /* New incoming data is available, wake up the user. User's
\r
3054 semaphores will be set just before the IP-task goes asleep. */
\r
3055 pxSocket->xEventBits |= eSOCKET_RECEIVE;
\r
3057 #if ipconfigSUPPORT_SELECT_FUNCTION == 1
\r
3059 if( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 )
\r
3061 pxSocket->xEventBits |= ( eSELECT_READ << SOCKET_EVENT_BIT_COUNT );
\r
3071 #endif /* ipconfigUSE_TCP */
\r
3072 /*-----------------------------------------------------------*/
\r
3074 #if( ipconfigUSE_TCP == 1 )
\r
3076 /* Function to get the remote address and IP port */
\r
3077 BaseType_t FreeRTOS_GetRemoteAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress )
\r
3079 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3080 BaseType_t xResult;
\r
3082 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3084 xResult = -pdFREERTOS_ERRNO_EINVAL;
\r
3088 /* BSD style sockets communicate IP and port addresses in network
\r
3091 IP address of remote machine. */
\r
3092 pxAddress->sin_addr = FreeRTOS_htonl ( pxSocket->u.xTCP.ulRemoteIP );
\r
3094 /* Port on remote machine. */
\r
3095 pxAddress->sin_port = FreeRTOS_htons ( pxSocket->u.xTCP.usRemotePort );
\r
3097 xResult = ( BaseType_t ) sizeof( ( *pxAddress ) );
\r
3103 #endif /* ipconfigUSE_TCP */
\r
3105 /*-----------------------------------------------------------*/
\r
3107 #if( ipconfigUSE_TCP == 1 )
\r
3109 /* Returns the number of bytes that may be added to txStream */
\r
3110 BaseType_t FreeRTOS_maywrite( Socket_t xSocket )
\r
3112 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3113 BaseType_t xResult;
\r
3115 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3117 xResult = -pdFREERTOS_ERRNO_EINVAL;
\r
3119 else if( pxSocket->u.xTCP.ucTCPState != eESTABLISHED )
\r
3121 if( ( pxSocket->u.xTCP.ucTCPState < eCONNECT_SYN ) || ( pxSocket->u.xTCP.ucTCPState > eESTABLISHED ) )
\r
3130 else if( pxSocket->u.xTCP.txStream == NULL )
\r
3132 xResult = ( BaseType_t ) pxSocket->u.xTCP.uxTxStreamSize;
\r
3136 xResult = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
\r
3142 #endif /* ipconfigUSE_TCP */
\r
3143 /*-----------------------------------------------------------*/
\r
3145 #if( ipconfigUSE_TCP ==1 )
\r
3147 BaseType_t FreeRTOS_tx_space( Socket_t xSocket )
\r
3149 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3150 BaseType_t xReturn;
\r
3152 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3154 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3158 if( pxSocket->u.xTCP.txStream != NULL )
\r
3160 xReturn = ( BaseType_t ) uxStreamBufferGetSpace ( pxSocket->u.xTCP.txStream );
\r
3164 xReturn = ( BaseType_t ) pxSocket->u.xTCP.uxTxStreamSize;
\r
3171 #endif /* ipconfigUSE_TCP */
\r
3172 /*-----------------------------------------------------------*/
\r
3174 #if( ipconfigUSE_TCP == 1 )
\r
3176 BaseType_t FreeRTOS_tx_size( Socket_t xSocket )
\r
3178 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3179 BaseType_t xReturn;
\r
3181 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3183 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3187 if( pxSocket->u.xTCP.txStream != NULL )
\r
3189 xReturn = ( BaseType_t ) uxStreamBufferGetSize ( pxSocket->u.xTCP.txStream );
\r
3200 #endif /* ipconfigUSE_TCP */
\r
3201 /*-----------------------------------------------------------*/
\r
3203 #if( ipconfigUSE_TCP == 1 )
\r
3205 /* Returns pdTRUE if TCP socket is connected. */
\r
3206 BaseType_t FreeRTOS_issocketconnected( Socket_t xSocket )
\r
3208 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3209 BaseType_t xReturn = pdFALSE;
\r
3211 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3213 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3217 if( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED )
\r
3219 if( pxSocket->u.xTCP.ucTCPState < eCLOSE_WAIT )
\r
3229 #endif /* ipconfigUSE_TCP */
\r
3230 /*-----------------------------------------------------------*/
\r
3232 #if( ipconfigUSE_TCP == 1 )
\r
3234 /* returns the actual size of MSS being used */
\r
3235 BaseType_t FreeRTOS_mss( Socket_t xSocket )
\r
3237 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3238 BaseType_t xReturn;
\r
3240 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3242 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3246 /* usCurMSS is declared as uint16_t to save space. FreeRTOS_mss()
\r
3247 will often be used in signed native-size expressions cast it to
\r
3249 xReturn = ( BaseType_t ) ( pxSocket->u.xTCP.usCurMSS );
\r
3255 #endif /* ipconfigUSE_TCP */
\r
3256 /*-----------------------------------------------------------*/
\r
3258 #if( ipconfigUSE_TCP == 1 )
\r
3260 /* HT: for internal use only: return the connection status */
\r
3261 BaseType_t FreeRTOS_connstatus( Socket_t xSocket )
\r
3263 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3264 BaseType_t xReturn;
\r
3266 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3268 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3272 /* Cast it to BaseType_t */
\r
3273 xReturn = ( BaseType_t ) ( pxSocket->u.xTCP.ucTCPState );
\r
3279 #endif /* ipconfigUSE_TCP */
\r
3280 /*-----------------------------------------------------------*/
\r
3282 #if( ipconfigUSE_TCP == 1 )
\r
3285 * Returns the number of bytes which can be read.
\r
3287 BaseType_t FreeRTOS_rx_size( Socket_t xSocket )
\r
3289 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3290 BaseType_t xReturn;
\r
3292 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3294 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3296 else if( pxSocket->u.xTCP.rxStream != NULL )
\r
3298 xReturn = ( BaseType_t ) uxStreamBufferGetSize( pxSocket->u.xTCP.rxStream );
\r
3308 #endif /* ipconfigUSE_TCP */
\r
3309 /*-----------------------------------------------------------*/
\r
3311 #if( ipconfigUSE_TCP == 1 )
\r
3313 void FreeRTOS_netstat( void )
\r
3315 IPStackEvent_t xAskEvent;
\r
3317 /* Ask the IP-task to call vTCPNetStat()
\r
3318 * to avoid accessing xBoundTCPSocketsList
\r
3320 xAskEvent.eEventType = eTCPNetStat;
\r
3321 xAskEvent.pvData = ( void * ) NULL;
\r
3322 xSendEventStructToIPTask( &xAskEvent, 1000u );
\r
3325 #endif /* ipconfigUSE_TCP */
\r
3326 /*-----------------------------------------------------------*/
\r
3328 #if( ( ipconfigHAS_PRINTF != 0 ) && ( ipconfigUSE_TCP == 1 ) )
\r
3330 void vTCPNetStat( void )
\r
3332 /* Show a simple listing of all created sockets and their connections */
\r
3333 ListItem_t *pxIterator;
\r
3334 BaseType_t count = 0;
\r
3336 if( listLIST_IS_INITIALISED( &xBoundTCPSocketsList ) == pdFALSE )
\r
3338 FreeRTOS_printf( ( "PLUS-TCP not initialized\n" ) );
\r
3342 FreeRTOS_printf( ( "Prot Port IP-Remote : Port R/T Status Alive tmout Child\n" ) );
\r
3343 for( pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );
\r
3344 pxIterator != ( ListItem_t * ) listGET_END_MARKER( &xBoundTCPSocketsList );
\r
3345 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
3347 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
\r
3348 #if( ipconfigTCP_KEEP_ALIVE == 1 )
\r
3349 TickType_t age = xTaskGetTickCount() - pxSocket->u.xTCP.xLastAliveTime;
\r
3351 TickType_t age = 0u;
\r
3353 #if( ipconfigUSE_CALLBACKS == 1 )
\r
3354 void *pxHandleReceive = (void*)pxSocket->u.xTCP.pxHandleReceive;
\r
3356 void *pxHandleReceive = (void*)NULL;
\r
3358 char ucChildText[16] = "";
\r
3359 if (pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN)
\r
3361 const int32_t copied_len = snprintf( ucChildText, sizeof( ucChildText ), " %d/%d",
\r
3362 ( int ) pxSocket->u.xTCP.usChildCount,
\r
3363 ( int ) pxSocket->u.xTCP.usBacklog);
\r
3364 /* These should never evaluate to false since the buffers are both shorter than 5-6 characters (<=65535) */
\r
3365 configASSERT( copied_len >= 0 );
\r
3366 configASSERT( copied_len < sizeof( ucChildText ) );
\r
3368 FreeRTOS_printf( ( "TCP %5d %-16lxip:%5d %d/%d %-13.13s %6lu %6u%s\n",
\r
3369 pxSocket->usLocalPort, /* Local port on this machine */
\r
3370 pxSocket->u.xTCP.ulRemoteIP, /* IP address of remote machine */
\r
3371 pxSocket->u.xTCP.usRemotePort, /* Port on remote machine */
\r
3372 pxSocket->u.xTCP.rxStream != NULL,
\r
3373 pxSocket->u.xTCP.txStream != NULL,
\r
3374 FreeRTOS_GetTCPStateName( pxSocket->u.xTCP.ucTCPState ),
\r
3375 (age > 999999 ? 999999 : age), /* Format 'age' for printing */
\r
3376 pxSocket->u.xTCP.usTimeout,
\r
3378 /* Remove compiler warnings if FreeRTOS_debug_printf() is not defined. */
\r
3379 ( void ) pxHandleReceive;
\r
3383 for( pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundUDPSocketsList );
\r
3384 pxIterator != ( ListItem_t * ) listGET_END_MARKER( &xBoundUDPSocketsList );
\r
3385 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
3387 /* Local port on this machine */
\r
3388 FreeRTOS_printf( ( "UDP Port %5u\n",
\r
3389 FreeRTOS_ntohs( listGET_LIST_ITEM_VALUE( pxIterator ) ) ) );
\r
3393 FreeRTOS_printf( ( "FreeRTOS_netstat: %lu sockets %lu < %lu < %d buffers free\n",
\r
3395 uxGetMinimumFreeNetworkBuffers( ),
\r
3396 uxGetNumberOfFreeNetworkBuffers( ),
\r
3397 ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ) );
\r
3401 #endif /* ( ( ipconfigHAS_PRINTF != 0 ) && ( ipconfigUSE_TCP == 1 ) ) */
\r
3402 /*-----------------------------------------------------------*/
\r
3404 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
3406 void vSocketSelect( SocketSelect_t *pxSocketSet )
\r
3408 BaseType_t xRound;
\r
3409 EventBits_t xSocketBits, xBitsToClear;
\r
3410 #if ipconfigUSE_TCP == 1
\r
3411 BaseType_t xLastRound = 1;
\r
3413 BaseType_t xLastRound = 0;
\r
3416 /* These flags will be switched on after checking the socket status. */
\r
3417 EventBits_t xGroupBits = 0;
\r
3418 pxSocketSet->pxSocket = NULL;
\r
3420 for( xRound = 0; xRound <= xLastRound; xRound++ )
\r
3422 const ListItem_t *pxIterator;
\r
3423 const MiniListItem_t *pxEnd;
\r
3426 pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundUDPSocketsList );
\r
3428 #if ipconfigUSE_TCP == 1
\r
3431 pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );
\r
3433 #endif /* ipconfigUSE_TCP == 1 */
\r
3434 for( pxIterator = ( const ListItem_t * ) ( listGET_NEXT( pxEnd ) );
\r
3435 pxIterator != ( const ListItem_t * ) pxEnd;
\r
3436 pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
3438 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
\r
3439 if( pxSocket->pxSocketSet != pxSocketSet )
\r
3441 /* Socket does not belong to this select group. */
\r
3446 #if( ipconfigUSE_TCP == 1 )
\r
3447 if( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP )
\r
3449 /* Check if the socket has already been accepted by the
\r
3450 owner. If not, it is useless to return it from a
\r
3452 BaseType_t bAccepted = pdFALSE;
\r
3454 if( pxSocket->u.xTCP.bits.bPassQueued == pdFALSE_UNSIGNED )
\r
3456 if( pxSocket->u.xTCP.bits.bPassAccept == pdFALSE_UNSIGNED )
\r
3458 bAccepted = pdTRUE;
\r
3462 /* Is the set owner interested in READ events? */
\r
3463 if( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 )
\r
3465 if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN )
\r
3467 if( ( pxSocket->u.xTCP.pxPeerSocket != NULL ) && ( pxSocket->u.xTCP.pxPeerSocket->u.xTCP.bits.bPassAccept != 0 ) )
\r
3469 xSocketBits |= eSELECT_READ;
\r
3472 else if( ( pxSocket->u.xTCP.bits.bReuseSocket != pdFALSE_UNSIGNED ) && ( pxSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED ) )
\r
3474 /* This socket has the re-use flag. After connecting it turns into
\r
3475 aconnected socket. Set the READ event, so that accept() will be called. */
\r
3476 xSocketBits |= eSELECT_READ;
\r
3478 else if( ( bAccepted != 0 ) && ( FreeRTOS_recvcount( pxSocket ) > 0 ) )
\r
3480 xSocketBits |= eSELECT_READ;
\r
3483 /* Is the set owner interested in EXCEPTION events? */
\r
3484 if( ( pxSocket->xSelectBits & eSELECT_EXCEPT ) != 0 )
\r
3486 if( ( pxSocket->u.xTCP.ucTCPState == eCLOSE_WAIT ) || ( pxSocket->u.xTCP.ucTCPState == eCLOSED ) )
\r
3488 xSocketBits |= eSELECT_EXCEPT;
\r
3492 /* Is the set owner interested in WRITE events? */
\r
3493 if( ( pxSocket->xSelectBits & eSELECT_WRITE ) != 0 )
\r
3495 BaseType_t bMatch = pdFALSE;
\r
3497 if( bAccepted != 0 )
\r
3499 if( FreeRTOS_tx_space( pxSocket ) > 0 )
\r
3505 if( bMatch == pdFALSE )
\r
3507 if( ( pxSocket->u.xTCP.bits.bConnPrepared != pdFALSE_UNSIGNED ) &&
\r
3508 ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) &&
\r
3509 ( pxSocket->u.xTCP.bits.bConnPassed == pdFALSE_UNSIGNED ) )
\r
3511 pxSocket->u.xTCP.bits.bConnPassed = pdTRUE_UNSIGNED;
\r
3516 if( bMatch != pdFALSE )
\r
3518 xSocketBits |= eSELECT_WRITE;
\r
3523 #endif /* ipconfigUSE_TCP == 1 */
\r
3525 /* Select events for UDP are simpler. */
\r
3526 if( ( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 ) &&
\r
3527 ( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) > 0U ) )
\r
3529 xSocketBits |= eSELECT_READ;
\r
3531 /* The WRITE and EXCEPT bits are not used for UDP */
\r
3532 } /* if( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP ) */
\r
3534 /* Each socket keeps its own event flags, which are looked-up
\r
3535 by FreeRTOS_FD_ISSSET() */
\r
3536 pxSocket->xSocketBits = xSocketBits;
\r
3538 /* The ORed value will be used to set the bits in the event
\r
3540 xGroupBits |= xSocketBits;
\r
3542 } /* for( pxIterator ... ) */
\r
3543 } /* for( xRound = 0; xRound <= xLastRound; xRound++ ) */
\r
3545 xBitsToClear = xEventGroupGetBits( pxSocketSet->xSelectGroup );
\r
3547 /* Now set the necessary bits. */
\r
3548 xBitsToClear = ( xBitsToClear & ~xGroupBits ) & eSELECT_ALL;
\r
3550 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
3552 /* Maybe the socketset was signalled, but don't
\r
3553 clear the 'eSELECT_INTR' bit here, as it will be used
\r
3554 and cleared in FreeRTOS_select(). */
\r
3555 xBitsToClear &= ( EventBits_t ) ~eSELECT_INTR;
\r
3557 #endif /* ipconfigSUPPORT_SIGNALS */
\r
3559 if( xBitsToClear != 0 )
\r
3561 xEventGroupClearBits( pxSocketSet->xSelectGroup, xBitsToClear );
\r
3564 /* Now include eSELECT_CALL_IP to wakeup the caller. */
\r
3565 xEventGroupSetBits( pxSocketSet->xSelectGroup, xGroupBits | eSELECT_CALL_IP );
\r
3568 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
3569 /*-----------------------------------------------------------*/
\r
3571 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
3573 /* Send a signal to the task which reads from this socket. */
\r
3574 BaseType_t FreeRTOS_SignalSocket( Socket_t xSocket )
\r
3576 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3577 BaseType_t xReturn;
\r
3579 if( pxSocket == NULL )
\r
3581 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3584 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
3585 if( ( pxSocket->pxSocketSet != NULL ) && ( pxSocket->pxSocketSet->xSelectGroup != NULL ) )
\r
3587 xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, eSELECT_INTR );
\r
3591 #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
\r
3592 if( pxSocket->xEventGroup != NULL )
\r
3594 xEventGroupSetBits( pxSocket->xEventGroup, eSOCKET_INTR );
\r
3599 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3605 #endif /* ipconfigSUPPORT_SIGNALS */
\r
3606 /*-----------------------------------------------------------*/
\r
3608 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
3610 /* Send a signal to the task which reads from this socket (FromISR version). */
\r
3611 BaseType_t FreeRTOS_SignalSocketFromISR( Socket_t xSocket, BaseType_t *pxHigherPriorityTaskWoken )
\r
3613 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3614 BaseType_t xReturn;
\r
3615 IPStackEvent_t xEvent;
\r
3616 extern QueueHandle_t xNetworkEventQueue;
\r
3618 configASSERT( pxSocket != NULL );
\r
3619 configASSERT( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP );
\r
3620 configASSERT( pxSocket->xEventGroup );
\r
3622 xEvent.eEventType = eSocketSignalEvent;
\r
3623 xEvent.pvData = ( void * )pxSocket;
\r
3625 /* The IP-task will call FreeRTOS_SignalSocket for this socket. */
\r
3626 xReturn = xQueueSendToBackFromISR( xNetworkEventQueue, &xEvent, pxHigherPriorityTaskWoken );
\r
3631 #endif /* ipconfigSUPPORT_SIGNALS */
\r
3632 /*-----------------------------------------------------------*/
\r