2 * FreeRTOS+TCP V2.0.11
\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 data length, which may have been capped to
\r
706 the receive buffer size. */
\r
707 lReturn = ( int32_t ) pxNetworkBuffer->xDataLength;
\r
709 if( pxSourceAddress != NULL )
\r
711 pxSourceAddress->sin_port = pxNetworkBuffer->usPort;
\r
712 pxSourceAddress->sin_addr = pxNetworkBuffer->ulIPAddress;
\r
715 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
\r
717 /* The zero copy flag is not set. Truncate the length if it won't
\r
718 fit in the provided buffer. */
\r
719 if( lReturn > ( int32_t ) xBufferLength )
\r
721 iptraceRECVFROM_DISCARDING_BYTES( ( xBufferLength - lReturn ) );
\r
722 lReturn = ( int32_t )xBufferLength;
\r
725 /* Copy the received data into the provided buffer, then release the
\r
727 memcpy( pvBuffer, ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ), ( size_t )lReturn );
\r
729 if( ( xFlags & FREERTOS_MSG_PEEK ) == 0 )
\r
731 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
\r
736 /* The zero copy flag was set. pvBuffer is not a buffer into which
\r
737 the received data can be copied, but a pointer that must be set to
\r
738 point to the buffer in which the received data has already been
\r
740 *( ( void** ) pvBuffer ) = ( void * ) ( &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ) );
\r
744 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
745 else if( ( xEventBits & eSOCKET_INTR ) != 0 )
\r
747 lReturn = -pdFREERTOS_ERRNO_EINTR;
\r
748 iptraceRECVFROM_INTERRUPTED();
\r
750 #endif /* ipconfigSUPPORT_SIGNALS */
\r
753 lReturn = -pdFREERTOS_ERRNO_EWOULDBLOCK;
\r
754 iptraceRECVFROM_TIMEOUT();
\r
759 /*-----------------------------------------------------------*/
\r
761 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
763 NetworkBufferDescriptor_t *pxNetworkBuffer;
\r
764 IPStackEvent_t xStackTxEvent = { eStackTxEvent, NULL };
\r
765 TimeOut_t xTimeOut;
\r
766 TickType_t xTicksToWait;
\r
767 int32_t lReturn = 0;
\r
768 FreeRTOS_Socket_t *pxSocket;
\r
770 pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
772 /* The function prototype is designed to maintain the expected Berkeley
\r
773 sockets standard, but this implementation does not use all the
\r
775 ( void ) xDestinationAddressLength;
\r
776 configASSERT( pvBuffer );
\r
778 if( xTotalDataLength <= ( size_t ) ipMAX_UDP_PAYLOAD_LENGTH )
\r
780 /* If the socket is not already bound to an address, bind it now.
\r
781 Passing NULL as the address parameter tells FreeRTOS_bind() to select
\r
782 the address to bind to. */
\r
783 if( ( socketSOCKET_IS_BOUND( pxSocket ) != pdFALSE ) ||
\r
784 ( FreeRTOS_bind( xSocket, NULL, 0u ) == 0 ) )
\r
786 xTicksToWait = pxSocket->xSendBlockTime;
\r
788 #if( ipconfigUSE_CALLBACKS != 0 )
\r
790 if( xIsCallingFromIPTask() != pdFALSE )
\r
792 /* If this send function is called from within a call-back
\r
793 handler it may not block, otherwise chances would be big to
\r
794 get a deadlock: the IP-task waiting for itself. */
\r
795 xTicksToWait = ( TickType_t )0;
\r
798 #endif /* ipconfigUSE_CALLBACKS */
\r
800 if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
\r
802 xTicksToWait = ( TickType_t ) 0;
\r
805 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
\r
807 /* Zero copy is not set, so obtain a network buffer into
\r
808 which the payload will be copied. */
\r
809 vTaskSetTimeOutState( &xTimeOut );
\r
811 /* Block until a buffer becomes available, or until a
\r
812 timeout has been reached */
\r
813 pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( xTotalDataLength + sizeof( UDPPacket_t ), xTicksToWait );
\r
815 if( pxNetworkBuffer != NULL )
\r
817 memcpy( ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ), ( void * ) pvBuffer, xTotalDataLength );
\r
819 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdTRUE )
\r
821 /* The entire block time has been used up. */
\r
822 xTicksToWait = ( TickType_t ) 0;
\r
828 /* When zero copy is used, pvBuffer is a pointer to the
\r
829 payload of a buffer that has already been obtained from the
\r
830 stack. Obtain the network buffer pointer from the buffer. */
\r
831 pxNetworkBuffer = pxUDPPayloadBuffer_to_NetworkBuffer( (void*)pvBuffer );
\r
834 if( pxNetworkBuffer != NULL )
\r
836 pxNetworkBuffer->xDataLength = xTotalDataLength;
\r
837 pxNetworkBuffer->usPort = pxDestinationAddress->sin_port;
\r
838 pxNetworkBuffer->usBoundPort = ( uint16_t ) socketGET_SOCKET_PORT( pxSocket );
\r
839 pxNetworkBuffer->ulIPAddress = pxDestinationAddress->sin_addr;
\r
841 /* The socket options are passed to the IP layer in the
\r
842 space that will eventually get used by the Ethernet header. */
\r
843 pxNetworkBuffer->pucEthernetBuffer[ ipSOCKET_OPTIONS_OFFSET ] = pxSocket->ucSocketOptions;
\r
845 /* Tell the networking task that the packet needs sending. */
\r
846 xStackTxEvent.pvData = pxNetworkBuffer;
\r
848 /* Ask the IP-task to send this packet */
\r
849 if( xSendEventStructToIPTask( &xStackTxEvent, xTicksToWait ) == pdPASS )
\r
851 /* The packet was successfully sent to the IP task. */
\r
852 lReturn = ( int32_t ) xTotalDataLength;
\r
853 #if( ipconfigUSE_CALLBACKS == 1 )
\r
855 if( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xUDP.pxHandleSent ) )
\r
857 pxSocket->u.xUDP.pxHandleSent( (Socket_t *)pxSocket, xTotalDataLength );
\r
860 #endif /* ipconfigUSE_CALLBACKS */
\r
864 /* If the buffer was allocated in this function, release
\r
866 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
\r
868 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
\r
870 iptraceSTACK_TX_EVENT_LOST( ipSTACK_TX_EVENT );
\r
875 /* If errno was available, errno would be set to
\r
876 FREERTOS_ENOPKTS. As it is, the function must return the
\r
877 number of transmitted bytes, so the calling function knows
\r
878 how much data was actually sent. */
\r
879 iptraceNO_BUFFER_FOR_SENDTO();
\r
884 iptraceSENDTO_SOCKET_NOT_BOUND();
\r
889 /* The data is longer than the available buffer space. */
\r
890 iptraceSENDTO_DATA_TOO_LONG();
\r
895 /*-----------------------------------------------------------*/
\r
898 * FreeRTOS_bind() : binds a sockt to a local port number. If port 0 is
\r
899 * provided, a system provided port number will be assigned. This function can
\r
900 * be used for both UDP and TCP sockets. The actual binding will be performed
\r
901 * by the IP-task to avoid mutual access to the bound-socket-lists
\r
902 * (xBoundUDPSocketsList or xBoundTCPSocketsList).
\r
904 BaseType_t FreeRTOS_bind( Socket_t xSocket, struct freertos_sockaddr * pxAddress, socklen_t xAddressLength )
\r
906 IPStackEvent_t xBindEvent;
\r
907 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
908 BaseType_t xReturn = 0;
\r
910 ( void ) xAddressLength;
\r
912 if( ( pxSocket == NULL ) || ( pxSocket == FREERTOS_INVALID_SOCKET ) )
\r
914 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
916 /* Once a socket is bound to a port, it can not be bound to a different
\r
918 else if( socketSOCKET_IS_BOUND( pxSocket) != pdFALSE )
\r
920 /* The socket is already bound. */
\r
921 FreeRTOS_debug_printf( ( "vSocketBind: Socket already bound to %d\n", pxSocket->usLocalPort ) );
\r
922 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
926 /* Prepare a messages to the IP-task in order to perform the binding.
\r
927 The desired port number will be passed in usLocalPort. */
\r
928 xBindEvent.eEventType = eSocketBindEvent;
\r
929 xBindEvent.pvData = ( void * ) xSocket;
\r
930 if( pxAddress != NULL )
\r
932 pxSocket->usLocalPort = FreeRTOS_ntohs( pxAddress->sin_port );
\r
936 /* Caller wants to bind to a random port number. */
\r
937 pxSocket->usLocalPort = 0u;
\r
940 /* portMAX_DELAY is used as a the time-out parameter, as binding *must*
\r
941 succeed before the socket can be used. _RB_ The use of an infinite
\r
942 block time needs be changed as it could result in the task hanging. */
\r
943 if( xSendEventStructToIPTask( &xBindEvent, ( TickType_t ) portMAX_DELAY ) == pdFAIL )
\r
945 /* Failed to wake-up the IP-task, no use to wait for it */
\r
946 FreeRTOS_debug_printf( ( "FreeRTOS_bind: send event failed\n" ) );
\r
947 xReturn = -pdFREERTOS_ERRNO_ECANCELED;
\r
951 /* The IP-task will set the 'eSOCKET_BOUND' bit when it has done its
\r
953 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_BOUND, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, portMAX_DELAY );
\r
954 if( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE )
\r
956 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
965 * vSocketBind(): internal version of bind() that should not be called directly.
\r
966 * 'xInternal' is used for TCP sockets only: it allows to have several
\r
967 * (connected) child sockets bound to the same server port.
\r
969 BaseType_t vSocketBind( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr * pxAddress, size_t uxAddressLength, BaseType_t xInternal )
\r
971 BaseType_t xReturn = 0; /* In Berkeley sockets, 0 means pass for bind(). */
\r
972 List_t *pxSocketList;
\r
973 #if( ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 )
\r
974 struct freertos_sockaddr xAddress;
\r
975 #endif /* ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND */
\r
977 #if( ipconfigUSE_TCP == 1 )
\r
978 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
980 pxSocketList = &xBoundTCPSocketsList;
\r
983 #endif /* ipconfigUSE_TCP == 1 */
\r
985 pxSocketList = &xBoundUDPSocketsList;
\r
988 /* The function prototype is designed to maintain the expected Berkeley
\r
989 sockets standard, but this implementation does not use all the parameters. */
\r
990 ( void ) uxAddressLength;
\r
992 configASSERT( pxSocket );
\r
993 configASSERT( pxSocket != FREERTOS_INVALID_SOCKET );
\r
995 #if( ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 )
\r
997 /* pxAddress will be NULL if sendto() was called on a socket without the
\r
998 socket being bound to an address. In this case, automatically allocate
\r
999 an address and port to the socket. */
\r
1000 if( pxAddress == NULL )
\r
1002 pxAddress = &xAddress;
\r
1003 /* Put the port to zero to be assigned later. */
\r
1004 pxAddress->sin_port = 0u;
\r
1007 #endif /* ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 */
\r
1009 /* Sockets must be bound before calling FreeRTOS_sendto() if
\r
1010 ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is not set to 1. */
\r
1011 configASSERT( pxAddress );
\r
1013 if( pxAddress != NULL )
\r
1015 if( pxAddress->sin_port == 0u )
\r
1017 pxAddress->sin_port = prvGetPrivatePortNumber( ( BaseType_t )pxSocket->ucProtocol );
\r
1018 if( 0 == pxAddress->sin_port )
\r
1020 return -pdFREERTOS_ERRNO_EADDRNOTAVAIL;
\r
1024 /* If vSocketBind() is called from the API FreeRTOS_bind() it has been
\r
1025 confirmed that the socket was not yet bound to a port. If it is called
\r
1026 from the IP-task, no such check is necessary. */
\r
1028 /* Check to ensure the port is not already in use. If the bind is
\r
1029 called internally, a port MAY be used by more than one socket. */
\r
1030 if( ( ( xInternal == pdFALSE ) || ( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP ) ) &&
\r
1031 ( pxListFindListItemWithValue( pxSocketList, ( TickType_t ) pxAddress->sin_port ) != NULL ) )
\r
1033 FreeRTOS_debug_printf( ( "vSocketBind: %sP port %d in use\n",
\r
1034 pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP ? "TC" : "UD",
\r
1035 FreeRTOS_ntohs( pxAddress->sin_port ) ) );
\r
1036 xReturn = -pdFREERTOS_ERRNO_EADDRINUSE;
\r
1040 /* Allocate the port number to the socket.
\r
1041 This macro will set 'xBoundSocketListItem->xItemValue' */
\r
1042 socketSET_SOCKET_PORT( pxSocket, pxAddress->sin_port );
\r
1044 /* And also store it in a socket field 'usLocalPort' in host-byte-order,
\r
1045 mostly used for logging and debugging purposes */
\r
1046 pxSocket->usLocalPort = FreeRTOS_ntohs( pxAddress->sin_port );
\r
1048 /* Add the socket to the list of bound ports. */
\r
1050 /* If the network driver can iterate through 'xBoundUDPSocketsList',
\r
1051 by calling xPortHasUDPSocket() then the IP-task must temporarily
\r
1052 suspend the scheduler to keep the list in a consistent state. */
\r
1053 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1055 vTaskSuspendAll();
\r
1057 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1059 /* Add the socket to 'xBoundUDPSocketsList' or 'xBoundTCPSocketsList' */
\r
1060 vListInsertEnd( pxSocketList, &( pxSocket->xBoundSocketListItem ) );
\r
1062 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1066 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1072 xReturn = -pdFREERTOS_ERRNO_EADDRNOTAVAIL;
\r
1073 FreeRTOS_debug_printf( ( "vSocketBind: Socket no addr\n" ) );
\r
1076 if( xReturn != 0 )
\r
1078 iptraceBIND_FAILED( xSocket, ( FreeRTOS_ntohs( pxAddress->sin_port ) ) );
\r
1083 /*-----------------------------------------------------------*/
\r
1086 * Close a socket and free the allocated space
\r
1087 * In case of a TCP socket: the connection will not be closed automatically
\r
1088 * Subsequent messages for the closed socket will be responded to with a RST
\r
1089 * The IP-task will actually close the socket, after receiving a 'eSocketCloseEvent' message
\r
1091 BaseType_t FreeRTOS_closesocket( Socket_t xSocket )
\r
1093 BaseType_t xResult;
\r
1094 #if( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 )
\r
1095 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * )xSocket;
\r
1097 IPStackEvent_t xCloseEvent;
\r
1098 xCloseEvent.eEventType = eSocketCloseEvent;
\r
1099 xCloseEvent.pvData = ( void * ) xSocket;
\r
1101 if( ( xSocket == NULL ) || ( xSocket == FREERTOS_INVALID_SOCKET ) )
\r
1107 #if( ( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 ) )
\r
1109 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1111 /* Make sure that IP-task won't call the user callback's anymore */
\r
1112 pxSocket->u.xTCP.pxHandleConnected = NULL;
\r
1113 pxSocket->u.xTCP.pxHandleReceive = NULL;
\r
1114 pxSocket->u.xTCP.pxHandleSent = NULL;
\r
1117 #endif /* ( ( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 ) ) */
\r
1119 /* Let the IP task close the socket to keep it synchronised with the
\r
1120 packet handling. */
\r
1122 /* Note when changing the time-out value below, it must be checked who is calling
\r
1123 this function. If it is called by the IP-task, a deadlock could occur.
\r
1124 The IP-task would only call it in case of a user call-back */
\r
1125 if( xSendEventStructToIPTask( &xCloseEvent, ( TickType_t ) 0 ) == pdFAIL )
\r
1127 FreeRTOS_debug_printf( ( "FreeRTOS_closesocket: failed\n" ) );
\r
1139 /* This is the internal version of FreeRTOS_closesocket()
\r
1140 * It will be called by the IPtask only to avoid problems with synchronicity
\r
1142 void *vSocketClose( FreeRTOS_Socket_t *pxSocket )
\r
1144 NetworkBufferDescriptor_t *pxNetworkBuffer;
\r
1146 #if( ipconfigUSE_TCP == 1 )
\r
1148 /* For TCP: clean up a little more. */
\r
1149 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1151 #if( ipconfigUSE_TCP_WIN == 1 )
\r
1153 if( pxSocket->u.xTCP.pxAckMessage != NULL )
\r
1155 vReleaseNetworkBufferAndDescriptor( pxSocket->u.xTCP.pxAckMessage );
\r
1157 /* Free the resources which were claimed by the tcpWin member */
\r
1158 vTCPWindowDestroy( &pxSocket->u.xTCP.xTCPWindow );
\r
1160 #endif /* ipconfigUSE_TCP_WIN */
\r
1162 /* Free the input and output streams */
\r
1163 if( pxSocket->u.xTCP.rxStream != NULL )
\r
1165 vPortFreeLarge( pxSocket->u.xTCP.rxStream );
\r
1168 if( pxSocket->u.xTCP.txStream != NULL )
\r
1170 vPortFreeLarge( pxSocket->u.xTCP.txStream );
\r
1173 /* In case this is a child socket, make sure the child-count of the
\r
1174 parent socket is decreased. */
\r
1175 prvTCPSetSocketCount( pxSocket );
\r
1178 #endif /* ipconfigUSE_TCP == 1 */
\r
1180 /* Socket must be unbound first, to ensure no more packets are queued on
\r
1182 if( socketSOCKET_IS_BOUND( pxSocket ) != pdFALSE )
\r
1184 /* If the network driver can iterate through 'xBoundUDPSocketsList',
\r
1185 by calling xPortHasUDPSocket(), then the IP-task must temporarily
\r
1186 suspend the scheduler to keep the list in a consistent state. */
\r
1187 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1189 vTaskSuspendAll();
\r
1191 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1193 uxListRemove( &( pxSocket->xBoundSocketListItem ) );
\r
1195 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1199 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1202 /* Now the socket is not bound the list of waiting packets can be
\r
1204 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_UDP )
\r
1206 while( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) > 0U )
\r
1208 pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
\r
1209 uxListRemove( &( pxNetworkBuffer->xBufferListItem ) );
\r
1210 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
\r
1214 if( pxSocket->xEventGroup )
\r
1216 vEventGroupDelete( pxSocket->xEventGroup );
\r
1219 #if( ipconfigUSE_TCP == 1 ) && ( ipconfigHAS_DEBUG_PRINTF != 0 )
\r
1221 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1223 FreeRTOS_debug_printf( ( "FreeRTOS_closesocket[%u to %lxip:%u]: buffers %lu socks %lu\n",
\r
1224 pxSocket->usLocalPort,
\r
1225 pxSocket->u.xTCP.ulRemoteIP,
\r
1226 pxSocket->u.xTCP.usRemotePort,
\r
1227 uxGetNumberOfFreeNetworkBuffers(),
\r
1228 listCURRENT_LIST_LENGTH( &xBoundTCPSocketsList ) ) );
\r
1231 #endif /* ( ipconfigUSE_TCP == 1 ) && ( ipconfigHAS_DEBUG_PRINTF != 0 ) */
\r
1233 /* Anf finally, after all resources have been freed, free the socket space */
\r
1234 vPortFreeSocket( pxSocket );
\r
1239 /*-----------------------------------------------------------*/
\r
1241 #if ipconfigUSE_TCP == 1
\r
1244 * When a child socket gets closed, make sure to update the child-count of the
\r
1245 * parent. When a listening parent socket is closed, make sure no child-sockets
\r
1246 * keep a pointer to it.
\r
1248 static void prvTCPSetSocketCount( FreeRTOS_Socket_t *pxSocketToDelete )
\r
1250 const ListItem_t *pxIterator;
\r
1251 const MiniListItem_t *pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );
\r
1252 FreeRTOS_Socket_t *pxOtherSocket;
\r
1253 uint16_t usLocalPort = pxSocketToDelete->usLocalPort;
\r
1255 for( pxIterator = ( const ListItem_t * ) listGET_NEXT( pxEnd );
\r
1256 pxIterator != ( const ListItem_t * ) pxEnd;
\r
1257 pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
1259 pxOtherSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
\r
1260 if( ( pxOtherSocket->u.xTCP.ucTCPState == eTCP_LISTEN ) &&
\r
1261 ( pxOtherSocket->usLocalPort == usLocalPort ) &&
\r
1262 ( pxOtherSocket->u.xTCP.usChildCount ) )
\r
1264 pxOtherSocket->u.xTCP.usChildCount--;
\r
1265 FreeRTOS_debug_printf( ( "Lost: Socket %u now has %u / %u child%s\n",
\r
1266 pxOtherSocket->usLocalPort,
\r
1267 pxOtherSocket->u.xTCP.usChildCount,
\r
1268 pxOtherSocket->u.xTCP.usBacklog,
\r
1269 pxOtherSocket->u.xTCP.usChildCount == 1u ? "" : "ren" ) );
\r
1275 #endif /* ipconfigUSE_TCP == 1 */
\r
1277 /*-----------------------------------------------------------*/
\r
1279 BaseType_t FreeRTOS_setsockopt( Socket_t xSocket, int32_t lLevel, int32_t lOptionName, const void *pvOptionValue, size_t xOptionLength )
\r
1281 /* The standard Berkeley function returns 0 for success. */
\r
1282 BaseType_t xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
1283 BaseType_t lOptionValue;
\r
1284 FreeRTOS_Socket_t *pxSocket;
\r
1286 pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
1288 /* The function prototype is designed to maintain the expected Berkeley
\r
1289 sockets standard, but this implementation does not use all the parameters. */
\r
1291 ( void ) xOptionLength;
\r
1293 configASSERT( xSocket );
\r
1295 switch( lOptionName )
\r
1297 case FREERTOS_SO_RCVTIMEO :
\r
1298 /* Receive time out. */
\r
1299 pxSocket->xReceiveBlockTime = *( ( TickType_t * ) pvOptionValue );
\r
1303 case FREERTOS_SO_SNDTIMEO :
\r
1304 pxSocket->xSendBlockTime = *( ( TickType_t * ) pvOptionValue );
\r
1305 if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_UDP )
\r
1307 /* The send time out is capped for the reason stated in the
\r
1308 comments where ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS is defined
\r
1309 in FreeRTOSIPConfig.h (assuming an official configuration file
\r
1311 if( pxSocket->xSendBlockTime > ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS )
\r
1313 pxSocket->xSendBlockTime = ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS;
\r
1318 /* For TCP socket, it isn't necessary to limit the blocking time
\r
1319 because the FreeRTOS_send() function does not wait for a network
\r
1320 buffer to become available. */
\r
1324 #if( ipconfigUDP_MAX_RX_PACKETS > 0 )
\r
1325 case FREERTOS_SO_UDP_MAX_RX_PACKETS:
\r
1326 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_UDP )
\r
1328 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1330 pxSocket->u.xUDP.uxMaxPackets = *( ( UBaseType_t * ) pvOptionValue );
\r
1333 #endif /* ipconfigUDP_MAX_RX_PACKETS */
\r
1335 case FREERTOS_SO_UDPCKSUM_OUT :
\r
1336 /* Turn calculating of the UDP checksum on/off for this socket. */
\r
1337 lOptionValue = ( BaseType_t ) pvOptionValue;
\r
1339 if( lOptionValue == 0 )
\r
1341 pxSocket->ucSocketOptions &= ( uint8_t ) ~FREERTOS_SO_UDPCKSUM_OUT;
\r
1345 pxSocket->ucSocketOptions |= ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT;
\r
1350 #if( ipconfigUSE_CALLBACKS == 1 )
\r
1351 #if( ipconfigUSE_TCP == 1 )
\r
1352 case FREERTOS_SO_TCP_CONN_HANDLER: /* Set a callback for (dis)connection events */
\r
1353 case FREERTOS_SO_TCP_RECV_HANDLER: /* Install a callback for receiving TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
\r
1354 case FREERTOS_SO_TCP_SENT_HANDLER: /* Install a callback for sending TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
\r
1355 #endif /* ipconfigUSE_TCP */
\r
1356 case FREERTOS_SO_UDP_RECV_HANDLER: /* Install a callback for receiving UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
\r
1357 case FREERTOS_SO_UDP_SENT_HANDLER: /* Install a callback for sending UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
\r
1359 #if( ipconfigUSE_TCP == 1 )
\r
1361 UBaseType_t uxProtocol;
\r
1362 if( ( lOptionName == FREERTOS_SO_UDP_RECV_HANDLER ) ||
\r
1363 ( lOptionName == FREERTOS_SO_UDP_SENT_HANDLER ) )
\r
1365 uxProtocol = ( UBaseType_t ) FREERTOS_IPPROTO_UDP;
\r
1369 uxProtocol = ( UBaseType_t ) FREERTOS_IPPROTO_TCP;
\r
1372 if( pxSocket->ucProtocol != ( uint8_t ) uxProtocol )
\r
1374 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1379 /* No need to check if the socket has the right
\r
1380 protocol, because only UDP socket can be created. */
\r
1382 #endif /* ipconfigUSE_TCP */
\r
1384 switch( lOptionName )
\r
1386 #if ipconfigUSE_TCP == 1
\r
1387 case FREERTOS_SO_TCP_CONN_HANDLER:
\r
1388 pxSocket->u.xTCP.pxHandleConnected = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPConnected;
\r
1390 case FREERTOS_SO_TCP_RECV_HANDLER:
\r
1391 pxSocket->u.xTCP.pxHandleReceive = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPReceive;
\r
1393 case FREERTOS_SO_TCP_SENT_HANDLER:
\r
1394 pxSocket->u.xTCP.pxHandleSent = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPSent;
\r
1396 #endif /* ipconfigUSE_TCP */
\r
1397 case FREERTOS_SO_UDP_RECV_HANDLER:
\r
1398 pxSocket->u.xUDP.pxHandleReceive = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnUDPReceive;
\r
1400 case FREERTOS_SO_UDP_SENT_HANDLER:
\r
1401 pxSocket->u.xUDP.pxHandleSent = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnUDPSent;
\r
1410 #endif /* ipconfigUSE_CALLBACKS */
\r
1412 #if( ipconfigUSE_TCP != 0 )
\r
1413 #if( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 )
\r
1414 /* Each socket has a semaphore on which the using task normally
\r
1416 case FREERTOS_SO_SET_SEMAPHORE:
\r
1418 pxSocket->pxUserSemaphore = *( ( SemaphoreHandle_t * ) pvOptionValue );
\r
1422 #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
\r
1424 #if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK != 0 )
\r
1425 case FREERTOS_SO_WAKEUP_CALLBACK:
\r
1427 /* Each socket can have a callback function that is executed
\r
1428 when there is an event the socket's owner might want to
\r
1430 pxSocket->pxUserWakeCallback = ( SocketWakeupCallback_t ) pvOptionValue;
\r
1434 #endif /* ipconfigSOCKET_HAS_USER_WAKE_CALLBACK */
\r
1436 case FREERTOS_SO_SET_LOW_HIGH_WATER:
\r
1438 LowHighWater_t *pxLowHighWater = ( LowHighWater_t * ) pvOptionValue;
\r
1440 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1442 /* It is not allowed to access 'pxSocket->u.xTCP'. */
\r
1443 FreeRTOS_debug_printf( ( "FREERTOS_SO_SET_LOW_HIGH_WATER: wrong socket type\n" ) );
\r
1444 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1446 if( ( pxLowHighWater->uxLittleSpace >= pxLowHighWater->uxEnoughSpace ) ||
\r
1447 ( pxLowHighWater->uxEnoughSpace > pxSocket->u.xTCP.uxRxStreamSize ) )
\r
1449 /* Impossible values. */
\r
1450 FreeRTOS_debug_printf( ( "FREERTOS_SO_SET_LOW_HIGH_WATER: bad values\n" ) );
\r
1451 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1453 /* Send a STOP when buffer space drops below 'uxLittleSpace' bytes. */
\r
1454 pxSocket->u.xTCP.uxLittleSpace = pxLowHighWater->uxLittleSpace;
\r
1455 /* Send a GO when buffer space grows above 'uxEnoughSpace' bytes. */
\r
1456 pxSocket->u.xTCP.uxEnoughSpace = pxLowHighWater->uxEnoughSpace;
\r
1461 case FREERTOS_SO_SNDBUF: /* Set the size of the send buffer, in units of MSS (TCP only) */
\r
1462 case FREERTOS_SO_RCVBUF: /* Set the size of the receive buffer, in units of MSS (TCP only) */
\r
1464 uint32_t ulNewValue;
\r
1466 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1468 FreeRTOS_debug_printf( ( "Set SO_%sBUF: wrong socket type\n",
\r
1469 ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );
\r
1470 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1473 if( ( ( lOptionName == FREERTOS_SO_SNDBUF ) && ( pxSocket->u.xTCP.txStream != NULL ) ) ||
\r
1474 ( ( lOptionName == FREERTOS_SO_RCVBUF ) && ( pxSocket->u.xTCP.rxStream != NULL ) ) )
\r
1476 FreeRTOS_debug_printf( ( "Set SO_%sBUF: buffer already created\n",
\r
1477 ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );
\r
1478 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1481 ulNewValue = *( ( uint32_t * ) pvOptionValue );
\r
1483 if( lOptionName == FREERTOS_SO_SNDBUF )
\r
1485 /* Round up to nearest MSS size */
\r
1486 ulNewValue = FreeRTOS_round_up( ulNewValue, ( uint32_t ) pxSocket->u.xTCP.usInitMSS );
\r
1487 pxSocket->u.xTCP.uxTxStreamSize = ulNewValue;
\r
1491 pxSocket->u.xTCP.uxRxStreamSize = ulNewValue;
\r
1497 case FREERTOS_SO_WIN_PROPERTIES: /* Set all buffer and window properties in one call, parameter is pointer to WinProperties_t */
\r
1499 WinProperties_t* pxProps;
\r
1501 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1503 FreeRTOS_debug_printf( ( "Set SO_WIN_PROP: wrong socket type\n" ) );
\r
1504 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1507 if( ( pxSocket->u.xTCP.txStream != NULL ) || ( pxSocket->u.xTCP.rxStream != NULL ) )
\r
1509 FreeRTOS_debug_printf( ( "Set SO_WIN_PROP: buffer already created\n" ) );
\r
1510 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1513 pxProps = ( ( WinProperties_t * ) pvOptionValue );
\r
1515 if ( FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDBUF, &( pxProps->lTxBufSize ), sizeof( pxProps->lTxBufSize ) ) != 0 )
\r
1517 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1520 if ( FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVBUF, &( pxProps->lRxBufSize ), sizeof( pxProps->lRxBufSize ) ) != 0 )
\r
1522 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1525 #if( ipconfigUSE_TCP_WIN == 1 )
\r
1527 pxSocket->u.xTCP.uxRxWinSize = ( uint32_t )pxProps->lRxWinSize; /* Fixed value: size of the TCP reception window */
\r
1528 pxSocket->u.xTCP.uxTxWinSize = ( uint32_t )pxProps->lTxWinSize; /* Fixed value: size of the TCP transmit window */
\r
1532 pxSocket->u.xTCP.uxRxWinSize = 1u;
\r
1533 pxSocket->u.xTCP.uxTxWinSize = 1u;
\r
1537 /* In case the socket has already initialised its tcpWin,
\r
1538 adapt the window size parameters */
\r
1539 if( pxSocket->u.xTCP.xTCPWindow.u.bits.bHasInit != pdFALSE_UNSIGNED )
\r
1541 pxSocket->u.xTCP.xTCPWindow.xSize.ulRxWindowLength = pxSocket->u.xTCP.uxRxWinSize * pxSocket->u.xTCP.usInitMSS;
\r
1542 pxSocket->u.xTCP.xTCPWindow.xSize.ulTxWindowLength = pxSocket->u.xTCP.uxTxWinSize * pxSocket->u.xTCP.usInitMSS;
\r
1549 case FREERTOS_SO_REUSE_LISTEN_SOCKET: /* If true, the server-socket will turn into a connected socket */
\r
1551 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1553 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1555 if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
\r
1557 pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE_UNSIGNED;
\r
1561 pxSocket->u.xTCP.bits.bReuseSocket = pdFALSE_UNSIGNED;
\r
1567 case FREERTOS_SO_CLOSE_AFTER_SEND: /* As soon as the last byte has been transmitted, finalise the connection */
\r
1569 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1571 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1574 if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
\r
1576 pxSocket->u.xTCP.bits.bCloseAfterSend = pdTRUE_UNSIGNED;
\r
1580 pxSocket->u.xTCP.bits.bCloseAfterSend = pdFALSE_UNSIGNED;
\r
1586 case FREERTOS_SO_SET_FULL_SIZE: /* Refuse to send packets smaller than MSS */
\r
1588 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1590 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1593 if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
\r
1595 pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdTRUE_UNSIGNED;
\r
1599 pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdFALSE_UNSIGNED;
\r
1602 if( ( pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize == pdFALSE_UNSIGNED ) &&
\r
1603 ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) &&
\r
1604 ( FreeRTOS_outstanding( pxSocket ) != 0 ) )
\r
1606 pxSocket->u.xTCP.usTimeout = 1u; /* to set/clear bSendFullSize */
\r
1607 xSendEventToIPTask( eTCPTimerEvent );
\r
1613 case FREERTOS_SO_STOP_RX: /* Refuse to receive more packts */
\r
1615 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1617 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1620 if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
\r
1622 pxSocket->u.xTCP.bits.bRxStopped = pdTRUE_UNSIGNED;
\r
1626 pxSocket->u.xTCP.bits.bRxStopped = pdFALSE_UNSIGNED;
\r
1629 pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
\r
1630 pxSocket->u.xTCP.usTimeout = 1u; /* to set/clear bRxStopped */
\r
1631 xSendEventToIPTask( eTCPTimerEvent );
\r
1636 #endif /* ipconfigUSE_TCP == 1 */
\r
1639 /* No other options are handled. */
\r
1640 xReturn = -pdFREERTOS_ERRNO_ENOPROTOOPT;
\r
1647 /*-----------------------------------------------------------*/
\r
1649 /* Find an available port number per https://tools.ietf.org/html/rfc6056. */
\r
1650 static uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol )
\r
1652 const uint16_t usEphemeralPortCount =
\r
1653 socketAUTO_PORT_ALLOCATION_MAX_NUMBER - socketAUTO_PORT_ALLOCATION_START_NUMBER + 1;
\r
1654 uint16_t usIterations = usEphemeralPortCount;
\r
1655 uint32_t ulRandomSeed = 0;
\r
1656 uint16_t usResult = 0;
\r
1657 BaseType_t xGotZeroOnce = pdFALSE;
\r
1658 const List_t *pxList;
\r
1660 #if ipconfigUSE_TCP == 1
\r
1661 if( xProtocol == ( BaseType_t ) FREERTOS_IPPROTO_TCP )
\r
1663 pxList = &xBoundTCPSocketsList;
\r
1668 pxList = &xBoundUDPSocketsList;
\r
1671 /* Avoid compiler warnings if ipconfigUSE_TCP is not defined. */
\r
1672 ( void ) xProtocol;
\r
1674 /* Find the next available port using the random seed as a starting
\r
1678 /* Generate a random seed. */
\r
1679 ulRandomSeed = ipconfigRAND32( );
\r
1681 /* Only proceed if the random number generator succeeded. */
\r
1682 if( 0 == ulRandomSeed )
\r
1684 if( pdFALSE == xGotZeroOnce )
\r
1686 xGotZeroOnce = pdTRUE;
\r
1695 /* Map the random to a candidate port. */
\r
1697 socketAUTO_PORT_ALLOCATION_START_NUMBER +
\r
1698 ( ( ( uint16_t )ulRandomSeed ) % usEphemeralPortCount );
\r
1700 /* Check if there's already an open socket with the same protocol
\r
1702 if( NULL == pxListFindListItemWithValue(
\r
1704 ( TickType_t )FreeRTOS_htons( usResult ) ) )
\r
1706 usResult = FreeRTOS_htons( usResult );
\r
1716 while( usIterations > 0 );
\r
1720 /*-----------------------------------------------------------*/
\r
1722 /* pxListFindListItemWithValue: find a list item in a bound socket list
\r
1723 'xWantedItemValue' refers to a port number */
\r
1724 static const ListItem_t * pxListFindListItemWithValue( const List_t *pxList, TickType_t xWantedItemValue )
\r
1726 const ListItem_t * pxResult = NULL;
\r
1728 if( ( xIPIsNetworkTaskReady() != pdFALSE ) && ( pxList != NULL ) )
\r
1730 const ListItem_t *pxIterator;
\r
1731 const MiniListItem_t *pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( pxList );
\r
1732 for( pxIterator = ( const ListItem_t * ) listGET_NEXT( pxEnd );
\r
1733 pxIterator != ( const ListItem_t * ) pxEnd;
\r
1734 pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
1736 if( listGET_LIST_ITEM_VALUE( pxIterator ) == xWantedItemValue )
\r
1738 pxResult = pxIterator;
\r
1747 /*-----------------------------------------------------------*/
\r
1749 FreeRTOS_Socket_t *pxUDPSocketLookup( UBaseType_t uxLocalPort )
\r
1751 const ListItem_t *pxListItem;
\r
1752 FreeRTOS_Socket_t *pxSocket = NULL;
\r
1754 /* Looking up a socket is quite simple, find a match with the local port.
\r
1756 See if there is a list item associated with the port number on the
\r
1757 list of bound sockets. */
\r
1758 pxListItem = pxListFindListItemWithValue( &xBoundUDPSocketsList, ( TickType_t ) uxLocalPort );
\r
1760 if( pxListItem != NULL )
\r
1762 /* The owner of the list item is the socket itself. */
\r
1763 pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxListItem );
\r
1764 configASSERT( pxSocket != NULL );
\r
1769 /*-----------------------------------------------------------*/
\r
1771 #if ipconfigINCLUDE_FULL_INET_ADDR == 1
\r
1773 uint32_t FreeRTOS_inet_addr( const char * pcIPAddress )
\r
1775 const uint32_t ulDecimalBase = 10u;
\r
1776 uint8_t ucOctet[ socketMAX_IP_ADDRESS_OCTETS ];
\r
1777 const char *pcPointerOnEntering;
\r
1778 uint32_t ulReturn = 0UL, ulValue;
\r
1779 UBaseType_t uxOctetNumber;
\r
1780 BaseType_t xResult = pdPASS;
\r
1782 for( uxOctetNumber = 0u; uxOctetNumber < socketMAX_IP_ADDRESS_OCTETS; uxOctetNumber++ )
\r
1785 pcPointerOnEntering = pcIPAddress;
\r
1787 while( ( *pcIPAddress >= '0' ) && ( *pcIPAddress <= '9' ) )
\r
1789 /* Move previous read characters into the next decimal
\r
1791 ulValue *= ulDecimalBase;
\r
1793 /* Add the binary value of the ascii character. */
\r
1794 ulValue += ( ( uint32_t ) ( *pcIPAddress ) - ( uint32_t ) '0' );
\r
1796 /* Move to next character in the string. */
\r
1800 /* Check characters were read. */
\r
1801 if( pcIPAddress == pcPointerOnEntering )
\r
1806 /* Check the value fits in an 8-bit number. */
\r
1807 if( ulValue > 0xffUL )
\r
1813 ucOctet[ uxOctetNumber ] = ( uint8_t ) ulValue;
\r
1815 /* Check the next character is as expected. */
\r
1816 if( uxOctetNumber < ( socketMAX_IP_ADDRESS_OCTETS - 1u ) )
\r
1818 if( *pcIPAddress != '.' )
\r
1824 /* Move past the dot. */
\r
1830 if( xResult == pdFAIL )
\r
1832 /* No point going on. */
\r
1837 if( *pcIPAddress != ( char ) 0 )
\r
1839 /* Expected the end of the string. */
\r
1843 if( uxOctetNumber != socketMAX_IP_ADDRESS_OCTETS )
\r
1845 /* Didn't read enough octets. */
\r
1849 if( xResult == pdPASS )
\r
1851 ulReturn = FreeRTOS_inet_addr_quick( ucOctet[ 0 ], ucOctet[ 1 ], ucOctet[ 2 ], ucOctet[ 3 ] );
\r
1857 #endif /* ipconfigINCLUDE_FULL_INET_ADDR */
\r
1859 /*-----------------------------------------------------------*/
\r
1861 /* Function to get the local address and IP port */
\r
1862 size_t FreeRTOS_GetLocalAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress )
\r
1864 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
1866 /* IP address of local machine. */
\r
1867 pxAddress->sin_addr = *ipLOCAL_IP_ADDRESS_POINTER;
\r
1869 /* Local port on this machine. */
\r
1870 pxAddress->sin_port = FreeRTOS_htons( pxSocket->usLocalPort );
\r
1872 return sizeof( *pxAddress );
\r
1875 /*-----------------------------------------------------------*/
\r
1877 void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
\r
1879 /* _HT_ must work this out, now vSocketWakeUpUser will be called for any important
\r
1880 * event or transition */
\r
1881 #if( ipconfigSOCKET_HAS_USER_SEMAPHORE == 1 )
\r
1883 if( pxSocket->pxUserSemaphore != NULL )
\r
1885 xSemaphoreGive( pxSocket->pxUserSemaphore );
\r
1888 #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
\r
1890 #if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK == 1 )
\r
1892 if( pxSocket->pxUserWakeCallback != NULL )
\r
1894 pxSocket->pxUserWakeCallback( pxSocket );
\r
1897 #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
\r
1899 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
1901 if( pxSocket->pxSocketSet != NULL )
\r
1903 EventBits_t xSelectBits = ( pxSocket->xEventBits >> SOCKET_EVENT_BIT_COUNT ) & eSELECT_ALL;
\r
1904 if( xSelectBits != 0ul )
\r
1906 pxSocket->xSocketBits |= xSelectBits;
\r
1907 xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, xSelectBits );
\r
1911 pxSocket->xEventBits &= eSOCKET_ALL;
\r
1913 #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
\r
1915 if( ( pxSocket->xEventGroup != NULL ) && ( pxSocket->xEventBits != 0u ) )
\r
1917 xEventGroupSetBits( pxSocket->xEventGroup, pxSocket->xEventBits );
\r
1920 pxSocket->xEventBits = 0ul;
\r
1923 /*-----------------------------------------------------------*/
\r
1925 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1927 /* This define makes it possible for network-card drivers to inspect
\r
1928 * UDP message and see if there is any UDP socket bound to a given port
\r
1930 * This is probably only usefull in systems with a minimum of RAM and
\r
1931 * when lots of anonymous broadcast messages come in
\r
1933 BaseType_t xPortHasUDPSocket( uint16_t usPortNr )
\r
1935 BaseType_t xFound = pdFALSE;
\r
1937 vTaskSuspendAll();
\r
1939 if( ( pxListFindListItemWithValue( &xBoundUDPSocketsList, ( TickType_t ) usPortNr ) != NULL ) )
\r
1949 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1951 /*-----------------------------------------------------------*/
\r
1953 #if( ipconfigUSE_TCP == 1 )
\r
1955 static BaseType_t bMayConnect( FreeRTOS_Socket_t *pxSocket );
\r
1956 static BaseType_t bMayConnect( FreeRTOS_Socket_t *pxSocket )
\r
1958 switch( pxSocket->u.xTCP.ucTCPState )
\r
1961 case eCLOSE_WAIT: return 0;
\r
1962 case eCONNECT_SYN: return -pdFREERTOS_ERRNO_EINPROGRESS;
\r
1963 default: return -pdFREERTOS_ERRNO_EAGAIN;
\r
1967 #endif /* ipconfigUSE_TCP */
\r
1968 /*-----------------------------------------------------------*/
\r
1970 #if( ipconfigUSE_TCP == 1 )
\r
1972 static BaseType_t prvTCPConnectStart( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr *pxAddress )
\r
1974 BaseType_t xResult = 0;
\r
1976 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdFALSE )
\r
1978 /* Not a valid socket or wrong type */
\r
1979 xResult = -pdFREERTOS_ERRNO_EBADF;
\r
1981 else if( FreeRTOS_issocketconnected( pxSocket ) > 0 )
\r
1983 /* The socket is already connected. */
\r
1984 xResult = -pdFREERTOS_ERRNO_EISCONN;
\r
1986 else if( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE )
\r
1988 /* Bind the socket to the port that the client task will send from.
\r
1989 Non-standard, so the error returned is that returned by bind(). */
\r
1990 xResult = FreeRTOS_bind( ( Socket_t ) pxSocket, NULL, 0u );
\r
1993 if( xResult == 0 )
\r
1995 /* Check if it makes any sense to wait for a connect event, this condition
\r
1996 might change while sleeping, so it must be checked within each loop */
\r
1997 xResult = bMayConnect( pxSocket ); /* -EINPROGRESS, -EAGAIN, or 0 for OK */
\r
1999 /* Start the connect procedure, kernel will start working on it */
\r
2000 if( xResult == 0 )
\r
2002 pxSocket->u.xTCP.bits.bConnPrepared = pdFALSE_UNSIGNED;
\r
2003 pxSocket->u.xTCP.ucRepCount = 0u;
\r
2005 FreeRTOS_debug_printf( ( "FreeRTOS_connect: %u to %lxip:%u\n",
\r
2006 pxSocket->usLocalPort, FreeRTOS_ntohl( pxAddress->sin_addr ), FreeRTOS_ntohs( pxAddress->sin_port ) ) );
\r
2008 /* Port on remote machine. */
\r
2009 pxSocket->u.xTCP.usRemotePort = FreeRTOS_ntohs( pxAddress->sin_port );
\r
2011 /* IP address of remote machine. */
\r
2012 pxSocket->u.xTCP.ulRemoteIP = FreeRTOS_ntohl( pxAddress->sin_addr );
\r
2014 /* (client) internal state: socket wants to send a connect. */
\r
2015 vTCPStateChange( pxSocket, eCONNECT_SYN );
\r
2017 /* To start an active connect. */
\r
2018 pxSocket->u.xTCP.usTimeout = 1u;
\r
2020 if( xSendEventToIPTask( eTCPTimerEvent ) != pdPASS )
\r
2022 xResult = -pdFREERTOS_ERRNO_ECANCELED;
\r
2030 #endif /* ipconfigUSE_TCP */
\r
2031 /*-----------------------------------------------------------*/
\r
2033 #if( ipconfigUSE_TCP == 1 )
\r
2036 * FreeRTOS_connect: socket wants to connect to a remote port
\r
2038 BaseType_t FreeRTOS_connect( Socket_t xClientSocket, struct freertos_sockaddr *pxAddress, socklen_t xAddressLength )
\r
2040 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t* ) xClientSocket;
\r
2041 TickType_t xRemainingTime;
\r
2042 BaseType_t xTimed = pdFALSE;
\r
2043 BaseType_t xResult;
\r
2044 TimeOut_t xTimeOut;
\r
2046 ( void ) xAddressLength;
\r
2048 xResult = prvTCPConnectStart( pxSocket, pxAddress );
\r
2050 if( xResult == 0 )
\r
2052 /* And wait for the result */
\r
2055 if( xTimed == pdFALSE )
\r
2057 /* Only in the first round, check for non-blocking */
\r
2058 xRemainingTime = pxSocket->xReceiveBlockTime;
\r
2059 if( xRemainingTime == ( TickType_t )0 )
\r
2061 /* Not yet connected, correct state, non-blocking. */
\r
2062 xResult = -pdFREERTOS_ERRNO_EWOULDBLOCK;
\r
2066 /* Don't get here a second time. */
\r
2069 /* Fetch the current time */
\r
2070 vTaskSetTimeOutState( &xTimeOut );
\r
2073 /* Did it get connected while sleeping ? */
\r
2074 xResult = FreeRTOS_issocketconnected( pxSocket );
\r
2076 /* Returns positive when connected, negative means an error */
\r
2079 /* Return the error */
\r
2085 /* Socket now connected, return a zero */
\r
2090 /* Is it allowed to sleep more? */
\r
2091 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) )
\r
2093 xResult = -pdFREERTOS_ERRNO_ETIMEDOUT;
\r
2097 /* Go sleeping until we get any down-stream event */
\r
2098 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_CONNECT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2104 #endif /* ipconfigUSE_TCP */
\r
2105 /*-----------------------------------------------------------*/
\r
2107 #if( ipconfigUSE_TCP == 1 )
\r
2110 * FreeRTOS_accept: can return a new connected socket
\r
2111 * if the server socket is in listen mode and receives a connection request
\r
2112 * The new socket will be bound already to the same port number as the listing
\r
2115 Socket_t FreeRTOS_accept( Socket_t xServerSocket, struct freertos_sockaddr *pxAddress, socklen_t *pxAddressLength )
\r
2117 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xServerSocket;
\r
2118 FreeRTOS_Socket_t *pxClientSocket = NULL;
\r
2119 TickType_t xRemainingTime;
\r
2120 BaseType_t xTimed = pdFALSE, xAsk = pdFALSE;
\r
2121 TimeOut_t xTimeOut;
\r
2122 IPStackEvent_t xAskEvent;
\r
2124 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2126 /* Not a valid socket or wrong type */
\r
2127 pxClientSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
\r
2129 else if( ( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED ) &&
\r
2130 ( pxSocket->u.xTCP.ucTCPState != eTCP_LISTEN ) )
\r
2132 /* Parent socket is not in listening mode */
\r
2133 pxClientSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
\r
2137 /* Loop will stop with breaks. */
\r
2140 /* Is there a new client? */
\r
2141 vTaskSuspendAll();
\r
2143 if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED )
\r
2145 pxClientSocket = pxSocket->u.xTCP.pxPeerSocket;
\r
2149 pxClientSocket = pxSocket;
\r
2151 if( pxClientSocket != NULL )
\r
2153 pxSocket->u.xTCP.pxPeerSocket = NULL;
\r
2155 /* Is it still not taken ? */
\r
2156 if( pxClientSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED )
\r
2158 pxClientSocket->u.xTCP.bits.bPassAccept = pdFALSE_UNSIGNED;
\r
2162 pxClientSocket = NULL;
\r
2168 if( pxClientSocket != NULL )
\r
2170 if( pxAddress != NULL )
\r
2172 /* IP address of remote machine. */
\r
2173 pxAddress->sin_addr = FreeRTOS_ntohl( pxClientSocket->u.xTCP.ulRemoteIP );
\r
2175 /* Port on remote machine. */
\r
2176 pxAddress->sin_port = FreeRTOS_ntohs( pxClientSocket->u.xTCP.usRemotePort );
\r
2178 if( pxAddressLength != NULL )
\r
2180 *pxAddressLength = sizeof( *pxAddress );
\r
2183 if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED )
\r
2189 if( xAsk != pdFALSE )
\r
2191 /* Ask to set an event in 'xEventGroup' as soon as a new
\r
2192 client gets connected for this listening socket. */
\r
2193 xAskEvent.eEventType = eTCPAcceptEvent;
\r
2194 xAskEvent.pvData = ( void * ) pxSocket;
\r
2195 xSendEventStructToIPTask( &xAskEvent, portMAX_DELAY );
\r
2198 if( pxClientSocket != NULL )
\r
2203 if( xTimed == pdFALSE )
\r
2205 /* Only in the first round, check for non-blocking */
\r
2206 xRemainingTime = pxSocket->xReceiveBlockTime;
\r
2207 if( xRemainingTime == ( TickType_t ) 0 )
\r
2212 /* Don't get here a second time */
\r
2215 /* Fetch the current time */
\r
2216 vTaskSetTimeOutState( &xTimeOut );
\r
2219 /* Has the timeout been reached? */
\r
2220 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
\r
2225 /* Go sleeping until we get any down-stream event */
\r
2226 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_ACCEPT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2230 return ( Socket_t ) pxClientSocket;
\r
2232 #endif /* ipconfigUSE_TCP */
\r
2233 /*-----------------------------------------------------------*/
\r
2235 #if( ipconfigUSE_TCP == 1 )
\r
2238 * Read incoming data from a TCP socket
\r
2239 * Only after the last byte has been read, a close error might be returned
\r
2241 BaseType_t FreeRTOS_recv( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags )
\r
2243 BaseType_t xByteCount;
\r
2244 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2245 TickType_t xRemainingTime;
\r
2246 BaseType_t xTimed = pdFALSE;
\r
2247 TimeOut_t xTimeOut;
\r
2248 EventBits_t xEventBits = ( EventBits_t ) 0;
\r
2250 /* Check if the socket is valid, has type TCP and if it is bound to a
\r
2252 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2254 xByteCount = -pdFREERTOS_ERRNO_EINVAL;
\r
2258 if( pxSocket->u.xTCP.rxStream != NULL )
\r
2260 xByteCount = ( BaseType_t )uxStreamBufferGetSize ( pxSocket->u.xTCP.rxStream );
\r
2267 while( xByteCount == 0 )
\r
2269 switch( pxSocket->u.xTCP.ucTCPState )
\r
2272 case eCLOSE_WAIT: /* (server + client) waiting for a connection termination request from the local user. */
\r
2273 case eCLOSING: /* (server + client) waiting for a connection termination request acknowledgement from the remote TCP. */
\r
2274 if( pxSocket->u.xTCP.bits.bMallocError != pdFALSE_UNSIGNED )
\r
2276 /* The no-memory error has priority above the non-connected error.
\r
2277 Both are fatal and will elad to closing the socket. */
\r
2278 xByteCount = -pdFREERTOS_ERRNO_ENOMEM;
\r
2282 xByteCount = -pdFREERTOS_ERRNO_ENOTCONN;
\r
2284 /* Call continue to break out of the switch and also the while
\r
2291 if( xTimed == pdFALSE )
\r
2293 /* Only in the first round, check for non-blocking. */
\r
2294 xRemainingTime = pxSocket->xReceiveBlockTime;
\r
2296 if( xRemainingTime == ( TickType_t ) 0 )
\r
2298 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
2300 /* Just check for the interrupt flag. */
\r
2301 xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_INTR,
\r
2302 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, socketDONT_BLOCK );
\r
2304 #endif /* ipconfigSUPPORT_SIGNALS */
\r
2308 if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
\r
2313 /* Don't get here a second time. */
\r
2316 /* Fetch the current time. */
\r
2317 vTaskSetTimeOutState( &xTimeOut );
\r
2320 /* Has the timeout been reached? */
\r
2321 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
\r
2326 /* Block until there is a down-stream event. */
\r
2327 xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup,
\r
2328 eSOCKET_RECEIVE | eSOCKET_CLOSED | eSOCKET_INTR,
\r
2329 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2330 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
2332 if( ( xEventBits & eSOCKET_INTR ) != 0u )
\r
2339 ( void ) xEventBits;
\r
2341 #endif /* ipconfigSUPPORT_SIGNALS */
\r
2343 if( pxSocket->u.xTCP.rxStream != NULL )
\r
2345 xByteCount = ( BaseType_t ) uxStreamBufferGetSize ( pxSocket->u.xTCP.rxStream );
\r
2353 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
2354 if( ( xEventBits & eSOCKET_INTR ) != 0 )
\r
2356 if( ( xEventBits & ( eSOCKET_RECEIVE | eSOCKET_CLOSED ) ) != 0 )
\r
2358 /* Shouldn't have cleared other flags. */
\r
2359 xEventBits &= ~eSOCKET_INTR;
\r
2360 xEventGroupSetBits( pxSocket->xEventGroup, xEventBits );
\r
2362 xByteCount = -pdFREERTOS_ERRNO_EINTR;
\r
2365 #endif /* ipconfigSUPPORT_SIGNALS */
\r
2366 if( xByteCount > 0 )
\r
2368 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
\r
2370 xByteCount = ( BaseType_t ) uxStreamBufferGet( pxSocket->u.xTCP.rxStream, 0ul, ( uint8_t * ) pvBuffer, ( size_t ) xBufferLength, ( xFlags & FREERTOS_MSG_PEEK ) != 0 );
\r
2371 if( pxSocket->u.xTCP.bits.bLowWater != pdFALSE_UNSIGNED )
\r
2373 /* We had reached the low-water mark, now see if the flag
\r
2375 size_t uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );
\r
2377 if( uxFrontSpace >= pxSocket->u.xTCP.uxEnoughSpace )
\r
2379 pxSocket->u.xTCP.bits.bLowWater = pdFALSE_UNSIGNED;
\r
2380 pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
\r
2381 pxSocket->u.xTCP.usTimeout = 1u; /* because bLowWater is cleared. */
\r
2382 xSendEventToIPTask( eTCPTimerEvent );
\r
2388 /* Zero-copy reception of data: pvBuffer is a pointer to a pointer. */
\r
2389 xByteCount = ( BaseType_t ) uxStreamBufferGetPtr( pxSocket->u.xTCP.rxStream, (uint8_t **)pvBuffer );
\r
2392 } /* prvValidSocket() */
\r
2394 return xByteCount;
\r
2397 #endif /* ipconfigUSE_TCP */
\r
2398 /*-----------------------------------------------------------*/
\r
2400 #if( ipconfigUSE_TCP == 1 )
\r
2402 static int32_t prvTCPSendCheck( FreeRTOS_Socket_t *pxSocket, size_t xDataLength )
\r
2404 int32_t xResult = 1;
\r
2406 /* Is this a socket of type TCP and is it already bound to a port number ? */
\r
2407 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2409 xResult = -pdFREERTOS_ERRNO_EINVAL;
\r
2411 else if( pxSocket->u.xTCP.bits.bMallocError != pdFALSE_UNSIGNED )
\r
2413 xResult = -pdFREERTOS_ERRNO_ENOMEM;
\r
2415 else if( pxSocket->u.xTCP.ucTCPState == eCLOSED ||
\r
2416 pxSocket->u.xTCP.ucTCPState == eCLOSE_WAIT ||
\r
2417 pxSocket->u.xTCP.ucTCPState == eCLOSING )
\r
2419 xResult = -pdFREERTOS_ERRNO_ENOTCONN;
\r
2421 else if( pxSocket->u.xTCP.bits.bFinSent != pdFALSE_UNSIGNED )
\r
2423 /* This TCP connection is closing already, the FIN flag has been sent.
\r
2424 Maybe it is still delivering or receiving data.
\r
2425 Return OK in order not to get closed/deleted too quickly */
\r
2428 else if( xDataLength == 0ul )
\r
2430 /* send() is being called to send zero bytes */
\r
2433 else if( pxSocket->u.xTCP.txStream == NULL )
\r
2435 /* Create the outgoing stream only when it is needed */
\r
2436 prvTCPCreateStream( pxSocket, pdFALSE );
\r
2438 if( pxSocket->u.xTCP.txStream == NULL )
\r
2440 xResult = -pdFREERTOS_ERRNO_ENOMEM;
\r
2447 #endif /* ipconfigUSE_TCP */
\r
2448 /*-----------------------------------------------------------*/
\r
2450 #if( ipconfigUSE_TCP == 1 )
\r
2452 /* Get a direct pointer to the circular transmit buffer.
\r
2453 '*pxLength' will contain the number of bytes that may be written. */
\r
2454 uint8_t *FreeRTOS_get_tx_head( Socket_t xSocket, BaseType_t *pxLength )
\r
2456 uint8_t *pucReturn = NULL;
\r
2457 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2458 StreamBuffer_t *pxBuffer = NULL;
\r
2462 /* Confirm that this is a TCP socket before dereferencing structure
\r
2463 member pointers. */
\r
2464 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdTRUE )
\r
2466 pxBuffer = pxSocket->u.xTCP.txStream;
\r
2467 if( pxBuffer != NULL )
\r
2469 BaseType_t xSpace = ( BaseType_t )uxStreamBufferGetSpace( pxBuffer );
\r
2470 BaseType_t xRemain = ( BaseType_t )( pxBuffer->LENGTH - pxBuffer->uxHead );
\r
2472 *pxLength = FreeRTOS_min_BaseType( xSpace, xRemain );
\r
2473 pucReturn = pxBuffer->ucArray + pxBuffer->uxHead;
\r
2479 #endif /* ipconfigUSE_TCP */
\r
2480 /*-----------------------------------------------------------*/
\r
2482 #if( ipconfigUSE_TCP == 1 )
\r
2484 * Send data using a TCP socket. It is not necessary to have the socket
\r
2485 * connected already. Outgoing data will be stored and delivered as soon as
\r
2486 * the socket gets connected.
\r
2488 BaseType_t FreeRTOS_send( Socket_t xSocket, const void *pvBuffer, size_t uxDataLength, BaseType_t xFlags )
\r
2490 BaseType_t xByteCount;
\r
2491 BaseType_t xBytesLeft;
\r
2492 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2493 TickType_t xRemainingTime;
\r
2494 BaseType_t xTimed = pdFALSE;
\r
2495 TimeOut_t xTimeOut;
\r
2496 BaseType_t xCloseAfterSend;
\r
2498 /* Prevent compiler warnings about unused parameters. The parameter
\r
2499 may be used in future versions. */
\r
2502 xByteCount = ( BaseType_t ) prvTCPSendCheck( pxSocket, uxDataLength );
\r
2504 if( xByteCount > 0 )
\r
2506 /* xBytesLeft is number of bytes to send, will count to zero. */
\r
2507 xBytesLeft = ( BaseType_t ) uxDataLength;
\r
2509 /* xByteCount is number of bytes that can be sent now. */
\r
2510 xByteCount = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
\r
2512 /* While there are still bytes to be sent. */
\r
2513 while( xBytesLeft > 0 )
\r
2515 /* If txStream has space. */
\r
2516 if( xByteCount > 0 )
\r
2518 /* Don't send more than necessary. */
\r
2519 if( xByteCount > xBytesLeft )
\r
2521 xByteCount = xBytesLeft;
\r
2524 /* Is the close-after-send flag set and is this really the
\r
2525 last transmission? */
\r
2526 if( ( pxSocket->u.xTCP.bits.bCloseAfterSend != pdFALSE_UNSIGNED ) && ( xByteCount == xBytesLeft ) )
\r
2528 xCloseAfterSend = pdTRUE;
\r
2532 xCloseAfterSend = pdFALSE;
\r
2535 /* The flag 'bCloseAfterSend' can be set before sending data
\r
2536 using setsockopt()
\r
2538 When the last data packet is being sent out, a FIN flag will
\r
2539 be included to let the peer know that no more data is to be
\r
2540 expected. The use of 'bCloseAfterSend' is not mandatory, it
\r
2541 is just a faster way of transferring files (e.g. when using
\r
2543 if( xCloseAfterSend != pdFALSE )
\r
2545 /* Now suspend the scheduler: sending the last data and
\r
2546 setting bCloseRequested must be done together */
\r
2547 vTaskSuspendAll();
\r
2548 pxSocket->u.xTCP.bits.bCloseRequested = pdTRUE_UNSIGNED;
\r
2551 xByteCount = ( BaseType_t ) uxStreamBufferAdd( pxSocket->u.xTCP.txStream, 0ul, ( const uint8_t * ) pvBuffer, ( size_t ) xByteCount );
\r
2553 if( xCloseAfterSend != pdFALSE )
\r
2555 /* Now when the IP-task transmits the data, it will also
\r
2556 see that bCloseRequested is true and include the FIN
\r
2557 flag to start closure of the connection. */
\r
2561 /* Send a message to the IP-task so it can work on this
\r
2562 socket. Data is sent, let the IP-task work on it. */
\r
2563 pxSocket->u.xTCP.usTimeout = 1u;
\r
2565 if( xIsCallingFromIPTask() == pdFALSE )
\r
2567 /* Only send a TCP timer event when not called from the
\r
2569 xSendEventToIPTask( eTCPTimerEvent );
\r
2572 xBytesLeft -= xByteCount;
\r
2574 if( xBytesLeft == 0 )
\r
2579 /* As there are still bytes left to be sent, increase the
\r
2581 pvBuffer = ( void * ) ( ( ( const uint8_t * ) pvBuffer) + xByteCount );
\r
2584 /* Not all bytes have been sent. In case the socket is marked as
\r
2585 blocking sleep for a while. */
\r
2586 if( xTimed == pdFALSE )
\r
2588 /* Only in the first round, check for non-blocking. */
\r
2589 xRemainingTime = pxSocket->xSendBlockTime;
\r
2591 #if( ipconfigUSE_CALLBACKS != 0 )
\r
2593 if( xIsCallingFromIPTask() != pdFALSE )
\r
2595 /* If this send function is called from within a
\r
2596 call-back handler it may not block, otherwise
\r
2597 chances would be big to get a deadlock: the IP-task
\r
2598 waiting for itself. */
\r
2599 xRemainingTime = ( TickType_t ) 0;
\r
2602 #endif /* ipconfigUSE_CALLBACKS */
\r
2604 if( xRemainingTime == ( TickType_t ) 0 )
\r
2609 if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
\r
2614 /* Don't get here a second time. */
\r
2617 /* Fetch the current time. */
\r
2618 vTaskSetTimeOutState( &xTimeOut );
\r
2622 /* Has the timeout been reached? */
\r
2623 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
\r
2629 /* Go sleeping until down-stream events are received. */
\r
2630 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_SEND | eSOCKET_CLOSED,
\r
2631 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2633 xByteCount = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
\r
2636 /* How much was actually sent? */
\r
2637 xByteCount = ( ( BaseType_t ) uxDataLength ) - xBytesLeft;
\r
2639 if( xByteCount == 0 )
\r
2641 if( pxSocket->u.xTCP.ucTCPState > eESTABLISHED )
\r
2643 xByteCount = ( BaseType_t ) -pdFREERTOS_ERRNO_ENOTCONN;
\r
2647 if( ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) != pdFALSE )
\r
2649 FreeRTOS_debug_printf( ( "FreeRTOS_send: %u -> %lxip:%d: no space\n",
\r
2650 pxSocket->usLocalPort,
\r
2651 pxSocket->u.xTCP.ulRemoteIP,
\r
2652 pxSocket->u.xTCP.usRemotePort ) );
\r
2655 xByteCount = ( BaseType_t ) -pdFREERTOS_ERRNO_ENOSPC;
\r
2660 return xByteCount;
\r
2663 #endif /* ipconfigUSE_TCP */
\r
2664 /*-----------------------------------------------------------*/
\r
2666 #if( ipconfigUSE_TCP == 1 )
\r
2669 * Request to put a socket in listen mode
\r
2671 BaseType_t FreeRTOS_listen( Socket_t xSocket, BaseType_t xBacklog )
\r
2673 FreeRTOS_Socket_t *pxSocket;
\r
2674 BaseType_t xResult = 0;
\r
2676 pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2678 /* listen() is allowed for a valid TCP socket in Closed state and already
\r
2680 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2682 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2684 else if( ( pxSocket->u.xTCP.ucTCPState != eCLOSED ) && ( pxSocket->u.xTCP.ucTCPState != eCLOSE_WAIT ) )
\r
2686 /* Socket is in a wrong state. */
\r
2687 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2691 /* Backlog is interpreted here as "the maximum number of child
\r
2693 pxSocket->u.xTCP.usBacklog = ( uint16_t )FreeRTOS_min_int32( ( int32_t ) 0xffff, ( int32_t ) xBacklog );
\r
2695 /* This cleaning is necessary only if a listening socket is being
\r
2696 reused as it might have had a previous connection. */
\r
2697 if( pxSocket->u.xTCP.bits.bReuseSocket )
\r
2699 if( pxSocket->u.xTCP.rxStream != NULL )
\r
2701 vStreamBufferClear( pxSocket->u.xTCP.rxStream );
\r
2704 if( pxSocket->u.xTCP.txStream != NULL )
\r
2706 vStreamBufferClear( pxSocket->u.xTCP.txStream );
\r
2709 memset( pxSocket->u.xTCP.xPacket.u.ucLastPacket, '\0', sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket ) );
\r
2710 memset( &pxSocket->u.xTCP.xTCPWindow, '\0', sizeof( pxSocket->u.xTCP.xTCPWindow ) );
\r
2711 memset( &pxSocket->u.xTCP.bits, '\0', sizeof( pxSocket->u.xTCP.bits ) );
\r
2713 /* Now set the bReuseSocket flag again, because the bits have
\r
2714 just been cleared. */
\r
2715 pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE_UNSIGNED;
\r
2718 vTCPStateChange( pxSocket, eTCP_LISTEN );
\r
2724 #endif /* ipconfigUSE_TCP */
\r
2725 /*-----------------------------------------------------------*/
\r
2727 #if( ipconfigUSE_TCP == 1 )
\r
2729 /* shutdown - shut down part of a full-duplex connection */
\r
2730 BaseType_t FreeRTOS_shutdown( Socket_t xSocket, BaseType_t xHow )
\r
2732 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2733 BaseType_t xResult;
\r
2735 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2737 /*_RB_ Is this comment correct? The socket is not of a type that
\r
2738 supports the listen() operation. */
\r
2739 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2741 else if ( pxSocket->u.xTCP.ucTCPState != eESTABLISHED )
\r
2743 /*_RB_ Is this comment correct? The socket is not of a type that
\r
2744 supports the listen() operation. */
\r
2745 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2749 pxSocket->u.xTCP.bits.bUserShutdown = pdTRUE_UNSIGNED;
\r
2751 /* Let the IP-task perform the shutdown of the connection. */
\r
2752 pxSocket->u.xTCP.usTimeout = 1u;
\r
2753 xSendEventToIPTask( eTCPTimerEvent );
\r
2761 #endif /* ipconfigUSE_TCP */
\r
2762 /*-----------------------------------------------------------*/
\r
2764 #if( ipconfigUSE_TCP == 1 )
\r
2767 * A TCP timer has expired, now check all TCP sockets for:
\r
2768 * - Active connect
\r
2769 * - Send a delayed ACK
\r
2771 * - Send a keep-alive packet
\r
2772 * - Check for timeout (in non-connected states only)
\r
2774 TickType_t xTCPTimerCheck( BaseType_t xWillSleep )
\r
2776 FreeRTOS_Socket_t *pxSocket;
\r
2777 TickType_t xShortest = pdMS_TO_TICKS( ( TickType_t ) ipTCP_TIMER_PERIOD_MS );
\r
2778 TickType_t xNow = xTaskGetTickCount();
\r
2779 static TickType_t xLastTime = 0u;
\r
2780 TickType_t xDelta = xNow - xLastTime;
\r
2781 ListItem_t* pxEnd = ( ListItem_t * ) listGET_END_MARKER( &xBoundTCPSocketsList );
\r
2782 ListItem_t *pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );
\r
2786 if( xDelta == 0u )
\r
2791 while( pxIterator != pxEnd )
\r
2793 pxSocket = ( FreeRTOS_Socket_t * )listGET_LIST_ITEM_OWNER( pxIterator );
\r
2794 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator );
\r
2796 /* Sockets with 'tmout == 0' do not need any regular attention. */
\r
2797 if( pxSocket->u.xTCP.usTimeout == 0u )
\r
2802 if( xDelta < ( TickType_t ) pxSocket->u.xTCP.usTimeout )
\r
2804 pxSocket->u.xTCP.usTimeout = ( uint16_t ) ( ( ( TickType_t ) pxSocket->u.xTCP.usTimeout ) - xDelta );
\r
2809 pxSocket->u.xTCP.usTimeout = 0u;
\r
2810 rc = xTCPSocketCheck( pxSocket );
\r
2812 /* Within this function, the socket might want to send a delayed
\r
2813 ack or send out data or whatever it needs to do. */
\r
2816 /* Continue because the socket was deleted. */
\r
2821 /* In xEventBits the driver may indicate that the socket has
\r
2822 important events for the user. These are only done just before the
\r
2823 IP-task goes to sleep. */
\r
2824 if( pxSocket->xEventBits != 0u )
\r
2826 if( xWillSleep != pdFALSE )
\r
2828 /* The IP-task is about to go to sleep, so messages can be
\r
2829 sent to the socket owners. */
\r
2830 vSocketWakeUpUser( pxSocket );
\r
2834 /* Or else make sure this will be called again to wake-up
\r
2835 the sockets' owner. */
\r
2836 xShortest = ( TickType_t ) 0;
\r
2840 if( ( pxSocket->u.xTCP.usTimeout != 0u ) && ( xShortest > ( TickType_t ) pxSocket->u.xTCP.usTimeout ) )
\r
2842 xShortest = ( TickType_t ) pxSocket->u.xTCP.usTimeout;
\r
2849 #endif /* ipconfigUSE_TCP */
\r
2850 /*-----------------------------------------------------------*/
\r
2852 #if( ipconfigUSE_TCP == 1 )
\r
2855 * TCP: as multiple sockets may be bound to the same local port number
\r
2856 * looking up a socket is a little more complex:
\r
2857 * Both a local port, and a remote port and IP address are being used
\r
2858 * For a socket in listening mode, the remote port and IP address are both 0
\r
2860 FreeRTOS_Socket_t *pxTCPSocketLookup( uint32_t ulLocalIP, UBaseType_t uxLocalPort, uint32_t ulRemoteIP, UBaseType_t uxRemotePort )
\r
2862 ListItem_t *pxIterator;
\r
2863 FreeRTOS_Socket_t *pxResult = NULL, *pxListenSocket = NULL;
\r
2864 MiniListItem_t *pxEnd = ( MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );
\r
2866 /* Parameter not yet supported. */
\r
2867 ( void ) ulLocalIP;
\r
2869 for( pxIterator = ( ListItem_t * ) listGET_NEXT( pxEnd );
\r
2870 pxIterator != ( ListItem_t * ) pxEnd;
\r
2871 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
2873 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
\r
2875 if( pxSocket->usLocalPort == ( uint16_t ) uxLocalPort )
\r
2877 if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN )
\r
2879 /* If this is a socket listening to uxLocalPort, remember it
\r
2880 in case there is no perfect match. */
\r
2881 pxListenSocket = pxSocket;
\r
2883 else if( ( pxSocket->u.xTCP.usRemotePort == ( uint16_t ) uxRemotePort ) && ( pxSocket->u.xTCP.ulRemoteIP == ulRemoteIP ) )
\r
2885 /* For sockets not in listening mode, find a match with
\r
2886 xLocalPort, ulRemoteIP AND xRemotePort. */
\r
2887 pxResult = pxSocket;
\r
2892 if( pxResult == NULL )
\r
2894 /* An exact match was not found, maybe a listening socket was
\r
2896 pxResult = pxListenSocket;
\r
2902 #endif /* ipconfigUSE_TCP */
\r
2903 /*-----------------------------------------------------------*/
\r
2905 #if( ipconfigUSE_TCP == 1 )
\r
2907 const struct xSTREAM_BUFFER *FreeRTOS_get_rx_buf( Socket_t xSocket )
\r
2909 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * )xSocket;
\r
2910 struct xSTREAM_BUFFER *pxReturn = NULL;
\r
2912 /* Confirm that this is a TCP socket before dereferencing structure
\r
2913 member pointers. */
\r
2914 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdTRUE )
\r
2916 pxReturn = pxSocket->u.xTCP.rxStream;
\r
2922 #endif /* ipconfigUSE_TCP */
\r
2923 /*-----------------------------------------------------------*/
\r
2925 #if( ipconfigUSE_TCP == 1 )
\r
2927 static StreamBuffer_t *prvTCPCreateStream ( FreeRTOS_Socket_t *pxSocket, BaseType_t xIsInputStream )
\r
2929 StreamBuffer_t *pxBuffer;
\r
2933 /* Now that a stream is created, the maximum size is fixed before
\r
2934 creation, it could still be changed with setsockopt(). */
\r
2935 if( xIsInputStream != pdFALSE )
\r
2937 uxLength = pxSocket->u.xTCP.uxRxStreamSize;
\r
2939 if( pxSocket->u.xTCP.uxLittleSpace == 0ul )
\r
2941 pxSocket->u.xTCP.uxLittleSpace = ( sock20_PERCENT * pxSocket->u.xTCP.uxRxStreamSize ) / sock100_PERCENT;
\r
2944 if( pxSocket->u.xTCP.uxEnoughSpace == 0ul )
\r
2946 pxSocket->u.xTCP.uxEnoughSpace = ( sock80_PERCENT * pxSocket->u.xTCP.uxRxStreamSize ) / sock100_PERCENT;
\r
2951 uxLength = pxSocket->u.xTCP.uxTxStreamSize;
\r
2954 /* Add an extra 4 (or 8) bytes. */
\r
2955 uxLength += sizeof( size_t );
\r
2957 /* And make the length a multiple of sizeof( size_t ). */
\r
2958 uxLength &= ~( sizeof( size_t ) - 1u );
\r
2960 uxSize = sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) + uxLength;
\r
2962 pxBuffer = ( StreamBuffer_t * )pvPortMallocLarge( uxSize );
\r
2964 if( pxBuffer == NULL )
\r
2966 FreeRTOS_debug_printf( ( "prvTCPCreateStream: malloc failed\n" ) );
\r
2967 pxSocket->u.xTCP.bits.bMallocError = pdTRUE_UNSIGNED;
\r
2968 vTCPStateChange( pxSocket, eCLOSE_WAIT );
\r
2972 /* Clear the markers of the stream */
\r
2973 memset( pxBuffer, '\0', sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) );
\r
2974 pxBuffer->LENGTH = ( size_t ) uxLength ;
\r
2976 if( xTCPWindowLoggingLevel != 0 )
\r
2978 FreeRTOS_debug_printf( ( "prvTCPCreateStream: %cxStream created %lu bytes (total %lu)\n", xIsInputStream ? 'R' : 'T', uxLength, uxSize ) );
\r
2981 if( xIsInputStream != 0 )
\r
2983 pxSocket->u.xTCP.rxStream = pxBuffer;
\r
2987 pxSocket->u.xTCP.txStream = pxBuffer;
\r
2994 #endif /* ipconfigUSE_TCP */
\r
2995 /*-----------------------------------------------------------*/
\r
2997 #if( ipconfigUSE_TCP == 1 )
\r
3000 * Add data to the RxStream. When uxOffset > 0, data has come in out-of-order
\r
3001 * and will be put in front of the head so it can not be popped by the user.
\r
3003 int32_t lTCPAddRxdata( FreeRTOS_Socket_t *pxSocket, size_t uxOffset, const uint8_t *pcData, uint32_t ulByteCount )
\r
3005 StreamBuffer_t *pxStream = pxSocket->u.xTCP.rxStream;
\r
3007 #if( ipconfigUSE_CALLBACKS == 1 )
\r
3008 BaseType_t bHasHandler = ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xTCP.pxHandleReceive );
\r
3009 const uint8_t *pucBuffer = NULL;
\r
3010 #endif /* ipconfigUSE_CALLBACKS */
\r
3012 /* int32_t uxStreamBufferAdd( pxBuffer, uxOffset, pucData, aCount )
\r
3013 if( pucData != NULL ) copy data the the buffer
\r
3014 if( pucData == NULL ) no copying, just advance rxHead
\r
3015 if( uxOffset != 0 ) Just store data which has come out-of-order
\r
3016 if( uxOffset == 0 ) Also advance rxHead */
\r
3017 if( pxStream == NULL )
\r
3019 pxStream = prvTCPCreateStream( pxSocket, pdTRUE );
\r
3020 if( pxStream == NULL )
\r
3026 #if( ipconfigUSE_CALLBACKS == 1 )
\r
3028 if( ( bHasHandler != pdFALSE ) && ( uxStreamBufferGetSize( pxStream ) == 0u ) && ( uxOffset == 0ul ) && ( pcData != NULL ) )
\r
3030 /* Data can be passed directly to the user */
\r
3031 pucBuffer = pcData;
\r
3033 /* Zero-copy for call-back: no need to add the bytes to the
\r
3034 stream, only the pointer will be advanced by uxStreamBufferAdd(). */
\r
3038 #endif /* ipconfigUSE_CALLBACKS */
\r
3040 xResult = ( int32_t ) uxStreamBufferAdd( pxStream, uxOffset, pcData, ( size_t ) ulByteCount );
\r
3042 #if( ipconfigHAS_DEBUG_PRINTF != 0 )
\r
3044 if( xResult != ( int32_t ) ulByteCount )
\r
3046 FreeRTOS_debug_printf( ( "lTCPAddRxdata: at %ld: %ld/%lu bytes (tail %lu head %lu space %lu front %lu)\n",
\r
3047 uxOffset, xResult, ulByteCount,
\r
3050 uxStreamBufferFrontSpace( pxStream ),
\r
3051 pxStream->uxFront ) );
\r
3054 #endif /* ipconfigHAS_DEBUG_PRINTF */
\r
3056 if( uxOffset == 0u )
\r
3058 /* Data is being added to rxStream at the head (offs = 0) */
\r
3059 #if( ipconfigUSE_CALLBACKS == 1 )
\r
3060 if( bHasHandler != pdFALSE )
\r
3062 /* The socket owner has installed an OnReceive handler. Pass the
\r
3063 Rx data, without copying from the rxStream, to the user. */
\r
3066 uint8_t *ucReadPtr = NULL;
\r
3068 if( pucBuffer != NULL )
\r
3070 ucReadPtr = ( uint8_t * )pucBuffer;
\r
3071 ulCount = ulByteCount;
\r
3076 ulCount = ( uint32_t ) uxStreamBufferGetPtr( pxStream, &( ucReadPtr ) );
\r
3079 if( ulCount == 0ul )
\r
3084 pxSocket->u.xTCP.pxHandleReceive( (Socket_t *)pxSocket, ( void* )ucReadPtr, ( size_t ) ulCount );
\r
3085 uxStreamBufferGet( pxStream, 0ul, NULL, ( size_t ) ulCount, pdFALSE );
\r
3088 #endif /* ipconfigUSE_CALLBACKS */
\r
3090 /* See if running out of space. */
\r
3091 if( pxSocket->u.xTCP.bits.bLowWater == pdFALSE_UNSIGNED )
\r
3093 size_t uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );
\r
3094 if( uxFrontSpace <= pxSocket->u.xTCP.uxLittleSpace )
\r
3096 pxSocket->u.xTCP.bits.bLowWater = pdTRUE_UNSIGNED;
\r
3097 pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
\r
3099 /* bLowWater was reached, send the changed window size. */
\r
3100 pxSocket->u.xTCP.usTimeout = 1u;
\r
3101 xSendEventToIPTask( eTCPTimerEvent );
\r
3105 /* New incoming data is available, wake up the user. User's
\r
3106 semaphores will be set just before the IP-task goes asleep. */
\r
3107 pxSocket->xEventBits |= eSOCKET_RECEIVE;
\r
3109 #if ipconfigSUPPORT_SELECT_FUNCTION == 1
\r
3111 if( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 )
\r
3113 pxSocket->xEventBits |= ( eSELECT_READ << SOCKET_EVENT_BIT_COUNT );
\r
3123 #endif /* ipconfigUSE_TCP */
\r
3124 /*-----------------------------------------------------------*/
\r
3126 #if( ipconfigUSE_TCP == 1 )
\r
3128 /* Function to get the remote address and IP port */
\r
3129 BaseType_t FreeRTOS_GetRemoteAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress )
\r
3131 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3132 BaseType_t xResult;
\r
3134 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3136 xResult = -pdFREERTOS_ERRNO_EINVAL;
\r
3140 /* BSD style sockets communicate IP and port addresses in network
\r
3143 IP address of remote machine. */
\r
3144 pxAddress->sin_addr = FreeRTOS_htonl ( pxSocket->u.xTCP.ulRemoteIP );
\r
3146 /* Port on remote machine. */
\r
3147 pxAddress->sin_port = FreeRTOS_htons ( pxSocket->u.xTCP.usRemotePort );
\r
3149 xResult = ( BaseType_t ) sizeof( ( *pxAddress ) );
\r
3155 #endif /* ipconfigUSE_TCP */
\r
3157 /*-----------------------------------------------------------*/
\r
3159 #if( ipconfigUSE_TCP == 1 )
\r
3161 /* Returns the number of bytes that may be added to txStream */
\r
3162 BaseType_t FreeRTOS_maywrite( Socket_t xSocket )
\r
3164 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3165 BaseType_t xResult;
\r
3167 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3169 xResult = -pdFREERTOS_ERRNO_EINVAL;
\r
3171 else if( pxSocket->u.xTCP.ucTCPState != eESTABLISHED )
\r
3173 if( ( pxSocket->u.xTCP.ucTCPState < eCONNECT_SYN ) || ( pxSocket->u.xTCP.ucTCPState > eESTABLISHED ) )
\r
3182 else if( pxSocket->u.xTCP.txStream == NULL )
\r
3184 xResult = ( BaseType_t ) pxSocket->u.xTCP.uxTxStreamSize;
\r
3188 xResult = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
\r
3194 #endif /* ipconfigUSE_TCP */
\r
3195 /*-----------------------------------------------------------*/
\r
3197 #if( ipconfigUSE_TCP ==1 )
\r
3199 BaseType_t FreeRTOS_tx_space( Socket_t xSocket )
\r
3201 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3202 BaseType_t xReturn;
\r
3204 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3206 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3210 if( pxSocket->u.xTCP.txStream != NULL )
\r
3212 xReturn = ( BaseType_t ) uxStreamBufferGetSpace ( pxSocket->u.xTCP.txStream );
\r
3216 xReturn = ( BaseType_t ) pxSocket->u.xTCP.uxTxStreamSize;
\r
3223 #endif /* ipconfigUSE_TCP */
\r
3224 /*-----------------------------------------------------------*/
\r
3226 #if( ipconfigUSE_TCP == 1 )
\r
3228 BaseType_t FreeRTOS_tx_size( Socket_t xSocket )
\r
3230 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3231 BaseType_t xReturn;
\r
3233 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3235 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3239 if( pxSocket->u.xTCP.txStream != NULL )
\r
3241 xReturn = ( BaseType_t ) uxStreamBufferGetSize ( pxSocket->u.xTCP.txStream );
\r
3252 #endif /* ipconfigUSE_TCP */
\r
3253 /*-----------------------------------------------------------*/
\r
3255 #if( ipconfigUSE_TCP == 1 )
\r
3257 /* Returns pdTRUE if TCP socket is connected. */
\r
3258 BaseType_t FreeRTOS_issocketconnected( Socket_t xSocket )
\r
3260 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3261 BaseType_t xReturn = pdFALSE;
\r
3263 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3265 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3269 if( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED )
\r
3271 if( pxSocket->u.xTCP.ucTCPState < eCLOSE_WAIT )
\r
3281 #endif /* ipconfigUSE_TCP */
\r
3282 /*-----------------------------------------------------------*/
\r
3284 #if( ipconfigUSE_TCP == 1 )
\r
3286 /* returns the actual size of MSS being used */
\r
3287 BaseType_t FreeRTOS_mss( Socket_t xSocket )
\r
3289 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3290 BaseType_t xReturn;
\r
3292 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3294 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3298 /* usCurMSS is declared as uint16_t to save space. FreeRTOS_mss()
\r
3299 will often be used in signed native-size expressions cast it to
\r
3301 xReturn = ( BaseType_t ) ( pxSocket->u.xTCP.usCurMSS );
\r
3307 #endif /* ipconfigUSE_TCP */
\r
3308 /*-----------------------------------------------------------*/
\r
3310 #if( ipconfigUSE_TCP == 1 )
\r
3312 /* HT: for internal use only: return the connection status */
\r
3313 BaseType_t FreeRTOS_connstatus( Socket_t xSocket )
\r
3315 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3316 BaseType_t xReturn;
\r
3318 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3320 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3324 /* Cast it to BaseType_t */
\r
3325 xReturn = ( BaseType_t ) ( pxSocket->u.xTCP.ucTCPState );
\r
3331 #endif /* ipconfigUSE_TCP */
\r
3332 /*-----------------------------------------------------------*/
\r
3334 #if( ipconfigUSE_TCP == 1 )
\r
3337 * Returns the number of bytes which can be read.
\r
3339 BaseType_t FreeRTOS_rx_size( Socket_t xSocket )
\r
3341 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3342 BaseType_t xReturn;
\r
3344 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3346 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3348 else if( pxSocket->u.xTCP.rxStream != NULL )
\r
3350 xReturn = ( BaseType_t ) uxStreamBufferGetSize( pxSocket->u.xTCP.rxStream );
\r
3360 #endif /* ipconfigUSE_TCP */
\r
3361 /*-----------------------------------------------------------*/
\r
3363 #if( ipconfigUSE_TCP == 1 )
\r
3365 void FreeRTOS_netstat( void )
\r
3367 IPStackEvent_t xAskEvent;
\r
3369 /* Ask the IP-task to call vTCPNetStat()
\r
3370 * to avoid accessing xBoundTCPSocketsList
\r
3372 xAskEvent.eEventType = eTCPNetStat;
\r
3373 xAskEvent.pvData = ( void * ) NULL;
\r
3374 xSendEventStructToIPTask( &xAskEvent, 1000u );
\r
3377 #endif /* ipconfigUSE_TCP */
\r
3378 /*-----------------------------------------------------------*/
\r
3380 #if( ( ipconfigHAS_PRINTF != 0 ) && ( ipconfigUSE_TCP == 1 ) )
\r
3382 void vTCPNetStat( void )
\r
3384 /* Show a simple listing of all created sockets and their connections */
\r
3385 ListItem_t *pxIterator;
\r
3386 BaseType_t count = 0;
\r
3388 if( listLIST_IS_INITIALISED( &xBoundTCPSocketsList ) == pdFALSE )
\r
3390 FreeRTOS_printf( ( "PLUS-TCP not initialized\n" ) );
\r
3394 FreeRTOS_printf( ( "Prot Port IP-Remote : Port R/T Status Alive tmout Child\n" ) );
\r
3395 for( pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );
\r
3396 pxIterator != ( ListItem_t * ) listGET_END_MARKER( &xBoundTCPSocketsList );
\r
3397 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
3399 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
\r
3400 #if( ipconfigTCP_KEEP_ALIVE == 1 )
\r
3401 TickType_t age = xTaskGetTickCount() - pxSocket->u.xTCP.xLastAliveTime;
\r
3403 TickType_t age = 0u;
\r
3405 #if( ipconfigUSE_CALLBACKS == 1 )
\r
3406 void *pxHandleReceive = (void*)pxSocket->u.xTCP.pxHandleReceive;
\r
3408 void *pxHandleReceive = (void*)NULL;
\r
3410 char ucChildText[16] = "";
\r
3411 if (pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN)
\r
3413 const int32_t copied_len = snprintf( ucChildText, sizeof( ucChildText ), " %d/%d",
\r
3414 ( int ) pxSocket->u.xTCP.usChildCount,
\r
3415 ( int ) pxSocket->u.xTCP.usBacklog);
\r
3416 /* These should never evaluate to false since the buffers are both shorter than 5-6 characters (<=65535) */
\r
3417 configASSERT( copied_len >= 0 );
\r
3418 configASSERT( copied_len < sizeof( ucChildText ) );
\r
3420 FreeRTOS_printf( ( "TCP %5d %-16lxip:%5d %d/%d %-13.13s %6lu %6u%s\n",
\r
3421 pxSocket->usLocalPort, /* Local port on this machine */
\r
3422 pxSocket->u.xTCP.ulRemoteIP, /* IP address of remote machine */
\r
3423 pxSocket->u.xTCP.usRemotePort, /* Port on remote machine */
\r
3424 pxSocket->u.xTCP.rxStream != NULL,
\r
3425 pxSocket->u.xTCP.txStream != NULL,
\r
3426 FreeRTOS_GetTCPStateName( pxSocket->u.xTCP.ucTCPState ),
\r
3427 (age > 999999 ? 999999 : age), /* Format 'age' for printing */
\r
3428 pxSocket->u.xTCP.usTimeout,
\r
3430 /* Remove compiler warnings if FreeRTOS_debug_printf() is not defined. */
\r
3431 ( void ) pxHandleReceive;
\r
3435 for( pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundUDPSocketsList );
\r
3436 pxIterator != ( ListItem_t * ) listGET_END_MARKER( &xBoundUDPSocketsList );
\r
3437 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
3439 /* Local port on this machine */
\r
3440 FreeRTOS_printf( ( "UDP Port %5u\n",
\r
3441 FreeRTOS_ntohs( listGET_LIST_ITEM_VALUE( pxIterator ) ) ) );
\r
3445 FreeRTOS_printf( ( "FreeRTOS_netstat: %lu sockets %lu < %lu < %d buffers free\n",
\r
3447 uxGetMinimumFreeNetworkBuffers( ),
\r
3448 uxGetNumberOfFreeNetworkBuffers( ),
\r
3449 ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ) );
\r
3453 #endif /* ( ( ipconfigHAS_PRINTF != 0 ) && ( ipconfigUSE_TCP == 1 ) ) */
\r
3454 /*-----------------------------------------------------------*/
\r
3456 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
3458 void vSocketSelect( SocketSelect_t *pxSocketSet )
\r
3460 BaseType_t xRound;
\r
3461 EventBits_t xSocketBits, xBitsToClear;
\r
3462 #if ipconfigUSE_TCP == 1
\r
3463 BaseType_t xLastRound = 1;
\r
3465 BaseType_t xLastRound = 0;
\r
3468 /* These flags will be switched on after checking the socket status. */
\r
3469 EventBits_t xGroupBits = 0;
\r
3470 pxSocketSet->pxSocket = NULL;
\r
3472 for( xRound = 0; xRound <= xLastRound; xRound++ )
\r
3474 const ListItem_t *pxIterator;
\r
3475 const MiniListItem_t *pxEnd;
\r
3478 pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundUDPSocketsList );
\r
3480 #if ipconfigUSE_TCP == 1
\r
3483 pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );
\r
3485 #endif /* ipconfigUSE_TCP == 1 */
\r
3486 for( pxIterator = ( const ListItem_t * ) ( listGET_NEXT( pxEnd ) );
\r
3487 pxIterator != ( const ListItem_t * ) pxEnd;
\r
3488 pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
3490 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
\r
3491 if( pxSocket->pxSocketSet != pxSocketSet )
\r
3493 /* Socket does not belong to this select group. */
\r
3498 #if( ipconfigUSE_TCP == 1 )
\r
3499 if( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP )
\r
3501 /* Check if the socket has already been accepted by the
\r
3502 owner. If not, it is useless to return it from a
\r
3504 BaseType_t bAccepted = pdFALSE;
\r
3506 if( pxSocket->u.xTCP.bits.bPassQueued == pdFALSE_UNSIGNED )
\r
3508 if( pxSocket->u.xTCP.bits.bPassAccept == pdFALSE_UNSIGNED )
\r
3510 bAccepted = pdTRUE;
\r
3514 /* Is the set owner interested in READ events? */
\r
3515 if( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 )
\r
3517 if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN )
\r
3519 if( ( pxSocket->u.xTCP.pxPeerSocket != NULL ) && ( pxSocket->u.xTCP.pxPeerSocket->u.xTCP.bits.bPassAccept != 0 ) )
\r
3521 xSocketBits |= eSELECT_READ;
\r
3524 else if( ( pxSocket->u.xTCP.bits.bReuseSocket != pdFALSE_UNSIGNED ) && ( pxSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED ) )
\r
3526 /* This socket has the re-use flag. After connecting it turns into
\r
3527 aconnected socket. Set the READ event, so that accept() will be called. */
\r
3528 xSocketBits |= eSELECT_READ;
\r
3530 else if( ( bAccepted != 0 ) && ( FreeRTOS_recvcount( pxSocket ) > 0 ) )
\r
3532 xSocketBits |= eSELECT_READ;
\r
3535 /* Is the set owner interested in EXCEPTION events? */
\r
3536 if( ( pxSocket->xSelectBits & eSELECT_EXCEPT ) != 0 )
\r
3538 if( ( pxSocket->u.xTCP.ucTCPState == eCLOSE_WAIT ) || ( pxSocket->u.xTCP.ucTCPState == eCLOSED ) )
\r
3540 xSocketBits |= eSELECT_EXCEPT;
\r
3544 /* Is the set owner interested in WRITE events? */
\r
3545 if( ( pxSocket->xSelectBits & eSELECT_WRITE ) != 0 )
\r
3547 BaseType_t bMatch = pdFALSE;
\r
3549 if( bAccepted != 0 )
\r
3551 if( FreeRTOS_tx_space( pxSocket ) > 0 )
\r
3557 if( bMatch == pdFALSE )
\r
3559 if( ( pxSocket->u.xTCP.bits.bConnPrepared != pdFALSE_UNSIGNED ) &&
\r
3560 ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) &&
\r
3561 ( pxSocket->u.xTCP.bits.bConnPassed == pdFALSE_UNSIGNED ) )
\r
3563 pxSocket->u.xTCP.bits.bConnPassed = pdTRUE_UNSIGNED;
\r
3568 if( bMatch != pdFALSE )
\r
3570 xSocketBits |= eSELECT_WRITE;
\r
3575 #endif /* ipconfigUSE_TCP == 1 */
\r
3577 /* Select events for UDP are simpler. */
\r
3578 if( ( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 ) &&
\r
3579 ( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) > 0U ) )
\r
3581 xSocketBits |= eSELECT_READ;
\r
3583 /* The WRITE and EXCEPT bits are not used for UDP */
\r
3584 } /* if( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP ) */
\r
3586 /* Each socket keeps its own event flags, which are looked-up
\r
3587 by FreeRTOS_FD_ISSSET() */
\r
3588 pxSocket->xSocketBits = xSocketBits;
\r
3590 /* The ORed value will be used to set the bits in the event
\r
3592 xGroupBits |= xSocketBits;
\r
3594 } /* for( pxIterator ... ) */
\r
3595 } /* for( xRound = 0; xRound <= xLastRound; xRound++ ) */
\r
3597 xBitsToClear = xEventGroupGetBits( pxSocketSet->xSelectGroup );
\r
3599 /* Now set the necessary bits. */
\r
3600 xBitsToClear = ( xBitsToClear & ~xGroupBits ) & eSELECT_ALL;
\r
3602 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
3604 /* Maybe the socketset was signalled, but don't
\r
3605 clear the 'eSELECT_INTR' bit here, as it will be used
\r
3606 and cleared in FreeRTOS_select(). */
\r
3607 xBitsToClear &= ( EventBits_t ) ~eSELECT_INTR;
\r
3609 #endif /* ipconfigSUPPORT_SIGNALS */
\r
3611 if( xBitsToClear != 0 )
\r
3613 xEventGroupClearBits( pxSocketSet->xSelectGroup, xBitsToClear );
\r
3616 /* Now include eSELECT_CALL_IP to wakeup the caller. */
\r
3617 xEventGroupSetBits( pxSocketSet->xSelectGroup, xGroupBits | eSELECT_CALL_IP );
\r
3620 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
3621 /*-----------------------------------------------------------*/
\r
3623 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
3625 /* Send a signal to the task which reads from this socket. */
\r
3626 BaseType_t FreeRTOS_SignalSocket( Socket_t xSocket )
\r
3628 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3629 BaseType_t xReturn;
\r
3631 if( pxSocket == NULL )
\r
3633 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3636 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
3637 if( ( pxSocket->pxSocketSet != NULL ) && ( pxSocket->pxSocketSet->xSelectGroup != NULL ) )
\r
3639 xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, eSELECT_INTR );
\r
3643 #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
\r
3644 if( pxSocket->xEventGroup != NULL )
\r
3646 xEventGroupSetBits( pxSocket->xEventGroup, eSOCKET_INTR );
\r
3651 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3657 #endif /* ipconfigSUPPORT_SIGNALS */
\r
3658 /*-----------------------------------------------------------*/
\r
3660 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
3662 /* Send a signal to the task which reads from this socket (FromISR version). */
\r
3663 BaseType_t FreeRTOS_SignalSocketFromISR( Socket_t xSocket, BaseType_t *pxHigherPriorityTaskWoken )
\r
3665 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3666 BaseType_t xReturn;
\r
3667 IPStackEvent_t xEvent;
\r
3668 extern QueueHandle_t xNetworkEventQueue;
\r
3670 configASSERT( pxSocket != NULL );
\r
3671 configASSERT( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP );
\r
3672 configASSERT( pxSocket->xEventGroup );
\r
3674 xEvent.eEventType = eSocketSignalEvent;
\r
3675 xEvent.pvData = ( void * )pxSocket;
\r
3677 /* The IP-task will call FreeRTOS_SignalSocket for this socket. */
\r
3678 xReturn = xQueueSendToBackFromISR( xNetworkEventQueue, &xEvent, pxHigherPriorityTaskWoken );
\r
3683 #endif /* ipconfigSUPPORT_SIGNALS */
\r
3684 /*-----------------------------------------------------------*/
\r