2 * FreeRTOS+TCP V2.0.0
\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. If you wish to use our Amazon
\r
14 * FreeRTOS name, please do so in a fair use way that does not cause confusion.
\r
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
\r
18 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
\r
19 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
\r
20 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
23 * http://www.FreeRTOS.org
\r
24 * http://aws.amazon.com/freertos
\r
26 * 1 tab == 4 spaces!
\r
29 /* Standard includes. */
\r
33 /* FreeRTOS includes. */
\r
34 #include "FreeRTOS.h"
\r
39 /* FreeRTOS+TCP includes. */
\r
40 #include "FreeRTOS_UDP_IP.h"
\r
41 #include "FreeRTOS_IP.h"
\r
42 #include "FreeRTOS_Sockets.h"
\r
43 #include "FreeRTOS_IP_Private.h"
\r
44 #include "FreeRTOS_DNS.h"
\r
45 #include "NetworkBufferManagement.h"
\r
47 /* The ItemValue of the sockets xBoundSocketListItem member holds the socket's
\r
49 #define socketSET_SOCKET_PORT( pxSocket, usPort ) listSET_LIST_ITEM_VALUE( ( &( ( pxSocket )->xBoundSocketListItem ) ), ( usPort ) )
\r
50 #define socketGET_SOCKET_PORT( pxSocket ) listGET_LIST_ITEM_VALUE( ( &( ( pxSocket )->xBoundSocketListItem ) ) )
\r
52 /* Test if a socket it bound which means it is either included in
\r
53 xBoundUDPSocketsList or xBoundTCPSocketsList */
\r
54 #define socketSOCKET_IS_BOUND( pxSocket ) ( listLIST_ITEM_CONTAINER( & ( pxSocket )->xBoundSocketListItem ) != NULL )
\r
56 /* If FreeRTOS_sendto() is called on a socket that is not bound to a port
\r
57 number then, depending on the FreeRTOSIPConfig.h settings, it might be that a
\r
58 port number is automatically generated for the socket. Automatically generated
\r
59 port numbers will be between socketAUTO_PORT_ALLOCATION_START_NUMBER and
\r
61 /* _HT_ thinks that the default of 0xc000 is pretty high */
\r
62 #if !defined( socketAUTO_PORT_ALLOCATION_START_NUMBER )
\r
63 #define socketAUTO_PORT_ALLOCATION_START_NUMBER ( ( uint16_t ) 0xc000 )
\r
66 /* When the automatically generated port numbers overflow, the next value used
\r
67 is not set back to socketAUTO_PORT_ALLOCATION_START_NUMBER because it is likely
\r
68 that the first few automatically generated ports will still be in use. Instead
\r
69 it is reset back to the value defined by this constant. */
\r
70 #define socketAUTO_PORT_ALLOCATION_RESET_NUMBER ( ( uint16_t ) 0xc100 )
\r
71 #define socketAUTO_PORT_ALLOCATION_MAX_NUMBER ( ( uint16_t ) 0xff00 )
\r
73 /* The number of octets that make up an IP address. */
\r
74 #define socketMAX_IP_ADDRESS_OCTETS 4u
\r
76 /* A block time of 0 simply means "don't block". */
\r
77 #define socketDONT_BLOCK ( ( TickType_t ) 0 )
\r
79 #if( ( ipconfigUSE_TCP == 1 ) && !defined( ipTCP_TIMER_PERIOD_MS ) )
\r
80 #define ipTCP_TIMER_PERIOD_MS ( 1000 )
\r
83 /* The next private port number to use when binding a client socket is stored in
\r
84 the usNextPortToUse[] array - which has either 1 or two indexes depending on
\r
85 whether TCP is being supported. */
\r
86 #if( ipconfigUSE_TCP == 1 )
\r
87 #define socketPROTOCOL_COUNT 2
\r
89 #define socketPROTOCOL_COUNT 1
\r
92 /* Indexes into the usNextPortToUse[] array for UDP and TCP sockets
\r
94 #define socketNEXT_UDP_PORT_NUMBER_INDEX 0
\r
95 #define socketNEXT_TCP_PORT_NUMBER_INDEX 1
\r
98 /*-----------------------------------------------------------*/
\r
101 * Allocate the next port number from the private allocation range.
\r
102 * TCP and UDP each have their own series of port numbers
\r
103 * ulProtocol is either ipPROTOCOL_UDP or ipPROTOCOL_TCP
\r
105 static uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol );
\r
108 * Return the list item from within pxList that has an item value of
\r
109 * xWantedItemValue. If there is no such list item return NULL.
\r
111 static const ListItem_t * pxListFindListItemWithValue( const List_t *pxList, TickType_t xWantedItemValue );
\r
114 * Return pdTRUE only if pxSocket is valid and bound, as far as can be
\r
117 static BaseType_t prvValidSocket( FreeRTOS_Socket_t *pxSocket, BaseType_t xProtocol, BaseType_t xIsBound );
\r
120 * Before creating a socket, check the validity of the parameters used
\r
121 * and find the size of the socket space, which is different for UDP and TCP
\r
123 static BaseType_t prvDetermineSocketSize( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol, size_t *pxSocketSize );
\r
125 #if( ipconfigUSE_TCP == 1 )
\r
127 * Create a txStream or a rxStream, depending on the parameter 'xIsInputStream'
\r
129 static StreamBuffer_t *prvTCPCreateStream (FreeRTOS_Socket_t *pxSocket, BaseType_t xIsInputStream );
\r
130 #endif /* ipconfigUSE_TCP == 1 */
\r
132 #if( ipconfigUSE_TCP == 1 )
\r
134 * Called from FreeRTOS_send(): some checks which will be done before
\r
135 * sending a TCP packed.
\r
137 static int32_t prvTCPSendCheck( FreeRTOS_Socket_t *pxSocket, size_t xDataLength );
\r
138 #endif /* ipconfigUSE_TCP */
\r
140 #if( ipconfigUSE_TCP == 1 )
\r
142 * When a child socket gets closed, make sure to update the child-count of the parent
\r
144 static void prvTCPSetSocketCount( FreeRTOS_Socket_t *pxSocketToDelete );
\r
145 #endif /* ipconfigUSE_TCP == 1 */
\r
147 #if( ipconfigUSE_TCP == 1 )
\r
149 * Called from FreeRTOS_connect(): make some checks and if allowed, send a
\r
150 * message to the IP-task to start connecting to a remote socket
\r
152 static BaseType_t prvTCPConnectStart( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr *pxAddress );
\r
153 #endif /* ipconfigUSE_TCP */
\r
155 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
157 /* Executed by the IP-task, it will check all sockets belonging to a set */
\r
158 static FreeRTOS_Socket_t *prvFindSelectedSocket( SocketSelect_t *pxSocketSet );
\r
160 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
161 /*-----------------------------------------------------------*/
\r
163 /* The list that contains mappings between sockets and port numbers. Accesses
\r
164 to this list must be protected by critical sections of one kind or another. */
\r
165 List_t xBoundUDPSocketsList;
\r
167 #if ipconfigUSE_TCP == 1
\r
168 List_t xBoundTCPSocketsList;
\r
169 #endif /* ipconfigUSE_TCP == 1 */
\r
171 /* Holds the next private port number to use when binding a client socket for
\r
172 UDP, and if ipconfigUSE_TCP is set to 1, also TCP. UDP uses index
\r
173 socketNEXT_UDP_PORT_NUMBER_INDEX and TCP uses index
\r
174 socketNEXT_TCP_PORT_NUMBER_INDEX. The initial value is set to be between
\r
175 socketAUTO_PORT_ALLOCATION_RESET_NUMBER and socketAUTO_PORT_ALLOCATION_MAX_NUMBER
\r
176 when the IP stack is initialised. Note ipconfigRAND32() is used, which must be
\r
177 seeded prior to the IP task being started. */
\r
178 static uint16_t usNextPortToUse[ socketPROTOCOL_COUNT ] = { 0 };
\r
180 /*-----------------------------------------------------------*/
\r
182 static BaseType_t prvValidSocket( FreeRTOS_Socket_t *pxSocket, BaseType_t xProtocol, BaseType_t xIsBound )
\r
184 BaseType_t xReturn = pdTRUE;
\r
186 if( ( pxSocket == NULL ) || ( pxSocket == FREERTOS_INVALID_SOCKET ) )
\r
190 else if( ( xIsBound != pdFALSE ) && ( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE ) )
\r
192 /* The caller expects the socket to be bound, but it isn't. */
\r
195 else if( pxSocket->ucProtocol != ( uint8_t ) xProtocol )
\r
197 /* Socket has a wrong type (UDP != TCP). */
\r
203 /*-----------------------------------------------------------*/
\r
205 void vNetworkSocketsInit( void )
\r
207 const uint32_t ulAutoPortRange = socketAUTO_PORT_ALLOCATION_MAX_NUMBER - socketAUTO_PORT_ALLOCATION_RESET_NUMBER;
\r
208 uint32_t ulRandomPort;
\r
210 vListInitialise( &xBoundUDPSocketsList );
\r
212 /* Determine the first anonymous UDP port number to get assigned. Give it
\r
213 a random value in order to avoid confusion about port numbers being used
\r
214 earlier, before rebooting the device. Start with the first auto port
\r
215 number, then add a random offset up to a maximum of the range of numbers. */
\r
216 ulRandomPort = socketAUTO_PORT_ALLOCATION_START_NUMBER;
\r
217 ulRandomPort += ( ipconfigRAND32() % ulAutoPortRange );
\r
218 usNextPortToUse[ socketNEXT_UDP_PORT_NUMBER_INDEX ] = ( uint16_t ) ulRandomPort;
\r
220 #if( ipconfigUSE_TCP == 1 )
\r
222 extern uint32_t ulNextInitialSequenceNumber;
\r
224 ulNextInitialSequenceNumber = ipconfigRAND32();
\r
226 /* Determine the first anonymous TCP port number to get assigned. */
\r
227 ulRandomPort = socketAUTO_PORT_ALLOCATION_START_NUMBER;
\r
228 ulRandomPort += ( ipconfigRAND32() % ulAutoPortRange );
\r
229 usNextPortToUse[ socketNEXT_TCP_PORT_NUMBER_INDEX ] = ( uint16_t ) ulRandomPort;
\r
231 vListInitialise( &xBoundTCPSocketsList );
\r
233 #endif /* ipconfigUSE_TCP == 1 */
\r
235 /*-----------------------------------------------------------*/
\r
237 static BaseType_t prvDetermineSocketSize( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol, size_t *pxSocketSize )
\r
239 BaseType_t xReturn = pdPASS;
\r
240 FreeRTOS_Socket_t *pxSocket;
\r
242 /* Asserts must not appear before it has been determined that the network
\r
243 task is ready - otherwise the asserts will fail. */
\r
244 if( xIPIsNetworkTaskReady() == pdFALSE )
\r
250 /* Only Ethernet is currently supported. */
\r
251 configASSERT( xDomain == FREERTOS_AF_INET );
\r
253 /* Check if the UDP socket-list has been initialised. */
\r
254 configASSERT( listLIST_IS_INITIALISED( &xBoundUDPSocketsList ) );
\r
255 #if( ipconfigUSE_TCP == 1 )
\r
257 /* Check if the TCP socket-list has been initialised. */
\r
258 configASSERT( listLIST_IS_INITIALISED( &xBoundTCPSocketsList ) );
\r
260 #endif /* ipconfigUSE_TCP == 1 */
\r
262 if( xProtocol == FREERTOS_IPPROTO_UDP )
\r
264 if( xType != FREERTOS_SOCK_DGRAM )
\r
268 /* In case a UDP socket is created, do not allocate space for TCP data. */
\r
269 *pxSocketSize = ( sizeof( *pxSocket ) - sizeof( pxSocket->u ) ) + sizeof( pxSocket->u.xUDP );
\r
271 #if( ipconfigUSE_TCP == 1 )
\r
272 else if( xProtocol == FREERTOS_IPPROTO_TCP )
\r
274 if( xType != FREERTOS_SOCK_STREAM )
\r
279 *pxSocketSize = ( sizeof( *pxSocket ) - sizeof( pxSocket->u ) ) + sizeof( pxSocket->u.xTCP );
\r
281 #endif /* ipconfigUSE_TCP == 1 */
\r
287 /* In case configASSERT() is not used */
\r
291 /*-----------------------------------------------------------*/
\r
293 /* FreeRTOS_socket() allocates and initiates a socket */
\r
294 Socket_t FreeRTOS_socket( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol )
\r
296 FreeRTOS_Socket_t *pxSocket;
\r
297 size_t uxSocketSize;
\r
298 EventGroupHandle_t xEventGroup;
\r
301 if( prvDetermineSocketSize( xDomain, xType, xProtocol, &uxSocketSize ) == pdFAIL )
\r
303 xReturn = FREERTOS_INVALID_SOCKET;
\r
307 /* Allocate the structure that will hold the socket information. The
\r
308 size depends on the type of socket: UDP sockets need less space. A
\r
309 define 'pvPortMallocSocket' will used to allocate the necessary space.
\r
310 By default it points to the FreeRTOS function 'pvPortMalloc()'. */
\r
311 pxSocket = ( FreeRTOS_Socket_t * ) pvPortMallocSocket( uxSocketSize );
\r
313 if( pxSocket == NULL )
\r
315 pxSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
\r
316 iptraceFAILED_TO_CREATE_SOCKET();
\r
318 else if( ( xEventGroup = xEventGroupCreate() ) == NULL )
\r
320 vPortFreeSocket( pxSocket );
\r
321 pxSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
\r
322 iptraceFAILED_TO_CREATE_EVENT_GROUP();
\r
326 /* Clear the entire space to avoid nulling individual entries. */
\r
327 memset( pxSocket, '\0', uxSocketSize );
\r
329 pxSocket->xEventGroup = xEventGroup;
\r
331 /* Initialise the socket's members. The semaphore will be created
\r
332 if the socket is bound to an address, for now the pointer to the
\r
333 semaphore is just set to NULL to show it has not been created. */
\r
334 if( xProtocol == FREERTOS_IPPROTO_UDP )
\r
336 vListInitialise( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
\r
338 #if( ipconfigUDP_MAX_RX_PACKETS > 0 )
\r
340 pxSocket->u.xUDP.uxMaxPackets = ( UBaseType_t ) ipconfigUDP_MAX_RX_PACKETS;
\r
342 #endif /* ipconfigUDP_MAX_RX_PACKETS > 0 */
\r
345 vListInitialiseItem( &( pxSocket->xBoundSocketListItem ) );
\r
346 listSET_LIST_ITEM_OWNER( &( pxSocket->xBoundSocketListItem ), ( void * ) pxSocket );
\r
348 pxSocket->xReceiveBlockTime = ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME;
\r
349 pxSocket->xSendBlockTime = ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME;
\r
350 pxSocket->ucSocketOptions = ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT;
\r
351 pxSocket->ucProtocol = ( uint8_t ) xProtocol; /* protocol: UDP or TCP */
\r
353 #if( ipconfigUSE_TCP == 1 )
\r
355 if( xProtocol == FREERTOS_IPPROTO_TCP )
\r
357 /* StreamSize is expressed in number of bytes */
\r
358 /* Round up buffer sizes to nearest multiple of MSS */
\r
359 pxSocket->u.xTCP.usInitMSS = pxSocket->u.xTCP.usCurMSS = ipconfigTCP_MSS;
\r
360 pxSocket->u.xTCP.uxRxStreamSize = ( size_t ) ipconfigTCP_RX_BUFFER_LENGTH;
\r
361 pxSocket->u.xTCP.uxTxStreamSize = ( size_t ) FreeRTOS_round_up( ipconfigTCP_TX_BUFFER_LENGTH, ipconfigTCP_MSS );
\r
362 /* Use half of the buffer size of the TCP windows */
\r
363 #if ( ipconfigUSE_TCP_WIN == 1 )
\r
365 pxSocket->u.xTCP.uxRxWinSize = FreeRTOS_max_uint32( 1UL, ( uint32_t ) ( pxSocket->u.xTCP.uxRxStreamSize / 2 ) / ipconfigTCP_MSS );
\r
366 pxSocket->u.xTCP.uxTxWinSize = FreeRTOS_max_uint32( 1UL, ( uint32_t ) ( pxSocket->u.xTCP.uxTxStreamSize / 2 ) / ipconfigTCP_MSS );
\r
370 pxSocket->u.xTCP.uxRxWinSize = 1u;
\r
371 pxSocket->u.xTCP.uxTxWinSize = 1u;
\r
374 /* The above values are just defaults, and can be overridden by
\r
375 calling FreeRTOS_setsockopt(). No buffers will be allocated until a
\r
376 socket is connected and data is exchanged. */
\r
379 #endif /* ipconfigUSE_TCP == 1 */
\r
382 xReturn = ( Socket_t ) pxSocket;
\r
385 /* Remove compiler warnings in the case the configASSERT() is not defined. */
\r
390 /*-----------------------------------------------------------*/
\r
392 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
394 SocketSet_t FreeRTOS_CreateSocketSet( void )
\r
396 SocketSelect_t *pxSocketSet;
\r
398 pxSocketSet = ( SocketSelect_t * ) pvPortMalloc( sizeof( *pxSocketSet ) );
\r
400 if( pxSocketSet != NULL )
\r
402 memset( pxSocketSet, '\0', sizeof( *pxSocketSet ) );
\r
403 pxSocketSet->xSelectGroup = xEventGroupCreate();
\r
405 if( pxSocketSet->xSelectGroup == NULL )
\r
407 vPortFree( ( void* ) pxSocketSet );
\r
408 pxSocketSet = NULL;
\r
412 return ( SocketSet_t * ) pxSocketSet;
\r
415 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
416 /*-----------------------------------------------------------*/
\r
418 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
420 void FreeRTOS_DeleteSocketSet( SocketSet_t xSocketSet )
\r
422 SocketSelect_t *pxSocketSet = ( SocketSelect_t*) xSocketSet;
\r
424 vEventGroupDelete( pxSocketSet->xSelectGroup );
\r
425 vPortFree( ( void* ) pxSocketSet );
\r
428 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
429 /*-----------------------------------------------------------*/
\r
431 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
433 /* Add a socket to a set */
\r
434 void FreeRTOS_FD_SET( Socket_t xSocket, SocketSet_t xSocketSet, EventBits_t xSelectBits )
\r
436 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
437 SocketSelect_t *pxSocketSet = ( SocketSelect_t * ) xSocketSet;
\r
439 configASSERT( pxSocket != NULL );
\r
440 configASSERT( xSocketSet != NULL );
\r
442 /* Make sure we're not adding bits which are reserved for internal use,
\r
443 such as eSELECT_CALL_IP */
\r
444 pxSocket->xSelectBits |= ( xSelectBits & eSELECT_ALL );
\r
446 if( ( pxSocket->xSelectBits & eSELECT_ALL ) != 0 )
\r
448 /* Adding a socket to a socket set. */
\r
449 pxSocket->pxSocketSet = ( SocketSelect_t * ) xSocketSet;
\r
451 /* Now have the IP-task call vSocketSelect() to see if the set contains
\r
452 any sockets which are 'ready' and set the proper bits.
\r
453 By setting 'bApiCalled = false', vSocketSelect() knows that it was
\r
454 not called from a user API */
\r
455 pxSocketSet->bApiCalled = pdFALSE;
\r
456 prvFindSelectedSocket( pxSocketSet );
\r
460 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
461 /*-----------------------------------------------------------*/
\r
463 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
464 /* Clear select bits for a socket
\r
465 If the mask becomes 0, remove the socket from the set */
\r
466 void FreeRTOS_FD_CLR( Socket_t xSocket, SocketSet_t xSocketSet, EventBits_t xSelectBits )
\r
468 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
470 configASSERT( pxSocket != NULL );
\r
471 configASSERT( xSocketSet != NULL );
\r
473 pxSocket->xSelectBits &= ~( xSelectBits & eSELECT_ALL );
\r
474 if( ( pxSocket->xSelectBits & eSELECT_ALL ) != 0 )
\r
476 pxSocket->pxSocketSet = ( SocketSelect_t *)xSocketSet;
\r
480 /* disconnect it from the socket set */
\r
481 pxSocket->pxSocketSet = ( SocketSelect_t *)NULL;
\r
485 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
486 /*-----------------------------------------------------------*/
\r
489 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
491 /* Test if a socket belongs to a socket-set */
\r
492 EventBits_t FreeRTOS_FD_ISSET( Socket_t xSocket, SocketSet_t xSocketSet )
\r
494 EventBits_t xReturn;
\r
495 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
497 configASSERT( pxSocket != NULL );
\r
498 configASSERT( xSocketSet != NULL );
\r
500 if( xSocketSet == ( SocketSet_t ) pxSocket->pxSocketSet )
\r
502 /* Make sure we're not adding bits which are reserved for internal
\r
504 xReturn = pxSocket->xSocketBits & eSELECT_ALL;
\r
514 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
515 /*-----------------------------------------------------------*/
\r
517 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
519 /* The select() statement: wait for an event to occur on any of the sockets
\r
520 included in a socket set */
\r
521 BaseType_t FreeRTOS_select( SocketSet_t xSocketSet, TickType_t xBlockTimeTicks )
\r
523 TimeOut_t xTimeOut;
\r
524 TickType_t xRemainingTime;
\r
525 SocketSelect_t *pxSocketSet = ( SocketSelect_t*) xSocketSet;
\r
526 BaseType_t xResult;
\r
528 configASSERT( xSocketSet != NULL );
\r
530 /* Only in the first round, check for non-blocking */
\r
531 xRemainingTime = xBlockTimeTicks;
\r
533 /* Fetch the current time */
\r
534 vTaskSetTimeOutState( &xTimeOut );
\r
538 /* Find a socket which might have triggered the bit
\r
539 This function might return immediately or block for a limited time */
\r
540 xResult = ( BaseType_t ) xEventGroupWaitBits( pxSocketSet->xSelectGroup, eSELECT_ALL, pdFALSE, pdFALSE, xRemainingTime );
\r
542 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
544 if( ( xResult & eSELECT_INTR ) != 0u )
\r
546 xEventGroupClearBits( pxSocketSet->xSelectGroup, eSELECT_INTR );
\r
547 FreeRTOS_debug_printf( ( "FreeRTOS_select: interrupted\n" ) );
\r
551 #endif /* ipconfigSUPPORT_SIGNALS */
\r
553 /* Have the IP-task find the socket which had an event */
\r
554 pxSocketSet->bApiCalled = pdTRUE;
\r
555 prvFindSelectedSocket( pxSocketSet );
\r
557 xResult = ( BaseType_t ) xEventGroupGetBits( pxSocketSet->xSelectGroup );
\r
564 /* Has the timeout been reached? */
\r
565 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
\r
574 #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
\r
575 /*-----------------------------------------------------------*/
\r
577 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
579 /* Send a message to the IP-task to have it check all sockets belonging to
\r
581 static FreeRTOS_Socket_t *prvFindSelectedSocket( SocketSelect_t *pxSocketSet )
\r
583 IPStackEvent_t xSelectEvent;
\r
584 FreeRTOS_Socket_t *xReturn;
\r
586 xSelectEvent.eEventType = eSocketSelectEvent;
\r
587 xSelectEvent.pvData = ( void * ) pxSocketSet;
\r
589 /* while the IP-task works on the request, the API will block on
\r
590 'eSELECT_CALL_IP'. So clear it first. */
\r
591 xEventGroupClearBits( pxSocketSet->xSelectGroup, eSELECT_CALL_IP );
\r
593 /* Now send the socket select event */
\r
594 if( xSendEventStructToIPTask( &xSelectEvent, ( TickType_t ) portMAX_DELAY ) == pdFAIL )
\r
596 /* Oops, we failed to wake-up the IP task. No use to wait for it. */
\r
597 FreeRTOS_debug_printf( ( "prvFindSelectedSocket: failed\n" ) );
\r
602 /* As soon as the IP-task is ready, it will set 'eSELECT_CALL_IP' to
\r
603 wakeup the calling API */
\r
604 xEventGroupWaitBits( pxSocketSet->xSelectGroup, eSELECT_CALL_IP, pdTRUE, pdFALSE, portMAX_DELAY );
\r
606 /* Return 'pxSocket' which is set by the IP-task */
\r
607 xReturn = pxSocketSet->pxSocket;
\r
613 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
614 /*-----------------------------------------------------------*/
\r
617 * FreeRTOS_recvfrom: receive data from a bound socket
\r
618 * In this library, the function can only be used with connectionsless sockets
\r
621 int32_t FreeRTOS_recvfrom( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags, struct freertos_sockaddr *pxSourceAddress, socklen_t *pxSourceAddressLength )
\r
623 BaseType_t lPacketCount = 0;
\r
624 NetworkBufferDescriptor_t *pxNetworkBuffer;
\r
625 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
626 TickType_t xRemainingTime = ( TickType_t ) 0; /* Obsolete assignment, but some compilers output a warning if its not done. */
\r
627 BaseType_t xTimed = pdFALSE;
\r
628 TimeOut_t xTimeOut;
\r
630 EventBits_t xEventBits = ( EventBits_t ) 0;
\r
632 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_UDP, pdTRUE ) == pdFALSE )
\r
634 return -pdFREERTOS_ERRNO_EINVAL;
\r
637 lPacketCount = ( BaseType_t ) listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
\r
639 /* The function prototype is designed to maintain the expected Berkeley
\r
640 sockets standard, but this implementation does not use all the parameters. */
\r
641 ( void ) pxSourceAddressLength;
\r
643 while( lPacketCount == 0 )
\r
645 if( xTimed == pdFALSE )
\r
647 /* Check to see if the socket is non blocking on the first
\r
649 xRemainingTime = pxSocket->xReceiveBlockTime;
\r
651 if( xRemainingTime == ( TickType_t ) 0 )
\r
653 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
655 /* Just check for the interrupt flag. */
\r
656 xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_INTR,
\r
657 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, socketDONT_BLOCK );
\r
659 #endif /* ipconfigSUPPORT_SIGNALS */
\r
663 if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
\r
668 /* To ensure this part only executes once. */
\r
671 /* Fetch the current time. */
\r
672 vTaskSetTimeOutState( &xTimeOut );
\r
675 /* Wait for arrival of data. While waiting, the IP-task may set the
\r
676 'eSOCKET_RECEIVE' bit in 'xEventGroup', if it receives data for this
\r
677 socket, thus unblocking this API call. */
\r
678 xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_RECEIVE | eSOCKET_INTR,
\r
679 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
681 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
683 if( ( xEventBits & eSOCKET_INTR ) != 0 )
\r
685 if( ( xEventBits & eSOCKET_RECEIVE ) != 0 )
\r
687 /* Shouldn't have cleared the eSOCKET_RECEIVE flag. */
\r
688 xEventGroupSetBits( pxSocket->xEventGroup, eSOCKET_RECEIVE );
\r
695 ( void ) xEventBits;
\r
697 #endif /* ipconfigSUPPORT_SIGNALS */
\r
699 lPacketCount = ( BaseType_t ) listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
\r
701 if( lPacketCount != 0 )
\r
706 /* Has the timeout been reached ? */
\r
707 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) )
\r
711 } /* while( lPacketCount == 0 ) */
\r
713 if( lPacketCount != 0 )
\r
715 taskENTER_CRITICAL();
\r
717 /* The owner of the list item is the network buffer. */
\r
718 pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
\r
720 if( ( xFlags & FREERTOS_MSG_PEEK ) == 0 )
\r
722 /* Remove the network buffer from the list of buffers waiting to
\r
723 be processed by the socket. */
\r
724 uxListRemove( &( pxNetworkBuffer->xBufferListItem ) );
\r
727 taskEXIT_CRITICAL();
\r
729 /* The returned value is the data length, which may have been capped to
\r
730 the receive buffer size. */
\r
731 lReturn = ( int32_t ) pxNetworkBuffer->xDataLength;
\r
733 if( pxSourceAddress != NULL )
\r
735 pxSourceAddress->sin_port = pxNetworkBuffer->usPort;
\r
736 pxSourceAddress->sin_addr = pxNetworkBuffer->ulIPAddress;
\r
739 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
\r
741 /* The zero copy flag is not set. Truncate the length if it won't
\r
742 fit in the provided buffer. */
\r
743 if( lReturn > ( int32_t ) xBufferLength )
\r
745 iptraceRECVFROM_DISCARDING_BYTES( ( xBufferLength - lReturn ) );
\r
746 lReturn = ( int32_t )xBufferLength;
\r
749 /* Copy the received data into the provided buffer, then release the
\r
751 memcpy( pvBuffer, ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ), ( size_t )lReturn );
\r
753 if( ( xFlags & FREERTOS_MSG_PEEK ) == 0 )
\r
755 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
\r
760 /* The zero copy flag was set. pvBuffer is not a buffer into which
\r
761 the received data can be copied, but a pointer that must be set to
\r
762 point to the buffer in which the received data has already been
\r
764 *( ( void** ) pvBuffer ) = ( void * ) ( &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ) );
\r
768 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
769 else if( ( xEventBits & eSOCKET_INTR ) != 0 )
\r
771 lReturn = -pdFREERTOS_ERRNO_EINTR;
\r
772 iptraceRECVFROM_INTERRUPTED();
\r
774 #endif /* ipconfigSUPPORT_SIGNALS */
\r
777 lReturn = -pdFREERTOS_ERRNO_EWOULDBLOCK;
\r
778 iptraceRECVFROM_TIMEOUT();
\r
783 /*-----------------------------------------------------------*/
\r
785 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
787 NetworkBufferDescriptor_t *pxNetworkBuffer;
\r
788 IPStackEvent_t xStackTxEvent = { eStackTxEvent, NULL };
\r
789 TimeOut_t xTimeOut;
\r
790 TickType_t xTicksToWait;
\r
791 int32_t lReturn = 0;
\r
792 FreeRTOS_Socket_t *pxSocket;
\r
794 pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
796 /* The function prototype is designed to maintain the expected Berkeley
\r
797 sockets standard, but this implementation does not use all the
\r
799 ( void ) xDestinationAddressLength;
\r
800 configASSERT( pvBuffer );
\r
802 if( xTotalDataLength <= ( size_t ) ipMAX_UDP_PAYLOAD_LENGTH )
\r
804 /* If the socket is not already bound to an address, bind it now.
\r
805 Passing NULL as the address parameter tells FreeRTOS_bind() to select
\r
806 the address to bind to. */
\r
807 if( ( socketSOCKET_IS_BOUND( pxSocket ) != pdFALSE ) ||
\r
808 ( FreeRTOS_bind( xSocket, NULL, 0u ) == 0 ) )
\r
810 xTicksToWait = pxSocket->xSendBlockTime;
\r
812 #if( ipconfigUSE_CALLBACKS != 0 )
\r
814 if( xIsCallingFromIPTask() != pdFALSE )
\r
816 /* If this send function is called from within a call-back
\r
817 handler it may not block, otherwise chances would be big to
\r
818 get a deadlock: the IP-task waiting for itself. */
\r
819 xTicksToWait = ( TickType_t )0;
\r
822 #endif /* ipconfigUSE_CALLBACKS */
\r
824 if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
\r
826 xTicksToWait = ( TickType_t ) 0;
\r
829 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
\r
831 /* Zero copy is not set, so obtain a network buffer into
\r
832 which the payload will be copied. */
\r
833 vTaskSetTimeOutState( &xTimeOut );
\r
835 /* Block until a buffer becomes available, or until a
\r
836 timeout has been reached */
\r
837 pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( xTotalDataLength + sizeof( UDPPacket_t ), xTicksToWait );
\r
839 if( pxNetworkBuffer != NULL )
\r
841 memcpy( ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ), ( void * ) pvBuffer, xTotalDataLength );
\r
843 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdTRUE )
\r
845 /* The entire block time has been used up. */
\r
846 xTicksToWait = ( TickType_t ) 0;
\r
852 /* When zero copy is used, pvBuffer is a pointer to the
\r
853 payload of a buffer that has already been obtained from the
\r
854 stack. Obtain the network buffer pointer from the buffer. */
\r
855 pxNetworkBuffer = pxUDPPayloadBuffer_to_NetworkBuffer( (void*)pvBuffer );
\r
858 if( pxNetworkBuffer != NULL )
\r
860 pxNetworkBuffer->xDataLength = xTotalDataLength;
\r
861 pxNetworkBuffer->usPort = pxDestinationAddress->sin_port;
\r
862 pxNetworkBuffer->usBoundPort = ( uint16_t ) socketGET_SOCKET_PORT( pxSocket );
\r
863 pxNetworkBuffer->ulIPAddress = pxDestinationAddress->sin_addr;
\r
865 /* The socket options are passed to the IP layer in the
\r
866 space that will eventually get used by the Ethernet header. */
\r
867 pxNetworkBuffer->pucEthernetBuffer[ ipSOCKET_OPTIONS_OFFSET ] = pxSocket->ucSocketOptions;
\r
869 /* Tell the networking task that the packet needs sending. */
\r
870 xStackTxEvent.pvData = pxNetworkBuffer;
\r
872 /* Ask the IP-task to send this packet */
\r
873 if( xSendEventStructToIPTask( &xStackTxEvent, xTicksToWait ) == pdPASS )
\r
875 /* The packet was successfully sent to the IP task. */
\r
876 lReturn = ( int32_t ) xTotalDataLength;
\r
877 #if( ipconfigUSE_CALLBACKS == 1 )
\r
879 if( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xUDP.pxHandleSent ) )
\r
881 pxSocket->u.xUDP.pxHandleSent( (Socket_t *)pxSocket, xTotalDataLength );
\r
884 #endif /* ipconfigUSE_CALLBACKS */
\r
888 /* If the buffer was allocated in this function, release
\r
890 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
\r
892 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
\r
894 iptraceSTACK_TX_EVENT_LOST( ipSTACK_TX_EVENT );
\r
899 /* If errno was available, errno would be set to
\r
900 FREERTOS_ENOPKTS. As it is, the function must return the
\r
901 number of transmitted bytes, so the calling function knows
\r
902 how much data was actually sent. */
\r
903 iptraceNO_BUFFER_FOR_SENDTO();
\r
908 iptraceSENDTO_SOCKET_NOT_BOUND();
\r
913 /* The data is longer than the available buffer space. */
\r
914 iptraceSENDTO_DATA_TOO_LONG();
\r
919 /*-----------------------------------------------------------*/
\r
922 * FreeRTOS_bind() : binds a sockt to a local port number. If port 0 is
\r
923 * provided, a system provided port number will be assigned. This function can
\r
924 * be used for both UDP and TCP sockets. The actual binding will be performed
\r
925 * by the IP-task to avoid mutual access to the bound-socket-lists
\r
926 * (xBoundUDPSocketsList or xBoundTCPSocketsList).
\r
928 BaseType_t FreeRTOS_bind( Socket_t xSocket, struct freertos_sockaddr * pxAddress, socklen_t xAddressLength )
\r
930 IPStackEvent_t xBindEvent;
\r
931 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
932 BaseType_t xReturn = 0;
\r
934 ( void ) xAddressLength;
\r
936 if( ( pxSocket == NULL ) || ( pxSocket == FREERTOS_INVALID_SOCKET ) )
\r
938 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
940 /* Once a socket is bound to a port, it can not be bound to a different
\r
942 else if( socketSOCKET_IS_BOUND( pxSocket) != pdFALSE )
\r
944 /* The socket is already bound. */
\r
945 FreeRTOS_debug_printf( ( "vSocketBind: Socket already bound to %d\n", pxSocket->usLocalPort ) );
\r
946 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
950 /* Prepare a messages to the IP-task in order to perform the binding.
\r
951 The desired port number will be passed in usLocalPort. */
\r
952 xBindEvent.eEventType = eSocketBindEvent;
\r
953 xBindEvent.pvData = ( void * ) xSocket;
\r
954 if( pxAddress != NULL )
\r
956 pxSocket->usLocalPort = FreeRTOS_ntohs( pxAddress->sin_port );
\r
960 /* Caller wants to bind to a random port number. */
\r
961 pxSocket->usLocalPort = 0u;
\r
964 /* portMAX_DELAY is used as a the time-out parameter, as binding *must*
\r
965 succeed before the socket can be used. _RB_ The use of an infinite
\r
966 block time needs be changed as it could result in the task hanging. */
\r
967 if( xSendEventStructToIPTask( &xBindEvent, ( TickType_t ) portMAX_DELAY ) == pdFAIL )
\r
969 /* Failed to wake-up the IP-task, no use to wait for it */
\r
970 FreeRTOS_debug_printf( ( "FreeRTOS_bind: send event failed\n" ) );
\r
971 xReturn = -pdFREERTOS_ERRNO_ECANCELED;
\r
975 /* The IP-task will set the 'eSOCKET_BOUND' bit when it has done its
\r
977 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_BOUND, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, portMAX_DELAY );
\r
978 if( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE )
\r
980 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
989 * vSocketBind(): internal version of bind() that should not be called directly.
\r
990 * 'xInternal' is used for TCP sockets only: it allows to have several
\r
991 * (connected) child sockets bound to the same server port.
\r
993 BaseType_t vSocketBind( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr * pxAddress, size_t uxAddressLength, BaseType_t xInternal )
\r
995 BaseType_t xReturn = 0; /* In Berkeley sockets, 0 means pass for bind(). */
\r
996 List_t *pxSocketList;
\r
997 #if( ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 )
\r
998 struct freertos_sockaddr xAddress;
\r
999 #endif /* ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND */
\r
1001 #if( ipconfigUSE_TCP == 1 )
\r
1002 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1004 pxSocketList = &xBoundTCPSocketsList;
\r
1007 #endif /* ipconfigUSE_TCP == 1 */
\r
1009 pxSocketList = &xBoundUDPSocketsList;
\r
1012 /* The function prototype is designed to maintain the expected Berkeley
\r
1013 sockets standard, but this implementation does not use all the parameters. */
\r
1014 ( void ) uxAddressLength;
\r
1016 configASSERT( pxSocket );
\r
1017 configASSERT( pxSocket != FREERTOS_INVALID_SOCKET );
\r
1019 #if( ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 )
\r
1021 /* pxAddress will be NULL if sendto() was called on a socket without the
\r
1022 socket being bound to an address. In this case, automatically allocate
\r
1023 an address to the socket. There is a very tiny chance that the allocated
\r
1024 port will already be in use - if that is the case, then the check below
\r
1025 [pxListFindListItemWithValue()] will result in an error being returned. */
\r
1026 if( pxAddress == NULL )
\r
1028 pxAddress = &xAddress;
\r
1029 /* For now, put it to zero, will be assigned later */
\r
1030 pxAddress->sin_port = 0u;
\r
1033 #endif /* ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 */
\r
1035 /* Sockets must be bound before calling FreeRTOS_sendto() if
\r
1036 ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is not set to 1. */
\r
1037 configASSERT( pxAddress );
\r
1039 if( pxAddress != NULL )
\r
1041 if( pxAddress->sin_port == 0u )
\r
1043 pxAddress->sin_port = prvGetPrivatePortNumber( ( BaseType_t ) pxSocket->ucProtocol );
\r
1046 /* If vSocketBind() is called from the API FreeRTOS_bind() it has been
\r
1047 confirmed that the socket was not yet bound to a port. If it is called
\r
1048 from the IP-task, no such check is necessary. */
\r
1050 /* Check to ensure the port is not already in use. If the bind is
\r
1051 called internally, a port MAY be used by more than one socket. */
\r
1052 if( ( ( xInternal == pdFALSE ) || ( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP ) ) &&
\r
1053 ( pxListFindListItemWithValue( pxSocketList, ( TickType_t ) pxAddress->sin_port ) != NULL ) )
\r
1055 FreeRTOS_debug_printf( ( "vSocketBind: %sP port %d in use\n",
\r
1056 pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP ? "TC" : "UD",
\r
1057 FreeRTOS_ntohs( pxAddress->sin_port ) ) );
\r
1058 xReturn = -pdFREERTOS_ERRNO_EADDRINUSE;
\r
1062 /* Allocate the port number to the socket.
\r
1063 This macro will set 'xBoundSocketListItem->xItemValue' */
\r
1064 socketSET_SOCKET_PORT( pxSocket, pxAddress->sin_port );
\r
1066 /* And also store it in a socket field 'usLocalPort' in host-byte-order,
\r
1067 mostly used for logging and debugging purposes */
\r
1068 pxSocket->usLocalPort = FreeRTOS_ntohs( pxAddress->sin_port );
\r
1070 /* Add the socket to the list of bound ports. */
\r
1072 /* If the network driver can iterate through 'xBoundUDPSocketsList',
\r
1073 by calling xPortHasUDPSocket() then the IP-task must temporarily
\r
1074 suspend the scheduler to keep the list in a consistent state. */
\r
1075 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1077 vTaskSuspendAll();
\r
1079 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1081 /* Add the socket to 'xBoundUDPSocketsList' or 'xBoundTCPSocketsList' */
\r
1082 vListInsertEnd( pxSocketList, &( pxSocket->xBoundSocketListItem ) );
\r
1084 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1088 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1094 xReturn = -pdFREERTOS_ERRNO_EADDRNOTAVAIL;
\r
1095 FreeRTOS_debug_printf( ( "vSocketBind: Socket no addr\n" ) );
\r
1098 if( xReturn != 0 )
\r
1100 iptraceBIND_FAILED( xSocket, ( FreeRTOS_ntohs( pxAddress->sin_port ) ) );
\r
1105 /*-----------------------------------------------------------*/
\r
1108 * Close a socket and free the allocated space
\r
1109 * In case of a TCP socket: the connection will not be closed automatically
\r
1110 * Subsequent messages for the closed socket will be responded to with a RST
\r
1111 * The IP-task will actually close the socket, after receiving a 'eSocketCloseEvent' message
\r
1113 BaseType_t FreeRTOS_closesocket( Socket_t xSocket )
\r
1115 BaseType_t xResult;
\r
1116 #if( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 )
\r
1117 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * )xSocket;
\r
1119 IPStackEvent_t xCloseEvent;
\r
1120 xCloseEvent.eEventType = eSocketCloseEvent;
\r
1121 xCloseEvent.pvData = ( void * ) xSocket;
\r
1123 if( ( xSocket == NULL ) || ( xSocket == FREERTOS_INVALID_SOCKET ) )
\r
1129 #if( ( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 ) )
\r
1131 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1133 /* Make sure that IP-task won't call the user callback's anymore */
\r
1134 pxSocket->u.xTCP.pxHandleConnected = NULL;
\r
1135 pxSocket->u.xTCP.pxHandleReceive = NULL;
\r
1136 pxSocket->u.xTCP.pxHandleSent = NULL;
\r
1139 #endif /* ( ( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 ) ) */
\r
1141 /* Let the IP task close the socket to keep it synchronised with the
\r
1142 packet handling. */
\r
1144 /* Note when changing the time-out value below, it must be checked who is calling
\r
1145 this function. If it is called by the IP-task, a deadlock could occur.
\r
1146 The IP-task would only call it in case of a user call-back */
\r
1147 if( xSendEventStructToIPTask( &xCloseEvent, ( TickType_t ) 0 ) == pdFAIL )
\r
1149 FreeRTOS_debug_printf( ( "FreeRTOS_closesocket: failed\n" ) );
\r
1161 /* This is the internal version of FreeRTOS_closesocket()
\r
1162 * It will be called by the IPtask only to avoid problems with synchronicity
\r
1164 void *vSocketClose( FreeRTOS_Socket_t *pxSocket )
\r
1166 NetworkBufferDescriptor_t *pxNetworkBuffer;
\r
1168 #if( ipconfigUSE_TCP == 1 )
\r
1170 /* For TCP: clean up a little more. */
\r
1171 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1173 #if( ipconfigUSE_TCP_WIN == 1 )
\r
1175 if( pxSocket->u.xTCP.pxAckMessage != NULL )
\r
1177 vReleaseNetworkBufferAndDescriptor( pxSocket->u.xTCP.pxAckMessage );
\r
1179 /* Free the resources which were claimed by the tcpWin member */
\r
1180 vTCPWindowDestroy( &pxSocket->u.xTCP.xTCPWindow );
\r
1182 #endif /* ipconfigUSE_TCP_WIN */
\r
1184 /* Free the input and output streams */
\r
1185 if( pxSocket->u.xTCP.rxStream != NULL )
\r
1187 vPortFreeLarge( pxSocket->u.xTCP.rxStream );
\r
1190 if( pxSocket->u.xTCP.txStream != NULL )
\r
1192 vPortFreeLarge( pxSocket->u.xTCP.txStream );
\r
1195 /* In case this is a child socket, make sure the child-count of the
\r
1196 parent socket is decreased. */
\r
1197 prvTCPSetSocketCount( pxSocket );
\r
1200 #endif /* ipconfigUSE_TCP == 1 */
\r
1202 /* Socket must be unbound first, to ensure no more packets are queued on
\r
1204 if( socketSOCKET_IS_BOUND( pxSocket ) != pdFALSE )
\r
1206 /* If the network driver can iterate through 'xBoundUDPSocketsList',
\r
1207 by calling xPortHasUDPSocket(), then the IP-task must temporarily
\r
1208 suspend the scheduler to keep the list in a consistent state. */
\r
1209 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1211 vTaskSuspendAll();
\r
1213 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1215 uxListRemove( &( pxSocket->xBoundSocketListItem ) );
\r
1217 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1221 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1224 /* Now the socket is not bound the list of waiting packets can be
\r
1226 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_UDP )
\r
1228 while( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) > 0U )
\r
1230 pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
\r
1231 uxListRemove( &( pxNetworkBuffer->xBufferListItem ) );
\r
1232 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
\r
1236 if( pxSocket->xEventGroup )
\r
1238 vEventGroupDelete( pxSocket->xEventGroup );
\r
1241 #if( ipconfigUSE_TCP == 1 ) && ( ipconfigHAS_DEBUG_PRINTF != 0 )
\r
1243 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1245 FreeRTOS_debug_printf( ( "FreeRTOS_closesocket[%u to %lxip:%u]: buffers %lu socks %lu\n",
\r
1246 pxSocket->usLocalPort,
\r
1247 pxSocket->u.xTCP.ulRemoteIP,
\r
1248 pxSocket->u.xTCP.usRemotePort,
\r
1249 uxGetNumberOfFreeNetworkBuffers(),
\r
1250 listCURRENT_LIST_LENGTH( &xBoundTCPSocketsList ) ) );
\r
1253 #endif /* ( ipconfigUSE_TCP == 1 ) && ( ipconfigHAS_DEBUG_PRINTF != 0 ) */
\r
1255 /* Anf finally, after all resources have been freed, free the socket space */
\r
1256 vPortFreeSocket( pxSocket );
\r
1261 /*-----------------------------------------------------------*/
\r
1263 #if ipconfigUSE_TCP == 1
\r
1266 * When a child socket gets closed, make sure to update the child-count of the
\r
1267 * parent. When a listening parent socket is closed, make sure no child-sockets
\r
1268 * keep a pointer to it.
\r
1270 static void prvTCPSetSocketCount( FreeRTOS_Socket_t *pxSocketToDelete )
\r
1272 const ListItem_t *pxIterator;
\r
1273 const MiniListItem_t *pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );
\r
1274 FreeRTOS_Socket_t *pxOtherSocket;
\r
1275 uint16_t usLocalPort = pxSocketToDelete->usLocalPort;
\r
1277 for( pxIterator = ( const ListItem_t * ) listGET_NEXT( pxEnd );
\r
1278 pxIterator != ( const ListItem_t * ) pxEnd;
\r
1279 pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
1281 pxOtherSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
\r
1282 if( ( pxOtherSocket->u.xTCP.ucTCPState == eTCP_LISTEN ) &&
\r
1283 ( pxOtherSocket->usLocalPort == usLocalPort ) &&
\r
1284 ( pxOtherSocket->u.xTCP.usChildCount ) )
\r
1286 pxOtherSocket->u.xTCP.usChildCount--;
\r
1287 FreeRTOS_debug_printf( ( "Lost: Socket %u now has %u / %u child%s\n",
\r
1288 pxOtherSocket->usLocalPort,
\r
1289 pxOtherSocket->u.xTCP.usChildCount,
\r
1290 pxOtherSocket->u.xTCP.usBacklog,
\r
1291 pxOtherSocket->u.xTCP.usChildCount == 1u ? "" : "ren" ) );
\r
1297 #endif /* ipconfigUSE_TCP == 1 */
\r
1299 /*-----------------------------------------------------------*/
\r
1301 BaseType_t FreeRTOS_setsockopt( Socket_t xSocket, int32_t lLevel, int32_t lOptionName, const void *pvOptionValue, size_t xOptionLength )
\r
1303 /* The standard Berkeley function returns 0 for success. */
\r
1304 BaseType_t xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
1305 BaseType_t lOptionValue;
\r
1306 FreeRTOS_Socket_t *pxSocket;
\r
1308 pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
1310 /* The function prototype is designed to maintain the expected Berkeley
\r
1311 sockets standard, but this implementation does not use all the parameters. */
\r
1313 ( void ) xOptionLength;
\r
1315 configASSERT( xSocket );
\r
1317 switch( lOptionName )
\r
1319 case FREERTOS_SO_RCVTIMEO :
\r
1320 /* Receive time out. */
\r
1321 pxSocket->xReceiveBlockTime = *( ( TickType_t * ) pvOptionValue );
\r
1325 case FREERTOS_SO_SNDTIMEO :
\r
1326 pxSocket->xSendBlockTime = *( ( TickType_t * ) pvOptionValue );
\r
1327 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_UDP )
\r
1329 /* The send time out is capped for the reason stated in the
\r
1330 comments where ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS is defined
\r
1331 in FreeRTOSIPConfig.h (assuming an official configuration file
\r
1333 if( pxSocket->xSendBlockTime > ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS )
\r
1335 pxSocket->xSendBlockTime = ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS;
\r
1340 /* For TCP socket, it isn't necessary to limit the blocking time
\r
1341 because the FreeRTOS_send() function does not wait for a network
\r
1342 buffer to become available. */
\r
1346 #if( ipconfigUDP_MAX_RX_PACKETS > 0 )
\r
1347 case FREERTOS_SO_UDP_MAX_RX_PACKETS:
\r
1348 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_UDP )
\r
1350 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1352 pxSocket->u.xUDP.uxMaxPackets = *( ( UBaseType_t * ) pvOptionValue );
\r
1355 #endif /* ipconfigUDP_MAX_RX_PACKETS */
\r
1357 case FREERTOS_SO_UDPCKSUM_OUT :
\r
1358 /* Turn calculating of the UDP checksum on/off for this socket. */
\r
1359 lOptionValue = ( BaseType_t ) pvOptionValue;
\r
1361 if( lOptionValue == 0 )
\r
1363 pxSocket->ucSocketOptions &= ( uint8_t ) ~FREERTOS_SO_UDPCKSUM_OUT;
\r
1367 pxSocket->ucSocketOptions |= ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT;
\r
1372 #if( ipconfigUSE_CALLBACKS == 1 )
\r
1373 #if( ipconfigUSE_TCP == 1 )
\r
1374 case FREERTOS_SO_TCP_CONN_HANDLER: /* Set a callback for (dis)connection events */
\r
1375 case FREERTOS_SO_TCP_RECV_HANDLER: /* Install a callback for receiving TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
\r
1376 case FREERTOS_SO_TCP_SENT_HANDLER: /* Install a callback for sending TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
\r
1377 #endif /* ipconfigUSE_TCP */
\r
1378 case FREERTOS_SO_UDP_RECV_HANDLER: /* Install a callback for receiving UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
\r
1379 case FREERTOS_SO_UDP_SENT_HANDLER: /* Install a callback for sending UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
\r
1381 #if( ipconfigUSE_TCP == 1 )
\r
1383 UBaseType_t uxProtocol;
\r
1384 if( ( lOptionName == FREERTOS_SO_UDP_RECV_HANDLER ) ||
\r
1385 ( lOptionName == FREERTOS_SO_UDP_SENT_HANDLER ) )
\r
1387 uxProtocol = ( UBaseType_t ) FREERTOS_IPPROTO_UDP;
\r
1391 uxProtocol = ( UBaseType_t ) FREERTOS_IPPROTO_TCP;
\r
1394 if( pxSocket->ucProtocol != ( uint8_t ) uxProtocol )
\r
1396 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1401 /* No need to check if the socket has the right
\r
1402 protocol, because only UDP socket can be created. */
\r
1404 #endif /* ipconfigUSE_TCP */
\r
1406 switch( lOptionName )
\r
1408 #if ipconfigUSE_TCP == 1
\r
1409 case FREERTOS_SO_TCP_CONN_HANDLER:
\r
1410 pxSocket->u.xTCP.pxHandleConnected = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPConnected;
\r
1412 case FREERTOS_SO_TCP_RECV_HANDLER:
\r
1413 pxSocket->u.xTCP.pxHandleReceive = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPReceive;
\r
1415 case FREERTOS_SO_TCP_SENT_HANDLER:
\r
1416 pxSocket->u.xTCP.pxHandleSent = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPSent;
\r
1418 #endif /* ipconfigUSE_TCP */
\r
1419 case FREERTOS_SO_UDP_RECV_HANDLER:
\r
1420 pxSocket->u.xUDP.pxHandleReceive = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnUDPReceive;
\r
1422 case FREERTOS_SO_UDP_SENT_HANDLER:
\r
1423 pxSocket->u.xUDP.pxHandleSent = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnUDPSent;
\r
1432 #endif /* ipconfigUSE_CALLBACKS */
\r
1434 #if( ipconfigUSE_TCP != 0 )
\r
1435 #if( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 )
\r
1436 /* Each socket has a semaphore on which the using task normally
\r
1438 case FREERTOS_SO_SET_SEMAPHORE:
\r
1440 pxSocket->pxUserSemaphore = *( ( SemaphoreHandle_t * ) pvOptionValue );
\r
1444 #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
\r
1445 case FREERTOS_SO_SNDBUF: /* Set the size of the send buffer, in units of MSS (TCP only) */
\r
1446 case FREERTOS_SO_RCVBUF: /* Set the size of the receive buffer, in units of MSS (TCP only) */
\r
1448 uint32_t ulNewValue;
\r
1450 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1452 FreeRTOS_debug_printf( ( "Set SO_%sBUF: wrong socket type\n",
\r
1453 ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );
\r
1454 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1457 if( ( ( lOptionName == FREERTOS_SO_SNDBUF ) && ( pxSocket->u.xTCP.txStream != NULL ) ) ||
\r
1458 ( ( lOptionName == FREERTOS_SO_RCVBUF ) && ( pxSocket->u.xTCP.rxStream != NULL ) ) )
\r
1460 FreeRTOS_debug_printf( ( "Set SO_%sBUF: buffer already created\n",
\r
1461 ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );
\r
1462 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1465 ulNewValue = *( ( uint32_t * ) pvOptionValue );
\r
1467 if( lOptionName == FREERTOS_SO_SNDBUF )
\r
1469 /* Round up to nearest MSS size */
\r
1470 ulNewValue = FreeRTOS_round_up( ulNewValue, ( uint32_t ) pxSocket->u.xTCP.usInitMSS );
\r
1471 pxSocket->u.xTCP.uxTxStreamSize = ulNewValue;
\r
1475 pxSocket->u.xTCP.uxRxStreamSize = ulNewValue;
\r
1481 case FREERTOS_SO_WIN_PROPERTIES: /* Set all buffer and window properties in one call, parameter is pointer to WinProperties_t */
\r
1483 WinProperties_t* pxProps;
\r
1485 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1487 FreeRTOS_debug_printf( ( "Set SO_WIN_PROP: wrong socket type\n" ) );
\r
1488 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1491 if( ( pxSocket->u.xTCP.txStream != NULL ) || ( pxSocket->u.xTCP.rxStream != NULL ) )
\r
1493 FreeRTOS_debug_printf( ( "Set SO_WIN_PROP: buffer already created\n" ) );
\r
1494 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1497 pxProps = ( ( WinProperties_t * ) pvOptionValue );
\r
1498 FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDBUF, &( pxProps->lTxBufSize ), sizeof( pxProps->lTxBufSize ) );
\r
1499 FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVBUF, &( pxProps->lRxBufSize ), sizeof( pxProps->lRxBufSize ) );
\r
1500 #if( ipconfigUSE_TCP_WIN == 1 )
\r
1502 pxSocket->u.xTCP.uxRxWinSize = ( uint32_t )pxProps->lRxWinSize; /* Fixed value: size of the TCP reception window */
\r
1503 pxSocket->u.xTCP.uxTxWinSize = ( uint32_t )pxProps->lTxWinSize; /* Fixed value: size of the TCP transmit window */
\r
1507 pxSocket->u.xTCP.uxRxWinSize = 1u;
\r
1508 pxSocket->u.xTCP.uxTxWinSize = 1u;
\r
1512 /* In case the socket has already initialised its tcpWin,
\r
1513 adapt the window size parameters */
\r
1514 if( pxSocket->u.xTCP.xTCPWindow.u.bits.bHasInit != pdFALSE_UNSIGNED )
\r
1516 pxSocket->u.xTCP.xTCPWindow.xSize.ulRxWindowLength = pxSocket->u.xTCP.uxRxWinSize * pxSocket->u.xTCP.usInitMSS;
\r
1517 pxSocket->u.xTCP.xTCPWindow.xSize.ulRxWindowLength = pxSocket->u.xTCP.uxTxWinSize * pxSocket->u.xTCP.usInitMSS;
\r
1524 case FREERTOS_SO_REUSE_LISTEN_SOCKET: /* If true, the server-socket will turn into a connected socket */
\r
1526 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1528 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1530 if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
\r
1532 pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE_UNSIGNED;
\r
1536 pxSocket->u.xTCP.bits.bReuseSocket = pdFALSE_UNSIGNED;
\r
1542 case FREERTOS_SO_CLOSE_AFTER_SEND: /* As soon as the last byte has been transmitted, finalise the connection */
\r
1544 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1546 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1549 if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
\r
1551 pxSocket->u.xTCP.bits.bCloseAfterSend = pdTRUE_UNSIGNED;
\r
1555 pxSocket->u.xTCP.bits.bCloseAfterSend = pdFALSE_UNSIGNED;
\r
1561 case FREERTOS_SO_SET_FULL_SIZE: /* Refuse to send packets smaller than MSS */
\r
1563 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1565 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1568 if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
\r
1570 pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdTRUE_UNSIGNED;
\r
1574 pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdFALSE_UNSIGNED;
\r
1577 if( ( pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize == pdFALSE_UNSIGNED ) &&
\r
1578 ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) &&
\r
1579 ( FreeRTOS_outstanding( pxSocket ) != 0 ) )
\r
1581 pxSocket->u.xTCP.usTimeout = 1u; /* to set/clear bSendFullSize */
\r
1582 xSendEventToIPTask( eTCPTimerEvent );
\r
1588 case FREERTOS_SO_STOP_RX: /* Refuse to receive more packts */
\r
1590 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1592 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1595 if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
\r
1597 pxSocket->u.xTCP.bits.bRxStopped = pdTRUE_UNSIGNED;
\r
1601 pxSocket->u.xTCP.bits.bRxStopped = pdFALSE_UNSIGNED;
\r
1604 pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
\r
1605 pxSocket->u.xTCP.usTimeout = 1u; /* to set/clear bRxStopped */
\r
1606 xSendEventToIPTask( eTCPTimerEvent );
\r
1611 #endif /* ipconfigUSE_TCP == 1 */
\r
1614 /* No other options are handled. */
\r
1615 xReturn = -pdFREERTOS_ERRNO_ENOPROTOOPT;
\r
1622 /*-----------------------------------------------------------*/
\r
1624 /* Get a free private ('anonymous') port number */
\r
1625 static uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol )
\r
1627 uint16_t usResult;
\r
1628 BaseType_t xIndex;
\r
1629 const List_t *pxList;
\r
1631 #if ipconfigUSE_TCP == 1
\r
1632 if( xProtocol == ( BaseType_t ) FREERTOS_IPPROTO_TCP )
\r
1634 xIndex = socketNEXT_TCP_PORT_NUMBER_INDEX;
\r
1635 pxList = &xBoundTCPSocketsList;
\r
1640 xIndex = socketNEXT_UDP_PORT_NUMBER_INDEX;
\r
1641 pxList = &xBoundUDPSocketsList;
\r
1644 /* Avoid compiler warnings if ipconfigUSE_TCP is not defined. */
\r
1645 ( void ) xProtocol;
\r
1647 /* Assign the next port in the range. Has it overflowed? */
\r
1648 /*_RB_ This needs to be randomised rather than sequential. */
\r
1649 /* _HT_ Agreed, although many OS's use sequential port numbers, see
\r
1650 https://www.cymru.com/jtk/misc/ephemeralports.html */
\r
1653 ++( usNextPortToUse[ xIndex ] );
\r
1655 if( usNextPortToUse[ xIndex ] >= socketAUTO_PORT_ALLOCATION_MAX_NUMBER )
\r
1657 /* Don't go right back to the start of the dynamic/private port
\r
1658 range numbers as any persistent sockets are likely to have been
\r
1659 create first so the early port numbers may still be in use. */
\r
1660 usNextPortToUse[ xIndex ] = socketAUTO_PORT_ALLOCATION_RESET_NUMBER;
\r
1663 usResult = FreeRTOS_htons( usNextPortToUse[ xIndex ] );
\r
1665 if( pxListFindListItemWithValue( pxList, ( TickType_t ) usResult ) == NULL )
\r
1672 /*-----------------------------------------------------------*/
\r
1674 /* pxListFindListItemWithValue: find a list item in a bound socket list
\r
1675 'xWantedItemValue' refers to a port number */
\r
1676 static const ListItem_t * pxListFindListItemWithValue( const List_t *pxList, TickType_t xWantedItemValue )
\r
1678 const ListItem_t * pxResult = NULL;
\r
1680 if( ( xIPIsNetworkTaskReady() != pdFALSE ) && ( pxList != NULL ) )
\r
1682 const ListItem_t *pxIterator;
\r
1683 const MiniListItem_t *pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( pxList );
\r
1684 for( pxIterator = ( const ListItem_t * ) listGET_NEXT( pxEnd );
\r
1685 pxIterator != ( const ListItem_t * ) pxEnd;
\r
1686 pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
1688 if( listGET_LIST_ITEM_VALUE( pxIterator ) == xWantedItemValue )
\r
1690 pxResult = pxIterator;
\r
1699 /*-----------------------------------------------------------*/
\r
1701 FreeRTOS_Socket_t *pxUDPSocketLookup( UBaseType_t uxLocalPort )
\r
1703 const ListItem_t *pxListItem;
\r
1704 FreeRTOS_Socket_t *pxSocket = NULL;
\r
1706 /* Looking up a socket is quite simple, find a match with the local port.
\r
1708 See if there is a list item associated with the port number on the
\r
1709 list of bound sockets. */
\r
1710 pxListItem = pxListFindListItemWithValue( &xBoundUDPSocketsList, ( TickType_t ) uxLocalPort );
\r
1712 if( pxListItem != NULL )
\r
1714 /* The owner of the list item is the socket itself. */
\r
1715 pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxListItem );
\r
1716 configASSERT( pxSocket != NULL );
\r
1721 /*-----------------------------------------------------------*/
\r
1723 #if ipconfigINCLUDE_FULL_INET_ADDR == 1
\r
1725 uint32_t FreeRTOS_inet_addr( const char * pcIPAddress )
\r
1727 const uint32_t ulDecimalBase = 10u;
\r
1728 uint8_t ucOctet[ socketMAX_IP_ADDRESS_OCTETS ];
\r
1729 const char *pcPointerOnEntering;
\r
1730 uint32_t ulReturn = 0UL, ulValue;
\r
1731 UBaseType_t uxOctetNumber;
\r
1732 BaseType_t xResult = pdPASS;
\r
1734 for( uxOctetNumber = 0u; uxOctetNumber < socketMAX_IP_ADDRESS_OCTETS; uxOctetNumber++ )
\r
1737 pcPointerOnEntering = pcIPAddress;
\r
1739 while( ( *pcIPAddress >= '0' ) && ( *pcIPAddress <= '9' ) )
\r
1741 /* Move previous read characters into the next decimal
\r
1743 ulValue *= ulDecimalBase;
\r
1745 /* Add the binary value of the ascii character. */
\r
1746 ulValue += ( ( uint32_t ) ( *pcIPAddress ) - ( uint32_t ) '0' );
\r
1748 /* Move to next character in the string. */
\r
1752 /* Check characters were read. */
\r
1753 if( pcIPAddress == pcPointerOnEntering )
\r
1758 /* Check the value fits in an 8-bit number. */
\r
1759 if( ulValue > 0xffUL )
\r
1765 ucOctet[ uxOctetNumber ] = ( uint8_t ) ulValue;
\r
1767 /* Check the next character is as expected. */
\r
1768 if( uxOctetNumber < ( socketMAX_IP_ADDRESS_OCTETS - 1u ) )
\r
1770 if( *pcIPAddress != '.' )
\r
1776 /* Move past the dot. */
\r
1782 if( xResult == pdFAIL )
\r
1784 /* No point going on. */
\r
1789 if( *pcIPAddress != ( char ) 0 )
\r
1791 /* Expected the end of the string. */
\r
1795 if( uxOctetNumber != socketMAX_IP_ADDRESS_OCTETS )
\r
1797 /* Didn't read enough octets. */
\r
1801 if( xResult == pdPASS )
\r
1803 ulReturn = FreeRTOS_inet_addr_quick( ucOctet[ 0 ], ucOctet[ 1 ], ucOctet[ 2 ], ucOctet[ 3 ] );
\r
1809 #endif /* ipconfigINCLUDE_FULL_INET_ADDR */
\r
1811 /*-----------------------------------------------------------*/
\r
1813 /* Function to get the local address and IP port */
\r
1814 size_t FreeRTOS_GetLocalAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress )
\r
1816 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
1818 /* IP address of local machine. */
\r
1819 pxAddress->sin_addr = *ipLOCAL_IP_ADDRESS_POINTER;
\r
1821 /* Local port on this machine. */
\r
1822 pxAddress->sin_port = FreeRTOS_htons( pxSocket->usLocalPort );
\r
1824 return sizeof( *pxAddress );
\r
1827 /*-----------------------------------------------------------*/
\r
1829 void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
\r
1831 /* _HT_ must work this out, now vSocketWakeUpUser will be called for any important
\r
1832 * event or transition */
\r
1833 #if( ipconfigSOCKET_HAS_USER_SEMAPHORE == 1 )
\r
1835 if( pxSocket->pxUserSemaphore != NULL )
\r
1837 xSemaphoreGive( pxSocket->pxUserSemaphore );
\r
1840 #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
\r
1842 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
1844 if( pxSocket->pxSocketSet != NULL )
\r
1846 EventBits_t xSelectBits = ( pxSocket->xEventBits >> SOCKET_EVENT_BIT_COUNT ) & eSELECT_ALL;
\r
1847 if( xSelectBits != 0ul )
\r
1849 pxSocket->xSocketBits |= xSelectBits;
\r
1850 xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, xSelectBits );
\r
1854 pxSocket->xEventBits &= eSOCKET_ALL;
\r
1856 #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
\r
1858 if( ( pxSocket->xEventGroup != NULL ) && ( pxSocket->xEventBits != 0u ) )
\r
1860 xEventGroupSetBits( pxSocket->xEventGroup, pxSocket->xEventBits );
\r
1863 pxSocket->xEventBits = 0ul;
\r
1866 /*-----------------------------------------------------------*/
\r
1868 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1870 /* This define makes it possible for network-card drivers to inspect
\r
1871 * UDP message and see if there is any UDP socket bound to a given port
\r
1873 * This is probably only useful in systems with a minimum of RAM and
\r
1874 * when lots of anonymous broadcast messages come in
\r
1876 BaseType_t xPortHasUDPSocket( uint16_t usPortNr )
\r
1878 BaseType_t xFound = pdFALSE;
\r
1880 vTaskSuspendAll();
\r
1882 if( ( pxListFindListItemWithValue( &xBoundUDPSocketsList, ( TickType_t ) usPortNr ) != NULL ) )
\r
1892 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1894 /*-----------------------------------------------------------*/
\r
1896 #if( ipconfigUSE_TCP == 1 )
\r
1898 static BaseType_t bMayConnect( FreeRTOS_Socket_t *pxSocket );
\r
1899 static BaseType_t bMayConnect( FreeRTOS_Socket_t *pxSocket )
\r
1901 switch( pxSocket->u.xTCP.ucTCPState )
\r
1904 case eCLOSE_WAIT: return 0;
\r
1905 case eCONNECT_SYN: return -pdFREERTOS_ERRNO_EINPROGRESS;
\r
1906 default: return -pdFREERTOS_ERRNO_EAGAIN;
\r
1910 #endif /* ipconfigUSE_TCP */
\r
1911 /*-----------------------------------------------------------*/
\r
1913 #if( ipconfigUSE_TCP == 1 )
\r
1915 static BaseType_t prvTCPConnectStart( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr *pxAddress )
\r
1917 BaseType_t xResult = 0;
\r
1919 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdFALSE )
\r
1921 /* Not a valid socket or wrong type */
\r
1922 xResult = -pdFREERTOS_ERRNO_EBADF;
\r
1924 else if( FreeRTOS_issocketconnected( pxSocket ) > 0 )
\r
1926 /* The socket is already connected. */
\r
1927 xResult = -pdFREERTOS_ERRNO_EISCONN;
\r
1929 else if( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE )
\r
1931 /* Bind the socket to the port that the client task will send from.
\r
1932 Non-standard, so the error returned is that returned by bind(). */
\r
1933 xResult = FreeRTOS_bind( ( Socket_t ) pxSocket, NULL, 0u );
\r
1936 if( xResult == 0 )
\r
1938 /* Check if it makes any sense to wait for a connect event, this condition
\r
1939 might change while sleeping, so it must be checked within each loop */
\r
1940 xResult = bMayConnect( pxSocket ); /* -EINPROGRESS, -EAGAIN, or 0 for OK */
\r
1942 /* Start the connect procedure, kernel will start working on it */
\r
1943 if( xResult == 0 )
\r
1945 pxSocket->u.xTCP.bits.bConnPrepared = pdFALSE_UNSIGNED;
\r
1946 pxSocket->u.xTCP.ucRepCount = 0u;
\r
1948 FreeRTOS_debug_printf( ( "FreeRTOS_connect: %u to %lxip:%u\n",
\r
1949 pxSocket->usLocalPort, FreeRTOS_ntohl( pxAddress->sin_addr ), FreeRTOS_ntohs( pxAddress->sin_port ) ) );
\r
1951 /* Port on remote machine. */
\r
1952 pxSocket->u.xTCP.usRemotePort = FreeRTOS_ntohs( pxAddress->sin_port );
\r
1954 /* IP address of remote machine. */
\r
1955 pxSocket->u.xTCP.ulRemoteIP = FreeRTOS_ntohl( pxAddress->sin_addr );
\r
1957 /* (client) internal state: socket wants to send a connect. */
\r
1958 vTCPStateChange( pxSocket, eCONNECT_SYN );
\r
1960 /* To start an active connect. */
\r
1961 pxSocket->u.xTCP.usTimeout = 1u;
\r
1963 if( xSendEventToIPTask( eTCPTimerEvent ) != pdPASS )
\r
1965 xResult = -pdFREERTOS_ERRNO_ECANCELED;
\r
1973 #endif /* ipconfigUSE_TCP */
\r
1974 /*-----------------------------------------------------------*/
\r
1976 #if( ipconfigUSE_TCP == 1 )
\r
1979 * FreeRTOS_connect: socket wants to connect to a remote port
\r
1981 BaseType_t FreeRTOS_connect( Socket_t xClientSocket, struct freertos_sockaddr *pxAddress, socklen_t xAddressLength )
\r
1983 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t* ) xClientSocket;
\r
1984 TickType_t xRemainingTime;
\r
1985 BaseType_t xTimed = pdFALSE;
\r
1986 BaseType_t xResult;
\r
1987 TimeOut_t xTimeOut;
\r
1989 ( void ) xAddressLength;
\r
1991 xResult = prvTCPConnectStart( pxSocket, pxAddress );
\r
1993 if( xResult == 0 )
\r
1995 /* And wait for the result */
\r
1998 if( xTimed == pdFALSE )
\r
2000 /* Only in the first round, check for non-blocking */
\r
2001 xRemainingTime = pxSocket->xReceiveBlockTime;
\r
2002 if( xRemainingTime == ( TickType_t )0 )
\r
2004 /* Not yet connected, correct state, non-blocking. */
\r
2005 xResult = -pdFREERTOS_ERRNO_EWOULDBLOCK;
\r
2009 /* Don't get here a second time. */
\r
2012 /* Fetch the current time */
\r
2013 vTaskSetTimeOutState( &xTimeOut );
\r
2016 /* Did it get connected while sleeping ? */
\r
2017 xResult = FreeRTOS_issocketconnected( pxSocket );
\r
2019 /* Returns positive when connected, negative means an error */
\r
2022 /* Return the error */
\r
2028 /* Socket now connected, return a zero */
\r
2033 /* Is it allowed to sleep more? */
\r
2034 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) )
\r
2036 xResult = -pdFREERTOS_ERRNO_ETIMEDOUT;
\r
2040 /* Go sleeping until we get any down-stream event */
\r
2041 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_CONNECT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2047 #endif /* ipconfigUSE_TCP */
\r
2048 /*-----------------------------------------------------------*/
\r
2050 #if( ipconfigUSE_TCP == 1 )
\r
2053 * FreeRTOS_accept: can return a new connected socket
\r
2054 * if the server socket is in listen mode and receives a connection request
\r
2055 * The new socket will be bound already to the same port number as the listing
\r
2058 Socket_t FreeRTOS_accept( Socket_t xServerSocket, struct freertos_sockaddr *pxAddress, socklen_t *pxAddressLength )
\r
2060 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xServerSocket;
\r
2061 FreeRTOS_Socket_t *pxClientSocket = NULL;
\r
2062 TickType_t xRemainingTime;
\r
2063 BaseType_t xTimed = pdFALSE, xAsk = pdFALSE;
\r
2064 TimeOut_t xTimeOut;
\r
2065 IPStackEvent_t xAskEvent;
\r
2067 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2069 /* Not a valid socket or wrong type */
\r
2070 pxClientSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
\r
2072 else if( ( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED ) &&
\r
2073 ( pxSocket->u.xTCP.ucTCPState != eTCP_LISTEN ) )
\r
2075 /* Parent socket is not in listening mode */
\r
2076 pxClientSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
\r
2080 /* Loop will stop with breaks. */
\r
2083 /* Is there a new client? */
\r
2084 vTaskSuspendAll();
\r
2086 if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED )
\r
2088 pxClientSocket = pxSocket->u.xTCP.pxPeerSocket;
\r
2092 pxClientSocket = pxSocket;
\r
2094 if( pxClientSocket != NULL )
\r
2096 pxSocket->u.xTCP.pxPeerSocket = NULL;
\r
2098 /* Is it still not taken ? */
\r
2099 if( pxClientSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED )
\r
2101 pxClientSocket->u.xTCP.bits.bPassAccept = pdFALSE_UNSIGNED;
\r
2105 pxClientSocket = NULL;
\r
2111 if( pxClientSocket != NULL )
\r
2113 if( pxAddress != NULL )
\r
2115 /* IP address of remote machine. */
\r
2116 pxAddress->sin_addr = FreeRTOS_ntohl( pxClientSocket->u.xTCP.ulRemoteIP );
\r
2118 /* Port on remote machine. */
\r
2119 pxAddress->sin_port = FreeRTOS_ntohs( pxClientSocket->u.xTCP.usRemotePort );
\r
2121 if( pxAddressLength != NULL )
\r
2123 *pxAddressLength = sizeof( *pxAddress );
\r
2126 if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED )
\r
2132 if( xAsk != pdFALSE )
\r
2134 /* Ask to set an event in 'xEventGroup' as soon as a new
\r
2135 client gets connected for this listening socket. */
\r
2136 xAskEvent.eEventType = eTCPAcceptEvent;
\r
2137 xAskEvent.pvData = ( void * ) pxSocket;
\r
2138 xSendEventStructToIPTask( &xAskEvent, portMAX_DELAY );
\r
2141 if( pxClientSocket != NULL )
\r
2146 if( xTimed == pdFALSE )
\r
2148 /* Only in the first round, check for non-blocking */
\r
2149 xRemainingTime = pxSocket->xReceiveBlockTime;
\r
2150 if( xRemainingTime == ( TickType_t ) 0 )
\r
2155 /* Don't get here a second time */
\r
2158 /* Fetch the current time */
\r
2159 vTaskSetTimeOutState( &xTimeOut );
\r
2162 /* Has the timeout been reached? */
\r
2163 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
\r
2168 /* Go sleeping until we get any down-stream event */
\r
2169 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_ACCEPT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2173 return ( Socket_t ) pxClientSocket;
\r
2175 #endif /* ipconfigUSE_TCP */
\r
2176 /*-----------------------------------------------------------*/
\r
2178 #if( ipconfigUSE_TCP == 1 )
\r
2181 * Read incoming data from a TCP socket
\r
2182 * Only after the last byte has been read, a close error might be returned
\r
2184 BaseType_t FreeRTOS_recv( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags )
\r
2186 BaseType_t xByteCount;
\r
2187 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2188 TickType_t xRemainingTime;
\r
2189 BaseType_t xTimed = pdFALSE;
\r
2190 TimeOut_t xTimeOut;
\r
2191 EventBits_t xEventBits = ( EventBits_t ) 0;
\r
2193 /* Check if the socket is valid, has type TCP and if it is bound to a
\r
2195 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2197 xByteCount = -pdFREERTOS_ERRNO_EINVAL;
\r
2201 if( pxSocket->u.xTCP.rxStream != NULL )
\r
2203 xByteCount = ( BaseType_t )uxStreamBufferGetSize ( pxSocket->u.xTCP.rxStream );
\r
2210 while( xByteCount == 0 )
\r
2212 switch( pxSocket->u.xTCP.ucTCPState )
\r
2215 case eCLOSE_WAIT: /* (server + client) waiting for a connection termination request from the local user. */
\r
2216 case eCLOSING: /* (server + client) waiting for a connection termination request acknowledgement from the remote TCP. */
\r
2217 if( pxSocket->u.xTCP.bits.bMallocError != pdFALSE_UNSIGNED )
\r
2219 /* The no-memory error has priority above the non-connected error.
\r
2220 Both are fatal and will elad to closing the socket. */
\r
2221 xByteCount = -pdFREERTOS_ERRNO_ENOMEM;
\r
2225 xByteCount = -pdFREERTOS_ERRNO_ENOTCONN;
\r
2227 /* Call continue to break out of the switch and also the while
\r
2234 if( xTimed == pdFALSE )
\r
2236 /* Only in the first round, check for non-blocking. */
\r
2237 xRemainingTime = pxSocket->xReceiveBlockTime;
\r
2239 if( xRemainingTime == ( TickType_t ) 0 )
\r
2241 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
2243 /* Just check for the interrupt flag. */
\r
2244 xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_INTR,
\r
2245 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, socketDONT_BLOCK );
\r
2247 #endif /* ipconfigSUPPORT_SIGNALS */
\r
2251 if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
\r
2256 /* Don't get here a second time. */
\r
2259 /* Fetch the current time. */
\r
2260 vTaskSetTimeOutState( &xTimeOut );
\r
2263 /* Has the timeout been reached? */
\r
2264 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
\r
2269 /* Block until there is a down-stream event. */
\r
2270 xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup,
\r
2271 eSOCKET_RECEIVE | eSOCKET_CLOSED | eSOCKET_INTR,
\r
2272 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2273 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
2275 if( ( xEventBits & eSOCKET_INTR ) != 0u )
\r
2282 ( void ) xEventBits;
\r
2284 #endif /* ipconfigSUPPORT_SIGNALS */
\r
2286 if( pxSocket->u.xTCP.rxStream != NULL )
\r
2288 xByteCount = ( BaseType_t ) uxStreamBufferGetSize ( pxSocket->u.xTCP.rxStream );
\r
2296 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
2297 if( ( xEventBits & eSOCKET_INTR ) != 0 )
\r
2299 if( ( xEventBits & ( eSOCKET_RECEIVE | eSOCKET_CLOSED ) ) != 0 )
\r
2301 /* Shouldn't have cleared other flags. */
\r
2302 xEventBits &= ~eSOCKET_INTR;
\r
2303 xEventGroupSetBits( pxSocket->xEventGroup, xEventBits );
\r
2305 xByteCount = -pdFREERTOS_ERRNO_EINTR;
\r
2308 #endif /* ipconfigSUPPORT_SIGNALS */
\r
2309 if( xByteCount > 0 )
\r
2311 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
\r
2313 xByteCount = ( BaseType_t ) uxStreamBufferGet( pxSocket->u.xTCP.rxStream, 0ul, ( uint8_t * ) pvBuffer, ( size_t ) xBufferLength, ( xFlags & FREERTOS_MSG_PEEK ) != 0 );
\r
2314 if( pxSocket->u.xTCP.bits.bLowWater != pdFALSE_UNSIGNED )
\r
2316 /* We had reached the low-water mark, now see if the flag
\r
2318 size_t uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );
\r
2320 if( uxFrontSpace >= pxSocket->u.xTCP.uxEnoughSpace )
\r
2322 pxSocket->u.xTCP.bits.bLowWater = pdFALSE_UNSIGNED;
\r
2323 pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
\r
2324 pxSocket->u.xTCP.usTimeout = 1u; /* because bLowWater is cleared. */
\r
2325 xSendEventToIPTask( eTCPTimerEvent );
\r
2331 /* Zero-copy reception of data: pvBuffer is a pointer to a pointer. */
\r
2332 xByteCount = ( BaseType_t ) uxStreamBufferGetPtr( pxSocket->u.xTCP.rxStream, (uint8_t **)pvBuffer );
\r
2335 } /* prvValidSocket() */
\r
2337 return xByteCount;
\r
2340 #endif /* ipconfigUSE_TCP */
\r
2341 /*-----------------------------------------------------------*/
\r
2343 #if( ipconfigUSE_TCP == 1 )
\r
2345 static int32_t prvTCPSendCheck( FreeRTOS_Socket_t *pxSocket, size_t xDataLength )
\r
2347 int32_t xResult = 1;
\r
2349 /* Is this a socket of type TCP and is it already bound to a port number ? */
\r
2350 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2352 xResult = -pdFREERTOS_ERRNO_EINVAL;
\r
2354 else if( pxSocket->u.xTCP.bits.bMallocError != pdFALSE_UNSIGNED )
\r
2356 xResult = -pdFREERTOS_ERRNO_ENOMEM;
\r
2358 else if( pxSocket->u.xTCP.ucTCPState == eCLOSED )
\r
2360 xResult = -pdFREERTOS_ERRNO_ENOTCONN;
\r
2362 else if( pxSocket->u.xTCP.bits.bFinSent != pdFALSE_UNSIGNED )
\r
2364 /* This TCP connection is closing already, the FIN flag has been sent.
\r
2365 Maybe it is still delivering or receiving data.
\r
2366 Return OK in order not to get closed/deleted too quickly */
\r
2369 else if( xDataLength == 0ul )
\r
2371 /* send() is being called to send zero bytes */
\r
2374 else if( pxSocket->u.xTCP.txStream == NULL )
\r
2376 /* Create the outgoing stream only when it is needed */
\r
2377 prvTCPCreateStream( pxSocket, pdFALSE );
\r
2379 if( pxSocket->u.xTCP.txStream == NULL )
\r
2381 xResult = -pdFREERTOS_ERRNO_ENOMEM;
\r
2388 #endif /* ipconfigUSE_TCP */
\r
2389 /*-----------------------------------------------------------*/
\r
2391 #if( ipconfigUSE_TCP == 1 )
\r
2393 /* Get a direct pointer to the circular transmit buffer.
\r
2394 '*pxLength' will contain the number of bytes that may be written. */
\r
2395 uint8_t *FreeRTOS_get_tx_head( Socket_t xSocket, BaseType_t *pxLength )
\r
2397 uint8_t *pucReturn;
\r
2398 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2399 StreamBuffer_t *pxBuffer = pxSocket->u.xTCP.txStream;
\r
2401 if( pxBuffer != NULL )
\r
2403 BaseType_t xSpace = ( BaseType_t ) uxStreamBufferGetSpace( pxBuffer );
\r
2404 BaseType_t xRemain = ( BaseType_t ) ( pxBuffer->LENGTH - pxBuffer->uxHead );
\r
2406 *pxLength = FreeRTOS_min_BaseType( xSpace, xRemain );
\r
2407 pucReturn = pxBuffer->ucArray + pxBuffer->uxHead;
\r
2417 #endif /* ipconfigUSE_TCP */
\r
2418 /*-----------------------------------------------------------*/
\r
2420 #if( ipconfigUSE_TCP == 1 )
\r
2422 * Send data using a TCP socket. It is not necessary to have the socket
\r
2423 * connected already. Outgoing data will be stored and delivered as soon as
\r
2424 * the socket gets connected.
\r
2426 BaseType_t FreeRTOS_send( Socket_t xSocket, const void *pvBuffer, size_t uxDataLength, BaseType_t xFlags )
\r
2428 BaseType_t xByteCount;
\r
2429 BaseType_t xBytesLeft;
\r
2430 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2431 TickType_t xRemainingTime;
\r
2432 BaseType_t xTimed = pdFALSE;
\r
2433 TimeOut_t xTimeOut;
\r
2434 BaseType_t xCloseAfterSend;
\r
2436 /* Prevent compiler warnings about unused parameters. The parameter
\r
2437 may be used in future versions. */
\r
2440 xByteCount = ( BaseType_t ) prvTCPSendCheck( pxSocket, uxDataLength );
\r
2442 if( xByteCount > 0 )
\r
2444 /* xBytesLeft is number of bytes to send, will count to zero. */
\r
2445 xBytesLeft = ( BaseType_t ) uxDataLength;
\r
2447 /* xByteCount is number of bytes that can be sent now. */
\r
2448 xByteCount = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
\r
2450 /* While there are still bytes to be sent. */
\r
2451 while( xBytesLeft > 0 )
\r
2453 /* If txStream has space. */
\r
2454 if( xByteCount > 0 )
\r
2456 /* Don't send more than necessary. */
\r
2457 if( xByteCount > xBytesLeft )
\r
2459 xByteCount = xBytesLeft;
\r
2462 /* Is the close-after-send flag set and is this really the
\r
2463 last transmission? */
\r
2464 if( ( pxSocket->u.xTCP.bits.bCloseAfterSend != pdFALSE_UNSIGNED ) && ( xByteCount == xBytesLeft ) )
\r
2466 xCloseAfterSend = pdTRUE;
\r
2470 xCloseAfterSend = pdFALSE;
\r
2473 /* The flag 'bCloseAfterSend' can be set before sending data
\r
2474 using setsockopt()
\r
2476 When the last data packet is being sent out, a FIN flag will
\r
2477 be included to let the peer know that no more data is to be
\r
2478 expected. The use of 'bCloseAfterSend' is not mandatory, it
\r
2479 is just a faster way of transferring files (e.g. when using
\r
2481 if( xCloseAfterSend != pdFALSE )
\r
2483 /* Now suspend the scheduler: sending the last data and
\r
2484 setting bCloseRequested must be done together */
\r
2485 vTaskSuspendAll();
\r
2486 pxSocket->u.xTCP.bits.bCloseRequested = pdTRUE_UNSIGNED;
\r
2489 xByteCount = ( BaseType_t ) uxStreamBufferAdd( pxSocket->u.xTCP.txStream, 0ul, ( const uint8_t * ) pvBuffer, ( size_t ) xByteCount );
\r
2491 if( xCloseAfterSend != pdFALSE )
\r
2493 /* Now when the IP-task transmits the data, it will also
\r
2494 see that bCloseRequested is true and include the FIN
\r
2495 flag to start closure of the connection. */
\r
2499 /* Send a message to the IP-task so it can work on this
\r
2500 socket. Data is sent, let the IP-task work on it. */
\r
2501 pxSocket->u.xTCP.usTimeout = 1u;
\r
2503 if( xIsCallingFromIPTask() == pdFALSE )
\r
2505 /* Only send a TCP timer event when not called from the
\r
2507 xSendEventToIPTask( eTCPTimerEvent );
\r
2510 xBytesLeft -= xByteCount;
\r
2512 if( xBytesLeft == 0 )
\r
2517 /* As there are still bytes left to be sent, increase the
\r
2519 pvBuffer = ( void * ) ( ( ( const uint8_t * ) pvBuffer) + xByteCount );
\r
2522 /* Not all bytes have been sent. In case the socket is marked as
\r
2523 blocking sleep for a while. */
\r
2524 if( xTimed == pdFALSE )
\r
2526 /* Only in the first round, check for non-blocking. */
\r
2527 xRemainingTime = pxSocket->xSendBlockTime;
\r
2529 #if( ipconfigUSE_CALLBACKS != 0 )
\r
2531 if( xIsCallingFromIPTask() != pdFALSE )
\r
2533 /* If this send function is called from within a
\r
2534 call-back handler it may not block, otherwise
\r
2535 chances would be big to get a deadlock: the IP-task
\r
2536 waiting for itself. */
\r
2537 xRemainingTime = ( TickType_t ) 0;
\r
2540 #endif /* ipconfigUSE_CALLBACKS */
\r
2542 if( xRemainingTime == ( TickType_t ) 0 )
\r
2547 if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
\r
2552 /* Don't get here a second time. */
\r
2555 /* Fetch the current time. */
\r
2556 vTaskSetTimeOutState( &xTimeOut );
\r
2560 /* Has the timeout been reached? */
\r
2561 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
\r
2567 /* Go sleeping until down-stream events are received. */
\r
2568 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_SEND | eSOCKET_CLOSED,
\r
2569 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2571 xByteCount = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
\r
2574 /* How much was actually sent? */
\r
2575 xByteCount = ( ( BaseType_t ) uxDataLength ) - xBytesLeft;
\r
2577 if( xByteCount == 0 )
\r
2579 if( pxSocket->u.xTCP.ucTCPState > eESTABLISHED )
\r
2581 xByteCount = ( BaseType_t ) -pdFREERTOS_ERRNO_ENOTCONN;
\r
2585 if( ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) != pdFALSE )
\r
2587 FreeRTOS_debug_printf( ( "FreeRTOS_send: %u -> %lxip:%d: no space\n",
\r
2588 pxSocket->usLocalPort,
\r
2589 pxSocket->u.xTCP.ulRemoteIP,
\r
2590 pxSocket->u.xTCP.usRemotePort ) );
\r
2593 xByteCount = ( BaseType_t ) -pdFREERTOS_ERRNO_ENOSPC;
\r
2598 return xByteCount;
\r
2601 #endif /* ipconfigUSE_TCP */
\r
2602 /*-----------------------------------------------------------*/
\r
2604 #if( ipconfigUSE_TCP == 1 )
\r
2607 * Request to put a socket in listen mode
\r
2609 BaseType_t FreeRTOS_listen( Socket_t xSocket, BaseType_t xBacklog )
\r
2611 FreeRTOS_Socket_t *pxSocket;
\r
2612 BaseType_t xResult = 0;
\r
2614 pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2616 /* listen() is allowed for a valid TCP socket in Closed state and already
\r
2618 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2620 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2622 else if( ( pxSocket->u.xTCP.ucTCPState != eCLOSED ) && ( pxSocket->u.xTCP.ucTCPState != eCLOSE_WAIT ) )
\r
2624 /* Socket is in a wrong state. */
\r
2625 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2629 /* Backlog is interpreted here as "the maximum number of child
\r
2631 pxSocket->u.xTCP.usBacklog = ( uint16_t )FreeRTOS_min_int32( ( int32_t ) 0xffff, ( int32_t ) xBacklog );
\r
2633 /* This cleaning is necessary only if a listening socket is being
\r
2634 reused as it might have had a previous connection. */
\r
2635 if( pxSocket->u.xTCP.bits.bReuseSocket )
\r
2637 if( pxSocket->u.xTCP.rxStream != NULL )
\r
2639 vStreamBufferClear( pxSocket->u.xTCP.rxStream );
\r
2642 if( pxSocket->u.xTCP.txStream != NULL )
\r
2644 vStreamBufferClear( pxSocket->u.xTCP.txStream );
\r
2647 memset( pxSocket->u.xTCP.xPacket.u.ucLastPacket, '\0', sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket ) );
\r
2648 memset( &pxSocket->u.xTCP.xTCPWindow, '\0', sizeof( pxSocket->u.xTCP.xTCPWindow ) );
\r
2649 memset( &pxSocket->u.xTCP.bits, '\0', sizeof( pxSocket->u.xTCP.bits ) );
\r
2651 /* Now set the bReuseSocket flag again, because the bits have
\r
2652 just been cleared. */
\r
2653 pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE_UNSIGNED;
\r
2656 vTCPStateChange( pxSocket, eTCP_LISTEN );
\r
2662 #endif /* ipconfigUSE_TCP */
\r
2663 /*-----------------------------------------------------------*/
\r
2665 #if( ipconfigUSE_TCP == 1 )
\r
2667 /* shutdown - shut down part of a full-duplex connection */
\r
2668 BaseType_t FreeRTOS_shutdown( Socket_t xSocket, BaseType_t xHow )
\r
2670 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2671 BaseType_t xResult;
\r
2673 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2675 /*_RB_ Is this comment correct? The socket is not of a type that
\r
2676 supports the listen() operation. */
\r
2677 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2679 else if ( pxSocket->u.xTCP.ucTCPState != eESTABLISHED )
\r
2681 /*_RB_ Is this comment correct? The socket is not of a type that
\r
2682 supports the listen() operation. */
\r
2683 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2687 pxSocket->u.xTCP.bits.bUserShutdown = pdTRUE_UNSIGNED;
\r
2689 /* Let the IP-task perform the shutdown of the connection. */
\r
2690 pxSocket->u.xTCP.usTimeout = 1u;
\r
2691 xSendEventToIPTask( eTCPTimerEvent );
\r
2699 #endif /* ipconfigUSE_TCP */
\r
2700 /*-----------------------------------------------------------*/
\r
2702 #if( ipconfigUSE_TCP == 1 )
\r
2705 * A TCP timer has expired, now check all TCP sockets for:
\r
2706 * - Active connect
\r
2707 * - Send a delayed ACK
\r
2709 * - Send a keep-alive packet
\r
2710 * - Check for timeout (in non-connected states only)
\r
2712 TickType_t xTCPTimerCheck( BaseType_t xWillSleep )
\r
2714 FreeRTOS_Socket_t *pxSocket;
\r
2715 TickType_t xShortest = pdMS_TO_TICKS( ( TickType_t ) ipTCP_TIMER_PERIOD_MS );
\r
2716 TickType_t xNow = xTaskGetTickCount();
\r
2717 static TickType_t xLastTime = 0u;
\r
2718 TickType_t xDelta = xNow - xLastTime;
\r
2719 ListItem_t* pxEnd = ( ListItem_t * ) listGET_END_MARKER( &xBoundTCPSocketsList );
\r
2720 ListItem_t *pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );
\r
2724 if( xDelta == 0u )
\r
2729 while( pxIterator != pxEnd )
\r
2731 pxSocket = ( FreeRTOS_Socket_t * )listGET_LIST_ITEM_OWNER( pxIterator );
\r
2732 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator );
\r
2734 /* Sockets with 'tmout == 0' do not need any regular attention. */
\r
2735 if( pxSocket->u.xTCP.usTimeout == 0u )
\r
2740 if( xDelta < ( TickType_t ) pxSocket->u.xTCP.usTimeout )
\r
2742 pxSocket->u.xTCP.usTimeout = ( uint16_t ) ( ( ( TickType_t ) pxSocket->u.xTCP.usTimeout ) - xDelta );
\r
2747 pxSocket->u.xTCP.usTimeout = 0u;
\r
2748 rc = xTCPSocketCheck( pxSocket );
\r
2750 /* Within this function, the socket might want to send a delayed
\r
2751 ack or send out data or whatever it needs to do. */
\r
2754 /* Continue because the socket was deleted. */
\r
2759 /* In xEventBits the driver may indicate that the socket has
\r
2760 important events for the user. These are only done just before the
\r
2761 IP-task goes to sleep. */
\r
2762 if( pxSocket->xEventBits != 0u )
\r
2764 if( xWillSleep != pdFALSE )
\r
2766 /* The IP-task is about to go to sleep, so messages can be
\r
2767 sent to the socket owners. */
\r
2768 vSocketWakeUpUser( pxSocket );
\r
2772 /* Or else make sure this will be called again to wake-up
\r
2773 the sockets' owner. */
\r
2774 xShortest = ( TickType_t ) 0;
\r
2778 if( ( pxSocket->u.xTCP.usTimeout != 0u ) && ( xShortest > ( TickType_t ) pxSocket->u.xTCP.usTimeout ) )
\r
2780 xShortest = ( TickType_t ) pxSocket->u.xTCP.usTimeout;
\r
2787 #endif /* ipconfigUSE_TCP */
\r
2788 /*-----------------------------------------------------------*/
\r
2790 #if( ipconfigUSE_TCP == 1 )
\r
2793 * TCP: as multiple sockets may be bound to the same local port number
\r
2794 * looking up a socket is a little more complex:
\r
2795 * Both a local port, and a remote port and IP address are being used
\r
2796 * For a socket in listening mode, the remote port and IP address are both 0
\r
2798 FreeRTOS_Socket_t *pxTCPSocketLookup( uint32_t ulLocalIP, UBaseType_t uxLocalPort, uint32_t ulRemoteIP, UBaseType_t uxRemotePort )
\r
2800 ListItem_t *pxIterator;
\r
2801 FreeRTOS_Socket_t *pxResult = NULL, *pxListenSocket = NULL;
\r
2802 MiniListItem_t *pxEnd = ( MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );
\r
2804 /* Parameter not yet supported. */
\r
2805 ( void ) ulLocalIP;
\r
2807 for( pxIterator = ( ListItem_t * ) listGET_NEXT( pxEnd );
\r
2808 pxIterator != ( ListItem_t * ) pxEnd;
\r
2809 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
2811 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
\r
2813 if( pxSocket->usLocalPort == ( uint16_t ) uxLocalPort )
\r
2815 if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN )
\r
2817 /* If this is a socket listening to uxLocalPort, remember it
\r
2818 in case there is no perfect match. */
\r
2819 pxListenSocket = pxSocket;
\r
2821 else if( ( pxSocket->u.xTCP.usRemotePort == ( uint16_t ) uxRemotePort ) && ( pxSocket->u.xTCP.ulRemoteIP == ulRemoteIP ) )
\r
2823 /* For sockets not in listening mode, find a match with
\r
2824 xLocalPort, ulRemoteIP AND xRemotePort. */
\r
2825 pxResult = pxSocket;
\r
2830 if( pxResult == NULL )
\r
2832 /* An exact match was not found, maybe a listening socket was
\r
2834 pxResult = pxListenSocket;
\r
2840 #endif /* ipconfigUSE_TCP */
\r
2841 /*-----------------------------------------------------------*/
\r
2843 #if( ipconfigUSE_TCP == 1 )
\r
2845 const struct xSTREAM_BUFFER *FreeRTOS_get_rx_buf( Socket_t xSocket )
\r
2847 FreeRTOS_Socket_t *pxSocket = (FreeRTOS_Socket_t *)xSocket;
\r
2849 return pxSocket->u.xTCP.rxStream;
\r
2852 #endif /* ipconfigUSE_TCP */
\r
2853 /*-----------------------------------------------------------*/
\r
2855 #if( ipconfigUSE_TCP == 1 )
\r
2857 static StreamBuffer_t *prvTCPCreateStream ( FreeRTOS_Socket_t *pxSocket, BaseType_t xIsInputStream )
\r
2859 StreamBuffer_t *pxBuffer;
\r
2863 /* Now that a stream is created, the maximum size is fixed before
\r
2864 creation, it could still be changed with setsockopt(). */
\r
2865 if( xIsInputStream != pdFALSE )
\r
2867 /* Flow control for input streams works with a low- and a high-water mark.
\r
2868 1) If the RX-space becomes less than uxLittleSpace, the flag 'bLowWater' will
\r
2869 be set, and a TCP window update message will be sent to the peer.
\r
2870 2) The data will be read from the socket by recv() and when RX-space becomes
\r
2871 larger than or equal to than 'uxEnoughSpace', a new TCP window update
\r
2872 message will be sent to the peer, and 'bLowWater' will get cleared again.
\r
2874 uxLittleSpace == 1/5 x uxRxStreamSize
\r
2875 uxEnoughSpace == 4/5 x uxRxStreamSize
\r
2876 How-ever it is very inefficient to make 'uxLittleSpace' smaller than the actual MSS.
\r
2878 uxLength = pxSocket->u.xTCP.uxRxStreamSize;
\r
2880 if( pxSocket->u.xTCP.uxLittleSpace == 0ul )
\r
2882 pxSocket->u.xTCP.uxLittleSpace = ( 1ul * pxSocket->u.xTCP.uxRxStreamSize ) / 5u; /*_RB_ Why divide by 5? Can this be changed to a #define? */
\r
2883 if( (pxSocket->u.xTCP.uxLittleSpace < pxSocket->u.xTCP.usCurMSS ) && ( pxSocket->u.xTCP.uxRxStreamSize >= 2 * pxSocket->u.xTCP.usCurMSS ) )
\r
2885 pxSocket->u.xTCP.uxLittleSpace = pxSocket->u.xTCP.usCurMSS;
\r
2889 if( pxSocket->u.xTCP.uxEnoughSpace == 0ul )
\r
2891 pxSocket->u.xTCP.uxEnoughSpace = ( 4ul * pxSocket->u.xTCP.uxRxStreamSize ) / 5u; /*_RB_ Why multiply by 4? Maybe sock80_PERCENT?*/
\r
2896 uxLength = pxSocket->u.xTCP.uxTxStreamSize;
\r
2899 /* Add an extra 4 (or 8) bytes. */
\r
2900 uxLength += sizeof( size_t );
\r
2902 /* And make the length a multiple of sizeof( size_t ). */
\r
2903 uxLength &= ~( sizeof( size_t ) - 1u );
\r
2905 uxSize = sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) + uxLength;
\r
2907 pxBuffer = ( StreamBuffer_t * )pvPortMallocLarge( uxSize );
\r
2909 if( pxBuffer == NULL )
\r
2911 FreeRTOS_debug_printf( ( "prvTCPCreateStream: malloc failed\n" ) );
\r
2912 pxSocket->u.xTCP.bits.bMallocError = pdTRUE_UNSIGNED;
\r
2913 vTCPStateChange( pxSocket, eCLOSE_WAIT );
\r
2917 /* Clear the markers of the stream */
\r
2918 memset( pxBuffer, '\0', sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) );
\r
2919 pxBuffer->LENGTH = ( size_t ) uxLength ;
\r
2921 if( xTCPWindowLoggingLevel != 0 )
\r
2923 FreeRTOS_debug_printf( ( "prvTCPCreateStream: %cxStream created %lu bytes (total %lu)\n", xIsInputStream ? 'R' : 'T', uxLength, uxSize ) );
\r
2926 if( xIsInputStream != 0 )
\r
2928 pxSocket->u.xTCP.rxStream = pxBuffer;
\r
2932 pxSocket->u.xTCP.txStream = pxBuffer;
\r
2939 #endif /* ipconfigUSE_TCP */
\r
2940 /*-----------------------------------------------------------*/
\r
2942 #if( ipconfigUSE_TCP == 1 )
\r
2945 * Add data to the RxStream. When uxOffset > 0, data has come in out-of-order
\r
2946 * and will be put in front of the head so it can not be popped by the user.
\r
2948 int32_t lTCPAddRxdata( FreeRTOS_Socket_t *pxSocket, size_t uxOffset, const uint8_t *pcData, uint32_t ulByteCount )
\r
2950 StreamBuffer_t *pxStream = pxSocket->u.xTCP.rxStream;
\r
2952 #if( ipconfigUSE_CALLBACKS == 1 )
\r
2953 BaseType_t bHasHandler = ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xTCP.pxHandleReceive );
\r
2954 const uint8_t *pucBuffer = NULL;
\r
2955 #endif /* ipconfigUSE_CALLBACKS */
\r
2957 /* int32_t uxStreamBufferAdd( pxBuffer, uxOffset, pucData, aCount )
\r
2958 if( pucData != NULL ) copy data the the buffer
\r
2959 if( pucData == NULL ) no copying, just advance rxHead
\r
2960 if( uxOffset != 0 ) Just store data which has come out-of-order
\r
2961 if( uxOffset == 0 ) Also advance rxHead */
\r
2962 if( pxStream == NULL )
\r
2964 pxStream = prvTCPCreateStream( pxSocket, pdTRUE );
\r
2965 if( pxStream == NULL )
\r
2971 #if( ipconfigUSE_CALLBACKS == 1 )
\r
2973 if( ( bHasHandler != pdFALSE ) && ( uxStreamBufferGetSize( pxStream ) == 0u ) && ( uxOffset == 0ul ) && ( pcData != NULL ) )
\r
2975 /* Data can be passed directly to the user */
\r
2976 pucBuffer = pcData;
\r
2978 /* Zero-copy for call-back: no need to add the bytes to the
\r
2979 stream, only the pointer will be advanced by uxStreamBufferAdd(). */
\r
2983 #endif /* ipconfigUSE_CALLBACKS */
\r
2985 xResult = ( int32_t ) uxStreamBufferAdd( pxStream, uxOffset, pcData, ( size_t ) ulByteCount );
\r
2987 #if( ipconfigHAS_DEBUG_PRINTF != 0 )
\r
2989 if( xResult != ( int32_t ) ulByteCount )
\r
2991 FreeRTOS_debug_printf( ( "lTCPAddRxdata: at %ld: %ld/%lu bytes (tail %lu head %lu space %lu front %lu)\n",
\r
2992 uxOffset, xResult, ulByteCount,
\r
2995 uxStreamBufferFrontSpace( pxStream ),
\r
2996 pxStream->uxFront ) );
\r
2999 #endif /* ipconfigHAS_DEBUG_PRINTF */
\r
3001 if( uxOffset == 0u )
\r
3003 /* Data is being added to rxStream at the head (offs = 0) */
\r
3004 #if( ipconfigUSE_CALLBACKS == 1 )
\r
3005 if( bHasHandler != pdFALSE )
\r
3007 /* The socket owner has installed an OnReceive handler. Pass the
\r
3008 Rx data, without copying from the rxStream, to the user. */
\r
3011 uint8_t *ucReadPtr = NULL;
\r
3013 if( pucBuffer != NULL )
\r
3015 ucReadPtr = ( uint8_t * )pucBuffer;
\r
3016 ulCount = ulByteCount;
\r
3021 ulCount = ( uint32_t ) uxStreamBufferGetPtr( pxStream, &( ucReadPtr ) );
\r
3024 if( ulCount == 0ul )
\r
3029 if( pxSocket->u.xTCP.pxHandleReceive( (Socket_t *)pxSocket, ( void* )ucReadPtr, ( size_t ) ulCount ) != pdFALSE )
\r
3031 uxStreamBufferGet( pxStream, 0ul, NULL, ( size_t ) ulCount, pdFALSE );
\r
3035 #endif /* ipconfigUSE_CALLBACKS */
\r
3037 /* See if running out of space. */
\r
3038 if( pxSocket->u.xTCP.bits.bLowWater == pdFALSE_UNSIGNED )
\r
3040 size_t uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );
\r
3041 if( uxFrontSpace <= pxSocket->u.xTCP.uxLittleSpace )
\r
3043 pxSocket->u.xTCP.bits.bLowWater = pdTRUE_UNSIGNED;
\r
3044 pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
\r
3046 /* bLowWater was reached, send the changed window size. */
\r
3047 pxSocket->u.xTCP.usTimeout = 1u;
\r
3048 xSendEventToIPTask( eTCPTimerEvent );
\r
3052 /* New incoming data is available, wake up the user. User's
\r
3053 semaphores will be set just before the IP-task goes asleep. */
\r
3054 pxSocket->xEventBits |= eSOCKET_RECEIVE;
\r
3056 #if ipconfigSUPPORT_SELECT_FUNCTION == 1
\r
3058 if( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 )
\r
3060 pxSocket->xEventBits |= ( eSELECT_READ << SOCKET_EVENT_BIT_COUNT );
\r
3070 #endif /* ipconfigUSE_TCP */
\r
3071 /*-----------------------------------------------------------*/
\r
3073 #if( ipconfigUSE_TCP == 1 )
\r
3075 /* Function to get the remote address and IP port */
\r
3076 BaseType_t FreeRTOS_GetRemoteAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress )
\r
3078 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3079 BaseType_t xResult;
\r
3081 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3083 xResult = -pdFREERTOS_ERRNO_EINVAL;
\r
3087 /* BSD style sockets communicate IP and port addresses in network
\r
3090 IP address of remote machine. */
\r
3091 pxAddress->sin_addr = FreeRTOS_htonl ( pxSocket->u.xTCP.ulRemoteIP );
\r
3093 /* Port on remote machine. */
\r
3094 pxAddress->sin_port = FreeRTOS_htons ( pxSocket->u.xTCP.usRemotePort );
\r
3096 xResult = ( BaseType_t ) sizeof( ( *pxAddress ) );
\r
3102 #endif /* ipconfigUSE_TCP */
\r
3104 /*-----------------------------------------------------------*/
\r
3106 #if( ipconfigUSE_TCP == 1 )
\r
3108 /* Returns the number of bytes that may be added to txStream */
\r
3109 BaseType_t FreeRTOS_maywrite( Socket_t xSocket )
\r
3111 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3112 BaseType_t xResult;
\r
3114 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3116 xResult = -pdFREERTOS_ERRNO_EINVAL;
\r
3118 else if( pxSocket->u.xTCP.ucTCPState != eESTABLISHED )
\r
3120 if( ( pxSocket->u.xTCP.ucTCPState < eCONNECT_SYN ) || ( pxSocket->u.xTCP.ucTCPState > eESTABLISHED ) )
\r
3129 else if( pxSocket->u.xTCP.txStream == NULL )
\r
3131 xResult = ( BaseType_t ) pxSocket->u.xTCP.uxTxStreamSize;
\r
3135 xResult = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
\r
3141 #endif /* ipconfigUSE_TCP */
\r
3142 /*-----------------------------------------------------------*/
\r
3144 #if( ipconfigUSE_TCP ==1 )
\r
3146 BaseType_t FreeRTOS_tx_space( Socket_t xSocket )
\r
3148 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3149 BaseType_t xReturn;
\r
3151 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3153 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3157 if( pxSocket->u.xTCP.txStream != NULL )
\r
3159 xReturn = ( BaseType_t ) uxStreamBufferGetSpace ( pxSocket->u.xTCP.txStream );
\r
3163 xReturn = ( BaseType_t ) pxSocket->u.xTCP.uxTxStreamSize;
\r
3170 #endif /* ipconfigUSE_TCP */
\r
3171 /*-----------------------------------------------------------*/
\r
3173 #if( ipconfigUSE_TCP == 1 )
\r
3175 BaseType_t FreeRTOS_tx_size( Socket_t xSocket )
\r
3177 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3178 BaseType_t xReturn;
\r
3180 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3182 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3186 if( pxSocket->u.xTCP.txStream != NULL )
\r
3188 xReturn = ( BaseType_t ) uxStreamBufferGetSize ( pxSocket->u.xTCP.txStream );
\r
3199 #endif /* ipconfigUSE_TCP */
\r
3200 /*-----------------------------------------------------------*/
\r
3202 #if( ipconfigUSE_TCP == 1 )
\r
3204 /* Returns pdTRUE if TCP socket is connected. */
\r
3205 BaseType_t FreeRTOS_issocketconnected( Socket_t xSocket )
\r
3207 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3208 BaseType_t xReturn = pdFALSE;
\r
3210 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3212 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3216 if( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED )
\r
3218 if( pxSocket->u.xTCP.ucTCPState < eCLOSE_WAIT )
\r
3228 #endif /* ipconfigUSE_TCP */
\r
3229 /*-----------------------------------------------------------*/
\r
3231 #if( ipconfigUSE_TCP == 1 )
\r
3233 /* returns the actual size of MSS being used */
\r
3234 BaseType_t FreeRTOS_mss( Socket_t xSocket )
\r
3236 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3237 BaseType_t xReturn;
\r
3239 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3241 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3245 /* usCurMSS is declared as uint16_t to save space. FreeRTOS_mss()
\r
3246 will often be used in signed native-size expressions cast it to
\r
3248 xReturn = ( BaseType_t ) ( pxSocket->u.xTCP.usCurMSS );
\r
3254 #endif /* ipconfigUSE_TCP */
\r
3255 /*-----------------------------------------------------------*/
\r
3257 #if( ipconfigUSE_TCP == 1 )
\r
3259 /* HT: for internal use only: return the connection status */
\r
3260 BaseType_t FreeRTOS_connstatus( Socket_t xSocket )
\r
3262 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3263 BaseType_t xReturn;
\r
3265 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3267 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3271 /* Cast it to BaseType_t */
\r
3272 xReturn = ( BaseType_t ) ( pxSocket->u.xTCP.ucTCPState );
\r
3278 #endif /* ipconfigUSE_TCP */
\r
3279 /*-----------------------------------------------------------*/
\r
3281 #if( ipconfigUSE_TCP == 1 )
\r
3284 * Returns the number of bytes which can be read.
\r
3286 BaseType_t FreeRTOS_rx_size( Socket_t xSocket )
\r
3288 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3289 BaseType_t xReturn;
\r
3291 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3293 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3295 else if( pxSocket->u.xTCP.rxStream != NULL )
\r
3297 xReturn = ( BaseType_t ) uxStreamBufferGetSize( pxSocket->u.xTCP.rxStream );
\r
3307 #endif /* ipconfigUSE_TCP */
\r
3308 /*-----------------------------------------------------------*/
\r
3310 #if( ipconfigUSE_TCP == 1 )
\r
3312 void FreeRTOS_netstat( void )
\r
3314 IPStackEvent_t xAskEvent;
\r
3316 /* Ask the IP-task to call vTCPNetStat()
\r
3317 * to avoid accessing xBoundTCPSocketsList
\r
3319 xAskEvent.eEventType = eTCPNetStat;
\r
3320 xAskEvent.pvData = ( void * ) NULL;
\r
3321 xSendEventStructToIPTask( &xAskEvent, 1000u );
\r
3324 #endif /* ipconfigUSE_TCP */
\r
3325 /*-----------------------------------------------------------*/
\r
3327 #if( ( ipconfigHAS_PRINTF != 0 ) && ( ipconfigUSE_TCP == 1 ) )
\r
3329 void vTCPNetStat( void )
\r
3331 /* Show a simple listing of all created sockets and their connections */
\r
3332 ListItem_t *pxIterator;
\r
3333 BaseType_t count = 0;
\r
3335 if( listLIST_IS_INITIALISED( &xBoundTCPSocketsList ) == pdFALSE )
\r
3337 FreeRTOS_printf( ( "PLUS-TCP not initialized\n" ) );
\r
3341 FreeRTOS_printf( ( "Prot Port IP-Remote : Port R/T Status Alive tmout Child\n" ) );
\r
3342 for( pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );
\r
3343 pxIterator != ( ListItem_t * ) listGET_END_MARKER( &xBoundTCPSocketsList );
\r
3344 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
3346 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
\r
3347 #if( ipconfigTCP_KEEP_ALIVE == 1 )
\r
3348 TickType_t age = xTaskGetTickCount() - pxSocket->u.xTCP.xLastAliveTime;
\r
3350 TickType_t age = 0u;
\r
3352 #if( ipconfigUSE_CALLBACKS == 1 )
\r
3353 void *pxHandleReceive = (void*)pxSocket->u.xTCP.pxHandleReceive;
\r
3355 void *pxHandleReceive = (void*)NULL;
\r
3357 char ucChildText[16] = "";
\r
3358 if (pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN)
\r
3360 snprintf( ucChildText, sizeof( ucChildText ), " %d/%d",
\r
3361 pxSocket->u.xTCP.usChildCount,
\r
3362 pxSocket->u.xTCP.usBacklog);
\r
3364 if( age > 999999 )
\r
3366 FreeRTOS_printf( ( "TCP %5d %-16lxip:%5d %d/%d %-13.13s %6lu %6u%s\n",
\r
3367 pxSocket->usLocalPort, /* Local port on this machine */
\r
3368 pxSocket->u.xTCP.ulRemoteIP, /* IP address of remote machine */
\r
3369 pxSocket->u.xTCP.usRemotePort, /* Port on remote machine */
\r
3370 pxSocket->u.xTCP.rxStream != NULL,
\r
3371 pxSocket->u.xTCP.txStream != NULL,
\r
3372 FreeRTOS_GetTCPStateName( pxSocket->u.xTCP.ucTCPState ),
\r
3374 pxSocket->u.xTCP.usTimeout,
\r
3376 /* Remove compiler warnings if FreeRTOS_debug_printf() is not defined. */
\r
3377 ( void ) pxHandleReceive;
\r
3381 for( pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundUDPSocketsList );
\r
3382 pxIterator != ( ListItem_t * ) listGET_END_MARKER( &xBoundUDPSocketsList );
\r
3383 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
3385 /* Local port on this machine */
\r
3386 FreeRTOS_printf( ( "UDP Port %5u\n",
\r
3387 FreeRTOS_ntohs( listGET_LIST_ITEM_VALUE( pxIterator ) ) ) );
\r
3391 FreeRTOS_printf( ( "FreeRTOS_netstat: %lu sockets %lu < %lu < %d buffers free\n",
\r
3393 uxGetMinimumFreeNetworkBuffers( ),
\r
3394 uxGetNumberOfFreeNetworkBuffers( ),
\r
3395 ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ) );
\r
3399 #endif /* ( ( ipconfigHAS_PRINTF != 0 ) && ( ipconfigUSE_TCP == 1 ) ) */
\r
3400 /*-----------------------------------------------------------*/
\r
3402 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
3404 void vSocketSelect( SocketSelect_t *pxSocketSet )
\r
3406 BaseType_t xRound;
\r
3407 EventBits_t xSocketBits, xBitsToClear;
\r
3408 #if ipconfigUSE_TCP == 1
\r
3409 BaseType_t xLastRound = 1;
\r
3411 BaseType_t xLastRound = 0;
\r
3414 /* These flags will be switched on after checking the socket status. */
\r
3415 EventBits_t xGroupBits = 0;
\r
3416 pxSocketSet->pxSocket = NULL;
\r
3418 for( xRound = 0; xRound <= xLastRound; xRound++ )
\r
3420 const ListItem_t *pxIterator;
\r
3421 const MiniListItem_t *pxEnd;
\r
3424 pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundUDPSocketsList );
\r
3426 #if ipconfigUSE_TCP == 1
\r
3429 pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );
\r
3431 #endif /* ipconfigUSE_TCP == 1 */
\r
3432 for( pxIterator = ( const ListItem_t * ) ( listGET_NEXT( pxEnd ) );
\r
3433 pxIterator != ( const ListItem_t * ) pxEnd;
\r
3434 pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
3436 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
\r
3437 if( pxSocket->pxSocketSet != pxSocketSet )
\r
3439 /* Socket does not belong to this select group. */
\r
3444 #if( ipconfigUSE_TCP == 1 )
\r
3445 if( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP )
\r
3447 /* Check if the socket has already been accepted by the
\r
3448 owner. If not, it is useless to return it from a
\r
3450 BaseType_t bAccepted = pdFALSE;
\r
3452 if( pxSocket->u.xTCP.bits.bPassQueued == pdFALSE_UNSIGNED )
\r
3454 if( pxSocket->u.xTCP.bits.bPassAccept == pdFALSE_UNSIGNED )
\r
3456 bAccepted = pdTRUE;
\r
3460 /* Is the set owner interested in READ events? */
\r
3461 if( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 )
\r
3463 if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN )
\r
3465 if( ( pxSocket->u.xTCP.pxPeerSocket != NULL ) && ( pxSocket->u.xTCP.pxPeerSocket->u.xTCP.bits.bPassAccept != 0 ) )
\r
3467 xSocketBits |= eSELECT_READ;
\r
3470 else if( ( pxSocket->u.xTCP.bits.bReuseSocket != pdFALSE_UNSIGNED ) && ( pxSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED ) )
\r
3472 /* This socket has the re-use flag. After connecting it turns into
\r
3473 aconnected socket. Set the READ event, so that accept() will be called. */
\r
3474 xSocketBits |= eSELECT_READ;
\r
3476 else if( ( bAccepted != 0 ) && ( FreeRTOS_recvcount( pxSocket ) > 0 ) )
\r
3478 xSocketBits |= eSELECT_READ;
\r
3481 /* Is the set owner interested in EXCEPTION events? */
\r
3482 if( ( pxSocket->xSelectBits & eSELECT_EXCEPT ) != 0 )
\r
3484 if( ( pxSocket->u.xTCP.ucTCPState == eCLOSE_WAIT ) || ( pxSocket->u.xTCP.ucTCPState == eCLOSED ) )
\r
3486 xSocketBits |= eSELECT_EXCEPT;
\r
3490 /* Is the set owner interested in WRITE events? */
\r
3491 if( ( pxSocket->xSelectBits & eSELECT_WRITE ) != 0 )
\r
3493 BaseType_t bMatch = pdFALSE;
\r
3495 if( bAccepted != 0 )
\r
3497 if( FreeRTOS_tx_space( pxSocket ) > 0 )
\r
3503 if( bMatch == pdFALSE )
\r
3505 if( ( pxSocket->u.xTCP.bits.bConnPrepared != pdFALSE_UNSIGNED ) &&
\r
3506 ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) &&
\r
3507 ( pxSocket->u.xTCP.bits.bConnPassed == pdFALSE_UNSIGNED ) )
\r
3509 pxSocket->u.xTCP.bits.bConnPassed = pdTRUE_UNSIGNED;
\r
3514 if( bMatch != pdFALSE )
\r
3516 xSocketBits |= eSELECT_WRITE;
\r
3521 #endif /* ipconfigUSE_TCP == 1 */
\r
3523 /* Select events for UDP are simpler. */
\r
3524 if( ( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 ) &&
\r
3525 ( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) > 0U ) )
\r
3527 xSocketBits |= eSELECT_READ;
\r
3529 /* The WRITE and EXCEPT bits are not used for UDP */
\r
3530 } /* if( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP ) */
\r
3532 /* Each socket keeps its own event flags, which are looked-up
\r
3533 by FreeRTOS_FD_ISSSET() */
\r
3534 pxSocket->xSocketBits = xSocketBits;
\r
3536 /* The ORed value will be used to set the bits in the event
\r
3538 xGroupBits |= xSocketBits;
\r
3540 } /* for( pxIterator ... ) */
\r
3541 } /* for( xRound = 0; xRound <= xLastRound; xRound++ ) */
\r
3543 xBitsToClear = xEventGroupGetBits( pxSocketSet->xSelectGroup );
\r
3545 /* Now set the necessary bits. */
\r
3546 xBitsToClear = ( xBitsToClear & ~xGroupBits ) & eSELECT_ALL;
\r
3548 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
3550 /* Maybe the socketset was signalled, but don't
\r
3551 clear the 'eSELECT_INTR' bit here, as it will be used
\r
3552 and cleared in FreeRTOS_select(). */
\r
3553 xBitsToClear &= ( EventBits_t ) ~eSELECT_INTR;
\r
3555 #endif /* ipconfigSUPPORT_SIGNALS */
\r
3557 if( xBitsToClear != 0 )
\r
3559 xEventGroupClearBits( pxSocketSet->xSelectGroup, xBitsToClear );
\r
3562 /* Now include eSELECT_CALL_IP to wakeup the caller. */
\r
3563 xEventGroupSetBits( pxSocketSet->xSelectGroup, xGroupBits | eSELECT_CALL_IP );
\r
3566 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
3567 /*-----------------------------------------------------------*/
\r
3569 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
3571 /* Send a signal to the task which reads from this socket. */
\r
3572 BaseType_t FreeRTOS_SignalSocket( Socket_t xSocket )
\r
3574 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3575 BaseType_t xReturn;
\r
3577 if( pxSocket == NULL )
\r
3579 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3582 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
3583 if( ( pxSocket->pxSocketSet != NULL ) && ( pxSocket->pxSocketSet->xSelectGroup != NULL ) )
\r
3585 xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, eSELECT_INTR );
\r
3589 #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
\r
3590 if( pxSocket->xEventGroup != NULL )
\r
3592 xEventGroupSetBits( pxSocket->xEventGroup, eSOCKET_INTR );
\r
3597 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3603 #endif /* ipconfigSUPPORT_SIGNALS */
\r
3604 /*-----------------------------------------------------------*/
\r
3606 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
3608 /* Send a signal to the task which reads from this socket (FromISR version). */
\r
3609 BaseType_t FreeRTOS_SignalSocketFromISR( Socket_t xSocket, BaseType_t *pxHigherPriorityTaskWoken )
\r
3611 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3612 BaseType_t xReturn;
\r
3613 IPStackEvent_t xEvent;
\r
3614 extern QueueHandle_t xNetworkEventQueue;
\r
3616 configASSERT( pxSocket != NULL );
\r
3617 configASSERT( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP );
\r
3618 configASSERT( pxSocket->xEventGroup );
\r
3620 xEvent.eEventType = eSocketSignalEvent;
\r
3621 xEvent.pvData = ( void * )pxSocket;
\r
3623 /* The IP-task will call FreeRTOS_SignalSocket for this socket. */
\r
3624 xReturn = xQueueSendToBackFromISR( xNetworkEventQueue, &xEvent, pxHigherPriorityTaskWoken );
\r
3629 #endif /* ipconfigSUPPORT_SIGNALS */
\r
3630 /*-----------------------------------------------------------*/
\r