2 * FreeRTOS+TCP 191100 experimental
\r
3 * Copyright (C) 2018 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 ) || ( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK_WITH_CONTEXT != 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 #if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK_WITH_CONTEXT != 0 )
\r
1437 case FREERTOS_SO_WAKE_CALLBACK_CONTEXT:
\r
1439 /* Each socket wake callback may be passed a user context. */
\r
1440 pxSocket->pvUserWakeCallbackContext = ( void * ) pvOptionValue;
\r
1444 #endif /* ipconfigSOCKET_HAS_USER_WAKE_CALLBACK_WITH_CONTEXT */
\r
1446 case FREERTOS_SO_SET_LOW_HIGH_WATER:
\r
1448 LowHighWater_t *pxLowHighWater = ( LowHighWater_t * ) pvOptionValue;
\r
1450 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1452 /* It is not allowed to access 'pxSocket->u.xTCP'. */
\r
1453 FreeRTOS_debug_printf( ( "FREERTOS_SO_SET_LOW_HIGH_WATER: wrong socket type\n" ) );
\r
1454 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1456 if( ( pxLowHighWater->uxLittleSpace >= pxLowHighWater->uxEnoughSpace ) ||
\r
1457 ( pxLowHighWater->uxEnoughSpace > pxSocket->u.xTCP.uxRxStreamSize ) )
\r
1459 /* Impossible values. */
\r
1460 FreeRTOS_debug_printf( ( "FREERTOS_SO_SET_LOW_HIGH_WATER: bad values\n" ) );
\r
1461 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1463 /* Send a STOP when buffer space drops below 'uxLittleSpace' bytes. */
\r
1464 pxSocket->u.xTCP.uxLittleSpace = pxLowHighWater->uxLittleSpace;
\r
1465 /* Send a GO when buffer space grows above 'uxEnoughSpace' bytes. */
\r
1466 pxSocket->u.xTCP.uxEnoughSpace = pxLowHighWater->uxEnoughSpace;
\r
1471 case FREERTOS_SO_SNDBUF: /* Set the size of the send buffer, in units of MSS (TCP only) */
\r
1472 case FREERTOS_SO_RCVBUF: /* Set the size of the receive buffer, in units of MSS (TCP only) */
\r
1474 uint32_t ulNewValue;
\r
1476 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1478 FreeRTOS_debug_printf( ( "Set SO_%sBUF: wrong socket type\n",
\r
1479 ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );
\r
1480 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1483 if( ( ( lOptionName == FREERTOS_SO_SNDBUF ) && ( pxSocket->u.xTCP.txStream != NULL ) ) ||
\r
1484 ( ( lOptionName == FREERTOS_SO_RCVBUF ) && ( pxSocket->u.xTCP.rxStream != NULL ) ) )
\r
1486 FreeRTOS_debug_printf( ( "Set SO_%sBUF: buffer already created\n",
\r
1487 ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );
\r
1488 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1491 ulNewValue = *( ( uint32_t * ) pvOptionValue );
\r
1493 if( lOptionName == FREERTOS_SO_SNDBUF )
\r
1495 /* Round up to nearest MSS size */
\r
1496 ulNewValue = FreeRTOS_round_up( ulNewValue, ( uint32_t ) pxSocket->u.xTCP.usInitMSS );
\r
1497 pxSocket->u.xTCP.uxTxStreamSize = ulNewValue;
\r
1501 pxSocket->u.xTCP.uxRxStreamSize = ulNewValue;
\r
1507 case FREERTOS_SO_WIN_PROPERTIES: /* Set all buffer and window properties in one call, parameter is pointer to WinProperties_t */
\r
1509 WinProperties_t* pxProps;
\r
1511 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1513 FreeRTOS_debug_printf( ( "Set SO_WIN_PROP: wrong socket type\n" ) );
\r
1514 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1517 if( ( pxSocket->u.xTCP.txStream != NULL ) || ( pxSocket->u.xTCP.rxStream != NULL ) )
\r
1519 FreeRTOS_debug_printf( ( "Set SO_WIN_PROP: buffer already created\n" ) );
\r
1520 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1523 pxProps = ( ( WinProperties_t * ) pvOptionValue );
\r
1525 if ( FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDBUF, &( pxProps->lTxBufSize ), sizeof( pxProps->lTxBufSize ) ) != 0 )
\r
1527 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1530 if ( FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVBUF, &( pxProps->lRxBufSize ), sizeof( pxProps->lRxBufSize ) ) != 0 )
\r
1532 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1535 #if( ipconfigUSE_TCP_WIN == 1 )
\r
1537 pxSocket->u.xTCP.uxRxWinSize = ( uint32_t )pxProps->lRxWinSize; /* Fixed value: size of the TCP reception window */
\r
1538 pxSocket->u.xTCP.uxTxWinSize = ( uint32_t )pxProps->lTxWinSize; /* Fixed value: size of the TCP transmit window */
\r
1542 pxSocket->u.xTCP.uxRxWinSize = 1u;
\r
1543 pxSocket->u.xTCP.uxTxWinSize = 1u;
\r
1547 /* In case the socket has already initialised its tcpWin,
\r
1548 adapt the window size parameters */
\r
1549 if( pxSocket->u.xTCP.xTCPWindow.u.bits.bHasInit != pdFALSE_UNSIGNED )
\r
1551 pxSocket->u.xTCP.xTCPWindow.xSize.ulRxWindowLength = pxSocket->u.xTCP.uxRxWinSize * pxSocket->u.xTCP.usInitMSS;
\r
1552 pxSocket->u.xTCP.xTCPWindow.xSize.ulTxWindowLength = pxSocket->u.xTCP.uxTxWinSize * pxSocket->u.xTCP.usInitMSS;
\r
1559 case FREERTOS_SO_REUSE_LISTEN_SOCKET: /* If true, the server-socket will turn into a connected socket */
\r
1561 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1563 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1565 if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
\r
1567 pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE_UNSIGNED;
\r
1571 pxSocket->u.xTCP.bits.bReuseSocket = pdFALSE_UNSIGNED;
\r
1577 case FREERTOS_SO_CLOSE_AFTER_SEND: /* As soon as the last byte has been transmitted, finalise the connection */
\r
1579 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1581 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1584 if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
\r
1586 pxSocket->u.xTCP.bits.bCloseAfterSend = pdTRUE_UNSIGNED;
\r
1590 pxSocket->u.xTCP.bits.bCloseAfterSend = pdFALSE_UNSIGNED;
\r
1596 case FREERTOS_SO_SET_FULL_SIZE: /* Refuse to send packets smaller than MSS */
\r
1598 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1600 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1603 if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
\r
1605 pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdTRUE_UNSIGNED;
\r
1609 pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdFALSE_UNSIGNED;
\r
1612 if( ( pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize == pdFALSE_UNSIGNED ) &&
\r
1613 ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) &&
\r
1614 ( FreeRTOS_outstanding( pxSocket ) != 0 ) )
\r
1616 pxSocket->u.xTCP.usTimeout = 1u; /* to set/clear bSendFullSize */
\r
1617 xSendEventToIPTask( eTCPTimerEvent );
\r
1623 case FREERTOS_SO_STOP_RX: /* Refuse to receive more packts */
\r
1625 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
1627 break; /* will return -pdFREERTOS_ERRNO_EINVAL */
\r
1630 if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
\r
1632 pxSocket->u.xTCP.bits.bRxStopped = pdTRUE_UNSIGNED;
\r
1636 pxSocket->u.xTCP.bits.bRxStopped = pdFALSE_UNSIGNED;
\r
1639 pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
\r
1640 pxSocket->u.xTCP.usTimeout = 1u; /* to set/clear bRxStopped */
\r
1641 xSendEventToIPTask( eTCPTimerEvent );
\r
1646 #endif /* ipconfigUSE_TCP == 1 */
\r
1649 /* No other options are handled. */
\r
1650 xReturn = -pdFREERTOS_ERRNO_ENOPROTOOPT;
\r
1657 /*-----------------------------------------------------------*/
\r
1659 /* Find an available port number per https://tools.ietf.org/html/rfc6056. */
\r
1660 static uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol )
\r
1662 const uint16_t usEphemeralPortCount =
\r
1663 socketAUTO_PORT_ALLOCATION_MAX_NUMBER - socketAUTO_PORT_ALLOCATION_START_NUMBER + 1;
\r
1664 uint16_t usIterations = usEphemeralPortCount;
\r
1665 uint32_t ulRandomSeed = 0;
\r
1666 uint16_t usResult = 0;
\r
1667 BaseType_t xGotZeroOnce = pdFALSE;
\r
1668 const List_t *pxList;
\r
1670 #if ipconfigUSE_TCP == 1
\r
1671 if( xProtocol == ( BaseType_t ) FREERTOS_IPPROTO_TCP )
\r
1673 pxList = &xBoundTCPSocketsList;
\r
1678 pxList = &xBoundUDPSocketsList;
\r
1681 /* Avoid compiler warnings if ipconfigUSE_TCP is not defined. */
\r
1682 ( void ) xProtocol;
\r
1684 /* Find the next available port using the random seed as a starting
\r
1688 /* Generate a random seed. */
\r
1689 ulRandomSeed = ipconfigRAND32( );
\r
1691 /* Only proceed if the random number generator succeeded. */
\r
1692 if( 0 == ulRandomSeed )
\r
1694 if( pdFALSE == xGotZeroOnce )
\r
1696 xGotZeroOnce = pdTRUE;
\r
1705 /* Map the random to a candidate port. */
\r
1707 socketAUTO_PORT_ALLOCATION_START_NUMBER +
\r
1708 ( ( ( uint16_t )ulRandomSeed ) % usEphemeralPortCount );
\r
1710 /* Check if there's already an open socket with the same protocol
\r
1712 if( NULL == pxListFindListItemWithValue(
\r
1714 ( TickType_t )FreeRTOS_htons( usResult ) ) )
\r
1716 usResult = FreeRTOS_htons( usResult );
\r
1726 while( usIterations > 0 );
\r
1730 /*-----------------------------------------------------------*/
\r
1732 /* pxListFindListItemWithValue: find a list item in a bound socket list
\r
1733 'xWantedItemValue' refers to a port number */
\r
1734 static const ListItem_t * pxListFindListItemWithValue( const List_t *pxList, TickType_t xWantedItemValue )
\r
1736 const ListItem_t * pxResult = NULL;
\r
1738 if( ( xIPIsNetworkTaskReady() != pdFALSE ) && ( pxList != NULL ) )
\r
1740 const ListItem_t *pxIterator;
\r
1741 const MiniListItem_t *pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( pxList );
\r
1742 for( pxIterator = ( const ListItem_t * ) listGET_NEXT( pxEnd );
\r
1743 pxIterator != ( const ListItem_t * ) pxEnd;
\r
1744 pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
1746 if( listGET_LIST_ITEM_VALUE( pxIterator ) == xWantedItemValue )
\r
1748 pxResult = pxIterator;
\r
1757 /*-----------------------------------------------------------*/
\r
1759 FreeRTOS_Socket_t *pxUDPSocketLookup( UBaseType_t uxLocalPort )
\r
1761 const ListItem_t *pxListItem;
\r
1762 FreeRTOS_Socket_t *pxSocket = NULL;
\r
1764 /* Looking up a socket is quite simple, find a match with the local port.
\r
1766 See if there is a list item associated with the port number on the
\r
1767 list of bound sockets. */
\r
1768 pxListItem = pxListFindListItemWithValue( &xBoundUDPSocketsList, ( TickType_t ) uxLocalPort );
\r
1770 if( pxListItem != NULL )
\r
1772 /* The owner of the list item is the socket itself. */
\r
1773 pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxListItem );
\r
1774 configASSERT( pxSocket != NULL );
\r
1779 /*-----------------------------------------------------------*/
\r
1781 #if ipconfigINCLUDE_FULL_INET_ADDR == 1
\r
1783 uint32_t FreeRTOS_inet_addr( const char * pcIPAddress )
\r
1785 const uint32_t ulDecimalBase = 10u;
\r
1786 uint8_t ucOctet[ socketMAX_IP_ADDRESS_OCTETS ];
\r
1787 const char *pcPointerOnEntering;
\r
1788 uint32_t ulReturn = 0UL, ulValue;
\r
1789 UBaseType_t uxOctetNumber;
\r
1790 BaseType_t xResult = pdPASS;
\r
1792 for( uxOctetNumber = 0u; uxOctetNumber < socketMAX_IP_ADDRESS_OCTETS; uxOctetNumber++ )
\r
1795 pcPointerOnEntering = pcIPAddress;
\r
1797 while( ( *pcIPAddress >= '0' ) && ( *pcIPAddress <= '9' ) )
\r
1799 /* Move previous read characters into the next decimal
\r
1801 ulValue *= ulDecimalBase;
\r
1803 /* Add the binary value of the ascii character. */
\r
1804 ulValue += ( ( uint32_t ) ( *pcIPAddress ) - ( uint32_t ) '0' );
\r
1806 /* Move to next character in the string. */
\r
1810 /* Check characters were read. */
\r
1811 if( pcIPAddress == pcPointerOnEntering )
\r
1816 /* Check the value fits in an 8-bit number. */
\r
1817 if( ulValue > 0xffUL )
\r
1823 ucOctet[ uxOctetNumber ] = ( uint8_t ) ulValue;
\r
1825 /* Check the next character is as expected. */
\r
1826 if( uxOctetNumber < ( socketMAX_IP_ADDRESS_OCTETS - 1u ) )
\r
1828 if( *pcIPAddress != '.' )
\r
1834 /* Move past the dot. */
\r
1840 if( xResult == pdFAIL )
\r
1842 /* No point going on. */
\r
1847 if( *pcIPAddress != ( char ) 0 )
\r
1849 /* Expected the end of the string. */
\r
1853 if( uxOctetNumber != socketMAX_IP_ADDRESS_OCTETS )
\r
1855 /* Didn't read enough octets. */
\r
1859 if( xResult == pdPASS )
\r
1861 ulReturn = FreeRTOS_inet_addr_quick( ucOctet[ 0 ], ucOctet[ 1 ], ucOctet[ 2 ], ucOctet[ 3 ] );
\r
1867 #endif /* ipconfigINCLUDE_FULL_INET_ADDR */
\r
1869 /*-----------------------------------------------------------*/
\r
1871 /* Function to get the local address and IP port */
\r
1872 size_t FreeRTOS_GetLocalAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress )
\r
1874 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
1876 /* IP address of local machine. */
\r
1877 pxAddress->sin_addr = *ipLOCAL_IP_ADDRESS_POINTER;
\r
1879 /* Local port on this machine. */
\r
1880 pxAddress->sin_port = FreeRTOS_htons( pxSocket->usLocalPort );
\r
1882 return sizeof( *pxAddress );
\r
1885 /*-----------------------------------------------------------*/
\r
1887 void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
\r
1889 /* _HT_ must work this out, now vSocketWakeUpUser will be called for any important
\r
1890 * event or transition */
\r
1891 #if( ipconfigSOCKET_HAS_USER_SEMAPHORE == 1 )
\r
1893 if( pxSocket->pxUserSemaphore != NULL )
\r
1895 xSemaphoreGive( pxSocket->pxUserSemaphore );
\r
1898 #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
\r
1900 #if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK == 1 )
\r
1902 if( pxSocket->pxUserWakeCallback != NULL )
\r
1904 pxSocket->pxUserWakeCallback( pxSocket );
\r
1907 #endif /* ipconfigSOCKET_HAS_USER_WAKE_CALLBACK */
\r
1909 #if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK_WITH_CONTEXT == 1 )
\r
1911 if( pxSocket->pxUserWakeCallback != NULL )
\r
1913 pxSocket->pxUserWakeCallback( pxSocket, pxSocket->pvUserWakeCallbackContext );
\r
1916 #endif /* ipconfigSOCKET_HAS_USER_WAKE_CALLBACK_WITH_CONTEXT */
\r
1918 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
1920 if( pxSocket->pxSocketSet != NULL )
\r
1922 EventBits_t xSelectBits = ( pxSocket->xEventBits >> SOCKET_EVENT_BIT_COUNT ) & eSELECT_ALL;
\r
1923 if( xSelectBits != 0ul )
\r
1925 pxSocket->xSocketBits |= xSelectBits;
\r
1926 xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, xSelectBits );
\r
1930 pxSocket->xEventBits &= eSOCKET_ALL;
\r
1932 #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
\r
1934 if( ( pxSocket->xEventGroup != NULL ) && ( pxSocket->xEventBits != 0u ) )
\r
1936 xEventGroupSetBits( pxSocket->xEventGroup, pxSocket->xEventBits );
\r
1939 pxSocket->xEventBits = 0ul;
\r
1942 /*-----------------------------------------------------------*/
\r
1944 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
\r
1946 /* This define makes it possible for network-card drivers to inspect
\r
1947 * UDP message and see if there is any UDP socket bound to a given port
\r
1949 * This is probably only usefull in systems with a minimum of RAM and
\r
1950 * when lots of anonymous broadcast messages come in
\r
1952 BaseType_t xPortHasUDPSocket( uint16_t usPortNr )
\r
1954 BaseType_t xFound = pdFALSE;
\r
1956 vTaskSuspendAll();
\r
1958 if( ( pxListFindListItemWithValue( &xBoundUDPSocketsList, ( TickType_t ) usPortNr ) != NULL ) )
\r
1968 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1970 /*-----------------------------------------------------------*/
\r
1972 #if( ipconfigUSE_TCP == 1 )
\r
1974 static BaseType_t bMayConnect( FreeRTOS_Socket_t *pxSocket );
\r
1975 static BaseType_t bMayConnect( FreeRTOS_Socket_t *pxSocket )
\r
1977 switch( pxSocket->u.xTCP.ucTCPState )
\r
1980 case eCLOSE_WAIT: return 0;
\r
1981 case eCONNECT_SYN: return -pdFREERTOS_ERRNO_EINPROGRESS;
\r
1982 default: return -pdFREERTOS_ERRNO_EAGAIN;
\r
1986 #endif /* ipconfigUSE_TCP */
\r
1987 /*-----------------------------------------------------------*/
\r
1989 #if( ipconfigUSE_TCP == 1 )
\r
1991 static BaseType_t prvTCPConnectStart( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr *pxAddress )
\r
1993 BaseType_t xResult = 0;
\r
1995 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdFALSE )
\r
1997 /* Not a valid socket or wrong type */
\r
1998 xResult = -pdFREERTOS_ERRNO_EBADF;
\r
2000 else if( FreeRTOS_issocketconnected( pxSocket ) > 0 )
\r
2002 /* The socket is already connected. */
\r
2003 xResult = -pdFREERTOS_ERRNO_EISCONN;
\r
2005 else if( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE )
\r
2007 /* Bind the socket to the port that the client task will send from.
\r
2008 Non-standard, so the error returned is that returned by bind(). */
\r
2009 xResult = FreeRTOS_bind( ( Socket_t ) pxSocket, NULL, 0u );
\r
2012 if( xResult == 0 )
\r
2014 /* Check if it makes any sense to wait for a connect event, this condition
\r
2015 might change while sleeping, so it must be checked within each loop */
\r
2016 xResult = bMayConnect( pxSocket ); /* -EINPROGRESS, -EAGAIN, or 0 for OK */
\r
2018 /* Start the connect procedure, kernel will start working on it */
\r
2019 if( xResult == 0 )
\r
2021 pxSocket->u.xTCP.bits.bConnPrepared = pdFALSE_UNSIGNED;
\r
2022 pxSocket->u.xTCP.ucRepCount = 0u;
\r
2024 FreeRTOS_debug_printf( ( "FreeRTOS_connect: %u to %lxip:%u\n",
\r
2025 pxSocket->usLocalPort, FreeRTOS_ntohl( pxAddress->sin_addr ), FreeRTOS_ntohs( pxAddress->sin_port ) ) );
\r
2027 /* Port on remote machine. */
\r
2028 pxSocket->u.xTCP.usRemotePort = FreeRTOS_ntohs( pxAddress->sin_port );
\r
2030 /* IP address of remote machine. */
\r
2031 pxSocket->u.xTCP.ulRemoteIP = FreeRTOS_ntohl( pxAddress->sin_addr );
\r
2033 /* (client) internal state: socket wants to send a connect. */
\r
2034 vTCPStateChange( pxSocket, eCONNECT_SYN );
\r
2036 /* To start an active connect. */
\r
2037 pxSocket->u.xTCP.usTimeout = 1u;
\r
2039 if( xSendEventToIPTask( eTCPTimerEvent ) != pdPASS )
\r
2041 xResult = -pdFREERTOS_ERRNO_ECANCELED;
\r
2049 #endif /* ipconfigUSE_TCP */
\r
2050 /*-----------------------------------------------------------*/
\r
2052 #if( ipconfigUSE_TCP == 1 )
\r
2055 * FreeRTOS_connect: socket wants to connect to a remote port
\r
2057 BaseType_t FreeRTOS_connect( Socket_t xClientSocket, struct freertos_sockaddr *pxAddress, socklen_t xAddressLength )
\r
2059 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t* ) xClientSocket;
\r
2060 TickType_t xRemainingTime;
\r
2061 BaseType_t xTimed = pdFALSE;
\r
2062 BaseType_t xResult;
\r
2063 TimeOut_t xTimeOut;
\r
2065 ( void ) xAddressLength;
\r
2067 xResult = prvTCPConnectStart( pxSocket, pxAddress );
\r
2069 if( xResult == 0 )
\r
2071 /* And wait for the result */
\r
2074 if( xTimed == pdFALSE )
\r
2076 /* Only in the first round, check for non-blocking */
\r
2077 xRemainingTime = pxSocket->xReceiveBlockTime;
\r
2078 if( xRemainingTime == ( TickType_t )0 )
\r
2080 /* Not yet connected, correct state, non-blocking. */
\r
2081 xResult = -pdFREERTOS_ERRNO_EWOULDBLOCK;
\r
2085 /* Don't get here a second time. */
\r
2088 /* Fetch the current time */
\r
2089 vTaskSetTimeOutState( &xTimeOut );
\r
2092 /* Did it get connected while sleeping ? */
\r
2093 xResult = FreeRTOS_issocketconnected( pxSocket );
\r
2095 /* Returns positive when connected, negative means an error */
\r
2098 /* Return the error */
\r
2104 /* Socket now connected, return a zero */
\r
2109 /* Is it allowed to sleep more? */
\r
2110 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) )
\r
2112 xResult = -pdFREERTOS_ERRNO_ETIMEDOUT;
\r
2116 /* Go sleeping until we get any down-stream event */
\r
2117 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_CONNECT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2123 #endif /* ipconfigUSE_TCP */
\r
2124 /*-----------------------------------------------------------*/
\r
2126 #if( ipconfigUSE_TCP == 1 )
\r
2129 * FreeRTOS_accept: can return a new connected socket
\r
2130 * if the server socket is in listen mode and receives a connection request
\r
2131 * The new socket will be bound already to the same port number as the listing
\r
2134 Socket_t FreeRTOS_accept( Socket_t xServerSocket, struct freertos_sockaddr *pxAddress, socklen_t *pxAddressLength )
\r
2136 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xServerSocket;
\r
2137 FreeRTOS_Socket_t *pxClientSocket = NULL;
\r
2138 TickType_t xRemainingTime;
\r
2139 BaseType_t xTimed = pdFALSE, xAsk = pdFALSE;
\r
2140 TimeOut_t xTimeOut;
\r
2141 IPStackEvent_t xAskEvent;
\r
2143 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2145 /* Not a valid socket or wrong type */
\r
2146 pxClientSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
\r
2148 else if( ( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED ) &&
\r
2149 ( pxSocket->u.xTCP.ucTCPState != eTCP_LISTEN ) )
\r
2151 /* Parent socket is not in listening mode */
\r
2152 pxClientSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
\r
2156 /* Loop will stop with breaks. */
\r
2159 /* Is there a new client? */
\r
2160 vTaskSuspendAll();
\r
2162 if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED )
\r
2164 pxClientSocket = pxSocket->u.xTCP.pxPeerSocket;
\r
2168 pxClientSocket = pxSocket;
\r
2170 if( pxClientSocket != NULL )
\r
2172 pxSocket->u.xTCP.pxPeerSocket = NULL;
\r
2174 /* Is it still not taken ? */
\r
2175 if( pxClientSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED )
\r
2177 pxClientSocket->u.xTCP.bits.bPassAccept = pdFALSE_UNSIGNED;
\r
2181 pxClientSocket = NULL;
\r
2187 if( pxClientSocket != NULL )
\r
2189 if( pxAddress != NULL )
\r
2191 /* IP address of remote machine. */
\r
2192 pxAddress->sin_addr = FreeRTOS_ntohl( pxClientSocket->u.xTCP.ulRemoteIP );
\r
2194 /* Port on remote machine. */
\r
2195 pxAddress->sin_port = FreeRTOS_ntohs( pxClientSocket->u.xTCP.usRemotePort );
\r
2197 if( pxAddressLength != NULL )
\r
2199 *pxAddressLength = sizeof( *pxAddress );
\r
2202 if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED )
\r
2208 if( xAsk != pdFALSE )
\r
2210 /* Ask to set an event in 'xEventGroup' as soon as a new
\r
2211 client gets connected for this listening socket. */
\r
2212 xAskEvent.eEventType = eTCPAcceptEvent;
\r
2213 xAskEvent.pvData = ( void * ) pxSocket;
\r
2214 xSendEventStructToIPTask( &xAskEvent, portMAX_DELAY );
\r
2217 if( pxClientSocket != NULL )
\r
2222 if( xTimed == pdFALSE )
\r
2224 /* Only in the first round, check for non-blocking */
\r
2225 xRemainingTime = pxSocket->xReceiveBlockTime;
\r
2226 if( xRemainingTime == ( TickType_t ) 0 )
\r
2231 /* Don't get here a second time */
\r
2234 /* Fetch the current time */
\r
2235 vTaskSetTimeOutState( &xTimeOut );
\r
2238 /* Has the timeout been reached? */
\r
2239 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
\r
2244 /* Go sleeping until we get any down-stream event */
\r
2245 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_ACCEPT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2249 return ( Socket_t ) pxClientSocket;
\r
2251 #endif /* ipconfigUSE_TCP */
\r
2252 /*-----------------------------------------------------------*/
\r
2254 #if( ipconfigUSE_TCP == 1 )
\r
2257 * Read incoming data from a TCP socket
\r
2258 * Only after the last byte has been read, a close error might be returned
\r
2260 BaseType_t FreeRTOS_recv( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags )
\r
2262 BaseType_t xByteCount;
\r
2263 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2264 TickType_t xRemainingTime;
\r
2265 BaseType_t xTimed = pdFALSE;
\r
2266 TimeOut_t xTimeOut;
\r
2267 EventBits_t xEventBits = ( EventBits_t ) 0;
\r
2269 /* Check if the socket is valid, has type TCP and if it is bound to a
\r
2271 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2273 xByteCount = -pdFREERTOS_ERRNO_EINVAL;
\r
2277 if( pxSocket->u.xTCP.rxStream != NULL )
\r
2279 xByteCount = ( BaseType_t )uxStreamBufferGetSize ( pxSocket->u.xTCP.rxStream );
\r
2286 while( xByteCount == 0 )
\r
2288 switch( pxSocket->u.xTCP.ucTCPState )
\r
2291 case eCLOSE_WAIT: /* (server + client) waiting for a connection termination request from the local user. */
\r
2292 case eCLOSING: /* (server + client) waiting for a connection termination request acknowledgement from the remote TCP. */
\r
2293 if( pxSocket->u.xTCP.bits.bMallocError != pdFALSE_UNSIGNED )
\r
2295 /* The no-memory error has priority above the non-connected error.
\r
2296 Both are fatal and will elad to closing the socket. */
\r
2297 xByteCount = -pdFREERTOS_ERRNO_ENOMEM;
\r
2301 xByteCount = -pdFREERTOS_ERRNO_ENOTCONN;
\r
2303 /* Call continue to break out of the switch and also the while
\r
2310 if( xTimed == pdFALSE )
\r
2312 /* Only in the first round, check for non-blocking. */
\r
2313 xRemainingTime = pxSocket->xReceiveBlockTime;
\r
2315 if( xRemainingTime == ( TickType_t ) 0 )
\r
2317 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
2319 /* Just check for the interrupt flag. */
\r
2320 xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_INTR,
\r
2321 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, socketDONT_BLOCK );
\r
2323 #endif /* ipconfigSUPPORT_SIGNALS */
\r
2327 if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
\r
2332 /* Don't get here a second time. */
\r
2335 /* Fetch the current time. */
\r
2336 vTaskSetTimeOutState( &xTimeOut );
\r
2339 /* Has the timeout been reached? */
\r
2340 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
\r
2345 /* Block until there is a down-stream event. */
\r
2346 xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup,
\r
2347 eSOCKET_RECEIVE | eSOCKET_CLOSED | eSOCKET_INTR,
\r
2348 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2349 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
2351 if( ( xEventBits & eSOCKET_INTR ) != 0u )
\r
2358 ( void ) xEventBits;
\r
2360 #endif /* ipconfigSUPPORT_SIGNALS */
\r
2362 if( pxSocket->u.xTCP.rxStream != NULL )
\r
2364 xByteCount = ( BaseType_t ) uxStreamBufferGetSize ( pxSocket->u.xTCP.rxStream );
\r
2372 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
2373 if( ( xEventBits & eSOCKET_INTR ) != 0 )
\r
2375 if( ( xEventBits & ( eSOCKET_RECEIVE | eSOCKET_CLOSED ) ) != 0 )
\r
2377 /* Shouldn't have cleared other flags. */
\r
2378 xEventBits &= ~eSOCKET_INTR;
\r
2379 xEventGroupSetBits( pxSocket->xEventGroup, xEventBits );
\r
2381 xByteCount = -pdFREERTOS_ERRNO_EINTR;
\r
2384 #endif /* ipconfigSUPPORT_SIGNALS */
\r
2385 if( xByteCount > 0 )
\r
2387 if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
\r
2389 xByteCount = ( BaseType_t ) uxStreamBufferGet( pxSocket->u.xTCP.rxStream, 0ul, ( uint8_t * ) pvBuffer, ( size_t ) xBufferLength, ( xFlags & FREERTOS_MSG_PEEK ) != 0 );
\r
2390 if( pxSocket->u.xTCP.bits.bLowWater != pdFALSE_UNSIGNED )
\r
2392 /* We had reached the low-water mark, now see if the flag
\r
2394 size_t uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );
\r
2396 if( uxFrontSpace >= pxSocket->u.xTCP.uxEnoughSpace )
\r
2398 pxSocket->u.xTCP.bits.bLowWater = pdFALSE_UNSIGNED;
\r
2399 pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
\r
2400 pxSocket->u.xTCP.usTimeout = 1u; /* because bLowWater is cleared. */
\r
2401 xSendEventToIPTask( eTCPTimerEvent );
\r
2407 /* Zero-copy reception of data: pvBuffer is a pointer to a pointer. */
\r
2408 xByteCount = ( BaseType_t ) uxStreamBufferGetPtr( pxSocket->u.xTCP.rxStream, (uint8_t **)pvBuffer );
\r
2411 } /* prvValidSocket() */
\r
2413 return xByteCount;
\r
2416 #endif /* ipconfigUSE_TCP */
\r
2417 /*-----------------------------------------------------------*/
\r
2419 #if( ipconfigUSE_TCP == 1 )
\r
2421 static int32_t prvTCPSendCheck( FreeRTOS_Socket_t *pxSocket, size_t xDataLength )
\r
2423 int32_t xResult = 1;
\r
2425 /* Is this a socket of type TCP and is it already bound to a port number ? */
\r
2426 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2428 xResult = -pdFREERTOS_ERRNO_EINVAL;
\r
2430 else if( pxSocket->u.xTCP.bits.bMallocError != pdFALSE_UNSIGNED )
\r
2432 xResult = -pdFREERTOS_ERRNO_ENOMEM;
\r
2434 else if( pxSocket->u.xTCP.ucTCPState == eCLOSED ||
\r
2435 pxSocket->u.xTCP.ucTCPState == eCLOSE_WAIT ||
\r
2436 pxSocket->u.xTCP.ucTCPState == eCLOSING )
\r
2438 xResult = -pdFREERTOS_ERRNO_ENOTCONN;
\r
2440 else if( pxSocket->u.xTCP.bits.bFinSent != pdFALSE_UNSIGNED )
\r
2442 /* This TCP connection is closing already, the FIN flag has been sent.
\r
2443 Maybe it is still delivering or receiving data.
\r
2444 Return OK in order not to get closed/deleted too quickly */
\r
2447 else if( xDataLength == 0ul )
\r
2449 /* send() is being called to send zero bytes */
\r
2452 else if( pxSocket->u.xTCP.txStream == NULL )
\r
2454 /* Create the outgoing stream only when it is needed */
\r
2455 prvTCPCreateStream( pxSocket, pdFALSE );
\r
2457 if( pxSocket->u.xTCP.txStream == NULL )
\r
2459 xResult = -pdFREERTOS_ERRNO_ENOMEM;
\r
2466 #endif /* ipconfigUSE_TCP */
\r
2467 /*-----------------------------------------------------------*/
\r
2469 #if( ipconfigUSE_TCP == 1 )
\r
2471 /* Get a direct pointer to the circular transmit buffer.
\r
2472 '*pxLength' will contain the number of bytes that may be written. */
\r
2473 uint8_t *FreeRTOS_get_tx_head( Socket_t xSocket, BaseType_t *pxLength )
\r
2475 uint8_t *pucReturn = NULL;
\r
2476 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2477 StreamBuffer_t *pxBuffer = NULL;
\r
2481 /* Confirm that this is a TCP socket before dereferencing structure
\r
2482 member pointers. */
\r
2483 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdTRUE )
\r
2485 pxBuffer = pxSocket->u.xTCP.txStream;
\r
2486 if( pxBuffer != NULL )
\r
2488 BaseType_t xSpace = ( BaseType_t )uxStreamBufferGetSpace( pxBuffer );
\r
2489 BaseType_t xRemain = ( BaseType_t )( pxBuffer->LENGTH - pxBuffer->uxHead );
\r
2491 *pxLength = FreeRTOS_min_BaseType( xSpace, xRemain );
\r
2492 pucReturn = pxBuffer->ucArray + pxBuffer->uxHead;
\r
2498 #endif /* ipconfigUSE_TCP */
\r
2499 /*-----------------------------------------------------------*/
\r
2501 #if( ipconfigUSE_TCP == 1 )
\r
2503 * Send data using a TCP socket. It is not necessary to have the socket
\r
2504 * connected already. Outgoing data will be stored and delivered as soon as
\r
2505 * the socket gets connected.
\r
2507 BaseType_t FreeRTOS_send( Socket_t xSocket, const void *pvBuffer, size_t uxDataLength, BaseType_t xFlags )
\r
2509 BaseType_t xByteCount;
\r
2510 BaseType_t xBytesLeft;
\r
2511 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2512 TickType_t xRemainingTime;
\r
2513 BaseType_t xTimed = pdFALSE;
\r
2514 TimeOut_t xTimeOut;
\r
2515 BaseType_t xCloseAfterSend;
\r
2517 /* Prevent compiler warnings about unused parameters. The parameter
\r
2518 may be used in future versions. */
\r
2521 xByteCount = ( BaseType_t ) prvTCPSendCheck( pxSocket, uxDataLength );
\r
2523 if( xByteCount > 0 )
\r
2525 /* xBytesLeft is number of bytes to send, will count to zero. */
\r
2526 xBytesLeft = ( BaseType_t ) uxDataLength;
\r
2528 /* xByteCount is number of bytes that can be sent now. */
\r
2529 xByteCount = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
\r
2531 /* While there are still bytes to be sent. */
\r
2532 while( xBytesLeft > 0 )
\r
2534 /* If txStream has space. */
\r
2535 if( xByteCount > 0 )
\r
2537 /* Don't send more than necessary. */
\r
2538 if( xByteCount > xBytesLeft )
\r
2540 xByteCount = xBytesLeft;
\r
2543 /* Is the close-after-send flag set and is this really the
\r
2544 last transmission? */
\r
2545 if( ( pxSocket->u.xTCP.bits.bCloseAfterSend != pdFALSE_UNSIGNED ) && ( xByteCount == xBytesLeft ) )
\r
2547 xCloseAfterSend = pdTRUE;
\r
2551 xCloseAfterSend = pdFALSE;
\r
2554 /* The flag 'bCloseAfterSend' can be set before sending data
\r
2555 using setsockopt()
\r
2557 When the last data packet is being sent out, a FIN flag will
\r
2558 be included to let the peer know that no more data is to be
\r
2559 expected. The use of 'bCloseAfterSend' is not mandatory, it
\r
2560 is just a faster way of transferring files (e.g. when using
\r
2562 if( xCloseAfterSend != pdFALSE )
\r
2564 /* Now suspend the scheduler: sending the last data and
\r
2565 setting bCloseRequested must be done together */
\r
2566 vTaskSuspendAll();
\r
2567 pxSocket->u.xTCP.bits.bCloseRequested = pdTRUE_UNSIGNED;
\r
2570 xByteCount = ( BaseType_t ) uxStreamBufferAdd( pxSocket->u.xTCP.txStream, 0ul, ( const uint8_t * ) pvBuffer, ( size_t ) xByteCount );
\r
2572 if( xCloseAfterSend != pdFALSE )
\r
2574 /* Now when the IP-task transmits the data, it will also
\r
2575 see that bCloseRequested is true and include the FIN
\r
2576 flag to start closure of the connection. */
\r
2580 /* Send a message to the IP-task so it can work on this
\r
2581 socket. Data is sent, let the IP-task work on it. */
\r
2582 pxSocket->u.xTCP.usTimeout = 1u;
\r
2584 if( xIsCallingFromIPTask() == pdFALSE )
\r
2586 /* Only send a TCP timer event when not called from the
\r
2588 xSendEventToIPTask( eTCPTimerEvent );
\r
2591 xBytesLeft -= xByteCount;
\r
2593 if( xBytesLeft == 0 )
\r
2598 /* As there are still bytes left to be sent, increase the
\r
2600 pvBuffer = ( void * ) ( ( ( const uint8_t * ) pvBuffer) + xByteCount );
\r
2603 /* Not all bytes have been sent. In case the socket is marked as
\r
2604 blocking sleep for a while. */
\r
2605 if( xTimed == pdFALSE )
\r
2607 /* Only in the first round, check for non-blocking. */
\r
2608 xRemainingTime = pxSocket->xSendBlockTime;
\r
2610 #if( ipconfigUSE_CALLBACKS != 0 )
\r
2612 if( xIsCallingFromIPTask() != pdFALSE )
\r
2614 /* If this send function is called from within a
\r
2615 call-back handler it may not block, otherwise
\r
2616 chances would be big to get a deadlock: the IP-task
\r
2617 waiting for itself. */
\r
2618 xRemainingTime = ( TickType_t ) 0;
\r
2621 #endif /* ipconfigUSE_CALLBACKS */
\r
2623 if( xRemainingTime == ( TickType_t ) 0 )
\r
2628 if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
\r
2633 /* Don't get here a second time. */
\r
2636 /* Fetch the current time. */
\r
2637 vTaskSetTimeOutState( &xTimeOut );
\r
2641 /* Has the timeout been reached? */
\r
2642 if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
\r
2648 /* Go sleeping until down-stream events are received. */
\r
2649 xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_SEND | eSOCKET_CLOSED,
\r
2650 pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
\r
2652 xByteCount = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
\r
2655 /* How much was actually sent? */
\r
2656 xByteCount = ( ( BaseType_t ) uxDataLength ) - xBytesLeft;
\r
2658 if( xByteCount == 0 )
\r
2660 if( pxSocket->u.xTCP.ucTCPState > eESTABLISHED )
\r
2662 xByteCount = ( BaseType_t ) -pdFREERTOS_ERRNO_ENOTCONN;
\r
2666 if( ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) != pdFALSE )
\r
2668 FreeRTOS_debug_printf( ( "FreeRTOS_send: %u -> %lxip:%d: no space\n",
\r
2669 pxSocket->usLocalPort,
\r
2670 pxSocket->u.xTCP.ulRemoteIP,
\r
2671 pxSocket->u.xTCP.usRemotePort ) );
\r
2674 xByteCount = ( BaseType_t ) -pdFREERTOS_ERRNO_ENOSPC;
\r
2679 return xByteCount;
\r
2682 #endif /* ipconfigUSE_TCP */
\r
2683 /*-----------------------------------------------------------*/
\r
2685 #if( ipconfigUSE_TCP == 1 )
\r
2688 * Request to put a socket in listen mode
\r
2690 BaseType_t FreeRTOS_listen( Socket_t xSocket, BaseType_t xBacklog )
\r
2692 FreeRTOS_Socket_t *pxSocket;
\r
2693 BaseType_t xResult = 0;
\r
2695 pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2697 /* listen() is allowed for a valid TCP socket in Closed state and already
\r
2699 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2701 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2703 else if( ( pxSocket->u.xTCP.ucTCPState != eCLOSED ) && ( pxSocket->u.xTCP.ucTCPState != eCLOSE_WAIT ) )
\r
2705 /* Socket is in a wrong state. */
\r
2706 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2710 /* Backlog is interpreted here as "the maximum number of child
\r
2712 pxSocket->u.xTCP.usBacklog = ( uint16_t )FreeRTOS_min_int32( ( int32_t ) 0xffff, ( int32_t ) xBacklog );
\r
2714 /* This cleaning is necessary only if a listening socket is being
\r
2715 reused as it might have had a previous connection. */
\r
2716 if( pxSocket->u.xTCP.bits.bReuseSocket )
\r
2718 if( pxSocket->u.xTCP.rxStream != NULL )
\r
2720 vStreamBufferClear( pxSocket->u.xTCP.rxStream );
\r
2723 if( pxSocket->u.xTCP.txStream != NULL )
\r
2725 vStreamBufferClear( pxSocket->u.xTCP.txStream );
\r
2728 memset( pxSocket->u.xTCP.xPacket.u.ucLastPacket, '\0', sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket ) );
\r
2729 memset( &pxSocket->u.xTCP.xTCPWindow, '\0', sizeof( pxSocket->u.xTCP.xTCPWindow ) );
\r
2730 memset( &pxSocket->u.xTCP.bits, '\0', sizeof( pxSocket->u.xTCP.bits ) );
\r
2732 /* Now set the bReuseSocket flag again, because the bits have
\r
2733 just been cleared. */
\r
2734 pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE_UNSIGNED;
\r
2737 vTCPStateChange( pxSocket, eTCP_LISTEN );
\r
2743 #endif /* ipconfigUSE_TCP */
\r
2744 /*-----------------------------------------------------------*/
\r
2746 #if( ipconfigUSE_TCP == 1 )
\r
2748 /* shutdown - shut down part of a full-duplex connection */
\r
2749 BaseType_t FreeRTOS_shutdown( Socket_t xSocket, BaseType_t xHow )
\r
2751 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
2752 BaseType_t xResult;
\r
2754 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
\r
2756 /*_RB_ Is this comment correct? The socket is not of a type that
\r
2757 supports the listen() operation. */
\r
2758 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2760 else if ( pxSocket->u.xTCP.ucTCPState != eESTABLISHED )
\r
2762 /*_RB_ Is this comment correct? The socket is not of a type that
\r
2763 supports the listen() operation. */
\r
2764 xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
\r
2768 pxSocket->u.xTCP.bits.bUserShutdown = pdTRUE_UNSIGNED;
\r
2770 /* Let the IP-task perform the shutdown of the connection. */
\r
2771 pxSocket->u.xTCP.usTimeout = 1u;
\r
2772 xSendEventToIPTask( eTCPTimerEvent );
\r
2780 #endif /* ipconfigUSE_TCP */
\r
2781 /*-----------------------------------------------------------*/
\r
2783 #if( ipconfigUSE_TCP == 1 )
\r
2786 * A TCP timer has expired, now check all TCP sockets for:
\r
2787 * - Active connect
\r
2788 * - Send a delayed ACK
\r
2790 * - Send a keep-alive packet
\r
2791 * - Check for timeout (in non-connected states only)
\r
2793 TickType_t xTCPTimerCheck( BaseType_t xWillSleep )
\r
2795 FreeRTOS_Socket_t *pxSocket;
\r
2796 TickType_t xShortest = pdMS_TO_TICKS( ( TickType_t ) ipTCP_TIMER_PERIOD_MS );
\r
2797 TickType_t xNow = xTaskGetTickCount();
\r
2798 static TickType_t xLastTime = 0u;
\r
2799 TickType_t xDelta = xNow - xLastTime;
\r
2800 ListItem_t* pxEnd = ( ListItem_t * ) listGET_END_MARKER( &xBoundTCPSocketsList );
\r
2801 ListItem_t *pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );
\r
2805 if( xDelta == 0u )
\r
2810 while( pxIterator != pxEnd )
\r
2812 pxSocket = ( FreeRTOS_Socket_t * )listGET_LIST_ITEM_OWNER( pxIterator );
\r
2813 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator );
\r
2815 /* Sockets with 'tmout == 0' do not need any regular attention. */
\r
2816 if( pxSocket->u.xTCP.usTimeout == 0u )
\r
2821 if( xDelta < ( TickType_t ) pxSocket->u.xTCP.usTimeout )
\r
2823 pxSocket->u.xTCP.usTimeout = ( uint16_t ) ( ( ( TickType_t ) pxSocket->u.xTCP.usTimeout ) - xDelta );
\r
2828 pxSocket->u.xTCP.usTimeout = 0u;
\r
2829 rc = xTCPSocketCheck( pxSocket );
\r
2831 /* Within this function, the socket might want to send a delayed
\r
2832 ack or send out data or whatever it needs to do. */
\r
2835 /* Continue because the socket was deleted. */
\r
2840 /* In xEventBits the driver may indicate that the socket has
\r
2841 important events for the user. These are only done just before the
\r
2842 IP-task goes to sleep. */
\r
2843 if( pxSocket->xEventBits != 0u )
\r
2845 if( xWillSleep != pdFALSE )
\r
2847 /* The IP-task is about to go to sleep, so messages can be
\r
2848 sent to the socket owners. */
\r
2849 vSocketWakeUpUser( pxSocket );
\r
2853 /* Or else make sure this will be called again to wake-up
\r
2854 the sockets' owner. */
\r
2855 xShortest = ( TickType_t ) 0;
\r
2859 if( ( pxSocket->u.xTCP.usTimeout != 0u ) && ( xShortest > ( TickType_t ) pxSocket->u.xTCP.usTimeout ) )
\r
2861 xShortest = ( TickType_t ) pxSocket->u.xTCP.usTimeout;
\r
2868 #endif /* ipconfigUSE_TCP */
\r
2869 /*-----------------------------------------------------------*/
\r
2871 #if( ipconfigUSE_TCP == 1 )
\r
2874 * TCP: as multiple sockets may be bound to the same local port number
\r
2875 * looking up a socket is a little more complex:
\r
2876 * Both a local port, and a remote port and IP address are being used
\r
2877 * For a socket in listening mode, the remote port and IP address are both 0
\r
2879 FreeRTOS_Socket_t *pxTCPSocketLookup( uint32_t ulLocalIP, UBaseType_t uxLocalPort, uint32_t ulRemoteIP, UBaseType_t uxRemotePort )
\r
2881 ListItem_t *pxIterator;
\r
2882 FreeRTOS_Socket_t *pxResult = NULL, *pxListenSocket = NULL;
\r
2883 MiniListItem_t *pxEnd = ( MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );
\r
2885 /* Parameter not yet supported. */
\r
2886 ( void ) ulLocalIP;
\r
2888 for( pxIterator = ( ListItem_t * ) listGET_NEXT( pxEnd );
\r
2889 pxIterator != ( ListItem_t * ) pxEnd;
\r
2890 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
2892 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
\r
2894 if( pxSocket->usLocalPort == ( uint16_t ) uxLocalPort )
\r
2896 if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN )
\r
2898 /* If this is a socket listening to uxLocalPort, remember it
\r
2899 in case there is no perfect match. */
\r
2900 pxListenSocket = pxSocket;
\r
2902 else if( ( pxSocket->u.xTCP.usRemotePort == ( uint16_t ) uxRemotePort ) && ( pxSocket->u.xTCP.ulRemoteIP == ulRemoteIP ) )
\r
2904 /* For sockets not in listening mode, find a match with
\r
2905 xLocalPort, ulRemoteIP AND xRemotePort. */
\r
2906 pxResult = pxSocket;
\r
2911 if( pxResult == NULL )
\r
2913 /* An exact match was not found, maybe a listening socket was
\r
2915 pxResult = pxListenSocket;
\r
2921 #endif /* ipconfigUSE_TCP */
\r
2922 /*-----------------------------------------------------------*/
\r
2924 #if( ipconfigUSE_TCP == 1 )
\r
2926 const struct xSTREAM_BUFFER *FreeRTOS_get_rx_buf( Socket_t xSocket )
\r
2928 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * )xSocket;
\r
2929 struct xSTREAM_BUFFER *pxReturn = NULL;
\r
2931 /* Confirm that this is a TCP socket before dereferencing structure
\r
2932 member pointers. */
\r
2933 if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdTRUE )
\r
2935 pxReturn = pxSocket->u.xTCP.rxStream;
\r
2941 #endif /* ipconfigUSE_TCP */
\r
2942 /*-----------------------------------------------------------*/
\r
2944 #if( ipconfigUSE_TCP == 1 )
\r
2946 static StreamBuffer_t *prvTCPCreateStream ( FreeRTOS_Socket_t *pxSocket, BaseType_t xIsInputStream )
\r
2948 StreamBuffer_t *pxBuffer;
\r
2952 /* Now that a stream is created, the maximum size is fixed before
\r
2953 creation, it could still be changed with setsockopt(). */
\r
2954 if( xIsInputStream != pdFALSE )
\r
2956 uxLength = pxSocket->u.xTCP.uxRxStreamSize;
\r
2958 if( pxSocket->u.xTCP.uxLittleSpace == 0ul )
\r
2960 pxSocket->u.xTCP.uxLittleSpace = ( sock20_PERCENT * pxSocket->u.xTCP.uxRxStreamSize ) / sock100_PERCENT;
\r
2963 if( pxSocket->u.xTCP.uxEnoughSpace == 0ul )
\r
2965 pxSocket->u.xTCP.uxEnoughSpace = ( sock80_PERCENT * pxSocket->u.xTCP.uxRxStreamSize ) / sock100_PERCENT;
\r
2970 uxLength = pxSocket->u.xTCP.uxTxStreamSize;
\r
2973 /* Add an extra 4 (or 8) bytes. */
\r
2974 uxLength += sizeof( size_t );
\r
2976 /* And make the length a multiple of sizeof( size_t ). */
\r
2977 uxLength &= ~( sizeof( size_t ) - 1u );
\r
2979 uxSize = sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) + uxLength;
\r
2981 pxBuffer = ( StreamBuffer_t * )pvPortMallocLarge( uxSize );
\r
2983 if( pxBuffer == NULL )
\r
2985 FreeRTOS_debug_printf( ( "prvTCPCreateStream: malloc failed\n" ) );
\r
2986 pxSocket->u.xTCP.bits.bMallocError = pdTRUE_UNSIGNED;
\r
2987 vTCPStateChange( pxSocket, eCLOSE_WAIT );
\r
2991 /* Clear the markers of the stream */
\r
2992 memset( pxBuffer, '\0', sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) );
\r
2993 pxBuffer->LENGTH = ( size_t ) uxLength ;
\r
2995 if( xTCPWindowLoggingLevel != 0 )
\r
2997 FreeRTOS_debug_printf( ( "prvTCPCreateStream: %cxStream created %lu bytes (total %lu)\n", xIsInputStream ? 'R' : 'T', uxLength, uxSize ) );
\r
3000 if( xIsInputStream != 0 )
\r
3002 pxSocket->u.xTCP.rxStream = pxBuffer;
\r
3006 pxSocket->u.xTCP.txStream = pxBuffer;
\r
3013 #endif /* ipconfigUSE_TCP */
\r
3014 /*-----------------------------------------------------------*/
\r
3016 #if( ipconfigUSE_TCP == 1 )
\r
3019 * Add data to the RxStream. When uxOffset > 0, data has come in out-of-order
\r
3020 * and will be put in front of the head so it can not be popped by the user.
\r
3022 int32_t lTCPAddRxdata( FreeRTOS_Socket_t *pxSocket, size_t uxOffset, const uint8_t *pcData, uint32_t ulByteCount )
\r
3024 StreamBuffer_t *pxStream = pxSocket->u.xTCP.rxStream;
\r
3026 #if( ipconfigUSE_CALLBACKS == 1 )
\r
3027 BaseType_t bHasHandler = ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xTCP.pxHandleReceive );
\r
3028 const uint8_t *pucBuffer = NULL;
\r
3029 #endif /* ipconfigUSE_CALLBACKS */
\r
3031 /* int32_t uxStreamBufferAdd( pxBuffer, uxOffset, pucData, aCount )
\r
3032 if( pucData != NULL ) copy data the the buffer
\r
3033 if( pucData == NULL ) no copying, just advance rxHead
\r
3034 if( uxOffset != 0 ) Just store data which has come out-of-order
\r
3035 if( uxOffset == 0 ) Also advance rxHead */
\r
3036 if( pxStream == NULL )
\r
3038 pxStream = prvTCPCreateStream( pxSocket, pdTRUE );
\r
3039 if( pxStream == NULL )
\r
3045 #if( ipconfigUSE_CALLBACKS == 1 )
\r
3047 if( ( bHasHandler != pdFALSE ) && ( uxStreamBufferGetSize( pxStream ) == 0u ) && ( uxOffset == 0ul ) && ( pcData != NULL ) )
\r
3049 /* Data can be passed directly to the user */
\r
3050 pucBuffer = pcData;
\r
3052 /* Zero-copy for call-back: no need to add the bytes to the
\r
3053 stream, only the pointer will be advanced by uxStreamBufferAdd(). */
\r
3057 #endif /* ipconfigUSE_CALLBACKS */
\r
3059 xResult = ( int32_t ) uxStreamBufferAdd( pxStream, uxOffset, pcData, ( size_t ) ulByteCount );
\r
3061 #if( ipconfigHAS_DEBUG_PRINTF != 0 )
\r
3063 if( xResult != ( int32_t ) ulByteCount )
\r
3065 FreeRTOS_debug_printf( ( "lTCPAddRxdata: at %ld: %ld/%lu bytes (tail %lu head %lu space %lu front %lu)\n",
\r
3066 uxOffset, xResult, ulByteCount,
\r
3069 uxStreamBufferFrontSpace( pxStream ),
\r
3070 pxStream->uxFront ) );
\r
3073 #endif /* ipconfigHAS_DEBUG_PRINTF */
\r
3075 if( uxOffset == 0u )
\r
3077 /* Data is being added to rxStream at the head (offs = 0) */
\r
3078 #if( ipconfigUSE_CALLBACKS == 1 )
\r
3079 if( bHasHandler != pdFALSE )
\r
3081 /* The socket owner has installed an OnReceive handler. Pass the
\r
3082 Rx data, without copying from the rxStream, to the user. */
\r
3085 uint8_t *ucReadPtr = NULL;
\r
3087 if( pucBuffer != NULL )
\r
3089 ucReadPtr = ( uint8_t * )pucBuffer;
\r
3090 ulCount = ulByteCount;
\r
3095 ulCount = ( uint32_t ) uxStreamBufferGetPtr( pxStream, &( ucReadPtr ) );
\r
3098 if( ulCount == 0ul )
\r
3103 pxSocket->u.xTCP.pxHandleReceive( (Socket_t *)pxSocket, ( void* )ucReadPtr, ( size_t ) ulCount );
\r
3104 uxStreamBufferGet( pxStream, 0ul, NULL, ( size_t ) ulCount, pdFALSE );
\r
3107 #endif /* ipconfigUSE_CALLBACKS */
\r
3109 /* See if running out of space. */
\r
3110 if( pxSocket->u.xTCP.bits.bLowWater == pdFALSE_UNSIGNED )
\r
3112 size_t uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );
\r
3113 if( uxFrontSpace <= pxSocket->u.xTCP.uxLittleSpace )
\r
3115 pxSocket->u.xTCP.bits.bLowWater = pdTRUE_UNSIGNED;
\r
3116 pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
\r
3118 /* bLowWater was reached, send the changed window size. */
\r
3119 pxSocket->u.xTCP.usTimeout = 1u;
\r
3120 xSendEventToIPTask( eTCPTimerEvent );
\r
3124 /* New incoming data is available, wake up the user. User's
\r
3125 semaphores will be set just before the IP-task goes asleep. */
\r
3126 pxSocket->xEventBits |= eSOCKET_RECEIVE;
\r
3128 #if ipconfigSUPPORT_SELECT_FUNCTION == 1
\r
3130 if( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 )
\r
3132 pxSocket->xEventBits |= ( eSELECT_READ << SOCKET_EVENT_BIT_COUNT );
\r
3142 #endif /* ipconfigUSE_TCP */
\r
3143 /*-----------------------------------------------------------*/
\r
3145 #if( ipconfigUSE_TCP == 1 )
\r
3147 /* Function to get the remote address and IP port */
\r
3148 BaseType_t FreeRTOS_GetRemoteAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress )
\r
3150 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3151 BaseType_t xResult;
\r
3153 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3155 xResult = -pdFREERTOS_ERRNO_EINVAL;
\r
3159 /* BSD style sockets communicate IP and port addresses in network
\r
3162 IP address of remote machine. */
\r
3163 pxAddress->sin_addr = FreeRTOS_htonl ( pxSocket->u.xTCP.ulRemoteIP );
\r
3165 /* Port on remote machine. */
\r
3166 pxAddress->sin_port = FreeRTOS_htons ( pxSocket->u.xTCP.usRemotePort );
\r
3168 xResult = ( BaseType_t ) sizeof( ( *pxAddress ) );
\r
3174 #endif /* ipconfigUSE_TCP */
\r
3176 /*-----------------------------------------------------------*/
\r
3178 #if( ipconfigUSE_TCP == 1 )
\r
3180 /* Returns the number of bytes that may be added to txStream */
\r
3181 BaseType_t FreeRTOS_maywrite( Socket_t xSocket )
\r
3183 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3184 BaseType_t xResult;
\r
3186 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3188 xResult = -pdFREERTOS_ERRNO_EINVAL;
\r
3190 else if( pxSocket->u.xTCP.ucTCPState != eESTABLISHED )
\r
3192 if( ( pxSocket->u.xTCP.ucTCPState < eCONNECT_SYN ) || ( pxSocket->u.xTCP.ucTCPState > eESTABLISHED ) )
\r
3201 else if( pxSocket->u.xTCP.txStream == NULL )
\r
3203 xResult = ( BaseType_t ) pxSocket->u.xTCP.uxTxStreamSize;
\r
3207 xResult = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
\r
3213 #endif /* ipconfigUSE_TCP */
\r
3214 /*-----------------------------------------------------------*/
\r
3216 #if( ipconfigUSE_TCP ==1 )
\r
3218 BaseType_t FreeRTOS_tx_space( Socket_t xSocket )
\r
3220 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3221 BaseType_t xReturn;
\r
3223 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3225 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3229 if( pxSocket->u.xTCP.txStream != NULL )
\r
3231 xReturn = ( BaseType_t ) uxStreamBufferGetSpace ( pxSocket->u.xTCP.txStream );
\r
3235 xReturn = ( BaseType_t ) pxSocket->u.xTCP.uxTxStreamSize;
\r
3242 #endif /* ipconfigUSE_TCP */
\r
3243 /*-----------------------------------------------------------*/
\r
3245 #if( ipconfigUSE_TCP == 1 )
\r
3247 BaseType_t FreeRTOS_tx_size( Socket_t xSocket )
\r
3249 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3250 BaseType_t xReturn;
\r
3252 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3254 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3258 if( pxSocket->u.xTCP.txStream != NULL )
\r
3260 xReturn = ( BaseType_t ) uxStreamBufferGetSize ( pxSocket->u.xTCP.txStream );
\r
3271 #endif /* ipconfigUSE_TCP */
\r
3272 /*-----------------------------------------------------------*/
\r
3274 #if( ipconfigUSE_TCP == 1 )
\r
3276 /* Returns pdTRUE if TCP socket is connected. */
\r
3277 BaseType_t FreeRTOS_issocketconnected( Socket_t xSocket )
\r
3279 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3280 BaseType_t xReturn = pdFALSE;
\r
3282 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3284 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3288 if( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED )
\r
3290 if( pxSocket->u.xTCP.ucTCPState < eCLOSE_WAIT )
\r
3300 #endif /* ipconfigUSE_TCP */
\r
3301 /*-----------------------------------------------------------*/
\r
3303 #if( ipconfigUSE_TCP == 1 )
\r
3305 /* returns the actual size of MSS being used */
\r
3306 BaseType_t FreeRTOS_mss( Socket_t xSocket )
\r
3308 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3309 BaseType_t xReturn;
\r
3311 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3313 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3317 /* usCurMSS is declared as uint16_t to save space. FreeRTOS_mss()
\r
3318 will often be used in signed native-size expressions cast it to
\r
3320 xReturn = ( BaseType_t ) ( pxSocket->u.xTCP.usCurMSS );
\r
3326 #endif /* ipconfigUSE_TCP */
\r
3327 /*-----------------------------------------------------------*/
\r
3329 #if( ipconfigUSE_TCP == 1 )
\r
3331 /* HT: for internal use only: return the connection status */
\r
3332 BaseType_t FreeRTOS_connstatus( Socket_t xSocket )
\r
3334 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3335 BaseType_t xReturn;
\r
3337 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3339 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3343 /* Cast it to BaseType_t */
\r
3344 xReturn = ( BaseType_t ) ( pxSocket->u.xTCP.ucTCPState );
\r
3350 #endif /* ipconfigUSE_TCP */
\r
3351 /*-----------------------------------------------------------*/
\r
3353 #if( ipconfigUSE_TCP == 1 )
\r
3356 * Returns the number of bytes which can be read.
\r
3358 BaseType_t FreeRTOS_rx_size( Socket_t xSocket )
\r
3360 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3361 BaseType_t xReturn;
\r
3363 if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
\r
3365 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3367 else if( pxSocket->u.xTCP.rxStream != NULL )
\r
3369 xReturn = ( BaseType_t ) uxStreamBufferGetSize( pxSocket->u.xTCP.rxStream );
\r
3379 #endif /* ipconfigUSE_TCP */
\r
3380 /*-----------------------------------------------------------*/
\r
3382 #if( ipconfigUSE_TCP == 1 )
\r
3384 void FreeRTOS_netstat( void )
\r
3386 IPStackEvent_t xAskEvent;
\r
3388 /* Ask the IP-task to call vTCPNetStat()
\r
3389 * to avoid accessing xBoundTCPSocketsList
\r
3391 xAskEvent.eEventType = eTCPNetStat;
\r
3392 xAskEvent.pvData = ( void * ) NULL;
\r
3393 xSendEventStructToIPTask( &xAskEvent, 1000u );
\r
3396 #endif /* ipconfigUSE_TCP */
\r
3397 /*-----------------------------------------------------------*/
\r
3399 #if( ( ipconfigHAS_PRINTF != 0 ) && ( ipconfigUSE_TCP == 1 ) )
\r
3401 void vTCPNetStat( void )
\r
3403 /* Show a simple listing of all created sockets and their connections */
\r
3404 ListItem_t *pxIterator;
\r
3405 BaseType_t count = 0;
\r
3407 if( listLIST_IS_INITIALISED( &xBoundTCPSocketsList ) == pdFALSE )
\r
3409 FreeRTOS_printf( ( "PLUS-TCP not initialized\n" ) );
\r
3413 FreeRTOS_printf( ( "Prot Port IP-Remote : Port R/T Status Alive tmout Child\n" ) );
\r
3414 for( pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );
\r
3415 pxIterator != ( ListItem_t * ) listGET_END_MARKER( &xBoundTCPSocketsList );
\r
3416 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
3418 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
\r
3419 #if( ipconfigTCP_KEEP_ALIVE == 1 )
\r
3420 TickType_t age = xTaskGetTickCount() - pxSocket->u.xTCP.xLastAliveTime;
\r
3422 TickType_t age = 0u;
\r
3424 #if( ipconfigUSE_CALLBACKS == 1 )
\r
3425 void *pxHandleReceive = (void*)pxSocket->u.xTCP.pxHandleReceive;
\r
3427 void *pxHandleReceive = (void*)NULL;
\r
3429 char ucChildText[16] = "";
\r
3430 if (pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN)
\r
3432 const int32_t copied_len = snprintf( ucChildText, sizeof( ucChildText ), " %d/%d",
\r
3433 ( int ) pxSocket->u.xTCP.usChildCount,
\r
3434 ( int ) pxSocket->u.xTCP.usBacklog);
\r
3435 /* These should never evaluate to false since the buffers are both shorter than 5-6 characters (<=65535) */
\r
3436 configASSERT( copied_len >= 0 );
\r
3437 configASSERT( copied_len < sizeof( ucChildText ) );
\r
3439 FreeRTOS_printf( ( "TCP %5d %-16lxip:%5d %d/%d %-13.13s %6lu %6u%s\n",
\r
3440 pxSocket->usLocalPort, /* Local port on this machine */
\r
3441 pxSocket->u.xTCP.ulRemoteIP, /* IP address of remote machine */
\r
3442 pxSocket->u.xTCP.usRemotePort, /* Port on remote machine */
\r
3443 pxSocket->u.xTCP.rxStream != NULL,
\r
3444 pxSocket->u.xTCP.txStream != NULL,
\r
3445 FreeRTOS_GetTCPStateName( pxSocket->u.xTCP.ucTCPState ),
\r
3446 (age > 999999 ? 999999 : age), /* Format 'age' for printing */
\r
3447 pxSocket->u.xTCP.usTimeout,
\r
3449 /* Remove compiler warnings if FreeRTOS_debug_printf() is not defined. */
\r
3450 ( void ) pxHandleReceive;
\r
3454 for( pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundUDPSocketsList );
\r
3455 pxIterator != ( ListItem_t * ) listGET_END_MARKER( &xBoundUDPSocketsList );
\r
3456 pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
3458 /* Local port on this machine */
\r
3459 FreeRTOS_printf( ( "UDP Port %5u\n",
\r
3460 FreeRTOS_ntohs( listGET_LIST_ITEM_VALUE( pxIterator ) ) ) );
\r
3464 FreeRTOS_printf( ( "FreeRTOS_netstat: %lu sockets %lu < %lu < %d buffers free\n",
\r
3466 uxGetMinimumFreeNetworkBuffers( ),
\r
3467 uxGetNumberOfFreeNetworkBuffers( ),
\r
3468 ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ) );
\r
3472 #endif /* ( ( ipconfigHAS_PRINTF != 0 ) && ( ipconfigUSE_TCP == 1 ) ) */
\r
3473 /*-----------------------------------------------------------*/
\r
3475 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
3477 void vSocketSelect( SocketSelect_t *pxSocketSet )
\r
3479 BaseType_t xRound;
\r
3480 EventBits_t xSocketBits, xBitsToClear;
\r
3481 #if ipconfigUSE_TCP == 1
\r
3482 BaseType_t xLastRound = 1;
\r
3484 BaseType_t xLastRound = 0;
\r
3487 /* These flags will be switched on after checking the socket status. */
\r
3488 EventBits_t xGroupBits = 0;
\r
3489 pxSocketSet->pxSocket = NULL;
\r
3491 for( xRound = 0; xRound <= xLastRound; xRound++ )
\r
3493 const ListItem_t *pxIterator;
\r
3494 const MiniListItem_t *pxEnd;
\r
3497 pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundUDPSocketsList );
\r
3499 #if ipconfigUSE_TCP == 1
\r
3502 pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );
\r
3504 #endif /* ipconfigUSE_TCP == 1 */
\r
3505 for( pxIterator = ( const ListItem_t * ) ( listGET_NEXT( pxEnd ) );
\r
3506 pxIterator != ( const ListItem_t * ) pxEnd;
\r
3507 pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
\r
3509 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
\r
3510 if( pxSocket->pxSocketSet != pxSocketSet )
\r
3512 /* Socket does not belong to this select group. */
\r
3517 #if( ipconfigUSE_TCP == 1 )
\r
3518 if( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP )
\r
3520 /* Check if the socket has already been accepted by the
\r
3521 owner. If not, it is useless to return it from a
\r
3523 BaseType_t bAccepted = pdFALSE;
\r
3525 if( pxSocket->u.xTCP.bits.bPassQueued == pdFALSE_UNSIGNED )
\r
3527 if( pxSocket->u.xTCP.bits.bPassAccept == pdFALSE_UNSIGNED )
\r
3529 bAccepted = pdTRUE;
\r
3533 /* Is the set owner interested in READ events? */
\r
3534 if( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 )
\r
3536 if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN )
\r
3538 if( ( pxSocket->u.xTCP.pxPeerSocket != NULL ) && ( pxSocket->u.xTCP.pxPeerSocket->u.xTCP.bits.bPassAccept != 0 ) )
\r
3540 xSocketBits |= eSELECT_READ;
\r
3543 else if( ( pxSocket->u.xTCP.bits.bReuseSocket != pdFALSE_UNSIGNED ) && ( pxSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED ) )
\r
3545 /* This socket has the re-use flag. After connecting it turns into
\r
3546 aconnected socket. Set the READ event, so that accept() will be called. */
\r
3547 xSocketBits |= eSELECT_READ;
\r
3549 else if( ( bAccepted != 0 ) && ( FreeRTOS_recvcount( pxSocket ) > 0 ) )
\r
3551 xSocketBits |= eSELECT_READ;
\r
3554 /* Is the set owner interested in EXCEPTION events? */
\r
3555 if( ( pxSocket->xSelectBits & eSELECT_EXCEPT ) != 0 )
\r
3557 if( ( pxSocket->u.xTCP.ucTCPState == eCLOSE_WAIT ) || ( pxSocket->u.xTCP.ucTCPState == eCLOSED ) )
\r
3559 xSocketBits |= eSELECT_EXCEPT;
\r
3563 /* Is the set owner interested in WRITE events? */
\r
3564 if( ( pxSocket->xSelectBits & eSELECT_WRITE ) != 0 )
\r
3566 BaseType_t bMatch = pdFALSE;
\r
3568 if( bAccepted != 0 )
\r
3570 if( FreeRTOS_tx_space( pxSocket ) > 0 )
\r
3576 if( bMatch == pdFALSE )
\r
3578 if( ( pxSocket->u.xTCP.bits.bConnPrepared != pdFALSE_UNSIGNED ) &&
\r
3579 ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) &&
\r
3580 ( pxSocket->u.xTCP.bits.bConnPassed == pdFALSE_UNSIGNED ) )
\r
3582 pxSocket->u.xTCP.bits.bConnPassed = pdTRUE_UNSIGNED;
\r
3587 if( bMatch != pdFALSE )
\r
3589 xSocketBits |= eSELECT_WRITE;
\r
3594 #endif /* ipconfigUSE_TCP == 1 */
\r
3596 /* Select events for UDP are simpler. */
\r
3597 if( ( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 ) &&
\r
3598 ( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) > 0U ) )
\r
3600 xSocketBits |= eSELECT_READ;
\r
3602 /* The WRITE and EXCEPT bits are not used for UDP */
\r
3603 } /* if( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP ) */
\r
3605 /* Each socket keeps its own event flags, which are looked-up
\r
3606 by FreeRTOS_FD_ISSSET() */
\r
3607 pxSocket->xSocketBits = xSocketBits;
\r
3609 /* The ORed value will be used to set the bits in the event
\r
3611 xGroupBits |= xSocketBits;
\r
3613 } /* for( pxIterator ... ) */
\r
3614 } /* for( xRound = 0; xRound <= xLastRound; xRound++ ) */
\r
3616 xBitsToClear = xEventGroupGetBits( pxSocketSet->xSelectGroup );
\r
3618 /* Now set the necessary bits. */
\r
3619 xBitsToClear = ( xBitsToClear & ~xGroupBits ) & eSELECT_ALL;
\r
3621 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
3623 /* Maybe the socketset was signalled, but don't
\r
3624 clear the 'eSELECT_INTR' bit here, as it will be used
\r
3625 and cleared in FreeRTOS_select(). */
\r
3626 xBitsToClear &= ( EventBits_t ) ~eSELECT_INTR;
\r
3628 #endif /* ipconfigSUPPORT_SIGNALS */
\r
3630 if( xBitsToClear != 0 )
\r
3632 xEventGroupClearBits( pxSocketSet->xSelectGroup, xBitsToClear );
\r
3635 /* Now include eSELECT_CALL_IP to wakeup the caller. */
\r
3636 xEventGroupSetBits( pxSocketSet->xSelectGroup, xGroupBits | eSELECT_CALL_IP );
\r
3639 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
3640 /*-----------------------------------------------------------*/
\r
3642 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
3644 /* Send a signal to the task which reads from this socket. */
\r
3645 BaseType_t FreeRTOS_SignalSocket( Socket_t xSocket )
\r
3647 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3648 BaseType_t xReturn;
\r
3650 if( pxSocket == NULL )
\r
3652 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3655 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
3656 if( ( pxSocket->pxSocketSet != NULL ) && ( pxSocket->pxSocketSet->xSelectGroup != NULL ) )
\r
3658 xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, eSELECT_INTR );
\r
3662 #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
\r
3663 if( pxSocket->xEventGroup != NULL )
\r
3665 xEventGroupSetBits( pxSocket->xEventGroup, eSOCKET_INTR );
\r
3670 xReturn = -pdFREERTOS_ERRNO_EINVAL;
\r
3676 #endif /* ipconfigSUPPORT_SIGNALS */
\r
3677 /*-----------------------------------------------------------*/
\r
3679 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
3681 /* Send a signal to the task which reads from this socket (FromISR version). */
\r
3682 BaseType_t FreeRTOS_SignalSocketFromISR( Socket_t xSocket, BaseType_t *pxHigherPriorityTaskWoken )
\r
3684 FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
\r
3685 BaseType_t xReturn;
\r
3686 IPStackEvent_t xEvent;
\r
3687 extern QueueHandle_t xNetworkEventQueue;
\r
3689 configASSERT( pxSocket != NULL );
\r
3690 configASSERT( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP );
\r
3691 configASSERT( pxSocket->xEventGroup );
\r
3693 xEvent.eEventType = eSocketSignalEvent;
\r
3694 xEvent.pvData = ( void * )pxSocket;
\r
3696 /* The IP-task will call FreeRTOS_SignalSocket for this socket. */
\r
3697 xReturn = xQueueSendToBackFromISR( xNetworkEventQueue, &xEvent, pxHigherPriorityTaskWoken );
\r
3702 #endif /* ipconfigSUPPORT_SIGNALS */
\r
3703 /*-----------------------------------------------------------*/
\r