1
0
mirror of https://github.com/FreeRTOS/FreeRTOS-Plus-TCP synced 2025-10-20 22:10:04 +08:00
Files
FreeRTOS-Plus-TCP/source/FreeRTOS_IP_Timers.c
Aniruddha Kanhere a4124602cc Merge changes to main.
This commit brings in the refactoring and restructuring changes
from IntegrationTesting1 branch to the main branch.
It also includes additional unit tests for 100% coverage.
The rationale behind not creating a PR is that the conflicts were too
huge to be resolved correctly. Thus, a force push to the main branch is
being done.
2022-05-26 12:42:45 -07:00

489 lines
14 KiB
C

/*
* FreeRTOS+TCP V2.3.4
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
/**
* @file FreeRTOS_ICMP.c
* @brief Implements the Internet Control Message Protocol for the FreeRTOS+TCP network stack.
*/
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
#include <string.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_IP_Timers.h"
#include "FreeRTOS_IP_Utils.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_ARP.h"
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_DHCP.h"
#include "NetworkInterface.h"
#include "NetworkBufferManagement.h"
#include "FreeRTOS_DNS.h"
/** @brief The pointer to buffer with packet waiting for ARP resolution. */
extern NetworkBufferDescriptor_t * pxARPWaitingNetworkBuffer;
/*
* Utility functions for the light weight IP timers.
*/
static void prvIPTimerStart( IPTimer_t * pxTimer,
TickType_t xTime );
static BaseType_t prvIPTimerCheck( IPTimer_t * pxTimer );
static void prvIPTimerReload( IPTimer_t * pxTimer,
TickType_t xTime );
/*
* A timer for each of the following processes, all of which need attention on a
* regular basis
*/
/** @brief Timer to limit the maximum time a packet should be stored while
* awaiting an ARP resolution. */
static IPTimer_t xARPResolutionTimer;
/** @brief ARP timer, to check its table entries. */
static IPTimer_t xARPTimer;
#if ( ipconfigUSE_DHCP != 0 )
/** @brief DHCP timer, to send requests and to renew a reservation. */
static IPTimer_t xDHCPTimer;
#endif
#if ( ipconfigUSE_TCP != 0 )
/** @brief TCP timer, to check for timeouts, resends. */
static IPTimer_t xTCPTimer;
#endif
#if ( ipconfigDNS_USE_CALLBACKS != 0 )
/** @brief DNS timer, to check for timeouts when looking-up a domain. */
static IPTimer_t xDNSTimer;
#endif
#if ( ipconfigUSE_TCP != 0 )
/** @brief Set to a non-zero value if one or more TCP message have been processed
* within the last round. */
extern BaseType_t xProcessedTCPMessage;
#endif
/**
* @brief Calculate the maximum sleep time remaining. It will go through all
* timers to see which timer will expire first. That will be the amount
* of time to block in the next call to xQueueReceive().
*
* @return The maximum sleep time or ipconfigMAX_IP_TASK_SLEEP_TIME,
* whichever is smaller.
*/
TickType_t xCalculateSleepTime( void )
{
TickType_t uxMaximumSleepTime;
/* Start with the maximum sleep time, then check this against the remaining
* time in any other timers that are active. */
uxMaximumSleepTime = ipconfigMAX_IP_TASK_SLEEP_TIME;
if( xARPTimer.bActive != pdFALSE_UNSIGNED )
{
if( xARPTimer.ulRemainingTime < uxMaximumSleepTime )
{
uxMaximumSleepTime = xARPTimer.ulRemainingTime;
}
}
#if ( ipconfigUSE_DHCP == 1 )
{
if( xDHCPTimer.bActive != pdFALSE_UNSIGNED )
{
if( xDHCPTimer.ulRemainingTime < uxMaximumSleepTime )
{
uxMaximumSleepTime = xDHCPTimer.ulRemainingTime;
}
}
}
#endif /* ipconfigUSE_DHCP */
#if ( ipconfigUSE_TCP == 1 )
{
if( xTCPTimer.bActive != pdFALSE_UNSIGNED )
{
if( xTCPTimer.ulRemainingTime < uxMaximumSleepTime )
{
uxMaximumSleepTime = xTCPTimer.ulRemainingTime;
}
}
}
#endif
#if ( ipconfigDNS_USE_CALLBACKS != 0 )
{
if( xDNSTimer.bActive != pdFALSE_UNSIGNED )
{
if( xDNSTimer.ulRemainingTime < uxMaximumSleepTime )
{
uxMaximumSleepTime = xDNSTimer.ulRemainingTime;
}
}
}
#endif
return uxMaximumSleepTime;
}
/*-----------------------------------------------------------*/
/**
* @brief Check the network timers (ARP/DHCP/DNS/TCP) and if they are
* expired, send an event to the IP-Task.
*/
void vCheckNetworkTimers( void )
{
/* Is it time for ARP processing? */
if( prvIPTimerCheck( &xARPTimer ) != pdFALSE )
{
( void ) xSendEventToIPTask( eARPTimerEvent );
}
/* Is the ARP resolution timer expired? */
if( prvIPTimerCheck( &xARPResolutionTimer ) != pdFALSE )
{
if( pxARPWaitingNetworkBuffer != NULL )
{
/* Disable the ARP resolution timer. */
vIPSetARPResolutionTimerEnableState( pdFALSE );
/* We have waited long enough for the ARP response. Now, free the network
* buffer. */
vReleaseNetworkBufferAndDescriptor( pxARPWaitingNetworkBuffer );
/* Clear the pointer. */
pxARPWaitingNetworkBuffer = NULL;
iptraceDELAYED_ARP_TIMER_EXPIRED();
}
}
#if ( ipconfigUSE_DHCP == 1 )
{
/* Is it time for DHCP processing? */
if( prvIPTimerCheck( &xDHCPTimer ) != pdFALSE )
{
( void ) xSendDHCPEvent();
}
}
#endif /* ipconfigUSE_DHCP */
#if ( ipconfigDNS_USE_CALLBACKS != 0 )
{
/* Is it time for DNS processing? */
if( prvIPTimerCheck( &xDNSTimer ) != pdFALSE )
{
vDNSCheckCallBack( NULL );
}
}
#endif /* ipconfigDNS_USE_CALLBACKS */
#if ( ipconfigUSE_TCP == 1 )
{
BaseType_t xWillSleep;
TickType_t xNextTime;
BaseType_t xCheckTCPSockets;
/* If the IP task has messages waiting to be processed then
* it will not sleep in any case. */
if( uxQueueMessagesWaiting( xNetworkEventQueue ) == 0U )
{
xWillSleep = pdTRUE;
}
else
{
xWillSleep = pdFALSE;
}
/* Sockets need to be checked if the TCP timer has expired. */
xCheckTCPSockets = prvIPTimerCheck( &xTCPTimer );
/* Sockets will also be checked if there are TCP messages but the
* message queue is empty (indicated by xWillSleep being true). */
if( ( xProcessedTCPMessage != pdFALSE ) && ( xWillSleep != pdFALSE ) )
{
xCheckTCPSockets = pdTRUE;
}
if( xCheckTCPSockets != pdFALSE )
{
/* Attend to the sockets, returning the period after which the
* check must be repeated. */
xNextTime = xTCPTimerCheck( xWillSleep );
prvIPTimerStart( &xTCPTimer, xNextTime );
xProcessedTCPMessage = 0;
}
}
/* See if any socket was planned to be closed. */
vSocketCloseNextTime( NULL );
#endif /* ipconfigUSE_TCP == 1 */
}
/*-----------------------------------------------------------*/
/**
* @brief Start an IP timer. The IP-task has its own implementation of a timer
* called 'IPTimer_t', which is based on the FreeRTOS 'TimeOut_t'.
*
* @param[in] pxTimer: Pointer to the IP timer. When zero, the timer is marked
* as expired.
* @param[in] xTime: Time to be loaded into the IP timer.
*/
static void prvIPTimerStart( IPTimer_t * pxTimer,
TickType_t xTime )
{
vTaskSetTimeOutState( &pxTimer->xTimeOut );
pxTimer->ulRemainingTime = xTime;
if( xTime == ( TickType_t ) 0 )
{
pxTimer->bExpired = pdTRUE_UNSIGNED;
}
else
{
pxTimer->bExpired = pdFALSE_UNSIGNED;
}
pxTimer->bActive = pdTRUE_UNSIGNED;
}
/*-----------------------------------------------------------*/
void vIPTimerStartARPResolution( TickType_t xTime )
{
prvIPTimerStart( &( xARPResolutionTimer ), xTime );
}
/*-----------------------------------------------------------*/
/**
* @brief Sets the reload time of an IP timer and restarts it.
*
* @param[in] pxTimer: Pointer to the IP timer.
* @param[in] xTime: Time to be reloaded into the IP timer.
*/
static void prvIPTimerReload( IPTimer_t * pxTimer,
TickType_t xTime )
{
pxTimer->ulReloadTime = xTime;
prvIPTimerStart( pxTimer, xTime );
}
/*-----------------------------------------------------------*/
#if ( ipconfigUSE_TCP == 1 )
void vTCPTimerReload( TickType_t xTime )
{
prvIPTimerReload( &xTCPTimer, xTime );
}
#endif
/*-----------------------------------------------------------*/
void vARPTimerReload( TickType_t xTime )
{
prvIPTimerReload( &xARPTimer, xTime );
}
/*-----------------------------------------------------------*/
#if ( ipconfigUSE_DHCP == 1 )
/**
* @brief Reload the DHCP timer.
*
* @param[in] ulLeaseTime: The reload value.
*/
void vDHCPTimerReload( TickType_t xLeaseTime )
{
prvIPTimerReload( &xDHCPTimer, xLeaseTime );
}
#endif /* ipconfigUSE_DHCP */
/*-----------------------------------------------------------*/
#if ( ipconfigDNS_USE_CALLBACKS != 0 )
/**
* @brief Reload the DNS timer.
*
* @param[in] ulCheckTime: The reload value.
*/
void vDNSTimerReload( uint32_t ulCheckTime )
{
prvIPTimerReload( &xDNSTimer, ulCheckTime );
}
#endif /* ipconfigDNS_USE_CALLBACKS != 0 */
/*-----------------------------------------------------------*/
/**
* @brief Check the IP timer to see whether an IP event should be processed or not.
*
* @param[in] pxTimer: Pointer to the IP timer.
*
* @return If the timer is expired then pdTRUE is returned. Else pdFALSE.
*/
static BaseType_t prvIPTimerCheck( IPTimer_t * pxTimer )
{
BaseType_t xReturn;
if( pxTimer->bActive == pdFALSE_UNSIGNED )
{
/* The timer is not enabled. */
xReturn = pdFALSE;
}
else
{
/* The timer might have set the bExpired flag already, if not, check the
* value of xTimeOut against ulRemainingTime. */
if( pxTimer->bExpired == pdFALSE_UNSIGNED )
{
if( xTaskCheckForTimeOut( &( pxTimer->xTimeOut ), &( pxTimer->ulRemainingTime ) ) != pdFALSE )
{
pxTimer->bExpired = pdTRUE_UNSIGNED;
}
}
if( pxTimer->bExpired != pdFALSE_UNSIGNED )
{
prvIPTimerStart( pxTimer, pxTimer->ulReloadTime );
xReturn = pdTRUE;
}
else
{
xReturn = pdFALSE;
}
}
return xReturn;
}
/*-----------------------------------------------------------*/
#if ( ipconfigUSE_TCP == 1 )
/**
* @brief Enable/disable the TCP timer.
*
* @param[in] xEnableState: pdTRUE - enable timer; pdFALSE - disable timer.
*/
void vIPSetTCPTimerEnableState( BaseType_t xEnableState )
{
if( xEnableState != pdFALSE )
{
xTCPTimer.bActive = pdTRUE_UNSIGNED;
}
else
{
xTCPTimer.bActive = pdFALSE_UNSIGNED;
}
}
/*-----------------------------------------------------------*/
#endif /* if ( ipconfigUSE_TCP == 1 ) */
/**
* @brief Enable/disable the ARP timer.
*
* @param[in] xEnableState: pdTRUE - enable timer; pdFALSE - disable timer.
*/
void vIPSetARPTimerEnableState( BaseType_t xEnableState )
{
if( xEnableState != pdFALSE )
{
xARPTimer.bActive = pdTRUE_UNSIGNED;
}
else
{
xARPTimer.bActive = pdFALSE_UNSIGNED;
}
}
/*-----------------------------------------------------------*/
/**
* @brief Enable or disable the ARP resolution timer.
*
* @param[in] xEnableState: pdTRUE if the timer must be enabled, pdFALSE otherwise.
*/
void vIPSetARPResolutionTimerEnableState( BaseType_t xEnableState )
{
if( xEnableState != pdFALSE )
{
xARPResolutionTimer.bActive = pdTRUE_UNSIGNED;
}
else
{
xARPResolutionTimer.bActive = pdFALSE_UNSIGNED;
}
}
/*-----------------------------------------------------------*/
#if ( ipconfigUSE_DHCP == 1 )
/**
* @brief Enable/disable the DHCP timer.
*
* @param[in] xEnableState: pdTRUE - enable timer; pdFALSE - disable timer.
*/
void vIPSetDHCPTimerEnableState( BaseType_t xEnableState )
{
if( xEnableState != pdFALSE )
{
xDHCPTimer.bActive = pdTRUE_UNSIGNED;
}
else
{
xDHCPTimer.bActive = pdFALSE_UNSIGNED;
}
}
#endif /* ipconfigUSE_DHCP */
/*-----------------------------------------------------------*/
#if ( ipconfigDNS_USE_CALLBACKS == 1 )
/**
* @brief Enable/disable the DNS timer.
*
* @param[in] xEnableState: pdTRUE - enable timer; pdFALSE - disable timer.
*/
void vIPSetDNSTimerEnableState( BaseType_t xEnableState )
{
if( xEnableState != 0 )
{
xDNSTimer.bActive = pdTRUE_UNSIGNED;
}
else
{
xDNSTimer.bActive = pdFALSE_UNSIGNED;
}
}
#endif /* ipconfigDNS_USE_CALLBACKS == 1 */
/*-----------------------------------------------------------*/