2 * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
\r
3 * Authors include Hein Tibosch and Richard Barry
\r
5 *******************************************************************************
\r
6 ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
\r
9 *** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP ***
\r
10 *** demos have a dependency on FreeRTOS+FAT, which is only in the Labs ***
\r
13 *** FreeRTOS+TCP is functional and has been used in commercial products ***
\r
14 *** for some time. Be aware however that we are still refining its ***
\r
15 *** design, the source code does not yet quite conform to the strict ***
\r
16 *** coding and style standards mandated by Real Time Engineers ltd., and ***
\r
17 *** the documentation and testing is not necessarily complete. ***
\r
19 *** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE ***
\r
20 *** URL: http://www.FreeRTOS.org/contact Active early adopters may, at ***
\r
21 *** the sole discretion of Real Time Engineers Ltd., be offered versions ***
\r
22 *** under a license other than that described below. ***
\r
25 ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
\r
26 *******************************************************************************
\r
28 * FreeRTOS+TCP can be used under two different free open source licenses. The
\r
29 * license that applies is dependent on the processor on which FreeRTOS+TCP is
\r
30 * executed, as follows:
\r
32 * If FreeRTOS+TCP is executed on one of the processors listed under the Special
\r
33 * License Arrangements heading of the FreeRTOS+TCP license information web
\r
34 * page, then it can be used under the terms of the FreeRTOS Open Source
\r
35 * License. If FreeRTOS+TCP is used on any other processor, then it can be used
\r
36 * under the terms of the GNU General Public License V2. Links to the relevant
\r
39 * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
\r
40 * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
\r
41 * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
\r
43 * FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot
\r
44 * use FreeRTOS+TCP unless you agree that you use the software 'as is'.
\r
45 * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
\r
46 * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
\r
47 * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
\r
48 * implied, expressed, or statutory.
\r
50 * 1 tab == 4 spaces!
\r
52 * http://www.FreeRTOS.org
\r
53 * http://www.FreeRTOS.org/plus
\r
54 * http://www.FreeRTOS.org/labs
\r
58 /* Standard includes. */
\r
62 /* FreeRTOS includes. */
\r
63 #include "FreeRTOS.h"
\r
68 /* FreeRTOS+TCP includes. */
\r
69 #include "FreeRTOS_UDP_IP.h"
\r
70 #include "FreeRTOS_IP.h"
\r
71 #include "FreeRTOS_Sockets.h"
\r
72 #include "FreeRTOS_IP_Private.h"
\r
73 #include "FreeRTOS_DNS.h"
\r
74 #include "NetworkBufferManagement.h"
\r
76 /* The ItemValue of the sockets xBoundSocketListItem member holds the socket's
\r
78 #define socketSET_SOCKET_PORT( pxSocket, usPort ) listSET_LIST_ITEM_VALUE( ( &( ( pxSocket )->xBoundSocketListItem ) ), ( usPort ) )
\r
79 #define socketGET_SOCKET_PORT( pxSocket ) listGET_LIST_ITEM_VALUE( ( &( ( pxSocket )->xBoundSocketListItem ) ) )
\r
81 /* Test if a socket it bound which means it is either included in
\r
82 xBoundUDPSocketsList or xBoundTCPSocketsList */
\r
83 #define socketSOCKET_IS_BOUND( pxSocket ) ( listLIST_ITEM_CONTAINER( & ( pxSocket )->xBoundSocketListItem ) != NULL )
\r
85 /* If FreeRTOS_sendto() is called on a socket that is not bound to a port
\r
86 number then, depending on the FreeRTOSIPConfig.h settings, it might be that a
\r
87 port number is automatically generated for the socket. Automatically generated
\r
88 port numbers will be between socketAUTO_PORT_ALLOCATION_START_NUMBER and
\r
90 /* _HT_ thinks that the default of 0xc000 is pretty high */
\r
91 #if !defined( socketAUTO_PORT_ALLOCATION_START_NUMBER )
\r
92 #define socketAUTO_PORT_ALLOCATION_START_NUMBER ( ( uint16_t ) 0xc000 )
\r
95 /* When the automatically generated port numbers overflow, the next value used
\r
96 is not set back to socketAUTO_PORT_ALLOCATION_START_NUMBER because it is likely
\r
97 that the first few automatically generated ports will still be in use. Instead
\r
98 it is reset back to the value defined by this constant. */
\r
99 #define socketAUTO_PORT_ALLOCATION_RESET_NUMBER ( ( uint16_t ) 0xc100 )
\r
100 #define socketAUTO_PORT_ALLOCATION_MAX_NUMBER ( ( uint16_t ) 0xff00 )
\r
102 /* The number of octets that make up an IP address. */
\r
103 #define socketMAX_IP_ADDRESS_OCTETS 4u
\r
105 /* A block time of 0 simply means "don't block". */
\r
106 #define socketDONT_BLOCK ( ( TickType_t ) 0 )
\r
108 #if( ( ipconfigUSE_TCP == 1 ) && !defined( ipTCP_TIMER_PERIOD_MS ) )
\r
109 #define ipTCP_TIMER_PERIOD_MS ( 1000 )
\r
112 /* The next private port number to use when binding a client socket is stored in
\r
113 the usNextPortToUse[] array - which has either 1 or two indexes depending on
\r
114 whether TCP is being supported. */
\r
115 #if( ipconfigUSE_TCP == 1 )
\r
116 #define socketPROTOCOL_COUNT 2
\r
118 #define socketPROTOCOL_COUNT 1
\r
121 /* Indexes into the usNextPortToUse[] array for UDP and TCP sockets
\r
123 #define socketNEXT_UDP_PORT_NUMBER_INDEX 0
\r
124 #define socketNEXT_TCP_PORT_NUMBER_INDEX 1
\r
127 /*-----------------------------------------------------------*/
\r
130 * Allocate the next port number from the private allocation range.
\r
131 * TCP and UDP each have their own series of port numbers
\r
132 * ulProtocol is either ipPROTOCOL_UDP or ipPROTOCOL_TCP
\r
134 static uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol );
\r
137 * Return the list item from within pxList that has an item value of
\r
138 * xWantedItemValue. If there is no such list item return NULL.
\r
140 static const ListItem_t * pxListFindListItemWithValue( const List_t *pxList, TickType_t xWantedItemValue );
\r
143 * Return pdTRUE only if pxSocket is valid and bound, as far as can be
\r
146 static BaseType_t prvValidSocket( FreeRTOS_Socket_t *pxSocket, BaseType_t xProtocol, BaseType_t xIsBound );
\r
149 * Before creating a socket, check the validity of the parameters used
\r
150 * and find the size of the socket space, which is different for UDP and TCP
\r
152 static BaseType_t prvDetermineSocketSize( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol, size_t *pxSocketSize );
\r
154 #if( ipconfigUSE_TCP == 1 )
\r
156 * Create a txStream or a rxStream, depending on the parameter 'xIsInputStream'
\r
158 static StreamBuffer_t *prvTCPCreateStream (FreeRTOS_Socket_t *pxSocket, BaseType_t xIsInputStream );
\r
159 #endif /* ipconfigUSE_TCP == 1 */
\r
161 #if( ipconfigUSE_TCP == 1 )
\r
163 * Called from FreeRTOS_send(): some checks which will be done before
\r
164 * sending a TCP packed.
\r
166 static int32_t prvTCPSendCheck( FreeRTOS_Socket_t *pxSocket, size_t xDataLength );
\r
167 #endif /* ipconfigUSE_TCP */
\r
169 #if( ipconfigUSE_TCP == 1 )
\r
171 * When a child socket gets closed, make sure to update the child-count of the parent
\r
173 static void prvTCPSetSocketCount( FreeRTOS_Socket_t *pxSocketToDelete );
\r
174 #endif /* ipconfigUSE_TCP == 1 */
\r
176 #if( ipconfigUSE_TCP == 1 )
\r
178 * Called from FreeRTOS_connect(): make some checks and if allowed, send a
\r
179 * message to the IP-task to start connecting to a remote socket
\r
181 static BaseType_t prvTCPConnectStart( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr *pxAddress );
\r
182 #endif /* ipconfigUSE_TCP */
\r
184 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
186 /* Executed by the IP-task, it will check all sockets belonging to a set */
\r
187 static FreeRTOS_Socket_t *prvFindSelectedSocket( SocketSelect_t *pxSocketSet );
\r
189 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
190 /*-----------------------------------------------------------*/
\r
192 /* The list that contains mappings between sockets and port numbers. Accesses
\r
193 to this list must be protected by critical sections of one kind or another. */
\r
194 List_t xBoundUDPSocketsList;
\r
196 #if ipconfigUSE_TCP == 1
\r
197 List_t xBoundTCPSocketsList;
\r
198 #endif /* ipconfigUSE_TCP == 1 */
\r
200 /* Holds the next private port number to use when binding a client socket for
\r
201 UDP, and if ipconfigUSE_TCP is set to 1, also TCP. UDP uses index
\r
202 socketNEXT_UDP_PORT_NUMBER_INDEX and TCP uses index
\r
203 socketNEXT_TCP_PORT_NUMBER_INDEX. The initial value is set to be between
\r
204 socketAUTO_PORT_ALLOCATION_RESET_NUMBER and socketAUTO_PORT_ALLOCATION_MAX_NUMBER
\r
205 when the IP stack is initialised. Note ipconfigRAND32() is used, which must be
\r
206 seeded prior to the IP task being started. */
\r
207 static uint16_t usNextPortToUse[ socketPROTOCOL_COUNT ] = { 0 };
\r
209 /*-----------------------------------------------------------*/
\r
211 static BaseType_t prvValidSocket( FreeRTOS_Socket_t *pxSocket, BaseType_t xProtocol, BaseType_t xIsBound )
\r
213 BaseType_t xReturn = pdTRUE;
\r
215 if( ( pxSocket == NULL ) || ( pxSocket == FREERTOS_INVALID_SOCKET ) )
\r
219 else if( ( xIsBound != pdFALSE ) && ( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE ) )
\r
221 /* The caller expects the socket to be bound, but it isn't. */
\r
224 else if( pxSocket->ucProtocol != ( uint8_t ) xProtocol )
\r
226 /* Socket has a wrong type (UDP != TCP). */
\r
232 /*-----------------------------------------------------------*/
\r
234 void vNetworkSocketsInit( void )
\r
236 const uint32_t ulAutoPortRange = socketAUTO_PORT_ALLOCATION_MAX_NUMBER - socketAUTO_PORT_ALLOCATION_RESET_NUMBER;
\r
237 uint32_t ulRandomPort;
\r
239 vListInitialise( &xBoundUDPSocketsList );
\r
241 /* Determine the first anonymous UDP port number to get assigned. Give it
\r
242 a random value in order to avoid confusion about port numbers being used
\r
243 earlier, before rebooting the device. Start with the first auto port
\r
244 number, then add a random offset up to a maximum of the range of numbers. */
\r
245 ulRandomPort = socketAUTO_PORT_ALLOCATION_START_NUMBER;
\r
246 ulRandomPort += ( ipconfigRAND32() % ulAutoPortRange );
\r
247 usNextPortToUse[ socketNEXT_UDP_PORT_NUMBER_INDEX ] = ( uint16_t ) ulRandomPort;
\r
249 #if( ipconfigUSE_TCP == 1 )
\r
251 extern uint32_t ulNextInitialSequenceNumber;
\r
253 ulNextInitialSequenceNumber = ipconfigRAND32();
\r
255 /* Determine the first anonymous TCP port number to get assigned. */
\r
256 ulRandomPort = socketAUTO_PORT_ALLOCATION_START_NUMBER;
\r
257 ulRandomPort += ( ipconfigRAND32() % ulAutoPortRange );
\r
258 usNextPortToUse[ socketNEXT_TCP_PORT_NUMBER_INDEX ] = ( uint16_t ) ulRandomPort;
\r
260 vListInitialise( &xBoundTCPSocketsList );
\r
262 #endif /* ipconfigUSE_TCP == 1 */
\r
264 /*-----------------------------------------------------------*/
\r
266 static BaseType_t prvDetermineSocketSize( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol, size_t *pxSocketSize )
\r
268 BaseType_t xReturn = pdPASS;
\r
269 FreeRTOS_Socket_t *pxSocket;
\r
271 /* Asserts must not appear before it has been determined that the network
\r
272 task is ready - otherwise the asserts will fail. */
\r
273 if( xIPIsNetworkTaskReady() == pdFALSE )
\r
279 /* Only Ethernet is currently supported. */
\r
280 configASSERT( xDomain == FREERTOS_AF_INET );
\r
282 /* Check if the UDP socket-list has been initialised. */
\r
283 configASSERT( listLIST_IS_INITIALISED( &xBoundUDPSocketsList ) );
\r
284 #if( ipconfigUSE_TCP == 1 )
\r
286 /* Check if the TCP socket-list has been initialised. */
\r
287 configASSERT( listLIST_IS_INITIALISED( &xBoundTCPSocketsList ) );
\r
289 #endif /* ipconfigUSE_TCP == 1 */
\r
291 if( xProtocol == FREERTOS_IPPROTO_UDP )
\r
293 if( xType != FREERTOS_SOCK_DGRAM )
\r
297 /* In case a UDP socket is created, do not allocate space for TCP data. */
\r
298 *pxSocketSize = ( sizeof( *pxSocket ) - sizeof( pxSocket->u ) ) + sizeof( pxSocket->u.xUDP );
\r
300 #if( ipconfigUSE_TCP == 1 )
\r
301 else if( xProtocol == FREERTOS_IPPROTO_TCP )
\r
303 if( xType != FREERTOS_SOCK_STREAM )
\r
308 *pxSocketSize = ( sizeof( *pxSocket ) - sizeof( pxSocket->u ) ) + sizeof( pxSocket->u.xTCP );
\r
310 #endif /* ipconfigUSE_TCP == 1 */
\r
316 /* In case configASSERT() is not used */
\r
320 /*-----------------------------------------------------------*/
\r
322 /* FreeRTOS_socket() allocates and initiates a socket */
\r
323 Socket_t FreeRTOS_socket( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol )
\r
325 FreeRTOS_Socket_t *pxSocket;
\r
326 size_t uxSocketSize;
\r
327 EventGroupHandle_t xEventGroup;
\r
330 if( prvDetermineSocketSize( xDomain, xType, xProtocol, &uxSocketSize ) == pdFAIL )
\r
332 xReturn = FREERTOS_INVALID_SOCKET;
\r
336 /* Allocate the structure that will hold the socket information. The
\r
337 size depends on the type of socket: UDP sockets need less space. A
\r
338 define 'pvPortMallocSocket' will used to allocate the necessary space.
\r
339 By default it points to the FreeRTOS function 'pvPortMalloc()'. */
\r
340 pxSocket = ( FreeRTOS_Socket_t * ) pvPortMallocSocket( uxSocketSize );
\r
342 if( pxSocket == NULL )
\r
344 pxSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
\r
345 iptraceFAILED_TO_CREATE_SOCKET();
\r
347 else if( ( xEventGroup = xEventGroupCreate() ) == NULL )
\r
349 vPortFreeSocket( pxSocket );
\r
350 pxSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
\r
351 iptraceFAILED_TO_CREATE_EVENT_GROUP();
\r
355 /* Clear the entire space to avoid nulling individual entries. */
\r
356 memset( pxSocket, '\0', uxSocketSize );
\r
358 pxSocket->xEventGroup = xEventGroup;
\r
360 /* Initialise the socket's members. The semaphore will be created
\r
361 if the socket is bound to an address, for now the pointer to the
\r
362 semaphore is just set to NULL to show it has not been created. */
\r
363 if( xProtocol == FREERTOS_IPPROTO_UDP )
\r
365 vListInitialise( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
\r
367 #if( ipconfigUDP_MAX_RX_PACKETS > 0 )
\r
369 pxSocket->u.xUDP.uxMaxPackets = ( UBaseType_t ) ipconfigUDP_MAX_RX_PACKETS;
\r
371 #endif /* ipconfigUDP_MAX_RX_PACKETS > 0 */
\r
374 vListInitialiseItem( &( pxSocket->xBoundSocketListItem ) );
\r
375 listSET_LIST_ITEM_OWNER( &( pxSocket->xBoundSocketListItem ), ( void * ) pxSocket );
\r
377 pxSocket->xReceiveBlockTime = ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME;
\r
378 pxSocket->xSendBlockTime = ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME;
\r
379 pxSocket->ucSocketOptions = ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT;
\r
380 pxSocket->ucProtocol = ( uint8_t ) xProtocol; /* protocol: UDP or TCP */
\r
382 #if( ipconfigUSE_TCP == 1 )
\r
384 if( xProtocol == FREERTOS_IPPROTO_TCP )
\r
386 /* StreamSize is expressed in number of bytes */
\r
387 /* Round up buffer sizes to nearest multiple of MSS */
\r
388 pxSocket->u.xTCP.usInitMSS = pxSocket->u.xTCP.usCurMSS = ipconfigTCP_MSS;
\r
389 pxSocket->u.xTCP.uxRxStreamSize = ( size_t ) ipconfigTCP_RX_BUFFER_LENGTH;
\r
390 pxSocket->u.xTCP.uxTxStreamSize = ( size_t ) FreeRTOS_round_up( ipconfigTCP_TX_BUFFER_LENGTH, ipconfigTCP_MSS );
\r
391 /* Use half of the buffer size of the TCP windows */
\r
392 #if ( ipconfigUSE_TCP_WIN == 1 )
\r
394 pxSocket->u.xTCP.uxRxWinSize = FreeRTOS_max_uint32( 1UL, ( uint32_t ) ( pxSocket->u.xTCP.uxRxStreamSize / 2 ) / ipconfigTCP_MSS );
\r
395 pxSocket->u.xTCP.uxTxWinSize = FreeRTOS_max_uint32( 1UL, ( uint32_t ) ( pxSocket->u.xTCP.uxTxStreamSize / 2 ) / ipconfigTCP_MSS );
\r
399 pxSocket->u.xTCP.uxRxWinSize = 1u;
\r
400 pxSocket->u.xTCP.uxTxWinSize = 1u;
\r
403 /* The above values are just defaults, and can be overridden by
\r
404 calling FreeRTOS_setsockopt(). No buffers will be allocated until a
\r
405 socket is connected and data is exchanged. */
\r
408 #endif /* ipconfigUSE_TCP == 1 */
\r
411 xReturn = ( Socket_t ) pxSocket;
\r
414 /* Remove compiler warnings in the case the configASSERT() is not defined. */
\r
419 /*-----------------------------------------------------------*/
\r
421 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
423 SocketSet_t FreeRTOS_CreateSocketSet( void )
\r
425 SocketSelect_t *pxSocketSet;
\r
427 pxSocketSet = ( SocketSelect_t * ) pvPortMalloc( sizeof( *pxSocketSet ) );
\r
429 if( pxSocketSet != NULL )
\r
431 memset( pxSocketSet, '\0', sizeof( *pxSocketSet ) );
\r
432 pxSocketSet->xSelectGroup = xEventGroupCreate();
\r
434 if( pxSocketSet->xSelectGroup == NULL )
\r
436 vPortFree( ( void* ) pxSocketSet );
\r
437 pxSocketSet = NULL;
\r
441 return ( SocketSet_t * ) pxSocketSet;
\r
444 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
445 /*-----------------------------------------------------------*/
\r
447 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
449 void FreeRTOS_DeleteSocketSet( SocketSet_t xSocketSet )
\r
451 SocketSelect_t *pxSocketSet = ( SocketSelect_t*) xSocketSet;
\r
453 vEventGroupDelete( pxSocketSet->xSelectGroup );
\r
454 vPortFree( ( void* ) pxSocketSet );
\r
457 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
458 /*-----------------------------------------------------------*/
\r
460 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
462 /* Add a socket to a set */
\r
463 void FreeRTOS_FD_SET( Socket_t xSocket, SocketSet_t xSocketSet, EventBits_t xSelectBits )
\r
465 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
466 SocketSelect_t *pxSocketSet = ( SocketSelect_t * ) xSocketSet;
\r
468 configASSERT( pxSocket != NULL );
\r
469 configASSERT( xSocketSet != NULL );
\r
471 /* Make sure we're not adding bits which are reserved for internal use,
\r
472 such as eSELECT_CALL_IP */
\r
473 pxSocket->xSelectBits |= ( xSelectBits & eSELECT_ALL );
\r
475 if( ( pxSocket->xSelectBits & eSELECT_ALL ) != 0 )
\r
477 /* Adding a socket to a socket set. */
\r
478 pxSocket->pxSocketSet = ( SocketSelect_t * ) xSocketSet;
\r
480 /* Now have the IP-task call vSocketSelect() to see if the set contains
\r
481 any sockets which are 'ready' and set the proper bits.
\r
482 By setting 'bApiCalled = false', vSocketSelect() knows that it was
\r
483 not called from a user API */
\r
484 pxSocketSet->bApiCalled = pdFALSE;
\r
485 prvFindSelectedSocket( pxSocketSet );
\r
489 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
490 /*-----------------------------------------------------------*/
\r
492 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
493 /* Clear select bits for a socket
\r
494 If the mask becomes 0, remove the socket from the set */
\r
495 void FreeRTOS_FD_CLR( Socket_t xSocket, SocketSet_t xSocketSet, EventBits_t xSelectBits )
\r
497 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
499 configASSERT( pxSocket != NULL );
\r
500 configASSERT( xSocketSet != NULL );
\r
502 pxSocket->xSelectBits &= ~( xSelectBits & eSELECT_ALL );
\r
503 if( ( pxSocket->xSelectBits & eSELECT_ALL ) != 0 )
\r
505 pxSocket->pxSocketSet = ( SocketSelect_t *)xSocketSet;
\r
509 /* disconnect it from the socket set */
\r
510 pxSocket->pxSocketSet = ( SocketSelect_t *)NULL;
\r
514 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
515 /*-----------------------------------------------------------*/
\r
518 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
520 /* Test if a socket belongs to a socket-set */
\r
521 EventBits_t FreeRTOS_FD_ISSET( Socket_t xSocket, SocketSet_t xSocketSet )
\r
523 EventBits_t xReturn;
\r
524 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
526 configASSERT( pxSocket != NULL );
\r
527 configASSERT( xSocketSet != NULL );
\r
529 if( xSocketSet == ( SocketSet_t ) pxSocket->pxSocketSet )
\r
531 /* Make sure we're not adding bits which are reserved for internal
\r
533 xReturn = pxSocket->xSocketBits & eSELECT_ALL;
\r
543 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
544 /*-----------------------------------------------------------*/
\r
546 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
548 /* The select() statement: wait for an event to occur on any of the sockets
\r
549 included in a socket set */
\r
550 BaseType_t FreeRTOS_select( SocketSet_t xSocketSet, TickType_t xBlockTimeTicks )
\r
552 TimeOut_t xTimeOut;
\r
553 TickType_t xRemainingTime;
\r
554 SocketSelect_t *pxSocketSet = ( SocketSelect_t*) xSocketSet;
\r
555 BaseType_t xResult;
\r
557 configASSERT( xSocketSet != NULL );
\r
559 /* Only in the first round, check for non-blocking */
\r
560 xRemainingTime = xBlockTimeTicks;
\r
562 /* Fetch the current time */
\r
563 vTaskSetTimeOutState( &xTimeOut );
\r
567 /* Find a socket which might have triggered the bit
\r
568 This function might return immediately or block for a limited time */
\r
569 xResult = ( BaseType_t ) xEventGroupWaitBits( pxSocketSet->xSelectGroup, eSELECT_ALL, pdFALSE, pdFALSE, xRemainingTime );
\r
571 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
573 if( ( xResult & eSELECT_INTR ) != 0u )
\r
575 xEventGroupClearBits( pxSocketSet->xSelectGroup, eSELECT_INTR );
\r
576 FreeRTOS_debug_printf( ( "FreeRTOS_select: interrupted\n" ) );
\r
580 #endif /* ipconfigSUPPORT_SIGNALS */
\r
582 /* Have the IP-task find the socket which had an event */
\r
583 pxSocketSet->bApiCalled = pdTRUE;
\r
584 prvFindSelectedSocket( pxSocketSet );
\r
586 xResult = ( BaseType_t ) xEventGroupGetBits( pxSocketSet->xSelectGroup );
\r
593 /* Has the timeout been reached? */
\r
594 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
\r
603 #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
\r
604 /*-----------------------------------------------------------*/
\r
606 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
608 /* Send a message to the IP-task to have it check all sockets belonging to
\r
610 static FreeRTOS_Socket_t *prvFindSelectedSocket( SocketSelect_t *pxSocketSet )
\r
612 IPStackEvent_t xSelectEvent;
\r
613 FreeRTOS_Socket_t *xReturn;
\r
615 xSelectEvent.eEventType = eSocketSelectEvent;
\r
616 xSelectEvent.pvData = ( void * ) pxSocketSet;
\r
618 /* while the IP-task works on the request, the API will block on
\r
619 'eSELECT_CALL_IP'. So clear it first. */
\r
620 xEventGroupClearBits( pxSocketSet->xSelectGroup, eSELECT_CALL_IP );
\r
622 /* Now send the socket select event */
\r
623 if( xSendEventStructToIPTask( &xSelectEvent, ( TickType_t ) portMAX_DELAY ) == pdFAIL )
\r
625 /* Oops, we failed to wake-up the IP task. No use to wait for it. */
\r
626 FreeRTOS_debug_printf( ( "prvFindSelectedSocket: failed\n" ) );
\r
631 /* As soon as the IP-task is ready, it will set 'eSELECT_CALL_IP' to
\r
632 wakeup the calling API */
\r
633 xEventGroupWaitBits( pxSocketSet->xSelectGroup, eSELECT_CALL_IP, pdTRUE, pdFALSE, portMAX_DELAY );
\r
635 /* Return 'pxSocket' which is set by the IP-task */
\r
636 xReturn = pxSocketSet->pxSocket;
\r
642 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
643 /*-----------------------------------------------------------*/
\r
646 * FreeRTOS_recvfrom: receive data from a bound socket
\r
647 * In this library, the function can only be used with connectionsless sockets
\r
650 int32_t FreeRTOS_recvfrom( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags, struct freertos_sockaddr *pxSourceAddress, socklen_t *pxSourceAddressLength )
\r
652 BaseType_t lPacketCount = 0;
\r
653 NetworkBufferDescriptor_t *pxNetworkBuffer;
\r
654 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
655 TickType_t xRemainingTime = ( TickType_t ) 0; /* Obsolete assignment, but some compilers output a warning if its not done. */
\r
656 BaseType_t xTimed = pdFALSE;
\r
657 TimeOut_t xTimeOut;
\r
659 EventBits_t xEventBits = ( EventBits_t ) 0;
\r
661 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_UDP, pdTRUE ) == pdFALSE )
\r
663 return -pdFREERTOS_ERRNO_EINVAL;
\r
666 lPacketCount = ( BaseType_t ) listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
\r
668 /* The function prototype is designed to maintain the expected Berkeley
\r
669 sockets standard, but this implementation does not use all the parameters. */
\r
670 ( void ) pxSourceAddressLength;
\r
672 while( lPacketCount == 0 )
\r
674 if( xTimed == pdFALSE )
\r
676 /* Check to see if the socket is non blocking on the first
\r
678 xRemainingTime = pxSocket->xReceiveBlockTime;
\r
680 if( xRemainingTime == ( TickType_t ) 0 )
\r
682 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
684 /* Just check for the interrupt flag. */
\r
685 xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_INTR,
\r
686 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, socketDONT_BLOCK );
\r
688 #endif /* ipconfigSUPPORT_SIGNALS */
\r
692 if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
\r
697 /* To ensure this part only executes once. */
\r
700 /* Fetch the current time. */
\r
701 vTaskSetTimeOutState( &xTimeOut );
\r
704 /* Wait for arrival of data. While waiting, the IP-task may set the
\r
705 'eSOCKET_RECEIVE' bit in 'xEventGroup', if it receives data for this
\r
706 socket, thus unblocking this API call. */
\r
707 xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_RECEIVE | eSOCKET_INTR,
\r
708 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
710 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
712 if( ( xEventBits & eSOCKET_INTR ) != 0 )
\r
714 if( ( xEventBits & eSOCKET_RECEIVE ) != 0 )
\r
716 /* Shouldn't have cleared the eSOCKET_RECEIVE flag. */
\r
717 xEventGroupSetBits( pxSocket->xEventGroup, eSOCKET_RECEIVE );
\r
724 ( void ) xEventBits;
\r
726 #endif /* ipconfigSUPPORT_SIGNALS */
\r
728 lPacketCount = ( BaseType_t ) listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
\r
730 if( lPacketCount != 0 )
\r
735 /* Has the timeout been reached ? */
\r
736 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) )
\r
740 } /* while( lPacketCount == 0 ) */
\r
742 if( lPacketCount != 0 )
\r
744 taskENTER_CRITICAL();
\r
746 /* The owner of the list item is the network buffer. */
\r
747 pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
\r
749 if( ( xFlags & FREERTOS_MSG_PEEK ) == 0 )
\r
751 /* Remove the network buffer from the list of buffers waiting to
\r
752 be processed by the socket. */
\r
753 uxListRemove( &( pxNetworkBuffer->xBufferListItem ) );
\r
756 taskEXIT_CRITICAL();
\r
758 /* The returned value is the data length, which may have been capped to
\r
759 the receive buffer size. */
\r
760 lReturn = ( int32_t ) pxNetworkBuffer->xDataLength;
\r
762 if( pxSourceAddress != NULL )
\r
764 pxSourceAddress->sin_port = pxNetworkBuffer->usPort;
\r
765 pxSourceAddress->sin_addr = pxNetworkBuffer->ulIPAddress;
\r
768 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
\r
770 /* The zero copy flag is not set. Truncate the length if it won't
\r
771 fit in the provided buffer. */
\r
772 if( lReturn > ( int32_t ) xBufferLength )
\r
774 iptraceRECVFROM_DISCARDING_BYTES( ( xBufferLength - lReturn ) );
\r
775 lReturn = ( int32_t )xBufferLength;
\r
778 /* Copy the received data into the provided buffer, then release the
\r
780 memcpy( pvBuffer, ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ), ( size_t )lReturn );
\r
782 if( ( xFlags & FREERTOS_MSG_PEEK ) == 0 )
\r
784 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
\r
789 /* The zero copy flag was set. pvBuffer is not a buffer into which
\r
790 the received data can be copied, but a pointer that must be set to
\r
791 point to the buffer in which the received data has already been
\r
793 *( ( void** ) pvBuffer ) = ( void * ) ( &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ) );
\r
797 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
798 else if( ( xEventBits & eSOCKET_INTR ) != 0 )
\r
800 lReturn = -pdFREERTOS_ERRNO_EINTR;
\r
801 iptraceRECVFROM_INTERRUPTED();
\r
803 #endif /* ipconfigSUPPORT_SIGNALS */
\r
806 lReturn = -pdFREERTOS_ERRNO_EWOULDBLOCK;
\r
807 iptraceRECVFROM_TIMEOUT();
\r
812 /*-----------------------------------------------------------*/
\r
814 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
816 NetworkBufferDescriptor_t *pxNetworkBuffer;
\r
817 IPStackEvent_t xStackTxEvent = { eStackTxEvent, NULL };
\r
818 TimeOut_t xTimeOut;
\r
819 TickType_t xTicksToWait;
\r
820 int32_t lReturn = 0;
\r
821 FreeRTOS_Socket_t *pxSocket;
\r
823 pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
825 /* The function prototype is designed to maintain the expected Berkeley
\r
826 sockets standard, but this implementation does not use all the
\r
828 ( void ) xDestinationAddressLength;
\r
829 configASSERT( pvBuffer );
\r
831 if( xTotalDataLength <= ( size_t ) ipMAX_UDP_PAYLOAD_LENGTH )
\r
833 /* If the socket is not already bound to an address, bind it now.
\r
834 Passing NULL as the address parameter tells FreeRTOS_bind() to select
\r
835 the address to bind to. */
\r
836 if( ( socketSOCKET_IS_BOUND( pxSocket ) != pdFALSE ) ||
\r
837 ( FreeRTOS_bind( xSocket, NULL, 0u ) == 0 ) )
\r
839 xTicksToWait = pxSocket->xSendBlockTime;
\r
841 #if( ipconfigUSE_CALLBACKS != 0 )
\r
843 if( xIsCallingFromIPTask() != pdFALSE )
\r
845 /* If this send function is called from within a call-back
\r
846 handler it may not block, otherwise chances would be big to
\r
847 get a deadlock: the IP-task waiting for itself. */
\r
848 xTicksToWait = ( TickType_t )0;
\r
851 #endif /* ipconfigUSE_CALLBACKS */
\r
853 if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
\r
855 xTicksToWait = ( TickType_t ) 0;
\r
858 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
\r
860 /* Zero copy is not set, so obtain a network buffer into
\r
861 which the payload will be copied. */
\r
862 vTaskSetTimeOutState( &xTimeOut );
\r
864 /* Block until a buffer becomes available, or until a
\r
865 timeout has been reached */
\r
866 pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( xTotalDataLength + sizeof( UDPPacket_t ), xTicksToWait );
\r
868 if( pxNetworkBuffer != NULL )
\r
870 memcpy( ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ), ( void * ) pvBuffer, xTotalDataLength );
\r
872 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdTRUE )
\r
874 /* The entire block time has been used up. */
\r
875 xTicksToWait = ( TickType_t ) 0;
\r
881 /* When zero copy is used, pvBuffer is a pointer to the
\r
882 payload of a buffer that has already been obtained from the
\r
883 stack. Obtain the network buffer pointer from the buffer. */
\r
884 pxNetworkBuffer = pxUDPPayloadBuffer_to_NetworkBuffer( (void*)pvBuffer );
\r
887 if( pxNetworkBuffer != NULL )
\r
889 pxNetworkBuffer->xDataLength = xTotalDataLength;
\r
890 pxNetworkBuffer->usPort = pxDestinationAddress->sin_port;
\r
891 pxNetworkBuffer->usBoundPort = ( uint16_t ) socketGET_SOCKET_PORT( pxSocket );
\r
892 pxNetworkBuffer->ulIPAddress = pxDestinationAddress->sin_addr;
\r
894 /* The socket options are passed to the IP layer in the
\r
895 space that will eventually get used by the Ethernet header. */
\r
896 pxNetworkBuffer->pucEthernetBuffer[ ipSOCKET_OPTIONS_OFFSET ] = pxSocket->ucSocketOptions;
\r
898 /* Tell the networking task that the packet needs sending. */
\r
899 xStackTxEvent.pvData = pxNetworkBuffer;
\r
901 /* Ask the IP-task to send this packet */
\r
902 if( xSendEventStructToIPTask( &xStackTxEvent, xTicksToWait ) == pdPASS )
\r
904 /* The packet was successfully sent to the IP task. */
\r
905 lReturn = ( int32_t ) xTotalDataLength;
\r
906 #if( ipconfigUSE_CALLBACKS == 1 )
\r
908 if( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xUDP.pxHandleSent ) )
\r
910 pxSocket->u.xUDP.pxHandleSent( (Socket_t *)pxSocket, xTotalDataLength );
\r
913 #endif /* ipconfigUSE_CALLBACKS */
\r
917 /* If the buffer was allocated in this function, release
\r
919 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
\r
921 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
\r
923 iptraceSTACK_TX_EVENT_LOST( ipSTACK_TX_EVENT );
\r
928 /* If errno was available, errno would be set to
\r
929 FREERTOS_ENOPKTS. As it is, the function must return the
\r
930 number of transmitted bytes, so the calling function knows
\r
931 how much data was actually sent. */
\r
932 iptraceNO_BUFFER_FOR_SENDTO();
\r
937 iptraceSENDTO_SOCKET_NOT_BOUND();
\r
942 /* The data is longer than the available buffer space. */
\r
943 iptraceSENDTO_DATA_TOO_LONG();
\r
948 /*-----------------------------------------------------------*/
\r
951 * FreeRTOS_bind() : binds a sockt to a local port number. If port 0 is
\r
952 * provided, a system provided port number will be assigned. This function can
\r
953 * be used for both UDP and TCP sockets. The actual binding will be performed
\r
954 * by the IP-task to avoid mutual access to the bound-socket-lists
\r
955 * (xBoundUDPSocketsList or xBoundTCPSocketsList).
\r
957 BaseType_t FreeRTOS_bind( Socket_t xSocket, struct freertos_sockaddr * pxAddress, socklen_t xAddressLength )
\r
959 IPStackEvent_t xBindEvent;
\r
960 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
961 BaseType_t xReturn = 0;
\r
963 ( void ) xAddressLength;
\r
965 if( ( pxSocket == NULL ) || ( pxSocket == FREERTOS_INVALID_SOCKET ) )
\r
967 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
969 /* Once a socket is bound to a port, it can not be bound to a different
\r
971 else if( socketSOCKET_IS_BOUND( pxSocket) != pdFALSE )
\r
973 /* The socket is already bound. */
\r
974 FreeRTOS_debug_printf( ( "vSocketBind: Socket already bound to %d\n", pxSocket->usLocalPort ) );
\r
975 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
979 /* Prepare a messages to the IP-task in order to perform the binding.
\r
980 The desired port number will be passed in usLocalPort. */
\r
981 xBindEvent.eEventType = eSocketBindEvent;
\r
982 xBindEvent.pvData = ( void * ) xSocket;
\r
983 if( pxAddress != NULL )
\r
985 pxSocket->usLocalPort = FreeRTOS_ntohs( pxAddress->sin_port );
\r
989 /* Caller wants to bind to a random port number. */
\r
990 pxSocket->usLocalPort = 0u;
\r
993 /* portMAX_DELAY is used as a the time-out parameter, as binding *must*
\r
994 succeed before the socket can be used. _RB_ The use of an infinite
\r
995 block time needs be changed as it could result in the task hanging. */
\r
996 if( xSendEventStructToIPTask( &xBindEvent, ( TickType_t ) portMAX_DELAY ) == pdFAIL )
\r
998 /* Failed to wake-up the IP-task, no use to wait for it */
\r
999 FreeRTOS_debug_printf( ( "FreeRTOS_bind: send event failed\n" ) );
\r
1000 xReturn = -pdFREERTOS_ERRNO_ECANCELED;
\r
1004 /* The IP-task will set the 'eSOCKET_BOUND' bit when it has done its
\r
1006 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_BOUND, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, portMAX_DELAY );
\r
1007 if( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE )
\r
1009 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
1018 * vSocketBind(): internal version of bind() that should not be called directly.
\r
1019 * 'xInternal' is used for TCP sockets only: it allows to have several
\r
1020 * (connected) child sockets bound to the same server port.
\r
1022 BaseType_t vSocketBind( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr * pxAddress, size_t uxAddressLength, BaseType_t xInternal )
\r
1024 BaseType_t xReturn = 0; /* In Berkeley sockets, 0 means pass for bind(). */
\r
1025 List_t *pxSocketList;
\r
1026 #if( ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 )
\r
1027 struct freertos_sockaddr xAddress;
\r
1028 #endif /* ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND */
\r
1030 #if( ipconfigUSE_TCP == 1 )
\r
1031 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1033 pxSocketList = &xBoundTCPSocketsList;
\r
1036 #endif /* ipconfigUSE_TCP == 1 */
\r
1038 pxSocketList = &xBoundUDPSocketsList;
\r
1041 /* The function prototype is designed to maintain the expected Berkeley
\r
1042 sockets standard, but this implementation does not use all the parameters. */
\r
1043 ( void ) uxAddressLength;
\r
1045 configASSERT( pxSocket );
\r
1046 configASSERT( pxSocket != FREERTOS_INVALID_SOCKET );
\r
1048 #if( ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 )
\r
1050 /* pxAddress will be NULL if sendto() was called on a socket without the
\r
1051 socket being bound to an address. In this case, automatically allocate
\r
1052 an address to the socket. There is a very tiny chance that the allocated
\r
1053 port will already be in use - if that is the case, then the check below
\r
1054 [pxListFindListItemWithValue()] will result in an error being returned. */
\r
1055 if( pxAddress == NULL )
\r
1057 pxAddress = &xAddress;
\r
1058 /* For now, put it to zero, will be assigned later */
\r
1059 pxAddress->sin_port = 0u;
\r
1062 #endif /* ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 */
\r
1064 /* Sockets must be bound before calling FreeRTOS_sendto() if
\r
1065 ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is not set to 1. */
\r
1066 configASSERT( pxAddress );
\r
1068 if( pxAddress != NULL )
\r
1070 if( pxAddress->sin_port == 0u )
\r
1072 pxAddress->sin_port = prvGetPrivatePortNumber( ( BaseType_t ) pxSocket->ucProtocol );
\r
1075 /* If vSocketBind() is called from the API FreeRTOS_bind() it has been
\r
1076 confirmed that the socket was not yet bound to a port. If it is called
\r
1077 from the IP-task, no such check is necessary. */
\r
1079 /* Check to ensure the port is not already in use. If the bind is
\r
1080 called internally, a port MAY be used by more than one socket. */
\r
1081 if( ( ( xInternal == pdFALSE ) || ( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP ) ) &&
\r
1082 ( pxListFindListItemWithValue( pxSocketList, ( TickType_t ) pxAddress->sin_port ) != NULL ) )
\r
1084 FreeRTOS_debug_printf( ( "vSocketBind: %sP port %d in use\n",
\r
1085 pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP ? "TC" : "UD",
\r
1086 FreeRTOS_ntohs( pxAddress->sin_port ) ) );
\r
1087 xReturn = -pdFREERTOS_ERRNO_EADDRINUSE;
\r
1091 /* Allocate the port number to the socket.
\r
1092 This macro will set 'xBoundSocketListItem->xItemValue' */
\r
1093 socketSET_SOCKET_PORT( pxSocket, pxAddress->sin_port );
\r
1095 /* And also store it in a socket field 'usLocalPort' in host-byte-order,
\r
1096 mostly used for logging and debugging purposes */
\r
1097 pxSocket->usLocalPort = FreeRTOS_ntohs( pxAddress->sin_port );
\r
1099 /* Add the socket to the list of bound ports. */
\r
1101 /* If the network driver can iterate through 'xBoundUDPSocketsList',
\r
1102 by calling xPortHasUDPSocket() then the IP-task must temporarily
\r
1103 suspend the scheduler to keep the list in a consistent state. */
\r
1104 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1106 vTaskSuspendAll();
\r
1108 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1110 /* Add the socket to 'xBoundUDPSocketsList' or 'xBoundTCPSocketsList' */
\r
1111 vListInsertEnd( pxSocketList, &( pxSocket->xBoundSocketListItem ) );
\r
1113 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1117 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1123 xReturn = -pdFREERTOS_ERRNO_EADDRNOTAVAIL;
\r
1124 FreeRTOS_debug_printf( ( "vSocketBind: Socket no addr\n" ) );
\r
1127 if( xReturn != 0 )
\r
1129 iptraceBIND_FAILED( xSocket, ( FreeRTOS_ntohs( pxAddress->sin_port ) ) );
\r
1134 /*-----------------------------------------------------------*/
\r
1137 * Close a socket and free the allocated space
\r
1138 * In case of a TCP socket: the connection will not be closed automatically
\r
1139 * Subsequent messages for the closed socket will be responded to with a RST
\r
1140 * The IP-task will actually close the socket, after receiving a 'eSocketCloseEvent' message
\r
1142 BaseType_t FreeRTOS_closesocket( Socket_t xSocket )
\r
1144 BaseType_t xResult;
\r
1145 #if( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 )
\r
1146 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * )xSocket;
\r
1148 IPStackEvent_t xCloseEvent;
\r
1149 xCloseEvent.eEventType = eSocketCloseEvent;
\r
1150 xCloseEvent.pvData = ( void * ) xSocket;
\r
1152 if( ( xSocket == NULL ) || ( xSocket == FREERTOS_INVALID_SOCKET ) )
\r
1158 #if( ( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 ) )
\r
1160 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1162 /* Make sure that IP-task won't call the user callback's anymore */
\r
1163 pxSocket->u.xTCP.pxHandleConnected = NULL;
\r
1164 pxSocket->u.xTCP.pxHandleReceive = NULL;
\r
1165 pxSocket->u.xTCP.pxHandleSent = NULL;
\r
1168 #endif /* ( ( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 ) ) */
\r
1170 /* Let the IP task close the socket to keep it synchronised with the
\r
1171 packet handling. */
\r
1173 /* Note when changing the time-out value below, it must be checked who is calling
\r
1174 this function. If it is called by the IP-task, a deadlock could occur.
\r
1175 The IP-task would only call it in case of a user call-back */
\r
1176 if( xSendEventStructToIPTask( &xCloseEvent, ( TickType_t ) 0 ) == pdFAIL )
\r
1178 FreeRTOS_debug_printf( ( "FreeRTOS_closesocket: failed\n" ) );
\r
1190 /* This is the internal version of FreeRTOS_closesocket()
\r
1191 * It will be called by the IPtask only to avoid problems with synchronicity
\r
1193 void *vSocketClose( FreeRTOS_Socket_t *pxSocket )
\r
1195 NetworkBufferDescriptor_t *pxNetworkBuffer;
\r
1197 #if( ipconfigUSE_TCP == 1 )
\r
1199 /* For TCP: clean up a little more. */
\r
1200 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1202 #if( ipconfigUSE_TCP_WIN == 1 )
\r
1204 if( pxSocket->u.xTCP.pxAckMessage != NULL )
\r
1206 vReleaseNetworkBufferAndDescriptor( pxSocket->u.xTCP.pxAckMessage );
\r
1208 /* Free the resources which were claimed by the tcpWin member */
\r
1209 vTCPWindowDestroy( &pxSocket->u.xTCP.xTCPWindow );
\r
1211 #endif /* ipconfigUSE_TCP_WIN */
\r
1213 /* Free the input and output streams */
\r
1214 if( pxSocket->u.xTCP.rxStream != NULL )
\r
1216 vPortFreeLarge( pxSocket->u.xTCP.rxStream );
\r
1219 if( pxSocket->u.xTCP.txStream != NULL )
\r
1221 vPortFreeLarge( pxSocket->u.xTCP.txStream );
\r
1224 /* In case this is a child socket, make sure the child-count of the
\r
1225 parent socket is decreased. */
\r
1226 prvTCPSetSocketCount( pxSocket );
\r
1229 #endif /* ipconfigUSE_TCP == 1 */
\r
1231 /* Socket must be unbound first, to ensure no more packets are queued on
\r
1233 if( socketSOCKET_IS_BOUND( pxSocket ) != pdFALSE )
\r
1235 /* If the network driver can iterate through 'xBoundUDPSocketsList',
\r
1236 by calling xPortHasUDPSocket(), then the IP-task must temporarily
\r
1237 suspend the scheduler to keep the list in a consistent state. */
\r
1238 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1240 vTaskSuspendAll();
\r
1242 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1244 uxListRemove( &( pxSocket->xBoundSocketListItem ) );
\r
1246 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1250 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1253 /* Now the socket is not bound the list of waiting packets can be
\r
1255 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_UDP )
\r
1257 while( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) > 0U )
\r
1259 pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
\r
1260 uxListRemove( &( pxNetworkBuffer->xBufferListItem ) );
\r
1261 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
\r
1265 if( pxSocket->xEventGroup )
\r
1267 vEventGroupDelete( pxSocket->xEventGroup );
\r
1270 #if( ipconfigUSE_TCP == 1 ) && ( ipconfigHAS_DEBUG_PRINTF != 0 )
\r
1272 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1274 FreeRTOS_debug_printf( ( "FreeRTOS_closesocket[%u to %lxip:%u]: buffers %lu socks %lu\n",
\r
1275 pxSocket->usLocalPort,
\r
1276 pxSocket->u.xTCP.ulRemoteIP,
\r
1277 pxSocket->u.xTCP.usRemotePort,
\r
1278 uxGetNumberOfFreeNetworkBuffers(),
\r
1279 listCURRENT_LIST_LENGTH( &xBoundTCPSocketsList ) ) );
\r
1282 #endif /* ( ipconfigUSE_TCP == 1 ) && ( ipconfigHAS_DEBUG_PRINTF != 0 ) */
\r
1284 /* Anf finally, after all resources have been freed, free the socket space */
\r
1285 vPortFreeSocket( pxSocket );
\r
1290 /*-----------------------------------------------------------*/
\r
1292 #if ipconfigUSE_TCP == 1
\r
1295 * When a child socket gets closed, make sure to update the child-count of the
\r
1296 * parent. When a listening parent socket is closed, make sure no child-sockets
\r
1297 * keep a pointer to it.
\r
1299 static void prvTCPSetSocketCount( FreeRTOS_Socket_t *pxSocketToDelete )
\r
1301 const ListItem_t *pxIterator;
\r
1302 const MiniListItem_t *pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );
\r
1303 FreeRTOS_Socket_t *pxOtherSocket;
\r
1304 uint16_t usLocalPort = pxSocketToDelete->usLocalPort;
\r
1306 for( pxIterator = ( const ListItem_t * ) listGET_NEXT( pxEnd );
\r
1307 pxIterator != ( const ListItem_t * ) pxEnd;
\r
1308 pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
1310 pxOtherSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
\r
1311 if( ( pxOtherSocket->u.xTCP.ucTCPState == eTCP_LISTEN ) &&
\r
1312 ( pxOtherSocket->usLocalPort == usLocalPort ) &&
\r
1313 ( pxOtherSocket->u.xTCP.usChildCount ) )
\r
1315 pxOtherSocket->u.xTCP.usChildCount--;
\r
1316 FreeRTOS_debug_printf( ( "Lost: Socket %u now has %u / %u child%s\n",
\r
1317 pxOtherSocket->usLocalPort,
\r
1318 pxOtherSocket->u.xTCP.usChildCount,
\r
1319 pxOtherSocket->u.xTCP.usBacklog,
\r
1320 pxOtherSocket->u.xTCP.usChildCount == 1u ? "" : "ren" ) );
\r
1326 #endif /* ipconfigUSE_TCP == 1 */
\r
1328 /*-----------------------------------------------------------*/
\r
1330 BaseType_t FreeRTOS_setsockopt( Socket_t xSocket, int32_t lLevel, int32_t lOptionName, const void *pvOptionValue, size_t xOptionLength )
\r
1332 /* The standard Berkeley function returns 0 for success. */
\r
1333 BaseType_t xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
1334 BaseType_t lOptionValue;
\r
1335 FreeRTOS_Socket_t *pxSocket;
\r
1337 pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
1339 /* The function prototype is designed to maintain the expected Berkeley
\r
1340 sockets standard, but this implementation does not use all the parameters. */
\r
1342 ( void ) xOptionLength;
\r
1344 configASSERT( xSocket );
\r
1346 switch( lOptionName )
\r
1348 case FREERTOS_SO_RCVTIMEO :
\r
1349 /* Receive time out. */
\r
1350 pxSocket->xReceiveBlockTime = *( ( TickType_t * ) pvOptionValue );
\r
1354 case FREERTOS_SO_SNDTIMEO :
\r
1355 pxSocket->xSendBlockTime = *( ( TickType_t * ) pvOptionValue );
\r
1356 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_UDP )
\r
1358 /* The send time out is capped for the reason stated in the
\r
1359 comments where ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS is defined
\r
1360 in FreeRTOSIPConfig.h (assuming an official configuration file
\r
1362 if( pxSocket->xSendBlockTime > ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS )
\r
1364 pxSocket->xSendBlockTime = ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS;
\r
1369 /* For TCP socket, it isn't necessary to limit the blocking time
\r
1370 because the FreeRTOS_send() function does not wait for a network
\r
1371 buffer to become available. */
\r
1375 #if( ipconfigUDP_MAX_RX_PACKETS > 0 )
\r
1376 case FREERTOS_SO_UDP_MAX_RX_PACKETS:
\r
1377 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_UDP )
\r
1379 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1381 pxSocket->u.xUDP.uxMaxPackets = *( ( UBaseType_t * ) pvOptionValue );
\r
1384 #endif /* ipconfigUDP_MAX_RX_PACKETS */
\r
1386 case FREERTOS_SO_UDPCKSUM_OUT :
\r
1387 /* Turn calculating of the UDP checksum on/off for this socket. */
\r
1388 lOptionValue = ( BaseType_t ) pvOptionValue;
\r
1390 if( lOptionValue == 0 )
\r
1392 pxSocket->ucSocketOptions &= ( uint8_t ) ~FREERTOS_SO_UDPCKSUM_OUT;
\r
1396 pxSocket->ucSocketOptions |= ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT;
\r
1401 #if( ipconfigUSE_CALLBACKS == 1 )
\r
1402 #if( ipconfigUSE_TCP == 1 )
\r
1403 case FREERTOS_SO_TCP_CONN_HANDLER: /* Set a callback for (dis)connection events */
\r
1404 case FREERTOS_SO_TCP_RECV_HANDLER: /* Install a callback for receiving TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
\r
1405 case FREERTOS_SO_TCP_SENT_HANDLER: /* Install a callback for sending TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
\r
1406 #endif /* ipconfigUSE_TCP */
\r
1407 case FREERTOS_SO_UDP_RECV_HANDLER: /* Install a callback for receiving UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
\r
1408 case FREERTOS_SO_UDP_SENT_HANDLER: /* Install a callback for sending UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
\r
1410 #if( ipconfigUSE_TCP == 1 )
\r
1412 UBaseType_t uxProtocol;
\r
1413 if( ( lOptionName == FREERTOS_SO_UDP_RECV_HANDLER ) ||
\r
1414 ( lOptionName == FREERTOS_SO_UDP_SENT_HANDLER ) )
\r
1416 uxProtocol = ( UBaseType_t ) FREERTOS_IPPROTO_UDP;
\r
1420 uxProtocol = ( UBaseType_t ) FREERTOS_IPPROTO_TCP;
\r
1423 if( pxSocket->ucProtocol != ( uint8_t ) uxProtocol )
\r
1425 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1430 /* No need to check if the socket has the right
\r
1431 protocol, because only UDP socket can be created. */
\r
1433 #endif /* ipconfigUSE_TCP */
\r
1435 switch( lOptionName )
\r
1437 #if ipconfigUSE_TCP == 1
\r
1438 case FREERTOS_SO_TCP_CONN_HANDLER:
\r
1439 pxSocket->u.xTCP.pxHandleConnected = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPConnected;
\r
1441 case FREERTOS_SO_TCP_RECV_HANDLER:
\r
1442 pxSocket->u.xTCP.pxHandleReceive = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPReceive;
\r
1444 case FREERTOS_SO_TCP_SENT_HANDLER:
\r
1445 pxSocket->u.xTCP.pxHandleSent = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPSent;
\r
1447 #endif /* ipconfigUSE_TCP */
\r
1448 case FREERTOS_SO_UDP_RECV_HANDLER:
\r
1449 pxSocket->u.xUDP.pxHandleReceive = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnUDPReceive;
\r
1451 case FREERTOS_SO_UDP_SENT_HANDLER:
\r
1452 pxSocket->u.xUDP.pxHandleSent = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnUDPSent;
\r
1461 #endif /* ipconfigUSE_CALLBACKS */
\r
1463 #if( ipconfigUSE_TCP != 0 )
\r
1464 #if( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 )
\r
1465 /* Each socket has a semaphore on which the using task normally
\r
1467 case FREERTOS_SO_SET_SEMAPHORE:
\r
1469 pxSocket->pxUserSemaphore = *( ( SemaphoreHandle_t * ) pvOptionValue );
\r
1473 #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
\r
1474 case FREERTOS_SO_SNDBUF: /* Set the size of the send buffer, in units of MSS (TCP only) */
\r
1475 case FREERTOS_SO_RCVBUF: /* Set the size of the receive buffer, in units of MSS (TCP only) */
\r
1477 uint32_t ulNewValue;
\r
1479 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1481 FreeRTOS_debug_printf( ( "Set SO_%sBUF: wrong socket type\n",
\r
1482 ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );
\r
1483 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1486 if( ( ( lOptionName == FREERTOS_SO_SNDBUF ) && ( pxSocket->u.xTCP.txStream != NULL ) ) ||
\r
1487 ( ( lOptionName == FREERTOS_SO_RCVBUF ) && ( pxSocket->u.xTCP.rxStream != NULL ) ) )
\r
1489 FreeRTOS_debug_printf( ( "Set SO_%sBUF: buffer already created\n",
\r
1490 ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );
\r
1491 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1494 ulNewValue = *( ( uint32_t * ) pvOptionValue );
\r
1496 if( lOptionName == FREERTOS_SO_SNDBUF )
\r
1498 /* Round up to nearest MSS size */
\r
1499 ulNewValue = FreeRTOS_round_up( ulNewValue, ( uint32_t ) pxSocket->u.xTCP.usInitMSS );
\r
1500 pxSocket->u.xTCP.uxTxStreamSize = ulNewValue;
\r
1504 pxSocket->u.xTCP.uxRxStreamSize = ulNewValue;
\r
1510 case FREERTOS_SO_WIN_PROPERTIES: /* Set all buffer and window properties in one call, parameter is pointer to WinProperties_t */
\r
1512 WinProperties_t* pxProps;
\r
1514 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1516 FreeRTOS_debug_printf( ( "Set SO_WIN_PROP: wrong socket type\n" ) );
\r
1517 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1520 if( ( pxSocket->u.xTCP.txStream != NULL ) || ( pxSocket->u.xTCP.rxStream != NULL ) )
\r
1522 FreeRTOS_debug_printf( ( "Set SO_WIN_PROP: buffer already created\n" ) );
\r
1523 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1526 pxProps = ( ( WinProperties_t * ) pvOptionValue );
\r
1527 FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDBUF, &( pxProps->lTxBufSize ), sizeof( pxProps->lTxBufSize ) );
\r
1528 FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVBUF, &( pxProps->lRxBufSize ), sizeof( pxProps->lRxBufSize ) );
\r
1529 #if( ipconfigUSE_TCP_WIN == 1 )
\r
1531 pxSocket->u.xTCP.uxRxWinSize = ( uint32_t )pxProps->lRxWinSize; /* Fixed value: size of the TCP reception window */
\r
1532 pxSocket->u.xTCP.uxTxWinSize = ( uint32_t )pxProps->lTxWinSize; /* Fixed value: size of the TCP transmit window */
\r
1536 pxSocket->u.xTCP.uxRxWinSize = 1u;
\r
1537 pxSocket->u.xTCP.uxTxWinSize = 1u;
\r
1541 /* In case the socket has already initialised its tcpWin,
\r
1542 adapt the window size parameters */
\r
1543 if( pxSocket->u.xTCP.xTCPWindow.u.bits.bHasInit != pdFALSE_UNSIGNED )
\r
1545 pxSocket->u.xTCP.xTCPWindow.xSize.ulRxWindowLength = pxSocket->u.xTCP.uxRxWinSize * pxSocket->u.xTCP.usInitMSS;
\r
1546 pxSocket->u.xTCP.xTCPWindow.xSize.ulRxWindowLength = pxSocket->u.xTCP.uxTxWinSize * pxSocket->u.xTCP.usInitMSS;
\r
1553 case FREERTOS_SO_REUSE_LISTEN_SOCKET: /* If true, the server-socket will turn into a connected socket */
\r
1555 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1557 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1559 if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
\r
1561 pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE_UNSIGNED;
\r
1565 pxSocket->u.xTCP.bits.bReuseSocket = pdFALSE_UNSIGNED;
\r
1571 case FREERTOS_SO_CLOSE_AFTER_SEND: /* As soon as the last byte has been transmitted, finalise the connection */
\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.bits.bCloseAfterSend = pdTRUE_UNSIGNED;
\r
1584 pxSocket->u.xTCP.bits.bCloseAfterSend = pdFALSE_UNSIGNED;
\r
1590 case FREERTOS_SO_SET_FULL_SIZE: /* Refuse to send packets smaller than MSS */
\r
1592 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1594 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1597 if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
\r
1599 pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdTRUE_UNSIGNED;
\r
1603 pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdFALSE_UNSIGNED;
\r
1606 if( ( pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize == pdFALSE_UNSIGNED ) &&
\r
1607 ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) &&
\r
1608 ( FreeRTOS_outstanding( pxSocket ) != 0 ) )
\r
1610 pxSocket->u.xTCP.usTimeout = 1u; /* to set/clear bSendFullSize */
\r
1611 xSendEventToIPTask( eTCPTimerEvent );
\r
1617 case FREERTOS_SO_STOP_RX: /* Refuse to receive more packts */
\r
1619 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1621 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1624 if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
\r
1626 pxSocket->u.xTCP.bits.bRxStopped = pdTRUE_UNSIGNED;
\r
1630 pxSocket->u.xTCP.bits.bRxStopped = pdFALSE_UNSIGNED;
\r
1633 pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
\r
1634 pxSocket->u.xTCP.usTimeout = 1u; /* to set/clear bRxStopped */
\r
1635 xSendEventToIPTask( eTCPTimerEvent );
\r
1640 #endif /* ipconfigUSE_TCP == 1 */
\r
1643 /* No other options are handled. */
\r
1644 xReturn = -pdFREERTOS_ERRNO_ENOPROTOOPT;
\r
1651 /*-----------------------------------------------------------*/
\r
1653 /* Get a free private ('anonymous') port number */
\r
1654 static uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol )
\r
1656 uint16_t usResult;
\r
1657 BaseType_t xIndex;
\r
1658 const List_t *pxList;
\r
1660 #if ipconfigUSE_TCP == 1
\r
1661 if( xProtocol == ( BaseType_t ) FREERTOS_IPPROTO_TCP )
\r
1663 xIndex = socketNEXT_TCP_PORT_NUMBER_INDEX;
\r
1664 pxList = &xBoundTCPSocketsList;
\r
1669 xIndex = socketNEXT_UDP_PORT_NUMBER_INDEX;
\r
1670 pxList = &xBoundUDPSocketsList;
\r
1673 /* Avoid compiler warnings if ipconfigUSE_TCP is not defined. */
\r
1674 ( void ) xProtocol;
\r
1676 /* Assign the next port in the range. Has it overflowed? */
\r
1677 /*_RB_ This needs to be randomised rather than sequential. */
\r
1678 /* _HT_ Agreed, although many OS's use sequential port numbers, see
\r
1679 https://www.cymru.com/jtk/misc/ephemeralports.html */
\r
1682 ++( usNextPortToUse[ xIndex ] );
\r
1684 if( usNextPortToUse[ xIndex ] >= socketAUTO_PORT_ALLOCATION_MAX_NUMBER )
\r
1686 /* Don't go right back to the start of the dynamic/private port
\r
1687 range numbers as any persistent sockets are likely to have been
\r
1688 create first so the early port numbers may still be in use. */
\r
1689 usNextPortToUse[ xIndex ] = socketAUTO_PORT_ALLOCATION_RESET_NUMBER;
\r
1692 usResult = FreeRTOS_htons( usNextPortToUse[ xIndex ] );
\r
1694 if( pxListFindListItemWithValue( pxList, ( TickType_t ) usResult ) == NULL )
\r
1701 /*-----------------------------------------------------------*/
\r
1703 /* pxListFindListItemWithValue: find a list item in a bound socket list
\r
1704 'xWantedItemValue' refers to a port number */
\r
1705 static const ListItem_t * pxListFindListItemWithValue( const List_t *pxList, TickType_t xWantedItemValue )
\r
1707 const ListItem_t * pxResult = NULL;
\r
1709 if( ( xIPIsNetworkTaskReady() != pdFALSE ) && ( pxList != NULL ) )
\r
1711 const ListItem_t *pxIterator;
\r
1712 const MiniListItem_t *pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( pxList );
\r
1713 for( pxIterator = ( const ListItem_t * ) listGET_NEXT( pxEnd );
\r
1714 pxIterator != ( const ListItem_t * ) pxEnd;
\r
1715 pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
1717 if( listGET_LIST_ITEM_VALUE( pxIterator ) == xWantedItemValue )
\r
1719 pxResult = pxIterator;
\r
1728 /*-----------------------------------------------------------*/
\r
1730 FreeRTOS_Socket_t *pxUDPSocketLookup( UBaseType_t uxLocalPort )
\r
1732 const ListItem_t *pxListItem;
\r
1733 FreeRTOS_Socket_t *pxSocket = NULL;
\r
1735 /* Looking up a socket is quite simple, find a match with the local port.
\r
1737 See if there is a list item associated with the port number on the
\r
1738 list of bound sockets. */
\r
1739 pxListItem = pxListFindListItemWithValue( &xBoundUDPSocketsList, ( TickType_t ) uxLocalPort );
\r
1741 if( pxListItem != NULL )
\r
1743 /* The owner of the list item is the socket itself. */
\r
1744 pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxListItem );
\r
1745 configASSERT( pxSocket != NULL );
\r
1750 /*-----------------------------------------------------------*/
\r
1752 #if ipconfigINCLUDE_FULL_INET_ADDR == 1
\r
1754 uint32_t FreeRTOS_inet_addr( const char * pcIPAddress )
\r
1756 const uint32_t ulDecimalBase = 10u;
\r
1757 uint8_t ucOctet[ socketMAX_IP_ADDRESS_OCTETS ];
\r
1758 const char *pcPointerOnEntering;
\r
1759 uint32_t ulReturn = 0UL, ulValue;
\r
1760 UBaseType_t uxOctetNumber;
\r
1761 BaseType_t xResult = pdPASS;
\r
1763 for( uxOctetNumber = 0u; uxOctetNumber < socketMAX_IP_ADDRESS_OCTETS; uxOctetNumber++ )
\r
1766 pcPointerOnEntering = pcIPAddress;
\r
1768 while( ( *pcIPAddress >= '0' ) && ( *pcIPAddress <= '9' ) )
\r
1770 /* Move previous read characters into the next decimal
\r
1772 ulValue *= ulDecimalBase;
\r
1774 /* Add the binary value of the ascii character. */
\r
1775 ulValue += ( ( uint32_t ) ( *pcIPAddress ) - ( uint32_t ) '0' );
\r
1777 /* Move to next character in the string. */
\r
1781 /* Check characters were read. */
\r
1782 if( pcIPAddress == pcPointerOnEntering )
\r
1787 /* Check the value fits in an 8-bit number. */
\r
1788 if( ulValue > 0xffUL )
\r
1794 ucOctet[ uxOctetNumber ] = ( uint8_t ) ulValue;
\r
1796 /* Check the next character is as expected. */
\r
1797 if( uxOctetNumber < ( socketMAX_IP_ADDRESS_OCTETS - 1u ) )
\r
1799 if( *pcIPAddress != '.' )
\r
1805 /* Move past the dot. */
\r
1811 if( xResult == pdFAIL )
\r
1813 /* No point going on. */
\r
1818 if( *pcIPAddress != ( char ) 0 )
\r
1820 /* Expected the end of the string. */
\r
1824 if( uxOctetNumber != socketMAX_IP_ADDRESS_OCTETS )
\r
1826 /* Didn't read enough octets. */
\r
1830 if( xResult == pdPASS )
\r
1832 ulReturn = FreeRTOS_inet_addr_quick( ucOctet[ 0 ], ucOctet[ 1 ], ucOctet[ 2 ], ucOctet[ 3 ] );
\r
1838 #endif /* ipconfigINCLUDE_FULL_INET_ADDR */
\r
1840 /*-----------------------------------------------------------*/
\r
1842 /* Function to get the local address and IP port */
\r
1843 size_t FreeRTOS_GetLocalAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress )
\r
1845 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
1847 /* IP address of local machine. */
\r
1848 pxAddress->sin_addr = *ipLOCAL_IP_ADDRESS_POINTER;
\r
1850 /* Local port on this machine. */
\r
1851 pxAddress->sin_port = FreeRTOS_htons( pxSocket->usLocalPort );
\r
1853 return sizeof( *pxAddress );
\r
1856 /*-----------------------------------------------------------*/
\r
1858 void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
\r
1860 /* _HT_ must work this out, now vSocketWakeUpUser will be called for any important
\r
1861 * event or transition */
\r
1862 #if( ipconfigSOCKET_HAS_USER_SEMAPHORE == 1 )
\r
1864 if( pxSocket->pxUserSemaphore != NULL )
\r
1866 xSemaphoreGive( pxSocket->pxUserSemaphore );
\r
1869 #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
\r
1871 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
1873 if( pxSocket->pxSocketSet != NULL )
\r
1875 EventBits_t xSelectBits = ( pxSocket->xEventBits >> SOCKET_EVENT_BIT_COUNT ) & eSELECT_ALL;
\r
1876 if( xSelectBits != 0ul )
\r
1878 pxSocket->xSocketBits |= xSelectBits;
\r
1879 xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, xSelectBits );
\r
1883 pxSocket->xEventBits &= eSOCKET_ALL;
\r
1885 #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
\r
1887 if( ( pxSocket->xEventGroup != NULL ) && ( pxSocket->xEventBits != 0u ) )
\r
1889 xEventGroupSetBits( pxSocket->xEventGroup, pxSocket->xEventBits );
\r
1892 pxSocket->xEventBits = 0ul;
\r
1895 /*-----------------------------------------------------------*/
\r
1897 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1899 /* This define makes it possible for network-card drivers to inspect
\r
1900 * UDP message and see if there is any UDP socket bound to a given port
\r
1902 * This is probably only useful in systems with a minimum of RAM and
\r
1903 * when lots of anonymous broadcast messages come in
\r
1905 BaseType_t xPortHasUDPSocket( uint16_t usPortNr )
\r
1907 BaseType_t xFound = pdFALSE;
\r
1909 vTaskSuspendAll();
\r
1911 if( ( pxListFindListItemWithValue( &xBoundUDPSocketsList, ( TickType_t ) usPortNr ) != NULL ) )
\r
1921 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1923 /*-----------------------------------------------------------*/
\r
1925 #if( ipconfigUSE_TCP == 1 )
\r
1927 static BaseType_t bMayConnect( FreeRTOS_Socket_t *pxSocket );
\r
1928 static BaseType_t bMayConnect( FreeRTOS_Socket_t *pxSocket )
\r
1930 switch( pxSocket->u.xTCP.ucTCPState )
\r
1933 case eCLOSE_WAIT: return 0;
\r
1934 case eCONNECT_SYN: return -pdFREERTOS_ERRNO_EINPROGRESS;
\r
1935 default: return -pdFREERTOS_ERRNO_EAGAIN;
\r
1939 #endif /* ipconfigUSE_TCP */
\r
1940 /*-----------------------------------------------------------*/
\r
1942 #if( ipconfigUSE_TCP == 1 )
\r
1944 static BaseType_t prvTCPConnectStart( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr *pxAddress )
\r
1946 BaseType_t xResult = 0;
\r
1948 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdFALSE )
\r
1950 /* Not a valid socket or wrong type */
\r
1951 xResult = -pdFREERTOS_ERRNO_EBADF;
\r
1953 else if( FreeRTOS_issocketconnected( pxSocket ) > 0 )
\r
1955 /* The socket is already connected. */
\r
1956 xResult = -pdFREERTOS_ERRNO_EISCONN;
\r
1958 else if( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE )
\r
1960 /* Bind the socket to the port that the client task will send from.
\r
1961 Non-standard, so the error returned is that returned by bind(). */
\r
1962 xResult = FreeRTOS_bind( ( Socket_t ) pxSocket, NULL, 0u );
\r
1965 if( xResult == 0 )
\r
1967 /* Check if it makes any sense to wait for a connect event, this condition
\r
1968 might change while sleeping, so it must be checked within each loop */
\r
1969 xResult = bMayConnect( pxSocket ); /* -EINPROGRESS, -EAGAIN, or 0 for OK */
\r
1971 /* Start the connect procedure, kernel will start working on it */
\r
1972 if( xResult == 0 )
\r
1974 pxSocket->u.xTCP.bits.bConnPrepared = pdFALSE_UNSIGNED;
\r
1975 pxSocket->u.xTCP.ucRepCount = 0u;
\r
1977 FreeRTOS_debug_printf( ( "FreeRTOS_connect: %u to %lxip:%u\n",
\r
1978 pxSocket->usLocalPort, FreeRTOS_ntohl( pxAddress->sin_addr ), FreeRTOS_ntohs( pxAddress->sin_port ) ) );
\r
1980 /* Port on remote machine. */
\r
1981 pxSocket->u.xTCP.usRemotePort = FreeRTOS_ntohs( pxAddress->sin_port );
\r
1983 /* IP address of remote machine. */
\r
1984 pxSocket->u.xTCP.ulRemoteIP = FreeRTOS_ntohl( pxAddress->sin_addr );
\r
1986 /* (client) internal state: socket wants to send a connect. */
\r
1987 vTCPStateChange( pxSocket, eCONNECT_SYN );
\r
1989 /* To start an active connect. */
\r
1990 pxSocket->u.xTCP.usTimeout = 1u;
\r
1992 if( xSendEventToIPTask( eTCPTimerEvent ) != pdPASS )
\r
1994 xResult = -pdFREERTOS_ERRNO_ECANCELED;
\r
2002 #endif /* ipconfigUSE_TCP */
\r
2003 /*-----------------------------------------------------------*/
\r
2005 #if( ipconfigUSE_TCP == 1 )
\r
2008 * FreeRTOS_connect: socket wants to connect to a remote port
\r
2010 BaseType_t FreeRTOS_connect( Socket_t xClientSocket, struct freertos_sockaddr *pxAddress, socklen_t xAddressLength )
\r
2012 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t* ) xClientSocket;
\r
2013 TickType_t xRemainingTime;
\r
2014 BaseType_t xTimed = pdFALSE;
\r
2015 BaseType_t xResult;
\r
2016 TimeOut_t xTimeOut;
\r
2018 ( void ) xAddressLength;
\r
2020 xResult = prvTCPConnectStart( pxSocket, pxAddress );
\r
2022 if( xResult == 0 )
\r
2024 /* And wait for the result */
\r
2027 if( xTimed == pdFALSE )
\r
2029 /* Only in the first round, check for non-blocking */
\r
2030 xRemainingTime = pxSocket->xReceiveBlockTime;
\r
2031 if( xRemainingTime == ( TickType_t )0 )
\r
2033 /* Not yet connected, correct state, non-blocking. */
\r
2034 xResult = -pdFREERTOS_ERRNO_EWOULDBLOCK;
\r
2038 /* Don't get here a second time. */
\r
2041 /* Fetch the current time */
\r
2042 vTaskSetTimeOutState( &xTimeOut );
\r
2045 /* Did it get connected while sleeping ? */
\r
2046 xResult = FreeRTOS_issocketconnected( pxSocket );
\r
2048 /* Returns positive when connected, negative means an error */
\r
2051 /* Return the error */
\r
2057 /* Socket now connected, return a zero */
\r
2062 /* Is it allowed to sleep more? */
\r
2063 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) )
\r
2065 xResult = -pdFREERTOS_ERRNO_ETIMEDOUT;
\r
2069 /* Go sleeping until we get any down-stream event */
\r
2070 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_CONNECT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2076 #endif /* ipconfigUSE_TCP */
\r
2077 /*-----------------------------------------------------------*/
\r
2079 #if( ipconfigUSE_TCP == 1 )
\r
2082 * FreeRTOS_accept: can return a new connected socket
\r
2083 * if the server socket is in listen mode and receives a connection request
\r
2084 * The new socket will be bound already to the same port number as the listing
\r
2087 Socket_t FreeRTOS_accept( Socket_t xServerSocket, struct freertos_sockaddr *pxAddress, socklen_t *pxAddressLength )
\r
2089 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xServerSocket;
\r
2090 FreeRTOS_Socket_t *pxClientSocket = NULL;
\r
2091 TickType_t xRemainingTime;
\r
2092 BaseType_t xTimed = pdFALSE, xAsk = pdFALSE;
\r
2093 TimeOut_t xTimeOut;
\r
2094 IPStackEvent_t xAskEvent;
\r
2096 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2098 /* Not a valid socket or wrong type */
\r
2099 pxClientSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
\r
2101 else if( ( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED ) &&
\r
2102 ( pxSocket->u.xTCP.ucTCPState != eTCP_LISTEN ) )
\r
2104 /* Parent socket is not in listening mode */
\r
2105 pxClientSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
\r
2109 /* Loop will stop with breaks. */
\r
2112 /* Is there a new client? */
\r
2113 vTaskSuspendAll();
\r
2115 if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED )
\r
2117 pxClientSocket = pxSocket->u.xTCP.pxPeerSocket;
\r
2121 pxClientSocket = pxSocket;
\r
2123 if( pxClientSocket != NULL )
\r
2125 pxSocket->u.xTCP.pxPeerSocket = NULL;
\r
2127 /* Is it still not taken ? */
\r
2128 if( pxClientSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED )
\r
2130 pxClientSocket->u.xTCP.bits.bPassAccept = pdFALSE_UNSIGNED;
\r
2134 pxClientSocket = NULL;
\r
2140 if( pxClientSocket != NULL )
\r
2142 if( pxAddress != NULL )
\r
2144 /* IP address of remote machine. */
\r
2145 pxAddress->sin_addr = FreeRTOS_ntohl( pxClientSocket->u.xTCP.ulRemoteIP );
\r
2147 /* Port on remote machine. */
\r
2148 pxAddress->sin_port = FreeRTOS_ntohs( pxClientSocket->u.xTCP.usRemotePort );
\r
2150 if( pxAddressLength != NULL )
\r
2152 *pxAddressLength = sizeof( *pxAddress );
\r
2155 if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED )
\r
2161 if( xAsk != pdFALSE )
\r
2163 /* Ask to set an event in 'xEventGroup' as soon as a new
\r
2164 client gets connected for this listening socket. */
\r
2165 xAskEvent.eEventType = eTCPAcceptEvent;
\r
2166 xAskEvent.pvData = ( void * ) pxSocket;
\r
2167 xSendEventStructToIPTask( &xAskEvent, portMAX_DELAY );
\r
2170 if( pxClientSocket != NULL )
\r
2175 if( xTimed == pdFALSE )
\r
2177 /* Only in the first round, check for non-blocking */
\r
2178 xRemainingTime = pxSocket->xReceiveBlockTime;
\r
2179 if( xRemainingTime == ( TickType_t ) 0 )
\r
2184 /* Don't get here a second time */
\r
2187 /* Fetch the current time */
\r
2188 vTaskSetTimeOutState( &xTimeOut );
\r
2191 /* Has the timeout been reached? */
\r
2192 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
\r
2197 /* Go sleeping until we get any down-stream event */
\r
2198 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_ACCEPT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2202 return ( Socket_t ) pxClientSocket;
\r
2204 #endif /* ipconfigUSE_TCP */
\r
2205 /*-----------------------------------------------------------*/
\r
2207 #if( ipconfigUSE_TCP == 1 )
\r
2210 * Read incoming data from a TCP socket
\r
2211 * Only after the last byte has been read, a close error might be returned
\r
2213 BaseType_t FreeRTOS_recv( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags )
\r
2215 BaseType_t xByteCount;
\r
2216 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2217 TickType_t xRemainingTime;
\r
2218 BaseType_t xTimed = pdFALSE;
\r
2219 TimeOut_t xTimeOut;
\r
2220 EventBits_t xEventBits = ( EventBits_t ) 0;
\r
2222 /* Check if the socket is valid, has type TCP and if it is bound to a
\r
2224 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2226 xByteCount = -pdFREERTOS_ERRNO_EINVAL;
\r
2230 if( pxSocket->u.xTCP.rxStream != NULL )
\r
2232 xByteCount = ( BaseType_t )uxStreamBufferGetSize ( pxSocket->u.xTCP.rxStream );
\r
2239 while( xByteCount == 0 )
\r
2241 switch( pxSocket->u.xTCP.ucTCPState )
\r
2244 case eCLOSE_WAIT: /* (server + client) waiting for a connection termination request from the local user. */
\r
2245 case eCLOSING: /* (server + client) waiting for a connection termination request acknowledgement from the remote TCP. */
\r
2246 if( pxSocket->u.xTCP.bits.bMallocError != pdFALSE_UNSIGNED )
\r
2248 /* The no-memory error has priority above the non-connected error.
\r
2249 Both are fatal and will elad to closing the socket. */
\r
2250 xByteCount = -pdFREERTOS_ERRNO_ENOMEM;
\r
2254 xByteCount = -pdFREERTOS_ERRNO_ENOTCONN;
\r
2256 /* Call continue to break out of the switch and also the while
\r
2263 if( xTimed == pdFALSE )
\r
2265 /* Only in the first round, check for non-blocking. */
\r
2266 xRemainingTime = pxSocket->xReceiveBlockTime;
\r
2268 if( xRemainingTime == ( TickType_t ) 0 )
\r
2270 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
2272 /* Just check for the interrupt flag. */
\r
2273 xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_INTR,
\r
2274 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, socketDONT_BLOCK );
\r
2276 #endif /* ipconfigSUPPORT_SIGNALS */
\r
2280 if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
\r
2285 /* Don't get here a second time. */
\r
2288 /* Fetch the current time. */
\r
2289 vTaskSetTimeOutState( &xTimeOut );
\r
2292 /* Has the timeout been reached? */
\r
2293 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
\r
2298 /* Block until there is a down-stream event. */
\r
2299 xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup,
\r
2300 eSOCKET_RECEIVE | eSOCKET_CLOSED | eSOCKET_INTR,
\r
2301 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2302 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
2304 if( ( xEventBits & eSOCKET_INTR ) != 0u )
\r
2311 ( void ) xEventBits;
\r
2313 #endif /* ipconfigSUPPORT_SIGNALS */
\r
2315 if( pxSocket->u.xTCP.rxStream != NULL )
\r
2317 xByteCount = ( BaseType_t ) uxStreamBufferGetSize ( pxSocket->u.xTCP.rxStream );
\r
2325 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
2326 if( ( xEventBits & eSOCKET_INTR ) != 0 )
\r
2328 if( ( xEventBits & ( eSOCKET_RECEIVE | eSOCKET_CLOSED ) ) != 0 )
\r
2330 /* Shouldn't have cleared other flags. */
\r
2331 xEventBits &= ~eSOCKET_INTR;
\r
2332 xEventGroupSetBits( pxSocket->xEventGroup, xEventBits );
\r
2334 xByteCount = -pdFREERTOS_ERRNO_EINTR;
\r
2337 #endif /* ipconfigSUPPORT_SIGNALS */
\r
2338 if( xByteCount > 0 )
\r
2340 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
\r
2342 xByteCount = ( BaseType_t ) uxStreamBufferGet( pxSocket->u.xTCP.rxStream, 0ul, ( uint8_t * ) pvBuffer, ( size_t ) xBufferLength, ( xFlags & FREERTOS_MSG_PEEK ) != 0 );
\r
2343 if( pxSocket->u.xTCP.bits.bLowWater != pdFALSE_UNSIGNED )
\r
2345 /* We had reached the low-water mark, now see if the flag
\r
2347 size_t uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );
\r
2349 if( uxFrontSpace >= pxSocket->u.xTCP.uxEnoughSpace )
\r
2351 pxSocket->u.xTCP.bits.bLowWater = pdFALSE_UNSIGNED;
\r
2352 pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
\r
2353 pxSocket->u.xTCP.usTimeout = 1u; /* because bLowWater is cleared. */
\r
2354 xSendEventToIPTask( eTCPTimerEvent );
\r
2360 /* Zero-copy reception of data: pvBuffer is a pointer to a pointer. */
\r
2361 xByteCount = ( BaseType_t ) uxStreamBufferGetPtr( pxSocket->u.xTCP.rxStream, (uint8_t **)pvBuffer );
\r
2364 } /* prvValidSocket() */
\r
2366 return xByteCount;
\r
2369 #endif /* ipconfigUSE_TCP */
\r
2370 /*-----------------------------------------------------------*/
\r
2372 #if( ipconfigUSE_TCP == 1 )
\r
2374 static int32_t prvTCPSendCheck( FreeRTOS_Socket_t *pxSocket, size_t xDataLength )
\r
2376 int32_t xResult = 1;
\r
2378 /* Is this a socket of type TCP and is it already bound to a port number ? */
\r
2379 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2381 xResult = -pdFREERTOS_ERRNO_EINVAL;
\r
2383 else if( pxSocket->u.xTCP.bits.bMallocError != pdFALSE_UNSIGNED )
\r
2385 xResult = -pdFREERTOS_ERRNO_ENOMEM;
\r
2387 else if( pxSocket->u.xTCP.ucTCPState == eCLOSED )
\r
2389 xResult = -pdFREERTOS_ERRNO_ENOTCONN;
\r
2391 else if( pxSocket->u.xTCP.bits.bFinSent != pdFALSE_UNSIGNED )
\r
2393 /* This TCP connection is closing already, the FIN flag has been sent.
\r
2394 Maybe it is still delivering or receiving data.
\r
2395 Return OK in order not to get closed/deleted too quickly */
\r
2398 else if( xDataLength == 0ul )
\r
2400 /* send() is being called to send zero bytes */
\r
2403 else if( pxSocket->u.xTCP.txStream == NULL )
\r
2405 /* Create the outgoing stream only when it is needed */
\r
2406 prvTCPCreateStream( pxSocket, pdFALSE );
\r
2408 if( pxSocket->u.xTCP.txStream == NULL )
\r
2410 xResult = -pdFREERTOS_ERRNO_ENOMEM;
\r
2417 #endif /* ipconfigUSE_TCP */
\r
2418 /*-----------------------------------------------------------*/
\r
2420 #if( ipconfigUSE_TCP == 1 )
\r
2422 /* Get a direct pointer to the circular transmit buffer.
\r
2423 '*pxLength' will contain the number of bytes that may be written. */
\r
2424 uint8_t *FreeRTOS_get_tx_head( Socket_t xSocket, BaseType_t *pxLength )
\r
2426 uint8_t *pucReturn;
\r
2427 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2428 StreamBuffer_t *pxBuffer = pxSocket->u.xTCP.txStream;
\r
2430 if( pxBuffer != NULL )
\r
2432 BaseType_t xSpace = ( BaseType_t ) uxStreamBufferGetSpace( pxBuffer );
\r
2433 BaseType_t xRemain = ( BaseType_t ) ( pxBuffer->LENGTH - pxBuffer->uxHead );
\r
2435 *pxLength = FreeRTOS_min_BaseType( xSpace, xRemain );
\r
2436 pucReturn = pxBuffer->ucArray + pxBuffer->uxHead;
\r
2446 #endif /* ipconfigUSE_TCP */
\r
2447 /*-----------------------------------------------------------*/
\r
2449 #if( ipconfigUSE_TCP == 1 )
\r
2451 * Send data using a TCP socket. It is not necessary to have the socket
\r
2452 * connected already. Outgoing data will be stored and delivered as soon as
\r
2453 * the socket gets connected.
\r
2455 BaseType_t FreeRTOS_send( Socket_t xSocket, const void *pvBuffer, size_t uxDataLength, BaseType_t xFlags )
\r
2457 BaseType_t xByteCount;
\r
2458 BaseType_t xBytesLeft;
\r
2459 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2460 TickType_t xRemainingTime;
\r
2461 BaseType_t xTimed = pdFALSE;
\r
2462 TimeOut_t xTimeOut;
\r
2463 BaseType_t xCloseAfterSend;
\r
2465 /* Prevent compiler warnings about unused parameters. The parameter
\r
2466 may be used in future versions. */
\r
2469 xByteCount = ( BaseType_t ) prvTCPSendCheck( pxSocket, uxDataLength );
\r
2471 if( xByteCount > 0 )
\r
2473 /* xBytesLeft is number of bytes to send, will count to zero. */
\r
2474 xBytesLeft = ( BaseType_t ) uxDataLength;
\r
2476 /* xByteCount is number of bytes that can be sent now. */
\r
2477 xByteCount = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
\r
2479 /* While there are still bytes to be sent. */
\r
2480 while( xBytesLeft > 0 )
\r
2482 /* If txStream has space. */
\r
2483 if( xByteCount > 0 )
\r
2485 /* Don't send more than necessary. */
\r
2486 if( xByteCount > xBytesLeft )
\r
2488 xByteCount = xBytesLeft;
\r
2491 /* Is the close-after-send flag set and is this really the
\r
2492 last transmission? */
\r
2493 if( ( pxSocket->u.xTCP.bits.bCloseAfterSend != pdFALSE_UNSIGNED ) && ( xByteCount == xBytesLeft ) )
\r
2495 xCloseAfterSend = pdTRUE;
\r
2499 xCloseAfterSend = pdFALSE;
\r
2502 /* The flag 'bCloseAfterSend' can be set before sending data
\r
2503 using setsockopt()
\r
2505 When the last data packet is being sent out, a FIN flag will
\r
2506 be included to let the peer know that no more data is to be
\r
2507 expected. The use of 'bCloseAfterSend' is not mandatory, it
\r
2508 is just a faster way of transferring files (e.g. when using
\r
2510 if( xCloseAfterSend != pdFALSE )
\r
2512 /* Now suspend the scheduler: sending the last data and
\r
2513 setting bCloseRequested must be done together */
\r
2514 vTaskSuspendAll();
\r
2515 pxSocket->u.xTCP.bits.bCloseRequested = pdTRUE_UNSIGNED;
\r
2518 xByteCount = ( BaseType_t ) uxStreamBufferAdd( pxSocket->u.xTCP.txStream, 0ul, ( const uint8_t * ) pvBuffer, ( size_t ) xByteCount );
\r
2520 if( xCloseAfterSend != pdFALSE )
\r
2522 /* Now when the IP-task transmits the data, it will also
\r
2523 see that bCloseRequested is true and include the FIN
\r
2524 flag to start closure of the connection. */
\r
2528 /* Send a message to the IP-task so it can work on this
\r
2529 socket. Data is sent, let the IP-task work on it. */
\r
2530 pxSocket->u.xTCP.usTimeout = 1u;
\r
2532 if( xIsCallingFromIPTask() == pdFALSE )
\r
2534 /* Only send a TCP timer event when not called from the
\r
2536 xSendEventToIPTask( eTCPTimerEvent );
\r
2539 xBytesLeft -= xByteCount;
\r
2541 if( xBytesLeft == 0 )
\r
2546 /* As there are still bytes left to be sent, increase the
\r
2548 pvBuffer = ( void * ) ( ( ( const uint8_t * ) pvBuffer) + xByteCount );
\r
2551 /* Not all bytes have been sent. In case the socket is marked as
\r
2552 blocking sleep for a while. */
\r
2553 if( xTimed == pdFALSE )
\r
2555 /* Only in the first round, check for non-blocking. */
\r
2556 xRemainingTime = pxSocket->xSendBlockTime;
\r
2558 #if( ipconfigUSE_CALLBACKS != 0 )
\r
2560 if( xIsCallingFromIPTask() != pdFALSE )
\r
2562 /* If this send function is called from within a
\r
2563 call-back handler it may not block, otherwise
\r
2564 chances would be big to get a deadlock: the IP-task
\r
2565 waiting for itself. */
\r
2566 xRemainingTime = ( TickType_t ) 0;
\r
2569 #endif /* ipconfigUSE_CALLBACKS */
\r
2571 if( xRemainingTime == ( TickType_t ) 0 )
\r
2576 if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
\r
2581 /* Don't get here a second time. */
\r
2584 /* Fetch the current time. */
\r
2585 vTaskSetTimeOutState( &xTimeOut );
\r
2589 /* Has the timeout been reached? */
\r
2590 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
\r
2596 /* Go sleeping until down-stream events are received. */
\r
2597 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_SEND | eSOCKET_CLOSED,
\r
2598 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2600 xByteCount = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
\r
2603 /* How much was actually sent? */
\r
2604 xByteCount = ( ( BaseType_t ) uxDataLength ) - xBytesLeft;
\r
2606 if( xByteCount == 0 )
\r
2608 if( pxSocket->u.xTCP.ucTCPState > eESTABLISHED )
\r
2610 xByteCount = ( BaseType_t ) -pdFREERTOS_ERRNO_ENOTCONN;
\r
2614 if( ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) != pdFALSE )
\r
2616 FreeRTOS_debug_printf( ( "FreeRTOS_send: %u -> %lxip:%d: no space\n",
\r
2617 pxSocket->usLocalPort,
\r
2618 pxSocket->u.xTCP.ulRemoteIP,
\r
2619 pxSocket->u.xTCP.usRemotePort ) );
\r
2622 xByteCount = ( BaseType_t ) -pdFREERTOS_ERRNO_ENOSPC;
\r
2627 return xByteCount;
\r
2630 #endif /* ipconfigUSE_TCP */
\r
2631 /*-----------------------------------------------------------*/
\r
2633 #if( ipconfigUSE_TCP == 1 )
\r
2636 * Request to put a socket in listen mode
\r
2638 BaseType_t FreeRTOS_listen( Socket_t xSocket, BaseType_t xBacklog )
\r
2640 FreeRTOS_Socket_t *pxSocket;
\r
2641 BaseType_t xResult = 0;
\r
2643 pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2645 /* listen() is allowed for a valid TCP socket in Closed state and already
\r
2647 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2649 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2651 else if( ( pxSocket->u.xTCP.ucTCPState != eCLOSED ) && ( pxSocket->u.xTCP.ucTCPState != eCLOSE_WAIT ) )
\r
2653 /* Socket is in a wrong state. */
\r
2654 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2658 /* Backlog is interpreted here as "the maximum number of child
\r
2660 pxSocket->u.xTCP.usBacklog = ( uint16_t )FreeRTOS_min_int32( ( int32_t ) 0xffff, ( int32_t ) xBacklog );
\r
2662 /* This cleaning is necessary only if a listening socket is being
\r
2663 reused as it might have had a previous connection. */
\r
2664 if( pxSocket->u.xTCP.bits.bReuseSocket )
\r
2666 if( pxSocket->u.xTCP.rxStream != NULL )
\r
2668 vStreamBufferClear( pxSocket->u.xTCP.rxStream );
\r
2671 if( pxSocket->u.xTCP.txStream != NULL )
\r
2673 vStreamBufferClear( pxSocket->u.xTCP.txStream );
\r
2676 memset( pxSocket->u.xTCP.xPacket.u.ucLastPacket, '\0', sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket ) );
\r
2677 memset( &pxSocket->u.xTCP.xTCPWindow, '\0', sizeof( pxSocket->u.xTCP.xTCPWindow ) );
\r
2678 memset( &pxSocket->u.xTCP.bits, '\0', sizeof( pxSocket->u.xTCP.bits ) );
\r
2680 /* Now set the bReuseSocket flag again, because the bits have
\r
2681 just been cleared. */
\r
2682 pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE_UNSIGNED;
\r
2685 vTCPStateChange( pxSocket, eTCP_LISTEN );
\r
2691 #endif /* ipconfigUSE_TCP */
\r
2692 /*-----------------------------------------------------------*/
\r
2694 #if( ipconfigUSE_TCP == 1 )
\r
2696 /* shutdown - shut down part of a full-duplex connection */
\r
2697 BaseType_t FreeRTOS_shutdown( Socket_t xSocket, BaseType_t xHow )
\r
2699 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2700 BaseType_t xResult;
\r
2702 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2704 /*_RB_ Is this comment correct? The socket is not of a type that
\r
2705 supports the listen() operation. */
\r
2706 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2708 else if ( pxSocket->u.xTCP.ucTCPState != eESTABLISHED )
\r
2710 /*_RB_ Is this comment correct? The socket is not of a type that
\r
2711 supports the listen() operation. */
\r
2712 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2716 pxSocket->u.xTCP.bits.bUserShutdown = pdTRUE_UNSIGNED;
\r
2718 /* Let the IP-task perform the shutdown of the connection. */
\r
2719 pxSocket->u.xTCP.usTimeout = 1u;
\r
2720 xSendEventToIPTask( eTCPTimerEvent );
\r
2728 #endif /* ipconfigUSE_TCP */
\r
2729 /*-----------------------------------------------------------*/
\r
2731 #if( ipconfigUSE_TCP == 1 )
\r
2734 * A TCP timer has expired, now check all TCP sockets for:
\r
2735 * - Active connect
\r
2736 * - Send a delayed ACK
\r
2738 * - Send a keep-alive packet
\r
2739 * - Check for timeout (in non-connected states only)
\r
2741 TickType_t xTCPTimerCheck( BaseType_t xWillSleep )
\r
2743 FreeRTOS_Socket_t *pxSocket;
\r
2744 TickType_t xShortest = pdMS_TO_TICKS( ( TickType_t ) ipTCP_TIMER_PERIOD_MS );
\r
2745 TickType_t xNow = xTaskGetTickCount();
\r
2746 static TickType_t xLastTime = 0u;
\r
2747 TickType_t xDelta = xNow - xLastTime;
\r
2748 ListItem_t* pxEnd = ( ListItem_t * ) listGET_END_MARKER( &xBoundTCPSocketsList );
\r
2749 ListItem_t *pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );
\r
2753 if( xDelta == 0u )
\r
2758 while( pxIterator != pxEnd )
\r
2760 pxSocket = ( FreeRTOS_Socket_t * )listGET_LIST_ITEM_OWNER( pxIterator );
\r
2761 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator );
\r
2763 /* Sockets with 'tmout == 0' do not need any regular attention. */
\r
2764 if( pxSocket->u.xTCP.usTimeout == 0u )
\r
2769 if( xDelta < ( TickType_t ) pxSocket->u.xTCP.usTimeout )
\r
2771 pxSocket->u.xTCP.usTimeout = ( uint16_t ) ( ( ( TickType_t ) pxSocket->u.xTCP.usTimeout ) - xDelta );
\r
2776 pxSocket->u.xTCP.usTimeout = 0u;
\r
2777 rc = xTCPSocketCheck( pxSocket );
\r
2779 /* Within this function, the socket might want to send a delayed
\r
2780 ack or send out data or whatever it needs to do. */
\r
2783 /* Continue because the socket was deleted. */
\r
2788 /* In xEventBits the driver may indicate that the socket has
\r
2789 important events for the user. These are only done just before the
\r
2790 IP-task goes to sleep. */
\r
2791 if( pxSocket->xEventBits != 0u )
\r
2793 if( xWillSleep != pdFALSE )
\r
2795 /* The IP-task is about to go to sleep, so messages can be
\r
2796 sent to the socket owners. */
\r
2797 vSocketWakeUpUser( pxSocket );
\r
2801 /* Or else make sure this will be called again to wake-up
\r
2802 the sockets' owner. */
\r
2803 xShortest = ( TickType_t ) 0;
\r
2807 if( ( pxSocket->u.xTCP.usTimeout != 0u ) && ( xShortest > ( TickType_t ) pxSocket->u.xTCP.usTimeout ) )
\r
2809 xShortest = ( TickType_t ) pxSocket->u.xTCP.usTimeout;
\r
2816 #endif /* ipconfigUSE_TCP */
\r
2817 /*-----------------------------------------------------------*/
\r
2819 #if( ipconfigUSE_TCP == 1 )
\r
2822 * TCP: as multiple sockets may be bound to the same local port number
\r
2823 * looking up a socket is a little more complex:
\r
2824 * Both a local port, and a remote port and IP address are being used
\r
2825 * For a socket in listening mode, the remote port and IP address are both 0
\r
2827 FreeRTOS_Socket_t *pxTCPSocketLookup( uint32_t ulLocalIP, UBaseType_t uxLocalPort, uint32_t ulRemoteIP, UBaseType_t uxRemotePort )
\r
2829 ListItem_t *pxIterator;
\r
2830 FreeRTOS_Socket_t *pxResult = NULL, *pxListenSocket = NULL;
\r
2831 MiniListItem_t *pxEnd = ( MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );
\r
2833 /* Parameter not yet supported. */
\r
2834 ( void ) ulLocalIP;
\r
2836 for( pxIterator = ( ListItem_t * ) listGET_NEXT( pxEnd );
\r
2837 pxIterator != ( ListItem_t * ) pxEnd;
\r
2838 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
2840 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
\r
2842 if( pxSocket->usLocalPort == ( uint16_t ) uxLocalPort )
\r
2844 if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN )
\r
2846 /* If this is a socket listening to uxLocalPort, remember it
\r
2847 in case there is no perfect match. */
\r
2848 pxListenSocket = pxSocket;
\r
2850 else if( ( pxSocket->u.xTCP.usRemotePort == ( uint16_t ) uxRemotePort ) && ( pxSocket->u.xTCP.ulRemoteIP == ulRemoteIP ) )
\r
2852 /* For sockets not in listening mode, find a match with
\r
2853 xLocalPort, ulRemoteIP AND xRemotePort. */
\r
2854 pxResult = pxSocket;
\r
2859 if( pxResult == NULL )
\r
2861 /* An exact match was not found, maybe a listening socket was
\r
2863 pxResult = pxListenSocket;
\r
2869 #endif /* ipconfigUSE_TCP */
\r
2870 /*-----------------------------------------------------------*/
\r
2872 #if( ipconfigUSE_TCP == 1 )
\r
2874 const struct xSTREAM_BUFFER *FreeRTOS_get_rx_buf( Socket_t xSocket )
\r
2876 FreeRTOS_Socket_t *pxSocket = (FreeRTOS_Socket_t *)xSocket;
\r
2878 return pxSocket->u.xTCP.rxStream;
\r
2881 #endif /* ipconfigUSE_TCP */
\r
2882 /*-----------------------------------------------------------*/
\r
2884 #if( ipconfigUSE_TCP == 1 )
\r
2886 static StreamBuffer_t *prvTCPCreateStream ( FreeRTOS_Socket_t *pxSocket, BaseType_t xIsInputStream )
\r
2888 StreamBuffer_t *pxBuffer;
\r
2892 /* Now that a stream is created, the maximum size is fixed before
\r
2893 creation, it could still be changed with setsockopt(). */
\r
2894 if( xIsInputStream != pdFALSE )
\r
2896 /* Flow control for input streams works with a low- and a high-water mark.
\r
2897 1) If the RX-space becomes less than uxLittleSpace, the flag 'bLowWater' will
\r
2898 be set, and a TCP window update message will be sent to the peer.
\r
2899 2) The data will be read from the socket by recv() and when RX-space becomes
\r
2900 larger than or equal to than 'uxEnoughSpace', a new TCP window update
\r
2901 message will be sent to the peer, and 'bLowWater' will get cleared again.
\r
2903 uxLittleSpace == 1/5 x uxRxStreamSize
\r
2904 uxEnoughSpace == 4/5 x uxRxStreamSize
\r
2905 How-ever it is very inefficient to make 'uxLittleSpace' smaller than the actual MSS.
\r
2907 uxLength = pxSocket->u.xTCP.uxRxStreamSize;
\r
2909 if( pxSocket->u.xTCP.uxLittleSpace == 0ul )
\r
2911 pxSocket->u.xTCP.uxLittleSpace = ( 1ul * pxSocket->u.xTCP.uxRxStreamSize ) / 5u; /*_RB_ Why divide by 5? Can this be changed to a #define? */
\r
2912 if( (pxSocket->u.xTCP.uxLittleSpace < pxSocket->u.xTCP.usCurMSS ) && ( pxSocket->u.xTCP.uxRxStreamSize >= 2 * pxSocket->u.xTCP.usCurMSS ) )
\r
2914 pxSocket->u.xTCP.uxLittleSpace = pxSocket->u.xTCP.usCurMSS;
\r
2918 if( pxSocket->u.xTCP.uxEnoughSpace == 0ul )
\r
2920 pxSocket->u.xTCP.uxEnoughSpace = ( 4ul * pxSocket->u.xTCP.uxRxStreamSize ) / 5u; /*_RB_ Why multiply by 4? Maybe sock80_PERCENT?*/
\r
2925 uxLength = pxSocket->u.xTCP.uxTxStreamSize;
\r
2928 /* Add an extra 4 (or 8) bytes. */
\r
2929 uxLength += sizeof( size_t );
\r
2931 /* And make the length a multiple of sizeof( size_t ). */
\r
2932 uxLength &= ~( sizeof( size_t ) - 1u );
\r
2934 uxSize = sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) + uxLength;
\r
2936 pxBuffer = ( StreamBuffer_t * )pvPortMallocLarge( uxSize );
\r
2938 if( pxBuffer == NULL )
\r
2940 FreeRTOS_debug_printf( ( "prvTCPCreateStream: malloc failed\n" ) );
\r
2941 pxSocket->u.xTCP.bits.bMallocError = pdTRUE_UNSIGNED;
\r
2942 vTCPStateChange( pxSocket, eCLOSE_WAIT );
\r
2946 /* Clear the markers of the stream */
\r
2947 memset( pxBuffer, '\0', sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) );
\r
2948 pxBuffer->LENGTH = ( size_t ) uxLength ;
\r
2950 if( xTCPWindowLoggingLevel != 0 )
\r
2952 FreeRTOS_debug_printf( ( "prvTCPCreateStream: %cxStream created %lu bytes (total %lu)\n", xIsInputStream ? 'R' : 'T', uxLength, uxSize ) );
\r
2955 if( xIsInputStream != 0 )
\r
2957 pxSocket->u.xTCP.rxStream = pxBuffer;
\r
2961 pxSocket->u.xTCP.txStream = pxBuffer;
\r
2968 #endif /* ipconfigUSE_TCP */
\r
2969 /*-----------------------------------------------------------*/
\r
2971 #if( ipconfigUSE_TCP == 1 )
\r
2974 * Add data to the RxStream. When uxOffset > 0, data has come in out-of-order
\r
2975 * and will be put in front of the head so it can not be popped by the user.
\r
2977 int32_t lTCPAddRxdata( FreeRTOS_Socket_t *pxSocket, size_t uxOffset, const uint8_t *pcData, uint32_t ulByteCount )
\r
2979 StreamBuffer_t *pxStream = pxSocket->u.xTCP.rxStream;
\r
2981 #if( ipconfigUSE_CALLBACKS == 1 )
\r
2982 BaseType_t bHasHandler = ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xTCP.pxHandleReceive );
\r
2983 const uint8_t *pucBuffer = NULL;
\r
2984 #endif /* ipconfigUSE_CALLBACKS */
\r
2986 /* int32_t uxStreamBufferAdd( pxBuffer, uxOffset, pucData, aCount )
\r
2987 if( pucData != NULL ) copy data the the buffer
\r
2988 if( pucData == NULL ) no copying, just advance rxHead
\r
2989 if( uxOffset != 0 ) Just store data which has come out-of-order
\r
2990 if( uxOffset == 0 ) Also advance rxHead */
\r
2991 if( pxStream == NULL )
\r
2993 pxStream = prvTCPCreateStream( pxSocket, pdTRUE );
\r
2994 if( pxStream == NULL )
\r
3000 #if( ipconfigUSE_CALLBACKS == 1 )
\r
3002 if( ( bHasHandler != pdFALSE ) && ( uxStreamBufferGetSize( pxStream ) == 0u ) && ( uxOffset == 0ul ) && ( pcData != NULL ) )
\r
3004 /* Data can be passed directly to the user */
\r
3005 pucBuffer = pcData;
\r
3007 /* Zero-copy for call-back: no need to add the bytes to the
\r
3008 stream, only the pointer will be advanced by uxStreamBufferAdd(). */
\r
3012 #endif /* ipconfigUSE_CALLBACKS */
\r
3014 xResult = ( int32_t ) uxStreamBufferAdd( pxStream, uxOffset, pcData, ( size_t ) ulByteCount );
\r
3016 #if( ipconfigHAS_DEBUG_PRINTF != 0 )
\r
3018 if( xResult != ( int32_t ) ulByteCount )
\r
3020 FreeRTOS_debug_printf( ( "lTCPAddRxdata: at %ld: %ld/%lu bytes (tail %lu head %lu space %lu front %lu)\n",
\r
3021 uxOffset, xResult, ulByteCount,
\r
3024 uxStreamBufferFrontSpace( pxStream ),
\r
3025 pxStream->uxFront ) );
\r
3028 #endif /* ipconfigHAS_DEBUG_PRINTF */
\r
3030 if( uxOffset == 0u )
\r
3032 /* Data is being added to rxStream at the head (offs = 0) */
\r
3033 #if( ipconfigUSE_CALLBACKS == 1 )
\r
3034 if( bHasHandler != pdFALSE )
\r
3036 /* The socket owner has installed an OnReceive handler. Pass the
\r
3037 Rx data, without copying from the rxStream, to the user. */
\r
3040 uint8_t *ucReadPtr = NULL;
\r
3042 if( pucBuffer != NULL )
\r
3044 ucReadPtr = ( uint8_t * )pucBuffer;
\r
3045 ulCount = ulByteCount;
\r
3050 ulCount = ( uint32_t ) uxStreamBufferGetPtr( pxStream, &( ucReadPtr ) );
\r
3053 if( ulCount == 0ul )
\r
3058 if( pxSocket->u.xTCP.pxHandleReceive( (Socket_t *)pxSocket, ( void* )ucReadPtr, ( size_t ) ulCount ) != pdFALSE )
\r
3060 uxStreamBufferGet( pxStream, 0ul, NULL, ( size_t ) ulCount, pdFALSE );
\r
3064 #endif /* ipconfigUSE_CALLBACKS */
\r
3066 /* See if running out of space. */
\r
3067 if( pxSocket->u.xTCP.bits.bLowWater == pdFALSE_UNSIGNED )
\r
3069 size_t uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );
\r
3070 if( uxFrontSpace <= pxSocket->u.xTCP.uxLittleSpace )
\r
3072 pxSocket->u.xTCP.bits.bLowWater = pdTRUE_UNSIGNED;
\r
3073 pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
\r
3075 /* bLowWater was reached, send the changed window size. */
\r
3076 pxSocket->u.xTCP.usTimeout = 1u;
\r
3077 xSendEventToIPTask( eTCPTimerEvent );
\r
3081 /* New incoming data is available, wake up the user. User's
\r
3082 semaphores will be set just before the IP-task goes asleep. */
\r
3083 pxSocket->xEventBits |= eSOCKET_RECEIVE;
\r
3085 #if ipconfigSUPPORT_SELECT_FUNCTION == 1
\r
3087 if( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 )
\r
3089 pxSocket->xEventBits |= ( eSELECT_READ << SOCKET_EVENT_BIT_COUNT );
\r
3099 #endif /* ipconfigUSE_TCP */
\r
3100 /*-----------------------------------------------------------*/
\r
3102 #if( ipconfigUSE_TCP == 1 )
\r
3104 /* Function to get the remote address and IP port */
\r
3105 BaseType_t FreeRTOS_GetRemoteAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress )
\r
3107 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3108 BaseType_t xResult;
\r
3110 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3112 xResult = -pdFREERTOS_ERRNO_EINVAL;
\r
3116 /* BSD style sockets communicate IP and port addresses in network
\r
3119 IP address of remote machine. */
\r
3120 pxAddress->sin_addr = FreeRTOS_htonl ( pxSocket->u.xTCP.ulRemoteIP );
\r
3122 /* Port on remote machine. */
\r
3123 pxAddress->sin_port = FreeRTOS_htons ( pxSocket->u.xTCP.usRemotePort );
\r
3125 xResult = ( BaseType_t ) sizeof( ( *pxAddress ) );
\r
3131 #endif /* ipconfigUSE_TCP */
\r
3133 /*-----------------------------------------------------------*/
\r
3135 #if( ipconfigUSE_TCP == 1 )
\r
3137 /* Returns the number of bytes that may be added to txStream */
\r
3138 BaseType_t FreeRTOS_maywrite( Socket_t xSocket )
\r
3140 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3141 BaseType_t xResult;
\r
3143 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3145 xResult = -pdFREERTOS_ERRNO_EINVAL;
\r
3147 else if( pxSocket->u.xTCP.ucTCPState != eESTABLISHED )
\r
3149 if( ( pxSocket->u.xTCP.ucTCPState < eCONNECT_SYN ) || ( pxSocket->u.xTCP.ucTCPState > eESTABLISHED ) )
\r
3158 else if( pxSocket->u.xTCP.txStream == NULL )
\r
3160 xResult = ( BaseType_t ) pxSocket->u.xTCP.uxTxStreamSize;
\r
3164 xResult = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
\r
3170 #endif /* ipconfigUSE_TCP */
\r
3171 /*-----------------------------------------------------------*/
\r
3173 #if( ipconfigUSE_TCP ==1 )
\r
3175 BaseType_t FreeRTOS_tx_space( Socket_t xSocket )
\r
3177 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3178 BaseType_t xReturn;
\r
3180 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3182 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3186 if( pxSocket->u.xTCP.txStream != NULL )
\r
3188 xReturn = ( BaseType_t ) uxStreamBufferGetSpace ( pxSocket->u.xTCP.txStream );
\r
3192 xReturn = ( BaseType_t ) pxSocket->u.xTCP.uxTxStreamSize;
\r
3199 #endif /* ipconfigUSE_TCP */
\r
3200 /*-----------------------------------------------------------*/
\r
3202 #if( ipconfigUSE_TCP == 1 )
\r
3204 BaseType_t FreeRTOS_tx_size( Socket_t xSocket )
\r
3206 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3207 BaseType_t xReturn;
\r
3209 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3211 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3215 if( pxSocket->u.xTCP.txStream != NULL )
\r
3217 xReturn = ( BaseType_t ) uxStreamBufferGetSize ( pxSocket->u.xTCP.txStream );
\r
3228 #endif /* ipconfigUSE_TCP */
\r
3229 /*-----------------------------------------------------------*/
\r
3231 #if( ipconfigUSE_TCP == 1 )
\r
3233 /* Returns pdTRUE if TCP socket is connected. */
\r
3234 BaseType_t FreeRTOS_issocketconnected( Socket_t xSocket )
\r
3236 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3237 BaseType_t xReturn = pdFALSE;
\r
3239 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3241 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3245 if( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED )
\r
3247 if( pxSocket->u.xTCP.ucTCPState < eCLOSE_WAIT )
\r
3257 #endif /* ipconfigUSE_TCP */
\r
3258 /*-----------------------------------------------------------*/
\r
3260 #if( ipconfigUSE_TCP == 1 )
\r
3262 /* returns the actual size of MSS being used */
\r
3263 BaseType_t FreeRTOS_mss( Socket_t xSocket )
\r
3265 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3266 BaseType_t xReturn;
\r
3268 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3270 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3274 /* usCurMSS is declared as uint16_t to save space. FreeRTOS_mss()
\r
3275 will often be used in signed native-size expressions cast it to
\r
3277 xReturn = ( BaseType_t ) ( pxSocket->u.xTCP.usCurMSS );
\r
3283 #endif /* ipconfigUSE_TCP */
\r
3284 /*-----------------------------------------------------------*/
\r
3286 #if( ipconfigUSE_TCP == 1 )
\r
3288 /* HT: for internal use only: return the connection status */
\r
3289 BaseType_t FreeRTOS_connstatus( Socket_t xSocket )
\r
3291 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3292 BaseType_t xReturn;
\r
3294 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3296 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3300 /* Cast it to BaseType_t */
\r
3301 xReturn = ( BaseType_t ) ( pxSocket->u.xTCP.ucTCPState );
\r
3307 #endif /* ipconfigUSE_TCP */
\r
3308 /*-----------------------------------------------------------*/
\r
3310 #if( ipconfigUSE_TCP == 1 )
\r
3313 * Returns the number of bytes which can be read.
\r
3315 BaseType_t FreeRTOS_rx_size( Socket_t xSocket )
\r
3317 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3318 BaseType_t xReturn;
\r
3320 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3322 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3324 else if( pxSocket->u.xTCP.rxStream != NULL )
\r
3326 xReturn = ( BaseType_t ) uxStreamBufferGetSize( pxSocket->u.xTCP.rxStream );
\r
3336 #endif /* ipconfigUSE_TCP */
\r
3337 /*-----------------------------------------------------------*/
\r
3339 #if( ipconfigUSE_TCP == 1 )
\r
3341 void FreeRTOS_netstat( void )
\r
3343 IPStackEvent_t xAskEvent;
\r
3345 /* Ask the IP-task to call vTCPNetStat()
\r
3346 * to avoid accessing xBoundTCPSocketsList
\r
3348 xAskEvent.eEventType = eTCPNetStat;
\r
3349 xAskEvent.pvData = ( void * ) NULL;
\r
3350 xSendEventStructToIPTask( &xAskEvent, 1000u );
\r
3353 #endif /* ipconfigUSE_TCP */
\r
3354 /*-----------------------------------------------------------*/
\r
3356 #if( ( ipconfigHAS_PRINTF != 0 ) && ( ipconfigUSE_TCP == 1 ) )
\r
3358 void vTCPNetStat( void )
\r
3360 /* Show a simple listing of all created sockets and their connections */
\r
3361 ListItem_t *pxIterator;
\r
3362 BaseType_t count = 0;
\r
3364 if( listLIST_IS_INITIALISED( &xBoundTCPSocketsList ) == pdFALSE )
\r
3366 FreeRTOS_printf( ( "PLUS-TCP not initialized\n" ) );
\r
3370 FreeRTOS_printf( ( "Prot Port IP-Remote : Port R/T Status Alive tmout Child\n" ) );
\r
3371 for( pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );
\r
3372 pxIterator != ( ListItem_t * ) listGET_END_MARKER( &xBoundTCPSocketsList );
\r
3373 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
3375 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
\r
3376 #if( ipconfigTCP_KEEP_ALIVE == 1 )
\r
3377 TickType_t age = xTaskGetTickCount() - pxSocket->u.xTCP.xLastAliveTime;
\r
3379 TickType_t age = 0u;
\r
3381 #if( ipconfigUSE_CALLBACKS == 1 )
\r
3382 void *pxHandleReceive = (void*)pxSocket->u.xTCP.pxHandleReceive;
\r
3384 void *pxHandleReceive = (void*)NULL;
\r
3386 char ucChildText[16] = "";
\r
3387 if (pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN)
\r
3389 snprintf( ucChildText, sizeof( ucChildText ), " %d/%d",
\r
3390 pxSocket->u.xTCP.usChildCount,
\r
3391 pxSocket->u.xTCP.usBacklog);
\r
3393 if( age > 999999 )
\r
3395 FreeRTOS_printf( ( "TCP %5d %-16lxip:%5d %d/%d %-13.13s %6lu %6u%s\n",
\r
3396 pxSocket->usLocalPort, /* Local port on this machine */
\r
3397 pxSocket->u.xTCP.ulRemoteIP, /* IP address of remote machine */
\r
3398 pxSocket->u.xTCP.usRemotePort, /* Port on remote machine */
\r
3399 pxSocket->u.xTCP.rxStream != NULL,
\r
3400 pxSocket->u.xTCP.txStream != NULL,
\r
3401 FreeRTOS_GetTCPStateName( pxSocket->u.xTCP.ucTCPState ),
\r
3403 pxSocket->u.xTCP.usTimeout,
\r
3405 /* Remove compiler warnings if FreeRTOS_debug_printf() is not defined. */
\r
3406 ( void ) pxHandleReceive;
\r
3410 for( pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundUDPSocketsList );
\r
3411 pxIterator != ( ListItem_t * ) listGET_END_MARKER( &xBoundUDPSocketsList );
\r
3412 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
3414 /* Local port on this machine */
\r
3415 FreeRTOS_printf( ( "UDP Port %5u\n",
\r
3416 FreeRTOS_ntohs( listGET_LIST_ITEM_VALUE( pxIterator ) ) ) );
\r
3420 FreeRTOS_printf( ( "FreeRTOS_netstat: %lu sockets %lu < %lu < %d buffers free\n",
\r
3422 uxGetMinimumFreeNetworkBuffers( ),
\r
3423 uxGetNumberOfFreeNetworkBuffers( ),
\r
3424 ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ) );
\r
3428 #endif /* ( ( ipconfigHAS_PRINTF != 0 ) && ( ipconfigUSE_TCP == 1 ) ) */
\r
3429 /*-----------------------------------------------------------*/
\r
3431 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
3433 void vSocketSelect( SocketSelect_t *pxSocketSet )
\r
3435 BaseType_t xRound;
\r
3436 EventBits_t xSocketBits, xBitsToClear;
\r
3437 #if ipconfigUSE_TCP == 1
\r
3438 BaseType_t xLastRound = 1;
\r
3440 BaseType_t xLastRound = 0;
\r
3443 /* These flags will be switched on after checking the socket status. */
\r
3444 EventBits_t xGroupBits = 0;
\r
3445 pxSocketSet->pxSocket = NULL;
\r
3447 for( xRound = 0; xRound <= xLastRound; xRound++ )
\r
3449 const ListItem_t *pxIterator;
\r
3450 const MiniListItem_t *pxEnd;
\r
3453 pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundUDPSocketsList );
\r
3455 #if ipconfigUSE_TCP == 1
\r
3458 pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );
\r
3460 #endif /* ipconfigUSE_TCP == 1 */
\r
3461 for( pxIterator = ( const ListItem_t * ) ( listGET_NEXT( pxEnd ) );
\r
3462 pxIterator != ( const ListItem_t * ) pxEnd;
\r
3463 pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
3465 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
\r
3466 if( pxSocket->pxSocketSet != pxSocketSet )
\r
3468 /* Socket does not belong to this select group. */
\r
3473 #if( ipconfigUSE_TCP == 1 )
\r
3474 if( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP )
\r
3476 /* Check if the socket has already been accepted by the
\r
3477 owner. If not, it is useless to return it from a
\r
3479 BaseType_t bAccepted = pdFALSE;
\r
3481 if( pxSocket->u.xTCP.bits.bPassQueued == pdFALSE_UNSIGNED )
\r
3483 if( pxSocket->u.xTCP.bits.bPassAccept == pdFALSE_UNSIGNED )
\r
3485 bAccepted = pdTRUE;
\r
3489 /* Is the set owner interested in READ events? */
\r
3490 if( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 )
\r
3492 if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN )
\r
3494 if( ( pxSocket->u.xTCP.pxPeerSocket != NULL ) && ( pxSocket->u.xTCP.pxPeerSocket->u.xTCP.bits.bPassAccept != 0 ) )
\r
3496 xSocketBits |= eSELECT_READ;
\r
3499 else if( ( pxSocket->u.xTCP.bits.bReuseSocket != pdFALSE_UNSIGNED ) && ( pxSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED ) )
\r
3501 /* This socket has the re-use flag. After connecting it turns into
\r
3502 aconnected socket. Set the READ event, so that accept() will be called. */
\r
3503 xSocketBits |= eSELECT_READ;
\r
3505 else if( ( bAccepted != 0 ) && ( FreeRTOS_recvcount( pxSocket ) > 0 ) )
\r
3507 xSocketBits |= eSELECT_READ;
\r
3510 /* Is the set owner interested in EXCEPTION events? */
\r
3511 if( ( pxSocket->xSelectBits & eSELECT_EXCEPT ) != 0 )
\r
3513 if( ( pxSocket->u.xTCP.ucTCPState == eCLOSE_WAIT ) || ( pxSocket->u.xTCP.ucTCPState == eCLOSED ) )
\r
3515 xSocketBits |= eSELECT_EXCEPT;
\r
3519 /* Is the set owner interested in WRITE events? */
\r
3520 if( ( pxSocket->xSelectBits & eSELECT_WRITE ) != 0 )
\r
3522 BaseType_t bMatch = pdFALSE;
\r
3524 if( bAccepted != 0 )
\r
3526 if( FreeRTOS_tx_space( pxSocket ) > 0 )
\r
3532 if( bMatch == pdFALSE )
\r
3534 if( ( pxSocket->u.xTCP.bits.bConnPrepared != pdFALSE_UNSIGNED ) &&
\r
3535 ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) &&
\r
3536 ( pxSocket->u.xTCP.bits.bConnPassed == pdFALSE_UNSIGNED ) )
\r
3538 pxSocket->u.xTCP.bits.bConnPassed = pdTRUE_UNSIGNED;
\r
3543 if( bMatch != pdFALSE )
\r
3545 xSocketBits |= eSELECT_WRITE;
\r
3550 #endif /* ipconfigUSE_TCP == 1 */
\r
3552 /* Select events for UDP are simpler. */
\r
3553 if( ( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 ) &&
\r
3554 ( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) > 0U ) )
\r
3556 xSocketBits |= eSELECT_READ;
\r
3558 /* The WRITE and EXCEPT bits are not used for UDP */
\r
3559 } /* if( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP ) */
\r
3561 /* Each socket keeps its own event flags, which are looked-up
\r
3562 by FreeRTOS_FD_ISSSET() */
\r
3563 pxSocket->xSocketBits = xSocketBits;
\r
3565 /* The ORed value will be used to set the bits in the event
\r
3567 xGroupBits |= xSocketBits;
\r
3569 } /* for( pxIterator ... ) */
\r
3570 } /* for( xRound = 0; xRound <= xLastRound; xRound++ ) */
\r
3572 xBitsToClear = xEventGroupGetBits( pxSocketSet->xSelectGroup );
\r
3574 /* Now set the necessary bits. */
\r
3575 xBitsToClear = ( xBitsToClear & ~xGroupBits ) & eSELECT_ALL;
\r
3577 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
3579 /* Maybe the socketset was signalled, but don't
\r
3580 clear the 'eSELECT_INTR' bit here, as it will be used
\r
3581 and cleared in FreeRTOS_select(). */
\r
3582 xBitsToClear &= ( EventBits_t ) ~eSELECT_INTR;
\r
3584 #endif /* ipconfigSUPPORT_SIGNALS */
\r
3586 if( xBitsToClear != 0 )
\r
3588 xEventGroupClearBits( pxSocketSet->xSelectGroup, xBitsToClear );
\r
3591 /* Now include eSELECT_CALL_IP to wakeup the caller. */
\r
3592 xEventGroupSetBits( pxSocketSet->xSelectGroup, xGroupBits | eSELECT_CALL_IP );
\r
3595 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
3596 /*-----------------------------------------------------------*/
\r
3598 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
3600 /* Send a signal to the task which reads from this socket. */
\r
3601 BaseType_t FreeRTOS_SignalSocket( Socket_t xSocket )
\r
3603 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3604 BaseType_t xReturn;
\r
3606 if( pxSocket == NULL )
\r
3608 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3611 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
3612 if( ( pxSocket->pxSocketSet != NULL ) && ( pxSocket->pxSocketSet->xSelectGroup != NULL ) )
\r
3614 xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, eSELECT_INTR );
\r
3618 #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
\r
3619 if( pxSocket->xEventGroup != NULL )
\r
3621 xEventGroupSetBits( pxSocket->xEventGroup, eSOCKET_INTR );
\r
3626 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3632 #endif /* ipconfigSUPPORT_SIGNALS */
\r
3633 /*-----------------------------------------------------------*/
\r
3635 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
3637 /* Send a signal to the task which reads from this socket (FromISR version). */
\r
3638 BaseType_t FreeRTOS_SignalSocketFromISR( Socket_t xSocket, BaseType_t *pxHigherPriorityTaskWoken )
\r
3640 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3641 BaseType_t xReturn;
\r
3642 IPStackEvent_t xEvent;
\r
3643 extern QueueHandle_t xNetworkEventQueue;
\r
3645 configASSERT( pxSocket != NULL );
\r
3646 configASSERT( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP );
\r
3647 configASSERT( pxSocket->xEventGroup );
\r
3649 xEvent.eEventType = eSocketSignalEvent;
\r
3650 xEvent.pvData = ( void * )pxSocket;
\r
3652 /* The IP-task will call FreeRTOS_SignalSocket for this socket. */
\r
3653 xReturn = xQueueSendToBackFromISR( xNetworkEventQueue, &xEvent, pxHigherPriorityTaskWoken );
\r
3658 #endif /* ipconfigSUPPORT_SIGNALS */
\r
3659 /*-----------------------------------------------------------*/
\r