void vDHCPProcess()

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;
		}
	}
}