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 );
}
示例#2
0
	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();
		}
	}
示例#3
0
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 );
}
示例#4
0
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;
}
示例#5
0
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;
}
示例#6
0
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 );
}
示例#7
0
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 );
}
示例#8
0
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;
}
示例#9
0
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;
}
示例#10
0
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;
}
示例#11
0
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 */
示例#12
0
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;
}