void vNetworkBufferRelease( xNetworkBufferDescriptor_t * const pxNetworkBuffer ) { BaseType_t xListItemAlreadyInFreeList; /* Ensure the buffer is returned to the list of free buffers before the counting semaphore is 'given' to say a buffer is available. Release the storage allocated to the buffer payload. THIS FILE SHOULD NOT BE USED IF THE PROJECT INCLUDES A MEMORY ALLOCATOR THAT WILL FRAGMENT THE HEAP MEMORY. For example, heap_2 must not be used, heap_4 can be used. */ vEthernetBufferRelease( pxNetworkBuffer->pucEthernetBuffer ); pxNetworkBuffer->pucEthernetBuffer = NULL; taskENTER_CRITICAL(); { xListItemAlreadyInFreeList = listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) ); if( xListItemAlreadyInFreeList == pdFALSE ) { vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) ); } configASSERT( xListItemAlreadyInFreeList == pdFALSE ); } taskEXIT_CRITICAL(); xSemaphoreGive( xNetworkBufferSemaphore ); iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer ); }
static void vDNSSetCallBack( const char *pcHostName, void *pvSearchID, FOnDNSEvent pCallbackFunction, TickType_t xTimeout, TickType_t xIdentifier ) { size_t lLength = strlen( pcHostName ); DNSCallback_t *pxCallback = ( DNSCallback_t * )pvPortMalloc( sizeof( *pxCallback ) + lLength ); /* Translate from ms to number of clock ticks. */ xTimeout /= portTICK_PERIOD_MS; if( pxCallback != NULL ) { if( listLIST_IS_EMPTY( &xCallbackList ) ) { /* This is the first one, start the DNS timer to check for timeouts */ vIPReloadDNSTimer( FreeRTOS_min_uint32( 1000U, xTimeout ) ); } strcpy( pxCallback->pcName, pcHostName ); pxCallback->pCallbackFunction = pCallbackFunction; pxCallback->pvSearchID = pvSearchID; pxCallback->xRemaningTime = xTimeout; vTaskSetTimeOutState( &pxCallback->xTimeoutState ); listSET_LIST_ITEM_OWNER( &( pxCallback->xListItem ), ( void* ) pxCallback ); listSET_LIST_ITEM_VALUE( &( pxCallback->xListItem ), xIdentifier ); vTaskSuspendAll(); { vListInsertEnd( &xCallbackList, &pxCallback->xListItem ); } xTaskResumeAll(); } }
void vReleaseNetworkBufferAndDescriptor( xNetworkBufferDescriptor_t * const pxNetworkBuffer ) { BaseType_t xListItemAlreadyInFreeList; #if( ipconfigIP_TASK_KEEPS_MESSAGE_BUFFER != 0 ) if( pxNetworkBuffer == pxIpTaskMessageBuffer ) return; #endif if( !bIsValidNetworkDescriptor ( pxNetworkBuffer ) ) { FreeRTOS_debug_printf( ( "vReleaseNetworkBufferAndDescriptor: Invalid buffer %p\n", pxNetworkBuffer ) ); return ; } /* Ensure the buffer is returned to the list of free buffers before the counting semaphore is 'given' to say a buffer is available. */ /* taskENTER_CRITICAL(); */ ipconfigBUFFER_ALLOC_LOCK(); { { xListItemAlreadyInFreeList = listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) ); if( xListItemAlreadyInFreeList == pdFALSE ) { vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) ); } } /* configASSERT( xListItemAlreadyInFreeList == pdFALSE ); */ } ipconfigBUFFER_ALLOC_UNLOCK(); /* taskEXIT_CRITICAL(); */ if( xListItemAlreadyInFreeList ) { FreeRTOS_debug_printf( ( "vReleaseNetworkBufferAndDescriptor: %p ALREADY RELEASED (now %lu)\n", pxNetworkBuffer, uxGetNumberOfFreeNetworkBuffers( ) ) ); } if( !xListItemAlreadyInFreeList ) { xSemaphoreGive( xNetworkBufferSemaphore ); showWarnings(); if( xTCPWindowLoggingLevel > 3 ) FreeRTOS_debug_printf( ( "BUF_PUT[%ld]: %p (%p) (now %lu)\n", bIsValidNetworkDescriptor( pxNetworkBuffer ), pxNetworkBuffer, pxNetworkBuffer->pucEthernetBuffer, uxGetNumberOfFreeNetworkBuffers( ) ) ); } iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer ); }
BaseType_t vNetworkBufferReleaseFromISR( NetworkBufferDescriptor_t * const pxNetworkBuffer ) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; /* Ensure the buffer is returned to the list of free buffers before the counting semaphore is 'given' to say a buffer is available. */ ipconfigBUFFER_ALLOC_LOCK_FROM_ISR(); { vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) ); } ipconfigBUFFER_ALLOC_UNLOCK_FROM_ISR(); xSemaphoreGiveFromISR( xNetworkBufferSemaphore, &xHigherPriorityTaskWoken ); iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer ); return xHigherPriorityTaskWoken; }
BaseType_t vNetworkBufferReleaseFromISR( xNetworkBufferDescriptor_t * const pxNetworkBuffer ) { UBaseType_t uxSavedInterruptStatus; BaseType_t xHigherPriorityTaskWoken = pdFALSE; /* Ensure the buffer is returned to the list of free buffers before the counting semaphore is 'given' to say a buffer is available. */ uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); { vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) ); } portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); xSemaphoreGiveFromISR( xNetworkBufferSemaphore, &xHigherPriorityTaskWoken ); iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer ); return xHigherPriorityTaskWoken; }
void vReleaseNetworkBufferAndDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer ) { BaseType_t xListItemAlreadyInFreeList; if( bIsValidNetworkDescriptor( pxNetworkBuffer ) == pdFALSE_UNSIGNED ) { FreeRTOS_debug_printf( ( "vReleaseNetworkBufferAndDescriptor: Invalid buffer %p\n", pxNetworkBuffer ) ); return ; } /* Ensure the buffer is returned to the list of free buffers before the counting semaphore is 'given' to say a buffer is available. */ ipconfigBUFFER_ALLOC_LOCK(); { { xListItemAlreadyInFreeList = listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) ); if( xListItemAlreadyInFreeList == pdFALSE ) { vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) ); } } } ipconfigBUFFER_ALLOC_UNLOCK(); if( xListItemAlreadyInFreeList ) { FreeRTOS_debug_printf( ( "vReleaseNetworkBufferAndDescriptor: %p ALREADY RELEASED (now %lu)\n", pxNetworkBuffer, uxGetNumberOfFreeNetworkBuffers( ) ) ); } if( xListItemAlreadyInFreeList == pdFALSE ) { xSemaphoreGive( xNetworkBufferSemaphore ); prvShowWarnings(); if( xTCPWindowLoggingLevel > 3 ) FreeRTOS_debug_printf( ( "BUF_PUT[%ld]: %p (%p) (now %lu)\n", bIsValidNetworkDescriptor( pxNetworkBuffer ), pxNetworkBuffer, pxNetworkBuffer->pucEthernetBuffer, uxGetNumberOfFreeNetworkBuffers( ) ) ); } iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer ); }
void vNetworkBufferRelease( xNetworkBufferDescriptor_t * const pxNetworkBuffer ) { BaseType_t xListItemAlreadyInFreeList; /* Ensure the buffer is returned to the list of free buffers before the counting semaphore is 'given' to say a buffer is available. */ taskENTER_CRITICAL(); { xListItemAlreadyInFreeList = listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) ); if( xListItemAlreadyInFreeList == pdFALSE ) { vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) ); } configASSERT( xListItemAlreadyInFreeList == pdFALSE ); } taskEXIT_CRITICAL(); xSemaphoreGive( xNetworkBufferSemaphore ); iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer ); }
signed portBASE_TYPE xCoRoutineRemoveFromEventList( const xList *pxEventList ) { corCRCB *pxUnblockedCRCB; signed portBASE_TYPE xReturn; /* This function is called from within an interrupt. It can only access event lists and the pending ready list. This function assumes that a check has already been made to ensure pxEventList is not empty. */ pxUnblockedCRCB = ( corCRCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); ( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) ); vListInsertEnd( ( xList * ) & ( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) ); if ( pxUnblockedCRCB->uxPriority >= pxCurrentCoRoutine->uxPriority ) { xReturn = pdTRUE; } else { xReturn = pdFALSE; } return xReturn; }
portBASE_TYPE xCoRoutineRemoveFromEventList( const xList *pxEventList ) { corCRCB *pxUnblockedCRCB; portBASE_TYPE xReturn; /* This function is called from within an interrupt. It can only access event lists and the pending ready list. */ pxUnblockedCRCB = ( corCRCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); vListRemove( &( pxUnblockedCRCB->xEventListItem ) ); vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxUnblockedCRCB->xEventListItem ) ); if( pxUnblockedCRCB->uxPriority >= pxCurrentCoRoutine->uxPriority ) { xReturn = pdTRUE; } else { xReturn = pdFALSE; } return xReturn; }
BaseType_t xProcessReceivedUDPPacket( xNetworkBufferDescriptor_t *pxNetworkBuffer, uint16_t usPort ) { xListItem *pxListItem; BaseType_t xReturn = pdPASS; xFreeRTOS_Socket_t *pxSocket; BaseType_t xHigherPriorityTaskWoken = pdFALSE; vTaskSuspendAll(); { /* See if there is a list item associated with the port number on the list of bound sockets. */ pxListItem = pxListFindListItemWithValue( &xBoundSocketsList, ( TickType_t ) usPort ); } xTaskResumeAll(); if( pxListItem != NULL ) { /* The owner of the list item is the socket itself. */ pxSocket = ( xFreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxListItem ); vTaskSuspendAll(); { #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 ) { /* Is the socket a member of a select() group? */ if( pxSocket->xSelectQueue != NULL ) { /* Can the select group be notified that the socket is ready to be read? */ if( xQueueSendFromISR( pxSocket->xSelectQueue, &pxSocket, &xHigherPriorityTaskWoken ) != pdPASS ) { /* Could not notify the select group. */ xReturn = pdFAIL; iptraceFAILED_TO_NOTIFY_SELECT_GROUP( pxSocket ); } } } #endif if( xReturn == pdPASS ) { taskENTER_CRITICAL(); { /* Add the network packet to the list of packets to be processed by the socket. */ vListInsertEnd( &( pxSocket->xWaitingPacketsList ), &( pxNetworkBuffer->xBufferListItem ) ); } taskEXIT_CRITICAL(); /* The socket's counting semaphore records how many packets are waiting to be processed by the socket. */ xSemaphoreGiveFromISR( pxSocket->xWaitingPacketSemaphore, &xHigherPriorityTaskWoken ); } } if( xTaskResumeAll() == pdFALSE ) { if( xHigherPriorityTaskWoken != pdFALSE ) { taskYIELD(); } } } else { xReturn = pdFAIL; } return xReturn; }
BaseType_t FreeRTOS_bind( xSocket_t xSocket, struct freertos_sockaddr * pxAddress, socklen_t xAddressLength ) { BaseType_t xReturn = 0; /* In Berkeley sockets, 0 means pass for bind(). */ xFreeRTOS_Socket_t *pxSocket; #if ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 struct freertos_sockaddr xAddress; #endif /* ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND */ pxSocket = ( xFreeRTOS_Socket_t * ) xSocket; /* The function prototype is designed to maintain the expected Berkeley sockets standard, but this implementation does not use all the parameters. */ ( void ) xAddressLength; configASSERT( xSocket ); configASSERT( xSocket != FREERTOS_INVALID_SOCKET ); #if ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 { /* pxAddress will be NULL if sendto() was called on a socket without the socket being bound to an address. In this case, automatically allocate an address to the socket. There is a very tiny chance that the allocated port will already be in use - if that is the case, then the check below [pxListFindListItemWithValue()] will result in an error being returned. */ if( pxAddress == NULL ) { pxAddress = &xAddress; pxAddress->sin_port = prvGetPrivatePortNumber(); } } #endif /* ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 */ /* Sockets must be bound before calling FreeRTOS_sendto() if ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is not set to 1. */ configASSERT( pxAddress ); if( pxAddress != NULL ) { if( pxAddress->sin_port == 0 ) { pxAddress->sin_port = prvGetPrivatePortNumber(); } vTaskSuspendAll(); { /* Check to ensure the port is not already in use. */ if( pxListFindListItemWithValue( &xBoundSocketsList, ( TickType_t ) pxAddress->sin_port ) != NULL ) { xReturn = FREERTOS_EADDRINUSE; } } xTaskResumeAll(); /* Check that xReturn has not been set before continuing. */ if( xReturn == 0 ) { if( pxSocket->xWaitingPacketSemaphore == NULL ) { /* Create the semaphore used to count the number of packets that are queued on this socket. */ pxSocket->xWaitingPacketSemaphore = xSemaphoreCreateCounting( ipconfigNUM_NETWORK_BUFFERS, 0 ); if( pxSocket->xWaitingPacketSemaphore != NULL ) { /* Allocate the port number to the socket. */ socketSET_SOCKET_ADDRESS( pxSocket, pxAddress->sin_port ); taskENTER_CRITICAL(); { /* Add the socket to the list of bound ports. */ vListInsertEnd( &xBoundSocketsList, &( pxSocket->xBoundSocketListItem ) ); } taskEXIT_CRITICAL(); } else { /* Out of memory. */ xReturn = FREERTOS_ENOBUFS; } } else { /* The socket is already bound. */ xReturn = FREERTOS_EINVAL; } } } else { xReturn = FREERTOS_EADDRNOTAVAIL; } if( xReturn != 0 ) { iptraceBIND_FAILED( xSocket, ( FreeRTOS_ntohs( pxAddress->sin_port ) ) ); } return xReturn; } /* Tested */
BaseType_t xProcessReceivedUDPPacket( xNetworkBufferDescriptor_t *pxNetworkBuffer, uint16_t usPort ) { BaseType_t xReturn = pdPASS; xFreeRTOS_Socket_t *pxSocket; xUDPPacket_t *pxUDPPacket = (xUDPPacket_t *) pxNetworkBuffer->pucEthernetBuffer; pxSocket = pxUDPSocketLookup( usPort ); if( pxSocket ) { /* When refreshing the ARP cache with received UDP packets we must be careful; hundreds of broadcast messages may pass and if we're not handling them, no use to fill the ARP cache with those IP addresses. */ vARPRefreshCacheEntry( &( pxUDPPacket->xEthernetHeader.xSourceAddress ), pxUDPPacket->xIPHeader.ulSourceIPAddress ); #if( ipconfigUSE_CALLBACKS == 1 ) { /* Did the owner of this socket register a reception handler ? */ if( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xUdp.pHndReceive ) ) { struct freertos_sockaddr xSourceAddress, destinationAddress; void *pcData = ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET ] ); FOnUdpReceive xHandler = ( FOnUdpReceive ) pxSocket->u.xUdp.pHndReceive; xSourceAddress.sin_port = pxNetworkBuffer->usPort; xSourceAddress.sin_addr = pxNetworkBuffer->ulIPAddress; destinationAddress.sin_port = usPort; destinationAddress.sin_addr = pxUDPPacket->xIPHeader.ulDestinationIPAddress; if( xHandler( (xSocket_t *)pxSocket, ( void* ) pcData, ( size_t ) pxNetworkBuffer->xDataLength, &xSourceAddress, &destinationAddress ) ) { xReturn = pdFAIL; /* FAIL means that we did not consume or release the buffer */ } } } #endif /* ipconfigUSE_CALLBACKS */ #if( ipconfigUDP_MAX_RX_PACKETS > 0 ) { if( xReturn == pdPASS ) { if ( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUdp.xWaitingPacketsList ) ) >= pxSocket->u.xUdp.xMaxPackets ) { FreeRTOS_debug_printf( ( "xProcessReceivedUDPPacket: buffer full %ld >= %ld port %u\n", listCURRENT_LIST_LENGTH( &( pxSocket->u.xUdp.xWaitingPacketsList ) ), pxSocket->u.xUdp.xMaxPackets, pxSocket->usLocPort ) ); xReturn = pdFAIL; /* we did not consume or release the buffer */ } } } #endif if( xReturn == pdPASS ) { vTaskSuspendAll(); { if( xReturn == pdPASS ) { taskENTER_CRITICAL(); { /* Add the network packet to the list of packets to be processed by the socket. */ vListInsertEnd( &( pxSocket->u.xUdp.xWaitingPacketsList ), &( pxNetworkBuffer->xBufferListItem ) ); } taskEXIT_CRITICAL(); } } xTaskResumeAll(); /* Set the socket's receive event */ if( pxSocket->xEventGroup != NULL ) { xEventGroupSetBits( pxSocket->xEventGroup, eSOCKET_RECEIVE ); } #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 ) { if( ( pxSocket->pxSocketSet != NULL ) && ( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 ) ) { xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, eSELECT_READ ); } } #endif #if( ipconfigSOCKET_HAS_USER_SEMAPHORE == 1 ) { if( pxSocket->pxUserSemaphore != NULL ) { xSemaphoreGive( pxSocket->pxUserSemaphore ); } } #endif #if( ipconfigUSE_DHCP == 1 ) { if( xIsDHCPSocket( pxSocket ) ) { xSendEventToIPTask( eDHCPEvent ); } } #endif } } else { /* There is no socket listening to the target port, but still it might be for this node. */ #if( ipconfigUSE_DNS == 1 ) /* a DNS reply, check for the source port. Although the DNS client does open a UDP socket to send a messages, this socket will be closed after a short timeout. Messages that come late (after the socket is closed) will be treated here. */ if( FreeRTOS_ntohs( pxUDPPacket->xUDPHeader.usSourcePort ) == ipDNS_PORT ) { vARPRefreshCacheEntry( &( pxUDPPacket->xEthernetHeader.xSourceAddress ), pxUDPPacket->xIPHeader.ulSourceIPAddress ); xReturn = ( BaseType_t )ulDNSHandlePacket( pxNetworkBuffer ); } else #endif #if( ipconfigUSE_LLMNR == 1 ) /* a LLMNR request, check for the destination port. */ if( usPort == FreeRTOS_ntohs( ipLLMNR_PORT ) ) { vARPRefreshCacheEntry( &( pxUDPPacket->xEthernetHeader.xSourceAddress ), pxUDPPacket->xIPHeader.ulSourceIPAddress ); xReturn = ( BaseType_t )ulDNSHandlePacket( pxNetworkBuffer ); } else #endif /* ipconfigUSE_LLMNR */ #if( ipconfigUSE_NBNS == 1 ) /* a NetBIOS request, check for the destination port */ if( usPort == FreeRTOS_ntohs( ipNBNS_PORT ) ) { vARPRefreshCacheEntry( &( pxUDPPacket->xEthernetHeader.xSourceAddress ), pxUDPPacket->xIPHeader.ulSourceIPAddress ); xReturn = ( BaseType_t )ulNBNSHandlePacket( pxNetworkBuffer ); } else #endif /* ipconfigUSE_NBNS */ { xReturn = pdFAIL; } } return xReturn; }