2 * FreeRTOS+TCP V2.0.3
\r
3 * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\r
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
\r
6 * this software and associated documentation files (the "Software"), to deal in
\r
7 * the Software without restriction, including without limitation the rights to
\r
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
\r
9 * the Software, and to permit persons to whom the Software is furnished to do so,
\r
10 * subject to the following conditions:
\r
12 * The above copyright notice and this permission notice shall be included in all
\r
13 * copies or substantial portions of the Software.
\r
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
\r
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
\r
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
\r
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
22 * http://aws.amazon.com/freertos
\r
23 * http://www.FreeRTOS.org
\r
26 /* Standard includes. */
\r
30 /* FreeRTOS includes. */
\r
31 #include "FreeRTOS.h"
\r
36 /* FreeRTOS+TCP includes. */
\r
37 #include "FreeRTOS_UDP_IP.h"
\r
38 #include "FreeRTOS_IP.h"
\r
39 #include "FreeRTOS_Sockets.h"
\r
40 #include "FreeRTOS_IP_Private.h"
\r
41 #include "FreeRTOS_DNS.h"
\r
42 #include "NetworkBufferManagement.h"
\r
44 /* The ItemValue of the sockets xBoundSocketListItem member holds the socket's
\r
46 #define socketSET_SOCKET_PORT( pxSocket, usPort ) listSET_LIST_ITEM_VALUE( ( &( ( pxSocket )->xBoundSocketListItem ) ), ( usPort ) )
\r
47 #define socketGET_SOCKET_PORT( pxSocket ) listGET_LIST_ITEM_VALUE( ( &( ( pxSocket )->xBoundSocketListItem ) ) )
\r
49 /* Test if a socket it bound which means it is either included in
\r
50 xBoundUDPSocketsList or xBoundTCPSocketsList */
\r
51 #define socketSOCKET_IS_BOUND( pxSocket ) ( listLIST_ITEM_CONTAINER( & ( pxSocket )->xBoundSocketListItem ) != NULL )
\r
53 /* If FreeRTOS_sendto() is called on a socket that is not bound to a port
\r
54 number then, depending on the FreeRTOSIPConfig.h settings, it might be that a
\r
55 port number is automatically generated for the socket. Automatically generated
\r
56 port numbers will be between socketAUTO_PORT_ALLOCATION_START_NUMBER and
\r
58 /* _HT_ thinks that the default of 0xc000 is pretty high */
\r
59 #if !defined( socketAUTO_PORT_ALLOCATION_START_NUMBER )
\r
60 #define socketAUTO_PORT_ALLOCATION_START_NUMBER ( ( uint16_t ) 0xc000 )
\r
63 /* When the automatically generated port numbers overflow, the next value used
\r
64 is not set back to socketAUTO_PORT_ALLOCATION_START_NUMBER because it is likely
\r
65 that the first few automatically generated ports will still be in use. Instead
\r
66 it is reset back to the value defined by this constant. */
\r
67 #define socketAUTO_PORT_ALLOCATION_RESET_NUMBER ( ( uint16_t ) 0xc100 )
\r
68 #define socketAUTO_PORT_ALLOCATION_MAX_NUMBER ( ( uint16_t ) 0xff00 )
\r
70 /* The number of octets that make up an IP address. */
\r
71 #define socketMAX_IP_ADDRESS_OCTETS 4u
\r
73 /* A block time of 0 simply means "don't block". */
\r
74 #define socketDONT_BLOCK ( ( TickType_t ) 0 )
\r
76 #if( ( ipconfigUSE_TCP == 1 ) && !defined( ipTCP_TIMER_PERIOD_MS ) )
\r
77 #define ipTCP_TIMER_PERIOD_MS ( 1000 )
\r
80 /* The next private port number to use when binding a client socket is stored in
\r
81 the usNextPortToUse[] array - which has either 1 or two indexes depending on
\r
82 whether TCP is being supported. */
\r
83 #if( ipconfigUSE_TCP == 1 )
\r
84 #define socketPROTOCOL_COUNT 2
\r
86 #define socketPROTOCOL_COUNT 1
\r
89 /* Indexes into the usNextPortToUse[] array for UDP and TCP sockets
\r
91 #define socketNEXT_UDP_PORT_NUMBER_INDEX 0
\r
92 #define socketNEXT_TCP_PORT_NUMBER_INDEX 1
\r
95 /*-----------------------------------------------------------*/
\r
98 * Allocate the next port number from the private allocation range.
\r
99 * TCP and UDP each have their own series of port numbers
\r
100 * ulProtocol is either ipPROTOCOL_UDP or ipPROTOCOL_TCP
\r
102 static uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol );
\r
105 * Return the list item from within pxList that has an item value of
\r
106 * xWantedItemValue. If there is no such list item return NULL.
\r
108 static const ListItem_t * pxListFindListItemWithValue( const List_t *pxList, TickType_t xWantedItemValue );
\r
111 * Return pdTRUE only if pxSocket is valid and bound, as far as can be
\r
114 static BaseType_t prvValidSocket( FreeRTOS_Socket_t *pxSocket, BaseType_t xProtocol, BaseType_t xIsBound );
\r
117 * Before creating a socket, check the validity of the parameters used
\r
118 * and find the size of the socket space, which is different for UDP and TCP
\r
120 static BaseType_t prvDetermineSocketSize( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol, size_t *pxSocketSize );
\r
122 #if( ipconfigUSE_TCP == 1 )
\r
124 * Create a txStream or a rxStream, depending on the parameter 'xIsInputStream'
\r
126 static StreamBuffer_t *prvTCPCreateStream (FreeRTOS_Socket_t *pxSocket, BaseType_t xIsInputStream );
\r
127 #endif /* ipconfigUSE_TCP == 1 */
\r
129 #if( ipconfigUSE_TCP == 1 )
\r
131 * Called from FreeRTOS_send(): some checks which will be done before
\r
132 * sending a TCP packed.
\r
134 static int32_t prvTCPSendCheck( FreeRTOS_Socket_t *pxSocket, size_t xDataLength );
\r
135 #endif /* ipconfigUSE_TCP */
\r
137 #if( ipconfigUSE_TCP == 1 )
\r
139 * When a child socket gets closed, make sure to update the child-count of the parent
\r
141 static void prvTCPSetSocketCount( FreeRTOS_Socket_t *pxSocketToDelete );
\r
142 #endif /* ipconfigUSE_TCP == 1 */
\r
144 #if( ipconfigUSE_TCP == 1 )
\r
146 * Called from FreeRTOS_connect(): make some checks and if allowed, send a
\r
147 * message to the IP-task to start connecting to a remote socket
\r
149 static BaseType_t prvTCPConnectStart( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr *pxAddress );
\r
150 #endif /* ipconfigUSE_TCP */
\r
152 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
154 /* Executed by the IP-task, it will check all sockets belonging to a set */
\r
155 static FreeRTOS_Socket_t *prvFindSelectedSocket( SocketSelect_t *pxSocketSet );
\r
157 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
158 /*-----------------------------------------------------------*/
\r
160 /* The list that contains mappings between sockets and port numbers. Accesses
\r
161 to this list must be protected by critical sections of one kind or another. */
\r
162 List_t xBoundUDPSocketsList;
\r
164 #if ipconfigUSE_TCP == 1
\r
165 List_t xBoundTCPSocketsList;
\r
166 #endif /* ipconfigUSE_TCP == 1 */
\r
168 /* Holds the next private port number to use when binding a client socket for
\r
169 UDP, and if ipconfigUSE_TCP is set to 1, also TCP. UDP uses index
\r
170 socketNEXT_UDP_PORT_NUMBER_INDEX and TCP uses index
\r
171 socketNEXT_TCP_PORT_NUMBER_INDEX. The initial value is set to be between
\r
172 socketAUTO_PORT_ALLOCATION_RESET_NUMBER and socketAUTO_PORT_ALLOCATION_MAX_NUMBER
\r
173 when the IP stack is initialised. Note ipconfigRAND32() is used, which must be
\r
174 seeded prior to the IP task being started. */
\r
175 static uint16_t usNextPortToUse[ socketPROTOCOL_COUNT ] = { 0 };
\r
177 /*-----------------------------------------------------------*/
\r
179 static BaseType_t prvValidSocket( FreeRTOS_Socket_t *pxSocket, BaseType_t xProtocol, BaseType_t xIsBound )
\r
181 BaseType_t xReturn = pdTRUE;
\r
183 if( ( pxSocket == NULL ) || ( pxSocket == FREERTOS_INVALID_SOCKET ) )
\r
187 else if( ( xIsBound != pdFALSE ) && ( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE ) )
\r
189 /* The caller expects the socket to be bound, but it isn't. */
\r
192 else if( pxSocket->ucProtocol != ( uint8_t ) xProtocol )
\r
194 /* Socket has a wrong type (UDP != TCP). */
\r
200 /*-----------------------------------------------------------*/
\r
202 void vNetworkSocketsInit( void )
\r
204 const uint32_t ulAutoPortRange = socketAUTO_PORT_ALLOCATION_MAX_NUMBER - socketAUTO_PORT_ALLOCATION_RESET_NUMBER;
\r
205 uint32_t ulRandomPort;
\r
207 vListInitialise( &xBoundUDPSocketsList );
\r
209 /* Determine the first anonymous UDP port number to get assigned. Give it
\r
210 a random value in order to avoid confusion about port numbers being used
\r
211 earlier, before rebooting the device. Start with the first auto port
\r
212 number, then add a random offset up to a maximum of the range of numbers. */
\r
213 ulRandomPort = socketAUTO_PORT_ALLOCATION_START_NUMBER;
\r
214 ulRandomPort += ( ipconfigRAND32() % ulAutoPortRange );
\r
215 usNextPortToUse[ socketNEXT_UDP_PORT_NUMBER_INDEX ] = ( uint16_t ) ulRandomPort;
\r
217 #if( ipconfigUSE_TCP == 1 )
\r
219 extern uint32_t ulNextInitialSequenceNumber;
\r
221 ulNextInitialSequenceNumber = ipconfigRAND32();
\r
223 /* Determine the first anonymous TCP port number to get assigned. */
\r
224 ulRandomPort = socketAUTO_PORT_ALLOCATION_START_NUMBER;
\r
225 ulRandomPort += ( ipconfigRAND32() % ulAutoPortRange );
\r
226 usNextPortToUse[ socketNEXT_TCP_PORT_NUMBER_INDEX ] = ( uint16_t ) ulRandomPort;
\r
228 vListInitialise( &xBoundTCPSocketsList );
\r
230 #endif /* ipconfigUSE_TCP == 1 */
\r
232 /*-----------------------------------------------------------*/
\r
234 static BaseType_t prvDetermineSocketSize( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol, size_t *pxSocketSize )
\r
236 BaseType_t xReturn = pdPASS;
\r
237 FreeRTOS_Socket_t *pxSocket;
\r
239 /* Asserts must not appear before it has been determined that the network
\r
240 task is ready - otherwise the asserts will fail. */
\r
241 if( xIPIsNetworkTaskReady() == pdFALSE )
\r
247 /* Only Ethernet is currently supported. */
\r
248 configASSERT( xDomain == FREERTOS_AF_INET );
\r
250 /* Check if the UDP socket-list has been initialised. */
\r
251 configASSERT( listLIST_IS_INITIALISED( &xBoundUDPSocketsList ) );
\r
252 #if( ipconfigUSE_TCP == 1 )
\r
254 /* Check if the TCP socket-list has been initialised. */
\r
255 configASSERT( listLIST_IS_INITIALISED( &xBoundTCPSocketsList ) );
\r
257 #endif /* ipconfigUSE_TCP == 1 */
\r
259 if( xProtocol == FREERTOS_IPPROTO_UDP )
\r
261 if( xType != FREERTOS_SOCK_DGRAM )
\r
265 /* In case a UDP socket is created, do not allocate space for TCP data. */
\r
266 *pxSocketSize = ( sizeof( *pxSocket ) - sizeof( pxSocket->u ) ) + sizeof( pxSocket->u.xUDP );
\r
268 #if( ipconfigUSE_TCP == 1 )
\r
269 else if( xProtocol == FREERTOS_IPPROTO_TCP )
\r
271 if( xType != FREERTOS_SOCK_STREAM )
\r
276 *pxSocketSize = ( sizeof( *pxSocket ) - sizeof( pxSocket->u ) ) + sizeof( pxSocket->u.xTCP );
\r
278 #endif /* ipconfigUSE_TCP == 1 */
\r
284 /* In case configASSERT() is not used */
\r
288 /*-----------------------------------------------------------*/
\r
290 /* FreeRTOS_socket() allocates and initiates a socket */
\r
291 Socket_t FreeRTOS_socket( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol )
\r
293 FreeRTOS_Socket_t *pxSocket;
\r
294 size_t uxSocketSize;
\r
295 EventGroupHandle_t xEventGroup;
\r
298 if( prvDetermineSocketSize( xDomain, xType, xProtocol, &uxSocketSize ) == pdFAIL )
\r
300 xReturn = FREERTOS_INVALID_SOCKET;
\r
304 /* Allocate the structure that will hold the socket information. The
\r
305 size depends on the type of socket: UDP sockets need less space. A
\r
306 define 'pvPortMallocSocket' will used to allocate the necessary space.
\r
307 By default it points to the FreeRTOS function 'pvPortMalloc()'. */
\r
308 pxSocket = ( FreeRTOS_Socket_t * ) pvPortMallocSocket( uxSocketSize );
\r
310 if( pxSocket == NULL )
\r
312 pxSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
\r
313 iptraceFAILED_TO_CREATE_SOCKET();
\r
315 else if( ( xEventGroup = xEventGroupCreate() ) == NULL )
\r
317 vPortFreeSocket( pxSocket );
\r
318 pxSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
\r
319 iptraceFAILED_TO_CREATE_EVENT_GROUP();
\r
323 /* Clear the entire space to avoid nulling individual entries. */
\r
324 memset( pxSocket, '\0', uxSocketSize );
\r
326 pxSocket->xEventGroup = xEventGroup;
\r
328 /* Initialise the socket's members. The semaphore will be created
\r
329 if the socket is bound to an address, for now the pointer to the
\r
330 semaphore is just set to NULL to show it has not been created. */
\r
331 if( xProtocol == FREERTOS_IPPROTO_UDP )
\r
333 vListInitialise( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
\r
335 #if( ipconfigUDP_MAX_RX_PACKETS > 0 )
\r
337 pxSocket->u.xUDP.uxMaxPackets = ( UBaseType_t ) ipconfigUDP_MAX_RX_PACKETS;
\r
339 #endif /* ipconfigUDP_MAX_RX_PACKETS > 0 */
\r
342 vListInitialiseItem( &( pxSocket->xBoundSocketListItem ) );
\r
343 listSET_LIST_ITEM_OWNER( &( pxSocket->xBoundSocketListItem ), ( void * ) pxSocket );
\r
345 pxSocket->xReceiveBlockTime = ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME;
\r
346 pxSocket->xSendBlockTime = ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME;
\r
347 pxSocket->ucSocketOptions = ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT;
\r
348 pxSocket->ucProtocol = ( uint8_t ) xProtocol; /* protocol: UDP or TCP */
\r
350 #if( ipconfigUSE_TCP == 1 )
\r
352 if( xProtocol == FREERTOS_IPPROTO_TCP )
\r
354 /* StreamSize is expressed in number of bytes */
\r
355 /* Round up buffer sizes to nearest multiple of MSS */
\r
356 pxSocket->u.xTCP.usInitMSS = pxSocket->u.xTCP.usCurMSS = ipconfigTCP_MSS;
\r
357 pxSocket->u.xTCP.uxRxStreamSize = ( size_t ) ipconfigTCP_RX_BUFFER_LENGTH;
\r
358 pxSocket->u.xTCP.uxTxStreamSize = ( size_t ) FreeRTOS_round_up( ipconfigTCP_TX_BUFFER_LENGTH, ipconfigTCP_MSS );
\r
359 /* Use half of the buffer size of the TCP windows */
\r
360 #if ( ipconfigUSE_TCP_WIN == 1 )
\r
362 pxSocket->u.xTCP.uxRxWinSize = FreeRTOS_max_uint32( 1UL, ( uint32_t ) ( pxSocket->u.xTCP.uxRxStreamSize / 2 ) / ipconfigTCP_MSS );
\r
363 pxSocket->u.xTCP.uxTxWinSize = FreeRTOS_max_uint32( 1UL, ( uint32_t ) ( pxSocket->u.xTCP.uxTxStreamSize / 2 ) / ipconfigTCP_MSS );
\r
367 pxSocket->u.xTCP.uxRxWinSize = 1u;
\r
368 pxSocket->u.xTCP.uxTxWinSize = 1u;
\r
371 /* The above values are just defaults, and can be overridden by
\r
372 calling FreeRTOS_setsockopt(). No buffers will be allocated until a
\r
373 socket is connected and data is exchanged. */
\r
376 #endif /* ipconfigUSE_TCP == 1 */
\r
379 xReturn = ( Socket_t ) pxSocket;
\r
382 /* Remove compiler warnings in the case the configASSERT() is not defined. */
\r
387 /*-----------------------------------------------------------*/
\r
389 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
391 SocketSet_t FreeRTOS_CreateSocketSet( void )
\r
393 SocketSelect_t *pxSocketSet;
\r
395 pxSocketSet = ( SocketSelect_t * ) pvPortMalloc( sizeof( *pxSocketSet ) );
\r
397 if( pxSocketSet != NULL )
\r
399 memset( pxSocketSet, '\0', sizeof( *pxSocketSet ) );
\r
400 pxSocketSet->xSelectGroup = xEventGroupCreate();
\r
402 if( pxSocketSet->xSelectGroup == NULL )
\r
404 vPortFree( ( void* ) pxSocketSet );
\r
405 pxSocketSet = NULL;
\r
409 return ( SocketSet_t * ) pxSocketSet;
\r
412 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
413 /*-----------------------------------------------------------*/
\r
415 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
417 void FreeRTOS_DeleteSocketSet( SocketSet_t xSocketSet )
\r
419 SocketSelect_t *pxSocketSet = ( SocketSelect_t*) xSocketSet;
\r
421 vEventGroupDelete( pxSocketSet->xSelectGroup );
\r
422 vPortFree( ( void* ) pxSocketSet );
\r
425 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
426 /*-----------------------------------------------------------*/
\r
428 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
430 /* Add a socket to a set */
\r
431 void FreeRTOS_FD_SET( Socket_t xSocket, SocketSet_t xSocketSet, EventBits_t xSelectBits )
\r
433 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
434 SocketSelect_t *pxSocketSet = ( SocketSelect_t * ) xSocketSet;
\r
436 configASSERT( pxSocket != NULL );
\r
437 configASSERT( xSocketSet != NULL );
\r
439 /* Make sure we're not adding bits which are reserved for internal use,
\r
440 such as eSELECT_CALL_IP */
\r
441 pxSocket->xSelectBits |= ( xSelectBits & eSELECT_ALL );
\r
443 if( ( pxSocket->xSelectBits & eSELECT_ALL ) != 0 )
\r
445 /* Adding a socket to a socket set. */
\r
446 pxSocket->pxSocketSet = ( SocketSelect_t * ) xSocketSet;
\r
448 /* Now have the IP-task call vSocketSelect() to see if the set contains
\r
449 any sockets which are 'ready' and set the proper bits.
\r
450 By setting 'bApiCalled = false', vSocketSelect() knows that it was
\r
451 not called from a user API */
\r
452 pxSocketSet->bApiCalled = pdFALSE;
\r
453 prvFindSelectedSocket( pxSocketSet );
\r
457 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
458 /*-----------------------------------------------------------*/
\r
460 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
461 /* Clear select bits for a socket
\r
462 If the mask becomes 0, remove the socket from the set */
\r
463 void FreeRTOS_FD_CLR( Socket_t xSocket, SocketSet_t xSocketSet, EventBits_t xSelectBits )
\r
465 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
467 configASSERT( pxSocket != NULL );
\r
468 configASSERT( xSocketSet != NULL );
\r
470 pxSocket->xSelectBits &= ~( xSelectBits & eSELECT_ALL );
\r
471 if( ( pxSocket->xSelectBits & eSELECT_ALL ) != 0 )
\r
473 pxSocket->pxSocketSet = ( SocketSelect_t *)xSocketSet;
\r
477 /* disconnect it from the socket set */
\r
478 pxSocket->pxSocketSet = ( SocketSelect_t *)NULL;
\r
482 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
483 /*-----------------------------------------------------------*/
\r
486 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
488 /* Test if a socket belongs to a socket-set */
\r
489 EventBits_t FreeRTOS_FD_ISSET( Socket_t xSocket, SocketSet_t xSocketSet )
\r
491 EventBits_t xReturn;
\r
492 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
494 configASSERT( pxSocket != NULL );
\r
495 configASSERT( xSocketSet != NULL );
\r
497 if( xSocketSet == ( SocketSet_t ) pxSocket->pxSocketSet )
\r
499 /* Make sure we're not adding bits which are reserved for internal
\r
501 xReturn = pxSocket->xSocketBits & eSELECT_ALL;
\r
511 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
512 /*-----------------------------------------------------------*/
\r
514 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
516 /* The select() statement: wait for an event to occur on any of the sockets
\r
517 included in a socket set */
\r
518 BaseType_t FreeRTOS_select( SocketSet_t xSocketSet, TickType_t xBlockTimeTicks )
\r
520 TimeOut_t xTimeOut;
\r
521 TickType_t xRemainingTime;
\r
522 SocketSelect_t *pxSocketSet = ( SocketSelect_t*) xSocketSet;
\r
523 BaseType_t xResult;
\r
525 configASSERT( xSocketSet != NULL );
\r
527 /* Only in the first round, check for non-blocking */
\r
528 xRemainingTime = xBlockTimeTicks;
\r
530 /* Fetch the current time */
\r
531 vTaskSetTimeOutState( &xTimeOut );
\r
535 /* Find a socket which might have triggered the bit
\r
536 This function might return immediately or block for a limited time */
\r
537 xResult = ( BaseType_t ) xEventGroupWaitBits( pxSocketSet->xSelectGroup, eSELECT_ALL, pdFALSE, pdFALSE, xRemainingTime );
\r
539 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
541 if( ( xResult & eSELECT_INTR ) != 0u )
\r
543 xEventGroupClearBits( pxSocketSet->xSelectGroup, eSELECT_INTR );
\r
544 FreeRTOS_debug_printf( ( "FreeRTOS_select: interrupted\n" ) );
\r
548 #endif /* ipconfigSUPPORT_SIGNALS */
\r
550 /* Have the IP-task find the socket which had an event */
\r
551 pxSocketSet->bApiCalled = pdTRUE;
\r
552 prvFindSelectedSocket( pxSocketSet );
\r
554 xResult = ( BaseType_t ) xEventGroupGetBits( pxSocketSet->xSelectGroup );
\r
561 /* Has the timeout been reached? */
\r
562 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
\r
571 #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
\r
572 /*-----------------------------------------------------------*/
\r
574 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
576 /* Send a message to the IP-task to have it check all sockets belonging to
\r
578 static FreeRTOS_Socket_t *prvFindSelectedSocket( SocketSelect_t *pxSocketSet )
\r
580 IPStackEvent_t xSelectEvent;
\r
581 FreeRTOS_Socket_t *xReturn;
\r
583 xSelectEvent.eEventType = eSocketSelectEvent;
\r
584 xSelectEvent.pvData = ( void * ) pxSocketSet;
\r
586 /* while the IP-task works on the request, the API will block on
\r
587 'eSELECT_CALL_IP'. So clear it first. */
\r
588 xEventGroupClearBits( pxSocketSet->xSelectGroup, eSELECT_CALL_IP );
\r
590 /* Now send the socket select event */
\r
591 if( xSendEventStructToIPTask( &xSelectEvent, ( TickType_t ) portMAX_DELAY ) == pdFAIL )
\r
593 /* Oops, we failed to wake-up the IP task. No use to wait for it. */
\r
594 FreeRTOS_debug_printf( ( "prvFindSelectedSocket: failed\n" ) );
\r
599 /* As soon as the IP-task is ready, it will set 'eSELECT_CALL_IP' to
\r
600 wakeup the calling API */
\r
601 xEventGroupWaitBits( pxSocketSet->xSelectGroup, eSELECT_CALL_IP, pdTRUE, pdFALSE, portMAX_DELAY );
\r
603 /* Return 'pxSocket' which is set by the IP-task */
\r
604 xReturn = pxSocketSet->pxSocket;
\r
610 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
611 /*-----------------------------------------------------------*/
\r
614 * FreeRTOS_recvfrom: receive data from a bound socket
\r
615 * In this library, the function can only be used with connectionsless sockets
\r
618 int32_t FreeRTOS_recvfrom( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags, struct freertos_sockaddr *pxSourceAddress, socklen_t *pxSourceAddressLength )
\r
620 BaseType_t lPacketCount = 0;
\r
621 NetworkBufferDescriptor_t *pxNetworkBuffer;
\r
622 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
623 TickType_t xRemainingTime = ( TickType_t ) 0; /* Obsolete assignment, but some compilers output a warning if its not done. */
\r
624 BaseType_t xTimed = pdFALSE;
\r
625 TimeOut_t xTimeOut;
\r
627 EventBits_t xEventBits = ( EventBits_t ) 0;
\r
629 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_UDP, pdTRUE ) == pdFALSE )
\r
631 return -pdFREERTOS_ERRNO_EINVAL;
\r
634 lPacketCount = ( BaseType_t ) listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
\r
636 /* The function prototype is designed to maintain the expected Berkeley
\r
637 sockets standard, but this implementation does not use all the parameters. */
\r
638 ( void ) pxSourceAddressLength;
\r
640 while( lPacketCount == 0 )
\r
642 if( xTimed == pdFALSE )
\r
644 /* Check to see if the socket is non blocking on the first
\r
646 xRemainingTime = pxSocket->xReceiveBlockTime;
\r
648 if( xRemainingTime == ( TickType_t ) 0 )
\r
650 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
652 /* Just check for the interrupt flag. */
\r
653 xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_INTR,
\r
654 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, socketDONT_BLOCK );
\r
656 #endif /* ipconfigSUPPORT_SIGNALS */
\r
660 if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
\r
665 /* To ensure this part only executes once. */
\r
668 /* Fetch the current time. */
\r
669 vTaskSetTimeOutState( &xTimeOut );
\r
672 /* Wait for arrival of data. While waiting, the IP-task may set the
\r
673 'eSOCKET_RECEIVE' bit in 'xEventGroup', if it receives data for this
\r
674 socket, thus unblocking this API call. */
\r
675 xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_RECEIVE | eSOCKET_INTR,
\r
676 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
678 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
680 if( ( xEventBits & eSOCKET_INTR ) != 0 )
\r
682 if( ( xEventBits & eSOCKET_RECEIVE ) != 0 )
\r
684 /* Shouldn't have cleared the eSOCKET_RECEIVE flag. */
\r
685 xEventGroupSetBits( pxSocket->xEventGroup, eSOCKET_RECEIVE );
\r
692 ( void ) xEventBits;
\r
694 #endif /* ipconfigSUPPORT_SIGNALS */
\r
696 lPacketCount = ( BaseType_t ) listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
\r
698 if( lPacketCount != 0 )
\r
703 /* Has the timeout been reached ? */
\r
704 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) )
\r
708 } /* while( lPacketCount == 0 ) */
\r
710 if( lPacketCount != 0 )
\r
712 taskENTER_CRITICAL();
\r
714 /* The owner of the list item is the network buffer. */
\r
715 pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
\r
717 if( ( xFlags & FREERTOS_MSG_PEEK ) == 0 )
\r
719 /* Remove the network buffer from the list of buffers waiting to
\r
720 be processed by the socket. */
\r
721 uxListRemove( &( pxNetworkBuffer->xBufferListItem ) );
\r
724 taskEXIT_CRITICAL();
\r
726 /* The returned value is the data length, which may have been capped to
\r
727 the receive buffer size. */
\r
728 lReturn = ( int32_t ) pxNetworkBuffer->xDataLength;
\r
730 if( pxSourceAddress != NULL )
\r
732 pxSourceAddress->sin_port = pxNetworkBuffer->usPort;
\r
733 pxSourceAddress->sin_addr = pxNetworkBuffer->ulIPAddress;
\r
736 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
\r
738 /* The zero copy flag is not set. Truncate the length if it won't
\r
739 fit in the provided buffer. */
\r
740 if( lReturn > ( int32_t ) xBufferLength )
\r
742 iptraceRECVFROM_DISCARDING_BYTES( ( xBufferLength - lReturn ) );
\r
743 lReturn = ( int32_t )xBufferLength;
\r
746 /* Copy the received data into the provided buffer, then release the
\r
748 memcpy( pvBuffer, ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ), ( size_t )lReturn );
\r
750 if( ( xFlags & FREERTOS_MSG_PEEK ) == 0 )
\r
752 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
\r
757 /* The zero copy flag was set. pvBuffer is not a buffer into which
\r
758 the received data can be copied, but a pointer that must be set to
\r
759 point to the buffer in which the received data has already been
\r
761 *( ( void** ) pvBuffer ) = ( void * ) ( &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ) );
\r
765 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
766 else if( ( xEventBits & eSOCKET_INTR ) != 0 )
\r
768 lReturn = -pdFREERTOS_ERRNO_EINTR;
\r
769 iptraceRECVFROM_INTERRUPTED();
\r
771 #endif /* ipconfigSUPPORT_SIGNALS */
\r
774 lReturn = -pdFREERTOS_ERRNO_EWOULDBLOCK;
\r
775 iptraceRECVFROM_TIMEOUT();
\r
780 /*-----------------------------------------------------------*/
\r
782 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
784 NetworkBufferDescriptor_t *pxNetworkBuffer;
\r
785 IPStackEvent_t xStackTxEvent = { eStackTxEvent, NULL };
\r
786 TimeOut_t xTimeOut;
\r
787 TickType_t xTicksToWait;
\r
788 int32_t lReturn = 0;
\r
789 FreeRTOS_Socket_t *pxSocket;
\r
791 pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
793 /* The function prototype is designed to maintain the expected Berkeley
\r
794 sockets standard, but this implementation does not use all the
\r
796 ( void ) xDestinationAddressLength;
\r
797 configASSERT( pvBuffer );
\r
799 if( xTotalDataLength <= ( size_t ) ipMAX_UDP_PAYLOAD_LENGTH )
\r
801 /* If the socket is not already bound to an address, bind it now.
\r
802 Passing NULL as the address parameter tells FreeRTOS_bind() to select
\r
803 the address to bind to. */
\r
804 if( ( socketSOCKET_IS_BOUND( pxSocket ) != pdFALSE ) ||
\r
805 ( FreeRTOS_bind( xSocket, NULL, 0u ) == 0 ) )
\r
807 xTicksToWait = pxSocket->xSendBlockTime;
\r
809 #if( ipconfigUSE_CALLBACKS != 0 )
\r
811 if( xIsCallingFromIPTask() != pdFALSE )
\r
813 /* If this send function is called from within a call-back
\r
814 handler it may not block, otherwise chances would be big to
\r
815 get a deadlock: the IP-task waiting for itself. */
\r
816 xTicksToWait = ( TickType_t )0;
\r
819 #endif /* ipconfigUSE_CALLBACKS */
\r
821 if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
\r
823 xTicksToWait = ( TickType_t ) 0;
\r
826 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
\r
828 /* Zero copy is not set, so obtain a network buffer into
\r
829 which the payload will be copied. */
\r
830 vTaskSetTimeOutState( &xTimeOut );
\r
832 /* Block until a buffer becomes available, or until a
\r
833 timeout has been reached */
\r
834 pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( xTotalDataLength + sizeof( UDPPacket_t ), xTicksToWait );
\r
836 if( pxNetworkBuffer != NULL )
\r
838 memcpy( ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ), ( void * ) pvBuffer, xTotalDataLength );
\r
840 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdTRUE )
\r
842 /* The entire block time has been used up. */
\r
843 xTicksToWait = ( TickType_t ) 0;
\r
849 /* When zero copy is used, pvBuffer is a pointer to the
\r
850 payload of a buffer that has already been obtained from the
\r
851 stack. Obtain the network buffer pointer from the buffer. */
\r
852 pxNetworkBuffer = pxUDPPayloadBuffer_to_NetworkBuffer( (void*)pvBuffer );
\r
855 if( pxNetworkBuffer != NULL )
\r
857 pxNetworkBuffer->xDataLength = xTotalDataLength;
\r
858 pxNetworkBuffer->usPort = pxDestinationAddress->sin_port;
\r
859 pxNetworkBuffer->usBoundPort = ( uint16_t ) socketGET_SOCKET_PORT( pxSocket );
\r
860 pxNetworkBuffer->ulIPAddress = pxDestinationAddress->sin_addr;
\r
862 /* The socket options are passed to the IP layer in the
\r
863 space that will eventually get used by the Ethernet header. */
\r
864 pxNetworkBuffer->pucEthernetBuffer[ ipSOCKET_OPTIONS_OFFSET ] = pxSocket->ucSocketOptions;
\r
866 /* Tell the networking task that the packet needs sending. */
\r
867 xStackTxEvent.pvData = pxNetworkBuffer;
\r
869 /* Ask the IP-task to send this packet */
\r
870 if( xSendEventStructToIPTask( &xStackTxEvent, xTicksToWait ) == pdPASS )
\r
872 /* The packet was successfully sent to the IP task. */
\r
873 lReturn = ( int32_t ) xTotalDataLength;
\r
874 #if( ipconfigUSE_CALLBACKS == 1 )
\r
876 if( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xUDP.pxHandleSent ) )
\r
878 pxSocket->u.xUDP.pxHandleSent( (Socket_t *)pxSocket, xTotalDataLength );
\r
881 #endif /* ipconfigUSE_CALLBACKS */
\r
885 /* If the buffer was allocated in this function, release
\r
887 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
\r
889 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
\r
891 iptraceSTACK_TX_EVENT_LOST( ipSTACK_TX_EVENT );
\r
896 /* If errno was available, errno would be set to
\r
897 FREERTOS_ENOPKTS. As it is, the function must return the
\r
898 number of transmitted bytes, so the calling function knows
\r
899 how much data was actually sent. */
\r
900 iptraceNO_BUFFER_FOR_SENDTO();
\r
905 iptraceSENDTO_SOCKET_NOT_BOUND();
\r
910 /* The data is longer than the available buffer space. */
\r
911 iptraceSENDTO_DATA_TOO_LONG();
\r
916 /*-----------------------------------------------------------*/
\r
919 * FreeRTOS_bind() : binds a sockt to a local port number. If port 0 is
\r
920 * provided, a system provided port number will be assigned. This function can
\r
921 * be used for both UDP and TCP sockets. The actual binding will be performed
\r
922 * by the IP-task to avoid mutual access to the bound-socket-lists
\r
923 * (xBoundUDPSocketsList or xBoundTCPSocketsList).
\r
925 BaseType_t FreeRTOS_bind( Socket_t xSocket, struct freertos_sockaddr * pxAddress, socklen_t xAddressLength )
\r
927 IPStackEvent_t xBindEvent;
\r
928 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
929 BaseType_t xReturn = 0;
\r
931 ( void ) xAddressLength;
\r
933 if( ( pxSocket == NULL ) || ( pxSocket == FREERTOS_INVALID_SOCKET ) )
\r
935 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
937 /* Once a socket is bound to a port, it can not be bound to a different
\r
939 else if( socketSOCKET_IS_BOUND( pxSocket) != pdFALSE )
\r
941 /* The socket is already bound. */
\r
942 FreeRTOS_debug_printf( ( "vSocketBind: Socket already bound to %d\n", pxSocket->usLocalPort ) );
\r
943 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
947 /* Prepare a messages to the IP-task in order to perform the binding.
\r
948 The desired port number will be passed in usLocalPort. */
\r
949 xBindEvent.eEventType = eSocketBindEvent;
\r
950 xBindEvent.pvData = ( void * ) xSocket;
\r
951 if( pxAddress != NULL )
\r
953 pxSocket->usLocalPort = FreeRTOS_ntohs( pxAddress->sin_port );
\r
957 /* Caller wants to bind to a random port number. */
\r
958 pxSocket->usLocalPort = 0u;
\r
961 /* portMAX_DELAY is used as a the time-out parameter, as binding *must*
\r
962 succeed before the socket can be used. _RB_ The use of an infinite
\r
963 block time needs be changed as it could result in the task hanging. */
\r
964 if( xSendEventStructToIPTask( &xBindEvent, ( TickType_t ) portMAX_DELAY ) == pdFAIL )
\r
966 /* Failed to wake-up the IP-task, no use to wait for it */
\r
967 FreeRTOS_debug_printf( ( "FreeRTOS_bind: send event failed\n" ) );
\r
968 xReturn = -pdFREERTOS_ERRNO_ECANCELED;
\r
972 /* The IP-task will set the 'eSOCKET_BOUND' bit when it has done its
\r
974 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_BOUND, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, portMAX_DELAY );
\r
975 if( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE )
\r
977 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
986 * vSocketBind(): internal version of bind() that should not be called directly.
\r
987 * 'xInternal' is used for TCP sockets only: it allows to have several
\r
988 * (connected) child sockets bound to the same server port.
\r
990 BaseType_t vSocketBind( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr * pxAddress, size_t uxAddressLength, BaseType_t xInternal )
\r
992 BaseType_t xReturn = 0; /* In Berkeley sockets, 0 means pass for bind(). */
\r
993 List_t *pxSocketList;
\r
994 #if( ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 )
\r
995 struct freertos_sockaddr xAddress;
\r
996 #endif /* ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND */
\r
998 #if( ipconfigUSE_TCP == 1 )
\r
999 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1001 pxSocketList = &xBoundTCPSocketsList;
\r
1004 #endif /* ipconfigUSE_TCP == 1 */
\r
1006 pxSocketList = &xBoundUDPSocketsList;
\r
1009 /* The function prototype is designed to maintain the expected Berkeley
\r
1010 sockets standard, but this implementation does not use all the parameters. */
\r
1011 ( void ) uxAddressLength;
\r
1013 configASSERT( pxSocket );
\r
1014 configASSERT( pxSocket != FREERTOS_INVALID_SOCKET );
\r
1016 #if( ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 )
\r
1018 /* pxAddress will be NULL if sendto() was called on a socket without the
\r
1019 socket being bound to an address. In this case, automatically allocate
\r
1020 an address to the socket. There is a very tiny chance that the allocated
\r
1021 port will already be in use - if that is the case, then the check below
\r
1022 [pxListFindListItemWithValue()] will result in an error being returned. */
\r
1023 if( pxAddress == NULL )
\r
1025 pxAddress = &xAddress;
\r
1026 /* For now, put it to zero, will be assigned later */
\r
1027 pxAddress->sin_port = 0u;
\r
1030 #endif /* ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 */
\r
1032 /* Sockets must be bound before calling FreeRTOS_sendto() if
\r
1033 ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is not set to 1. */
\r
1034 configASSERT( pxAddress );
\r
1036 if( pxAddress != NULL )
\r
1038 if( pxAddress->sin_port == 0u )
\r
1040 pxAddress->sin_port = prvGetPrivatePortNumber( ( BaseType_t ) pxSocket->ucProtocol );
\r
1043 /* If vSocketBind() is called from the API FreeRTOS_bind() it has been
\r
1044 confirmed that the socket was not yet bound to a port. If it is called
\r
1045 from the IP-task, no such check is necessary. */
\r
1047 /* Check to ensure the port is not already in use. If the bind is
\r
1048 called internally, a port MAY be used by more than one socket. */
\r
1049 if( ( ( xInternal == pdFALSE ) || ( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP ) ) &&
\r
1050 ( pxListFindListItemWithValue( pxSocketList, ( TickType_t ) pxAddress->sin_port ) != NULL ) )
\r
1052 FreeRTOS_debug_printf( ( "vSocketBind: %sP port %d in use\n",
\r
1053 pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP ? "TC" : "UD",
\r
1054 FreeRTOS_ntohs( pxAddress->sin_port ) ) );
\r
1055 xReturn = -pdFREERTOS_ERRNO_EADDRINUSE;
\r
1059 /* Allocate the port number to the socket.
\r
1060 This macro will set 'xBoundSocketListItem->xItemValue' */
\r
1061 socketSET_SOCKET_PORT( pxSocket, pxAddress->sin_port );
\r
1063 /* And also store it in a socket field 'usLocalPort' in host-byte-order,
\r
1064 mostly used for logging and debugging purposes */
\r
1065 pxSocket->usLocalPort = FreeRTOS_ntohs( pxAddress->sin_port );
\r
1067 /* Add the socket to the list of bound ports. */
\r
1069 /* If the network driver can iterate through 'xBoundUDPSocketsList',
\r
1070 by calling xPortHasUDPSocket() then the IP-task must temporarily
\r
1071 suspend the scheduler to keep the list in a consistent state. */
\r
1072 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1074 vTaskSuspendAll();
\r
1076 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1078 /* Add the socket to 'xBoundUDPSocketsList' or 'xBoundTCPSocketsList' */
\r
1079 vListInsertEnd( pxSocketList, &( pxSocket->xBoundSocketListItem ) );
\r
1081 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1085 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1091 xReturn = -pdFREERTOS_ERRNO_EADDRNOTAVAIL;
\r
1092 FreeRTOS_debug_printf( ( "vSocketBind: Socket no addr\n" ) );
\r
1095 if( xReturn != 0 )
\r
1097 iptraceBIND_FAILED( xSocket, ( FreeRTOS_ntohs( pxAddress->sin_port ) ) );
\r
1102 /*-----------------------------------------------------------*/
\r
1105 * Close a socket and free the allocated space
\r
1106 * In case of a TCP socket: the connection will not be closed automatically
\r
1107 * Subsequent messages for the closed socket will be responded to with a RST
\r
1108 * The IP-task will actually close the socket, after receiving a 'eSocketCloseEvent' message
\r
1110 BaseType_t FreeRTOS_closesocket( Socket_t xSocket )
\r
1112 BaseType_t xResult;
\r
1113 #if( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 )
\r
1114 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * )xSocket;
\r
1116 IPStackEvent_t xCloseEvent;
\r
1117 xCloseEvent.eEventType = eSocketCloseEvent;
\r
1118 xCloseEvent.pvData = ( void * ) xSocket;
\r
1120 if( ( xSocket == NULL ) || ( xSocket == FREERTOS_INVALID_SOCKET ) )
\r
1126 #if( ( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 ) )
\r
1128 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1130 /* Make sure that IP-task won't call the user callback's anymore */
\r
1131 pxSocket->u.xTCP.pxHandleConnected = NULL;
\r
1132 pxSocket->u.xTCP.pxHandleReceive = NULL;
\r
1133 pxSocket->u.xTCP.pxHandleSent = NULL;
\r
1136 #endif /* ( ( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 ) ) */
\r
1138 /* Let the IP task close the socket to keep it synchronised with the
\r
1139 packet handling. */
\r
1141 /* Note when changing the time-out value below, it must be checked who is calling
\r
1142 this function. If it is called by the IP-task, a deadlock could occur.
\r
1143 The IP-task would only call it in case of a user call-back */
\r
1144 if( xSendEventStructToIPTask( &xCloseEvent, ( TickType_t ) 0 ) == pdFAIL )
\r
1146 FreeRTOS_debug_printf( ( "FreeRTOS_closesocket: failed\n" ) );
\r
1158 /* This is the internal version of FreeRTOS_closesocket()
\r
1159 * It will be called by the IPtask only to avoid problems with synchronicity
\r
1161 void *vSocketClose( FreeRTOS_Socket_t *pxSocket )
\r
1163 NetworkBufferDescriptor_t *pxNetworkBuffer;
\r
1165 #if( ipconfigUSE_TCP == 1 )
\r
1167 /* For TCP: clean up a little more. */
\r
1168 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1170 #if( ipconfigUSE_TCP_WIN == 1 )
\r
1172 if( pxSocket->u.xTCP.pxAckMessage != NULL )
\r
1174 vReleaseNetworkBufferAndDescriptor( pxSocket->u.xTCP.pxAckMessage );
\r
1176 /* Free the resources which were claimed by the tcpWin member */
\r
1177 vTCPWindowDestroy( &pxSocket->u.xTCP.xTCPWindow );
\r
1179 #endif /* ipconfigUSE_TCP_WIN */
\r
1181 /* Free the input and output streams */
\r
1182 if( pxSocket->u.xTCP.rxStream != NULL )
\r
1184 vPortFreeLarge( pxSocket->u.xTCP.rxStream );
\r
1187 if( pxSocket->u.xTCP.txStream != NULL )
\r
1189 vPortFreeLarge( pxSocket->u.xTCP.txStream );
\r
1192 /* In case this is a child socket, make sure the child-count of the
\r
1193 parent socket is decreased. */
\r
1194 prvTCPSetSocketCount( pxSocket );
\r
1197 #endif /* ipconfigUSE_TCP == 1 */
\r
1199 /* Socket must be unbound first, to ensure no more packets are queued on
\r
1201 if( socketSOCKET_IS_BOUND( pxSocket ) != pdFALSE )
\r
1203 /* If the network driver can iterate through 'xBoundUDPSocketsList',
\r
1204 by calling xPortHasUDPSocket(), then the IP-task must temporarily
\r
1205 suspend the scheduler to keep the list in a consistent state. */
\r
1206 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1208 vTaskSuspendAll();
\r
1210 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1212 uxListRemove( &( pxSocket->xBoundSocketListItem ) );
\r
1214 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1218 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1221 /* Now the socket is not bound the list of waiting packets can be
\r
1223 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_UDP )
\r
1225 while( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) > 0U )
\r
1227 pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
\r
1228 uxListRemove( &( pxNetworkBuffer->xBufferListItem ) );
\r
1229 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
\r
1233 if( pxSocket->xEventGroup )
\r
1235 vEventGroupDelete( pxSocket->xEventGroup );
\r
1238 #if( ipconfigUSE_TCP == 1 ) && ( ipconfigHAS_DEBUG_PRINTF != 0 )
\r
1240 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1242 FreeRTOS_debug_printf( ( "FreeRTOS_closesocket[%u to %lxip:%u]: buffers %lu socks %lu\n",
\r
1243 pxSocket->usLocalPort,
\r
1244 pxSocket->u.xTCP.ulRemoteIP,
\r
1245 pxSocket->u.xTCP.usRemotePort,
\r
1246 uxGetNumberOfFreeNetworkBuffers(),
\r
1247 listCURRENT_LIST_LENGTH( &xBoundTCPSocketsList ) ) );
\r
1250 #endif /* ( ipconfigUSE_TCP == 1 ) && ( ipconfigHAS_DEBUG_PRINTF != 0 ) */
\r
1252 /* Anf finally, after all resources have been freed, free the socket space */
\r
1253 vPortFreeSocket( pxSocket );
\r
1258 /*-----------------------------------------------------------*/
\r
1260 #if ipconfigUSE_TCP == 1
\r
1263 * When a child socket gets closed, make sure to update the child-count of the
\r
1264 * parent. When a listening parent socket is closed, make sure no child-sockets
\r
1265 * keep a pointer to it.
\r
1267 static void prvTCPSetSocketCount( FreeRTOS_Socket_t *pxSocketToDelete )
\r
1269 const ListItem_t *pxIterator;
\r
1270 const MiniListItem_t *pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );
\r
1271 FreeRTOS_Socket_t *pxOtherSocket;
\r
1272 uint16_t usLocalPort = pxSocketToDelete->usLocalPort;
\r
1274 for( pxIterator = ( const ListItem_t * ) listGET_NEXT( pxEnd );
\r
1275 pxIterator != ( const ListItem_t * ) pxEnd;
\r
1276 pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
1278 pxOtherSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
\r
1279 if( ( pxOtherSocket->u.xTCP.ucTCPState == eTCP_LISTEN ) &&
\r
1280 ( pxOtherSocket->usLocalPort == usLocalPort ) &&
\r
1281 ( pxOtherSocket->u.xTCP.usChildCount ) )
\r
1283 pxOtherSocket->u.xTCP.usChildCount--;
\r
1284 FreeRTOS_debug_printf( ( "Lost: Socket %u now has %u / %u child%s\n",
\r
1285 pxOtherSocket->usLocalPort,
\r
1286 pxOtherSocket->u.xTCP.usChildCount,
\r
1287 pxOtherSocket->u.xTCP.usBacklog,
\r
1288 pxOtherSocket->u.xTCP.usChildCount == 1u ? "" : "ren" ) );
\r
1294 #endif /* ipconfigUSE_TCP == 1 */
\r
1296 /*-----------------------------------------------------------*/
\r
1298 BaseType_t FreeRTOS_setsockopt( Socket_t xSocket, int32_t lLevel, int32_t lOptionName, const void *pvOptionValue, size_t xOptionLength )
\r
1300 /* The standard Berkeley function returns 0 for success. */
\r
1301 BaseType_t xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
1302 BaseType_t lOptionValue;
\r
1303 FreeRTOS_Socket_t *pxSocket;
\r
1305 pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
1307 /* The function prototype is designed to maintain the expected Berkeley
\r
1308 sockets standard, but this implementation does not use all the parameters. */
\r
1310 ( void ) xOptionLength;
\r
1312 configASSERT( xSocket );
\r
1314 switch( lOptionName )
\r
1316 case FREERTOS_SO_RCVTIMEO :
\r
1317 /* Receive time out. */
\r
1318 pxSocket->xReceiveBlockTime = *( ( TickType_t * ) pvOptionValue );
\r
1322 case FREERTOS_SO_SNDTIMEO :
\r
1323 pxSocket->xSendBlockTime = *( ( TickType_t * ) pvOptionValue );
\r
1324 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_UDP )
\r
1326 /* The send time out is capped for the reason stated in the
\r
1327 comments where ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS is defined
\r
1328 in FreeRTOSIPConfig.h (assuming an official configuration file
\r
1330 if( pxSocket->xSendBlockTime > ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS )
\r
1332 pxSocket->xSendBlockTime = ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS;
\r
1337 /* For TCP socket, it isn't necessary to limit the blocking time
\r
1338 because the FreeRTOS_send() function does not wait for a network
\r
1339 buffer to become available. */
\r
1343 #if( ipconfigUDP_MAX_RX_PACKETS > 0 )
\r
1344 case FREERTOS_SO_UDP_MAX_RX_PACKETS:
\r
1345 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_UDP )
\r
1347 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1349 pxSocket->u.xUDP.uxMaxPackets = *( ( UBaseType_t * ) pvOptionValue );
\r
1352 #endif /* ipconfigUDP_MAX_RX_PACKETS */
\r
1354 case FREERTOS_SO_UDPCKSUM_OUT :
\r
1355 /* Turn calculating of the UDP checksum on/off for this socket. */
\r
1356 lOptionValue = ( BaseType_t ) pvOptionValue;
\r
1358 if( lOptionValue == 0 )
\r
1360 pxSocket->ucSocketOptions &= ( uint8_t ) ~FREERTOS_SO_UDPCKSUM_OUT;
\r
1364 pxSocket->ucSocketOptions |= ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT;
\r
1369 #if( ipconfigUSE_CALLBACKS == 1 )
\r
1370 #if( ipconfigUSE_TCP == 1 )
\r
1371 case FREERTOS_SO_TCP_CONN_HANDLER: /* Set a callback for (dis)connection events */
\r
1372 case FREERTOS_SO_TCP_RECV_HANDLER: /* Install a callback for receiving TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
\r
1373 case FREERTOS_SO_TCP_SENT_HANDLER: /* Install a callback for sending TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
\r
1374 #endif /* ipconfigUSE_TCP */
\r
1375 case FREERTOS_SO_UDP_RECV_HANDLER: /* Install a callback for receiving UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
\r
1376 case FREERTOS_SO_UDP_SENT_HANDLER: /* Install a callback for sending UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
\r
1378 #if( ipconfigUSE_TCP == 1 )
\r
1380 UBaseType_t uxProtocol;
\r
1381 if( ( lOptionName == FREERTOS_SO_UDP_RECV_HANDLER ) ||
\r
1382 ( lOptionName == FREERTOS_SO_UDP_SENT_HANDLER ) )
\r
1384 uxProtocol = ( UBaseType_t ) FREERTOS_IPPROTO_UDP;
\r
1388 uxProtocol = ( UBaseType_t ) FREERTOS_IPPROTO_TCP;
\r
1391 if( pxSocket->ucProtocol != ( uint8_t ) uxProtocol )
\r
1393 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1398 /* No need to check if the socket has the right
\r
1399 protocol, because only UDP socket can be created. */
\r
1401 #endif /* ipconfigUSE_TCP */
\r
1403 switch( lOptionName )
\r
1405 #if ipconfigUSE_TCP == 1
\r
1406 case FREERTOS_SO_TCP_CONN_HANDLER:
\r
1407 pxSocket->u.xTCP.pxHandleConnected = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPConnected;
\r
1409 case FREERTOS_SO_TCP_RECV_HANDLER:
\r
1410 pxSocket->u.xTCP.pxHandleReceive = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPReceive;
\r
1412 case FREERTOS_SO_TCP_SENT_HANDLER:
\r
1413 pxSocket->u.xTCP.pxHandleSent = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPSent;
\r
1415 #endif /* ipconfigUSE_TCP */
\r
1416 case FREERTOS_SO_UDP_RECV_HANDLER:
\r
1417 pxSocket->u.xUDP.pxHandleReceive = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnUDPReceive;
\r
1419 case FREERTOS_SO_UDP_SENT_HANDLER:
\r
1420 pxSocket->u.xUDP.pxHandleSent = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnUDPSent;
\r
1429 #endif /* ipconfigUSE_CALLBACKS */
\r
1431 #if( ipconfigUSE_TCP != 0 )
\r
1432 #if( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 )
\r
1433 /* Each socket has a semaphore on which the using task normally
\r
1435 case FREERTOS_SO_SET_SEMAPHORE:
\r
1437 pxSocket->pxUserSemaphore = *( ( SemaphoreHandle_t * ) pvOptionValue );
\r
1441 #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
\r
1443 #if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK != 0 )
\r
1444 case FREERTOS_SO_WAKEUP_CALLBACK:
\r
1446 /* Each socket can have a callback function that is executed
\r
1447 when there is an event the socket's owner might want to
\r
1449 pxSocket->pxUserWakeCallback = ( SocketWakeupCallback_t ) pvOptionValue;
\r
1453 #endif /* ipconfigSOCKET_HAS_USER_WAKE_CALLBACK */
\r
1455 case FREERTOS_SO_SNDBUF: /* Set the size of the send buffer, in units of MSS (TCP only) */
\r
1456 case FREERTOS_SO_RCVBUF: /* Set the size of the receive buffer, in units of MSS (TCP only) */
\r
1458 uint32_t ulNewValue;
\r
1460 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1462 FreeRTOS_debug_printf( ( "Set SO_%sBUF: wrong socket type\n",
\r
1463 ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );
\r
1464 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1467 if( ( ( lOptionName == FREERTOS_SO_SNDBUF ) && ( pxSocket->u.xTCP.txStream != NULL ) ) ||
\r
1468 ( ( lOptionName == FREERTOS_SO_RCVBUF ) && ( pxSocket->u.xTCP.rxStream != NULL ) ) )
\r
1470 FreeRTOS_debug_printf( ( "Set SO_%sBUF: buffer already created\n",
\r
1471 ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );
\r
1472 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1475 ulNewValue = *( ( uint32_t * ) pvOptionValue );
\r
1477 if( lOptionName == FREERTOS_SO_SNDBUF )
\r
1479 /* Round up to nearest MSS size */
\r
1480 ulNewValue = FreeRTOS_round_up( ulNewValue, ( uint32_t ) pxSocket->u.xTCP.usInitMSS );
\r
1481 pxSocket->u.xTCP.uxTxStreamSize = ulNewValue;
\r
1485 pxSocket->u.xTCP.uxRxStreamSize = ulNewValue;
\r
1491 case FREERTOS_SO_WIN_PROPERTIES: /* Set all buffer and window properties in one call, parameter is pointer to WinProperties_t */
\r
1493 WinProperties_t* pxProps;
\r
1495 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1497 FreeRTOS_debug_printf( ( "Set SO_WIN_PROP: wrong socket type\n" ) );
\r
1498 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1501 if( ( pxSocket->u.xTCP.txStream != NULL ) || ( pxSocket->u.xTCP.rxStream != NULL ) )
\r
1503 FreeRTOS_debug_printf( ( "Set SO_WIN_PROP: buffer already created\n" ) );
\r
1504 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1507 pxProps = ( ( WinProperties_t * ) pvOptionValue );
\r
1508 FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDBUF, &( pxProps->lTxBufSize ), sizeof( pxProps->lTxBufSize ) );
\r
1509 FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVBUF, &( pxProps->lRxBufSize ), sizeof( pxProps->lRxBufSize ) );
\r
1510 #if( ipconfigUSE_TCP_WIN == 1 )
\r
1512 pxSocket->u.xTCP.uxRxWinSize = ( uint32_t )pxProps->lRxWinSize; /* Fixed value: size of the TCP reception window */
\r
1513 pxSocket->u.xTCP.uxTxWinSize = ( uint32_t )pxProps->lTxWinSize; /* Fixed value: size of the TCP transmit window */
\r
1517 pxSocket->u.xTCP.uxRxWinSize = 1u;
\r
1518 pxSocket->u.xTCP.uxTxWinSize = 1u;
\r
1522 /* In case the socket has already initialised its tcpWin,
\r
1523 adapt the window size parameters */
\r
1524 if( pxSocket->u.xTCP.xTCPWindow.u.bits.bHasInit != pdFALSE_UNSIGNED )
\r
1526 pxSocket->u.xTCP.xTCPWindow.xSize.ulRxWindowLength = pxSocket->u.xTCP.uxRxWinSize * pxSocket->u.xTCP.usInitMSS;
\r
1527 pxSocket->u.xTCP.xTCPWindow.xSize.ulRxWindowLength = pxSocket->u.xTCP.uxTxWinSize * pxSocket->u.xTCP.usInitMSS;
\r
1534 case FREERTOS_SO_REUSE_LISTEN_SOCKET: /* If true, the server-socket will turn into a connected socket */
\r
1536 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1538 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1540 if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
\r
1542 pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE_UNSIGNED;
\r
1546 pxSocket->u.xTCP.bits.bReuseSocket = pdFALSE_UNSIGNED;
\r
1552 case FREERTOS_SO_CLOSE_AFTER_SEND: /* As soon as the last byte has been transmitted, finalise the connection */
\r
1554 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1556 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1559 if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
\r
1561 pxSocket->u.xTCP.bits.bCloseAfterSend = pdTRUE_UNSIGNED;
\r
1565 pxSocket->u.xTCP.bits.bCloseAfterSend = pdFALSE_UNSIGNED;
\r
1571 case FREERTOS_SO_SET_FULL_SIZE: /* Refuse to send packets smaller than MSS */
\r
1573 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1575 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1578 if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
\r
1580 pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdTRUE_UNSIGNED;
\r
1584 pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdFALSE_UNSIGNED;
\r
1587 if( ( pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize == pdFALSE_UNSIGNED ) &&
\r
1588 ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) &&
\r
1589 ( FreeRTOS_outstanding( pxSocket ) != 0 ) )
\r
1591 pxSocket->u.xTCP.usTimeout = 1u; /* to set/clear bSendFullSize */
\r
1592 xSendEventToIPTask( eTCPTimerEvent );
\r
1598 case FREERTOS_SO_STOP_RX: /* Refuse to receive more packts */
\r
1600 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1602 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1605 if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
\r
1607 pxSocket->u.xTCP.bits.bRxStopped = pdTRUE_UNSIGNED;
\r
1611 pxSocket->u.xTCP.bits.bRxStopped = pdFALSE_UNSIGNED;
\r
1614 pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
\r
1615 pxSocket->u.xTCP.usTimeout = 1u; /* to set/clear bRxStopped */
\r
1616 xSendEventToIPTask( eTCPTimerEvent );
\r
1621 #endif /* ipconfigUSE_TCP == 1 */
\r
1624 /* No other options are handled. */
\r
1625 xReturn = -pdFREERTOS_ERRNO_ENOPROTOOPT;
\r
1632 /*-----------------------------------------------------------*/
\r
1634 /* Get a free private ('anonymous') port number */
\r
1635 static uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol )
\r
1637 uint16_t usResult;
\r
1638 BaseType_t xIndex;
\r
1639 const List_t *pxList;
\r
1641 #if ipconfigUSE_TCP == 1
\r
1642 if( xProtocol == ( BaseType_t ) FREERTOS_IPPROTO_TCP )
\r
1644 xIndex = socketNEXT_TCP_PORT_NUMBER_INDEX;
\r
1645 pxList = &xBoundTCPSocketsList;
\r
1650 xIndex = socketNEXT_UDP_PORT_NUMBER_INDEX;
\r
1651 pxList = &xBoundUDPSocketsList;
\r
1654 /* Avoid compiler warnings if ipconfigUSE_TCP is not defined. */
\r
1655 ( void ) xProtocol;
\r
1657 /* Assign the next port in the range. Has it overflowed? */
\r
1658 /*_RB_ This needs to be randomised rather than sequential. */
\r
1659 /* _HT_ Agreed, although many OS's use sequential port numbers, see
\r
1660 https://www.cymru.com/jtk/misc/ephemeralports.html */
\r
1663 ++( usNextPortToUse[ xIndex ] );
\r
1665 if( usNextPortToUse[ xIndex ] >= socketAUTO_PORT_ALLOCATION_MAX_NUMBER )
\r
1667 /* Don't go right back to the start of the dynamic/private port
\r
1668 range numbers as any persistent sockets are likely to have been
\r
1669 create first so the early port numbers may still be in use. */
\r
1670 usNextPortToUse[ xIndex ] = socketAUTO_PORT_ALLOCATION_RESET_NUMBER;
\r
1673 usResult = FreeRTOS_htons( usNextPortToUse[ xIndex ] );
\r
1675 if( pxListFindListItemWithValue( pxList, ( TickType_t ) usResult ) == NULL )
\r
1682 /*-----------------------------------------------------------*/
\r
1684 /* pxListFindListItemWithValue: find a list item in a bound socket list
\r
1685 'xWantedItemValue' refers to a port number */
\r
1686 static const ListItem_t * pxListFindListItemWithValue( const List_t *pxList, TickType_t xWantedItemValue )
\r
1688 const ListItem_t * pxResult = NULL;
\r
1690 if( ( xIPIsNetworkTaskReady() != pdFALSE ) && ( pxList != NULL ) )
\r
1692 const ListItem_t *pxIterator;
\r
1693 const MiniListItem_t *pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( pxList );
\r
1694 for( pxIterator = ( const ListItem_t * ) listGET_NEXT( pxEnd );
\r
1695 pxIterator != ( const ListItem_t * ) pxEnd;
\r
1696 pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
1698 if( listGET_LIST_ITEM_VALUE( pxIterator ) == xWantedItemValue )
\r
1700 pxResult = pxIterator;
\r
1709 /*-----------------------------------------------------------*/
\r
1711 FreeRTOS_Socket_t *pxUDPSocketLookup( UBaseType_t uxLocalPort )
\r
1713 const ListItem_t *pxListItem;
\r
1714 FreeRTOS_Socket_t *pxSocket = NULL;
\r
1716 /* Looking up a socket is quite simple, find a match with the local port.
\r
1718 See if there is a list item associated with the port number on the
\r
1719 list of bound sockets. */
\r
1720 pxListItem = pxListFindListItemWithValue( &xBoundUDPSocketsList, ( TickType_t ) uxLocalPort );
\r
1722 if( pxListItem != NULL )
\r
1724 /* The owner of the list item is the socket itself. */
\r
1725 pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxListItem );
\r
1726 configASSERT( pxSocket != NULL );
\r
1731 /*-----------------------------------------------------------*/
\r
1733 #if ipconfigINCLUDE_FULL_INET_ADDR == 1
\r
1735 uint32_t FreeRTOS_inet_addr( const char * pcIPAddress )
\r
1737 const uint32_t ulDecimalBase = 10u;
\r
1738 uint8_t ucOctet[ socketMAX_IP_ADDRESS_OCTETS ];
\r
1739 const char *pcPointerOnEntering;
\r
1740 uint32_t ulReturn = 0UL, ulValue;
\r
1741 UBaseType_t uxOctetNumber;
\r
1742 BaseType_t xResult = pdPASS;
\r
1744 for( uxOctetNumber = 0u; uxOctetNumber < socketMAX_IP_ADDRESS_OCTETS; uxOctetNumber++ )
\r
1747 pcPointerOnEntering = pcIPAddress;
\r
1749 while( ( *pcIPAddress >= '0' ) && ( *pcIPAddress <= '9' ) )
\r
1751 /* Move previous read characters into the next decimal
\r
1753 ulValue *= ulDecimalBase;
\r
1755 /* Add the binary value of the ascii character. */
\r
1756 ulValue += ( ( uint32_t ) ( *pcIPAddress ) - ( uint32_t ) '0' );
\r
1758 /* Move to next character in the string. */
\r
1762 /* Check characters were read. */
\r
1763 if( pcIPAddress == pcPointerOnEntering )
\r
1768 /* Check the value fits in an 8-bit number. */
\r
1769 if( ulValue > 0xffUL )
\r
1775 ucOctet[ uxOctetNumber ] = ( uint8_t ) ulValue;
\r
1777 /* Check the next character is as expected. */
\r
1778 if( uxOctetNumber < ( socketMAX_IP_ADDRESS_OCTETS - 1u ) )
\r
1780 if( *pcIPAddress != '.' )
\r
1786 /* Move past the dot. */
\r
1792 if( xResult == pdFAIL )
\r
1794 /* No point going on. */
\r
1799 if( *pcIPAddress != ( char ) 0 )
\r
1801 /* Expected the end of the string. */
\r
1805 if( uxOctetNumber != socketMAX_IP_ADDRESS_OCTETS )
\r
1807 /* Didn't read enough octets. */
\r
1811 if( xResult == pdPASS )
\r
1813 ulReturn = FreeRTOS_inet_addr_quick( ucOctet[ 0 ], ucOctet[ 1 ], ucOctet[ 2 ], ucOctet[ 3 ] );
\r
1819 #endif /* ipconfigINCLUDE_FULL_INET_ADDR */
\r
1821 /*-----------------------------------------------------------*/
\r
1823 /* Function to get the local address and IP port */
\r
1824 size_t FreeRTOS_GetLocalAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress )
\r
1826 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
1828 /* IP address of local machine. */
\r
1829 pxAddress->sin_addr = *ipLOCAL_IP_ADDRESS_POINTER;
\r
1831 /* Local port on this machine. */
\r
1832 pxAddress->sin_port = FreeRTOS_htons( pxSocket->usLocalPort );
\r
1834 return sizeof( *pxAddress );
\r
1837 /*-----------------------------------------------------------*/
\r
1839 void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
\r
1841 /* _HT_ must work this out, now vSocketWakeUpUser will be called for any important
\r
1842 * event or transition */
\r
1843 #if( ipconfigSOCKET_HAS_USER_SEMAPHORE == 1 )
\r
1845 if( pxSocket->pxUserSemaphore != NULL )
\r
1847 xSemaphoreGive( pxSocket->pxUserSemaphore );
\r
1850 #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
\r
1852 #if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK == 1 )
\r
1854 if( pxSocket->pxUserWakeCallback != NULL )
\r
1856 pxSocket->pxUserWakeCallback( pxSocket );
\r
1859 #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
\r
1861 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
1863 if( pxSocket->pxSocketSet != NULL )
\r
1865 EventBits_t xSelectBits = ( pxSocket->xEventBits >> SOCKET_EVENT_BIT_COUNT ) & eSELECT_ALL;
\r
1866 if( xSelectBits != 0ul )
\r
1868 pxSocket->xSocketBits |= xSelectBits;
\r
1869 xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, xSelectBits );
\r
1873 pxSocket->xEventBits &= eSOCKET_ALL;
\r
1875 #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
\r
1877 if( ( pxSocket->xEventGroup != NULL ) && ( pxSocket->xEventBits != 0u ) )
\r
1879 xEventGroupSetBits( pxSocket->xEventGroup, pxSocket->xEventBits );
\r
1882 pxSocket->xEventBits = 0ul;
\r
1885 /*-----------------------------------------------------------*/
\r
1887 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1889 /* This define makes it possible for network-card drivers to inspect
\r
1890 * UDP message and see if there is any UDP socket bound to a given port
\r
1892 * This is probably only useful in systems with a minimum of RAM and
\r
1893 * when lots of anonymous broadcast messages come in
\r
1895 BaseType_t xPortHasUDPSocket( uint16_t usPortNr )
\r
1897 BaseType_t xFound = pdFALSE;
\r
1899 vTaskSuspendAll();
\r
1901 if( ( pxListFindListItemWithValue( &xBoundUDPSocketsList, ( TickType_t ) usPortNr ) != NULL ) )
\r
1911 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1913 /*-----------------------------------------------------------*/
\r
1915 #if( ipconfigUSE_TCP == 1 )
\r
1917 static BaseType_t bMayConnect( FreeRTOS_Socket_t *pxSocket );
\r
1918 static BaseType_t bMayConnect( FreeRTOS_Socket_t *pxSocket )
\r
1920 switch( pxSocket->u.xTCP.ucTCPState )
\r
1923 case eCLOSE_WAIT: return 0;
\r
1924 case eCONNECT_SYN: return -pdFREERTOS_ERRNO_EINPROGRESS;
\r
1925 default: return -pdFREERTOS_ERRNO_EAGAIN;
\r
1929 #endif /* ipconfigUSE_TCP */
\r
1930 /*-----------------------------------------------------------*/
\r
1932 #if( ipconfigUSE_TCP == 1 )
\r
1934 static BaseType_t prvTCPConnectStart( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr *pxAddress )
\r
1936 BaseType_t xResult = 0;
\r
1938 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdFALSE )
\r
1940 /* Not a valid socket or wrong type */
\r
1941 xResult = -pdFREERTOS_ERRNO_EBADF;
\r
1943 else if( FreeRTOS_issocketconnected( pxSocket ) > 0 )
\r
1945 /* The socket is already connected. */
\r
1946 xResult = -pdFREERTOS_ERRNO_EISCONN;
\r
1948 else if( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE )
\r
1950 /* Bind the socket to the port that the client task will send from.
\r
1951 Non-standard, so the error returned is that returned by bind(). */
\r
1952 xResult = FreeRTOS_bind( ( Socket_t ) pxSocket, NULL, 0u );
\r
1955 if( xResult == 0 )
\r
1957 /* Check if it makes any sense to wait for a connect event, this condition
\r
1958 might change while sleeping, so it must be checked within each loop */
\r
1959 xResult = bMayConnect( pxSocket ); /* -EINPROGRESS, -EAGAIN, or 0 for OK */
\r
1961 /* Start the connect procedure, kernel will start working on it */
\r
1962 if( xResult == 0 )
\r
1964 pxSocket->u.xTCP.bits.bConnPrepared = pdFALSE_UNSIGNED;
\r
1965 pxSocket->u.xTCP.ucRepCount = 0u;
\r
1967 FreeRTOS_debug_printf( ( "FreeRTOS_connect: %u to %lxip:%u\n",
\r
1968 pxSocket->usLocalPort, FreeRTOS_ntohl( pxAddress->sin_addr ), FreeRTOS_ntohs( pxAddress->sin_port ) ) );
\r
1970 /* Port on remote machine. */
\r
1971 pxSocket->u.xTCP.usRemotePort = FreeRTOS_ntohs( pxAddress->sin_port );
\r
1973 /* IP address of remote machine. */
\r
1974 pxSocket->u.xTCP.ulRemoteIP = FreeRTOS_ntohl( pxAddress->sin_addr );
\r
1976 /* (client) internal state: socket wants to send a connect. */
\r
1977 vTCPStateChange( pxSocket, eCONNECT_SYN );
\r
1979 /* To start an active connect. */
\r
1980 pxSocket->u.xTCP.usTimeout = 1u;
\r
1982 if( xSendEventToIPTask( eTCPTimerEvent ) != pdPASS )
\r
1984 xResult = -pdFREERTOS_ERRNO_ECANCELED;
\r
1992 #endif /* ipconfigUSE_TCP */
\r
1993 /*-----------------------------------------------------------*/
\r
1995 #if( ipconfigUSE_TCP == 1 )
\r
1998 * FreeRTOS_connect: socket wants to connect to a remote port
\r
2000 BaseType_t FreeRTOS_connect( Socket_t xClientSocket, struct freertos_sockaddr *pxAddress, socklen_t xAddressLength )
\r
2002 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t* ) xClientSocket;
\r
2003 TickType_t xRemainingTime;
\r
2004 BaseType_t xTimed = pdFALSE;
\r
2005 BaseType_t xResult;
\r
2006 TimeOut_t xTimeOut;
\r
2008 ( void ) xAddressLength;
\r
2010 xResult = prvTCPConnectStart( pxSocket, pxAddress );
\r
2012 if( xResult == 0 )
\r
2014 /* And wait for the result */
\r
2017 if( xTimed == pdFALSE )
\r
2019 /* Only in the first round, check for non-blocking */
\r
2020 xRemainingTime = pxSocket->xReceiveBlockTime;
\r
2021 if( xRemainingTime == ( TickType_t )0 )
\r
2023 /* Not yet connected, correct state, non-blocking. */
\r
2024 xResult = -pdFREERTOS_ERRNO_EWOULDBLOCK;
\r
2028 /* Don't get here a second time. */
\r
2031 /* Fetch the current time */
\r
2032 vTaskSetTimeOutState( &xTimeOut );
\r
2035 /* Did it get connected while sleeping ? */
\r
2036 xResult = FreeRTOS_issocketconnected( pxSocket );
\r
2038 /* Returns positive when connected, negative means an error */
\r
2041 /* Return the error */
\r
2047 /* Socket now connected, return a zero */
\r
2052 /* Is it allowed to sleep more? */
\r
2053 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) )
\r
2055 xResult = -pdFREERTOS_ERRNO_ETIMEDOUT;
\r
2059 /* Go sleeping until we get any down-stream event */
\r
2060 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_CONNECT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2066 #endif /* ipconfigUSE_TCP */
\r
2067 /*-----------------------------------------------------------*/
\r
2069 #if( ipconfigUSE_TCP == 1 )
\r
2072 * FreeRTOS_accept: can return a new connected socket
\r
2073 * if the server socket is in listen mode and receives a connection request
\r
2074 * The new socket will be bound already to the same port number as the listing
\r
2077 Socket_t FreeRTOS_accept( Socket_t xServerSocket, struct freertos_sockaddr *pxAddress, socklen_t *pxAddressLength )
\r
2079 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xServerSocket;
\r
2080 FreeRTOS_Socket_t *pxClientSocket = NULL;
\r
2081 TickType_t xRemainingTime;
\r
2082 BaseType_t xTimed = pdFALSE, xAsk = pdFALSE;
\r
2083 TimeOut_t xTimeOut;
\r
2084 IPStackEvent_t xAskEvent;
\r
2086 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2088 /* Not a valid socket or wrong type */
\r
2089 pxClientSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
\r
2091 else if( ( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED ) &&
\r
2092 ( pxSocket->u.xTCP.ucTCPState != eTCP_LISTEN ) )
\r
2094 /* Parent socket is not in listening mode */
\r
2095 pxClientSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
\r
2099 /* Loop will stop with breaks. */
\r
2102 /* Is there a new client? */
\r
2103 vTaskSuspendAll();
\r
2105 if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED )
\r
2107 pxClientSocket = pxSocket->u.xTCP.pxPeerSocket;
\r
2111 pxClientSocket = pxSocket;
\r
2113 if( pxClientSocket != NULL )
\r
2115 pxSocket->u.xTCP.pxPeerSocket = NULL;
\r
2117 /* Is it still not taken ? */
\r
2118 if( pxClientSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED )
\r
2120 pxClientSocket->u.xTCP.bits.bPassAccept = pdFALSE_UNSIGNED;
\r
2124 pxClientSocket = NULL;
\r
2130 if( pxClientSocket != NULL )
\r
2132 if( pxAddress != NULL )
\r
2134 /* IP address of remote machine. */
\r
2135 pxAddress->sin_addr = FreeRTOS_ntohl( pxClientSocket->u.xTCP.ulRemoteIP );
\r
2137 /* Port on remote machine. */
\r
2138 pxAddress->sin_port = FreeRTOS_ntohs( pxClientSocket->u.xTCP.usRemotePort );
\r
2140 if( pxAddressLength != NULL )
\r
2142 *pxAddressLength = sizeof( *pxAddress );
\r
2145 if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED )
\r
2151 if( xAsk != pdFALSE )
\r
2153 /* Ask to set an event in 'xEventGroup' as soon as a new
\r
2154 client gets connected for this listening socket. */
\r
2155 xAskEvent.eEventType = eTCPAcceptEvent;
\r
2156 xAskEvent.pvData = ( void * ) pxSocket;
\r
2157 xSendEventStructToIPTask( &xAskEvent, portMAX_DELAY );
\r
2160 if( pxClientSocket != NULL )
\r
2165 if( xTimed == pdFALSE )
\r
2167 /* Only in the first round, check for non-blocking */
\r
2168 xRemainingTime = pxSocket->xReceiveBlockTime;
\r
2169 if( xRemainingTime == ( TickType_t ) 0 )
\r
2174 /* Don't get here a second time */
\r
2177 /* Fetch the current time */
\r
2178 vTaskSetTimeOutState( &xTimeOut );
\r
2181 /* Has the timeout been reached? */
\r
2182 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
\r
2187 /* Go sleeping until we get any down-stream event */
\r
2188 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_ACCEPT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2192 return ( Socket_t ) pxClientSocket;
\r
2194 #endif /* ipconfigUSE_TCP */
\r
2195 /*-----------------------------------------------------------*/
\r
2197 #if( ipconfigUSE_TCP == 1 )
\r
2200 * Read incoming data from a TCP socket
\r
2201 * Only after the last byte has been read, a close error might be returned
\r
2203 BaseType_t FreeRTOS_recv( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags )
\r
2205 BaseType_t xByteCount;
\r
2206 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2207 TickType_t xRemainingTime;
\r
2208 BaseType_t xTimed = pdFALSE;
\r
2209 TimeOut_t xTimeOut;
\r
2210 EventBits_t xEventBits = ( EventBits_t ) 0;
\r
2212 /* Check if the socket is valid, has type TCP and if it is bound to a
\r
2214 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2216 xByteCount = -pdFREERTOS_ERRNO_EINVAL;
\r
2220 if( pxSocket->u.xTCP.rxStream != NULL )
\r
2222 xByteCount = ( BaseType_t )uxStreamBufferGetSize ( pxSocket->u.xTCP.rxStream );
\r
2229 while( xByteCount == 0 )
\r
2231 switch( pxSocket->u.xTCP.ucTCPState )
\r
2234 case eCLOSE_WAIT: /* (server + client) waiting for a connection termination request from the local user. */
\r
2235 case eCLOSING: /* (server + client) waiting for a connection termination request acknowledgement from the remote TCP. */
\r
2236 if( pxSocket->u.xTCP.bits.bMallocError != pdFALSE_UNSIGNED )
\r
2238 /* The no-memory error has priority above the non-connected error.
\r
2239 Both are fatal and will elad to closing the socket. */
\r
2240 xByteCount = -pdFREERTOS_ERRNO_ENOMEM;
\r
2244 xByteCount = -pdFREERTOS_ERRNO_ENOTCONN;
\r
2246 /* Call continue to break out of the switch and also the while
\r
2253 if( xTimed == pdFALSE )
\r
2255 /* Only in the first round, check for non-blocking. */
\r
2256 xRemainingTime = pxSocket->xReceiveBlockTime;
\r
2258 if( xRemainingTime == ( TickType_t ) 0 )
\r
2260 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
2262 /* Just check for the interrupt flag. */
\r
2263 xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_INTR,
\r
2264 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, socketDONT_BLOCK );
\r
2266 #endif /* ipconfigSUPPORT_SIGNALS */
\r
2270 if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
\r
2275 /* Don't get here a second time. */
\r
2278 /* Fetch the current time. */
\r
2279 vTaskSetTimeOutState( &xTimeOut );
\r
2282 /* Has the timeout been reached? */
\r
2283 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
\r
2288 /* Block until there is a down-stream event. */
\r
2289 xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup,
\r
2290 eSOCKET_RECEIVE | eSOCKET_CLOSED | eSOCKET_INTR,
\r
2291 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2292 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
2294 if( ( xEventBits & eSOCKET_INTR ) != 0u )
\r
2301 ( void ) xEventBits;
\r
2303 #endif /* ipconfigSUPPORT_SIGNALS */
\r
2305 if( pxSocket->u.xTCP.rxStream != NULL )
\r
2307 xByteCount = ( BaseType_t ) uxStreamBufferGetSize ( pxSocket->u.xTCP.rxStream );
\r
2315 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
2316 if( ( xEventBits & eSOCKET_INTR ) != 0 )
\r
2318 if( ( xEventBits & ( eSOCKET_RECEIVE | eSOCKET_CLOSED ) ) != 0 )
\r
2320 /* Shouldn't have cleared other flags. */
\r
2321 xEventBits &= ~eSOCKET_INTR;
\r
2322 xEventGroupSetBits( pxSocket->xEventGroup, xEventBits );
\r
2324 xByteCount = -pdFREERTOS_ERRNO_EINTR;
\r
2327 #endif /* ipconfigSUPPORT_SIGNALS */
\r
2328 if( xByteCount > 0 )
\r
2330 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
\r
2332 xByteCount = ( BaseType_t ) uxStreamBufferGet( pxSocket->u.xTCP.rxStream, 0ul, ( uint8_t * ) pvBuffer, ( size_t ) xBufferLength, ( xFlags & FREERTOS_MSG_PEEK ) != 0 );
\r
2333 if( pxSocket->u.xTCP.bits.bLowWater != pdFALSE_UNSIGNED )
\r
2335 /* We had reached the low-water mark, now see if the flag
\r
2337 size_t uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );
\r
2339 if( uxFrontSpace >= pxSocket->u.xTCP.uxEnoughSpace )
\r
2341 pxSocket->u.xTCP.bits.bLowWater = pdFALSE_UNSIGNED;
\r
2342 pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
\r
2343 pxSocket->u.xTCP.usTimeout = 1u; /* because bLowWater is cleared. */
\r
2344 xSendEventToIPTask( eTCPTimerEvent );
\r
2350 /* Zero-copy reception of data: pvBuffer is a pointer to a pointer. */
\r
2351 xByteCount = ( BaseType_t ) uxStreamBufferGetPtr( pxSocket->u.xTCP.rxStream, (uint8_t **)pvBuffer );
\r
2354 } /* prvValidSocket() */
\r
2356 return xByteCount;
\r
2359 #endif /* ipconfigUSE_TCP */
\r
2360 /*-----------------------------------------------------------*/
\r
2362 #if( ipconfigUSE_TCP == 1 )
\r
2364 static int32_t prvTCPSendCheck( FreeRTOS_Socket_t *pxSocket, size_t xDataLength )
\r
2366 int32_t xResult = 1;
\r
2368 /* Is this a socket of type TCP and is it already bound to a port number ? */
\r
2369 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2371 xResult = -pdFREERTOS_ERRNO_EINVAL;
\r
2373 else if( pxSocket->u.xTCP.bits.bMallocError != pdFALSE_UNSIGNED )
\r
2375 xResult = -pdFREERTOS_ERRNO_ENOMEM;
\r
2377 else if( ( pxSocket->u.xTCP.ucTCPState == eCLOSED ) ||
\r
2378 ( pxSocket->u.xTCP.ucTCPState == eCLOSE_WAIT ) ||
\r
2379 ( pxSocket->u.xTCP.ucTCPState == eCLOSING ) )
\r
2381 xResult = -pdFREERTOS_ERRNO_ENOTCONN;
\r
2383 else if( pxSocket->u.xTCP.bits.bFinSent != pdFALSE_UNSIGNED )
\r
2385 /* This TCP connection is closing already, the FIN flag has been sent.
\r
2386 Maybe it is still delivering or receiving data.
\r
2387 Return OK in order not to get closed/deleted too quickly */
\r
2390 else if( xDataLength == 0ul )
\r
2392 /* send() is being called to send zero bytes */
\r
2395 else if( pxSocket->u.xTCP.txStream == NULL )
\r
2397 /* Create the outgoing stream only when it is needed */
\r
2398 prvTCPCreateStream( pxSocket, pdFALSE );
\r
2400 if( pxSocket->u.xTCP.txStream == NULL )
\r
2402 xResult = -pdFREERTOS_ERRNO_ENOMEM;
\r
2409 #endif /* ipconfigUSE_TCP */
\r
2410 /*-----------------------------------------------------------*/
\r
2412 #if( ipconfigUSE_TCP == 1 )
\r
2414 /* Get a direct pointer to the circular transmit buffer.
\r
2415 '*pxLength' will contain the number of bytes that may be written. */
\r
2416 uint8_t *FreeRTOS_get_tx_head( Socket_t xSocket, BaseType_t *pxLength )
\r
2418 uint8_t *pucReturn;
\r
2419 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2420 StreamBuffer_t *pxBuffer = pxSocket->u.xTCP.txStream;
\r
2422 if( pxBuffer != NULL )
\r
2424 BaseType_t xSpace = ( BaseType_t ) uxStreamBufferGetSpace( pxBuffer );
\r
2425 BaseType_t xRemain = ( BaseType_t ) ( pxBuffer->LENGTH - pxBuffer->uxHead );
\r
2427 *pxLength = FreeRTOS_min_BaseType( xSpace, xRemain );
\r
2428 pucReturn = pxBuffer->ucArray + pxBuffer->uxHead;
\r
2438 #endif /* ipconfigUSE_TCP */
\r
2439 /*-----------------------------------------------------------*/
\r
2441 #if( ipconfigUSE_TCP == 1 )
\r
2443 * Send data using a TCP socket. It is not necessary to have the socket
\r
2444 * connected already. Outgoing data will be stored and delivered as soon as
\r
2445 * the socket gets connected.
\r
2447 BaseType_t FreeRTOS_send( Socket_t xSocket, const void *pvBuffer, size_t uxDataLength, BaseType_t xFlags )
\r
2449 BaseType_t xByteCount;
\r
2450 BaseType_t xBytesLeft;
\r
2451 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2452 TickType_t xRemainingTime;
\r
2453 BaseType_t xTimed = pdFALSE;
\r
2454 TimeOut_t xTimeOut;
\r
2455 BaseType_t xCloseAfterSend;
\r
2457 /* Prevent compiler warnings about unused parameters. The parameter
\r
2458 may be used in future versions. */
\r
2461 xByteCount = ( BaseType_t ) prvTCPSendCheck( pxSocket, uxDataLength );
\r
2463 if( xByteCount > 0 )
\r
2465 /* xBytesLeft is number of bytes to send, will count to zero. */
\r
2466 xBytesLeft = ( BaseType_t ) uxDataLength;
\r
2468 /* xByteCount is number of bytes that can be sent now. */
\r
2469 xByteCount = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
\r
2471 /* While there are still bytes to be sent. */
\r
2472 while( xBytesLeft > 0 )
\r
2474 /* If txStream has space. */
\r
2475 if( xByteCount > 0 )
\r
2477 /* Don't send more than necessary. */
\r
2478 if( xByteCount > xBytesLeft )
\r
2480 xByteCount = xBytesLeft;
\r
2483 /* Is the close-after-send flag set and is this really the
\r
2484 last transmission? */
\r
2485 if( ( pxSocket->u.xTCP.bits.bCloseAfterSend != pdFALSE_UNSIGNED ) && ( xByteCount == xBytesLeft ) )
\r
2487 xCloseAfterSend = pdTRUE;
\r
2491 xCloseAfterSend = pdFALSE;
\r
2494 /* The flag 'bCloseAfterSend' can be set before sending data
\r
2495 using setsockopt()
\r
2497 When the last data packet is being sent out, a FIN flag will
\r
2498 be included to let the peer know that no more data is to be
\r
2499 expected. The use of 'bCloseAfterSend' is not mandatory, it
\r
2500 is just a faster way of transferring files (e.g. when using
\r
2502 if( xCloseAfterSend != pdFALSE )
\r
2504 /* Now suspend the scheduler: sending the last data and
\r
2505 setting bCloseRequested must be done together */
\r
2506 vTaskSuspendAll();
\r
2507 pxSocket->u.xTCP.bits.bCloseRequested = pdTRUE_UNSIGNED;
\r
2510 xByteCount = ( BaseType_t ) uxStreamBufferAdd( pxSocket->u.xTCP.txStream, 0ul, ( const uint8_t * ) pvBuffer, ( size_t ) xByteCount );
\r
2512 if( xCloseAfterSend != pdFALSE )
\r
2514 /* Now when the IP-task transmits the data, it will also
\r
2515 see that bCloseRequested is true and include the FIN
\r
2516 flag to start closure of the connection. */
\r
2520 /* Send a message to the IP-task so it can work on this
\r
2521 socket. Data is sent, let the IP-task work on it. */
\r
2522 pxSocket->u.xTCP.usTimeout = 1u;
\r
2524 if( xIsCallingFromIPTask() == pdFALSE )
\r
2526 /* Only send a TCP timer event when not called from the
\r
2528 xSendEventToIPTask( eTCPTimerEvent );
\r
2531 xBytesLeft -= xByteCount;
\r
2533 if( xBytesLeft == 0 )
\r
2538 /* As there are still bytes left to be sent, increase the
\r
2540 pvBuffer = ( void * ) ( ( ( const uint8_t * ) pvBuffer) + xByteCount );
\r
2543 /* Not all bytes have been sent. In case the socket is marked as
\r
2544 blocking sleep for a while. */
\r
2545 if( xTimed == pdFALSE )
\r
2547 /* Only in the first round, check for non-blocking. */
\r
2548 xRemainingTime = pxSocket->xSendBlockTime;
\r
2550 #if( ipconfigUSE_CALLBACKS != 0 )
\r
2552 if( xIsCallingFromIPTask() != pdFALSE )
\r
2554 /* If this send function is called from within a
\r
2555 call-back handler it may not block, otherwise
\r
2556 chances would be big to get a deadlock: the IP-task
\r
2557 waiting for itself. */
\r
2558 xRemainingTime = ( TickType_t ) 0;
\r
2561 #endif /* ipconfigUSE_CALLBACKS */
\r
2563 if( xRemainingTime == ( TickType_t ) 0 )
\r
2568 if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
\r
2573 /* Don't get here a second time. */
\r
2576 /* Fetch the current time. */
\r
2577 vTaskSetTimeOutState( &xTimeOut );
\r
2581 /* Has the timeout been reached? */
\r
2582 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
\r
2588 /* Go sleeping until down-stream events are received. */
\r
2589 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_SEND | eSOCKET_CLOSED,
\r
2590 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2592 xByteCount = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
\r
2595 /* How much was actually sent? */
\r
2596 xByteCount = ( ( BaseType_t ) uxDataLength ) - xBytesLeft;
\r
2598 if( xByteCount == 0 )
\r
2600 if( pxSocket->u.xTCP.ucTCPState > eESTABLISHED )
\r
2602 xByteCount = ( BaseType_t ) -pdFREERTOS_ERRNO_ENOTCONN;
\r
2606 if( ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) != pdFALSE )
\r
2608 FreeRTOS_debug_printf( ( "FreeRTOS_send: %u -> %lxip:%d: no space\n",
\r
2609 pxSocket->usLocalPort,
\r
2610 pxSocket->u.xTCP.ulRemoteIP,
\r
2611 pxSocket->u.xTCP.usRemotePort ) );
\r
2614 xByteCount = ( BaseType_t ) -pdFREERTOS_ERRNO_ENOSPC;
\r
2619 return xByteCount;
\r
2622 #endif /* ipconfigUSE_TCP */
\r
2623 /*-----------------------------------------------------------*/
\r
2625 #if( ipconfigUSE_TCP == 1 )
\r
2628 * Request to put a socket in listen mode
\r
2630 BaseType_t FreeRTOS_listen( Socket_t xSocket, BaseType_t xBacklog )
\r
2632 FreeRTOS_Socket_t *pxSocket;
\r
2633 BaseType_t xResult = 0;
\r
2635 pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2637 /* listen() is allowed for a valid TCP socket in Closed state and already
\r
2639 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2641 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2643 else if( ( pxSocket->u.xTCP.ucTCPState != eCLOSED ) && ( pxSocket->u.xTCP.ucTCPState != eCLOSE_WAIT ) )
\r
2645 /* Socket is in a wrong state. */
\r
2646 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2650 /* Backlog is interpreted here as "the maximum number of child
\r
2652 pxSocket->u.xTCP.usBacklog = ( uint16_t )FreeRTOS_min_int32( ( int32_t ) 0xffff, ( int32_t ) xBacklog );
\r
2654 /* This cleaning is necessary only if a listening socket is being
\r
2655 reused as it might have had a previous connection. */
\r
2656 if( pxSocket->u.xTCP.bits.bReuseSocket )
\r
2658 if( pxSocket->u.xTCP.rxStream != NULL )
\r
2660 vStreamBufferClear( pxSocket->u.xTCP.rxStream );
\r
2663 if( pxSocket->u.xTCP.txStream != NULL )
\r
2665 vStreamBufferClear( pxSocket->u.xTCP.txStream );
\r
2668 memset( pxSocket->u.xTCP.xPacket.u.ucLastPacket, '\0', sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket ) );
\r
2669 memset( &pxSocket->u.xTCP.xTCPWindow, '\0', sizeof( pxSocket->u.xTCP.xTCPWindow ) );
\r
2670 memset( &pxSocket->u.xTCP.bits, '\0', sizeof( pxSocket->u.xTCP.bits ) );
\r
2672 /* Now set the bReuseSocket flag again, because the bits have
\r
2673 just been cleared. */
\r
2674 pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE_UNSIGNED;
\r
2677 vTCPStateChange( pxSocket, eTCP_LISTEN );
\r
2683 #endif /* ipconfigUSE_TCP */
\r
2684 /*-----------------------------------------------------------*/
\r
2686 #if( ipconfigUSE_TCP == 1 )
\r
2688 /* shutdown - shut down part of a full-duplex connection */
\r
2689 BaseType_t FreeRTOS_shutdown( Socket_t xSocket, BaseType_t xHow )
\r
2691 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2692 BaseType_t xResult;
\r
2694 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2696 /*_RB_ Is this comment correct? The socket is not of a type that
\r
2697 supports the listen() operation. */
\r
2698 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2700 else if ( pxSocket->u.xTCP.ucTCPState != eESTABLISHED )
\r
2702 /*_RB_ Is this comment correct? The socket is not of a type that
\r
2703 supports the listen() operation. */
\r
2704 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2708 pxSocket->u.xTCP.bits.bUserShutdown = pdTRUE_UNSIGNED;
\r
2710 /* Let the IP-task perform the shutdown of the connection. */
\r
2711 pxSocket->u.xTCP.usTimeout = 1u;
\r
2712 xSendEventToIPTask( eTCPTimerEvent );
\r
2720 #endif /* ipconfigUSE_TCP */
\r
2721 /*-----------------------------------------------------------*/
\r
2723 #if( ipconfigUSE_TCP == 1 )
\r
2726 * A TCP timer has expired, now check all TCP sockets for:
\r
2727 * - Active connect
\r
2728 * - Send a delayed ACK
\r
2730 * - Send a keep-alive packet
\r
2731 * - Check for timeout (in non-connected states only)
\r
2733 TickType_t xTCPTimerCheck( BaseType_t xWillSleep )
\r
2735 FreeRTOS_Socket_t *pxSocket;
\r
2736 TickType_t xShortest = pdMS_TO_TICKS( ( TickType_t ) ipTCP_TIMER_PERIOD_MS );
\r
2737 TickType_t xNow = xTaskGetTickCount();
\r
2738 static TickType_t xLastTime = 0u;
\r
2739 TickType_t xDelta = xNow - xLastTime;
\r
2740 ListItem_t* pxEnd = ( ListItem_t * ) listGET_END_MARKER( &xBoundTCPSocketsList );
\r
2741 ListItem_t *pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );
\r
2745 if( xDelta == 0u )
\r
2750 while( pxIterator != pxEnd )
\r
2752 pxSocket = ( FreeRTOS_Socket_t * )listGET_LIST_ITEM_OWNER( pxIterator );
\r
2753 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator );
\r
2755 /* Sockets with 'tmout == 0' do not need any regular attention. */
\r
2756 if( pxSocket->u.xTCP.usTimeout == 0u )
\r
2761 if( xDelta < ( TickType_t ) pxSocket->u.xTCP.usTimeout )
\r
2763 pxSocket->u.xTCP.usTimeout = ( uint16_t ) ( ( ( TickType_t ) pxSocket->u.xTCP.usTimeout ) - xDelta );
\r
2768 pxSocket->u.xTCP.usTimeout = 0u;
\r
2769 rc = xTCPSocketCheck( pxSocket );
\r
2771 /* Within this function, the socket might want to send a delayed
\r
2772 ack or send out data or whatever it needs to do. */
\r
2775 /* Continue because the socket was deleted. */
\r
2780 /* In xEventBits the driver may indicate that the socket has
\r
2781 important events for the user. These are only done just before the
\r
2782 IP-task goes to sleep. */
\r
2783 if( pxSocket->xEventBits != 0u )
\r
2785 if( xWillSleep != pdFALSE )
\r
2787 /* The IP-task is about to go to sleep, so messages can be
\r
2788 sent to the socket owners. */
\r
2789 vSocketWakeUpUser( pxSocket );
\r
2793 /* Or else make sure this will be called again to wake-up
\r
2794 the sockets' owner. */
\r
2795 xShortest = ( TickType_t ) 0;
\r
2799 if( ( pxSocket->u.xTCP.usTimeout != 0u ) && ( xShortest > ( TickType_t ) pxSocket->u.xTCP.usTimeout ) )
\r
2801 xShortest = ( TickType_t ) pxSocket->u.xTCP.usTimeout;
\r
2808 #endif /* ipconfigUSE_TCP */
\r
2809 /*-----------------------------------------------------------*/
\r
2811 #if( ipconfigUSE_TCP == 1 )
\r
2814 * TCP: as multiple sockets may be bound to the same local port number
\r
2815 * looking up a socket is a little more complex:
\r
2816 * Both a local port, and a remote port and IP address are being used
\r
2817 * For a socket in listening mode, the remote port and IP address are both 0
\r
2819 FreeRTOS_Socket_t *pxTCPSocketLookup( uint32_t ulLocalIP, UBaseType_t uxLocalPort, uint32_t ulRemoteIP, UBaseType_t uxRemotePort )
\r
2821 ListItem_t *pxIterator;
\r
2822 FreeRTOS_Socket_t *pxResult = NULL, *pxListenSocket = NULL;
\r
2823 MiniListItem_t *pxEnd = ( MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );
\r
2825 /* Parameter not yet supported. */
\r
2826 ( void ) ulLocalIP;
\r
2828 for( pxIterator = ( ListItem_t * ) listGET_NEXT( pxEnd );
\r
2829 pxIterator != ( ListItem_t * ) pxEnd;
\r
2830 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
2832 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
\r
2834 if( pxSocket->usLocalPort == ( uint16_t ) uxLocalPort )
\r
2836 if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN )
\r
2838 /* If this is a socket listening to uxLocalPort, remember it
\r
2839 in case there is no perfect match. */
\r
2840 pxListenSocket = pxSocket;
\r
2842 else if( ( pxSocket->u.xTCP.usRemotePort == ( uint16_t ) uxRemotePort ) && ( pxSocket->u.xTCP.ulRemoteIP == ulRemoteIP ) )
\r
2844 /* For sockets not in listening mode, find a match with
\r
2845 xLocalPort, ulRemoteIP AND xRemotePort. */
\r
2846 pxResult = pxSocket;
\r
2851 if( pxResult == NULL )
\r
2853 /* An exact match was not found, maybe a listening socket was
\r
2855 pxResult = pxListenSocket;
\r
2861 #endif /* ipconfigUSE_TCP */
\r
2862 /*-----------------------------------------------------------*/
\r
2864 #if( ipconfigUSE_TCP == 1 )
\r
2866 const struct xSTREAM_BUFFER *FreeRTOS_get_rx_buf( Socket_t xSocket )
\r
2868 FreeRTOS_Socket_t *pxSocket = (FreeRTOS_Socket_t *)xSocket;
\r
2870 return pxSocket->u.xTCP.rxStream;
\r
2873 #endif /* ipconfigUSE_TCP */
\r
2874 /*-----------------------------------------------------------*/
\r
2876 #if( ipconfigUSE_TCP == 1 )
\r
2878 static StreamBuffer_t *prvTCPCreateStream( FreeRTOS_Socket_t *pxSocket, BaseType_t xIsInputStream )
\r
2880 StreamBuffer_t *pxBuffer;
\r
2884 /* Now that a stream is created, the maximum size is fixed before
\r
2885 creation, it could still be changed with setsockopt(). */
\r
2886 if( xIsInputStream != pdFALSE )
\r
2888 /* Flow control for input streams works with a low- and a high-water mark.
\r
2889 1) If the RX-space becomes less than uxLittleSpace, the flag 'bLowWater' will
\r
2890 be set, and a TCP window update message will be sent to the peer.
\r
2891 2) The data will be read from the socket by recv() and when RX-space becomes
\r
2892 larger than or equal to than 'uxEnoughSpace', a new TCP window update
\r
2893 message will be sent to the peer, and 'bLowWater' will get cleared again.
\r
2895 uxLittleSpace == 1/5 x uxRxStreamSize
\r
2896 uxEnoughSpace == 4/5 x uxRxStreamSize
\r
2897 How-ever it is very inefficient to make 'uxLittleSpace' smaller than the actual MSS.
\r
2899 uxLength = pxSocket->u.xTCP.uxRxStreamSize;
\r
2901 if( pxSocket->u.xTCP.uxLittleSpace == 0ul )
\r
2903 pxSocket->u.xTCP.uxLittleSpace = ( 1ul * pxSocket->u.xTCP.uxRxStreamSize ) / 5u; /*_RB_ Why divide by 5? Can this be changed to a #define? */
\r
2904 if( ( pxSocket->u.xTCP.uxLittleSpace < pxSocket->u.xTCP.usCurMSS ) && ( pxSocket->u.xTCP.uxRxStreamSize >= 2u * pxSocket->u.xTCP.usCurMSS ) )
\r
2906 pxSocket->u.xTCP.uxLittleSpace = pxSocket->u.xTCP.usCurMSS;
\r
2910 if( pxSocket->u.xTCP.uxEnoughSpace == 0ul )
\r
2912 pxSocket->u.xTCP.uxEnoughSpace = ( 4ul * pxSocket->u.xTCP.uxRxStreamSize ) / 5u; /*_RB_ Why multiply by 4? Maybe sock80_PERCENT?*/
\r
2917 uxLength = pxSocket->u.xTCP.uxTxStreamSize;
\r
2920 /* Add an extra 4 (or 8) bytes. */
\r
2921 uxLength += sizeof( size_t );
\r
2923 /* And make the length a multiple of sizeof( size_t ). */
\r
2924 uxLength &= ~( sizeof( size_t ) - 1u );
\r
2926 uxSize = sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) + uxLength;
\r
2928 pxBuffer = ( StreamBuffer_t * )pvPortMallocLarge( uxSize );
\r
2930 if( pxBuffer == NULL )
\r
2932 FreeRTOS_debug_printf( ( "prvTCPCreateStream: malloc failed\n" ) );
\r
2933 pxSocket->u.xTCP.bits.bMallocError = pdTRUE_UNSIGNED;
\r
2934 vTCPStateChange( pxSocket, eCLOSE_WAIT );
\r
2938 /* Clear the markers of the stream */
\r
2939 memset( pxBuffer, '\0', sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) );
\r
2940 pxBuffer->LENGTH = ( size_t ) uxLength ;
\r
2942 if( xTCPWindowLoggingLevel != 0 )
\r
2944 FreeRTOS_debug_printf( ( "prvTCPCreateStream: %cxStream created %lu bytes (total %lu)\n", xIsInputStream ? 'R' : 'T', uxLength, uxSize ) );
\r
2947 if( xIsInputStream != 0 )
\r
2949 pxSocket->u.xTCP.rxStream = pxBuffer;
\r
2953 pxSocket->u.xTCP.txStream = pxBuffer;
\r
2960 #endif /* ipconfigUSE_TCP */
\r
2961 /*-----------------------------------------------------------*/
\r
2963 #if( ipconfigUSE_TCP == 1 )
\r
2966 * Add data to the RxStream. When uxOffset > 0, data has come in out-of-order
\r
2967 * and will be put in front of the head so it can not be popped by the user.
\r
2969 int32_t lTCPAddRxdata( FreeRTOS_Socket_t *pxSocket, size_t uxOffset, const uint8_t *pcData, uint32_t ulByteCount )
\r
2971 StreamBuffer_t *pxStream = pxSocket->u.xTCP.rxStream;
\r
2973 #if( ipconfigUSE_CALLBACKS == 1 )
\r
2974 BaseType_t bHasHandler = ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xTCP.pxHandleReceive );
\r
2975 const uint8_t *pucBuffer = NULL;
\r
2976 #endif /* ipconfigUSE_CALLBACKS */
\r
2978 /* int32_t uxStreamBufferAdd( pxBuffer, uxOffset, pucData, aCount )
\r
2979 if( pucData != NULL ) copy data the the buffer
\r
2980 if( pucData == NULL ) no copying, just advance rxHead
\r
2981 if( uxOffset != 0 ) Just store data which has come out-of-order
\r
2982 if( uxOffset == 0 ) Also advance rxHead */
\r
2983 if( pxStream == NULL )
\r
2985 pxStream = prvTCPCreateStream( pxSocket, pdTRUE );
\r
2986 if( pxStream == NULL )
\r
2992 #if( ipconfigUSE_CALLBACKS == 1 )
\r
2994 if( ( bHasHandler != pdFALSE ) && ( uxStreamBufferGetSize( pxStream ) == 0u ) && ( uxOffset == 0ul ) && ( pcData != NULL ) )
\r
2996 /* Data can be passed directly to the user */
\r
2997 pucBuffer = pcData;
\r
2999 /* Zero-copy for call-back: no need to add the bytes to the
\r
3000 stream, only the pointer will be advanced by uxStreamBufferAdd(). */
\r
3004 #endif /* ipconfigUSE_CALLBACKS */
\r
3006 xResult = ( int32_t ) uxStreamBufferAdd( pxStream, uxOffset, pcData, ( size_t ) ulByteCount );
\r
3008 #if( ipconfigHAS_DEBUG_PRINTF != 0 )
\r
3010 if( xResult != ( int32_t ) ulByteCount )
\r
3012 FreeRTOS_debug_printf( ( "lTCPAddRxdata: at %ld: %ld/%lu bytes (tail %lu head %lu space %lu front %lu)\n",
\r
3013 uxOffset, xResult, ulByteCount,
\r
3016 uxStreamBufferFrontSpace( pxStream ),
\r
3017 pxStream->uxFront ) );
\r
3020 #endif /* ipconfigHAS_DEBUG_PRINTF */
\r
3022 if( uxOffset == 0u )
\r
3024 /* Data is being added to rxStream at the head (offs = 0) */
\r
3025 #if( ipconfigUSE_CALLBACKS == 1 )
\r
3026 if( bHasHandler != pdFALSE )
\r
3028 /* The socket owner has installed an OnReceive handler. Pass the
\r
3029 Rx data, without copying from the rxStream, to the user. */
\r
3032 uint8_t *ucReadPtr = NULL;
\r
3034 if( pucBuffer != NULL )
\r
3036 ucReadPtr = ( uint8_t * )pucBuffer;
\r
3037 ulCount = ulByteCount;
\r
3042 ulCount = ( uint32_t ) uxStreamBufferGetPtr( pxStream, &( ucReadPtr ) );
\r
3045 if( ulCount == 0ul )
\r
3050 if( pxSocket->u.xTCP.pxHandleReceive( (Socket_t *)pxSocket, ( void* )ucReadPtr, ( size_t ) ulCount ) != pdFALSE )
\r
3052 uxStreamBufferGet( pxStream, 0ul, NULL, ( size_t ) ulCount, pdFALSE );
\r
3056 #endif /* ipconfigUSE_CALLBACKS */
\r
3058 /* See if running out of space. */
\r
3059 if( pxSocket->u.xTCP.bits.bLowWater == pdFALSE_UNSIGNED )
\r
3061 size_t uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );
\r
3062 if( uxFrontSpace <= pxSocket->u.xTCP.uxLittleSpace )
\r
3064 pxSocket->u.xTCP.bits.bLowWater = pdTRUE_UNSIGNED;
\r
3065 pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
\r
3067 /* bLowWater was reached, send the changed window size. */
\r
3068 pxSocket->u.xTCP.usTimeout = 1u;
\r
3069 xSendEventToIPTask( eTCPTimerEvent );
\r
3073 /* New incoming data is available, wake up the user. User's
\r
3074 semaphores will be set just before the IP-task goes asleep. */
\r
3075 pxSocket->xEventBits |= eSOCKET_RECEIVE;
\r
3077 #if ipconfigSUPPORT_SELECT_FUNCTION == 1
\r
3079 if( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 )
\r
3081 pxSocket->xEventBits |= ( eSELECT_READ << SOCKET_EVENT_BIT_COUNT );
\r
3091 #endif /* ipconfigUSE_TCP */
\r
3092 /*-----------------------------------------------------------*/
\r
3094 #if( ipconfigUSE_TCP == 1 )
\r
3096 /* Function to get the remote address and IP port */
\r
3097 BaseType_t FreeRTOS_GetRemoteAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress )
\r
3099 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3100 BaseType_t xResult;
\r
3102 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3104 xResult = -pdFREERTOS_ERRNO_EINVAL;
\r
3108 /* BSD style sockets communicate IP and port addresses in network
\r
3111 IP address of remote machine. */
\r
3112 pxAddress->sin_addr = FreeRTOS_htonl ( pxSocket->u.xTCP.ulRemoteIP );
\r
3114 /* Port on remote machine. */
\r
3115 pxAddress->sin_port = FreeRTOS_htons ( pxSocket->u.xTCP.usRemotePort );
\r
3117 xResult = ( BaseType_t ) sizeof( ( *pxAddress ) );
\r
3123 #endif /* ipconfigUSE_TCP */
\r
3125 /*-----------------------------------------------------------*/
\r
3127 #if( ipconfigUSE_TCP == 1 )
\r
3129 /* Returns the number of bytes that may be added to txStream */
\r
3130 BaseType_t FreeRTOS_maywrite( Socket_t xSocket )
\r
3132 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3133 BaseType_t xResult;
\r
3135 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3137 xResult = -pdFREERTOS_ERRNO_EINVAL;
\r
3139 else if( pxSocket->u.xTCP.ucTCPState != eESTABLISHED )
\r
3141 if( ( pxSocket->u.xTCP.ucTCPState < eCONNECT_SYN ) || ( pxSocket->u.xTCP.ucTCPState > eESTABLISHED ) )
\r
3150 else if( pxSocket->u.xTCP.txStream == NULL )
\r
3152 xResult = ( BaseType_t ) pxSocket->u.xTCP.uxTxStreamSize;
\r
3156 xResult = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
\r
3162 #endif /* ipconfigUSE_TCP */
\r
3163 /*-----------------------------------------------------------*/
\r
3165 #if( ipconfigUSE_TCP ==1 )
\r
3167 BaseType_t FreeRTOS_tx_space( Socket_t xSocket )
\r
3169 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3170 BaseType_t xReturn;
\r
3172 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3174 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3178 if( pxSocket->u.xTCP.txStream != NULL )
\r
3180 xReturn = ( BaseType_t ) uxStreamBufferGetSpace ( pxSocket->u.xTCP.txStream );
\r
3184 xReturn = ( BaseType_t ) pxSocket->u.xTCP.uxTxStreamSize;
\r
3191 #endif /* ipconfigUSE_TCP */
\r
3192 /*-----------------------------------------------------------*/
\r
3194 #if( ipconfigUSE_TCP == 1 )
\r
3196 BaseType_t FreeRTOS_tx_size( Socket_t xSocket )
\r
3198 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3199 BaseType_t xReturn;
\r
3201 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3203 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3207 if( pxSocket->u.xTCP.txStream != NULL )
\r
3209 xReturn = ( BaseType_t ) uxStreamBufferGetSize ( pxSocket->u.xTCP.txStream );
\r
3220 #endif /* ipconfigUSE_TCP */
\r
3221 /*-----------------------------------------------------------*/
\r
3223 #if( ipconfigUSE_TCP == 1 )
\r
3225 /* Returns pdTRUE if TCP socket is connected. */
\r
3226 BaseType_t FreeRTOS_issocketconnected( Socket_t xSocket )
\r
3228 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3229 BaseType_t xReturn = pdFALSE;
\r
3231 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3233 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3237 if( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED )
\r
3239 if( pxSocket->u.xTCP.ucTCPState < eCLOSE_WAIT )
\r
3249 #endif /* ipconfigUSE_TCP */
\r
3250 /*-----------------------------------------------------------*/
\r
3252 #if( ipconfigUSE_TCP == 1 )
\r
3254 /* returns the actual size of MSS being used */
\r
3255 BaseType_t FreeRTOS_mss( Socket_t xSocket )
\r
3257 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3258 BaseType_t xReturn;
\r
3260 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3262 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3266 /* usCurMSS is declared as uint16_t to save space. FreeRTOS_mss()
\r
3267 will often be used in signed native-size expressions cast it to
\r
3269 xReturn = ( BaseType_t ) ( pxSocket->u.xTCP.usCurMSS );
\r
3275 #endif /* ipconfigUSE_TCP */
\r
3276 /*-----------------------------------------------------------*/
\r
3278 #if( ipconfigUSE_TCP == 1 )
\r
3280 /* HT: for internal use only: return the connection status */
\r
3281 BaseType_t FreeRTOS_connstatus( Socket_t xSocket )
\r
3283 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3284 BaseType_t xReturn;
\r
3286 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3288 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3292 /* Cast it to BaseType_t */
\r
3293 xReturn = ( BaseType_t ) ( pxSocket->u.xTCP.ucTCPState );
\r
3299 #endif /* ipconfigUSE_TCP */
\r
3300 /*-----------------------------------------------------------*/
\r
3302 #if( ipconfigUSE_TCP == 1 )
\r
3305 * Returns the number of bytes which can be read.
\r
3307 BaseType_t FreeRTOS_rx_size( Socket_t xSocket )
\r
3309 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3310 BaseType_t xReturn;
\r
3312 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3314 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3316 else if( pxSocket->u.xTCP.rxStream != NULL )
\r
3318 xReturn = ( BaseType_t ) uxStreamBufferGetSize( pxSocket->u.xTCP.rxStream );
\r
3328 #endif /* ipconfigUSE_TCP */
\r
3329 /*-----------------------------------------------------------*/
\r
3331 #if( ipconfigUSE_TCP == 1 )
\r
3333 void FreeRTOS_netstat( void )
\r
3335 IPStackEvent_t xAskEvent;
\r
3337 /* Ask the IP-task to call vTCPNetStat()
\r
3338 * to avoid accessing xBoundTCPSocketsList
\r
3340 xAskEvent.eEventType = eTCPNetStat;
\r
3341 xAskEvent.pvData = ( void * ) NULL;
\r
3342 xSendEventStructToIPTask( &xAskEvent, 1000u );
\r
3345 #endif /* ipconfigUSE_TCP */
\r
3346 /*-----------------------------------------------------------*/
\r
3348 #if( ( ipconfigHAS_PRINTF != 0 ) && ( ipconfigUSE_TCP == 1 ) )
\r
3350 void vTCPNetStat( void )
\r
3352 /* Show a simple listing of all created sockets and their connections */
\r
3353 ListItem_t *pxIterator;
\r
3354 BaseType_t count = 0;
\r
3356 if( listLIST_IS_INITIALISED( &xBoundTCPSocketsList ) == pdFALSE )
\r
3358 FreeRTOS_printf( ( "PLUS-TCP not initialized\n" ) );
\r
3362 FreeRTOS_printf( ( "Prot Port IP-Remote : Port R/T Status Alive tmout Child\n" ) );
\r
3363 for( pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );
\r
3364 pxIterator != ( ListItem_t * ) listGET_END_MARKER( &xBoundTCPSocketsList );
\r
3365 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
3367 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
\r
3368 #if( ipconfigTCP_KEEP_ALIVE == 1 )
\r
3369 TickType_t age = xTaskGetTickCount() - pxSocket->u.xTCP.xLastAliveTime;
\r
3371 TickType_t age = 0u;
\r
3373 #if( ipconfigUSE_CALLBACKS == 1 )
\r
3374 void *pxHandleReceive = (void*)pxSocket->u.xTCP.pxHandleReceive;
\r
3376 void *pxHandleReceive = (void*)NULL;
\r
3378 char ucChildText[16] = "";
\r
3379 if (pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN)
\r
3381 snprintf( ucChildText, sizeof( ucChildText ), " %d/%d",
\r
3382 pxSocket->u.xTCP.usChildCount,
\r
3383 pxSocket->u.xTCP.usBacklog);
\r
3385 if( age > 999999 )
\r
3387 FreeRTOS_printf( ( "TCP %5d %-16lxip:%5d %d/%d %-13.13s %6lu %6u%s\n",
\r
3388 pxSocket->usLocalPort, /* Local port on this machine */
\r
3389 pxSocket->u.xTCP.ulRemoteIP, /* IP address of remote machine */
\r
3390 pxSocket->u.xTCP.usRemotePort, /* Port on remote machine */
\r
3391 pxSocket->u.xTCP.rxStream != NULL,
\r
3392 pxSocket->u.xTCP.txStream != NULL,
\r
3393 FreeRTOS_GetTCPStateName( pxSocket->u.xTCP.ucTCPState ),
\r
3395 pxSocket->u.xTCP.usTimeout,
\r
3397 /* Remove compiler warnings if FreeRTOS_debug_printf() is not defined. */
\r
3398 ( void ) pxHandleReceive;
\r
3402 for( pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundUDPSocketsList );
\r
3403 pxIterator != ( ListItem_t * ) listGET_END_MARKER( &xBoundUDPSocketsList );
\r
3404 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
3406 /* Local port on this machine */
\r
3407 FreeRTOS_printf( ( "UDP Port %5u\n",
\r
3408 FreeRTOS_ntohs( listGET_LIST_ITEM_VALUE( pxIterator ) ) ) );
\r
3412 FreeRTOS_printf( ( "FreeRTOS_netstat: %lu sockets %lu < %lu < %d buffers free\n",
\r
3414 uxGetMinimumFreeNetworkBuffers( ),
\r
3415 uxGetNumberOfFreeNetworkBuffers( ),
\r
3416 ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ) );
\r
3420 #endif /* ( ( ipconfigHAS_PRINTF != 0 ) && ( ipconfigUSE_TCP == 1 ) ) */
\r
3421 /*-----------------------------------------------------------*/
\r
3423 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
3425 void vSocketSelect( SocketSelect_t *pxSocketSet )
\r
3427 BaseType_t xRound;
\r
3428 EventBits_t xSocketBits, xBitsToClear;
\r
3429 #if ipconfigUSE_TCP == 1
\r
3430 BaseType_t xLastRound = 1;
\r
3432 BaseType_t xLastRound = 0;
\r
3435 /* These flags will be switched on after checking the socket status. */
\r
3436 EventBits_t xGroupBits = 0;
\r
3437 pxSocketSet->pxSocket = NULL;
\r
3439 for( xRound = 0; xRound <= xLastRound; xRound++ )
\r
3441 const ListItem_t *pxIterator;
\r
3442 const MiniListItem_t *pxEnd;
\r
3445 pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundUDPSocketsList );
\r
3447 #if ipconfigUSE_TCP == 1
\r
3450 pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );
\r
3452 #endif /* ipconfigUSE_TCP == 1 */
\r
3453 for( pxIterator = ( const ListItem_t * ) ( listGET_NEXT( pxEnd ) );
\r
3454 pxIterator != ( const ListItem_t * ) pxEnd;
\r
3455 pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
3457 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
\r
3458 if( pxSocket->pxSocketSet != pxSocketSet )
\r
3460 /* Socket does not belong to this select group. */
\r
3465 #if( ipconfigUSE_TCP == 1 )
\r
3466 if( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP )
\r
3468 /* Check if the socket has already been accepted by the
\r
3469 owner. If not, it is useless to return it from a
\r
3471 BaseType_t bAccepted = pdFALSE;
\r
3473 if( pxSocket->u.xTCP.bits.bPassQueued == pdFALSE_UNSIGNED )
\r
3475 if( pxSocket->u.xTCP.bits.bPassAccept == pdFALSE_UNSIGNED )
\r
3477 bAccepted = pdTRUE;
\r
3481 /* Is the set owner interested in READ events? */
\r
3482 if( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 )
\r
3484 if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN )
\r
3486 if( ( pxSocket->u.xTCP.pxPeerSocket != NULL ) && ( pxSocket->u.xTCP.pxPeerSocket->u.xTCP.bits.bPassAccept != 0 ) )
\r
3488 xSocketBits |= eSELECT_READ;
\r
3491 else if( ( pxSocket->u.xTCP.bits.bReuseSocket != pdFALSE_UNSIGNED ) && ( pxSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED ) )
\r
3493 /* This socket has the re-use flag. After connecting it turns into
\r
3494 aconnected socket. Set the READ event, so that accept() will be called. */
\r
3495 xSocketBits |= eSELECT_READ;
\r
3497 else if( ( bAccepted != 0 ) && ( FreeRTOS_recvcount( pxSocket ) > 0 ) )
\r
3499 xSocketBits |= eSELECT_READ;
\r
3502 /* Is the set owner interested in EXCEPTION events? */
\r
3503 if( ( pxSocket->xSelectBits & eSELECT_EXCEPT ) != 0 )
\r
3505 if( ( pxSocket->u.xTCP.ucTCPState == eCLOSE_WAIT ) || ( pxSocket->u.xTCP.ucTCPState == eCLOSED ) )
\r
3507 xSocketBits |= eSELECT_EXCEPT;
\r
3511 /* Is the set owner interested in WRITE events? */
\r
3512 if( ( pxSocket->xSelectBits & eSELECT_WRITE ) != 0 )
\r
3514 BaseType_t bMatch = pdFALSE;
\r
3516 if( bAccepted != 0 )
\r
3518 if( FreeRTOS_tx_space( pxSocket ) > 0 )
\r
3524 if( bMatch == pdFALSE )
\r
3526 if( ( pxSocket->u.xTCP.bits.bConnPrepared != pdFALSE_UNSIGNED ) &&
\r
3527 ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) &&
\r
3528 ( pxSocket->u.xTCP.bits.bConnPassed == pdFALSE_UNSIGNED ) )
\r
3530 pxSocket->u.xTCP.bits.bConnPassed = pdTRUE_UNSIGNED;
\r
3535 if( bMatch != pdFALSE )
\r
3537 xSocketBits |= eSELECT_WRITE;
\r
3542 #endif /* ipconfigUSE_TCP == 1 */
\r
3544 /* Select events for UDP are simpler. */
\r
3545 if( ( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 ) &&
\r
3546 ( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) > 0U ) )
\r
3548 xSocketBits |= eSELECT_READ;
\r
3550 /* The WRITE and EXCEPT bits are not used for UDP */
\r
3551 } /* if( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP ) */
\r
3553 /* Each socket keeps its own event flags, which are looked-up
\r
3554 by FreeRTOS_FD_ISSSET() */
\r
3555 pxSocket->xSocketBits = xSocketBits;
\r
3557 /* The ORed value will be used to set the bits in the event
\r
3559 xGroupBits |= xSocketBits;
\r
3561 } /* for( pxIterator ... ) */
\r
3562 } /* for( xRound = 0; xRound <= xLastRound; xRound++ ) */
\r
3564 xBitsToClear = xEventGroupGetBits( pxSocketSet->xSelectGroup );
\r
3566 /* Now set the necessary bits. */
\r
3567 xBitsToClear = ( xBitsToClear & ~xGroupBits ) & eSELECT_ALL;
\r
3569 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
3571 /* Maybe the socketset was signalled, but don't
\r
3572 clear the 'eSELECT_INTR' bit here, as it will be used
\r
3573 and cleared in FreeRTOS_select(). */
\r
3574 xBitsToClear &= ( EventBits_t ) ~eSELECT_INTR;
\r
3576 #endif /* ipconfigSUPPORT_SIGNALS */
\r
3578 if( xBitsToClear != 0 )
\r
3580 xEventGroupClearBits( pxSocketSet->xSelectGroup, xBitsToClear );
\r
3583 /* Now include eSELECT_CALL_IP to wakeup the caller. */
\r
3584 xEventGroupSetBits( pxSocketSet->xSelectGroup, xGroupBits | eSELECT_CALL_IP );
\r
3587 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
3588 /*-----------------------------------------------------------*/
\r
3590 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
3592 /* Send a signal to the task which reads from this socket. */
\r
3593 BaseType_t FreeRTOS_SignalSocket( Socket_t xSocket )
\r
3595 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3596 BaseType_t xReturn;
\r
3598 if( pxSocket == NULL )
\r
3600 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3603 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
3604 if( ( pxSocket->pxSocketSet != NULL ) && ( pxSocket->pxSocketSet->xSelectGroup != NULL ) )
\r
3606 xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, eSELECT_INTR );
\r
3610 #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
\r
3611 if( pxSocket->xEventGroup != NULL )
\r
3613 xEventGroupSetBits( pxSocket->xEventGroup, eSOCKET_INTR );
\r
3618 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3624 #endif /* ipconfigSUPPORT_SIGNALS */
\r
3625 /*-----------------------------------------------------------*/
\r
3627 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
3629 /* Send a signal to the task which reads from this socket (FromISR version). */
\r
3630 BaseType_t FreeRTOS_SignalSocketFromISR( Socket_t xSocket, BaseType_t *pxHigherPriorityTaskWoken )
\r
3632 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3633 BaseType_t xReturn;
\r
3634 IPStackEvent_t xEvent;
\r
3635 extern QueueHandle_t xNetworkEventQueue;
\r
3637 configASSERT( pxSocket != NULL );
\r
3638 configASSERT( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP );
\r
3639 configASSERT( pxSocket->xEventGroup );
\r
3641 xEvent.eEventType = eSocketSignalEvent;
\r
3642 xEvent.pvData = ( void * )pxSocket;
\r
3644 /* The IP-task will call FreeRTOS_SignalSocket for this socket. */
\r
3645 xReturn = xQueueSendToBackFromISR( xNetworkEventQueue, &xEvent, pxHigherPriorityTaskWoken );
\r
3650 #endif /* ipconfigSUPPORT_SIGNALS */
\r
3651 /*-----------------------------------------------------------*/
\r