2 * FreeRTOS+TCP V2.0.1
\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://www.FreeRTOS.org
\r
23 * http://aws.amazon.com/freertos
\r
25 * 1 tab == 4 spaces!
\r
28 /* Standard includes. */
\r
32 /* FreeRTOS includes. */
\r
33 #include "FreeRTOS.h"
\r
38 /* FreeRTOS+TCP includes. */
\r
39 #include "FreeRTOS_UDP_IP.h"
\r
40 #include "FreeRTOS_IP.h"
\r
41 #include "FreeRTOS_Sockets.h"
\r
42 #include "FreeRTOS_IP_Private.h"
\r
43 #include "FreeRTOS_DNS.h"
\r
44 #include "NetworkBufferManagement.h"
\r
46 /* The ItemValue of the sockets xBoundSocketListItem member holds the socket's
\r
48 #define socketSET_SOCKET_PORT( pxSocket, usPort ) listSET_LIST_ITEM_VALUE( ( &( ( pxSocket )->xBoundSocketListItem ) ), ( usPort ) )
\r
49 #define socketGET_SOCKET_PORT( pxSocket ) listGET_LIST_ITEM_VALUE( ( &( ( pxSocket )->xBoundSocketListItem ) ) )
\r
51 /* Test if a socket it bound which means it is either included in
\r
52 xBoundUDPSocketsList or xBoundTCPSocketsList */
\r
53 #define socketSOCKET_IS_BOUND( pxSocket ) ( listLIST_ITEM_CONTAINER( & ( pxSocket )->xBoundSocketListItem ) != NULL )
\r
55 /* If FreeRTOS_sendto() is called on a socket that is not bound to a port
\r
56 number then, depending on the FreeRTOSIPConfig.h settings, it might be that a
\r
57 port number is automatically generated for the socket. Automatically generated
\r
58 port numbers will be between socketAUTO_PORT_ALLOCATION_START_NUMBER and
\r
60 /* _HT_ thinks that the default of 0xc000 is pretty high */
\r
61 #if !defined( socketAUTO_PORT_ALLOCATION_START_NUMBER )
\r
62 #define socketAUTO_PORT_ALLOCATION_START_NUMBER ( ( uint16_t ) 0xc000 )
\r
65 /* When the automatically generated port numbers overflow, the next value used
\r
66 is not set back to socketAUTO_PORT_ALLOCATION_START_NUMBER because it is likely
\r
67 that the first few automatically generated ports will still be in use. Instead
\r
68 it is reset back to the value defined by this constant. */
\r
69 #define socketAUTO_PORT_ALLOCATION_RESET_NUMBER ( ( uint16_t ) 0xc100 )
\r
70 #define socketAUTO_PORT_ALLOCATION_MAX_NUMBER ( ( uint16_t ) 0xff00 )
\r
72 /* The number of octets that make up an IP address. */
\r
73 #define socketMAX_IP_ADDRESS_OCTETS 4u
\r
75 /* A block time of 0 simply means "don't block". */
\r
76 #define socketDONT_BLOCK ( ( TickType_t ) 0 )
\r
78 #if( ( ipconfigUSE_TCP == 1 ) && !defined( ipTCP_TIMER_PERIOD_MS ) )
\r
79 #define ipTCP_TIMER_PERIOD_MS ( 1000 )
\r
82 /* The next private port number to use when binding a client socket is stored in
\r
83 the usNextPortToUse[] array - which has either 1 or two indexes depending on
\r
84 whether TCP is being supported. */
\r
85 #if( ipconfigUSE_TCP == 1 )
\r
86 #define socketPROTOCOL_COUNT 2
\r
88 #define socketPROTOCOL_COUNT 1
\r
91 /* Indexes into the usNextPortToUse[] array for UDP and TCP sockets
\r
93 #define socketNEXT_UDP_PORT_NUMBER_INDEX 0
\r
94 #define socketNEXT_TCP_PORT_NUMBER_INDEX 1
\r
97 /*-----------------------------------------------------------*/
\r
100 * Allocate the next port number from the private allocation range.
\r
101 * TCP and UDP each have their own series of port numbers
\r
102 * ulProtocol is either ipPROTOCOL_UDP or ipPROTOCOL_TCP
\r
104 static uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol );
\r
107 * Return the list item from within pxList that has an item value of
\r
108 * xWantedItemValue. If there is no such list item return NULL.
\r
110 static const ListItem_t * pxListFindListItemWithValue( const List_t *pxList, TickType_t xWantedItemValue );
\r
113 * Return pdTRUE only if pxSocket is valid and bound, as far as can be
\r
116 static BaseType_t prvValidSocket( FreeRTOS_Socket_t *pxSocket, BaseType_t xProtocol, BaseType_t xIsBound );
\r
119 * Before creating a socket, check the validity of the parameters used
\r
120 * and find the size of the socket space, which is different for UDP and TCP
\r
122 static BaseType_t prvDetermineSocketSize( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol, size_t *pxSocketSize );
\r
124 #if( ipconfigUSE_TCP == 1 )
\r
126 * Create a txStream or a rxStream, depending on the parameter 'xIsInputStream'
\r
128 static StreamBuffer_t *prvTCPCreateStream (FreeRTOS_Socket_t *pxSocket, BaseType_t xIsInputStream );
\r
129 #endif /* ipconfigUSE_TCP == 1 */
\r
131 #if( ipconfigUSE_TCP == 1 )
\r
133 * Called from FreeRTOS_send(): some checks which will be done before
\r
134 * sending a TCP packed.
\r
136 static int32_t prvTCPSendCheck( FreeRTOS_Socket_t *pxSocket, size_t xDataLength );
\r
137 #endif /* ipconfigUSE_TCP */
\r
139 #if( ipconfigUSE_TCP == 1 )
\r
141 * When a child socket gets closed, make sure to update the child-count of the parent
\r
143 static void prvTCPSetSocketCount( FreeRTOS_Socket_t *pxSocketToDelete );
\r
144 #endif /* ipconfigUSE_TCP == 1 */
\r
146 #if( ipconfigUSE_TCP == 1 )
\r
148 * Called from FreeRTOS_connect(): make some checks and if allowed, send a
\r
149 * message to the IP-task to start connecting to a remote socket
\r
151 static BaseType_t prvTCPConnectStart( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr *pxAddress );
\r
152 #endif /* ipconfigUSE_TCP */
\r
154 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
156 /* Executed by the IP-task, it will check all sockets belonging to a set */
\r
157 static FreeRTOS_Socket_t *prvFindSelectedSocket( SocketSelect_t *pxSocketSet );
\r
159 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
160 /*-----------------------------------------------------------*/
\r
162 /* The list that contains mappings between sockets and port numbers. Accesses
\r
163 to this list must be protected by critical sections of one kind or another. */
\r
164 List_t xBoundUDPSocketsList;
\r
166 #if ipconfigUSE_TCP == 1
\r
167 List_t xBoundTCPSocketsList;
\r
168 #endif /* ipconfigUSE_TCP == 1 */
\r
170 /* Holds the next private port number to use when binding a client socket for
\r
171 UDP, and if ipconfigUSE_TCP is set to 1, also TCP. UDP uses index
\r
172 socketNEXT_UDP_PORT_NUMBER_INDEX and TCP uses index
\r
173 socketNEXT_TCP_PORT_NUMBER_INDEX. The initial value is set to be between
\r
174 socketAUTO_PORT_ALLOCATION_RESET_NUMBER and socketAUTO_PORT_ALLOCATION_MAX_NUMBER
\r
175 when the IP stack is initialised. Note ipconfigRAND32() is used, which must be
\r
176 seeded prior to the IP task being started. */
\r
177 static uint16_t usNextPortToUse[ socketPROTOCOL_COUNT ] = { 0 };
\r
179 /*-----------------------------------------------------------*/
\r
181 static BaseType_t prvValidSocket( FreeRTOS_Socket_t *pxSocket, BaseType_t xProtocol, BaseType_t xIsBound )
\r
183 BaseType_t xReturn = pdTRUE;
\r
185 if( ( pxSocket == NULL ) || ( pxSocket == FREERTOS_INVALID_SOCKET ) )
\r
189 else if( ( xIsBound != pdFALSE ) && ( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE ) )
\r
191 /* The caller expects the socket to be bound, but it isn't. */
\r
194 else if( pxSocket->ucProtocol != ( uint8_t ) xProtocol )
\r
196 /* Socket has a wrong type (UDP != TCP). */
\r
202 /*-----------------------------------------------------------*/
\r
204 void vNetworkSocketsInit( void )
\r
206 const uint32_t ulAutoPortRange = socketAUTO_PORT_ALLOCATION_MAX_NUMBER - socketAUTO_PORT_ALLOCATION_RESET_NUMBER;
\r
207 uint32_t ulRandomPort;
\r
209 vListInitialise( &xBoundUDPSocketsList );
\r
211 /* Determine the first anonymous UDP port number to get assigned. Give it
\r
212 a random value in order to avoid confusion about port numbers being used
\r
213 earlier, before rebooting the device. Start with the first auto port
\r
214 number, then add a random offset up to a maximum of the range of numbers. */
\r
215 ulRandomPort = socketAUTO_PORT_ALLOCATION_START_NUMBER;
\r
216 ulRandomPort += ( ipconfigRAND32() % ulAutoPortRange );
\r
217 usNextPortToUse[ socketNEXT_UDP_PORT_NUMBER_INDEX ] = ( uint16_t ) ulRandomPort;
\r
219 #if( ipconfigUSE_TCP == 1 )
\r
221 extern uint32_t ulNextInitialSequenceNumber;
\r
223 ulNextInitialSequenceNumber = ipconfigRAND32();
\r
225 /* Determine the first anonymous TCP port number to get assigned. */
\r
226 ulRandomPort = socketAUTO_PORT_ALLOCATION_START_NUMBER;
\r
227 ulRandomPort += ( ipconfigRAND32() % ulAutoPortRange );
\r
228 usNextPortToUse[ socketNEXT_TCP_PORT_NUMBER_INDEX ] = ( uint16_t ) ulRandomPort;
\r
230 vListInitialise( &xBoundTCPSocketsList );
\r
232 #endif /* ipconfigUSE_TCP == 1 */
\r
234 /*-----------------------------------------------------------*/
\r
236 static BaseType_t prvDetermineSocketSize( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol, size_t *pxSocketSize )
\r
238 BaseType_t xReturn = pdPASS;
\r
239 FreeRTOS_Socket_t *pxSocket;
\r
241 /* Asserts must not appear before it has been determined that the network
\r
242 task is ready - otherwise the asserts will fail. */
\r
243 if( xIPIsNetworkTaskReady() == pdFALSE )
\r
249 /* Only Ethernet is currently supported. */
\r
250 configASSERT( xDomain == FREERTOS_AF_INET );
\r
252 /* Check if the UDP socket-list has been initialised. */
\r
253 configASSERT( listLIST_IS_INITIALISED( &xBoundUDPSocketsList ) );
\r
254 #if( ipconfigUSE_TCP == 1 )
\r
256 /* Check if the TCP socket-list has been initialised. */
\r
257 configASSERT( listLIST_IS_INITIALISED( &xBoundTCPSocketsList ) );
\r
259 #endif /* ipconfigUSE_TCP == 1 */
\r
261 if( xProtocol == FREERTOS_IPPROTO_UDP )
\r
263 if( xType != FREERTOS_SOCK_DGRAM )
\r
267 /* In case a UDP socket is created, do not allocate space for TCP data. */
\r
268 *pxSocketSize = ( sizeof( *pxSocket ) - sizeof( pxSocket->u ) ) + sizeof( pxSocket->u.xUDP );
\r
270 #if( ipconfigUSE_TCP == 1 )
\r
271 else if( xProtocol == FREERTOS_IPPROTO_TCP )
\r
273 if( xType != FREERTOS_SOCK_STREAM )
\r
278 *pxSocketSize = ( sizeof( *pxSocket ) - sizeof( pxSocket->u ) ) + sizeof( pxSocket->u.xTCP );
\r
280 #endif /* ipconfigUSE_TCP == 1 */
\r
286 /* In case configASSERT() is not used */
\r
290 /*-----------------------------------------------------------*/
\r
292 /* FreeRTOS_socket() allocates and initiates a socket */
\r
293 Socket_t FreeRTOS_socket( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol )
\r
295 FreeRTOS_Socket_t *pxSocket;
\r
296 size_t uxSocketSize;
\r
297 EventGroupHandle_t xEventGroup;
\r
300 if( prvDetermineSocketSize( xDomain, xType, xProtocol, &uxSocketSize ) == pdFAIL )
\r
302 xReturn = FREERTOS_INVALID_SOCKET;
\r
306 /* Allocate the structure that will hold the socket information. The
\r
307 size depends on the type of socket: UDP sockets need less space. A
\r
308 define 'pvPortMallocSocket' will used to allocate the necessary space.
\r
309 By default it points to the FreeRTOS function 'pvPortMalloc()'. */
\r
310 pxSocket = ( FreeRTOS_Socket_t * ) pvPortMallocSocket( uxSocketSize );
\r
312 if( pxSocket == NULL )
\r
314 pxSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
\r
315 iptraceFAILED_TO_CREATE_SOCKET();
\r
317 else if( ( xEventGroup = xEventGroupCreate() ) == NULL )
\r
319 vPortFreeSocket( pxSocket );
\r
320 pxSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
\r
321 iptraceFAILED_TO_CREATE_EVENT_GROUP();
\r
325 /* Clear the entire space to avoid nulling individual entries. */
\r
326 memset( pxSocket, '\0', uxSocketSize );
\r
328 pxSocket->xEventGroup = xEventGroup;
\r
330 /* Initialise the socket's members. The semaphore will be created
\r
331 if the socket is bound to an address, for now the pointer to the
\r
332 semaphore is just set to NULL to show it has not been created. */
\r
333 if( xProtocol == FREERTOS_IPPROTO_UDP )
\r
335 vListInitialise( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
\r
337 #if( ipconfigUDP_MAX_RX_PACKETS > 0 )
\r
339 pxSocket->u.xUDP.uxMaxPackets = ( UBaseType_t ) ipconfigUDP_MAX_RX_PACKETS;
\r
341 #endif /* ipconfigUDP_MAX_RX_PACKETS > 0 */
\r
344 vListInitialiseItem( &( pxSocket->xBoundSocketListItem ) );
\r
345 listSET_LIST_ITEM_OWNER( &( pxSocket->xBoundSocketListItem ), ( void * ) pxSocket );
\r
347 pxSocket->xReceiveBlockTime = ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME;
\r
348 pxSocket->xSendBlockTime = ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME;
\r
349 pxSocket->ucSocketOptions = ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT;
\r
350 pxSocket->ucProtocol = ( uint8_t ) xProtocol; /* protocol: UDP or TCP */
\r
352 #if( ipconfigUSE_TCP == 1 )
\r
354 if( xProtocol == FREERTOS_IPPROTO_TCP )
\r
356 /* StreamSize is expressed in number of bytes */
\r
357 /* Round up buffer sizes to nearest multiple of MSS */
\r
358 pxSocket->u.xTCP.usInitMSS = pxSocket->u.xTCP.usCurMSS = ipconfigTCP_MSS;
\r
359 pxSocket->u.xTCP.uxRxStreamSize = ( size_t ) ipconfigTCP_RX_BUFFER_LENGTH;
\r
360 pxSocket->u.xTCP.uxTxStreamSize = ( size_t ) FreeRTOS_round_up( ipconfigTCP_TX_BUFFER_LENGTH, ipconfigTCP_MSS );
\r
361 /* Use half of the buffer size of the TCP windows */
\r
362 #if ( ipconfigUSE_TCP_WIN == 1 )
\r
364 pxSocket->u.xTCP.uxRxWinSize = FreeRTOS_max_uint32( 1UL, ( uint32_t ) ( pxSocket->u.xTCP.uxRxStreamSize / 2 ) / ipconfigTCP_MSS );
\r
365 pxSocket->u.xTCP.uxTxWinSize = FreeRTOS_max_uint32( 1UL, ( uint32_t ) ( pxSocket->u.xTCP.uxTxStreamSize / 2 ) / ipconfigTCP_MSS );
\r
369 pxSocket->u.xTCP.uxRxWinSize = 1u;
\r
370 pxSocket->u.xTCP.uxTxWinSize = 1u;
\r
373 /* The above values are just defaults, and can be overridden by
\r
374 calling FreeRTOS_setsockopt(). No buffers will be allocated until a
\r
375 socket is connected and data is exchanged. */
\r
378 #endif /* ipconfigUSE_TCP == 1 */
\r
381 xReturn = ( Socket_t ) pxSocket;
\r
384 /* Remove compiler warnings in the case the configASSERT() is not defined. */
\r
389 /*-----------------------------------------------------------*/
\r
391 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
393 SocketSet_t FreeRTOS_CreateSocketSet( void )
\r
395 SocketSelect_t *pxSocketSet;
\r
397 pxSocketSet = ( SocketSelect_t * ) pvPortMalloc( sizeof( *pxSocketSet ) );
\r
399 if( pxSocketSet != NULL )
\r
401 memset( pxSocketSet, '\0', sizeof( *pxSocketSet ) );
\r
402 pxSocketSet->xSelectGroup = xEventGroupCreate();
\r
404 if( pxSocketSet->xSelectGroup == NULL )
\r
406 vPortFree( ( void* ) pxSocketSet );
\r
407 pxSocketSet = NULL;
\r
411 return ( SocketSet_t * ) pxSocketSet;
\r
414 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
415 /*-----------------------------------------------------------*/
\r
417 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
419 void FreeRTOS_DeleteSocketSet( SocketSet_t xSocketSet )
\r
421 SocketSelect_t *pxSocketSet = ( SocketSelect_t*) xSocketSet;
\r
423 vEventGroupDelete( pxSocketSet->xSelectGroup );
\r
424 vPortFree( ( void* ) pxSocketSet );
\r
427 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
428 /*-----------------------------------------------------------*/
\r
430 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
432 /* Add a socket to a set */
\r
433 void FreeRTOS_FD_SET( Socket_t xSocket, SocketSet_t xSocketSet, EventBits_t xSelectBits )
\r
435 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
436 SocketSelect_t *pxSocketSet = ( SocketSelect_t * ) xSocketSet;
\r
438 configASSERT( pxSocket != NULL );
\r
439 configASSERT( xSocketSet != NULL );
\r
441 /* Make sure we're not adding bits which are reserved for internal use,
\r
442 such as eSELECT_CALL_IP */
\r
443 pxSocket->xSelectBits |= ( xSelectBits & eSELECT_ALL );
\r
445 if( ( pxSocket->xSelectBits & eSELECT_ALL ) != 0 )
\r
447 /* Adding a socket to a socket set. */
\r
448 pxSocket->pxSocketSet = ( SocketSelect_t * ) xSocketSet;
\r
450 /* Now have the IP-task call vSocketSelect() to see if the set contains
\r
451 any sockets which are 'ready' and set the proper bits.
\r
452 By setting 'bApiCalled = false', vSocketSelect() knows that it was
\r
453 not called from a user API */
\r
454 pxSocketSet->bApiCalled = pdFALSE;
\r
455 prvFindSelectedSocket( pxSocketSet );
\r
459 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
460 /*-----------------------------------------------------------*/
\r
462 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
463 /* Clear select bits for a socket
\r
464 If the mask becomes 0, remove the socket from the set */
\r
465 void FreeRTOS_FD_CLR( Socket_t xSocket, SocketSet_t xSocketSet, EventBits_t xSelectBits )
\r
467 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
469 configASSERT( pxSocket != NULL );
\r
470 configASSERT( xSocketSet != NULL );
\r
472 pxSocket->xSelectBits &= ~( xSelectBits & eSELECT_ALL );
\r
473 if( ( pxSocket->xSelectBits & eSELECT_ALL ) != 0 )
\r
475 pxSocket->pxSocketSet = ( SocketSelect_t *)xSocketSet;
\r
479 /* disconnect it from the socket set */
\r
480 pxSocket->pxSocketSet = ( SocketSelect_t *)NULL;
\r
484 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
485 /*-----------------------------------------------------------*/
\r
488 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
490 /* Test if a socket belongs to a socket-set */
\r
491 EventBits_t FreeRTOS_FD_ISSET( Socket_t xSocket, SocketSet_t xSocketSet )
\r
493 EventBits_t xReturn;
\r
494 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
496 configASSERT( pxSocket != NULL );
\r
497 configASSERT( xSocketSet != NULL );
\r
499 if( xSocketSet == ( SocketSet_t ) pxSocket->pxSocketSet )
\r
501 /* Make sure we're not adding bits which are reserved for internal
\r
503 xReturn = pxSocket->xSocketBits & eSELECT_ALL;
\r
513 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
514 /*-----------------------------------------------------------*/
\r
516 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
518 /* The select() statement: wait for an event to occur on any of the sockets
\r
519 included in a socket set */
\r
520 BaseType_t FreeRTOS_select( SocketSet_t xSocketSet, TickType_t xBlockTimeTicks )
\r
522 TimeOut_t xTimeOut;
\r
523 TickType_t xRemainingTime;
\r
524 SocketSelect_t *pxSocketSet = ( SocketSelect_t*) xSocketSet;
\r
525 BaseType_t xResult;
\r
527 configASSERT( xSocketSet != NULL );
\r
529 /* Only in the first round, check for non-blocking */
\r
530 xRemainingTime = xBlockTimeTicks;
\r
532 /* Fetch the current time */
\r
533 vTaskSetTimeOutState( &xTimeOut );
\r
537 /* Find a socket which might have triggered the bit
\r
538 This function might return immediately or block for a limited time */
\r
539 xResult = ( BaseType_t ) xEventGroupWaitBits( pxSocketSet->xSelectGroup, eSELECT_ALL, pdFALSE, pdFALSE, xRemainingTime );
\r
541 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
543 if( ( xResult & eSELECT_INTR ) != 0u )
\r
545 xEventGroupClearBits( pxSocketSet->xSelectGroup, eSELECT_INTR );
\r
546 FreeRTOS_debug_printf( ( "FreeRTOS_select: interrupted\n" ) );
\r
550 #endif /* ipconfigSUPPORT_SIGNALS */
\r
552 /* Have the IP-task find the socket which had an event */
\r
553 pxSocketSet->bApiCalled = pdTRUE;
\r
554 prvFindSelectedSocket( pxSocketSet );
\r
556 xResult = ( BaseType_t ) xEventGroupGetBits( pxSocketSet->xSelectGroup );
\r
563 /* Has the timeout been reached? */
\r
564 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
\r
573 #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
\r
574 /*-----------------------------------------------------------*/
\r
576 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
578 /* Send a message to the IP-task to have it check all sockets belonging to
\r
580 static FreeRTOS_Socket_t *prvFindSelectedSocket( SocketSelect_t *pxSocketSet )
\r
582 IPStackEvent_t xSelectEvent;
\r
583 FreeRTOS_Socket_t *xReturn;
\r
585 xSelectEvent.eEventType = eSocketSelectEvent;
\r
586 xSelectEvent.pvData = ( void * ) pxSocketSet;
\r
588 /* while the IP-task works on the request, the API will block on
\r
589 'eSELECT_CALL_IP'. So clear it first. */
\r
590 xEventGroupClearBits( pxSocketSet->xSelectGroup, eSELECT_CALL_IP );
\r
592 /* Now send the socket select event */
\r
593 if( xSendEventStructToIPTask( &xSelectEvent, ( TickType_t ) portMAX_DELAY ) == pdFAIL )
\r
595 /* Oops, we failed to wake-up the IP task. No use to wait for it. */
\r
596 FreeRTOS_debug_printf( ( "prvFindSelectedSocket: failed\n" ) );
\r
601 /* As soon as the IP-task is ready, it will set 'eSELECT_CALL_IP' to
\r
602 wakeup the calling API */
\r
603 xEventGroupWaitBits( pxSocketSet->xSelectGroup, eSELECT_CALL_IP, pdTRUE, pdFALSE, portMAX_DELAY );
\r
605 /* Return 'pxSocket' which is set by the IP-task */
\r
606 xReturn = pxSocketSet->pxSocket;
\r
612 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
613 /*-----------------------------------------------------------*/
\r
616 * FreeRTOS_recvfrom: receive data from a bound socket
\r
617 * In this library, the function can only be used with connectionsless sockets
\r
620 int32_t FreeRTOS_recvfrom( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags, struct freertos_sockaddr *pxSourceAddress, socklen_t *pxSourceAddressLength )
\r
622 BaseType_t lPacketCount = 0;
\r
623 NetworkBufferDescriptor_t *pxNetworkBuffer;
\r
624 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
625 TickType_t xRemainingTime = ( TickType_t ) 0; /* Obsolete assignment, but some compilers output a warning if its not done. */
\r
626 BaseType_t xTimed = pdFALSE;
\r
627 TimeOut_t xTimeOut;
\r
629 EventBits_t xEventBits = ( EventBits_t ) 0;
\r
631 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_UDP, pdTRUE ) == pdFALSE )
\r
633 return -pdFREERTOS_ERRNO_EINVAL;
\r
636 lPacketCount = ( BaseType_t ) listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
\r
638 /* The function prototype is designed to maintain the expected Berkeley
\r
639 sockets standard, but this implementation does not use all the parameters. */
\r
640 ( void ) pxSourceAddressLength;
\r
642 while( lPacketCount == 0 )
\r
644 if( xTimed == pdFALSE )
\r
646 /* Check to see if the socket is non blocking on the first
\r
648 xRemainingTime = pxSocket->xReceiveBlockTime;
\r
650 if( xRemainingTime == ( TickType_t ) 0 )
\r
652 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
654 /* Just check for the interrupt flag. */
\r
655 xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_INTR,
\r
656 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, socketDONT_BLOCK );
\r
658 #endif /* ipconfigSUPPORT_SIGNALS */
\r
662 if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
\r
667 /* To ensure this part only executes once. */
\r
670 /* Fetch the current time. */
\r
671 vTaskSetTimeOutState( &xTimeOut );
\r
674 /* Wait for arrival of data. While waiting, the IP-task may set the
\r
675 'eSOCKET_RECEIVE' bit in 'xEventGroup', if it receives data for this
\r
676 socket, thus unblocking this API call. */
\r
677 xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_RECEIVE | eSOCKET_INTR,
\r
678 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
680 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
682 if( ( xEventBits & eSOCKET_INTR ) != 0 )
\r
684 if( ( xEventBits & eSOCKET_RECEIVE ) != 0 )
\r
686 /* Shouldn't have cleared the eSOCKET_RECEIVE flag. */
\r
687 xEventGroupSetBits( pxSocket->xEventGroup, eSOCKET_RECEIVE );
\r
694 ( void ) xEventBits;
\r
696 #endif /* ipconfigSUPPORT_SIGNALS */
\r
698 lPacketCount = ( BaseType_t ) listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
\r
700 if( lPacketCount != 0 )
\r
705 /* Has the timeout been reached ? */
\r
706 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) )
\r
710 } /* while( lPacketCount == 0 ) */
\r
712 if( lPacketCount != 0 )
\r
714 taskENTER_CRITICAL();
\r
716 /* The owner of the list item is the network buffer. */
\r
717 pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
\r
719 if( ( xFlags & FREERTOS_MSG_PEEK ) == 0 )
\r
721 /* Remove the network buffer from the list of buffers waiting to
\r
722 be processed by the socket. */
\r
723 uxListRemove( &( pxNetworkBuffer->xBufferListItem ) );
\r
726 taskEXIT_CRITICAL();
\r
728 /* The returned value is the data length, which may have been capped to
\r
729 the receive buffer size. */
\r
730 lReturn = ( int32_t ) pxNetworkBuffer->xDataLength;
\r
732 if( pxSourceAddress != NULL )
\r
734 pxSourceAddress->sin_port = pxNetworkBuffer->usPort;
\r
735 pxSourceAddress->sin_addr = pxNetworkBuffer->ulIPAddress;
\r
738 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
\r
740 /* The zero copy flag is not set. Truncate the length if it won't
\r
741 fit in the provided buffer. */
\r
742 if( lReturn > ( int32_t ) xBufferLength )
\r
744 iptraceRECVFROM_DISCARDING_BYTES( ( xBufferLength - lReturn ) );
\r
745 lReturn = ( int32_t )xBufferLength;
\r
748 /* Copy the received data into the provided buffer, then release the
\r
750 memcpy( pvBuffer, ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ), ( size_t )lReturn );
\r
752 if( ( xFlags & FREERTOS_MSG_PEEK ) == 0 )
\r
754 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
\r
759 /* The zero copy flag was set. pvBuffer is not a buffer into which
\r
760 the received data can be copied, but a pointer that must be set to
\r
761 point to the buffer in which the received data has already been
\r
763 *( ( void** ) pvBuffer ) = ( void * ) ( &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ) );
\r
767 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
768 else if( ( xEventBits & eSOCKET_INTR ) != 0 )
\r
770 lReturn = -pdFREERTOS_ERRNO_EINTR;
\r
771 iptraceRECVFROM_INTERRUPTED();
\r
773 #endif /* ipconfigSUPPORT_SIGNALS */
\r
776 lReturn = -pdFREERTOS_ERRNO_EWOULDBLOCK;
\r
777 iptraceRECVFROM_TIMEOUT();
\r
782 /*-----------------------------------------------------------*/
\r
784 int32_t FreeRTOS_sendto( Socket_t xSocket, const void *pvBuffer, size_t xTotalDataLength, BaseType_t xFlags, const struct freertos_sockaddr *pxDestinationAddress, socklen_t xDestinationAddressLength )
\r
786 NetworkBufferDescriptor_t *pxNetworkBuffer;
\r
787 IPStackEvent_t xStackTxEvent = { eStackTxEvent, NULL };
\r
788 TimeOut_t xTimeOut;
\r
789 TickType_t xTicksToWait;
\r
790 int32_t lReturn = 0;
\r
791 FreeRTOS_Socket_t *pxSocket;
\r
793 pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
795 /* The function prototype is designed to maintain the expected Berkeley
\r
796 sockets standard, but this implementation does not use all the
\r
798 ( void ) xDestinationAddressLength;
\r
799 configASSERT( pvBuffer );
\r
801 if( xTotalDataLength <= ( size_t ) ipMAX_UDP_PAYLOAD_LENGTH )
\r
803 /* If the socket is not already bound to an address, bind it now.
\r
804 Passing NULL as the address parameter tells FreeRTOS_bind() to select
\r
805 the address to bind to. */
\r
806 if( ( socketSOCKET_IS_BOUND( pxSocket ) != pdFALSE ) ||
\r
807 ( FreeRTOS_bind( xSocket, NULL, 0u ) == 0 ) )
\r
809 xTicksToWait = pxSocket->xSendBlockTime;
\r
811 #if( ipconfigUSE_CALLBACKS != 0 )
\r
813 if( xIsCallingFromIPTask() != pdFALSE )
\r
815 /* If this send function is called from within a call-back
\r
816 handler it may not block, otherwise chances would be big to
\r
817 get a deadlock: the IP-task waiting for itself. */
\r
818 xTicksToWait = ( TickType_t )0;
\r
821 #endif /* ipconfigUSE_CALLBACKS */
\r
823 if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
\r
825 xTicksToWait = ( TickType_t ) 0;
\r
828 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
\r
830 /* Zero copy is not set, so obtain a network buffer into
\r
831 which the payload will be copied. */
\r
832 vTaskSetTimeOutState( &xTimeOut );
\r
834 /* Block until a buffer becomes available, or until a
\r
835 timeout has been reached */
\r
836 pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( xTotalDataLength + sizeof( UDPPacket_t ), xTicksToWait );
\r
838 if( pxNetworkBuffer != NULL )
\r
840 memcpy( ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ), ( void * ) pvBuffer, xTotalDataLength );
\r
842 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdTRUE )
\r
844 /* The entire block time has been used up. */
\r
845 xTicksToWait = ( TickType_t ) 0;
\r
851 /* When zero copy is used, pvBuffer is a pointer to the
\r
852 payload of a buffer that has already been obtained from the
\r
853 stack. Obtain the network buffer pointer from the buffer. */
\r
854 pxNetworkBuffer = pxUDPPayloadBuffer_to_NetworkBuffer( (void*)pvBuffer );
\r
857 if( pxNetworkBuffer != NULL )
\r
859 pxNetworkBuffer->xDataLength = xTotalDataLength;
\r
860 pxNetworkBuffer->usPort = pxDestinationAddress->sin_port;
\r
861 pxNetworkBuffer->usBoundPort = ( uint16_t ) socketGET_SOCKET_PORT( pxSocket );
\r
862 pxNetworkBuffer->ulIPAddress = pxDestinationAddress->sin_addr;
\r
864 /* The socket options are passed to the IP layer in the
\r
865 space that will eventually get used by the Ethernet header. */
\r
866 pxNetworkBuffer->pucEthernetBuffer[ ipSOCKET_OPTIONS_OFFSET ] = pxSocket->ucSocketOptions;
\r
868 /* Tell the networking task that the packet needs sending. */
\r
869 xStackTxEvent.pvData = pxNetworkBuffer;
\r
871 /* Ask the IP-task to send this packet */
\r
872 if( xSendEventStructToIPTask( &xStackTxEvent, xTicksToWait ) == pdPASS )
\r
874 /* The packet was successfully sent to the IP task. */
\r
875 lReturn = ( int32_t ) xTotalDataLength;
\r
876 #if( ipconfigUSE_CALLBACKS == 1 )
\r
878 if( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xUDP.pxHandleSent ) )
\r
880 pxSocket->u.xUDP.pxHandleSent( (Socket_t *)pxSocket, xTotalDataLength );
\r
883 #endif /* ipconfigUSE_CALLBACKS */
\r
887 /* If the buffer was allocated in this function, release
\r
889 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
\r
891 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
\r
893 iptraceSTACK_TX_EVENT_LOST( ipSTACK_TX_EVENT );
\r
898 /* If errno was available, errno would be set to
\r
899 FREERTOS_ENOPKTS. As it is, the function must return the
\r
900 number of transmitted bytes, so the calling function knows
\r
901 how much data was actually sent. */
\r
902 iptraceNO_BUFFER_FOR_SENDTO();
\r
907 iptraceSENDTO_SOCKET_NOT_BOUND();
\r
912 /* The data is longer than the available buffer space. */
\r
913 iptraceSENDTO_DATA_TOO_LONG();
\r
918 /*-----------------------------------------------------------*/
\r
921 * FreeRTOS_bind() : binds a sockt to a local port number. If port 0 is
\r
922 * provided, a system provided port number will be assigned. This function can
\r
923 * be used for both UDP and TCP sockets. The actual binding will be performed
\r
924 * by the IP-task to avoid mutual access to the bound-socket-lists
\r
925 * (xBoundUDPSocketsList or xBoundTCPSocketsList).
\r
927 BaseType_t FreeRTOS_bind( Socket_t xSocket, struct freertos_sockaddr * pxAddress, socklen_t xAddressLength )
\r
929 IPStackEvent_t xBindEvent;
\r
930 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
931 BaseType_t xReturn = 0;
\r
933 ( void ) xAddressLength;
\r
935 if( ( pxSocket == NULL ) || ( pxSocket == FREERTOS_INVALID_SOCKET ) )
\r
937 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
939 /* Once a socket is bound to a port, it can not be bound to a different
\r
941 else if( socketSOCKET_IS_BOUND( pxSocket) != pdFALSE )
\r
943 /* The socket is already bound. */
\r
944 FreeRTOS_debug_printf( ( "vSocketBind: Socket already bound to %d\n", pxSocket->usLocalPort ) );
\r
945 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
949 /* Prepare a messages to the IP-task in order to perform the binding.
\r
950 The desired port number will be passed in usLocalPort. */
\r
951 xBindEvent.eEventType = eSocketBindEvent;
\r
952 xBindEvent.pvData = ( void * ) xSocket;
\r
953 if( pxAddress != NULL )
\r
955 pxSocket->usLocalPort = FreeRTOS_ntohs( pxAddress->sin_port );
\r
959 /* Caller wants to bind to a random port number. */
\r
960 pxSocket->usLocalPort = 0u;
\r
963 /* portMAX_DELAY is used as a the time-out parameter, as binding *must*
\r
964 succeed before the socket can be used. _RB_ The use of an infinite
\r
965 block time needs be changed as it could result in the task hanging. */
\r
966 if( xSendEventStructToIPTask( &xBindEvent, ( TickType_t ) portMAX_DELAY ) == pdFAIL )
\r
968 /* Failed to wake-up the IP-task, no use to wait for it */
\r
969 FreeRTOS_debug_printf( ( "FreeRTOS_bind: send event failed\n" ) );
\r
970 xReturn = -pdFREERTOS_ERRNO_ECANCELED;
\r
974 /* The IP-task will set the 'eSOCKET_BOUND' bit when it has done its
\r
976 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_BOUND, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, portMAX_DELAY );
\r
977 if( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE )
\r
979 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
988 * vSocketBind(): internal version of bind() that should not be called directly.
\r
989 * 'xInternal' is used for TCP sockets only: it allows to have several
\r
990 * (connected) child sockets bound to the same server port.
\r
992 BaseType_t vSocketBind( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr * pxAddress, size_t uxAddressLength, BaseType_t xInternal )
\r
994 BaseType_t xReturn = 0; /* In Berkeley sockets, 0 means pass for bind(). */
\r
995 List_t *pxSocketList;
\r
996 #if( ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 )
\r
997 struct freertos_sockaddr xAddress;
\r
998 #endif /* ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND */
\r
1000 #if( ipconfigUSE_TCP == 1 )
\r
1001 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1003 pxSocketList = &xBoundTCPSocketsList;
\r
1006 #endif /* ipconfigUSE_TCP == 1 */
\r
1008 pxSocketList = &xBoundUDPSocketsList;
\r
1011 /* The function prototype is designed to maintain the expected Berkeley
\r
1012 sockets standard, but this implementation does not use all the parameters. */
\r
1013 ( void ) uxAddressLength;
\r
1015 configASSERT( pxSocket );
\r
1016 configASSERT( pxSocket != FREERTOS_INVALID_SOCKET );
\r
1018 #if( ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 )
\r
1020 /* pxAddress will be NULL if sendto() was called on a socket without the
\r
1021 socket being bound to an address. In this case, automatically allocate
\r
1022 an address to the socket. There is a very tiny chance that the allocated
\r
1023 port will already be in use - if that is the case, then the check below
\r
1024 [pxListFindListItemWithValue()] will result in an error being returned. */
\r
1025 if( pxAddress == NULL )
\r
1027 pxAddress = &xAddress;
\r
1028 /* For now, put it to zero, will be assigned later */
\r
1029 pxAddress->sin_port = 0u;
\r
1032 #endif /* ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 */
\r
1034 /* Sockets must be bound before calling FreeRTOS_sendto() if
\r
1035 ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is not set to 1. */
\r
1036 configASSERT( pxAddress );
\r
1038 if( pxAddress != NULL )
\r
1040 if( pxAddress->sin_port == 0u )
\r
1042 pxAddress->sin_port = prvGetPrivatePortNumber( ( BaseType_t ) pxSocket->ucProtocol );
\r
1045 /* If vSocketBind() is called from the API FreeRTOS_bind() it has been
\r
1046 confirmed that the socket was not yet bound to a port. If it is called
\r
1047 from the IP-task, no such check is necessary. */
\r
1049 /* Check to ensure the port is not already in use. If the bind is
\r
1050 called internally, a port MAY be used by more than one socket. */
\r
1051 if( ( ( xInternal == pdFALSE ) || ( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP ) ) &&
\r
1052 ( pxListFindListItemWithValue( pxSocketList, ( TickType_t ) pxAddress->sin_port ) != NULL ) )
\r
1054 FreeRTOS_debug_printf( ( "vSocketBind: %sP port %d in use\n",
\r
1055 pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP ? "TC" : "UD",
\r
1056 FreeRTOS_ntohs( pxAddress->sin_port ) ) );
\r
1057 xReturn = -pdFREERTOS_ERRNO_EADDRINUSE;
\r
1061 /* Allocate the port number to the socket.
\r
1062 This macro will set 'xBoundSocketListItem->xItemValue' */
\r
1063 socketSET_SOCKET_PORT( pxSocket, pxAddress->sin_port );
\r
1065 /* And also store it in a socket field 'usLocalPort' in host-byte-order,
\r
1066 mostly used for logging and debugging purposes */
\r
1067 pxSocket->usLocalPort = FreeRTOS_ntohs( pxAddress->sin_port );
\r
1069 /* Add the socket to the list of bound ports. */
\r
1071 /* If the network driver can iterate through 'xBoundUDPSocketsList',
\r
1072 by calling xPortHasUDPSocket() then the IP-task must temporarily
\r
1073 suspend the scheduler to keep the list in a consistent state. */
\r
1074 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1076 vTaskSuspendAll();
\r
1078 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1080 /* Add the socket to 'xBoundUDPSocketsList' or 'xBoundTCPSocketsList' */
\r
1081 vListInsertEnd( pxSocketList, &( pxSocket->xBoundSocketListItem ) );
\r
1083 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1087 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1093 xReturn = -pdFREERTOS_ERRNO_EADDRNOTAVAIL;
\r
1094 FreeRTOS_debug_printf( ( "vSocketBind: Socket no addr\n" ) );
\r
1097 if( xReturn != 0 )
\r
1099 iptraceBIND_FAILED( xSocket, ( FreeRTOS_ntohs( pxAddress->sin_port ) ) );
\r
1104 /*-----------------------------------------------------------*/
\r
1107 * Close a socket and free the allocated space
\r
1108 * In case of a TCP socket: the connection will not be closed automatically
\r
1109 * Subsequent messages for the closed socket will be responded to with a RST
\r
1110 * The IP-task will actually close the socket, after receiving a 'eSocketCloseEvent' message
\r
1112 BaseType_t FreeRTOS_closesocket( Socket_t xSocket )
\r
1114 BaseType_t xResult;
\r
1115 #if( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 )
\r
1116 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * )xSocket;
\r
1118 IPStackEvent_t xCloseEvent;
\r
1119 xCloseEvent.eEventType = eSocketCloseEvent;
\r
1120 xCloseEvent.pvData = ( void * ) xSocket;
\r
1122 if( ( xSocket == NULL ) || ( xSocket == FREERTOS_INVALID_SOCKET ) )
\r
1128 #if( ( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 ) )
\r
1130 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1132 /* Make sure that IP-task won't call the user callback's anymore */
\r
1133 pxSocket->u.xTCP.pxHandleConnected = NULL;
\r
1134 pxSocket->u.xTCP.pxHandleReceive = NULL;
\r
1135 pxSocket->u.xTCP.pxHandleSent = NULL;
\r
1138 #endif /* ( ( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 ) ) */
\r
1140 /* Let the IP task close the socket to keep it synchronised with the
\r
1141 packet handling. */
\r
1143 /* Note when changing the time-out value below, it must be checked who is calling
\r
1144 this function. If it is called by the IP-task, a deadlock could occur.
\r
1145 The IP-task would only call it in case of a user call-back */
\r
1146 if( xSendEventStructToIPTask( &xCloseEvent, ( TickType_t ) 0 ) == pdFAIL )
\r
1148 FreeRTOS_debug_printf( ( "FreeRTOS_closesocket: failed\n" ) );
\r
1160 /* This is the internal version of FreeRTOS_closesocket()
\r
1161 * It will be called by the IPtask only to avoid problems with synchronicity
\r
1163 void *vSocketClose( FreeRTOS_Socket_t *pxSocket )
\r
1165 NetworkBufferDescriptor_t *pxNetworkBuffer;
\r
1167 #if( ipconfigUSE_TCP == 1 )
\r
1169 /* For TCP: clean up a little more. */
\r
1170 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1172 #if( ipconfigUSE_TCP_WIN == 1 )
\r
1174 if( pxSocket->u.xTCP.pxAckMessage != NULL )
\r
1176 vReleaseNetworkBufferAndDescriptor( pxSocket->u.xTCP.pxAckMessage );
\r
1178 /* Free the resources which were claimed by the tcpWin member */
\r
1179 vTCPWindowDestroy( &pxSocket->u.xTCP.xTCPWindow );
\r
1181 #endif /* ipconfigUSE_TCP_WIN */
\r
1183 /* Free the input and output streams */
\r
1184 if( pxSocket->u.xTCP.rxStream != NULL )
\r
1186 vPortFreeLarge( pxSocket->u.xTCP.rxStream );
\r
1189 if( pxSocket->u.xTCP.txStream != NULL )
\r
1191 vPortFreeLarge( pxSocket->u.xTCP.txStream );
\r
1194 /* In case this is a child socket, make sure the child-count of the
\r
1195 parent socket is decreased. */
\r
1196 prvTCPSetSocketCount( pxSocket );
\r
1199 #endif /* ipconfigUSE_TCP == 1 */
\r
1201 /* Socket must be unbound first, to ensure no more packets are queued on
\r
1203 if( socketSOCKET_IS_BOUND( pxSocket ) != pdFALSE )
\r
1205 /* If the network driver can iterate through 'xBoundUDPSocketsList',
\r
1206 by calling xPortHasUDPSocket(), then the IP-task must temporarily
\r
1207 suspend the scheduler to keep the list in a consistent state. */
\r
1208 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1210 vTaskSuspendAll();
\r
1212 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1214 uxListRemove( &( pxSocket->xBoundSocketListItem ) );
\r
1216 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1220 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1223 /* Now the socket is not bound the list of waiting packets can be
\r
1225 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_UDP )
\r
1227 while( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) > 0U )
\r
1229 pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
\r
1230 uxListRemove( &( pxNetworkBuffer->xBufferListItem ) );
\r
1231 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
\r
1235 if( pxSocket->xEventGroup )
\r
1237 vEventGroupDelete( pxSocket->xEventGroup );
\r
1240 #if( ipconfigUSE_TCP == 1 ) && ( ipconfigHAS_DEBUG_PRINTF != 0 )
\r
1242 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1244 FreeRTOS_debug_printf( ( "FreeRTOS_closesocket[%u to %lxip:%u]: buffers %lu socks %lu\n",
\r
1245 pxSocket->usLocalPort,
\r
1246 pxSocket->u.xTCP.ulRemoteIP,
\r
1247 pxSocket->u.xTCP.usRemotePort,
\r
1248 uxGetNumberOfFreeNetworkBuffers(),
\r
1249 listCURRENT_LIST_LENGTH( &xBoundTCPSocketsList ) ) );
\r
1252 #endif /* ( ipconfigUSE_TCP == 1 ) && ( ipconfigHAS_DEBUG_PRINTF != 0 ) */
\r
1254 /* Anf finally, after all resources have been freed, free the socket space */
\r
1255 vPortFreeSocket( pxSocket );
\r
1260 /*-----------------------------------------------------------*/
\r
1262 #if ipconfigUSE_TCP == 1
\r
1265 * When a child socket gets closed, make sure to update the child-count of the
\r
1266 * parent. When a listening parent socket is closed, make sure no child-sockets
\r
1267 * keep a pointer to it.
\r
1269 static void prvTCPSetSocketCount( FreeRTOS_Socket_t *pxSocketToDelete )
\r
1271 const ListItem_t *pxIterator;
\r
1272 const MiniListItem_t *pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );
\r
1273 FreeRTOS_Socket_t *pxOtherSocket;
\r
1274 uint16_t usLocalPort = pxSocketToDelete->usLocalPort;
\r
1276 for( pxIterator = ( const ListItem_t * ) listGET_NEXT( pxEnd );
\r
1277 pxIterator != ( const ListItem_t * ) pxEnd;
\r
1278 pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
1280 pxOtherSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
\r
1281 if( ( pxOtherSocket->u.xTCP.ucTCPState == eTCP_LISTEN ) &&
\r
1282 ( pxOtherSocket->usLocalPort == usLocalPort ) &&
\r
1283 ( pxOtherSocket->u.xTCP.usChildCount ) )
\r
1285 pxOtherSocket->u.xTCP.usChildCount--;
\r
1286 FreeRTOS_debug_printf( ( "Lost: Socket %u now has %u / %u child%s\n",
\r
1287 pxOtherSocket->usLocalPort,
\r
1288 pxOtherSocket->u.xTCP.usChildCount,
\r
1289 pxOtherSocket->u.xTCP.usBacklog,
\r
1290 pxOtherSocket->u.xTCP.usChildCount == 1u ? "" : "ren" ) );
\r
1296 #endif /* ipconfigUSE_TCP == 1 */
\r
1298 /*-----------------------------------------------------------*/
\r
1300 BaseType_t FreeRTOS_setsockopt( Socket_t xSocket, int32_t lLevel, int32_t lOptionName, const void *pvOptionValue, size_t xOptionLength )
\r
1302 /* The standard Berkeley function returns 0 for success. */
\r
1303 BaseType_t xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
1304 BaseType_t lOptionValue;
\r
1305 FreeRTOS_Socket_t *pxSocket;
\r
1307 pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
1309 /* The function prototype is designed to maintain the expected Berkeley
\r
1310 sockets standard, but this implementation does not use all the parameters. */
\r
1312 ( void ) xOptionLength;
\r
1314 configASSERT( xSocket );
\r
1316 switch( lOptionName )
\r
1318 case FREERTOS_SO_RCVTIMEO :
\r
1319 /* Receive time out. */
\r
1320 pxSocket->xReceiveBlockTime = *( ( TickType_t * ) pvOptionValue );
\r
1324 case FREERTOS_SO_SNDTIMEO :
\r
1325 pxSocket->xSendBlockTime = *( ( TickType_t * ) pvOptionValue );
\r
1326 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_UDP )
\r
1328 /* The send time out is capped for the reason stated in the
\r
1329 comments where ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS is defined
\r
1330 in FreeRTOSIPConfig.h (assuming an official configuration file
\r
1332 if( pxSocket->xSendBlockTime > ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS )
\r
1334 pxSocket->xSendBlockTime = ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS;
\r
1339 /* For TCP socket, it isn't necessary to limit the blocking time
\r
1340 because the FreeRTOS_send() function does not wait for a network
\r
1341 buffer to become available. */
\r
1345 #if( ipconfigUDP_MAX_RX_PACKETS > 0 )
\r
1346 case FREERTOS_SO_UDP_MAX_RX_PACKETS:
\r
1347 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_UDP )
\r
1349 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1351 pxSocket->u.xUDP.uxMaxPackets = *( ( UBaseType_t * ) pvOptionValue );
\r
1354 #endif /* ipconfigUDP_MAX_RX_PACKETS */
\r
1356 case FREERTOS_SO_UDPCKSUM_OUT :
\r
1357 /* Turn calculating of the UDP checksum on/off for this socket. */
\r
1358 lOptionValue = ( BaseType_t ) pvOptionValue;
\r
1360 if( lOptionValue == 0 )
\r
1362 pxSocket->ucSocketOptions &= ( uint8_t ) ~FREERTOS_SO_UDPCKSUM_OUT;
\r
1366 pxSocket->ucSocketOptions |= ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT;
\r
1371 #if( ipconfigUSE_CALLBACKS == 1 )
\r
1372 #if( ipconfigUSE_TCP == 1 )
\r
1373 case FREERTOS_SO_TCP_CONN_HANDLER: /* Set a callback for (dis)connection events */
\r
1374 case FREERTOS_SO_TCP_RECV_HANDLER: /* Install a callback for receiving TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
\r
1375 case FREERTOS_SO_TCP_SENT_HANDLER: /* Install a callback for sending TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
\r
1376 #endif /* ipconfigUSE_TCP */
\r
1377 case FREERTOS_SO_UDP_RECV_HANDLER: /* Install a callback for receiving UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
\r
1378 case FREERTOS_SO_UDP_SENT_HANDLER: /* Install a callback for sending UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
\r
1380 #if( ipconfigUSE_TCP == 1 )
\r
1382 UBaseType_t uxProtocol;
\r
1383 if( ( lOptionName == FREERTOS_SO_UDP_RECV_HANDLER ) ||
\r
1384 ( lOptionName == FREERTOS_SO_UDP_SENT_HANDLER ) )
\r
1386 uxProtocol = ( UBaseType_t ) FREERTOS_IPPROTO_UDP;
\r
1390 uxProtocol = ( UBaseType_t ) FREERTOS_IPPROTO_TCP;
\r
1393 if( pxSocket->ucProtocol != ( uint8_t ) uxProtocol )
\r
1395 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1400 /* No need to check if the socket has the right
\r
1401 protocol, because only UDP socket can be created. */
\r
1403 #endif /* ipconfigUSE_TCP */
\r
1405 switch( lOptionName )
\r
1407 #if ipconfigUSE_TCP == 1
\r
1408 case FREERTOS_SO_TCP_CONN_HANDLER:
\r
1409 pxSocket->u.xTCP.pxHandleConnected = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPConnected;
\r
1411 case FREERTOS_SO_TCP_RECV_HANDLER:
\r
1412 pxSocket->u.xTCP.pxHandleReceive = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPReceive;
\r
1414 case FREERTOS_SO_TCP_SENT_HANDLER:
\r
1415 pxSocket->u.xTCP.pxHandleSent = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPSent;
\r
1417 #endif /* ipconfigUSE_TCP */
\r
1418 case FREERTOS_SO_UDP_RECV_HANDLER:
\r
1419 pxSocket->u.xUDP.pxHandleReceive = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnUDPReceive;
\r
1421 case FREERTOS_SO_UDP_SENT_HANDLER:
\r
1422 pxSocket->u.xUDP.pxHandleSent = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnUDPSent;
\r
1431 #endif /* ipconfigUSE_CALLBACKS */
\r
1433 #if( ipconfigUSE_TCP != 0 )
\r
1434 #if( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 )
\r
1435 /* Each socket has a semaphore on which the using task normally
\r
1437 case FREERTOS_SO_SET_SEMAPHORE:
\r
1439 pxSocket->pxUserSemaphore = *( ( SemaphoreHandle_t * ) pvOptionValue );
\r
1443 #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
\r
1445 #if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK != 0 )
\r
1446 case FREERTOS_SO_WAKEUP_CALLBACK:
\r
1448 /* Each socket can have a callback function that is executed
\r
1449 when there is an event the socket's owner might want to
\r
1451 pxSocket->pxUserWakeCallback = ( SocketWakeupCallback_t ) pvOptionValue;
\r
1455 #endif /* ipconfigSOCKET_HAS_USER_WAKE_CALLBACK */
\r
1457 case FREERTOS_SO_SNDBUF: /* Set the size of the send buffer, in units of MSS (TCP only) */
\r
1458 case FREERTOS_SO_RCVBUF: /* Set the size of the receive buffer, in units of MSS (TCP only) */
\r
1460 uint32_t ulNewValue;
\r
1462 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1464 FreeRTOS_debug_printf( ( "Set SO_%sBUF: wrong socket type\n",
\r
1465 ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );
\r
1466 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1469 if( ( ( lOptionName == FREERTOS_SO_SNDBUF ) && ( pxSocket->u.xTCP.txStream != NULL ) ) ||
\r
1470 ( ( lOptionName == FREERTOS_SO_RCVBUF ) && ( pxSocket->u.xTCP.rxStream != NULL ) ) )
\r
1472 FreeRTOS_debug_printf( ( "Set SO_%sBUF: buffer already created\n",
\r
1473 ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );
\r
1474 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1477 ulNewValue = *( ( uint32_t * ) pvOptionValue );
\r
1479 if( lOptionName == FREERTOS_SO_SNDBUF )
\r
1481 /* Round up to nearest MSS size */
\r
1482 ulNewValue = FreeRTOS_round_up( ulNewValue, ( uint32_t ) pxSocket->u.xTCP.usInitMSS );
\r
1483 pxSocket->u.xTCP.uxTxStreamSize = ulNewValue;
\r
1487 pxSocket->u.xTCP.uxRxStreamSize = ulNewValue;
\r
1493 case FREERTOS_SO_WIN_PROPERTIES: /* Set all buffer and window properties in one call, parameter is pointer to WinProperties_t */
\r
1495 WinProperties_t* pxProps;
\r
1497 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1499 FreeRTOS_debug_printf( ( "Set SO_WIN_PROP: wrong socket type\n" ) );
\r
1500 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1503 if( ( pxSocket->u.xTCP.txStream != NULL ) || ( pxSocket->u.xTCP.rxStream != NULL ) )
\r
1505 FreeRTOS_debug_printf( ( "Set SO_WIN_PROP: buffer already created\n" ) );
\r
1506 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1509 pxProps = ( ( WinProperties_t * ) pvOptionValue );
\r
1510 FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDBUF, &( pxProps->lTxBufSize ), sizeof( pxProps->lTxBufSize ) );
\r
1511 FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVBUF, &( pxProps->lRxBufSize ), sizeof( pxProps->lRxBufSize ) );
\r
1512 #if( ipconfigUSE_TCP_WIN == 1 )
\r
1514 pxSocket->u.xTCP.uxRxWinSize = ( uint32_t )pxProps->lRxWinSize; /* Fixed value: size of the TCP reception window */
\r
1515 pxSocket->u.xTCP.uxTxWinSize = ( uint32_t )pxProps->lTxWinSize; /* Fixed value: size of the TCP transmit window */
\r
1519 pxSocket->u.xTCP.uxRxWinSize = 1u;
\r
1520 pxSocket->u.xTCP.uxTxWinSize = 1u;
\r
1524 /* In case the socket has already initialised its tcpWin,
\r
1525 adapt the window size parameters */
\r
1526 if( pxSocket->u.xTCP.xTCPWindow.u.bits.bHasInit != pdFALSE_UNSIGNED )
\r
1528 pxSocket->u.xTCP.xTCPWindow.xSize.ulRxWindowLength = pxSocket->u.xTCP.uxRxWinSize * pxSocket->u.xTCP.usInitMSS;
\r
1529 pxSocket->u.xTCP.xTCPWindow.xSize.ulRxWindowLength = pxSocket->u.xTCP.uxTxWinSize * pxSocket->u.xTCP.usInitMSS;
\r
1536 case FREERTOS_SO_REUSE_LISTEN_SOCKET: /* If true, the server-socket will turn into a connected socket */
\r
1538 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1540 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1542 if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
\r
1544 pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE_UNSIGNED;
\r
1548 pxSocket->u.xTCP.bits.bReuseSocket = pdFALSE_UNSIGNED;
\r
1554 case FREERTOS_SO_CLOSE_AFTER_SEND: /* As soon as the last byte has been transmitted, finalise the connection */
\r
1556 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1558 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1561 if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
\r
1563 pxSocket->u.xTCP.bits.bCloseAfterSend = pdTRUE_UNSIGNED;
\r
1567 pxSocket->u.xTCP.bits.bCloseAfterSend = pdFALSE_UNSIGNED;
\r
1573 case FREERTOS_SO_SET_FULL_SIZE: /* Refuse to send packets smaller than MSS */
\r
1575 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1577 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1580 if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
\r
1582 pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdTRUE_UNSIGNED;
\r
1586 pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdFALSE_UNSIGNED;
\r
1589 if( ( pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize == pdFALSE_UNSIGNED ) &&
\r
1590 ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) &&
\r
1591 ( FreeRTOS_outstanding( pxSocket ) != 0 ) )
\r
1593 pxSocket->u.xTCP.usTimeout = 1u; /* to set/clear bSendFullSize */
\r
1594 xSendEventToIPTask( eTCPTimerEvent );
\r
1600 case FREERTOS_SO_STOP_RX: /* Refuse to receive more packts */
\r
1602 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1604 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1607 if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
\r
1609 pxSocket->u.xTCP.bits.bRxStopped = pdTRUE_UNSIGNED;
\r
1613 pxSocket->u.xTCP.bits.bRxStopped = pdFALSE_UNSIGNED;
\r
1616 pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
\r
1617 pxSocket->u.xTCP.usTimeout = 1u; /* to set/clear bRxStopped */
\r
1618 xSendEventToIPTask( eTCPTimerEvent );
\r
1623 #endif /* ipconfigUSE_TCP == 1 */
\r
1626 /* No other options are handled. */
\r
1627 xReturn = -pdFREERTOS_ERRNO_ENOPROTOOPT;
\r
1634 /*-----------------------------------------------------------*/
\r
1636 /* Get a free private ('anonymous') port number */
\r
1637 static uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol )
\r
1639 uint16_t usResult;
\r
1640 BaseType_t xIndex;
\r
1641 const List_t *pxList;
\r
1643 #if ipconfigUSE_TCP == 1
\r
1644 if( xProtocol == ( BaseType_t ) FREERTOS_IPPROTO_TCP )
\r
1646 xIndex = socketNEXT_TCP_PORT_NUMBER_INDEX;
\r
1647 pxList = &xBoundTCPSocketsList;
\r
1652 xIndex = socketNEXT_UDP_PORT_NUMBER_INDEX;
\r
1653 pxList = &xBoundUDPSocketsList;
\r
1656 /* Avoid compiler warnings if ipconfigUSE_TCP is not defined. */
\r
1657 ( void ) xProtocol;
\r
1659 /* Assign the next port in the range. Has it overflowed? */
\r
1660 /*_RB_ This needs to be randomised rather than sequential. */
\r
1661 /* _HT_ Agreed, although many OS's use sequential port numbers, see
\r
1662 https://www.cymru.com/jtk/misc/ephemeralports.html */
\r
1665 ++( usNextPortToUse[ xIndex ] );
\r
1667 if( usNextPortToUse[ xIndex ] >= socketAUTO_PORT_ALLOCATION_MAX_NUMBER )
\r
1669 /* Don't go right back to the start of the dynamic/private port
\r
1670 range numbers as any persistent sockets are likely to have been
\r
1671 create first so the early port numbers may still be in use. */
\r
1672 usNextPortToUse[ xIndex ] = socketAUTO_PORT_ALLOCATION_RESET_NUMBER;
\r
1675 usResult = FreeRTOS_htons( usNextPortToUse[ xIndex ] );
\r
1677 if( pxListFindListItemWithValue( pxList, ( TickType_t ) usResult ) == NULL )
\r
1684 /*-----------------------------------------------------------*/
\r
1686 /* pxListFindListItemWithValue: find a list item in a bound socket list
\r
1687 'xWantedItemValue' refers to a port number */
\r
1688 static const ListItem_t * pxListFindListItemWithValue( const List_t *pxList, TickType_t xWantedItemValue )
\r
1690 const ListItem_t * pxResult = NULL;
\r
1692 if( ( xIPIsNetworkTaskReady() != pdFALSE ) && ( pxList != NULL ) )
\r
1694 const ListItem_t *pxIterator;
\r
1695 const MiniListItem_t *pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( pxList );
\r
1696 for( pxIterator = ( const ListItem_t * ) listGET_NEXT( pxEnd );
\r
1697 pxIterator != ( const ListItem_t * ) pxEnd;
\r
1698 pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
1700 if( listGET_LIST_ITEM_VALUE( pxIterator ) == xWantedItemValue )
\r
1702 pxResult = pxIterator;
\r
1711 /*-----------------------------------------------------------*/
\r
1713 FreeRTOS_Socket_t *pxUDPSocketLookup( UBaseType_t uxLocalPort )
\r
1715 const ListItem_t *pxListItem;
\r
1716 FreeRTOS_Socket_t *pxSocket = NULL;
\r
1718 /* Looking up a socket is quite simple, find a match with the local port.
\r
1720 See if there is a list item associated with the port number on the
\r
1721 list of bound sockets. */
\r
1722 pxListItem = pxListFindListItemWithValue( &xBoundUDPSocketsList, ( TickType_t ) uxLocalPort );
\r
1724 if( pxListItem != NULL )
\r
1726 /* The owner of the list item is the socket itself. */
\r
1727 pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxListItem );
\r
1728 configASSERT( pxSocket != NULL );
\r
1733 /*-----------------------------------------------------------*/
\r
1735 #if ipconfigINCLUDE_FULL_INET_ADDR == 1
\r
1737 uint32_t FreeRTOS_inet_addr( const char * pcIPAddress )
\r
1739 const uint32_t ulDecimalBase = 10u;
\r
1740 uint8_t ucOctet[ socketMAX_IP_ADDRESS_OCTETS ];
\r
1741 const char *pcPointerOnEntering;
\r
1742 uint32_t ulReturn = 0UL, ulValue;
\r
1743 UBaseType_t uxOctetNumber;
\r
1744 BaseType_t xResult = pdPASS;
\r
1746 for( uxOctetNumber = 0u; uxOctetNumber < socketMAX_IP_ADDRESS_OCTETS; uxOctetNumber++ )
\r
1749 pcPointerOnEntering = pcIPAddress;
\r
1751 while( ( *pcIPAddress >= '0' ) && ( *pcIPAddress <= '9' ) )
\r
1753 /* Move previous read characters into the next decimal
\r
1755 ulValue *= ulDecimalBase;
\r
1757 /* Add the binary value of the ascii character. */
\r
1758 ulValue += ( ( uint32_t ) ( *pcIPAddress ) - ( uint32_t ) '0' );
\r
1760 /* Move to next character in the string. */
\r
1764 /* Check characters were read. */
\r
1765 if( pcIPAddress == pcPointerOnEntering )
\r
1770 /* Check the value fits in an 8-bit number. */
\r
1771 if( ulValue > 0xffUL )
\r
1777 ucOctet[ uxOctetNumber ] = ( uint8_t ) ulValue;
\r
1779 /* Check the next character is as expected. */
\r
1780 if( uxOctetNumber < ( socketMAX_IP_ADDRESS_OCTETS - 1u ) )
\r
1782 if( *pcIPAddress != '.' )
\r
1788 /* Move past the dot. */
\r
1794 if( xResult == pdFAIL )
\r
1796 /* No point going on. */
\r
1801 if( *pcIPAddress != ( char ) 0 )
\r
1803 /* Expected the end of the string. */
\r
1807 if( uxOctetNumber != socketMAX_IP_ADDRESS_OCTETS )
\r
1809 /* Didn't read enough octets. */
\r
1813 if( xResult == pdPASS )
\r
1815 ulReturn = FreeRTOS_inet_addr_quick( ucOctet[ 0 ], ucOctet[ 1 ], ucOctet[ 2 ], ucOctet[ 3 ] );
\r
1821 #endif /* ipconfigINCLUDE_FULL_INET_ADDR */
\r
1823 /*-----------------------------------------------------------*/
\r
1825 /* Function to get the local address and IP port */
\r
1826 size_t FreeRTOS_GetLocalAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress )
\r
1828 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
1830 /* IP address of local machine. */
\r
1831 pxAddress->sin_addr = *ipLOCAL_IP_ADDRESS_POINTER;
\r
1833 /* Local port on this machine. */
\r
1834 pxAddress->sin_port = FreeRTOS_htons( pxSocket->usLocalPort );
\r
1836 return sizeof( *pxAddress );
\r
1839 /*-----------------------------------------------------------*/
\r
1841 void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
\r
1843 /* _HT_ must work this out, now vSocketWakeUpUser will be called for any important
\r
1844 * event or transition */
\r
1845 #if( ipconfigSOCKET_HAS_USER_SEMAPHORE == 1 )
\r
1847 if( pxSocket->pxUserSemaphore != NULL )
\r
1849 xSemaphoreGive( pxSocket->pxUserSemaphore );
\r
1852 #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
\r
1854 #if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK == 1 )
\r
1856 if( pxSocket->pxUserWakeCallback != NULL )
\r
1858 pxSocket->pxUserWakeCallback( pxSocket );
\r
1861 #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
\r
1863 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
1865 if( pxSocket->pxSocketSet != NULL )
\r
1867 EventBits_t xSelectBits = ( pxSocket->xEventBits >> SOCKET_EVENT_BIT_COUNT ) & eSELECT_ALL;
\r
1868 if( xSelectBits != 0ul )
\r
1870 pxSocket->xSocketBits |= xSelectBits;
\r
1871 xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, xSelectBits );
\r
1875 pxSocket->xEventBits &= eSOCKET_ALL;
\r
1877 #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
\r
1879 if( ( pxSocket->xEventGroup != NULL ) && ( pxSocket->xEventBits != 0u ) )
\r
1881 xEventGroupSetBits( pxSocket->xEventGroup, pxSocket->xEventBits );
\r
1884 pxSocket->xEventBits = 0ul;
\r
1887 /*-----------------------------------------------------------*/
\r
1889 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1891 /* This define makes it possible for network-card drivers to inspect
\r
1892 * UDP message and see if there is any UDP socket bound to a given port
\r
1894 * This is probably only useful in systems with a minimum of RAM and
\r
1895 * when lots of anonymous broadcast messages come in
\r
1897 BaseType_t xPortHasUDPSocket( uint16_t usPortNr )
\r
1899 BaseType_t xFound = pdFALSE;
\r
1901 vTaskSuspendAll();
\r
1903 if( ( pxListFindListItemWithValue( &xBoundUDPSocketsList, ( TickType_t ) usPortNr ) != NULL ) )
\r
1913 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1915 /*-----------------------------------------------------------*/
\r
1917 #if( ipconfigUSE_TCP == 1 )
\r
1919 static BaseType_t bMayConnect( FreeRTOS_Socket_t *pxSocket );
\r
1920 static BaseType_t bMayConnect( FreeRTOS_Socket_t *pxSocket )
\r
1922 switch( pxSocket->u.xTCP.ucTCPState )
\r
1925 case eCLOSE_WAIT: return 0;
\r
1926 case eCONNECT_SYN: return -pdFREERTOS_ERRNO_EINPROGRESS;
\r
1927 default: return -pdFREERTOS_ERRNO_EAGAIN;
\r
1931 #endif /* ipconfigUSE_TCP */
\r
1932 /*-----------------------------------------------------------*/
\r
1934 #if( ipconfigUSE_TCP == 1 )
\r
1936 static BaseType_t prvTCPConnectStart( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr *pxAddress )
\r
1938 BaseType_t xResult = 0;
\r
1940 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdFALSE )
\r
1942 /* Not a valid socket or wrong type */
\r
1943 xResult = -pdFREERTOS_ERRNO_EBADF;
\r
1945 else if( FreeRTOS_issocketconnected( pxSocket ) > 0 )
\r
1947 /* The socket is already connected. */
\r
1948 xResult = -pdFREERTOS_ERRNO_EISCONN;
\r
1950 else if( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE )
\r
1952 /* Bind the socket to the port that the client task will send from.
\r
1953 Non-standard, so the error returned is that returned by bind(). */
\r
1954 xResult = FreeRTOS_bind( ( Socket_t ) pxSocket, NULL, 0u );
\r
1957 if( xResult == 0 )
\r
1959 /* Check if it makes any sense to wait for a connect event, this condition
\r
1960 might change while sleeping, so it must be checked within each loop */
\r
1961 xResult = bMayConnect( pxSocket ); /* -EINPROGRESS, -EAGAIN, or 0 for OK */
\r
1963 /* Start the connect procedure, kernel will start working on it */
\r
1964 if( xResult == 0 )
\r
1966 pxSocket->u.xTCP.bits.bConnPrepared = pdFALSE_UNSIGNED;
\r
1967 pxSocket->u.xTCP.ucRepCount = 0u;
\r
1969 FreeRTOS_debug_printf( ( "FreeRTOS_connect: %u to %lxip:%u\n",
\r
1970 pxSocket->usLocalPort, FreeRTOS_ntohl( pxAddress->sin_addr ), FreeRTOS_ntohs( pxAddress->sin_port ) ) );
\r
1972 /* Port on remote machine. */
\r
1973 pxSocket->u.xTCP.usRemotePort = FreeRTOS_ntohs( pxAddress->sin_port );
\r
1975 /* IP address of remote machine. */
\r
1976 pxSocket->u.xTCP.ulRemoteIP = FreeRTOS_ntohl( pxAddress->sin_addr );
\r
1978 /* (client) internal state: socket wants to send a connect. */
\r
1979 vTCPStateChange( pxSocket, eCONNECT_SYN );
\r
1981 /* To start an active connect. */
\r
1982 pxSocket->u.xTCP.usTimeout = 1u;
\r
1984 if( xSendEventToIPTask( eTCPTimerEvent ) != pdPASS )
\r
1986 xResult = -pdFREERTOS_ERRNO_ECANCELED;
\r
1994 #endif /* ipconfigUSE_TCP */
\r
1995 /*-----------------------------------------------------------*/
\r
1997 #if( ipconfigUSE_TCP == 1 )
\r
2000 * FreeRTOS_connect: socket wants to connect to a remote port
\r
2002 BaseType_t FreeRTOS_connect( Socket_t xClientSocket, struct freertos_sockaddr *pxAddress, socklen_t xAddressLength )
\r
2004 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t* ) xClientSocket;
\r
2005 TickType_t xRemainingTime;
\r
2006 BaseType_t xTimed = pdFALSE;
\r
2007 BaseType_t xResult;
\r
2008 TimeOut_t xTimeOut;
\r
2010 ( void ) xAddressLength;
\r
2012 xResult = prvTCPConnectStart( pxSocket, pxAddress );
\r
2014 if( xResult == 0 )
\r
2016 /* And wait for the result */
\r
2019 if( xTimed == pdFALSE )
\r
2021 /* Only in the first round, check for non-blocking */
\r
2022 xRemainingTime = pxSocket->xReceiveBlockTime;
\r
2023 if( xRemainingTime == ( TickType_t )0 )
\r
2025 /* Not yet connected, correct state, non-blocking. */
\r
2026 xResult = -pdFREERTOS_ERRNO_EWOULDBLOCK;
\r
2030 /* Don't get here a second time. */
\r
2033 /* Fetch the current time */
\r
2034 vTaskSetTimeOutState( &xTimeOut );
\r
2037 /* Did it get connected while sleeping ? */
\r
2038 xResult = FreeRTOS_issocketconnected( pxSocket );
\r
2040 /* Returns positive when connected, negative means an error */
\r
2043 /* Return the error */
\r
2049 /* Socket now connected, return a zero */
\r
2054 /* Is it allowed to sleep more? */
\r
2055 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) )
\r
2057 xResult = -pdFREERTOS_ERRNO_ETIMEDOUT;
\r
2061 /* Go sleeping until we get any down-stream event */
\r
2062 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_CONNECT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2068 #endif /* ipconfigUSE_TCP */
\r
2069 /*-----------------------------------------------------------*/
\r
2071 #if( ipconfigUSE_TCP == 1 )
\r
2074 * FreeRTOS_accept: can return a new connected socket
\r
2075 * if the server socket is in listen mode and receives a connection request
\r
2076 * The new socket will be bound already to the same port number as the listing
\r
2079 Socket_t FreeRTOS_accept( Socket_t xServerSocket, struct freertos_sockaddr *pxAddress, socklen_t *pxAddressLength )
\r
2081 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xServerSocket;
\r
2082 FreeRTOS_Socket_t *pxClientSocket = NULL;
\r
2083 TickType_t xRemainingTime;
\r
2084 BaseType_t xTimed = pdFALSE, xAsk = pdFALSE;
\r
2085 TimeOut_t xTimeOut;
\r
2086 IPStackEvent_t xAskEvent;
\r
2088 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2090 /* Not a valid socket or wrong type */
\r
2091 pxClientSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
\r
2093 else if( ( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED ) &&
\r
2094 ( pxSocket->u.xTCP.ucTCPState != eTCP_LISTEN ) )
\r
2096 /* Parent socket is not in listening mode */
\r
2097 pxClientSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
\r
2101 /* Loop will stop with breaks. */
\r
2104 /* Is there a new client? */
\r
2105 vTaskSuspendAll();
\r
2107 if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED )
\r
2109 pxClientSocket = pxSocket->u.xTCP.pxPeerSocket;
\r
2113 pxClientSocket = pxSocket;
\r
2115 if( pxClientSocket != NULL )
\r
2117 pxSocket->u.xTCP.pxPeerSocket = NULL;
\r
2119 /* Is it still not taken ? */
\r
2120 if( pxClientSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED )
\r
2122 pxClientSocket->u.xTCP.bits.bPassAccept = pdFALSE_UNSIGNED;
\r
2126 pxClientSocket = NULL;
\r
2132 if( pxClientSocket != NULL )
\r
2134 if( pxAddress != NULL )
\r
2136 /* IP address of remote machine. */
\r
2137 pxAddress->sin_addr = FreeRTOS_ntohl( pxClientSocket->u.xTCP.ulRemoteIP );
\r
2139 /* Port on remote machine. */
\r
2140 pxAddress->sin_port = FreeRTOS_ntohs( pxClientSocket->u.xTCP.usRemotePort );
\r
2142 if( pxAddressLength != NULL )
\r
2144 *pxAddressLength = sizeof( *pxAddress );
\r
2147 if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED )
\r
2153 if( xAsk != pdFALSE )
\r
2155 /* Ask to set an event in 'xEventGroup' as soon as a new
\r
2156 client gets connected for this listening socket. */
\r
2157 xAskEvent.eEventType = eTCPAcceptEvent;
\r
2158 xAskEvent.pvData = ( void * ) pxSocket;
\r
2159 xSendEventStructToIPTask( &xAskEvent, portMAX_DELAY );
\r
2162 if( pxClientSocket != NULL )
\r
2167 if( xTimed == pdFALSE )
\r
2169 /* Only in the first round, check for non-blocking */
\r
2170 xRemainingTime = pxSocket->xReceiveBlockTime;
\r
2171 if( xRemainingTime == ( TickType_t ) 0 )
\r
2176 /* Don't get here a second time */
\r
2179 /* Fetch the current time */
\r
2180 vTaskSetTimeOutState( &xTimeOut );
\r
2183 /* Has the timeout been reached? */
\r
2184 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
\r
2189 /* Go sleeping until we get any down-stream event */
\r
2190 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_ACCEPT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2194 return ( Socket_t ) pxClientSocket;
\r
2196 #endif /* ipconfigUSE_TCP */
\r
2197 /*-----------------------------------------------------------*/
\r
2199 #if( ipconfigUSE_TCP == 1 )
\r
2202 * Read incoming data from a TCP socket
\r
2203 * Only after the last byte has been read, a close error might be returned
\r
2205 BaseType_t FreeRTOS_recv( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags )
\r
2207 BaseType_t xByteCount;
\r
2208 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2209 TickType_t xRemainingTime;
\r
2210 BaseType_t xTimed = pdFALSE;
\r
2211 TimeOut_t xTimeOut;
\r
2212 EventBits_t xEventBits = ( EventBits_t ) 0;
\r
2214 /* Check if the socket is valid, has type TCP and if it is bound to a
\r
2216 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2218 xByteCount = -pdFREERTOS_ERRNO_EINVAL;
\r
2222 if( pxSocket->u.xTCP.rxStream != NULL )
\r
2224 xByteCount = ( BaseType_t )uxStreamBufferGetSize ( pxSocket->u.xTCP.rxStream );
\r
2231 while( xByteCount == 0 )
\r
2233 switch( pxSocket->u.xTCP.ucTCPState )
\r
2236 case eCLOSE_WAIT: /* (server + client) waiting for a connection termination request from the local user. */
\r
2237 case eCLOSING: /* (server + client) waiting for a connection termination request acknowledgement from the remote TCP. */
\r
2238 if( pxSocket->u.xTCP.bits.bMallocError != pdFALSE_UNSIGNED )
\r
2240 /* The no-memory error has priority above the non-connected error.
\r
2241 Both are fatal and will elad to closing the socket. */
\r
2242 xByteCount = -pdFREERTOS_ERRNO_ENOMEM;
\r
2246 xByteCount = -pdFREERTOS_ERRNO_ENOTCONN;
\r
2248 /* Call continue to break out of the switch and also the while
\r
2255 if( xTimed == pdFALSE )
\r
2257 /* Only in the first round, check for non-blocking. */
\r
2258 xRemainingTime = pxSocket->xReceiveBlockTime;
\r
2260 if( xRemainingTime == ( TickType_t ) 0 )
\r
2262 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
2264 /* Just check for the interrupt flag. */
\r
2265 xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_INTR,
\r
2266 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, socketDONT_BLOCK );
\r
2268 #endif /* ipconfigSUPPORT_SIGNALS */
\r
2272 if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
\r
2277 /* Don't get here a second time. */
\r
2280 /* Fetch the current time. */
\r
2281 vTaskSetTimeOutState( &xTimeOut );
\r
2284 /* Has the timeout been reached? */
\r
2285 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
\r
2290 /* Block until there is a down-stream event. */
\r
2291 xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup,
\r
2292 eSOCKET_RECEIVE | eSOCKET_CLOSED | eSOCKET_INTR,
\r
2293 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2294 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
2296 if( ( xEventBits & eSOCKET_INTR ) != 0u )
\r
2303 ( void ) xEventBits;
\r
2305 #endif /* ipconfigSUPPORT_SIGNALS */
\r
2307 if( pxSocket->u.xTCP.rxStream != NULL )
\r
2309 xByteCount = ( BaseType_t ) uxStreamBufferGetSize ( pxSocket->u.xTCP.rxStream );
\r
2317 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
2318 if( ( xEventBits & eSOCKET_INTR ) != 0 )
\r
2320 if( ( xEventBits & ( eSOCKET_RECEIVE | eSOCKET_CLOSED ) ) != 0 )
\r
2322 /* Shouldn't have cleared other flags. */
\r
2323 xEventBits &= ~eSOCKET_INTR;
\r
2324 xEventGroupSetBits( pxSocket->xEventGroup, xEventBits );
\r
2326 xByteCount = -pdFREERTOS_ERRNO_EINTR;
\r
2329 #endif /* ipconfigSUPPORT_SIGNALS */
\r
2330 if( xByteCount > 0 )
\r
2332 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
\r
2334 xByteCount = ( BaseType_t ) uxStreamBufferGet( pxSocket->u.xTCP.rxStream, 0ul, ( uint8_t * ) pvBuffer, ( size_t ) xBufferLength, ( xFlags & FREERTOS_MSG_PEEK ) != 0 );
\r
2335 if( pxSocket->u.xTCP.bits.bLowWater != pdFALSE_UNSIGNED )
\r
2337 /* We had reached the low-water mark, now see if the flag
\r
2339 size_t uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );
\r
2341 if( uxFrontSpace >= pxSocket->u.xTCP.uxEnoughSpace )
\r
2343 pxSocket->u.xTCP.bits.bLowWater = pdFALSE_UNSIGNED;
\r
2344 pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
\r
2345 pxSocket->u.xTCP.usTimeout = 1u; /* because bLowWater is cleared. */
\r
2346 xSendEventToIPTask( eTCPTimerEvent );
\r
2352 /* Zero-copy reception of data: pvBuffer is a pointer to a pointer. */
\r
2353 xByteCount = ( BaseType_t ) uxStreamBufferGetPtr( pxSocket->u.xTCP.rxStream, (uint8_t **)pvBuffer );
\r
2356 } /* prvValidSocket() */
\r
2358 return xByteCount;
\r
2361 #endif /* ipconfigUSE_TCP */
\r
2362 /*-----------------------------------------------------------*/
\r
2364 #if( ipconfigUSE_TCP == 1 )
\r
2366 static int32_t prvTCPSendCheck( FreeRTOS_Socket_t *pxSocket, size_t xDataLength )
\r
2368 int32_t xResult = 1;
\r
2370 /* Is this a socket of type TCP and is it already bound to a port number ? */
\r
2371 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2373 xResult = -pdFREERTOS_ERRNO_EINVAL;
\r
2375 else if( pxSocket->u.xTCP.bits.bMallocError != pdFALSE_UNSIGNED )
\r
2377 xResult = -pdFREERTOS_ERRNO_ENOMEM;
\r
2379 else if( ( pxSocket->u.xTCP.ucTCPState == eCLOSED ) ||
\r
2380 ( pxSocket->u.xTCP.ucTCPState == eCLOSE_WAIT ) ||
\r
2381 ( pxSocket->u.xTCP.ucTCPState == eCLOSING ) )
\r
2383 xResult = -pdFREERTOS_ERRNO_ENOTCONN;
\r
2385 else if( pxSocket->u.xTCP.bits.bFinSent != pdFALSE_UNSIGNED )
\r
2387 /* This TCP connection is closing already, the FIN flag has been sent.
\r
2388 Maybe it is still delivering or receiving data.
\r
2389 Return OK in order not to get closed/deleted too quickly */
\r
2392 else if( xDataLength == 0ul )
\r
2394 /* send() is being called to send zero bytes */
\r
2397 else if( pxSocket->u.xTCP.txStream == NULL )
\r
2399 /* Create the outgoing stream only when it is needed */
\r
2400 prvTCPCreateStream( pxSocket, pdFALSE );
\r
2402 if( pxSocket->u.xTCP.txStream == NULL )
\r
2404 xResult = -pdFREERTOS_ERRNO_ENOMEM;
\r
2411 #endif /* ipconfigUSE_TCP */
\r
2412 /*-----------------------------------------------------------*/
\r
2414 #if( ipconfigUSE_TCP == 1 )
\r
2416 /* Get a direct pointer to the circular transmit buffer.
\r
2417 '*pxLength' will contain the number of bytes that may be written. */
\r
2418 uint8_t *FreeRTOS_get_tx_head( Socket_t xSocket, BaseType_t *pxLength )
\r
2420 uint8_t *pucReturn;
\r
2421 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2422 StreamBuffer_t *pxBuffer = pxSocket->u.xTCP.txStream;
\r
2424 if( pxBuffer != NULL )
\r
2426 BaseType_t xSpace = ( BaseType_t ) uxStreamBufferGetSpace( pxBuffer );
\r
2427 BaseType_t xRemain = ( BaseType_t ) ( pxBuffer->LENGTH - pxBuffer->uxHead );
\r
2429 *pxLength = FreeRTOS_min_BaseType( xSpace, xRemain );
\r
2430 pucReturn = pxBuffer->ucArray + pxBuffer->uxHead;
\r
2440 #endif /* ipconfigUSE_TCP */
\r
2441 /*-----------------------------------------------------------*/
\r
2443 #if( ipconfigUSE_TCP == 1 )
\r
2445 * Send data using a TCP socket. It is not necessary to have the socket
\r
2446 * connected already. Outgoing data will be stored and delivered as soon as
\r
2447 * the socket gets connected.
\r
2449 BaseType_t FreeRTOS_send( Socket_t xSocket, const void *pvBuffer, size_t uxDataLength, BaseType_t xFlags )
\r
2451 BaseType_t xByteCount;
\r
2452 BaseType_t xBytesLeft;
\r
2453 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2454 TickType_t xRemainingTime;
\r
2455 BaseType_t xTimed = pdFALSE;
\r
2456 TimeOut_t xTimeOut;
\r
2457 BaseType_t xCloseAfterSend;
\r
2459 /* Prevent compiler warnings about unused parameters. The parameter
\r
2460 may be used in future versions. */
\r
2463 xByteCount = ( BaseType_t ) prvTCPSendCheck( pxSocket, uxDataLength );
\r
2465 if( xByteCount > 0 )
\r
2467 /* xBytesLeft is number of bytes to send, will count to zero. */
\r
2468 xBytesLeft = ( BaseType_t ) uxDataLength;
\r
2470 /* xByteCount is number of bytes that can be sent now. */
\r
2471 xByteCount = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
\r
2473 /* While there are still bytes to be sent. */
\r
2474 while( xBytesLeft > 0 )
\r
2476 /* If txStream has space. */
\r
2477 if( xByteCount > 0 )
\r
2479 /* Don't send more than necessary. */
\r
2480 if( xByteCount > xBytesLeft )
\r
2482 xByteCount = xBytesLeft;
\r
2485 /* Is the close-after-send flag set and is this really the
\r
2486 last transmission? */
\r
2487 if( ( pxSocket->u.xTCP.bits.bCloseAfterSend != pdFALSE_UNSIGNED ) && ( xByteCount == xBytesLeft ) )
\r
2489 xCloseAfterSend = pdTRUE;
\r
2493 xCloseAfterSend = pdFALSE;
\r
2496 /* The flag 'bCloseAfterSend' can be set before sending data
\r
2497 using setsockopt()
\r
2499 When the last data packet is being sent out, a FIN flag will
\r
2500 be included to let the peer know that no more data is to be
\r
2501 expected. The use of 'bCloseAfterSend' is not mandatory, it
\r
2502 is just a faster way of transferring files (e.g. when using
\r
2504 if( xCloseAfterSend != pdFALSE )
\r
2506 /* Now suspend the scheduler: sending the last data and
\r
2507 setting bCloseRequested must be done together */
\r
2508 vTaskSuspendAll();
\r
2509 pxSocket->u.xTCP.bits.bCloseRequested = pdTRUE_UNSIGNED;
\r
2512 xByteCount = ( BaseType_t ) uxStreamBufferAdd( pxSocket->u.xTCP.txStream, 0ul, ( const uint8_t * ) pvBuffer, ( size_t ) xByteCount );
\r
2514 if( xCloseAfterSend != pdFALSE )
\r
2516 /* Now when the IP-task transmits the data, it will also
\r
2517 see that bCloseRequested is true and include the FIN
\r
2518 flag to start closure of the connection. */
\r
2522 /* Send a message to the IP-task so it can work on this
\r
2523 socket. Data is sent, let the IP-task work on it. */
\r
2524 pxSocket->u.xTCP.usTimeout = 1u;
\r
2526 if( xIsCallingFromIPTask() == pdFALSE )
\r
2528 /* Only send a TCP timer event when not called from the
\r
2530 xSendEventToIPTask( eTCPTimerEvent );
\r
2533 xBytesLeft -= xByteCount;
\r
2535 if( xBytesLeft == 0 )
\r
2540 /* As there are still bytes left to be sent, increase the
\r
2542 pvBuffer = ( void * ) ( ( ( const uint8_t * ) pvBuffer) + xByteCount );
\r
2545 /* Not all bytes have been sent. In case the socket is marked as
\r
2546 blocking sleep for a while. */
\r
2547 if( xTimed == pdFALSE )
\r
2549 /* Only in the first round, check for non-blocking. */
\r
2550 xRemainingTime = pxSocket->xSendBlockTime;
\r
2552 #if( ipconfigUSE_CALLBACKS != 0 )
\r
2554 if( xIsCallingFromIPTask() != pdFALSE )
\r
2556 /* If this send function is called from within a
\r
2557 call-back handler it may not block, otherwise
\r
2558 chances would be big to get a deadlock: the IP-task
\r
2559 waiting for itself. */
\r
2560 xRemainingTime = ( TickType_t ) 0;
\r
2563 #endif /* ipconfigUSE_CALLBACKS */
\r
2565 if( xRemainingTime == ( TickType_t ) 0 )
\r
2570 if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
\r
2575 /* Don't get here a second time. */
\r
2578 /* Fetch the current time. */
\r
2579 vTaskSetTimeOutState( &xTimeOut );
\r
2583 /* Has the timeout been reached? */
\r
2584 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
\r
2590 /* Go sleeping until down-stream events are received. */
\r
2591 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_SEND | eSOCKET_CLOSED,
\r
2592 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2594 xByteCount = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
\r
2597 /* How much was actually sent? */
\r
2598 xByteCount = ( ( BaseType_t ) uxDataLength ) - xBytesLeft;
\r
2600 if( xByteCount == 0 )
\r
2602 if( pxSocket->u.xTCP.ucTCPState > eESTABLISHED )
\r
2604 xByteCount = ( BaseType_t ) -pdFREERTOS_ERRNO_ENOTCONN;
\r
2608 if( ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) != pdFALSE )
\r
2610 FreeRTOS_debug_printf( ( "FreeRTOS_send: %u -> %lxip:%d: no space\n",
\r
2611 pxSocket->usLocalPort,
\r
2612 pxSocket->u.xTCP.ulRemoteIP,
\r
2613 pxSocket->u.xTCP.usRemotePort ) );
\r
2616 xByteCount = ( BaseType_t ) -pdFREERTOS_ERRNO_ENOSPC;
\r
2621 return xByteCount;
\r
2624 #endif /* ipconfigUSE_TCP */
\r
2625 /*-----------------------------------------------------------*/
\r
2627 #if( ipconfigUSE_TCP == 1 )
\r
2630 * Request to put a socket in listen mode
\r
2632 BaseType_t FreeRTOS_listen( Socket_t xSocket, BaseType_t xBacklog )
\r
2634 FreeRTOS_Socket_t *pxSocket;
\r
2635 BaseType_t xResult = 0;
\r
2637 pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2639 /* listen() is allowed for a valid TCP socket in Closed state and already
\r
2641 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2643 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2645 else if( ( pxSocket->u.xTCP.ucTCPState != eCLOSED ) && ( pxSocket->u.xTCP.ucTCPState != eCLOSE_WAIT ) )
\r
2647 /* Socket is in a wrong state. */
\r
2648 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2652 /* Backlog is interpreted here as "the maximum number of child
\r
2654 pxSocket->u.xTCP.usBacklog = ( uint16_t )FreeRTOS_min_int32( ( int32_t ) 0xffff, ( int32_t ) xBacklog );
\r
2656 /* This cleaning is necessary only if a listening socket is being
\r
2657 reused as it might have had a previous connection. */
\r
2658 if( pxSocket->u.xTCP.bits.bReuseSocket )
\r
2660 if( pxSocket->u.xTCP.rxStream != NULL )
\r
2662 vStreamBufferClear( pxSocket->u.xTCP.rxStream );
\r
2665 if( pxSocket->u.xTCP.txStream != NULL )
\r
2667 vStreamBufferClear( pxSocket->u.xTCP.txStream );
\r
2670 memset( pxSocket->u.xTCP.xPacket.u.ucLastPacket, '\0', sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket ) );
\r
2671 memset( &pxSocket->u.xTCP.xTCPWindow, '\0', sizeof( pxSocket->u.xTCP.xTCPWindow ) );
\r
2672 memset( &pxSocket->u.xTCP.bits, '\0', sizeof( pxSocket->u.xTCP.bits ) );
\r
2674 /* Now set the bReuseSocket flag again, because the bits have
\r
2675 just been cleared. */
\r
2676 pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE_UNSIGNED;
\r
2679 vTCPStateChange( pxSocket, eTCP_LISTEN );
\r
2685 #endif /* ipconfigUSE_TCP */
\r
2686 /*-----------------------------------------------------------*/
\r
2688 #if( ipconfigUSE_TCP == 1 )
\r
2690 /* shutdown - shut down part of a full-duplex connection */
\r
2691 BaseType_t FreeRTOS_shutdown( Socket_t xSocket, BaseType_t xHow )
\r
2693 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2694 BaseType_t xResult;
\r
2696 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2698 /*_RB_ Is this comment correct? The socket is not of a type that
\r
2699 supports the listen() operation. */
\r
2700 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2702 else if ( pxSocket->u.xTCP.ucTCPState != eESTABLISHED )
\r
2704 /*_RB_ Is this comment correct? The socket is not of a type that
\r
2705 supports the listen() operation. */
\r
2706 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2710 pxSocket->u.xTCP.bits.bUserShutdown = pdTRUE_UNSIGNED;
\r
2712 /* Let the IP-task perform the shutdown of the connection. */
\r
2713 pxSocket->u.xTCP.usTimeout = 1u;
\r
2714 xSendEventToIPTask( eTCPTimerEvent );
\r
2722 #endif /* ipconfigUSE_TCP */
\r
2723 /*-----------------------------------------------------------*/
\r
2725 #if( ipconfigUSE_TCP == 1 )
\r
2728 * A TCP timer has expired, now check all TCP sockets for:
\r
2729 * - Active connect
\r
2730 * - Send a delayed ACK
\r
2732 * - Send a keep-alive packet
\r
2733 * - Check for timeout (in non-connected states only)
\r
2735 TickType_t xTCPTimerCheck( BaseType_t xWillSleep )
\r
2737 FreeRTOS_Socket_t *pxSocket;
\r
2738 TickType_t xShortest = pdMS_TO_TICKS( ( TickType_t ) ipTCP_TIMER_PERIOD_MS );
\r
2739 TickType_t xNow = xTaskGetTickCount();
\r
2740 static TickType_t xLastTime = 0u;
\r
2741 TickType_t xDelta = xNow - xLastTime;
\r
2742 ListItem_t* pxEnd = ( ListItem_t * ) listGET_END_MARKER( &xBoundTCPSocketsList );
\r
2743 ListItem_t *pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );
\r
2747 if( xDelta == 0u )
\r
2752 while( pxIterator != pxEnd )
\r
2754 pxSocket = ( FreeRTOS_Socket_t * )listGET_LIST_ITEM_OWNER( pxIterator );
\r
2755 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator );
\r
2757 /* Sockets with 'tmout == 0' do not need any regular attention. */
\r
2758 if( pxSocket->u.xTCP.usTimeout == 0u )
\r
2763 if( xDelta < ( TickType_t ) pxSocket->u.xTCP.usTimeout )
\r
2765 pxSocket->u.xTCP.usTimeout = ( uint16_t ) ( ( ( TickType_t ) pxSocket->u.xTCP.usTimeout ) - xDelta );
\r
2770 pxSocket->u.xTCP.usTimeout = 0u;
\r
2771 rc = xTCPSocketCheck( pxSocket );
\r
2773 /* Within this function, the socket might want to send a delayed
\r
2774 ack or send out data or whatever it needs to do. */
\r
2777 /* Continue because the socket was deleted. */
\r
2782 /* In xEventBits the driver may indicate that the socket has
\r
2783 important events for the user. These are only done just before the
\r
2784 IP-task goes to sleep. */
\r
2785 if( pxSocket->xEventBits != 0u )
\r
2787 if( xWillSleep != pdFALSE )
\r
2789 /* The IP-task is about to go to sleep, so messages can be
\r
2790 sent to the socket owners. */
\r
2791 vSocketWakeUpUser( pxSocket );
\r
2795 /* Or else make sure this will be called again to wake-up
\r
2796 the sockets' owner. */
\r
2797 xShortest = ( TickType_t ) 0;
\r
2801 if( ( pxSocket->u.xTCP.usTimeout != 0u ) && ( xShortest > ( TickType_t ) pxSocket->u.xTCP.usTimeout ) )
\r
2803 xShortest = ( TickType_t ) pxSocket->u.xTCP.usTimeout;
\r
2810 #endif /* ipconfigUSE_TCP */
\r
2811 /*-----------------------------------------------------------*/
\r
2813 #if( ipconfigUSE_TCP == 1 )
\r
2816 * TCP: as multiple sockets may be bound to the same local port number
\r
2817 * looking up a socket is a little more complex:
\r
2818 * Both a local port, and a remote port and IP address are being used
\r
2819 * For a socket in listening mode, the remote port and IP address are both 0
\r
2821 FreeRTOS_Socket_t *pxTCPSocketLookup( uint32_t ulLocalIP, UBaseType_t uxLocalPort, uint32_t ulRemoteIP, UBaseType_t uxRemotePort )
\r
2823 ListItem_t *pxIterator;
\r
2824 FreeRTOS_Socket_t *pxResult = NULL, *pxListenSocket = NULL;
\r
2825 MiniListItem_t *pxEnd = ( MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );
\r
2827 /* Parameter not yet supported. */
\r
2828 ( void ) ulLocalIP;
\r
2830 for( pxIterator = ( ListItem_t * ) listGET_NEXT( pxEnd );
\r
2831 pxIterator != ( ListItem_t * ) pxEnd;
\r
2832 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
2834 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
\r
2836 if( pxSocket->usLocalPort == ( uint16_t ) uxLocalPort )
\r
2838 if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN )
\r
2840 /* If this is a socket listening to uxLocalPort, remember it
\r
2841 in case there is no perfect match. */
\r
2842 pxListenSocket = pxSocket;
\r
2844 else if( ( pxSocket->u.xTCP.usRemotePort == ( uint16_t ) uxRemotePort ) && ( pxSocket->u.xTCP.ulRemoteIP == ulRemoteIP ) )
\r
2846 /* For sockets not in listening mode, find a match with
\r
2847 xLocalPort, ulRemoteIP AND xRemotePort. */
\r
2848 pxResult = pxSocket;
\r
2853 if( pxResult == NULL )
\r
2855 /* An exact match was not found, maybe a listening socket was
\r
2857 pxResult = pxListenSocket;
\r
2863 #endif /* ipconfigUSE_TCP */
\r
2864 /*-----------------------------------------------------------*/
\r
2866 #if( ipconfigUSE_TCP == 1 )
\r
2868 const struct xSTREAM_BUFFER *FreeRTOS_get_rx_buf( Socket_t xSocket )
\r
2870 FreeRTOS_Socket_t *pxSocket = (FreeRTOS_Socket_t *)xSocket;
\r
2872 return pxSocket->u.xTCP.rxStream;
\r
2875 #endif /* ipconfigUSE_TCP */
\r
2876 /*-----------------------------------------------------------*/
\r
2878 #if( ipconfigUSE_TCP == 1 )
\r
2880 static StreamBuffer_t *prvTCPCreateStream( FreeRTOS_Socket_t *pxSocket, BaseType_t xIsInputStream )
\r
2882 StreamBuffer_t *pxBuffer;
\r
2886 /* Now that a stream is created, the maximum size is fixed before
\r
2887 creation, it could still be changed with setsockopt(). */
\r
2888 if( xIsInputStream != pdFALSE )
\r
2890 /* Flow control for input streams works with a low- and a high-water mark.
\r
2891 1) If the RX-space becomes less than uxLittleSpace, the flag 'bLowWater' will
\r
2892 be set, and a TCP window update message will be sent to the peer.
\r
2893 2) The data will be read from the socket by recv() and when RX-space becomes
\r
2894 larger than or equal to than 'uxEnoughSpace', a new TCP window update
\r
2895 message will be sent to the peer, and 'bLowWater' will get cleared again.
\r
2897 uxLittleSpace == 1/5 x uxRxStreamSize
\r
2898 uxEnoughSpace == 4/5 x uxRxStreamSize
\r
2899 How-ever it is very inefficient to make 'uxLittleSpace' smaller than the actual MSS.
\r
2901 uxLength = pxSocket->u.xTCP.uxRxStreamSize;
\r
2903 if( pxSocket->u.xTCP.uxLittleSpace == 0ul )
\r
2905 pxSocket->u.xTCP.uxLittleSpace = ( 1ul * pxSocket->u.xTCP.uxRxStreamSize ) / 5u; /*_RB_ Why divide by 5? Can this be changed to a #define? */
\r
2906 if( ( pxSocket->u.xTCP.uxLittleSpace < pxSocket->u.xTCP.usCurMSS ) && ( pxSocket->u.xTCP.uxRxStreamSize >= 2u * pxSocket->u.xTCP.usCurMSS ) )
\r
2908 pxSocket->u.xTCP.uxLittleSpace = pxSocket->u.xTCP.usCurMSS;
\r
2912 if( pxSocket->u.xTCP.uxEnoughSpace == 0ul )
\r
2914 pxSocket->u.xTCP.uxEnoughSpace = ( 4ul * pxSocket->u.xTCP.uxRxStreamSize ) / 5u; /*_RB_ Why multiply by 4? Maybe sock80_PERCENT?*/
\r
2919 uxLength = pxSocket->u.xTCP.uxTxStreamSize;
\r
2922 /* Add an extra 4 (or 8) bytes. */
\r
2923 uxLength += sizeof( size_t );
\r
2925 /* And make the length a multiple of sizeof( size_t ). */
\r
2926 uxLength &= ~( sizeof( size_t ) - 1u );
\r
2928 uxSize = sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) + uxLength;
\r
2930 pxBuffer = ( StreamBuffer_t * )pvPortMallocLarge( uxSize );
\r
2932 if( pxBuffer == NULL )
\r
2934 FreeRTOS_debug_printf( ( "prvTCPCreateStream: malloc failed\n" ) );
\r
2935 pxSocket->u.xTCP.bits.bMallocError = pdTRUE_UNSIGNED;
\r
2936 vTCPStateChange( pxSocket, eCLOSE_WAIT );
\r
2940 /* Clear the markers of the stream */
\r
2941 memset( pxBuffer, '\0', sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) );
\r
2942 pxBuffer->LENGTH = ( size_t ) uxLength ;
\r
2944 if( xTCPWindowLoggingLevel != 0 )
\r
2946 FreeRTOS_debug_printf( ( "prvTCPCreateStream: %cxStream created %lu bytes (total %lu)\n", xIsInputStream ? 'R' : 'T', uxLength, uxSize ) );
\r
2949 if( xIsInputStream != 0 )
\r
2951 pxSocket->u.xTCP.rxStream = pxBuffer;
\r
2955 pxSocket->u.xTCP.txStream = pxBuffer;
\r
2962 #endif /* ipconfigUSE_TCP */
\r
2963 /*-----------------------------------------------------------*/
\r
2965 #if( ipconfigUSE_TCP == 1 )
\r
2968 * Add data to the RxStream. When uxOffset > 0, data has come in out-of-order
\r
2969 * and will be put in front of the head so it can not be popped by the user.
\r
2971 int32_t lTCPAddRxdata( FreeRTOS_Socket_t *pxSocket, size_t uxOffset, const uint8_t *pcData, uint32_t ulByteCount )
\r
2973 StreamBuffer_t *pxStream = pxSocket->u.xTCP.rxStream;
\r
2975 #if( ipconfigUSE_CALLBACKS == 1 )
\r
2976 BaseType_t bHasHandler = ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xTCP.pxHandleReceive );
\r
2977 const uint8_t *pucBuffer = NULL;
\r
2978 #endif /* ipconfigUSE_CALLBACKS */
\r
2980 /* int32_t uxStreamBufferAdd( pxBuffer, uxOffset, pucData, aCount )
\r
2981 if( pucData != NULL ) copy data the the buffer
\r
2982 if( pucData == NULL ) no copying, just advance rxHead
\r
2983 if( uxOffset != 0 ) Just store data which has come out-of-order
\r
2984 if( uxOffset == 0 ) Also advance rxHead */
\r
2985 if( pxStream == NULL )
\r
2987 pxStream = prvTCPCreateStream( pxSocket, pdTRUE );
\r
2988 if( pxStream == NULL )
\r
2994 #if( ipconfigUSE_CALLBACKS == 1 )
\r
2996 if( ( bHasHandler != pdFALSE ) && ( uxStreamBufferGetSize( pxStream ) == 0u ) && ( uxOffset == 0ul ) && ( pcData != NULL ) )
\r
2998 /* Data can be passed directly to the user */
\r
2999 pucBuffer = pcData;
\r
3001 /* Zero-copy for call-back: no need to add the bytes to the
\r
3002 stream, only the pointer will be advanced by uxStreamBufferAdd(). */
\r
3006 #endif /* ipconfigUSE_CALLBACKS */
\r
3008 xResult = ( int32_t ) uxStreamBufferAdd( pxStream, uxOffset, pcData, ( size_t ) ulByteCount );
\r
3010 #if( ipconfigHAS_DEBUG_PRINTF != 0 )
\r
3012 if( xResult != ( int32_t ) ulByteCount )
\r
3014 FreeRTOS_debug_printf( ( "lTCPAddRxdata: at %ld: %ld/%lu bytes (tail %lu head %lu space %lu front %lu)\n",
\r
3015 uxOffset, xResult, ulByteCount,
\r
3018 uxStreamBufferFrontSpace( pxStream ),
\r
3019 pxStream->uxFront ) );
\r
3022 #endif /* ipconfigHAS_DEBUG_PRINTF */
\r
3024 if( uxOffset == 0u )
\r
3026 /* Data is being added to rxStream at the head (offs = 0) */
\r
3027 #if( ipconfigUSE_CALLBACKS == 1 )
\r
3028 if( bHasHandler != pdFALSE )
\r
3030 /* The socket owner has installed an OnReceive handler. Pass the
\r
3031 Rx data, without copying from the rxStream, to the user. */
\r
3034 uint8_t *ucReadPtr = NULL;
\r
3036 if( pucBuffer != NULL )
\r
3038 ucReadPtr = ( uint8_t * )pucBuffer;
\r
3039 ulCount = ulByteCount;
\r
3044 ulCount = ( uint32_t ) uxStreamBufferGetPtr( pxStream, &( ucReadPtr ) );
\r
3047 if( ulCount == 0ul )
\r
3052 if( pxSocket->u.xTCP.pxHandleReceive( (Socket_t *)pxSocket, ( void* )ucReadPtr, ( size_t ) ulCount ) != pdFALSE )
\r
3054 uxStreamBufferGet( pxStream, 0ul, NULL, ( size_t ) ulCount, pdFALSE );
\r
3058 #endif /* ipconfigUSE_CALLBACKS */
\r
3060 /* See if running out of space. */
\r
3061 if( pxSocket->u.xTCP.bits.bLowWater == pdFALSE_UNSIGNED )
\r
3063 size_t uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );
\r
3064 if( uxFrontSpace <= pxSocket->u.xTCP.uxLittleSpace )
\r
3066 pxSocket->u.xTCP.bits.bLowWater = pdTRUE_UNSIGNED;
\r
3067 pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
\r
3069 /* bLowWater was reached, send the changed window size. */
\r
3070 pxSocket->u.xTCP.usTimeout = 1u;
\r
3071 xSendEventToIPTask( eTCPTimerEvent );
\r
3075 /* New incoming data is available, wake up the user. User's
\r
3076 semaphores will be set just before the IP-task goes asleep. */
\r
3077 pxSocket->xEventBits |= eSOCKET_RECEIVE;
\r
3079 #if ipconfigSUPPORT_SELECT_FUNCTION == 1
\r
3081 if( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 )
\r
3083 pxSocket->xEventBits |= ( eSELECT_READ << SOCKET_EVENT_BIT_COUNT );
\r
3093 #endif /* ipconfigUSE_TCP */
\r
3094 /*-----------------------------------------------------------*/
\r
3096 #if( ipconfigUSE_TCP == 1 )
\r
3098 /* Function to get the remote address and IP port */
\r
3099 BaseType_t FreeRTOS_GetRemoteAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress )
\r
3101 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3102 BaseType_t xResult;
\r
3104 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3106 xResult = -pdFREERTOS_ERRNO_EINVAL;
\r
3110 /* BSD style sockets communicate IP and port addresses in network
\r
3113 IP address of remote machine. */
\r
3114 pxAddress->sin_addr = FreeRTOS_htonl ( pxSocket->u.xTCP.ulRemoteIP );
\r
3116 /* Port on remote machine. */
\r
3117 pxAddress->sin_port = FreeRTOS_htons ( pxSocket->u.xTCP.usRemotePort );
\r
3119 xResult = ( BaseType_t ) sizeof( ( *pxAddress ) );
\r
3125 #endif /* ipconfigUSE_TCP */
\r
3127 /*-----------------------------------------------------------*/
\r
3129 #if( ipconfigUSE_TCP == 1 )
\r
3131 /* Returns the number of bytes that may be added to txStream */
\r
3132 BaseType_t FreeRTOS_maywrite( Socket_t xSocket )
\r
3134 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3135 BaseType_t xResult;
\r
3137 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3139 xResult = -pdFREERTOS_ERRNO_EINVAL;
\r
3141 else if( pxSocket->u.xTCP.ucTCPState != eESTABLISHED )
\r
3143 if( ( pxSocket->u.xTCP.ucTCPState < eCONNECT_SYN ) || ( pxSocket->u.xTCP.ucTCPState > eESTABLISHED ) )
\r
3152 else if( pxSocket->u.xTCP.txStream == NULL )
\r
3154 xResult = ( BaseType_t ) pxSocket->u.xTCP.uxTxStreamSize;
\r
3158 xResult = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
\r
3164 #endif /* ipconfigUSE_TCP */
\r
3165 /*-----------------------------------------------------------*/
\r
3167 #if( ipconfigUSE_TCP ==1 )
\r
3169 BaseType_t FreeRTOS_tx_space( Socket_t xSocket )
\r
3171 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3172 BaseType_t xReturn;
\r
3174 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3176 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3180 if( pxSocket->u.xTCP.txStream != NULL )
\r
3182 xReturn = ( BaseType_t ) uxStreamBufferGetSpace ( pxSocket->u.xTCP.txStream );
\r
3186 xReturn = ( BaseType_t ) pxSocket->u.xTCP.uxTxStreamSize;
\r
3193 #endif /* ipconfigUSE_TCP */
\r
3194 /*-----------------------------------------------------------*/
\r
3196 #if( ipconfigUSE_TCP == 1 )
\r
3198 BaseType_t FreeRTOS_tx_size( Socket_t xSocket )
\r
3200 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3201 BaseType_t xReturn;
\r
3203 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3205 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3209 if( pxSocket->u.xTCP.txStream != NULL )
\r
3211 xReturn = ( BaseType_t ) uxStreamBufferGetSize ( pxSocket->u.xTCP.txStream );
\r
3222 #endif /* ipconfigUSE_TCP */
\r
3223 /*-----------------------------------------------------------*/
\r
3225 #if( ipconfigUSE_TCP == 1 )
\r
3227 /* Returns pdTRUE if TCP socket is connected. */
\r
3228 BaseType_t FreeRTOS_issocketconnected( Socket_t xSocket )
\r
3230 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3231 BaseType_t xReturn = pdFALSE;
\r
3233 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3235 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3239 if( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED )
\r
3241 if( pxSocket->u.xTCP.ucTCPState < eCLOSE_WAIT )
\r
3251 #endif /* ipconfigUSE_TCP */
\r
3252 /*-----------------------------------------------------------*/
\r
3254 #if( ipconfigUSE_TCP == 1 )
\r
3256 /* returns the actual size of MSS being used */
\r
3257 BaseType_t FreeRTOS_mss( Socket_t xSocket )
\r
3259 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3260 BaseType_t xReturn;
\r
3262 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3264 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3268 /* usCurMSS is declared as uint16_t to save space. FreeRTOS_mss()
\r
3269 will often be used in signed native-size expressions cast it to
\r
3271 xReturn = ( BaseType_t ) ( pxSocket->u.xTCP.usCurMSS );
\r
3277 #endif /* ipconfigUSE_TCP */
\r
3278 /*-----------------------------------------------------------*/
\r
3280 #if( ipconfigUSE_TCP == 1 )
\r
3282 /* HT: for internal use only: return the connection status */
\r
3283 BaseType_t FreeRTOS_connstatus( Socket_t xSocket )
\r
3285 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3286 BaseType_t xReturn;
\r
3288 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3290 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3294 /* Cast it to BaseType_t */
\r
3295 xReturn = ( BaseType_t ) ( pxSocket->u.xTCP.ucTCPState );
\r
3301 #endif /* ipconfigUSE_TCP */
\r
3302 /*-----------------------------------------------------------*/
\r
3304 #if( ipconfigUSE_TCP == 1 )
\r
3307 * Returns the number of bytes which can be read.
\r
3309 BaseType_t FreeRTOS_rx_size( Socket_t xSocket )
\r
3311 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3312 BaseType_t xReturn;
\r
3314 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3316 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3318 else if( pxSocket->u.xTCP.rxStream != NULL )
\r
3320 xReturn = ( BaseType_t ) uxStreamBufferGetSize( pxSocket->u.xTCP.rxStream );
\r
3330 #endif /* ipconfigUSE_TCP */
\r
3331 /*-----------------------------------------------------------*/
\r
3333 #if( ipconfigUSE_TCP == 1 )
\r
3335 void FreeRTOS_netstat( void )
\r
3337 IPStackEvent_t xAskEvent;
\r
3339 /* Ask the IP-task to call vTCPNetStat()
\r
3340 * to avoid accessing xBoundTCPSocketsList
\r
3342 xAskEvent.eEventType = eTCPNetStat;
\r
3343 xAskEvent.pvData = ( void * ) NULL;
\r
3344 xSendEventStructToIPTask( &xAskEvent, 1000u );
\r
3347 #endif /* ipconfigUSE_TCP */
\r
3348 /*-----------------------------------------------------------*/
\r
3350 #if( ( ipconfigHAS_PRINTF != 0 ) && ( ipconfigUSE_TCP == 1 ) )
\r
3352 void vTCPNetStat( void )
\r
3354 /* Show a simple listing of all created sockets and their connections */
\r
3355 ListItem_t *pxIterator;
\r
3356 BaseType_t count = 0;
\r
3358 if( listLIST_IS_INITIALISED( &xBoundTCPSocketsList ) == pdFALSE )
\r
3360 FreeRTOS_printf( ( "PLUS-TCP not initialized\n" ) );
\r
3364 FreeRTOS_printf( ( "Prot Port IP-Remote : Port R/T Status Alive tmout Child\n" ) );
\r
3365 for( pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );
\r
3366 pxIterator != ( ListItem_t * ) listGET_END_MARKER( &xBoundTCPSocketsList );
\r
3367 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
3369 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
\r
3370 #if( ipconfigTCP_KEEP_ALIVE == 1 )
\r
3371 TickType_t age = xTaskGetTickCount() - pxSocket->u.xTCP.xLastAliveTime;
\r
3373 TickType_t age = 0u;
\r
3375 #if( ipconfigUSE_CALLBACKS == 1 )
\r
3376 void *pxHandleReceive = (void*)pxSocket->u.xTCP.pxHandleReceive;
\r
3378 void *pxHandleReceive = (void*)NULL;
\r
3380 char ucChildText[16] = "";
\r
3381 if (pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN)
\r
3383 snprintf( ucChildText, sizeof( ucChildText ), " %d/%d",
\r
3384 pxSocket->u.xTCP.usChildCount,
\r
3385 pxSocket->u.xTCP.usBacklog);
\r
3387 if( age > 999999 )
\r
3389 FreeRTOS_printf( ( "TCP %5d %-16lxip:%5d %d/%d %-13.13s %6lu %6u%s\n",
\r
3390 pxSocket->usLocalPort, /* Local port on this machine */
\r
3391 pxSocket->u.xTCP.ulRemoteIP, /* IP address of remote machine */
\r
3392 pxSocket->u.xTCP.usRemotePort, /* Port on remote machine */
\r
3393 pxSocket->u.xTCP.rxStream != NULL,
\r
3394 pxSocket->u.xTCP.txStream != NULL,
\r
3395 FreeRTOS_GetTCPStateName( pxSocket->u.xTCP.ucTCPState ),
\r
3397 pxSocket->u.xTCP.usTimeout,
\r
3399 /* Remove compiler warnings if FreeRTOS_debug_printf() is not defined. */
\r
3400 ( void ) pxHandleReceive;
\r
3404 for( pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundUDPSocketsList );
\r
3405 pxIterator != ( ListItem_t * ) listGET_END_MARKER( &xBoundUDPSocketsList );
\r
3406 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
3408 /* Local port on this machine */
\r
3409 FreeRTOS_printf( ( "UDP Port %5u\n",
\r
3410 FreeRTOS_ntohs( listGET_LIST_ITEM_VALUE( pxIterator ) ) ) );
\r
3414 FreeRTOS_printf( ( "FreeRTOS_netstat: %lu sockets %lu < %lu < %d buffers free\n",
\r
3416 uxGetMinimumFreeNetworkBuffers( ),
\r
3417 uxGetNumberOfFreeNetworkBuffers( ),
\r
3418 ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ) );
\r
3422 #endif /* ( ( ipconfigHAS_PRINTF != 0 ) && ( ipconfigUSE_TCP == 1 ) ) */
\r
3423 /*-----------------------------------------------------------*/
\r
3425 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
3427 void vSocketSelect( SocketSelect_t *pxSocketSet )
\r
3429 BaseType_t xRound;
\r
3430 EventBits_t xSocketBits, xBitsToClear;
\r
3431 #if ipconfigUSE_TCP == 1
\r
3432 BaseType_t xLastRound = 1;
\r
3434 BaseType_t xLastRound = 0;
\r
3437 /* These flags will be switched on after checking the socket status. */
\r
3438 EventBits_t xGroupBits = 0;
\r
3439 pxSocketSet->pxSocket = NULL;
\r
3441 for( xRound = 0; xRound <= xLastRound; xRound++ )
\r
3443 const ListItem_t *pxIterator;
\r
3444 const MiniListItem_t *pxEnd;
\r
3447 pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundUDPSocketsList );
\r
3449 #if ipconfigUSE_TCP == 1
\r
3452 pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );
\r
3454 #endif /* ipconfigUSE_TCP == 1 */
\r
3455 for( pxIterator = ( const ListItem_t * ) ( listGET_NEXT( pxEnd ) );
\r
3456 pxIterator != ( const ListItem_t * ) pxEnd;
\r
3457 pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
3459 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
\r
3460 if( pxSocket->pxSocketSet != pxSocketSet )
\r
3462 /* Socket does not belong to this select group. */
\r
3467 #if( ipconfigUSE_TCP == 1 )
\r
3468 if( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP )
\r
3470 /* Check if the socket has already been accepted by the
\r
3471 owner. If not, it is useless to return it from a
\r
3473 BaseType_t bAccepted = pdFALSE;
\r
3475 if( pxSocket->u.xTCP.bits.bPassQueued == pdFALSE_UNSIGNED )
\r
3477 if( pxSocket->u.xTCP.bits.bPassAccept == pdFALSE_UNSIGNED )
\r
3479 bAccepted = pdTRUE;
\r
3483 /* Is the set owner interested in READ events? */
\r
3484 if( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 )
\r
3486 if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN )
\r
3488 if( ( pxSocket->u.xTCP.pxPeerSocket != NULL ) && ( pxSocket->u.xTCP.pxPeerSocket->u.xTCP.bits.bPassAccept != 0 ) )
\r
3490 xSocketBits |= eSELECT_READ;
\r
3493 else if( ( pxSocket->u.xTCP.bits.bReuseSocket != pdFALSE_UNSIGNED ) && ( pxSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED ) )
\r
3495 /* This socket has the re-use flag. After connecting it turns into
\r
3496 aconnected socket. Set the READ event, so that accept() will be called. */
\r
3497 xSocketBits |= eSELECT_READ;
\r
3499 else if( ( bAccepted != 0 ) && ( FreeRTOS_recvcount( pxSocket ) > 0 ) )
\r
3501 xSocketBits |= eSELECT_READ;
\r
3504 /* Is the set owner interested in EXCEPTION events? */
\r
3505 if( ( pxSocket->xSelectBits & eSELECT_EXCEPT ) != 0 )
\r
3507 if( ( pxSocket->u.xTCP.ucTCPState == eCLOSE_WAIT ) || ( pxSocket->u.xTCP.ucTCPState == eCLOSED ) )
\r
3509 xSocketBits |= eSELECT_EXCEPT;
\r
3513 /* Is the set owner interested in WRITE events? */
\r
3514 if( ( pxSocket->xSelectBits & eSELECT_WRITE ) != 0 )
\r
3516 BaseType_t bMatch = pdFALSE;
\r
3518 if( bAccepted != 0 )
\r
3520 if( FreeRTOS_tx_space( pxSocket ) > 0 )
\r
3526 if( bMatch == pdFALSE )
\r
3528 if( ( pxSocket->u.xTCP.bits.bConnPrepared != pdFALSE_UNSIGNED ) &&
\r
3529 ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) &&
\r
3530 ( pxSocket->u.xTCP.bits.bConnPassed == pdFALSE_UNSIGNED ) )
\r
3532 pxSocket->u.xTCP.bits.bConnPassed = pdTRUE_UNSIGNED;
\r
3537 if( bMatch != pdFALSE )
\r
3539 xSocketBits |= eSELECT_WRITE;
\r
3544 #endif /* ipconfigUSE_TCP == 1 */
\r
3546 /* Select events for UDP are simpler. */
\r
3547 if( ( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 ) &&
\r
3548 ( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) > 0U ) )
\r
3550 xSocketBits |= eSELECT_READ;
\r
3552 /* The WRITE and EXCEPT bits are not used for UDP */
\r
3553 } /* if( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP ) */
\r
3555 /* Each socket keeps its own event flags, which are looked-up
\r
3556 by FreeRTOS_FD_ISSSET() */
\r
3557 pxSocket->xSocketBits = xSocketBits;
\r
3559 /* The ORed value will be used to set the bits in the event
\r
3561 xGroupBits |= xSocketBits;
\r
3563 } /* for( pxIterator ... ) */
\r
3564 } /* for( xRound = 0; xRound <= xLastRound; xRound++ ) */
\r
3566 xBitsToClear = xEventGroupGetBits( pxSocketSet->xSelectGroup );
\r
3568 /* Now set the necessary bits. */
\r
3569 xBitsToClear = ( xBitsToClear & ~xGroupBits ) & eSELECT_ALL;
\r
3571 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
3573 /* Maybe the socketset was signalled, but don't
\r
3574 clear the 'eSELECT_INTR' bit here, as it will be used
\r
3575 and cleared in FreeRTOS_select(). */
\r
3576 xBitsToClear &= ( EventBits_t ) ~eSELECT_INTR;
\r
3578 #endif /* ipconfigSUPPORT_SIGNALS */
\r
3580 if( xBitsToClear != 0 )
\r
3582 xEventGroupClearBits( pxSocketSet->xSelectGroup, xBitsToClear );
\r
3585 /* Now include eSELECT_CALL_IP to wakeup the caller. */
\r
3586 xEventGroupSetBits( pxSocketSet->xSelectGroup, xGroupBits | eSELECT_CALL_IP );
\r
3589 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
3590 /*-----------------------------------------------------------*/
\r
3592 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
3594 /* Send a signal to the task which reads from this socket. */
\r
3595 BaseType_t FreeRTOS_SignalSocket( Socket_t xSocket )
\r
3597 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3598 BaseType_t xReturn;
\r
3600 if( pxSocket == NULL )
\r
3602 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3605 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
3606 if( ( pxSocket->pxSocketSet != NULL ) && ( pxSocket->pxSocketSet->xSelectGroup != NULL ) )
\r
3608 xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, eSELECT_INTR );
\r
3612 #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
\r
3613 if( pxSocket->xEventGroup != NULL )
\r
3615 xEventGroupSetBits( pxSocket->xEventGroup, eSOCKET_INTR );
\r
3620 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3626 #endif /* ipconfigSUPPORT_SIGNALS */
\r
3627 /*-----------------------------------------------------------*/
\r
3629 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
3631 /* Send a signal to the task which reads from this socket (FromISR version). */
\r
3632 BaseType_t FreeRTOS_SignalSocketFromISR( Socket_t xSocket, BaseType_t *pxHigherPriorityTaskWoken )
\r
3634 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3635 BaseType_t xReturn;
\r
3636 IPStackEvent_t xEvent;
\r
3637 extern QueueHandle_t xNetworkEventQueue;
\r
3639 configASSERT( pxSocket != NULL );
\r
3640 configASSERT( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP );
\r
3641 configASSERT( pxSocket->xEventGroup );
\r
3643 xEvent.eEventType = eSocketSignalEvent;
\r
3644 xEvent.pvData = ( void * )pxSocket;
\r
3646 /* The IP-task will call FreeRTOS_SignalSocket for this socket. */
\r
3647 xReturn = xQueueSendToBackFromISR( xNetworkEventQueue, &xEvent, pxHigherPriorityTaskWoken );
\r
3652 #endif /* ipconfigSUPPORT_SIGNALS */
\r
3653 /*-----------------------------------------------------------*/
\r