2 * FreeRTOS+TCP V2.2.0
\r
3 * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\r
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
\r
6 * this software and associated documentation files (the "Software"), to deal in
\r
7 * the Software without restriction, including without limitation the rights to
\r
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
\r
9 * the Software, and to permit persons to whom the Software is furnished to do so,
\r
10 * subject to the following conditions:
\r
12 * The above copyright notice and this permission notice shall be included in all
\r
13 * copies or substantial portions of the Software.
\r
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
\r
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
\r
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
\r
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
22 * http://aws.amazon.com/freertos
\r
23 * http://www.FreeRTOS.org
\r
26 /* Standard includes. */
\r
30 /* FreeRTOS includes. */
\r
31 #include "FreeRTOS.h"
\r
36 /* FreeRTOS+TCP includes. */
\r
37 #include "FreeRTOS_UDP_IP.h"
\r
38 #include "FreeRTOS_IP.h"
\r
39 #include "FreeRTOS_Sockets.h"
\r
40 #include "FreeRTOS_IP_Private.h"
\r
41 #include "FreeRTOS_DNS.h"
\r
42 #include "NetworkBufferManagement.h"
\r
44 /* The ItemValue of the sockets xBoundSocketListItem member holds the socket's
\r
46 #define socketSET_SOCKET_PORT( pxSocket, usPort ) listSET_LIST_ITEM_VALUE( ( &( ( pxSocket )->xBoundSocketListItem ) ), ( usPort ) )
\r
47 #define socketGET_SOCKET_PORT( pxSocket ) listGET_LIST_ITEM_VALUE( ( &( ( pxSocket )->xBoundSocketListItem ) ) )
\r
49 /* Test if a socket it bound which means it is either included in
\r
50 xBoundUDPSocketsList or xBoundTCPSocketsList */
\r
51 #define socketSOCKET_IS_BOUND( pxSocket ) ( listLIST_ITEM_CONTAINER( & ( pxSocket )->xBoundSocketListItem ) != NULL )
\r
53 /* If FreeRTOS_sendto() is called on a socket that is not bound to a port
\r
54 number then, depending on the FreeRTOSIPConfig.h settings, it might be that a
\r
55 port number is automatically generated for the socket. Automatically generated
\r
56 port numbers will be between socketAUTO_PORT_ALLOCATION_START_NUMBER and
\r
59 Per https://tools.ietf.org/html/rfc6056, "the dynamic ports consist of the range
\r
60 49152-65535. However, ephemeral port selection algorithms should use the whole
\r
61 range 1024-65535" excluding those already in use (inbound or outbound). */
\r
62 #if !defined( socketAUTO_PORT_ALLOCATION_START_NUMBER )
\r
63 #define socketAUTO_PORT_ALLOCATION_START_NUMBER ( ( uint16_t ) 0x0400 )
\r
66 #define socketAUTO_PORT_ALLOCATION_MAX_NUMBER ( ( uint16_t ) 0xffff )
\r
68 /* The number of octets that make up an IP address. */
\r
69 #define socketMAX_IP_ADDRESS_OCTETS 4u
\r
71 /* A block time of 0 simply means "don't block". */
\r
72 #define socketDONT_BLOCK ( ( TickType_t ) 0 )
\r
74 #if( ( ipconfigUSE_TCP == 1 ) && !defined( ipTCP_TIMER_PERIOD_MS ) )
\r
75 #define ipTCP_TIMER_PERIOD_MS ( 1000 )
\r
78 /* The next private port number to use when binding a client socket is stored in
\r
79 the usNextPortToUse[] array - which has either 1 or two indexes depending on
\r
80 whether TCP is being supported. */
\r
81 #if( ipconfigUSE_TCP == 1 )
\r
82 #define socketPROTOCOL_COUNT 2
\r
84 #define socketPROTOCOL_COUNT 1
\r
87 /* Indexes into the usNextPortToUse[] array for UDP and TCP sockets
\r
89 #define socketNEXT_UDP_PORT_NUMBER_INDEX 0
\r
90 #define socketNEXT_TCP_PORT_NUMBER_INDEX 1
\r
92 /* Some helper macro's for defining the 20/80 % limits of uxLittleSpace / uxEnoughSpace. */
\r
93 #define sock20_PERCENT 20
\r
94 #define sock80_PERCENT 80
\r
95 #define sock100_PERCENT 100
\r
98 /*-----------------------------------------------------------*/
\r
101 * Allocate the next port number from the private allocation range.
\r
102 * TCP and UDP each have their own series of port numbers
\r
103 * ulProtocol is either ipPROTOCOL_UDP or ipPROTOCOL_TCP
\r
105 static uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol );
\r
108 * Return the list item from within pxList that has an item value of
\r
109 * xWantedItemValue. If there is no such list item return NULL.
\r
111 static const ListItem_t * pxListFindListItemWithValue( const List_t *pxList, TickType_t xWantedItemValue );
\r
114 * Return pdTRUE only if pxSocket is valid and bound, as far as can be
\r
117 static BaseType_t prvValidSocket( FreeRTOS_Socket_t *pxSocket, BaseType_t xProtocol, BaseType_t xIsBound );
\r
120 * Before creating a socket, check the validity of the parameters used
\r
121 * and find the size of the socket space, which is different for UDP and TCP
\r
123 static BaseType_t prvDetermineSocketSize( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol, size_t *pxSocketSize );
\r
125 #if( ipconfigUSE_TCP == 1 )
\r
127 * Create a txStream or a rxStream, depending on the parameter 'xIsInputStream'
\r
129 static StreamBuffer_t *prvTCPCreateStream (FreeRTOS_Socket_t *pxSocket, BaseType_t xIsInputStream );
\r
130 #endif /* ipconfigUSE_TCP == 1 */
\r
132 #if( ipconfigUSE_TCP == 1 )
\r
134 * Called from FreeRTOS_send(): some checks which will be done before
\r
135 * sending a TCP packed.
\r
137 static int32_t prvTCPSendCheck( FreeRTOS_Socket_t *pxSocket, size_t xDataLength );
\r
138 #endif /* ipconfigUSE_TCP */
\r
140 #if( ipconfigUSE_TCP == 1 )
\r
142 * When a child socket gets closed, make sure to update the child-count of the parent
\r
144 static void prvTCPSetSocketCount( FreeRTOS_Socket_t *pxSocketToDelete );
\r
145 #endif /* ipconfigUSE_TCP == 1 */
\r
147 #if( ipconfigUSE_TCP == 1 )
\r
149 * Called from FreeRTOS_connect(): make some checks and if allowed, send a
\r
150 * message to the IP-task to start connecting to a remote socket
\r
152 static BaseType_t prvTCPConnectStart( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr *pxAddress );
\r
153 #endif /* ipconfigUSE_TCP */
\r
155 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
157 /* Executed by the IP-task, it will check all sockets belonging to a set */
\r
158 static FreeRTOS_Socket_t *prvFindSelectedSocket( SocketSelect_t *pxSocketSet );
\r
160 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
161 /*-----------------------------------------------------------*/
\r
163 /* The list that contains mappings between sockets and port numbers. Accesses
\r
164 to this list must be protected by critical sections of one kind or another. */
\r
165 List_t xBoundUDPSocketsList;
\r
167 #if ipconfigUSE_TCP == 1
\r
168 List_t xBoundTCPSocketsList;
\r
169 #endif /* ipconfigUSE_TCP == 1 */
\r
171 /*-----------------------------------------------------------*/
\r
173 static BaseType_t prvValidSocket( FreeRTOS_Socket_t *pxSocket, BaseType_t xProtocol, BaseType_t xIsBound )
\r
175 BaseType_t xReturn = pdTRUE;
\r
177 if( ( pxSocket == NULL ) || ( pxSocket == FREERTOS_INVALID_SOCKET ) )
\r
181 else if( ( xIsBound != pdFALSE ) && ( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE ) )
\r
183 /* The caller expects the socket to be bound, but it isn't. */
\r
186 else if( pxSocket->ucProtocol != ( uint8_t ) xProtocol )
\r
188 /* Socket has a wrong type (UDP != TCP). */
\r
194 /*-----------------------------------------------------------*/
\r
196 BaseType_t vNetworkSocketsInit( void )
\r
198 vListInitialise( &xBoundUDPSocketsList );
\r
200 #if( ipconfigUSE_TCP == 1 )
\r
202 vListInitialise( &xBoundTCPSocketsList );
\r
204 #endif /* ipconfigUSE_TCP == 1 */
\r
208 /*-----------------------------------------------------------*/
\r
210 static BaseType_t prvDetermineSocketSize( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol, size_t *pxSocketSize )
\r
212 BaseType_t xReturn = pdPASS;
\r
213 FreeRTOS_Socket_t *pxSocket;
\r
215 /* Asserts must not appear before it has been determined that the network
\r
216 task is ready - otherwise the asserts will fail. */
\r
217 if( xIPIsNetworkTaskReady() == pdFALSE )
\r
223 /* Only Ethernet is currently supported. */
\r
224 configASSERT( xDomain == FREERTOS_AF_INET );
\r
226 /* Check if the UDP socket-list has been initialised. */
\r
227 configASSERT( listLIST_IS_INITIALISED( &xBoundUDPSocketsList ) );
\r
228 #if( ipconfigUSE_TCP == 1 )
\r
230 /* Check if the TCP socket-list has been initialised. */
\r
231 configASSERT( listLIST_IS_INITIALISED( &xBoundTCPSocketsList ) );
\r
233 #endif /* ipconfigUSE_TCP == 1 */
\r
235 if( xProtocol == FREERTOS_IPPROTO_UDP )
\r
237 if( xType != FREERTOS_SOCK_DGRAM )
\r
240 configASSERT( xReturn );
\r
242 /* In case a UDP socket is created, do not allocate space for TCP data. */
\r
243 *pxSocketSize = ( sizeof( *pxSocket ) - sizeof( pxSocket->u ) ) + sizeof( pxSocket->u.xUDP );
\r
245 #if( ipconfigUSE_TCP == 1 )
\r
246 else if( xProtocol == FREERTOS_IPPROTO_TCP )
\r
248 if( xType != FREERTOS_SOCK_STREAM )
\r
251 configASSERT( xReturn );
\r
254 *pxSocketSize = ( sizeof( *pxSocket ) - sizeof( pxSocket->u ) ) + sizeof( pxSocket->u.xTCP );
\r
256 #endif /* ipconfigUSE_TCP == 1 */
\r
260 configASSERT( xReturn );
\r
263 /* In case configASSERT() is not used */
\r
267 /*-----------------------------------------------------------*/
\r
269 /* FreeRTOS_socket() allocates and initiates a socket */
\r
270 Socket_t FreeRTOS_socket( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol )
\r
272 FreeRTOS_Socket_t *pxSocket;
\r
273 size_t uxSocketSize;
\r
274 EventGroupHandle_t xEventGroup;
\r
277 if( prvDetermineSocketSize( xDomain, xType, xProtocol, &uxSocketSize ) == pdFAIL )
\r
279 xReturn = FREERTOS_INVALID_SOCKET;
\r
283 /* Allocate the structure that will hold the socket information. The
\r
284 size depends on the type of socket: UDP sockets need less space. A
\r
285 define 'pvPortMallocSocket' will used to allocate the necessary space.
\r
286 By default it points to the FreeRTOS function 'pvPortMalloc()'. */
\r
287 pxSocket = ( FreeRTOS_Socket_t * ) pvPortMallocSocket( uxSocketSize );
\r
289 if( pxSocket == NULL )
\r
291 pxSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
\r
292 iptraceFAILED_TO_CREATE_SOCKET();
\r
294 else if( ( xEventGroup = xEventGroupCreate() ) == NULL )
\r
296 vPortFreeSocket( pxSocket );
\r
297 pxSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
\r
298 iptraceFAILED_TO_CREATE_EVENT_GROUP();
\r
302 /* Clear the entire space to avoid nulling individual entries */
\r
303 memset( pxSocket, '\0', uxSocketSize );
\r
305 pxSocket->xEventGroup = xEventGroup;
\r
307 /* Initialise the socket's members. The semaphore will be created
\r
308 if the socket is bound to an address, for now the pointer to the
\r
309 semaphore is just set to NULL to show it has not been created. */
\r
310 if( xProtocol == FREERTOS_IPPROTO_UDP )
\r
312 vListInitialise( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
\r
314 #if( ipconfigUDP_MAX_RX_PACKETS > 0 )
\r
316 pxSocket->u.xUDP.uxMaxPackets = ( UBaseType_t ) ipconfigUDP_MAX_RX_PACKETS;
\r
318 #endif /* ipconfigUDP_MAX_RX_PACKETS > 0 */
\r
321 vListInitialiseItem( &( pxSocket->xBoundSocketListItem ) );
\r
322 listSET_LIST_ITEM_OWNER( &( pxSocket->xBoundSocketListItem ), ( void * ) pxSocket );
\r
324 pxSocket->xReceiveBlockTime = ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME;
\r
325 pxSocket->xSendBlockTime = ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME;
\r
326 pxSocket->ucSocketOptions = ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT;
\r
327 pxSocket->ucProtocol = ( uint8_t ) xProtocol; /* protocol: UDP or TCP */
\r
329 #if( ipconfigUSE_TCP == 1 )
\r
331 if( xProtocol == FREERTOS_IPPROTO_TCP )
\r
333 /* StreamSize is expressed in number of bytes */
\r
334 /* Round up buffer sizes to nearest multiple of MSS */
\r
335 pxSocket->u.xTCP.usInitMSS = pxSocket->u.xTCP.usCurMSS = ipconfigTCP_MSS;
\r
336 pxSocket->u.xTCP.uxRxStreamSize = ( size_t ) ipconfigTCP_RX_BUFFER_LENGTH;
\r
337 pxSocket->u.xTCP.uxTxStreamSize = ( size_t ) FreeRTOS_round_up( ipconfigTCP_TX_BUFFER_LENGTH, ipconfigTCP_MSS );
\r
338 /* Use half of the buffer size of the TCP windows */
\r
339 #if ( ipconfigUSE_TCP_WIN == 1 )
\r
341 pxSocket->u.xTCP.uxRxWinSize = FreeRTOS_max_uint32( 1UL, ( uint32_t ) ( pxSocket->u.xTCP.uxRxStreamSize / 2 ) / ipconfigTCP_MSS );
\r
342 pxSocket->u.xTCP.uxTxWinSize = FreeRTOS_max_uint32( 1UL, ( uint32_t ) ( pxSocket->u.xTCP.uxTxStreamSize / 2 ) / ipconfigTCP_MSS );
\r
346 pxSocket->u.xTCP.uxRxWinSize = 1u;
\r
347 pxSocket->u.xTCP.uxTxWinSize = 1u;
\r
350 /* The above values are just defaults, and can be overridden by
\r
351 calling FreeRTOS_setsockopt(). No buffers will be allocated until a
\r
352 socket is connected and data is exchanged. */
\r
355 #endif /* ipconfigUSE_TCP == 1 */
\r
358 xReturn = ( Socket_t ) pxSocket;
\r
361 /* Remove compiler warnings in the case the configASSERT() is not defined. */
\r
366 /*-----------------------------------------------------------*/
\r
368 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
370 SocketSet_t FreeRTOS_CreateSocketSet( void )
\r
372 SocketSelect_t *pxSocketSet;
\r
374 pxSocketSet = ( SocketSelect_t * ) pvPortMalloc( sizeof( *pxSocketSet ) );
\r
376 if( pxSocketSet != NULL )
\r
378 memset( pxSocketSet, '\0', sizeof( *pxSocketSet ) );
\r
379 pxSocketSet->xSelectGroup = xEventGroupCreate();
\r
381 if( pxSocketSet->xSelectGroup == NULL )
\r
383 vPortFree( ( void* ) pxSocketSet );
\r
384 pxSocketSet = NULL;
\r
388 return ( SocketSet_t ) pxSocketSet;
\r
391 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
392 /*-----------------------------------------------------------*/
\r
394 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
396 void FreeRTOS_DeleteSocketSet( SocketSet_t xSocketSet )
\r
398 SocketSelect_t *pxSocketSet = ( SocketSelect_t*) xSocketSet;
\r
400 vEventGroupDelete( pxSocketSet->xSelectGroup );
\r
401 vPortFree( ( void* ) pxSocketSet );
\r
404 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
405 /*-----------------------------------------------------------*/
\r
407 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
409 /* Add a socket to a set */
\r
410 void FreeRTOS_FD_SET( Socket_t xSocket, SocketSet_t xSocketSet, EventBits_t xSelectBits )
\r
412 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
413 SocketSelect_t *pxSocketSet = ( SocketSelect_t * ) xSocketSet;
\r
415 configASSERT( pxSocket != NULL );
\r
416 configASSERT( xSocketSet != NULL );
\r
418 /* Make sure we're not adding bits which are reserved for internal use,
\r
419 such as eSELECT_CALL_IP */
\r
420 pxSocket->xSelectBits |= ( xSelectBits & eSELECT_ALL );
\r
422 if( ( pxSocket->xSelectBits & eSELECT_ALL ) != 0 )
\r
424 /* Adding a socket to a socket set. */
\r
425 pxSocket->pxSocketSet = ( SocketSelect_t * ) xSocketSet;
\r
427 /* Now have the IP-task call vSocketSelect() to see if the set contains
\r
428 any sockets which are 'ready' and set the proper bits.
\r
429 By setting 'bApiCalled = false', vSocketSelect() knows that it was
\r
430 not called from a user API */
\r
431 pxSocketSet->bApiCalled = pdFALSE;
\r
432 prvFindSelectedSocket( pxSocketSet );
\r
436 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
437 /*-----------------------------------------------------------*/
\r
439 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
440 /* Clear select bits for a socket
\r
441 If the mask becomes 0, remove the socket from the set */
\r
442 void FreeRTOS_FD_CLR( Socket_t xSocket, SocketSet_t xSocketSet, EventBits_t xSelectBits )
\r
444 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
446 configASSERT( pxSocket != NULL );
\r
447 configASSERT( xSocketSet != NULL );
\r
449 pxSocket->xSelectBits &= ~( xSelectBits & eSELECT_ALL );
\r
450 if( ( pxSocket->xSelectBits & eSELECT_ALL ) != 0 )
\r
452 pxSocket->pxSocketSet = ( SocketSelect_t *)xSocketSet;
\r
456 /* disconnect it from the socket set */
\r
457 pxSocket->pxSocketSet = ( SocketSelect_t *)NULL;
\r
461 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
462 /*-----------------------------------------------------------*/
\r
465 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
467 /* Test if a socket belongs to a socket-set */
\r
468 EventBits_t FreeRTOS_FD_ISSET( Socket_t xSocket, SocketSet_t xSocketSet )
\r
470 EventBits_t xReturn;
\r
471 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
473 configASSERT( pxSocket != NULL );
\r
474 configASSERT( xSocketSet != NULL );
\r
476 if( xSocketSet == ( SocketSet_t ) pxSocket->pxSocketSet )
\r
478 /* Make sure we're not adding bits which are reserved for internal
\r
480 xReturn = pxSocket->xSocketBits & eSELECT_ALL;
\r
490 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
491 /*-----------------------------------------------------------*/
\r
493 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
495 /* The select() statement: wait for an event to occur on any of the sockets
\r
496 included in a socket set */
\r
497 BaseType_t FreeRTOS_select( SocketSet_t xSocketSet, TickType_t xBlockTimeTicks )
\r
499 TimeOut_t xTimeOut;
\r
500 TickType_t xRemainingTime;
\r
501 SocketSelect_t *pxSocketSet = ( SocketSelect_t*) xSocketSet;
\r
502 BaseType_t xResult;
\r
504 configASSERT( xSocketSet != NULL );
\r
506 /* Only in the first round, check for non-blocking */
\r
507 xRemainingTime = xBlockTimeTicks;
\r
509 /* Fetch the current time */
\r
510 vTaskSetTimeOutState( &xTimeOut );
\r
514 /* Find a socket which might have triggered the bit
\r
515 This function might return immediately or block for a limited time */
\r
516 xResult = ( BaseType_t ) xEventGroupWaitBits( pxSocketSet->xSelectGroup, eSELECT_ALL, pdFALSE, pdFALSE, xRemainingTime );
\r
518 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
520 if( ( xResult & eSELECT_INTR ) != 0u )
\r
522 xEventGroupClearBits( pxSocketSet->xSelectGroup, eSELECT_INTR );
\r
523 FreeRTOS_debug_printf( ( "FreeRTOS_select: interrupted\n" ) );
\r
527 #endif /* ipconfigSUPPORT_SIGNALS */
\r
529 /* Have the IP-task find the socket which had an event */
\r
530 pxSocketSet->bApiCalled = pdTRUE;
\r
531 prvFindSelectedSocket( pxSocketSet );
\r
533 xResult = ( BaseType_t ) xEventGroupGetBits( pxSocketSet->xSelectGroup );
\r
540 /* Has the timeout been reached? */
\r
541 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
\r
550 #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
\r
551 /*-----------------------------------------------------------*/
\r
553 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
555 /* Send a message to the IP-task to have it check all sockets belonging to
\r
557 static FreeRTOS_Socket_t *prvFindSelectedSocket( SocketSelect_t *pxSocketSet )
\r
559 IPStackEvent_t xSelectEvent;
\r
560 FreeRTOS_Socket_t *xReturn;
\r
562 xSelectEvent.eEventType = eSocketSelectEvent;
\r
563 xSelectEvent.pvData = ( void * ) pxSocketSet;
\r
565 /* while the IP-task works on the request, the API will block on
\r
566 'eSELECT_CALL_IP'. So clear it first. */
\r
567 xEventGroupClearBits( pxSocketSet->xSelectGroup, eSELECT_CALL_IP );
\r
569 /* Now send the socket select event */
\r
570 if( xSendEventStructToIPTask( &xSelectEvent, ( TickType_t ) portMAX_DELAY ) == pdFAIL )
\r
572 /* Oops, we failed to wake-up the IP task. No use to wait for it. */
\r
573 FreeRTOS_debug_printf( ( "prvFindSelectedSocket: failed\n" ) );
\r
578 /* As soon as the IP-task is ready, it will set 'eSELECT_CALL_IP' to
\r
579 wakeup the calling API */
\r
580 xEventGroupWaitBits( pxSocketSet->xSelectGroup, eSELECT_CALL_IP, pdTRUE, pdFALSE, portMAX_DELAY );
\r
582 /* Return 'pxSocket' which is set by the IP-task */
\r
583 xReturn = pxSocketSet->pxSocket;
\r
589 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
590 /*-----------------------------------------------------------*/
\r
593 * FreeRTOS_recvfrom: receive data from a bound socket
\r
594 * In this library, the function can only be used with connectionsless sockets
\r
597 int32_t FreeRTOS_recvfrom( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags, struct freertos_sockaddr *pxSourceAddress, socklen_t *pxSourceAddressLength )
\r
599 BaseType_t lPacketCount = 0;
\r
600 NetworkBufferDescriptor_t *pxNetworkBuffer;
\r
601 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
602 TickType_t xRemainingTime = ( TickType_t ) 0; /* Obsolete assignment, but some compilers output a warning if its not done. */
\r
603 BaseType_t xTimed = pdFALSE;
\r
604 TimeOut_t xTimeOut;
\r
606 EventBits_t xEventBits = ( EventBits_t ) 0;
\r
608 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_UDP, pdTRUE ) == pdFALSE )
\r
610 return -pdFREERTOS_ERRNO_EINVAL;
\r
613 lPacketCount = ( BaseType_t ) listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
\r
615 /* The function prototype is designed to maintain the expected Berkeley
\r
616 sockets standard, but this implementation does not use all the parameters. */
\r
617 ( void ) pxSourceAddressLength;
\r
619 while( lPacketCount == 0 )
\r
621 if( xTimed == pdFALSE )
\r
623 /* Check to see if the socket is non blocking on the first
\r
625 xRemainingTime = pxSocket->xReceiveBlockTime;
\r
627 if( xRemainingTime == ( TickType_t ) 0 )
\r
629 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
631 /* Just check for the interrupt flag. */
\r
632 xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_INTR,
\r
633 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, socketDONT_BLOCK );
\r
635 #endif /* ipconfigSUPPORT_SIGNALS */
\r
639 if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
\r
644 /* To ensure this part only executes once. */
\r
647 /* Fetch the current time. */
\r
648 vTaskSetTimeOutState( &xTimeOut );
\r
651 /* Wait for arrival of data. While waiting, the IP-task may set the
\r
652 'eSOCKET_RECEIVE' bit in 'xEventGroup', if it receives data for this
\r
653 socket, thus unblocking this API call. */
\r
654 xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_RECEIVE | eSOCKET_INTR,
\r
655 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
657 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
659 if( ( xEventBits & eSOCKET_INTR ) != 0 )
\r
661 if( ( xEventBits & eSOCKET_RECEIVE ) != 0 )
\r
663 /* Shouldn't have cleared the eSOCKET_RECEIVE flag. */
\r
664 xEventGroupSetBits( pxSocket->xEventGroup, eSOCKET_RECEIVE );
\r
671 ( void ) xEventBits;
\r
673 #endif /* ipconfigSUPPORT_SIGNALS */
\r
675 lPacketCount = ( BaseType_t ) listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
\r
677 if( lPacketCount != 0 )
\r
682 /* Has the timeout been reached ? */
\r
683 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) )
\r
687 } /* while( lPacketCount == 0 ) */
\r
689 if( lPacketCount != 0 )
\r
691 taskENTER_CRITICAL();
\r
693 /* The owner of the list item is the network buffer. */
\r
694 pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
\r
696 if( ( xFlags & FREERTOS_MSG_PEEK ) == 0 )
\r
698 /* Remove the network buffer from the list of buffers waiting to
\r
699 be processed by the socket. */
\r
700 uxListRemove( &( pxNetworkBuffer->xBufferListItem ) );
\r
703 taskEXIT_CRITICAL();
\r
705 /* The returned value is the length of the payload data, which is
\r
706 calculated at the total packet size minus the headers.
\r
707 The validity of `xDataLength` prvProcessIPPacket has been confirmed
\r
708 in 'prvProcessIPPacket()'. */
\r
709 lReturn = ( int32_t ) ( pxNetworkBuffer->xDataLength - sizeof( UDPPacket_t ) );
\r
711 if( pxSourceAddress != NULL )
\r
713 pxSourceAddress->sin_port = pxNetworkBuffer->usPort;
\r
714 pxSourceAddress->sin_addr = pxNetworkBuffer->ulIPAddress;
\r
717 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
\r
719 /* The zero copy flag is not set. Truncate the length if it won't
\r
720 fit in the provided buffer. */
\r
721 if( lReturn > ( int32_t ) xBufferLength )
\r
723 iptraceRECVFROM_DISCARDING_BYTES( ( xBufferLength - lReturn ) );
\r
724 lReturn = ( int32_t )xBufferLength;
\r
727 /* Copy the received data into the provided buffer, then release the
\r
729 memcpy( pvBuffer, ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ), ( size_t )lReturn );
\r
731 if( ( xFlags & FREERTOS_MSG_PEEK ) == 0 )
\r
733 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
\r
738 /* The zero copy flag was set. pvBuffer is not a buffer into which
\r
739 the received data can be copied, but a pointer that must be set to
\r
740 point to the buffer in which the received data has already been
\r
742 *( ( void** ) pvBuffer ) = ( void * ) ( &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ) );
\r
746 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
747 else if( ( xEventBits & eSOCKET_INTR ) != 0 )
\r
749 lReturn = -pdFREERTOS_ERRNO_EINTR;
\r
750 iptraceRECVFROM_INTERRUPTED();
\r
752 #endif /* ipconfigSUPPORT_SIGNALS */
\r
755 lReturn = -pdFREERTOS_ERRNO_EWOULDBLOCK;
\r
756 iptraceRECVFROM_TIMEOUT();
\r
761 /*-----------------------------------------------------------*/
\r
763 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
765 NetworkBufferDescriptor_t *pxNetworkBuffer;
\r
766 IPStackEvent_t xStackTxEvent = { eStackTxEvent, NULL };
\r
767 TimeOut_t xTimeOut;
\r
768 TickType_t xTicksToWait;
\r
769 int32_t lReturn = 0;
\r
770 FreeRTOS_Socket_t *pxSocket;
\r
772 pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
774 /* The function prototype is designed to maintain the expected Berkeley
\r
775 sockets standard, but this implementation does not use all the
\r
777 ( void ) xDestinationAddressLength;
\r
778 configASSERT( pvBuffer );
\r
780 if( xTotalDataLength <= ( size_t ) ipMAX_UDP_PAYLOAD_LENGTH )
\r
782 /* If the socket is not already bound to an address, bind it now.
\r
783 Passing NULL as the address parameter tells FreeRTOS_bind() to select
\r
784 the address to bind to. */
\r
785 if( ( socketSOCKET_IS_BOUND( pxSocket ) != pdFALSE ) ||
\r
786 ( FreeRTOS_bind( xSocket, NULL, 0u ) == 0 ) )
\r
788 xTicksToWait = pxSocket->xSendBlockTime;
\r
790 #if( ipconfigUSE_CALLBACKS != 0 )
\r
792 if( xIsCallingFromIPTask() != pdFALSE )
\r
794 /* If this send function is called from within a call-back
\r
795 handler it may not block, otherwise chances would be big to
\r
796 get a deadlock: the IP-task waiting for itself. */
\r
797 xTicksToWait = ( TickType_t )0;
\r
800 #endif /* ipconfigUSE_CALLBACKS */
\r
802 if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
\r
804 xTicksToWait = ( TickType_t ) 0;
\r
807 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
\r
809 /* Zero copy is not set, so obtain a network buffer into
\r
810 which the payload will be copied. */
\r
811 vTaskSetTimeOutState( &xTimeOut );
\r
813 /* Block until a buffer becomes available, or until a
\r
814 timeout has been reached */
\r
815 pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( xTotalDataLength + sizeof( UDPPacket_t ), xTicksToWait );
\r
817 if( pxNetworkBuffer != NULL )
\r
819 memcpy( ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ), ( void * ) pvBuffer, xTotalDataLength );
\r
821 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdTRUE )
\r
823 /* The entire block time has been used up. */
\r
824 xTicksToWait = ( TickType_t ) 0;
\r
830 /* When zero copy is used, pvBuffer is a pointer to the
\r
831 payload of a buffer that has already been obtained from the
\r
832 stack. Obtain the network buffer pointer from the buffer. */
\r
833 pxNetworkBuffer = pxUDPPayloadBuffer_to_NetworkBuffer( (void*)pvBuffer );
\r
836 if( pxNetworkBuffer != NULL )
\r
838 /* xDataLength is the size of the total packet, including the Ethernet header. */
\r
839 pxNetworkBuffer->xDataLength = xTotalDataLength + sizeof( UDPPacket_t );
\r
840 pxNetworkBuffer->usPort = pxDestinationAddress->sin_port;
\r
841 pxNetworkBuffer->usBoundPort = ( uint16_t ) socketGET_SOCKET_PORT( pxSocket );
\r
842 pxNetworkBuffer->ulIPAddress = pxDestinationAddress->sin_addr;
\r
844 /* The socket options are passed to the IP layer in the
\r
845 space that will eventually get used by the Ethernet header. */
\r
846 pxNetworkBuffer->pucEthernetBuffer[ ipSOCKET_OPTIONS_OFFSET ] = pxSocket->ucSocketOptions;
\r
848 /* Tell the networking task that the packet needs sending. */
\r
849 xStackTxEvent.pvData = pxNetworkBuffer;
\r
851 /* Ask the IP-task to send this packet */
\r
852 if( xSendEventStructToIPTask( &xStackTxEvent, xTicksToWait ) == pdPASS )
\r
854 /* The packet was successfully sent to the IP task. */
\r
855 lReturn = ( int32_t ) xTotalDataLength;
\r
856 #if( ipconfigUSE_CALLBACKS == 1 )
\r
858 if( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xUDP.pxHandleSent ) )
\r
860 pxSocket->u.xUDP.pxHandleSent( ( Socket_t )pxSocket, xTotalDataLength );
\r
863 #endif /* ipconfigUSE_CALLBACKS */
\r
867 /* If the buffer was allocated in this function, release
\r
869 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
\r
871 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
\r
873 iptraceSTACK_TX_EVENT_LOST( ipSTACK_TX_EVENT );
\r
878 /* If errno was available, errno would be set to
\r
879 FREERTOS_ENOPKTS. As it is, the function must return the
\r
880 number of transmitted bytes, so the calling function knows
\r
881 how much data was actually sent. */
\r
882 iptraceNO_BUFFER_FOR_SENDTO();
\r
887 iptraceSENDTO_SOCKET_NOT_BOUND();
\r
892 /* The data is longer than the available buffer space. */
\r
893 iptraceSENDTO_DATA_TOO_LONG();
\r
898 /*-----------------------------------------------------------*/
\r
901 * FreeRTOS_bind() : binds a sockt to a local port number. If port 0 is
\r
902 * provided, a system provided port number will be assigned. This function can
\r
903 * be used for both UDP and TCP sockets. The actual binding will be performed
\r
904 * by the IP-task to avoid mutual access to the bound-socket-lists
\r
905 * (xBoundUDPSocketsList or xBoundTCPSocketsList).
\r
907 BaseType_t FreeRTOS_bind( Socket_t xSocket, struct freertos_sockaddr * pxAddress, socklen_t xAddressLength )
\r
909 IPStackEvent_t xBindEvent;
\r
910 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
911 BaseType_t xReturn = 0;
\r
913 ( void ) xAddressLength;
\r
915 if( ( pxSocket == NULL ) || ( pxSocket == FREERTOS_INVALID_SOCKET ) )
\r
917 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
919 /* Once a socket is bound to a port, it can not be bound to a different
\r
921 else if( socketSOCKET_IS_BOUND( pxSocket) != pdFALSE )
\r
923 /* The socket is already bound. */
\r
924 FreeRTOS_debug_printf( ( "vSocketBind: Socket already bound to %d\n", pxSocket->usLocalPort ) );
\r
925 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
929 /* Prepare a messages to the IP-task in order to perform the binding.
\r
930 The desired port number will be passed in usLocalPort. */
\r
931 xBindEvent.eEventType = eSocketBindEvent;
\r
932 xBindEvent.pvData = ( void * ) xSocket;
\r
933 if( pxAddress != NULL )
\r
935 pxSocket->usLocalPort = FreeRTOS_ntohs( pxAddress->sin_port );
\r
939 /* Caller wants to bind to a random port number. */
\r
940 pxSocket->usLocalPort = 0u;
\r
943 /* portMAX_DELAY is used as a the time-out parameter, as binding *must*
\r
944 succeed before the socket can be used. _RB_ The use of an infinite
\r
945 block time needs be changed as it could result in the task hanging. */
\r
946 if( xSendEventStructToIPTask( &xBindEvent, ( TickType_t ) portMAX_DELAY ) == pdFAIL )
\r
948 /* Failed to wake-up the IP-task, no use to wait for it */
\r
949 FreeRTOS_debug_printf( ( "FreeRTOS_bind: send event failed\n" ) );
\r
950 xReturn = -pdFREERTOS_ERRNO_ECANCELED;
\r
954 /* The IP-task will set the 'eSOCKET_BOUND' bit when it has done its
\r
956 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_BOUND, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, portMAX_DELAY );
\r
957 if( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE )
\r
959 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
968 * vSocketBind(): internal version of bind() that should not be called directly.
\r
969 * 'xInternal' is used for TCP sockets only: it allows to have several
\r
970 * (connected) child sockets bound to the same server port.
\r
972 BaseType_t vSocketBind( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr * pxAddress, size_t uxAddressLength, BaseType_t xInternal )
\r
974 BaseType_t xReturn = 0; /* In Berkeley sockets, 0 means pass for bind(). */
\r
975 List_t *pxSocketList;
\r
976 #if( ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 )
\r
977 struct freertos_sockaddr xAddress;
\r
978 #endif /* ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND */
\r
980 #if( ipconfigUSE_TCP == 1 )
\r
981 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
983 pxSocketList = &xBoundTCPSocketsList;
\r
986 #endif /* ipconfigUSE_TCP == 1 */
\r
988 pxSocketList = &xBoundUDPSocketsList;
\r
991 /* The function prototype is designed to maintain the expected Berkeley
\r
992 sockets standard, but this implementation does not use all the parameters. */
\r
993 ( void ) uxAddressLength;
\r
995 configASSERT( pxSocket );
\r
996 configASSERT( pxSocket != FREERTOS_INVALID_SOCKET );
\r
998 #if( ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 )
\r
1000 /* pxAddress will be NULL if sendto() was called on a socket without the
\r
1001 socket being bound to an address. In this case, automatically allocate
\r
1002 an address and port to the socket. */
\r
1003 if( pxAddress == NULL )
\r
1005 pxAddress = &xAddress;
\r
1006 /* Put the port to zero to be assigned later. */
\r
1007 pxAddress->sin_port = 0u;
\r
1010 #endif /* ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 */
\r
1012 /* Sockets must be bound before calling FreeRTOS_sendto() if
\r
1013 ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is not set to 1. */
\r
1014 configASSERT( pxAddress );
\r
1016 if( pxAddress != NULL )
\r
1018 if( pxAddress->sin_port == 0u )
\r
1020 pxAddress->sin_port = prvGetPrivatePortNumber( ( BaseType_t )pxSocket->ucProtocol );
\r
1021 if( 0 == pxAddress->sin_port )
\r
1023 return -pdFREERTOS_ERRNO_EADDRNOTAVAIL;
\r
1027 /* If vSocketBind() is called from the API FreeRTOS_bind() it has been
\r
1028 confirmed that the socket was not yet bound to a port. If it is called
\r
1029 from the IP-task, no such check is necessary. */
\r
1031 /* Check to ensure the port is not already in use. If the bind is
\r
1032 called internally, a port MAY be used by more than one socket. */
\r
1033 if( ( ( xInternal == pdFALSE ) || ( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP ) ) &&
\r
1034 ( pxListFindListItemWithValue( pxSocketList, ( TickType_t ) pxAddress->sin_port ) != NULL ) )
\r
1036 FreeRTOS_debug_printf( ( "vSocketBind: %sP port %d in use\n",
\r
1037 pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP ? "TC" : "UD",
\r
1038 FreeRTOS_ntohs( pxAddress->sin_port ) ) );
\r
1039 xReturn = -pdFREERTOS_ERRNO_EADDRINUSE;
\r
1043 /* Allocate the port number to the socket.
\r
1044 This macro will set 'xBoundSocketListItem->xItemValue' */
\r
1045 socketSET_SOCKET_PORT( pxSocket, pxAddress->sin_port );
\r
1047 /* And also store it in a socket field 'usLocalPort' in host-byte-order,
\r
1048 mostly used for logging and debugging purposes */
\r
1049 pxSocket->usLocalPort = FreeRTOS_ntohs( pxAddress->sin_port );
\r
1051 /* Add the socket to the list of bound ports. */
\r
1053 /* If the network driver can iterate through 'xBoundUDPSocketsList',
\r
1054 by calling xPortHasUDPSocket() then the IP-task must temporarily
\r
1055 suspend the scheduler to keep the list in a consistent state. */
\r
1056 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1058 vTaskSuspendAll();
\r
1060 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1062 /* Add the socket to 'xBoundUDPSocketsList' or 'xBoundTCPSocketsList' */
\r
1063 vListInsertEnd( pxSocketList, &( pxSocket->xBoundSocketListItem ) );
\r
1065 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1069 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1075 xReturn = -pdFREERTOS_ERRNO_EADDRNOTAVAIL;
\r
1076 FreeRTOS_debug_printf( ( "vSocketBind: Socket no addr\n" ) );
\r
1079 if( xReturn != 0 )
\r
1081 iptraceBIND_FAILED( xSocket, ( FreeRTOS_ntohs( pxAddress->sin_port ) ) );
\r
1086 /*-----------------------------------------------------------*/
\r
1089 * Close a socket and free the allocated space
\r
1090 * In case of a TCP socket: the connection will not be closed automatically
\r
1091 * Subsequent messages for the closed socket will be responded to with a RST
\r
1092 * The IP-task will actually close the socket, after receiving a 'eSocketCloseEvent' message
\r
1094 BaseType_t FreeRTOS_closesocket( Socket_t xSocket )
\r
1096 BaseType_t xResult;
\r
1097 #if( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 )
\r
1098 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * )xSocket;
\r
1100 IPStackEvent_t xCloseEvent;
\r
1101 xCloseEvent.eEventType = eSocketCloseEvent;
\r
1102 xCloseEvent.pvData = ( void * ) xSocket;
\r
1104 if( ( xSocket == NULL ) || ( xSocket == FREERTOS_INVALID_SOCKET ) )
\r
1110 #if( ( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 ) )
\r
1112 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1114 /* Make sure that IP-task won't call the user callback's anymore */
\r
1115 pxSocket->u.xTCP.pxHandleConnected = NULL;
\r
1116 pxSocket->u.xTCP.pxHandleReceive = NULL;
\r
1117 pxSocket->u.xTCP.pxHandleSent = NULL;
\r
1120 #endif /* ( ( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 ) ) */
\r
1122 /* Let the IP task close the socket to keep it synchronised with the
\r
1123 packet handling. */
\r
1125 /* Note when changing the time-out value below, it must be checked who is calling
\r
1126 this function. If it is called by the IP-task, a deadlock could occur.
\r
1127 The IP-task would only call it in case of a user call-back */
\r
1128 if( xSendEventStructToIPTask( &xCloseEvent, ( TickType_t ) 0 ) == pdFAIL )
\r
1130 FreeRTOS_debug_printf( ( "FreeRTOS_closesocket: failed\n" ) );
\r
1142 /* This is the internal version of FreeRTOS_closesocket()
\r
1143 * It will be called by the IPtask only to avoid problems with synchronicity
\r
1145 void *vSocketClose( FreeRTOS_Socket_t *pxSocket )
\r
1147 NetworkBufferDescriptor_t *pxNetworkBuffer;
\r
1149 #if( ipconfigUSE_TCP == 1 )
\r
1151 /* For TCP: clean up a little more. */
\r
1152 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1154 #if( ipconfigUSE_TCP_WIN == 1 )
\r
1156 if( pxSocket->u.xTCP.pxAckMessage != NULL )
\r
1158 vReleaseNetworkBufferAndDescriptor( pxSocket->u.xTCP.pxAckMessage );
\r
1160 /* Free the resources which were claimed by the tcpWin member */
\r
1161 vTCPWindowDestroy( &pxSocket->u.xTCP.xTCPWindow );
\r
1163 #endif /* ipconfigUSE_TCP_WIN */
\r
1165 /* Free the input and output streams */
\r
1166 if( pxSocket->u.xTCP.rxStream != NULL )
\r
1168 vPortFreeLarge( pxSocket->u.xTCP.rxStream );
\r
1171 if( pxSocket->u.xTCP.txStream != NULL )
\r
1173 vPortFreeLarge( pxSocket->u.xTCP.txStream );
\r
1176 /* In case this is a child socket, make sure the child-count of the
\r
1177 parent socket is decreased. */
\r
1178 prvTCPSetSocketCount( pxSocket );
\r
1181 #endif /* ipconfigUSE_TCP == 1 */
\r
1183 /* Socket must be unbound first, to ensure no more packets are queued on
\r
1185 if( socketSOCKET_IS_BOUND( pxSocket ) != pdFALSE )
\r
1187 /* If the network driver can iterate through 'xBoundUDPSocketsList',
\r
1188 by calling xPortHasUDPSocket(), then the IP-task must temporarily
\r
1189 suspend the scheduler to keep the list in a consistent state. */
\r
1190 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1192 vTaskSuspendAll();
\r
1194 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1196 uxListRemove( &( pxSocket->xBoundSocketListItem ) );
\r
1198 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1202 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1205 /* Now the socket is not bound the list of waiting packets can be
\r
1207 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_UDP )
\r
1209 while( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) > 0U )
\r
1211 pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
\r
1212 uxListRemove( &( pxNetworkBuffer->xBufferListItem ) );
\r
1213 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
\r
1217 if( pxSocket->xEventGroup )
\r
1219 vEventGroupDelete( pxSocket->xEventGroup );
\r
1222 #if( ipconfigUSE_TCP == 1 ) && ( ipconfigHAS_DEBUG_PRINTF != 0 )
\r
1224 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1226 FreeRTOS_debug_printf( ( "FreeRTOS_closesocket[%u to %lxip:%u]: buffers %lu socks %lu\n",
\r
1227 pxSocket->usLocalPort,
\r
1228 pxSocket->u.xTCP.ulRemoteIP,
\r
1229 pxSocket->u.xTCP.usRemotePort,
\r
1230 uxGetNumberOfFreeNetworkBuffers(),
\r
1231 listCURRENT_LIST_LENGTH( &xBoundTCPSocketsList ) ) );
\r
1234 #endif /* ( ipconfigUSE_TCP == 1 ) && ( ipconfigHAS_DEBUG_PRINTF != 0 ) */
\r
1236 /* Anf finally, after all resources have been freed, free the socket space */
\r
1237 vPortFreeSocket( pxSocket );
\r
1242 /*-----------------------------------------------------------*/
\r
1244 #if ipconfigUSE_TCP == 1
\r
1247 * When a child socket gets closed, make sure to update the child-count of the
\r
1248 * parent. When a listening parent socket is closed, make sure no child-sockets
\r
1249 * keep a pointer to it.
\r
1251 static void prvTCPSetSocketCount( FreeRTOS_Socket_t *pxSocketToDelete )
\r
1253 const ListItem_t *pxIterator;
\r
1254 const MiniListItem_t *pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );
\r
1255 FreeRTOS_Socket_t *pxOtherSocket;
\r
1256 uint16_t usLocalPort = pxSocketToDelete->usLocalPort;
\r
1258 for( pxIterator = ( const ListItem_t * ) listGET_NEXT( pxEnd );
\r
1259 pxIterator != ( const ListItem_t * ) pxEnd;
\r
1260 pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
1262 pxOtherSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
\r
1263 if( ( pxOtherSocket->u.xTCP.ucTCPState == eTCP_LISTEN ) &&
\r
1264 ( pxOtherSocket->usLocalPort == usLocalPort ) &&
\r
1265 ( pxOtherSocket->u.xTCP.usChildCount ) )
\r
1267 pxOtherSocket->u.xTCP.usChildCount--;
\r
1268 FreeRTOS_debug_printf( ( "Lost: Socket %u now has %u / %u child%s\n",
\r
1269 pxOtherSocket->usLocalPort,
\r
1270 pxOtherSocket->u.xTCP.usChildCount,
\r
1271 pxOtherSocket->u.xTCP.usBacklog,
\r
1272 pxOtherSocket->u.xTCP.usChildCount == 1u ? "" : "ren" ) );
\r
1278 #endif /* ipconfigUSE_TCP == 1 */
\r
1280 /*-----------------------------------------------------------*/
\r
1282 BaseType_t FreeRTOS_setsockopt( Socket_t xSocket, int32_t lLevel, int32_t lOptionName, const void *pvOptionValue, size_t xOptionLength )
\r
1284 /* The standard Berkeley function returns 0 for success. */
\r
1285 BaseType_t xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
1286 BaseType_t lOptionValue;
\r
1287 FreeRTOS_Socket_t *pxSocket;
\r
1289 pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
1291 /* The function prototype is designed to maintain the expected Berkeley
\r
1292 sockets standard, but this implementation does not use all the parameters. */
\r
1294 ( void ) xOptionLength;
\r
1296 configASSERT( xSocket );
\r
1298 switch( lOptionName )
\r
1300 case FREERTOS_SO_RCVTIMEO :
\r
1301 /* Receive time out. */
\r
1302 pxSocket->xReceiveBlockTime = *( ( TickType_t * ) pvOptionValue );
\r
1306 case FREERTOS_SO_SNDTIMEO :
\r
1307 pxSocket->xSendBlockTime = *( ( TickType_t * ) pvOptionValue );
\r
1308 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_UDP )
\r
1310 /* The send time out is capped for the reason stated in the
\r
1311 comments where ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS is defined
\r
1312 in FreeRTOSIPConfig.h (assuming an official configuration file
\r
1314 if( pxSocket->xSendBlockTime > ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS )
\r
1316 pxSocket->xSendBlockTime = ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS;
\r
1321 /* For TCP socket, it isn't necessary to limit the blocking time
\r
1322 because the FreeRTOS_send() function does not wait for a network
\r
1323 buffer to become available. */
\r
1327 #if( ipconfigUDP_MAX_RX_PACKETS > 0 )
\r
1328 case FREERTOS_SO_UDP_MAX_RX_PACKETS:
\r
1329 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_UDP )
\r
1331 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1333 pxSocket->u.xUDP.uxMaxPackets = *( ( UBaseType_t * ) pvOptionValue );
\r
1336 #endif /* ipconfigUDP_MAX_RX_PACKETS */
\r
1338 case FREERTOS_SO_UDPCKSUM_OUT :
\r
1339 /* Turn calculating of the UDP checksum on/off for this socket. */
\r
1340 lOptionValue = ( BaseType_t ) pvOptionValue;
\r
1342 if( lOptionValue == 0 )
\r
1344 pxSocket->ucSocketOptions &= ( uint8_t ) ~FREERTOS_SO_UDPCKSUM_OUT;
\r
1348 pxSocket->ucSocketOptions |= ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT;
\r
1353 #if( ipconfigUSE_CALLBACKS == 1 )
\r
1354 #if( ipconfigUSE_TCP == 1 )
\r
1355 case FREERTOS_SO_TCP_CONN_HANDLER: /* Set a callback for (dis)connection events */
\r
1356 case FREERTOS_SO_TCP_RECV_HANDLER: /* Install a callback for receiving TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
\r
1357 case FREERTOS_SO_TCP_SENT_HANDLER: /* Install a callback for sending TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
\r
1358 #endif /* ipconfigUSE_TCP */
\r
1359 case FREERTOS_SO_UDP_RECV_HANDLER: /* Install a callback for receiving UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
\r
1360 case FREERTOS_SO_UDP_SENT_HANDLER: /* Install a callback for sending UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
\r
1362 #if( ipconfigUSE_TCP == 1 )
\r
1364 UBaseType_t uxProtocol;
\r
1365 if( ( lOptionName == FREERTOS_SO_UDP_RECV_HANDLER ) ||
\r
1366 ( lOptionName == FREERTOS_SO_UDP_SENT_HANDLER ) )
\r
1368 uxProtocol = ( UBaseType_t ) FREERTOS_IPPROTO_UDP;
\r
1372 uxProtocol = ( UBaseType_t ) FREERTOS_IPPROTO_TCP;
\r
1375 if( pxSocket->ucProtocol != ( uint8_t ) uxProtocol )
\r
1377 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1382 /* No need to check if the socket has the right
\r
1383 protocol, because only UDP socket can be created. */
\r
1385 #endif /* ipconfigUSE_TCP */
\r
1387 switch( lOptionName )
\r
1389 #if ipconfigUSE_TCP == 1
\r
1390 case FREERTOS_SO_TCP_CONN_HANDLER:
\r
1391 pxSocket->u.xTCP.pxHandleConnected = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPConnected;
\r
1393 case FREERTOS_SO_TCP_RECV_HANDLER:
\r
1394 pxSocket->u.xTCP.pxHandleReceive = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPReceive;
\r
1396 case FREERTOS_SO_TCP_SENT_HANDLER:
\r
1397 pxSocket->u.xTCP.pxHandleSent = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPSent;
\r
1399 #endif /* ipconfigUSE_TCP */
\r
1400 case FREERTOS_SO_UDP_RECV_HANDLER:
\r
1401 pxSocket->u.xUDP.pxHandleReceive = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnUDPReceive;
\r
1403 case FREERTOS_SO_UDP_SENT_HANDLER:
\r
1404 pxSocket->u.xUDP.pxHandleSent = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnUDPSent;
\r
1413 #endif /* ipconfigUSE_CALLBACKS */
\r
1415 #if( ipconfigUSE_TCP != 0 )
\r
1416 #if( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 )
\r
1417 /* Each socket has a semaphore on which the using task normally
\r
1419 case FREERTOS_SO_SET_SEMAPHORE:
\r
1421 pxSocket->pxUserSemaphore = *( ( SemaphoreHandle_t * ) pvOptionValue );
\r
1425 #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
\r
1427 #if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK != 0 )
\r
1428 case FREERTOS_SO_WAKEUP_CALLBACK:
\r
1430 /* Each socket can have a callback function that is executed
\r
1431 when there is an event the socket's owner might want to
\r
1433 pxSocket->pxUserWakeCallback = ( SocketWakeupCallback_t ) pvOptionValue;
\r
1437 #endif /* ipconfigSOCKET_HAS_USER_WAKE_CALLBACK */
\r
1439 case FREERTOS_SO_SET_LOW_HIGH_WATER:
\r
1441 LowHighWater_t *pxLowHighWater = ( LowHighWater_t * ) pvOptionValue;
\r
1443 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1445 /* It is not allowed to access 'pxSocket->u.xTCP'. */
\r
1446 FreeRTOS_debug_printf( ( "FREERTOS_SO_SET_LOW_HIGH_WATER: wrong socket type\n" ) );
\r
1447 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1449 if( ( pxLowHighWater->uxLittleSpace >= pxLowHighWater->uxEnoughSpace ) ||
\r
1450 ( pxLowHighWater->uxEnoughSpace > pxSocket->u.xTCP.uxRxStreamSize ) )
\r
1452 /* Impossible values. */
\r
1453 FreeRTOS_debug_printf( ( "FREERTOS_SO_SET_LOW_HIGH_WATER: bad values\n" ) );
\r
1454 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1456 /* Send a STOP when buffer space drops below 'uxLittleSpace' bytes. */
\r
1457 pxSocket->u.xTCP.uxLittleSpace = pxLowHighWater->uxLittleSpace;
\r
1458 /* Send a GO when buffer space grows above 'uxEnoughSpace' bytes. */
\r
1459 pxSocket->u.xTCP.uxEnoughSpace = pxLowHighWater->uxEnoughSpace;
\r
1464 case FREERTOS_SO_SNDBUF: /* Set the size of the send buffer, in units of MSS (TCP only) */
\r
1465 case FREERTOS_SO_RCVBUF: /* Set the size of the receive buffer, in units of MSS (TCP only) */
\r
1467 uint32_t ulNewValue;
\r
1469 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1471 FreeRTOS_debug_printf( ( "Set SO_%sBUF: wrong socket type\n",
\r
1472 ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );
\r
1473 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1476 if( ( ( lOptionName == FREERTOS_SO_SNDBUF ) && ( pxSocket->u.xTCP.txStream != NULL ) ) ||
\r
1477 ( ( lOptionName == FREERTOS_SO_RCVBUF ) && ( pxSocket->u.xTCP.rxStream != NULL ) ) )
\r
1479 FreeRTOS_debug_printf( ( "Set SO_%sBUF: buffer already created\n",
\r
1480 ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );
\r
1481 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1484 ulNewValue = *( ( uint32_t * ) pvOptionValue );
\r
1486 if( lOptionName == FREERTOS_SO_SNDBUF )
\r
1488 /* Round up to nearest MSS size */
\r
1489 ulNewValue = FreeRTOS_round_up( ulNewValue, ( uint32_t ) pxSocket->u.xTCP.usInitMSS );
\r
1490 pxSocket->u.xTCP.uxTxStreamSize = ulNewValue;
\r
1494 pxSocket->u.xTCP.uxRxStreamSize = ulNewValue;
\r
1500 case FREERTOS_SO_WIN_PROPERTIES: /* Set all buffer and window properties in one call, parameter is pointer to WinProperties_t */
\r
1502 WinProperties_t* pxProps;
\r
1504 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1506 FreeRTOS_debug_printf( ( "Set SO_WIN_PROP: wrong socket type\n" ) );
\r
1507 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1510 if( ( pxSocket->u.xTCP.txStream != NULL ) || ( pxSocket->u.xTCP.rxStream != NULL ) )
\r
1512 FreeRTOS_debug_printf( ( "Set SO_WIN_PROP: buffer already created\n" ) );
\r
1513 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1516 pxProps = ( ( WinProperties_t * ) pvOptionValue );
\r
1518 if ( FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDBUF, &( pxProps->lTxBufSize ), sizeof( pxProps->lTxBufSize ) ) != 0 )
\r
1520 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1523 if ( FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVBUF, &( pxProps->lRxBufSize ), sizeof( pxProps->lRxBufSize ) ) != 0 )
\r
1525 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1528 #if( ipconfigUSE_TCP_WIN == 1 )
\r
1530 pxSocket->u.xTCP.uxRxWinSize = ( uint32_t )pxProps->lRxWinSize; /* Fixed value: size of the TCP reception window */
\r
1531 pxSocket->u.xTCP.uxTxWinSize = ( uint32_t )pxProps->lTxWinSize; /* Fixed value: size of the TCP transmit window */
\r
1535 pxSocket->u.xTCP.uxRxWinSize = 1u;
\r
1536 pxSocket->u.xTCP.uxTxWinSize = 1u;
\r
1540 /* In case the socket has already initialised its tcpWin,
\r
1541 adapt the window size parameters */
\r
1542 if( pxSocket->u.xTCP.xTCPWindow.u.bits.bHasInit != pdFALSE_UNSIGNED )
\r
1544 pxSocket->u.xTCP.xTCPWindow.xSize.ulRxWindowLength = pxSocket->u.xTCP.uxRxWinSize * pxSocket->u.xTCP.usInitMSS;
\r
1545 pxSocket->u.xTCP.xTCPWindow.xSize.ulTxWindowLength = pxSocket->u.xTCP.uxTxWinSize * pxSocket->u.xTCP.usInitMSS;
\r
1552 case FREERTOS_SO_REUSE_LISTEN_SOCKET: /* If true, the server-socket will turn into a connected socket */
\r
1554 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1556 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1558 if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
\r
1560 pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE_UNSIGNED;
\r
1564 pxSocket->u.xTCP.bits.bReuseSocket = pdFALSE_UNSIGNED;
\r
1570 case FREERTOS_SO_CLOSE_AFTER_SEND: /* As soon as the last byte has been transmitted, finalise the connection */
\r
1572 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1574 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1577 if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
\r
1579 pxSocket->u.xTCP.bits.bCloseAfterSend = pdTRUE_UNSIGNED;
\r
1583 pxSocket->u.xTCP.bits.bCloseAfterSend = pdFALSE_UNSIGNED;
\r
1589 case FREERTOS_SO_SET_FULL_SIZE: /* Refuse to send packets smaller than MSS */
\r
1591 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1593 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1596 if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
\r
1598 pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdTRUE_UNSIGNED;
\r
1602 pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdFALSE_UNSIGNED;
\r
1605 if( ( pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize == pdFALSE_UNSIGNED ) &&
\r
1606 ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) &&
\r
1607 ( FreeRTOS_outstanding( pxSocket ) != 0 ) )
\r
1609 pxSocket->u.xTCP.usTimeout = 1u; /* to set/clear bSendFullSize */
\r
1610 xSendEventToIPTask( eTCPTimerEvent );
\r
1616 case FREERTOS_SO_STOP_RX: /* Refuse to receive more packts */
\r
1618 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1620 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1623 if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
\r
1625 pxSocket->u.xTCP.bits.bRxStopped = pdTRUE_UNSIGNED;
\r
1629 pxSocket->u.xTCP.bits.bRxStopped = pdFALSE_UNSIGNED;
\r
1632 pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
\r
1633 pxSocket->u.xTCP.usTimeout = 1u; /* to set/clear bRxStopped */
\r
1634 xSendEventToIPTask( eTCPTimerEvent );
\r
1639 #endif /* ipconfigUSE_TCP == 1 */
\r
1642 /* No other options are handled. */
\r
1643 xReturn = -pdFREERTOS_ERRNO_ENOPROTOOPT;
\r
1650 /*-----------------------------------------------------------*/
\r
1652 /* Find an available port number per https://tools.ietf.org/html/rfc6056. */
\r
1653 static uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol )
\r
1655 const uint16_t usEphemeralPortCount =
\r
1656 socketAUTO_PORT_ALLOCATION_MAX_NUMBER - socketAUTO_PORT_ALLOCATION_START_NUMBER + 1;
\r
1657 uint16_t usIterations = usEphemeralPortCount;
\r
1658 uint32_t ulRandomSeed = 0;
\r
1659 uint16_t usResult = 0;
\r
1660 const List_t *pxList;
\r
1662 #if ipconfigUSE_TCP == 1
\r
1663 if( xProtocol == ( BaseType_t ) FREERTOS_IPPROTO_TCP )
\r
1665 pxList = &xBoundTCPSocketsList;
\r
1670 pxList = &xBoundUDPSocketsList;
\r
1673 /* Avoid compiler warnings if ipconfigUSE_TCP is not defined. */
\r
1674 ( void ) xProtocol;
\r
1676 /* Find the next available port using the random seed as a starting
\r
1680 /* Only proceed if the random number generator succeeded. */
\r
1681 if( xApplicationGetRandomNumber( &( ulRandomSeed ) ) == pdFALSE )
\r
1686 /* Map the random to a candidate port. */
\r
1688 socketAUTO_PORT_ALLOCATION_START_NUMBER +
\r
1689 ( ( ( uint16_t )ulRandomSeed ) % usEphemeralPortCount );
\r
1691 /* Check if there's already an open socket with the same protocol
\r
1693 if( NULL == pxListFindListItemWithValue(
\r
1695 ( TickType_t )FreeRTOS_htons( usResult ) ) )
\r
1697 usResult = FreeRTOS_htons( usResult );
\r
1707 while( usIterations > 0 );
\r
1711 /*-----------------------------------------------------------*/
\r
1713 /* pxListFindListItemWithValue: find a list item in a bound socket list
\r
1714 'xWantedItemValue' refers to a port number */
\r
1715 static const ListItem_t * pxListFindListItemWithValue( const List_t *pxList, TickType_t xWantedItemValue )
\r
1717 const ListItem_t * pxResult = NULL;
\r
1719 if( ( xIPIsNetworkTaskReady() != pdFALSE ) && ( pxList != NULL ) )
\r
1721 const ListItem_t *pxIterator;
\r
1722 const MiniListItem_t *pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( pxList );
\r
1723 for( pxIterator = ( const ListItem_t * ) listGET_NEXT( pxEnd );
\r
1724 pxIterator != ( const ListItem_t * ) pxEnd;
\r
1725 pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
1727 if( listGET_LIST_ITEM_VALUE( pxIterator ) == xWantedItemValue )
\r
1729 pxResult = pxIterator;
\r
1738 /*-----------------------------------------------------------*/
\r
1740 FreeRTOS_Socket_t *pxUDPSocketLookup( UBaseType_t uxLocalPort )
\r
1742 const ListItem_t *pxListItem;
\r
1743 FreeRTOS_Socket_t *pxSocket = NULL;
\r
1745 /* Looking up a socket is quite simple, find a match with the local port.
\r
1747 See if there is a list item associated with the port number on the
\r
1748 list of bound sockets. */
\r
1749 pxListItem = pxListFindListItemWithValue( &xBoundUDPSocketsList, ( TickType_t ) uxLocalPort );
\r
1751 if( pxListItem != NULL )
\r
1753 /* The owner of the list item is the socket itself. */
\r
1754 pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxListItem );
\r
1755 configASSERT( pxSocket != NULL );
\r
1760 /*-----------------------------------------------------------*/
\r
1762 #if ipconfigINCLUDE_FULL_INET_ADDR == 1
\r
1764 uint32_t FreeRTOS_inet_addr( const char * pcIPAddress )
\r
1766 const uint32_t ulDecimalBase = 10u;
\r
1767 uint8_t ucOctet[ socketMAX_IP_ADDRESS_OCTETS ];
\r
1768 const char *pcPointerOnEntering;
\r
1769 uint32_t ulReturn = 0UL, ulValue;
\r
1770 UBaseType_t uxOctetNumber;
\r
1771 BaseType_t xResult = pdPASS;
\r
1773 for( uxOctetNumber = 0u; uxOctetNumber < socketMAX_IP_ADDRESS_OCTETS; uxOctetNumber++ )
\r
1776 pcPointerOnEntering = pcIPAddress;
\r
1778 while( ( *pcIPAddress >= '0' ) && ( *pcIPAddress <= '9' ) )
\r
1780 /* Move previous read characters into the next decimal
\r
1782 ulValue *= ulDecimalBase;
\r
1784 /* Add the binary value of the ascii character. */
\r
1785 ulValue += ( ( uint32_t ) ( *pcIPAddress ) - ( uint32_t ) '0' );
\r
1787 /* Move to next character in the string. */
\r
1791 /* Check characters were read. */
\r
1792 if( pcIPAddress == pcPointerOnEntering )
\r
1797 /* Check the value fits in an 8-bit number. */
\r
1798 if( ulValue > 0xffUL )
\r
1804 ucOctet[ uxOctetNumber ] = ( uint8_t ) ulValue;
\r
1806 /* Check the next character is as expected. */
\r
1807 if( uxOctetNumber < ( socketMAX_IP_ADDRESS_OCTETS - 1u ) )
\r
1809 if( *pcIPAddress != '.' )
\r
1815 /* Move past the dot. */
\r
1821 if( xResult == pdFAIL )
\r
1823 /* No point going on. */
\r
1828 if( *pcIPAddress != ( char ) 0 )
\r
1830 /* Expected the end of the string. */
\r
1834 if( uxOctetNumber != socketMAX_IP_ADDRESS_OCTETS )
\r
1836 /* Didn't read enough octets. */
\r
1840 if( xResult == pdPASS )
\r
1842 ulReturn = FreeRTOS_inet_addr_quick( ucOctet[ 0 ], ucOctet[ 1 ], ucOctet[ 2 ], ucOctet[ 3 ] );
\r
1848 #endif /* ipconfigINCLUDE_FULL_INET_ADDR */
\r
1850 /*-----------------------------------------------------------*/
\r
1852 /* Function to get the local address and IP port */
\r
1853 size_t FreeRTOS_GetLocalAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress )
\r
1855 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
1857 /* IP address of local machine. */
\r
1858 pxAddress->sin_addr = *ipLOCAL_IP_ADDRESS_POINTER;
\r
1860 /* Local port on this machine. */
\r
1861 pxAddress->sin_port = FreeRTOS_htons( pxSocket->usLocalPort );
\r
1863 return sizeof( *pxAddress );
\r
1866 /*-----------------------------------------------------------*/
\r
1868 void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
\r
1870 /* _HT_ must work this out, now vSocketWakeUpUser will be called for any important
\r
1871 * event or transition */
\r
1872 #if( ipconfigSOCKET_HAS_USER_SEMAPHORE == 1 )
\r
1874 if( pxSocket->pxUserSemaphore != NULL )
\r
1876 xSemaphoreGive( pxSocket->pxUserSemaphore );
\r
1879 #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
\r
1881 #if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK == 1 )
\r
1883 if( pxSocket->pxUserWakeCallback != NULL )
\r
1885 pxSocket->pxUserWakeCallback( pxSocket );
\r
1888 #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
\r
1890 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
1892 if( pxSocket->pxSocketSet != NULL )
\r
1894 EventBits_t xSelectBits = ( pxSocket->xEventBits >> SOCKET_EVENT_BIT_COUNT ) & eSELECT_ALL;
\r
1895 if( xSelectBits != 0ul )
\r
1897 pxSocket->xSocketBits |= xSelectBits;
\r
1898 xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, xSelectBits );
\r
1902 pxSocket->xEventBits &= eSOCKET_ALL;
\r
1904 #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
\r
1906 if( ( pxSocket->xEventGroup != NULL ) && ( pxSocket->xEventBits != 0u ) )
\r
1908 xEventGroupSetBits( pxSocket->xEventGroup, pxSocket->xEventBits );
\r
1911 pxSocket->xEventBits = 0ul;
\r
1914 /*-----------------------------------------------------------*/
\r
1916 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1918 /* This define makes it possible for network-card drivers to inspect
\r
1919 * UDP message and see if there is any UDP socket bound to a given port
\r
1921 * This is probably only usefull in systems with a minimum of RAM and
\r
1922 * when lots of anonymous broadcast messages come in
\r
1924 BaseType_t xPortHasUDPSocket( uint16_t usPortNr )
\r
1926 BaseType_t xFound = pdFALSE;
\r
1928 vTaskSuspendAll();
\r
1930 if( ( pxListFindListItemWithValue( &xBoundUDPSocketsList, ( TickType_t ) usPortNr ) != NULL ) )
\r
1940 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1942 /*-----------------------------------------------------------*/
\r
1944 #if( ipconfigUSE_TCP == 1 )
\r
1946 static BaseType_t bMayConnect( FreeRTOS_Socket_t *pxSocket );
\r
1947 static BaseType_t bMayConnect( FreeRTOS_Socket_t *pxSocket )
\r
1949 switch( pxSocket->u.xTCP.ucTCPState )
\r
1952 case eCLOSE_WAIT: return 0;
\r
1953 case eCONNECT_SYN: return -pdFREERTOS_ERRNO_EINPROGRESS;
\r
1954 default: return -pdFREERTOS_ERRNO_EAGAIN;
\r
1958 #endif /* ipconfigUSE_TCP */
\r
1959 /*-----------------------------------------------------------*/
\r
1961 #if( ipconfigUSE_TCP == 1 )
\r
1963 static BaseType_t prvTCPConnectStart( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr *pxAddress )
\r
1965 BaseType_t xResult = 0;
\r
1967 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdFALSE )
\r
1969 /* Not a valid socket or wrong type */
\r
1970 xResult = -pdFREERTOS_ERRNO_EBADF;
\r
1972 else if( FreeRTOS_issocketconnected( pxSocket ) > 0 )
\r
1974 /* The socket is already connected. */
\r
1975 xResult = -pdFREERTOS_ERRNO_EISCONN;
\r
1977 else if( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE )
\r
1979 /* Bind the socket to the port that the client task will send from.
\r
1980 Non-standard, so the error returned is that returned by bind(). */
\r
1981 xResult = FreeRTOS_bind( ( Socket_t ) pxSocket, NULL, 0u );
\r
1984 if( xResult == 0 )
\r
1986 /* Check if it makes any sense to wait for a connect event, this condition
\r
1987 might change while sleeping, so it must be checked within each loop */
\r
1988 xResult = bMayConnect( pxSocket ); /* -EINPROGRESS, -EAGAIN, or 0 for OK */
\r
1990 /* Start the connect procedure, kernel will start working on it */
\r
1991 if( xResult == 0 )
\r
1993 pxSocket->u.xTCP.bits.bConnPrepared = pdFALSE_UNSIGNED;
\r
1994 pxSocket->u.xTCP.ucRepCount = 0u;
\r
1996 FreeRTOS_debug_printf( ( "FreeRTOS_connect: %u to %lxip:%u\n",
\r
1997 pxSocket->usLocalPort, FreeRTOS_ntohl( pxAddress->sin_addr ), FreeRTOS_ntohs( pxAddress->sin_port ) ) );
\r
1999 /* Port on remote machine. */
\r
2000 pxSocket->u.xTCP.usRemotePort = FreeRTOS_ntohs( pxAddress->sin_port );
\r
2002 /* IP address of remote machine. */
\r
2003 pxSocket->u.xTCP.ulRemoteIP = FreeRTOS_ntohl( pxAddress->sin_addr );
\r
2005 /* (client) internal state: socket wants to send a connect. */
\r
2006 vTCPStateChange( pxSocket, eCONNECT_SYN );
\r
2008 /* To start an active connect. */
\r
2009 pxSocket->u.xTCP.usTimeout = 1u;
\r
2011 if( xSendEventToIPTask( eTCPTimerEvent ) != pdPASS )
\r
2013 xResult = -pdFREERTOS_ERRNO_ECANCELED;
\r
2021 #endif /* ipconfigUSE_TCP */
\r
2022 /*-----------------------------------------------------------*/
\r
2024 #if( ipconfigUSE_TCP == 1 )
\r
2027 * FreeRTOS_connect: socket wants to connect to a remote port
\r
2029 BaseType_t FreeRTOS_connect( Socket_t xClientSocket, struct freertos_sockaddr *pxAddress, socklen_t xAddressLength )
\r
2031 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t* ) xClientSocket;
\r
2032 TickType_t xRemainingTime;
\r
2033 BaseType_t xTimed = pdFALSE;
\r
2034 BaseType_t xResult;
\r
2035 TimeOut_t xTimeOut;
\r
2037 ( void ) xAddressLength;
\r
2039 xResult = prvTCPConnectStart( pxSocket, pxAddress );
\r
2041 if( xResult == 0 )
\r
2043 /* And wait for the result */
\r
2046 if( xTimed == pdFALSE )
\r
2048 /* Only in the first round, check for non-blocking */
\r
2049 xRemainingTime = pxSocket->xReceiveBlockTime;
\r
2050 if( xRemainingTime == ( TickType_t )0 )
\r
2052 /* Not yet connected, correct state, non-blocking. */
\r
2053 xResult = -pdFREERTOS_ERRNO_EWOULDBLOCK;
\r
2057 /* Don't get here a second time. */
\r
2060 /* Fetch the current time */
\r
2061 vTaskSetTimeOutState( &xTimeOut );
\r
2064 /* Did it get connected while sleeping ? */
\r
2065 xResult = FreeRTOS_issocketconnected( pxSocket );
\r
2067 /* Returns positive when connected, negative means an error */
\r
2070 /* Return the error */
\r
2076 /* Socket now connected, return a zero */
\r
2081 /* Is it allowed to sleep more? */
\r
2082 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) )
\r
2084 xResult = -pdFREERTOS_ERRNO_ETIMEDOUT;
\r
2088 /* Go sleeping until we get any down-stream event */
\r
2089 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_CONNECT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2095 #endif /* ipconfigUSE_TCP */
\r
2096 /*-----------------------------------------------------------*/
\r
2098 #if( ipconfigUSE_TCP == 1 )
\r
2101 * FreeRTOS_accept: can return a new connected socket
\r
2102 * if the server socket is in listen mode and receives a connection request
\r
2103 * The new socket will be bound already to the same port number as the listing
\r
2106 Socket_t FreeRTOS_accept( Socket_t xServerSocket, struct freertos_sockaddr *pxAddress, socklen_t *pxAddressLength )
\r
2108 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xServerSocket;
\r
2109 FreeRTOS_Socket_t *pxClientSocket = NULL;
\r
2110 TickType_t xRemainingTime;
\r
2111 BaseType_t xTimed = pdFALSE, xAsk = pdFALSE;
\r
2112 TimeOut_t xTimeOut;
\r
2113 IPStackEvent_t xAskEvent;
\r
2115 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2117 /* Not a valid socket or wrong type */
\r
2118 pxClientSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
\r
2120 else if( ( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED ) &&
\r
2121 ( pxSocket->u.xTCP.ucTCPState != eTCP_LISTEN ) )
\r
2123 /* Parent socket is not in listening mode */
\r
2124 pxClientSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
\r
2128 /* Loop will stop with breaks. */
\r
2131 /* Is there a new client? */
\r
2132 vTaskSuspendAll();
\r
2134 if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED )
\r
2136 pxClientSocket = pxSocket->u.xTCP.pxPeerSocket;
\r
2140 pxClientSocket = pxSocket;
\r
2142 if( pxClientSocket != NULL )
\r
2144 pxSocket->u.xTCP.pxPeerSocket = NULL;
\r
2146 /* Is it still not taken ? */
\r
2147 if( pxClientSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED )
\r
2149 pxClientSocket->u.xTCP.bits.bPassAccept = pdFALSE_UNSIGNED;
\r
2153 pxClientSocket = NULL;
\r
2159 if( pxClientSocket != NULL )
\r
2161 if( pxAddress != NULL )
\r
2163 /* IP address of remote machine. */
\r
2164 pxAddress->sin_addr = FreeRTOS_ntohl( pxClientSocket->u.xTCP.ulRemoteIP );
\r
2166 /* Port on remote machine. */
\r
2167 pxAddress->sin_port = FreeRTOS_ntohs( pxClientSocket->u.xTCP.usRemotePort );
\r
2169 if( pxAddressLength != NULL )
\r
2171 *pxAddressLength = sizeof( *pxAddress );
\r
2174 if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED )
\r
2180 if( xAsk != pdFALSE )
\r
2182 /* Ask to set an event in 'xEventGroup' as soon as a new
\r
2183 client gets connected for this listening socket. */
\r
2184 xAskEvent.eEventType = eTCPAcceptEvent;
\r
2185 xAskEvent.pvData = ( void * ) pxSocket;
\r
2186 xSendEventStructToIPTask( &xAskEvent, portMAX_DELAY );
\r
2189 if( pxClientSocket != NULL )
\r
2194 if( xTimed == pdFALSE )
\r
2196 /* Only in the first round, check for non-blocking */
\r
2197 xRemainingTime = pxSocket->xReceiveBlockTime;
\r
2198 if( xRemainingTime == ( TickType_t ) 0 )
\r
2203 /* Don't get here a second time */
\r
2206 /* Fetch the current time */
\r
2207 vTaskSetTimeOutState( &xTimeOut );
\r
2210 /* Has the timeout been reached? */
\r
2211 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
\r
2216 /* Go sleeping until we get any down-stream event */
\r
2217 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_ACCEPT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2221 return ( Socket_t ) pxClientSocket;
\r
2223 #endif /* ipconfigUSE_TCP */
\r
2224 /*-----------------------------------------------------------*/
\r
2226 #if( ipconfigUSE_TCP == 1 )
\r
2229 * Read incoming data from a TCP socket
\r
2230 * Only after the last byte has been read, a close error might be returned
\r
2232 BaseType_t FreeRTOS_recv( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags )
\r
2234 BaseType_t xByteCount;
\r
2235 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2236 TickType_t xRemainingTime;
\r
2237 BaseType_t xTimed = pdFALSE;
\r
2238 TimeOut_t xTimeOut;
\r
2239 EventBits_t xEventBits = ( EventBits_t ) 0;
\r
2241 /* Check if the socket is valid, has type TCP and if it is bound to a
\r
2243 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2245 xByteCount = -pdFREERTOS_ERRNO_EINVAL;
\r
2249 if( pxSocket->u.xTCP.rxStream != NULL )
\r
2251 xByteCount = ( BaseType_t )uxStreamBufferGetSize ( pxSocket->u.xTCP.rxStream );
\r
2258 while( xByteCount == 0 )
\r
2260 switch( pxSocket->u.xTCP.ucTCPState )
\r
2263 case eCLOSE_WAIT: /* (server + client) waiting for a connection termination request from the local user. */
\r
2264 case eCLOSING: /* (server + client) waiting for a connection termination request acknowledgement from the remote TCP. */
\r
2265 if( pxSocket->u.xTCP.bits.bMallocError != pdFALSE_UNSIGNED )
\r
2267 /* The no-memory error has priority above the non-connected error.
\r
2268 Both are fatal and will elad to closing the socket. */
\r
2269 xByteCount = -pdFREERTOS_ERRNO_ENOMEM;
\r
2273 xByteCount = -pdFREERTOS_ERRNO_ENOTCONN;
\r
2275 /* Call continue to break out of the switch and also the while
\r
2282 if( xTimed == pdFALSE )
\r
2284 /* Only in the first round, check for non-blocking. */
\r
2285 xRemainingTime = pxSocket->xReceiveBlockTime;
\r
2287 if( xRemainingTime == ( TickType_t ) 0 )
\r
2289 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
2291 /* Just check for the interrupt flag. */
\r
2292 xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_INTR,
\r
2293 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, socketDONT_BLOCK );
\r
2295 #endif /* ipconfigSUPPORT_SIGNALS */
\r
2299 if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
\r
2304 /* Don't get here a second time. */
\r
2307 /* Fetch the current time. */
\r
2308 vTaskSetTimeOutState( &xTimeOut );
\r
2311 /* Has the timeout been reached? */
\r
2312 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
\r
2317 /* Block until there is a down-stream event. */
\r
2318 xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup,
\r
2319 eSOCKET_RECEIVE | eSOCKET_CLOSED | eSOCKET_INTR,
\r
2320 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2321 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
2323 if( ( xEventBits & eSOCKET_INTR ) != 0u )
\r
2330 ( void ) xEventBits;
\r
2332 #endif /* ipconfigSUPPORT_SIGNALS */
\r
2334 if( pxSocket->u.xTCP.rxStream != NULL )
\r
2336 xByteCount = ( BaseType_t ) uxStreamBufferGetSize ( pxSocket->u.xTCP.rxStream );
\r
2344 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
2345 if( ( xEventBits & eSOCKET_INTR ) != 0 )
\r
2347 if( ( xEventBits & ( eSOCKET_RECEIVE | eSOCKET_CLOSED ) ) != 0 )
\r
2349 /* Shouldn't have cleared other flags. */
\r
2350 xEventBits &= ~eSOCKET_INTR;
\r
2351 xEventGroupSetBits( pxSocket->xEventGroup, xEventBits );
\r
2353 xByteCount = -pdFREERTOS_ERRNO_EINTR;
\r
2356 #endif /* ipconfigSUPPORT_SIGNALS */
\r
2357 if( xByteCount > 0 )
\r
2359 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
\r
2361 xByteCount = ( BaseType_t ) uxStreamBufferGet( pxSocket->u.xTCP.rxStream, 0ul, ( uint8_t * ) pvBuffer, ( size_t ) xBufferLength, ( xFlags & FREERTOS_MSG_PEEK ) != 0 );
\r
2362 if( pxSocket->u.xTCP.bits.bLowWater != pdFALSE_UNSIGNED )
\r
2364 /* We had reached the low-water mark, now see if the flag
\r
2366 size_t uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );
\r
2368 if( uxFrontSpace >= pxSocket->u.xTCP.uxEnoughSpace )
\r
2370 pxSocket->u.xTCP.bits.bLowWater = pdFALSE_UNSIGNED;
\r
2371 pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
\r
2372 pxSocket->u.xTCP.usTimeout = 1u; /* because bLowWater is cleared. */
\r
2373 xSendEventToIPTask( eTCPTimerEvent );
\r
2379 /* Zero-copy reception of data: pvBuffer is a pointer to a pointer. */
\r
2380 xByteCount = ( BaseType_t ) uxStreamBufferGetPtr( pxSocket->u.xTCP.rxStream, (uint8_t **)pvBuffer );
\r
2383 } /* prvValidSocket() */
\r
2385 return xByteCount;
\r
2388 #endif /* ipconfigUSE_TCP */
\r
2389 /*-----------------------------------------------------------*/
\r
2391 #if( ipconfigUSE_TCP == 1 )
\r
2393 static int32_t prvTCPSendCheck( FreeRTOS_Socket_t *pxSocket, size_t xDataLength )
\r
2395 int32_t xResult = 1;
\r
2397 /* Is this a socket of type TCP and is it already bound to a port number ? */
\r
2398 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2400 xResult = -pdFREERTOS_ERRNO_EINVAL;
\r
2402 else if( pxSocket->u.xTCP.bits.bMallocError != pdFALSE_UNSIGNED )
\r
2404 xResult = -pdFREERTOS_ERRNO_ENOMEM;
\r
2406 else if( pxSocket->u.xTCP.ucTCPState == eCLOSED ||
\r
2407 pxSocket->u.xTCP.ucTCPState == eCLOSE_WAIT ||
\r
2408 pxSocket->u.xTCP.ucTCPState == eCLOSING )
\r
2410 xResult = -pdFREERTOS_ERRNO_ENOTCONN;
\r
2412 else if( pxSocket->u.xTCP.bits.bFinSent != pdFALSE_UNSIGNED )
\r
2414 /* This TCP connection is closing already, the FIN flag has been sent.
\r
2415 Maybe it is still delivering or receiving data.
\r
2416 Return OK in order not to get closed/deleted too quickly */
\r
2419 else if( xDataLength == 0ul )
\r
2421 /* send() is being called to send zero bytes */
\r
2424 else if( pxSocket->u.xTCP.txStream == NULL )
\r
2426 /* Create the outgoing stream only when it is needed */
\r
2427 prvTCPCreateStream( pxSocket, pdFALSE );
\r
2429 if( pxSocket->u.xTCP.txStream == NULL )
\r
2431 xResult = -pdFREERTOS_ERRNO_ENOMEM;
\r
2438 #endif /* ipconfigUSE_TCP */
\r
2439 /*-----------------------------------------------------------*/
\r
2441 #if( ipconfigUSE_TCP == 1 )
\r
2443 /* Get a direct pointer to the circular transmit buffer.
\r
2444 '*pxLength' will contain the number of bytes that may be written. */
\r
2445 uint8_t *FreeRTOS_get_tx_head( Socket_t xSocket, BaseType_t *pxLength )
\r
2447 uint8_t *pucReturn = NULL;
\r
2448 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2449 StreamBuffer_t *pxBuffer = NULL;
\r
2453 /* Confirm that this is a TCP socket before dereferencing structure
\r
2454 member pointers. */
\r
2455 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdTRUE )
\r
2457 pxBuffer = pxSocket->u.xTCP.txStream;
\r
2458 if( pxBuffer != NULL )
\r
2460 BaseType_t xSpace = ( BaseType_t )uxStreamBufferGetSpace( pxBuffer );
\r
2461 BaseType_t xRemain = ( BaseType_t )( pxBuffer->LENGTH - pxBuffer->uxHead );
\r
2463 *pxLength = FreeRTOS_min_BaseType( xSpace, xRemain );
\r
2464 pucReturn = pxBuffer->ucArray + pxBuffer->uxHead;
\r
2470 #endif /* ipconfigUSE_TCP */
\r
2471 /*-----------------------------------------------------------*/
\r
2473 #if( ipconfigUSE_TCP == 1 )
\r
2475 * Send data using a TCP socket. It is not necessary to have the socket
\r
2476 * connected already. Outgoing data will be stored and delivered as soon as
\r
2477 * the socket gets connected.
\r
2479 BaseType_t FreeRTOS_send( Socket_t xSocket, const void *pvBuffer, size_t uxDataLength, BaseType_t xFlags )
\r
2481 BaseType_t xByteCount;
\r
2482 BaseType_t xBytesLeft;
\r
2483 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2484 TickType_t xRemainingTime;
\r
2485 BaseType_t xTimed = pdFALSE;
\r
2486 TimeOut_t xTimeOut;
\r
2487 BaseType_t xCloseAfterSend;
\r
2489 /* Prevent compiler warnings about unused parameters. The parameter
\r
2490 may be used in future versions. */
\r
2493 xByteCount = ( BaseType_t ) prvTCPSendCheck( pxSocket, uxDataLength );
\r
2495 if( xByteCount > 0 )
\r
2497 /* xBytesLeft is number of bytes to send, will count to zero. */
\r
2498 xBytesLeft = ( BaseType_t ) uxDataLength;
\r
2500 /* xByteCount is number of bytes that can be sent now. */
\r
2501 xByteCount = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
\r
2503 /* While there are still bytes to be sent. */
\r
2504 while( xBytesLeft > 0 )
\r
2506 /* If txStream has space. */
\r
2507 if( xByteCount > 0 )
\r
2509 /* Don't send more than necessary. */
\r
2510 if( xByteCount > xBytesLeft )
\r
2512 xByteCount = xBytesLeft;
\r
2515 /* Is the close-after-send flag set and is this really the
\r
2516 last transmission? */
\r
2517 if( ( pxSocket->u.xTCP.bits.bCloseAfterSend != pdFALSE_UNSIGNED ) && ( xByteCount == xBytesLeft ) )
\r
2519 xCloseAfterSend = pdTRUE;
\r
2523 xCloseAfterSend = pdFALSE;
\r
2526 /* The flag 'bCloseAfterSend' can be set before sending data
\r
2527 using setsockopt()
\r
2529 When the last data packet is being sent out, a FIN flag will
\r
2530 be included to let the peer know that no more data is to be
\r
2531 expected. The use of 'bCloseAfterSend' is not mandatory, it
\r
2532 is just a faster way of transferring files (e.g. when using
\r
2534 if( xCloseAfterSend != pdFALSE )
\r
2536 /* Now suspend the scheduler: sending the last data and
\r
2537 setting bCloseRequested must be done together */
\r
2538 vTaskSuspendAll();
\r
2539 pxSocket->u.xTCP.bits.bCloseRequested = pdTRUE_UNSIGNED;
\r
2542 xByteCount = ( BaseType_t ) uxStreamBufferAdd( pxSocket->u.xTCP.txStream, 0ul, ( const uint8_t * ) pvBuffer, ( size_t ) xByteCount );
\r
2544 if( xCloseAfterSend != pdFALSE )
\r
2546 /* Now when the IP-task transmits the data, it will also
\r
2547 see that bCloseRequested is true and include the FIN
\r
2548 flag to start closure of the connection. */
\r
2552 /* Send a message to the IP-task so it can work on this
\r
2553 socket. Data is sent, let the IP-task work on it. */
\r
2554 pxSocket->u.xTCP.usTimeout = 1u;
\r
2556 if( xIsCallingFromIPTask() == pdFALSE )
\r
2558 /* Only send a TCP timer event when not called from the
\r
2560 xSendEventToIPTask( eTCPTimerEvent );
\r
2563 xBytesLeft -= xByteCount;
\r
2565 if( xBytesLeft == 0 )
\r
2570 /* As there are still bytes left to be sent, increase the
\r
2572 pvBuffer = ( void * ) ( ( ( const uint8_t * ) pvBuffer) + xByteCount );
\r
2575 /* Not all bytes have been sent. In case the socket is marked as
\r
2576 blocking sleep for a while. */
\r
2577 if( xTimed == pdFALSE )
\r
2579 /* Only in the first round, check for non-blocking. */
\r
2580 xRemainingTime = pxSocket->xSendBlockTime;
\r
2582 #if( ipconfigUSE_CALLBACKS != 0 )
\r
2584 if( xIsCallingFromIPTask() != pdFALSE )
\r
2586 /* If this send function is called from within a
\r
2587 call-back handler it may not block, otherwise
\r
2588 chances would be big to get a deadlock: the IP-task
\r
2589 waiting for itself. */
\r
2590 xRemainingTime = ( TickType_t ) 0;
\r
2593 #endif /* ipconfigUSE_CALLBACKS */
\r
2595 if( xRemainingTime == ( TickType_t ) 0 )
\r
2600 if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
\r
2605 /* Don't get here a second time. */
\r
2608 /* Fetch the current time. */
\r
2609 vTaskSetTimeOutState( &xTimeOut );
\r
2613 /* Has the timeout been reached? */
\r
2614 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
\r
2620 /* Go sleeping until down-stream events are received. */
\r
2621 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_SEND | eSOCKET_CLOSED,
\r
2622 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2624 xByteCount = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
\r
2627 /* How much was actually sent? */
\r
2628 xByteCount = ( ( BaseType_t ) uxDataLength ) - xBytesLeft;
\r
2630 if( xByteCount == 0 )
\r
2632 if( pxSocket->u.xTCP.ucTCPState > eESTABLISHED )
\r
2634 xByteCount = ( BaseType_t ) -pdFREERTOS_ERRNO_ENOTCONN;
\r
2638 if( ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) != pdFALSE )
\r
2640 FreeRTOS_debug_printf( ( "FreeRTOS_send: %u -> %lxip:%d: no space\n",
\r
2641 pxSocket->usLocalPort,
\r
2642 pxSocket->u.xTCP.ulRemoteIP,
\r
2643 pxSocket->u.xTCP.usRemotePort ) );
\r
2646 xByteCount = ( BaseType_t ) -pdFREERTOS_ERRNO_ENOSPC;
\r
2651 return xByteCount;
\r
2654 #endif /* ipconfigUSE_TCP */
\r
2655 /*-----------------------------------------------------------*/
\r
2657 #if( ipconfigUSE_TCP == 1 )
\r
2660 * Request to put a socket in listen mode
\r
2662 BaseType_t FreeRTOS_listen( Socket_t xSocket, BaseType_t xBacklog )
\r
2664 FreeRTOS_Socket_t *pxSocket;
\r
2665 BaseType_t xResult = 0;
\r
2667 pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2669 /* listen() is allowed for a valid TCP socket in Closed state and already
\r
2671 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2673 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2675 else if( ( pxSocket->u.xTCP.ucTCPState != eCLOSED ) && ( pxSocket->u.xTCP.ucTCPState != eCLOSE_WAIT ) )
\r
2677 /* Socket is in a wrong state. */
\r
2678 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2682 /* Backlog is interpreted here as "the maximum number of child
\r
2684 pxSocket->u.xTCP.usBacklog = ( uint16_t )FreeRTOS_min_int32( ( int32_t ) 0xffff, ( int32_t ) xBacklog );
\r
2686 /* This cleaning is necessary only if a listening socket is being
\r
2687 reused as it might have had a previous connection. */
\r
2688 if( pxSocket->u.xTCP.bits.bReuseSocket )
\r
2690 if( pxSocket->u.xTCP.rxStream != NULL )
\r
2692 vStreamBufferClear( pxSocket->u.xTCP.rxStream );
\r
2695 if( pxSocket->u.xTCP.txStream != NULL )
\r
2697 vStreamBufferClear( pxSocket->u.xTCP.txStream );
\r
2700 memset( pxSocket->u.xTCP.xPacket.u.ucLastPacket, '\0', sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket ) );
\r
2701 memset( &pxSocket->u.xTCP.xTCPWindow, '\0', sizeof( pxSocket->u.xTCP.xTCPWindow ) );
\r
2702 memset( &pxSocket->u.xTCP.bits, '\0', sizeof( pxSocket->u.xTCP.bits ) );
\r
2704 /* Now set the bReuseSocket flag again, because the bits have
\r
2705 just been cleared. */
\r
2706 pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE_UNSIGNED;
\r
2709 vTCPStateChange( pxSocket, eTCP_LISTEN );
\r
2715 #endif /* ipconfigUSE_TCP */
\r
2716 /*-----------------------------------------------------------*/
\r
2718 #if( ipconfigUSE_TCP == 1 )
\r
2720 /* shutdown - shut down part of a full-duplex connection */
\r
2721 BaseType_t FreeRTOS_shutdown( Socket_t xSocket, BaseType_t xHow )
\r
2723 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2724 BaseType_t xResult;
\r
2726 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2728 /*_RB_ Is this comment correct? The socket is not of a type that
\r
2729 supports the listen() operation. */
\r
2730 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2732 else if ( pxSocket->u.xTCP.ucTCPState != eESTABLISHED )
\r
2734 /*_RB_ Is this comment correct? The socket is not of a type that
\r
2735 supports the listen() operation. */
\r
2736 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2740 pxSocket->u.xTCP.bits.bUserShutdown = pdTRUE_UNSIGNED;
\r
2742 /* Let the IP-task perform the shutdown of the connection. */
\r
2743 pxSocket->u.xTCP.usTimeout = 1u;
\r
2744 xSendEventToIPTask( eTCPTimerEvent );
\r
2752 #endif /* ipconfigUSE_TCP */
\r
2753 /*-----------------------------------------------------------*/
\r
2755 #if( ipconfigUSE_TCP == 1 )
\r
2758 * A TCP timer has expired, now check all TCP sockets for:
\r
2759 * - Active connect
\r
2760 * - Send a delayed ACK
\r
2762 * - Send a keep-alive packet
\r
2763 * - Check for timeout (in non-connected states only)
\r
2765 TickType_t xTCPTimerCheck( BaseType_t xWillSleep )
\r
2767 FreeRTOS_Socket_t *pxSocket;
\r
2768 TickType_t xShortest = pdMS_TO_TICKS( ( TickType_t ) ipTCP_TIMER_PERIOD_MS );
\r
2769 TickType_t xNow = xTaskGetTickCount();
\r
2770 static TickType_t xLastTime = 0u;
\r
2771 TickType_t xDelta = xNow - xLastTime;
\r
2772 ListItem_t* pxEnd = ( ListItem_t * ) listGET_END_MARKER( &xBoundTCPSocketsList );
\r
2773 ListItem_t *pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );
\r
2777 if( xDelta == 0u )
\r
2782 while( pxIterator != pxEnd )
\r
2784 pxSocket = ( FreeRTOS_Socket_t * )listGET_LIST_ITEM_OWNER( pxIterator );
\r
2785 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator );
\r
2787 /* Sockets with 'tmout == 0' do not need any regular attention. */
\r
2788 if( pxSocket->u.xTCP.usTimeout == 0u )
\r
2793 if( xDelta < ( TickType_t ) pxSocket->u.xTCP.usTimeout )
\r
2795 pxSocket->u.xTCP.usTimeout = ( uint16_t ) ( ( ( TickType_t ) pxSocket->u.xTCP.usTimeout ) - xDelta );
\r
2800 pxSocket->u.xTCP.usTimeout = 0u;
\r
2801 rc = xTCPSocketCheck( pxSocket );
\r
2803 /* Within this function, the socket might want to send a delayed
\r
2804 ack or send out data or whatever it needs to do. */
\r
2807 /* Continue because the socket was deleted. */
\r
2812 /* In xEventBits the driver may indicate that the socket has
\r
2813 important events for the user. These are only done just before the
\r
2814 IP-task goes to sleep. */
\r
2815 if( pxSocket->xEventBits != 0u )
\r
2817 if( xWillSleep != pdFALSE )
\r
2819 /* The IP-task is about to go to sleep, so messages can be
\r
2820 sent to the socket owners. */
\r
2821 vSocketWakeUpUser( pxSocket );
\r
2825 /* Or else make sure this will be called again to wake-up
\r
2826 the sockets' owner. */
\r
2827 xShortest = ( TickType_t ) 0;
\r
2831 if( ( pxSocket->u.xTCP.usTimeout != 0u ) && ( xShortest > ( TickType_t ) pxSocket->u.xTCP.usTimeout ) )
\r
2833 xShortest = ( TickType_t ) pxSocket->u.xTCP.usTimeout;
\r
2840 #endif /* ipconfigUSE_TCP */
\r
2841 /*-----------------------------------------------------------*/
\r
2843 #if( ipconfigUSE_TCP == 1 )
\r
2846 * TCP: as multiple sockets may be bound to the same local port number
\r
2847 * looking up a socket is a little more complex:
\r
2848 * Both a local port, and a remote port and IP address are being used
\r
2849 * For a socket in listening mode, the remote port and IP address are both 0
\r
2851 FreeRTOS_Socket_t *pxTCPSocketLookup( uint32_t ulLocalIP, UBaseType_t uxLocalPort, uint32_t ulRemoteIP, UBaseType_t uxRemotePort )
\r
2853 ListItem_t *pxIterator;
\r
2854 FreeRTOS_Socket_t *pxResult = NULL, *pxListenSocket = NULL;
\r
2855 MiniListItem_t *pxEnd = ( MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );
\r
2857 /* Parameter not yet supported. */
\r
2858 ( void ) ulLocalIP;
\r
2860 for( pxIterator = ( ListItem_t * ) listGET_NEXT( pxEnd );
\r
2861 pxIterator != ( ListItem_t * ) pxEnd;
\r
2862 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
2864 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
\r
2866 if( pxSocket->usLocalPort == ( uint16_t ) uxLocalPort )
\r
2868 if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN )
\r
2870 /* If this is a socket listening to uxLocalPort, remember it
\r
2871 in case there is no perfect match. */
\r
2872 pxListenSocket = pxSocket;
\r
2874 else if( ( pxSocket->u.xTCP.usRemotePort == ( uint16_t ) uxRemotePort ) && ( pxSocket->u.xTCP.ulRemoteIP == ulRemoteIP ) )
\r
2876 /* For sockets not in listening mode, find a match with
\r
2877 xLocalPort, ulRemoteIP AND xRemotePort. */
\r
2878 pxResult = pxSocket;
\r
2883 if( pxResult == NULL )
\r
2885 /* An exact match was not found, maybe a listening socket was
\r
2887 pxResult = pxListenSocket;
\r
2893 #endif /* ipconfigUSE_TCP */
\r
2894 /*-----------------------------------------------------------*/
\r
2896 #if( ipconfigUSE_TCP == 1 )
\r
2898 const struct xSTREAM_BUFFER *FreeRTOS_get_rx_buf( Socket_t xSocket )
\r
2900 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * )xSocket;
\r
2901 struct xSTREAM_BUFFER *pxReturn = NULL;
\r
2903 /* Confirm that this is a TCP socket before dereferencing structure
\r
2904 member pointers. */
\r
2905 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdTRUE )
\r
2907 pxReturn = pxSocket->u.xTCP.rxStream;
\r
2913 #endif /* ipconfigUSE_TCP */
\r
2914 /*-----------------------------------------------------------*/
\r
2916 #if( ipconfigUSE_TCP == 1 )
\r
2918 static StreamBuffer_t *prvTCPCreateStream ( FreeRTOS_Socket_t *pxSocket, BaseType_t xIsInputStream )
\r
2920 StreamBuffer_t *pxBuffer;
\r
2924 /* Now that a stream is created, the maximum size is fixed before
\r
2925 creation, it could still be changed with setsockopt(). */
\r
2926 if( xIsInputStream != pdFALSE )
\r
2928 uxLength = pxSocket->u.xTCP.uxRxStreamSize;
\r
2930 if( pxSocket->u.xTCP.uxLittleSpace == 0ul )
\r
2932 pxSocket->u.xTCP.uxLittleSpace = ( sock20_PERCENT * pxSocket->u.xTCP.uxRxStreamSize ) / sock100_PERCENT;
\r
2935 if( pxSocket->u.xTCP.uxEnoughSpace == 0ul )
\r
2937 pxSocket->u.xTCP.uxEnoughSpace = ( sock80_PERCENT * pxSocket->u.xTCP.uxRxStreamSize ) / sock100_PERCENT;
\r
2942 uxLength = pxSocket->u.xTCP.uxTxStreamSize;
\r
2945 /* Add an extra 4 (or 8) bytes. */
\r
2946 uxLength += sizeof( size_t );
\r
2948 /* And make the length a multiple of sizeof( size_t ). */
\r
2949 uxLength &= ~( sizeof( size_t ) - 1u );
\r
2951 uxSize = sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) + uxLength;
\r
2953 pxBuffer = ( StreamBuffer_t * )pvPortMallocLarge( uxSize );
\r
2955 if( pxBuffer == NULL )
\r
2957 FreeRTOS_debug_printf( ( "prvTCPCreateStream: malloc failed\n" ) );
\r
2958 pxSocket->u.xTCP.bits.bMallocError = pdTRUE_UNSIGNED;
\r
2959 vTCPStateChange( pxSocket, eCLOSE_WAIT );
\r
2963 /* Clear the markers of the stream */
\r
2964 memset( pxBuffer, '\0', sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) );
\r
2965 pxBuffer->LENGTH = ( size_t ) uxLength ;
\r
2967 if( xTCPWindowLoggingLevel != 0 )
\r
2969 FreeRTOS_debug_printf( ( "prvTCPCreateStream: %cxStream created %lu bytes (total %lu)\n", xIsInputStream ? 'R' : 'T', uxLength, uxSize ) );
\r
2972 if( xIsInputStream != 0 )
\r
2974 pxSocket->u.xTCP.rxStream = pxBuffer;
\r
2978 pxSocket->u.xTCP.txStream = pxBuffer;
\r
2985 #endif /* ipconfigUSE_TCP */
\r
2986 /*-----------------------------------------------------------*/
\r
2988 #if( ipconfigUSE_TCP == 1 )
\r
2991 * Add data to the RxStream. When uxOffset > 0, data has come in out-of-order
\r
2992 * and will be put in front of the head so it can not be popped by the user.
\r
2994 int32_t lTCPAddRxdata( FreeRTOS_Socket_t *pxSocket, size_t uxOffset, const uint8_t *pcData, uint32_t ulByteCount )
\r
2996 StreamBuffer_t *pxStream = pxSocket->u.xTCP.rxStream;
\r
2998 #if( ipconfigUSE_CALLBACKS == 1 )
\r
2999 BaseType_t bHasHandler = ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xTCP.pxHandleReceive );
\r
3000 const uint8_t *pucBuffer = NULL;
\r
3001 #endif /* ipconfigUSE_CALLBACKS */
\r
3003 /* int32_t uxStreamBufferAdd( pxBuffer, uxOffset, pucData, aCount )
\r
3004 if( pucData != NULL ) copy data the the buffer
\r
3005 if( pucData == NULL ) no copying, just advance rxHead
\r
3006 if( uxOffset != 0 ) Just store data which has come out-of-order
\r
3007 if( uxOffset == 0 ) Also advance rxHead */
\r
3008 if( pxStream == NULL )
\r
3010 pxStream = prvTCPCreateStream( pxSocket, pdTRUE );
\r
3011 if( pxStream == NULL )
\r
3017 #if( ipconfigUSE_CALLBACKS == 1 )
\r
3019 if( ( bHasHandler != pdFALSE ) && ( uxStreamBufferGetSize( pxStream ) == 0u ) && ( uxOffset == 0ul ) && ( pcData != NULL ) )
\r
3021 /* Data can be passed directly to the user */
\r
3022 pucBuffer = pcData;
\r
3024 /* Zero-copy for call-back: no need to add the bytes to the
\r
3025 stream, only the pointer will be advanced by uxStreamBufferAdd(). */
\r
3029 #endif /* ipconfigUSE_CALLBACKS */
\r
3031 xResult = ( int32_t ) uxStreamBufferAdd( pxStream, uxOffset, pcData, ( size_t ) ulByteCount );
\r
3033 #if( ipconfigHAS_DEBUG_PRINTF != 0 )
\r
3035 if( xResult != ( int32_t ) ulByteCount )
\r
3037 FreeRTOS_debug_printf( ( "lTCPAddRxdata: at %ld: %ld/%lu bytes (tail %lu head %lu space %lu front %lu)\n",
\r
3038 uxOffset, xResult, ulByteCount,
\r
3041 uxStreamBufferFrontSpace( pxStream ),
\r
3042 pxStream->uxFront ) );
\r
3045 #endif /* ipconfigHAS_DEBUG_PRINTF */
\r
3047 if( uxOffset == 0u )
\r
3049 /* Data is being added to rxStream at the head (offs = 0) */
\r
3050 #if( ipconfigUSE_CALLBACKS == 1 )
\r
3051 if( bHasHandler != pdFALSE )
\r
3053 /* The socket owner has installed an OnReceive handler. Pass the
\r
3054 Rx data, without copying from the rxStream, to the user. */
\r
3057 uint8_t *ucReadPtr = NULL;
\r
3059 if( pucBuffer != NULL )
\r
3061 ucReadPtr = ( uint8_t * )pucBuffer;
\r
3062 ulCount = ulByteCount;
\r
3067 ulCount = ( uint32_t ) uxStreamBufferGetPtr( pxStream, &( ucReadPtr ) );
\r
3070 if( ulCount == 0ul )
\r
3075 pxSocket->u.xTCP.pxHandleReceive( ( Socket_t )pxSocket, ( void* )ucReadPtr, ( size_t ) ulCount );
\r
3076 uxStreamBufferGet( pxStream, 0ul, NULL, ( size_t ) ulCount, pdFALSE );
\r
3079 #endif /* ipconfigUSE_CALLBACKS */
\r
3081 /* See if running out of space. */
\r
3082 if( pxSocket->u.xTCP.bits.bLowWater == pdFALSE_UNSIGNED )
\r
3084 size_t uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );
\r
3085 if( uxFrontSpace <= pxSocket->u.xTCP.uxLittleSpace )
\r
3087 pxSocket->u.xTCP.bits.bLowWater = pdTRUE_UNSIGNED;
\r
3088 pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
\r
3090 /* bLowWater was reached, send the changed window size. */
\r
3091 pxSocket->u.xTCP.usTimeout = 1u;
\r
3092 xSendEventToIPTask( eTCPTimerEvent );
\r
3096 /* New incoming data is available, wake up the user. User's
\r
3097 semaphores will be set just before the IP-task goes asleep. */
\r
3098 pxSocket->xEventBits |= eSOCKET_RECEIVE;
\r
3100 #if ipconfigSUPPORT_SELECT_FUNCTION == 1
\r
3102 if( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 )
\r
3104 pxSocket->xEventBits |= ( eSELECT_READ << SOCKET_EVENT_BIT_COUNT );
\r
3114 #endif /* ipconfigUSE_TCP */
\r
3115 /*-----------------------------------------------------------*/
\r
3117 #if( ipconfigUSE_TCP == 1 )
\r
3119 /* Function to get the remote address and IP port */
\r
3120 BaseType_t FreeRTOS_GetRemoteAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress )
\r
3122 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3123 BaseType_t xResult;
\r
3125 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3127 xResult = -pdFREERTOS_ERRNO_EINVAL;
\r
3131 /* BSD style sockets communicate IP and port addresses in network
\r
3134 IP address of remote machine. */
\r
3135 pxAddress->sin_addr = FreeRTOS_htonl ( pxSocket->u.xTCP.ulRemoteIP );
\r
3137 /* Port on remote machine. */
\r
3138 pxAddress->sin_port = FreeRTOS_htons ( pxSocket->u.xTCP.usRemotePort );
\r
3140 xResult = ( BaseType_t ) sizeof( ( *pxAddress ) );
\r
3146 #endif /* ipconfigUSE_TCP */
\r
3148 /*-----------------------------------------------------------*/
\r
3150 #if( ipconfigUSE_TCP == 1 )
\r
3152 /* Returns the number of bytes that may be added to txStream */
\r
3153 BaseType_t FreeRTOS_maywrite( Socket_t xSocket )
\r
3155 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3156 BaseType_t xResult;
\r
3158 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3160 xResult = -pdFREERTOS_ERRNO_EINVAL;
\r
3162 else if( pxSocket->u.xTCP.ucTCPState != eESTABLISHED )
\r
3164 if( ( pxSocket->u.xTCP.ucTCPState < eCONNECT_SYN ) || ( pxSocket->u.xTCP.ucTCPState > eESTABLISHED ) )
\r
3173 else if( pxSocket->u.xTCP.txStream == NULL )
\r
3175 xResult = ( BaseType_t ) pxSocket->u.xTCP.uxTxStreamSize;
\r
3179 xResult = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
\r
3185 #endif /* ipconfigUSE_TCP */
\r
3186 /*-----------------------------------------------------------*/
\r
3188 #if( ipconfigUSE_TCP ==1 )
\r
3190 BaseType_t FreeRTOS_tx_space( Socket_t xSocket )
\r
3192 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3193 BaseType_t xReturn;
\r
3195 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3197 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3201 if( pxSocket->u.xTCP.txStream != NULL )
\r
3203 xReturn = ( BaseType_t ) uxStreamBufferGetSpace ( pxSocket->u.xTCP.txStream );
\r
3207 xReturn = ( BaseType_t ) pxSocket->u.xTCP.uxTxStreamSize;
\r
3214 #endif /* ipconfigUSE_TCP */
\r
3215 /*-----------------------------------------------------------*/
\r
3217 #if( ipconfigUSE_TCP == 1 )
\r
3219 BaseType_t FreeRTOS_tx_size( Socket_t xSocket )
\r
3221 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3222 BaseType_t xReturn;
\r
3224 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3226 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3230 if( pxSocket->u.xTCP.txStream != NULL )
\r
3232 xReturn = ( BaseType_t ) uxStreamBufferGetSize ( pxSocket->u.xTCP.txStream );
\r
3243 #endif /* ipconfigUSE_TCP */
\r
3244 /*-----------------------------------------------------------*/
\r
3246 #if( ipconfigUSE_TCP == 1 )
\r
3248 /* Returns pdTRUE if TCP socket is connected. */
\r
3249 BaseType_t FreeRTOS_issocketconnected( Socket_t xSocket )
\r
3251 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3252 BaseType_t xReturn = pdFALSE;
\r
3254 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3256 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3260 if( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED )
\r
3262 if( pxSocket->u.xTCP.ucTCPState < eCLOSE_WAIT )
\r
3272 #endif /* ipconfigUSE_TCP */
\r
3273 /*-----------------------------------------------------------*/
\r
3275 #if( ipconfigUSE_TCP == 1 )
\r
3277 /* returns the actual size of MSS being used */
\r
3278 BaseType_t FreeRTOS_mss( Socket_t xSocket )
\r
3280 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3281 BaseType_t xReturn;
\r
3283 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3285 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3289 /* usCurMSS is declared as uint16_t to save space. FreeRTOS_mss()
\r
3290 will often be used in signed native-size expressions cast it to
\r
3292 xReturn = ( BaseType_t ) ( pxSocket->u.xTCP.usCurMSS );
\r
3298 #endif /* ipconfigUSE_TCP */
\r
3299 /*-----------------------------------------------------------*/
\r
3301 #if( ipconfigUSE_TCP == 1 )
\r
3303 /* HT: for internal use only: return the connection status */
\r
3304 BaseType_t FreeRTOS_connstatus( Socket_t xSocket )
\r
3306 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3307 BaseType_t xReturn;
\r
3309 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3311 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3315 /* Cast it to BaseType_t */
\r
3316 xReturn = ( BaseType_t ) ( pxSocket->u.xTCP.ucTCPState );
\r
3322 #endif /* ipconfigUSE_TCP */
\r
3323 /*-----------------------------------------------------------*/
\r
3325 #if( ipconfigUSE_TCP == 1 )
\r
3328 * Returns the number of bytes which can be read.
\r
3330 BaseType_t FreeRTOS_rx_size( Socket_t xSocket )
\r
3332 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3333 BaseType_t xReturn;
\r
3335 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3337 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3339 else if( pxSocket->u.xTCP.rxStream != NULL )
\r
3341 xReturn = ( BaseType_t ) uxStreamBufferGetSize( pxSocket->u.xTCP.rxStream );
\r
3351 #endif /* ipconfigUSE_TCP */
\r
3352 /*-----------------------------------------------------------*/
\r
3354 #if( ipconfigUSE_TCP == 1 )
\r
3356 void FreeRTOS_netstat( void )
\r
3358 IPStackEvent_t xAskEvent;
\r
3360 /* Ask the IP-task to call vTCPNetStat()
\r
3361 * to avoid accessing xBoundTCPSocketsList
\r
3363 xAskEvent.eEventType = eTCPNetStat;
\r
3364 xAskEvent.pvData = ( void * ) NULL;
\r
3365 xSendEventStructToIPTask( &xAskEvent, 1000u );
\r
3368 #endif /* ipconfigUSE_TCP */
\r
3369 /*-----------------------------------------------------------*/
\r
3371 #if( ( ipconfigHAS_PRINTF != 0 ) && ( ipconfigUSE_TCP == 1 ) )
\r
3373 void vTCPNetStat( void )
\r
3375 /* Show a simple listing of all created sockets and their connections */
\r
3376 ListItem_t *pxIterator;
\r
3377 BaseType_t count = 0;
\r
3379 if( listLIST_IS_INITIALISED( &xBoundTCPSocketsList ) == pdFALSE )
\r
3381 FreeRTOS_printf( ( "PLUS-TCP not initialized\n" ) );
\r
3385 FreeRTOS_printf( ( "Prot Port IP-Remote : Port R/T Status Alive tmout Child\n" ) );
\r
3386 for( pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );
\r
3387 pxIterator != ( ListItem_t * ) listGET_END_MARKER( &xBoundTCPSocketsList );
\r
3388 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
3390 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
\r
3391 #if( ipconfigTCP_KEEP_ALIVE == 1 )
\r
3392 TickType_t age = xTaskGetTickCount() - pxSocket->u.xTCP.xLastAliveTime;
\r
3394 TickType_t age = 0u;
\r
3396 #if( ipconfigUSE_CALLBACKS == 1 )
\r
3397 void *pxHandleReceive = (void*)pxSocket->u.xTCP.pxHandleReceive;
\r
3399 void *pxHandleReceive = (void*)NULL;
\r
3401 char ucChildText[16] = "";
\r
3402 if (pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN)
\r
3404 const int32_t copied_len = snprintf( ucChildText, sizeof( ucChildText ), " %d/%d",
\r
3405 ( int ) pxSocket->u.xTCP.usChildCount,
\r
3406 ( int ) pxSocket->u.xTCP.usBacklog);
\r
3407 /* These should never evaluate to false since the buffers are both shorter than 5-6 characters (<=65535) */
\r
3408 configASSERT( copied_len >= 0 );
\r
3409 configASSERT( copied_len < sizeof( ucChildText ) );
\r
3411 FreeRTOS_printf( ( "TCP %5d %-16lxip:%5d %d/%d %-13.13s %6lu %6u%s\n",
\r
3412 pxSocket->usLocalPort, /* Local port on this machine */
\r
3413 pxSocket->u.xTCP.ulRemoteIP, /* IP address of remote machine */
\r
3414 pxSocket->u.xTCP.usRemotePort, /* Port on remote machine */
\r
3415 pxSocket->u.xTCP.rxStream != NULL,
\r
3416 pxSocket->u.xTCP.txStream != NULL,
\r
3417 FreeRTOS_GetTCPStateName( pxSocket->u.xTCP.ucTCPState ),
\r
3418 (age > 999999 ? 999999 : age), /* Format 'age' for printing */
\r
3419 pxSocket->u.xTCP.usTimeout,
\r
3421 /* Remove compiler warnings if FreeRTOS_debug_printf() is not defined. */
\r
3422 ( void ) pxHandleReceive;
\r
3426 for( pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundUDPSocketsList );
\r
3427 pxIterator != ( ListItem_t * ) listGET_END_MARKER( &xBoundUDPSocketsList );
\r
3428 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
3430 /* Local port on this machine */
\r
3431 FreeRTOS_printf( ( "UDP Port %5u\n",
\r
3432 FreeRTOS_ntohs( listGET_LIST_ITEM_VALUE( pxIterator ) ) ) );
\r
3436 FreeRTOS_printf( ( "FreeRTOS_netstat: %lu sockets %lu < %lu < %d buffers free\n",
\r
3438 uxGetMinimumFreeNetworkBuffers( ),
\r
3439 uxGetNumberOfFreeNetworkBuffers( ),
\r
3440 ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ) );
\r
3444 #endif /* ( ( ipconfigHAS_PRINTF != 0 ) && ( ipconfigUSE_TCP == 1 ) ) */
\r
3445 /*-----------------------------------------------------------*/
\r
3447 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
3449 void vSocketSelect( SocketSelect_t *pxSocketSet )
\r
3451 BaseType_t xRound;
\r
3452 EventBits_t xSocketBits, xBitsToClear;
\r
3453 #if ipconfigUSE_TCP == 1
\r
3454 BaseType_t xLastRound = 1;
\r
3456 BaseType_t xLastRound = 0;
\r
3459 /* These flags will be switched on after checking the socket status. */
\r
3460 EventBits_t xGroupBits = 0;
\r
3461 pxSocketSet->pxSocket = NULL;
\r
3463 for( xRound = 0; xRound <= xLastRound; xRound++ )
\r
3465 const ListItem_t *pxIterator;
\r
3466 const MiniListItem_t *pxEnd;
\r
3469 pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundUDPSocketsList );
\r
3471 #if ipconfigUSE_TCP == 1
\r
3474 pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );
\r
3476 #endif /* ipconfigUSE_TCP == 1 */
\r
3477 for( pxIterator = ( const ListItem_t * ) ( listGET_NEXT( pxEnd ) );
\r
3478 pxIterator != ( const ListItem_t * ) pxEnd;
\r
3479 pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
3481 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
\r
3482 if( pxSocket->pxSocketSet != pxSocketSet )
\r
3484 /* Socket does not belong to this select group. */
\r
3489 #if( ipconfigUSE_TCP == 1 )
\r
3490 if( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP )
\r
3492 /* Check if the socket has already been accepted by the
\r
3493 owner. If not, it is useless to return it from a
\r
3495 BaseType_t bAccepted = pdFALSE;
\r
3497 if( pxSocket->u.xTCP.bits.bPassQueued == pdFALSE_UNSIGNED )
\r
3499 if( pxSocket->u.xTCP.bits.bPassAccept == pdFALSE_UNSIGNED )
\r
3501 bAccepted = pdTRUE;
\r
3505 /* Is the set owner interested in READ events? */
\r
3506 if( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 )
\r
3508 if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN )
\r
3510 if( ( pxSocket->u.xTCP.pxPeerSocket != NULL ) && ( pxSocket->u.xTCP.pxPeerSocket->u.xTCP.bits.bPassAccept != 0 ) )
\r
3512 xSocketBits |= eSELECT_READ;
\r
3515 else if( ( pxSocket->u.xTCP.bits.bReuseSocket != pdFALSE_UNSIGNED ) && ( pxSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED ) )
\r
3517 /* This socket has the re-use flag. After connecting it turns into
\r
3518 aconnected socket. Set the READ event, so that accept() will be called. */
\r
3519 xSocketBits |= eSELECT_READ;
\r
3521 else if( ( bAccepted != 0 ) && ( FreeRTOS_recvcount( pxSocket ) > 0 ) )
\r
3523 xSocketBits |= eSELECT_READ;
\r
3526 /* Is the set owner interested in EXCEPTION events? */
\r
3527 if( ( pxSocket->xSelectBits & eSELECT_EXCEPT ) != 0 )
\r
3529 if( ( pxSocket->u.xTCP.ucTCPState == eCLOSE_WAIT ) || ( pxSocket->u.xTCP.ucTCPState == eCLOSED ) )
\r
3531 xSocketBits |= eSELECT_EXCEPT;
\r
3535 /* Is the set owner interested in WRITE events? */
\r
3536 if( ( pxSocket->xSelectBits & eSELECT_WRITE ) != 0 )
\r
3538 BaseType_t bMatch = pdFALSE;
\r
3540 if( bAccepted != 0 )
\r
3542 if( FreeRTOS_tx_space( pxSocket ) > 0 )
\r
3548 if( bMatch == pdFALSE )
\r
3550 if( ( pxSocket->u.xTCP.bits.bConnPrepared != pdFALSE_UNSIGNED ) &&
\r
3551 ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) &&
\r
3552 ( pxSocket->u.xTCP.bits.bConnPassed == pdFALSE_UNSIGNED ) )
\r
3554 pxSocket->u.xTCP.bits.bConnPassed = pdTRUE_UNSIGNED;
\r
3559 if( bMatch != pdFALSE )
\r
3561 xSocketBits |= eSELECT_WRITE;
\r
3566 #endif /* ipconfigUSE_TCP == 1 */
\r
3568 /* Select events for UDP are simpler. */
\r
3569 if( ( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 ) &&
\r
3570 ( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) > 0U ) )
\r
3572 xSocketBits |= eSELECT_READ;
\r
3574 /* The WRITE and EXCEPT bits are not used for UDP */
\r
3575 } /* if( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP ) */
\r
3577 /* Each socket keeps its own event flags, which are looked-up
\r
3578 by FreeRTOS_FD_ISSSET() */
\r
3579 pxSocket->xSocketBits = xSocketBits;
\r
3581 /* The ORed value will be used to set the bits in the event
\r
3583 xGroupBits |= xSocketBits;
\r
3585 } /* for( pxIterator ... ) */
\r
3586 } /* for( xRound = 0; xRound <= xLastRound; xRound++ ) */
\r
3588 xBitsToClear = xEventGroupGetBits( pxSocketSet->xSelectGroup );
\r
3590 /* Now set the necessary bits. */
\r
3591 xBitsToClear = ( xBitsToClear & ~xGroupBits ) & eSELECT_ALL;
\r
3593 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
3595 /* Maybe the socketset was signalled, but don't
\r
3596 clear the 'eSELECT_INTR' bit here, as it will be used
\r
3597 and cleared in FreeRTOS_select(). */
\r
3598 xBitsToClear &= ( EventBits_t ) ~eSELECT_INTR;
\r
3600 #endif /* ipconfigSUPPORT_SIGNALS */
\r
3602 if( xBitsToClear != 0 )
\r
3604 xEventGroupClearBits( pxSocketSet->xSelectGroup, xBitsToClear );
\r
3607 /* Now include eSELECT_CALL_IP to wakeup the caller. */
\r
3608 xEventGroupSetBits( pxSocketSet->xSelectGroup, xGroupBits | eSELECT_CALL_IP );
\r
3611 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
3612 /*-----------------------------------------------------------*/
\r
3614 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
3616 /* Send a signal to the task which reads from this socket. */
\r
3617 BaseType_t FreeRTOS_SignalSocket( Socket_t xSocket )
\r
3619 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3620 BaseType_t xReturn;
\r
3622 if( pxSocket == NULL )
\r
3624 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3627 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
3628 if( ( pxSocket->pxSocketSet != NULL ) && ( pxSocket->pxSocketSet->xSelectGroup != NULL ) )
\r
3630 xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, eSELECT_INTR );
\r
3634 #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
\r
3635 if( pxSocket->xEventGroup != NULL )
\r
3637 xEventGroupSetBits( pxSocket->xEventGroup, eSOCKET_INTR );
\r
3642 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3648 #endif /* ipconfigSUPPORT_SIGNALS */
\r
3649 /*-----------------------------------------------------------*/
\r
3651 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
3653 /* Send a signal to the task which reads from this socket (FromISR version). */
\r
3654 BaseType_t FreeRTOS_SignalSocketFromISR( Socket_t xSocket, BaseType_t *pxHigherPriorityTaskWoken )
\r
3656 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3657 BaseType_t xReturn;
\r
3658 IPStackEvent_t xEvent;
\r
3659 extern QueueHandle_t xNetworkEventQueue;
\r
3661 configASSERT( pxSocket != NULL );
\r
3662 configASSERT( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP );
\r
3663 configASSERT( pxSocket->xEventGroup );
\r
3665 xEvent.eEventType = eSocketSignalEvent;
\r
3666 xEvent.pvData = ( void * )pxSocket;
\r
3668 /* The IP-task will call FreeRTOS_SignalSocket for this socket. */
\r
3669 xReturn = xQueueSendToBackFromISR( xNetworkEventQueue, &xEvent, pxHigherPriorityTaskWoken );
\r
3674 #endif /* ipconfigSUPPORT_SIGNALS */
\r
3675 /*-----------------------------------------------------------*/
\r