in device_firmware/libraries/freertos_plus/standard/freertos_plus_tcp/source/FreeRTOS_DHCP.c [258:547]
void vDHCPProcess( BaseType_t xReset )
{
BaseType_t xGivingUp = pdFALSE;
#if( ipconfigUSE_DHCP_HOOK != 0 )
eDHCPCallbackAnswer_t eAnswer;
#endif /* ipconfigUSE_DHCP_HOOK */
/* Is DHCP starting over? */
if( xReset != pdFALSE )
{
xDHCPData.eDHCPState = eWaitingSendFirstDiscover;
}
switch( xDHCPData.eDHCPState )
{
case eWaitingSendFirstDiscover :
/* Ask the user if a DHCP discovery is required. */
#if( ipconfigUSE_DHCP_HOOK != 0 )
eAnswer = xApplicationDHCPHook( eDHCPPhasePreDiscover, xNetworkAddressing.ulDefaultIPAddress );
if( eAnswer == eDHCPContinue )
#endif /* ipconfigUSE_DHCP_HOOK */
{
/* Initial state. Create the DHCP socket, timer, etc. if they
have not already been created. */
prvInitialiseDHCP();
/* See if prvInitialiseDHCP() has creates a socket. */
if( xDHCPData.xDHCPSocket == NULL )
{
xGivingUp = pdTRUE;
break;
}
*ipLOCAL_IP_ADDRESS_POINTER = 0UL;
/* Send the first discover request. */
if( xDHCPData.xDHCPSocket != NULL )
{
xDHCPData.xDHCPTxTime = xTaskGetTickCount();
prvSendDHCPDiscover( );
xDHCPData.eDHCPState = eWaitingOffer;
}
}
#if( ipconfigUSE_DHCP_HOOK != 0 )
else
{
if( eAnswer == eDHCPUseDefaults )
{
memcpy( &xNetworkAddressing, &xDefaultAddressing, sizeof( xNetworkAddressing ) );
}
/* The user indicates that the DHCP process does not continue. */
xGivingUp = pdTRUE;
}
#endif /* ipconfigUSE_DHCP_HOOK */
break;
case eWaitingOffer :
xGivingUp = pdFALSE;
/* Look for offers coming in. */
if( prvProcessDHCPReplies( dhcpMESSAGE_TYPE_OFFER ) == pdPASS )
{
#if( ipconfigUSE_DHCP_HOOK != 0 )
/* Ask the user if a DHCP request is required. */
eAnswer = xApplicationDHCPHook( eDHCPPhasePreRequest, xDHCPData.ulOfferedIPAddress );
if( eAnswer == eDHCPContinue )
#endif /* ipconfigUSE_DHCP_HOOK */
{
/* An offer has been made, the user wants to continue,
generate the request. */
xDHCPData.xDHCPTxTime = xTaskGetTickCount();
xDHCPData.xDHCPTxPeriod = dhcpINITIAL_DHCP_TX_PERIOD;
prvSendDHCPRequest( );
xDHCPData.eDHCPState = eWaitingAcknowledge;
break;
}
#if( ipconfigUSE_DHCP_HOOK != 0 )
if( eAnswer == eDHCPUseDefaults )
{
memcpy( &xNetworkAddressing, &xDefaultAddressing, sizeof( xNetworkAddressing ) );
}
/* The user indicates that the DHCP process does not continue. */
xGivingUp = pdTRUE;
#endif /* ipconfigUSE_DHCP_HOOK */
}
else if( ( xTaskGetTickCount() - xDHCPData.xDHCPTxTime ) > xDHCPData.xDHCPTxPeriod )
{
/* It is time to send another Discover. Increase the time
period, and if it has not got to the point of giving up - send
another discovery. */
xDHCPData.xDHCPTxPeriod <<= 1;
if( xDHCPData.xDHCPTxPeriod <= ipconfigMAXIMUM_DISCOVER_TX_PERIOD )
{
xDHCPData.ulTransactionId = ipconfigRAND32( );
if( 0 != xDHCPData.ulTransactionId )
{
xDHCPData.xDHCPTxTime = xTaskGetTickCount( );
xDHCPData.xUseBroadcast = !xDHCPData.xUseBroadcast;
prvSendDHCPDiscover( );
FreeRTOS_debug_printf( ( "vDHCPProcess: timeout %lu ticks\n", xDHCPData.xDHCPTxPeriod ) );
}
else
{
FreeRTOS_debug_printf( ( "vDHCPProcess: failed to generate a random Transaction ID\n" ) );
}
}
else
{
FreeRTOS_debug_printf( ( "vDHCPProcess: giving up %lu > %lu ticks\n", xDHCPData.xDHCPTxPeriod, ipconfigMAXIMUM_DISCOVER_TX_PERIOD ) );
#if( ipconfigDHCP_FALL_BACK_AUTO_IP != 0 )
{
/* Only use a fake Ack if the default IP address == 0x00
and the link local addressing is used. Start searching
a free LinkLayer IP-address. Next state will be
'eGetLinkLayerAddress'. */
prvPrepareLinkLayerIPLookUp();
/* Setting an IP address manually so set to not using
leased address mode. */
xDHCPData.eDHCPState = eGetLinkLayerAddress;
}
#else
{
xGivingUp = pdTRUE;
}
#endif /* ipconfigDHCP_FALL_BACK_AUTO_IP */
}
}
break;
case eWaitingAcknowledge :
/* Look for acks coming in. */
if( prvProcessDHCPReplies( dhcpMESSAGE_TYPE_ACK ) == pdPASS )
{
FreeRTOS_debug_printf( ( "vDHCPProcess: acked %lxip\n", FreeRTOS_ntohl( xDHCPData.ulOfferedIPAddress ) ) );
/* DHCP completed. The IP address can now be used, and the
timer set to the lease timeout time. */
*ipLOCAL_IP_ADDRESS_POINTER = xDHCPData.ulOfferedIPAddress;
/* Setting the 'local' broadcast address, something like
'192.168.1.255'. */
xNetworkAddressing.ulBroadcastAddress = ( xDHCPData.ulOfferedIPAddress & xNetworkAddressing.ulNetMask ) | ~xNetworkAddressing.ulNetMask;
xDHCPData.eDHCPState = eLeasedAddress;
iptraceDHCP_SUCCEDEED( xDHCPData.ulOfferedIPAddress );
/* DHCP failed, the default configured IP-address will be used
Now call vIPNetworkUpCalls() to send the network-up event and
start the ARP timer. */
vIPNetworkUpCalls( );
/* Close socket to ensure packets don't queue on it. */
vSocketClose( xDHCPData.xDHCPSocket );
xDHCPData.xDHCPSocket = NULL;
if( xDHCPData.ulLeaseTime == 0UL )
{
xDHCPData.ulLeaseTime = dhcpDEFAULT_LEASE_TIME;
}
else if( xDHCPData.ulLeaseTime < dhcpMINIMUM_LEASE_TIME )
{
xDHCPData.ulLeaseTime = dhcpMINIMUM_LEASE_TIME;
}
else
{
/* The lease time is already valid. */
}
/* Check for clashes. */
vARPSendGratuitous();
vIPReloadDHCPTimer( xDHCPData.ulLeaseTime );
}
else
{
/* Is it time to send another Discover? */
if( ( xTaskGetTickCount() - xDHCPData.xDHCPTxTime ) > xDHCPData.xDHCPTxPeriod )
{
/* Increase the time period, and if it has not got to the
point of giving up - send another request. */
xDHCPData.xDHCPTxPeriod <<= 1;
if( xDHCPData.xDHCPTxPeriod <= ipconfigMAXIMUM_DISCOVER_TX_PERIOD )
{
xDHCPData.xDHCPTxTime = xTaskGetTickCount();
prvSendDHCPRequest( );
}
else
{
/* Give up, start again. */
xDHCPData.eDHCPState = eWaitingSendFirstDiscover;
}
}
}
break;
#if( ipconfigDHCP_FALL_BACK_AUTO_IP != 0 )
case eGetLinkLayerAddress:
if( ( xTaskGetTickCount() - xDHCPData.xDHCPTxTime ) > xDHCPData.xDHCPTxPeriod )
{
if( xARPHadIPClash == pdFALSE )
{
/* ARP OK. proceed. */
iptraceDHCP_SUCCEDEED( xDHCPData.ulOfferedIPAddress );
/* Auto-IP succeeded, the default configured IP-address will
be used. Now call vIPNetworkUpCalls() to send the
network-up event and start the ARP timer. */
vIPNetworkUpCalls( );
xDHCPData.eDHCPState = eNotUsingLeasedAddress;
}
else
{
/* ARP clashed - try another IP address. */
prvPrepareLinkLayerIPLookUp();
/* Setting an IP address manually so set to not using leased
address mode. */
xDHCPData.eDHCPState = eGetLinkLayerAddress;
}
}
break;
#endif /* ipconfigDHCP_FALL_BACK_AUTO_IP */
case eLeasedAddress :
/* Resend the request at the appropriate time to renew the lease. */
prvCreateDHCPSocket();
if( xDHCPData.xDHCPSocket != NULL )
{
xDHCPData.xDHCPTxTime = xTaskGetTickCount();
xDHCPData.xDHCPTxPeriod = dhcpINITIAL_DHCP_TX_PERIOD;
prvSendDHCPRequest( );
xDHCPData.eDHCPState = eWaitingAcknowledge;
/* From now on, we should be called more often */
vIPReloadDHCPTimer( dhcpINITIAL_TIMER_PERIOD );
}
break;
case eNotUsingLeasedAddress:
vIPSetDHCPTimerEnableState( pdFALSE );
break;
default:
break;
}
if( xGivingUp != pdFALSE )
{
/* xGivingUp became true either because of a time-out, or because
xApplicationDHCPHook() returned another value than 'eDHCPContinue',
meaning that the conversion is canceled from here. */
/* Revert to static IP address. */
taskENTER_CRITICAL();
{
*ipLOCAL_IP_ADDRESS_POINTER = xNetworkAddressing.ulDefaultIPAddress;
iptraceDHCP_REQUESTS_FAILED_USING_DEFAULT_IP_ADDRESS( xNetworkAddressing.ulDefaultIPAddress );
}
taskEXIT_CRITICAL();
xDHCPData.eDHCPState = eNotUsingLeasedAddress;
vIPSetDHCPTimerEnableState( pdFALSE );
/* DHCP failed, the default configured IP-address will be used. Now
call vIPNetworkUpCalls() to send the network-up event and start the ARP
timer. */
vIPNetworkUpCalls( );
/* Test if socket was indeed created. */
if( xDHCPData.xDHCPSocket != NULL )
{
/* Close socket to ensure packets don't queue on it. */
vSocketClose( xDHCPData.xDHCPSocket );
xDHCPData.xDHCPSocket = NULL;
}
}
}