/***************************************************************************** Function: void DHCPTask(void) Summary: Performs periodic DHCP tasks for all interfaces. Description: This function performs any periodic tasks requied by the DHCP module, such as sending and receiving messages involved with obtaining and maintaining a lease. Precondition: None Parameters: None Returns: None ***************************************************************************/ void DHCPTask(void) { BYTE i; for(i = 0; i < NETWORK_INTERFACES; i++) { LoadState(i); switch(DHCPClient.smState) { case SM_DHCP_DISABLED: // When the module is disabled, do absolutely nothing break; case SM_DHCP_GET_SOCKET: // Open a socket to send and receive broadcast messages on DHCPClient.hDHCPSocket = UDPOpen(DHCP_CLIENT_PORT, NULL, DHCP_SERVER_PORT); if(DHCPClient.hDHCPSocket == INVALID_UDP_SOCKET) break; DHCPClient.smState = SM_DHCP_SEND_DISCOVERY; // No break case SM_DHCP_SEND_DISCOVERY: // Assume default IP Lease time of 60 seconds. // This should be minimum possible to make sure that if the // server did not specify lease time, we try again after this // minimum time. DHCPClient.dwLeaseTime = 60; DHCPClient.validValues.val = 0x00; DHCPClient.flags.bits.bIsBound = FALSE; DHCPClient.flags.bits.bOfferReceived = FALSE; // No point in wasting time transmitting a discovery if we are // unlinked. No one will see it. if(!MACIsLinked()) break; // Ensure transmitter is ready to accept data if(UDPIsPutReady(DHCPClient.hDHCPSocket) < 300u) break; // Toggle the BOOTP Broadcast flag to ensure compatibility with // bad DHCP servers that don't know how to handle broadcast // responses. This results in the next discovery attempt to be // made using the opposite mode. DHCPClient.flags.bits.bUseUnicastMode ^= 1; // Ensure that we transmit to the broadcast IP and MAC addresses // The UDP Socket remembers who it was last talking to memset((void*)&UDPSocketInfo[DHCPClient.hDHCPSocket].remoteNode, 0xFF, sizeof(UDPSocketInfo[0].remoteNode)); // Send the DHCP Discover broadcast _DHCPSend(DHCP_DISCOVER_MESSAGE, FALSE); // Start a timer and begin looking for a response DHCPClient.dwTimer = TickGet(); DHCPClient.smState = SM_DHCP_GET_OFFER; break; case SM_DHCP_GET_OFFER: // Check to see if a packet has arrived if(UDPIsGetReady(DHCPClient.hDHCPSocket) < 250u) { // Go back and transmit a new discovery if we didn't get an offer after 2 seconds if(TickGet() - DHCPClient.dwTimer >= DHCP_TIMEOUT) DHCPClient.smState = SM_DHCP_SEND_DISCOVERY; break; } // Let the DHCP server module know that there is a DHCP server // on this network DHCPClient.flags.bits.bDHCPServerDetected = TRUE; // Check to see if we received an offer if(_DHCPReceive() != DHCP_OFFER_MESSAGE) break; DHCPClient.smState = SM_DHCP_SEND_REQUEST; // No break case SM_DHCP_SEND_REQUEST: if(UDPIsPutReady(DHCPClient.hDHCPSocket) < 258u) break; // Ensure that we transmit to the broadcast IP and MAC addresses // The UDP Socket remembers who it was last talking to, so // we must set this back to the broadcast address since the // current socket values are the unicast addresses of the DHCP // server. memset((void*)&UDPSocketInfo[DHCPClient.hDHCPSocket].remoteNode, 0xFF, sizeof(UDPSocketInfo[0].remoteNode)); // Send the DHCP request message _DHCPSend(DHCP_REQUEST_MESSAGE, FALSE); // Start a timer and begin looking for a response DHCPClient.dwTimer = TickGet(); DHCPClient.smState = SM_DHCP_GET_REQUEST_ACK; break; case SM_DHCP_GET_REQUEST_ACK: // Check to see if a packet has arrived if(UDPIsGetReady(DHCPClient.hDHCPSocket) < 250u) { // Go back and transmit a new discovery if we didn't get an ACK after 2 seconds if(TickGet() - DHCPClient.dwTimer >= DHCP_TIMEOUT) DHCPClient.smState = SM_DHCP_SEND_DISCOVERY; break; } // Check to see if we received an offer switch(_DHCPReceive()) { case DHCP_ACK_MESSAGE: UDPClose(DHCPClient.hDHCPSocket); DHCPClient.hDHCPSocket = INVALID_UDP_SOCKET; DHCPClient.dwTimer = TickGet(); DHCPClient.smState = SM_DHCP_BOUND; DHCPClient.flags.bits.bEvent = 1; DHCPClient.flags.bits.bIsBound = TRUE; if(DHCPClient.validValues.bits.IPAddress) AppConfig.MyIPAddr = DHCPClient.tempIPAddress; if(DHCPClient.validValues.bits.Mask) AppConfig.MyMask = DHCPClient.tempMask; if(DHCPClient.validValues.bits.Gateway) AppConfig.MyGateway = DHCPClient.tempGateway; #if defined(STACK_USE_DNS) if(DHCPClient.validValues.bits.DNS) AppConfig.PrimaryDNSServer.Val = DHCPClient.tempDNS.Val; AppConfig.SecondaryDNSServer.Val = 0x00000000ul; if(DHCPClient.validValues.bits.DNS2) AppConfig.SecondaryDNSServer.Val = DHCPClient.tempDNS2.Val; #endif //if(DHCPClient.validValues.bits.HostName) // memcpy(AppConfig.NetBIOSName, (void*)DHCPClient.tempHostName, sizeof(AppConfig.NetBIOSName)); break; case DHCP_NAK_MESSAGE: DHCPClient.smState = SM_DHCP_SEND_DISCOVERY; break; } break; case SM_DHCP_BOUND: if(TickGet() - DHCPClient.dwTimer < TICK_SECOND) break; // Check to see if our lease is still valid, if so, decrement lease // time if(DHCPClient.dwLeaseTime >= 2ul) { DHCPClient.dwTimer += TICK_SECOND; DHCPClient.dwLeaseTime--; break; } // Open a socket to send and receive DHCP messages on DHCPClient.hDHCPSocket = UDPOpen(DHCP_CLIENT_PORT, NULL, DHCP_SERVER_PORT); if(DHCPClient.hDHCPSocket == INVALID_UDP_SOCKET) break; DHCPClient.smState = SM_DHCP_SEND_RENEW; // No break case SM_DHCP_SEND_RENEW: case SM_DHCP_SEND_RENEW2: case SM_DHCP_SEND_RENEW3: if(UDPIsPutReady(DHCPClient.hDHCPSocket) < 258u) break; // Send the DHCP request message _DHCPSend(DHCP_REQUEST_MESSAGE, TRUE); DHCPClient.flags.bits.bOfferReceived = FALSE; // Start a timer and begin looking for a response DHCPClient.dwTimer = TickGet(); DHCPClient.smState++; break; case SM_DHCP_GET_RENEW_ACK: case SM_DHCP_GET_RENEW_ACK2: case SM_DHCP_GET_RENEW_ACK3: // Check to see if a packet has arrived if(UDPIsGetReady(DHCPClient.hDHCPSocket) < 250u) { // Go back and transmit a new discovery if we didn't get an ACK after 2 seconds if(TickGet() - DHCPClient.dwTimer >= DHCP_TIMEOUT) { if(++DHCPClient.smState > SM_DHCP_GET_RENEW_ACK3) DHCPClient.smState = SM_DHCP_SEND_DISCOVERY; } break; } // Check to see if we received an offer switch(_DHCPReceive()) { case DHCP_ACK_MESSAGE: UDPClose(DHCPClient.hDHCPSocket); DHCPClient.hDHCPSocket = INVALID_UDP_SOCKET; DHCPClient.dwTimer = TickGet(); DHCPClient.smState = SM_DHCP_BOUND; DHCPClient.flags.bits.bEvent = 1; break; case DHCP_NAK_MESSAGE: DHCPClient.smState = SM_DHCP_SEND_DISCOVERY; break; } break; } } }
/***************************************************************************** Function: void DHCPTask(void) Summary: Performs periodic DHCP tasks. Description: This function performs any periodic tasks requied by the DHCP module, such as sending and receiving messages involved with obtaining and maintaining a lease. Precondition: None Parameters: None Returns: None ***************************************************************************/ void DHCPTask(void) { static TICK eventTime; switch(smDHCPState) { case SM_DHCP_GET_SOCKET: // Open a socket to send and receive broadcast messages on DHCPSocket = UDPOpen(DHCP_CLIENT_PORT, NULL, DHCP_SERVER_PORT); if(DHCPSocket == INVALID_UDP_SOCKET) break; smDHCPState = SM_DHCP_SEND_DISCOVERY; // No break case SM_DHCP_SEND_DISCOVERY: if(UDPIsPutReady(DHCPSocket) < 300u) break; // Ensure that we transmit to the broadcast IP and MAC addresses // The UDP Socket remembers who it was last talking to memset((void*)&UDPSocketInfo[DHCPSocket].remoteNode, 0xFF, sizeof(UDPSocketInfo[DHCPSocket].remoteNode)); // Assume default IP Lease time of 60 seconds. // This should be minimum possible to make sure that if // server did not specify lease time, we try again after this minimum time. DHCPLeaseTime.Val = 60; ValidValues.Val = 0x00; DHCPBindCount = 0; DHCPFlags.bits.bIsBound = FALSE; DHCPFlags.bits.bOfferReceived = FALSE; // Send the DHCP Discover broadcast _DHCPSend(DHCP_DISCOVER_MESSAGE, FALSE); // Start a timer and begin looking for a response eventTime = TickGet(); smDHCPState = SM_DHCP_GET_OFFER; break; case SM_DHCP_GET_OFFER: // Check to see if a packet has arrived if(UDPIsGetReady(DHCPSocket) < 250u) { // Go back and transmit a new discovery if we didn't get an offer after 2 seconds if(TickGet() - eventTime >= DHCP_TIMEOUT) smDHCPState = SM_DHCP_SEND_DISCOVERY; break; } // Let the DHCP server module know that there is a DHCP server // on this network DHCPFlags.bits.bDHCPServerDetected = TRUE; // Check to see if we received an offer if(_DHCPReceive() != DHCP_OFFER_MESSAGE) break; smDHCPState = SM_DHCP_SEND_REQUEST; // No break case SM_DHCP_SEND_REQUEST: if(UDPIsPutReady(DHCPSocket) < 258u) break; // Send the DHCP request message _DHCPSend(DHCP_REQUEST_MESSAGE, FALSE); // Start a timer and begin looking for a response eventTime = TickGet(); smDHCPState = SM_DHCP_GET_REQUEST_ACK; break; case SM_DHCP_GET_REQUEST_ACK: // Check to see if a packet has arrived if(UDPIsGetReady(DHCPSocket) < 250u) { // Go back and transmit a new discovery if we didn't get an ACK after 2 seconds if(TickGet() - eventTime >= DHCP_TIMEOUT) smDHCPState = SM_DHCP_SEND_DISCOVERY; break; } // Check to see if we received an offer switch(_DHCPReceive()) { case DHCP_ACK_MESSAGE: UDPClose(DHCPSocket); DHCPSocket = INVALID_UDP_SOCKET; eventTime = TickGet(); smDHCPState = SM_DHCP_BOUND; DHCPFlags.bits.bIsBound = TRUE; DHCPBindCount++; if(ValidValues.bits.IPAddress) AppConfig.MyIPAddr = tempIPAddress; if(ValidValues.bits.Mask) AppConfig.MyMask = tempMask; if(ValidValues.bits.Gateway) AppConfig.MyGateway = tempGateway; #if defined(STACK_USE_DNS) if(ValidValues.bits.DNS) AppConfig.PrimaryDNSServer = tempDNS; AppConfig.SecondaryDNSServer.Val = ValidValues.bits.DNS2 ? tempDNS2.Val : 0x00000000ul; #endif // if(ValidValues.bits.HostName) // memcpy(AppConfig.NetBIOSName, (void*)tempHostName, sizeof(AppConfig.NetBIOSName)); break; case DHCP_NAK_MESSAGE: smDHCPState = SM_DHCP_SEND_DISCOVERY; break; } break; case SM_DHCP_BOUND: if(TickGet() - eventTime < TICK_SECOND) break; // Check to see if our lease is still valid, if so, decrement lease // time if(DHCPLeaseTime.Val >= 2ul) { eventTime += TICK_SECOND; DHCPLeaseTime.Val--; break; } // Open a socket to send and receive DHCP messages on DHCPSocket = UDPOpen(DHCP_CLIENT_PORT, NULL, DHCP_SERVER_PORT); if(DHCPSocket == INVALID_UDP_SOCKET) break; smDHCPState = SM_DHCP_SEND_RENEW; // No break case SM_DHCP_SEND_RENEW: case SM_DHCP_SEND_RENEW2: case SM_DHCP_SEND_RENEW3: if(UDPIsPutReady(DHCPSocket) < 258u) break; // Send the DHCP request message _DHCPSend(DHCP_REQUEST_MESSAGE, TRUE); DHCPFlags.bits.bOfferReceived = FALSE; // Start a timer and begin looking for a response eventTime = TickGet(); smDHCPState++; break; case SM_DHCP_GET_RENEW_ACK: case SM_DHCP_GET_RENEW_ACK2: case SM_DHCP_GET_RENEW_ACK3: // Check to see if a packet has arrived if(UDPIsGetReady(DHCPSocket) < 250u) { // Go back and transmit a new discovery if we didn't get an ACK after 2 seconds if(TickGet() - eventTime >= DHCP_TIMEOUT) { if(++smDHCPState > SM_DHCP_GET_RENEW_ACK3) smDHCPState = SM_DHCP_SEND_DISCOVERY; } break; } // Check to see if we received an offer switch(_DHCPReceive()) { case DHCP_ACK_MESSAGE: UDPClose(DHCPSocket); DHCPSocket = INVALID_UDP_SOCKET; eventTime = TickGet(); DHCPBindCount++; smDHCPState = SM_DHCP_BOUND; break; case DHCP_NAK_MESSAGE: smDHCPState = SM_DHCP_SEND_DISCOVERY; break; } break; // Handle SM_DHCP_DISABLED state by doing nothing. Default case needed // to supress compiler diagnostic. default: break; } }
/********************************************************************* * Function: void DHCPTask(void) * * PreCondition: DHCPInit() is already called AND * IPGetHeader() is called with * IPFrameType == IP_PROT_UDP * * Input: None * * Output: None * * Side Effects: None * * Overview: Fetches pending UDP packet from MAC receive buffer * and dispatches it appropriate UDP socket. * If not UDP socket is matched, UDP packet is * silently discarded. * * Note: Caller must make sure that MAC receive buffer * access pointer is set to begining of UDP packet. * Required steps before calling this function is: * * If ( MACIsRxReady() ) * { * MACGetHeader() * If MACFrameType == IP * IPGetHeader() * if ( IPFrameType == IP_PROT_UDP ) * Call DHCPTask() * ... ********************************************************************/ void DHCPTask(void) { NODE_INFO DHCPServerNode; static TICK lastTryTick; BYTE DHCPRecvReturnValue; switch(smDHCPState) { case SM_DHCP_INIT: DHCPServerNode.MACAddr.v[0] = 0xff; DHCPServerNode.MACAddr.v[1] = 0xff; DHCPServerNode.MACAddr.v[2] = 0xff; DHCPServerNode.MACAddr.v[3] = 0xff; DHCPServerNode.MACAddr.v[4] = 0xff; DHCPServerNode.MACAddr.v[5] = 0xff; DHCPServerNode.IPAddr.Val = 0xffffffff; tempIPAddress.Val = 0x0; DHCPSocket = UDPOpen(DHCP_CLIENT_PORT, &DHCPServerNode, DHCP_SERVER_PORT); lastTryTick = TickGet(); smDHCPState = SM_DHCP_RESET_WAIT; /* No break */ case SM_DHCP_RESET_WAIT: if ( TickGetDiff(TickGet(), lastTryTick) >= (TICK_SECOND/(TICK)5) ) smDHCPState = SM_DHCP_BROADCAST; break; case SM_DHCP_BROADCAST: /* * If we have already obtained some IP address, renew it. */ if ( tempIPAddress.Val != 0x00000 ) { smDHCPState = SM_DHCP_REQUEST; } else if ( UDPIsPutReady(DHCPSocket) ) { /* * To minimize code requirement, user must make sure that * above call will be successful by making at least one * UDP socket available. * Usually this will be the case, given that DHCP will be * the first one to use UDP socket. * * Also, we will not check for transmitter readiness, * we assume it to be ready. */ _DHCPSend(DHCP_DISCOVER_MESSAGE); // DEBUG USARTPut('\n'); USARTPut('\r'); USARTPut('D'); lastTryTick = TickGet(); smDHCPState = SM_DHCP_DISCOVER; } break; case SM_DHCP_DISCOVER: if ( TickGetDiff(TickGet(), lastTryTick) >= DHCP_TIMEOUT ) { smDHCPState = SM_DHCP_BROADCAST; //return; } if ( UDPIsGetReady(DHCPSocket) ) { // DEBUG USARTPut('R'); if ( _DHCPReceive() == DHCP_OFFER_MESSAGE ) { // DEBUG USARTPut('O'); smDHCPState = SM_DHCP_REQUEST; } else break; } else break; case SM_DHCP_REQUEST: if ( UDPIsPutReady(DHCPSocket) ) { _DHCPSend(DHCP_REQUEST_MESSAGE); lastTryTick = TickGet(); smDHCPState = SM_DHCP_BIND; } break; case SM_DHCP_BIND: if ( UDPIsGetReady(DHCPSocket) ) { DHCPRecvReturnValue = _DHCPReceive(); if ( DHCPRecvReturnValue == DHCP_NAK_MESSAGE ) { // (RSS) NAK recieved. DHCP server didn't like our DHCP Request format USARTPut('n'); smDHCPState = SM_DHCP_REQUEST; // Request again } else if ( DHCPRecvReturnValue == DHCP_ACK_MESSAGE ) { // DEBUG USARTPut('B'); /* * Once DCHP is successful, release the UDP socket * This will ensure that UDP layer discards any further * DHCP related packets. */ UDPClose(DHCPSocket); DHCPSocket = INVALID_UDP_SOCKET; lastTryTick = TickGet(); smDHCPState = SM_DHCP_BOUND; MY_IP_BYTE1 = tempIPAddress.v[0]; MY_IP_BYTE2 = tempIPAddress.v[1]; MY_IP_BYTE3 = tempIPAddress.v[2]; MY_IP_BYTE4 = tempIPAddress.v[3]; MY_MASK_BYTE1 = tempMask.v[0]; MY_MASK_BYTE2 = tempMask.v[1]; MY_MASK_BYTE3 = tempMask.v[2]; MY_MASK_BYTE4 = tempMask.v[3]; MY_GATE_BYTE1 = tempGateway.v[0]; MY_GATE_BYTE2 = tempGateway.v[1]; MY_GATE_BYTE3 = tempGateway.v[2]; MY_GATE_BYTE4 = tempGateway.v[3]; DHCPState.bits.bIsBound = TRUE; DHCPBindCount++; return; } } else if ( TickGetDiff(TickGet(), lastTryTick) >= DHCP_TIMEOUT ) { USARTPut('t'); smDHCPState = SM_DHCP_BROADCAST; } break; case SM_DHCP_BOUND: /* * Keep track of how long we use this IP configuration. * When lease period expires, renew the configuration. */ if ( TickGetDiff(TickGet(), lastTryTick) >= TICK_SECOND ) { DHCPLeaseTime.Val -= 1; if ( DHCPLeaseTime.Val == 0 ) smDHCPState = SM_DHCP_INIT; lastTryTick = TickGet(); } } }
/********************************************************************* * Function: void DHCPTask(void) * * PreCondition: DHCPInit() is already called AND * IPGetHeader() is called with * IPFrameType == IP_PROT_UDP * * Input: None * * Output: None * * Side Effects: None * * Overview: Fetches pending UDP packet from MAC receive buffer * and dispatches it appropriate UDP socket. * If not UDP socket is matched, UDP packet is * silently discarded. * * Note: Caller must make sure that MAC receive buffer * access pointer is set to begining of UDP packet. * Required steps before calling this function is: * * If ( MACIsRxReady() ) * { * MACGetHeader() * If MACFrameType == IP * IPGetHeader() * if ( IPFrameType == IP_PROT_UDP ) * Call DHCPTask() * ... ********************************************************************/ void DHCPTask(void) { NODE_INFO DHCPServerNode; static TICKTYPE lastTryTick; BYTE DHCPRecvReturnValue; TICKTYPE tickDiff; //static int8 debugLastState; //debugLastState = smDHCPState; switch(smDHCPState) { case SM_DHCP_INIT_FIRST_TIME: tempIPAddress.Val = 0x0; // smDHCPState = SM_DHCP_INIT; // State automatically changes /* No break */ case SM_DHCP_INIT: //debug(debug_putc,"\r\n\r\nDHCP: INIT"); //dsr add 061404 //MY_IP=0; DHCPServerNode.MACAddr.v[0] = 0xff; DHCPServerNode.MACAddr.v[1] = 0xff; DHCPServerNode.MACAddr.v[2] = 0xff; DHCPServerNode.MACAddr.v[3] = 0xff; DHCPServerNode.MACAddr.v[4] = 0xff; DHCPServerNode.MACAddr.v[5] = 0xff; DHCPServerNode.IPAddr.Val = 0xffffffff; DHCPSocket = UDPOpen(DHCP_CLIENT_PORT, &DHCPServerNode, DHCP_SERVER_PORT); lastTryTick = TickGet(); smDHCPState = SM_DHCP_RESET_WAIT; /* No break */ case SM_DHCP_RESET_WAIT: if ( TickGetDiff(TickGet(), lastTryTick) >= (TICKS_PER_SECOND/5) ) //debug(debug_putc,"\r\n\r\nDHCP: RESET_WAIT"); smDHCPState = SM_DHCP_BROADCAST; break; case SM_DHCP_BROADCAST: // Assume default IP Lease time of 60 seconds. // This should be minimum possible to make sure that if // server did not specify lease time, we try again after this minimum time. DHCPLeaseTime.Val = 60; // If we have already obtained some IP address, renew it. if(DHCPState.bits.bIsBound) { smDHCPState = SM_DHCP_REQUEST; } else if ( UDPIsPutReady(DHCPSocket) ) { // To minimize code requirement, user must make sure that // above call will be successful by making at least one // UDP socket available. // Usually this will be the case, given that DHCP will be // the first one to use UDP socket. // Also, we will not check for transmitter readiness, // we assume it to be ready. _DHCPSend(DHCP_DISCOVER_MESSAGE); ValidValues.Val = 0x00; lastTryTick = TickGet(); smDHCPState = SM_DHCP_DISCOVER; } break; case SM_DHCP_DISCOVER: if ( TickGetDiff(TickGet(), lastTryTick) >= DHCP_TIMEOUT ) { //debug(debug_putc,"\r\n\r\nDHCP: DISCOVER TO BROADCAST"); smDHCPState = SM_DHCP_BROADCAST; //return; } if ( UDPIsGetReady(DHCPSocket) ) { if ( _DHCPReceive() == DHCP_OFFER_MESSAGE ) { //debug(debug_putc,"\r\n\r\nDHCP: DISCOVER BACK TO REQUEST"); smDHCPState = SM_DHCP_REQUEST; } else break; } else break; case SM_DHCP_REQUEST: if ( UDPIsPutReady(DHCPSocket) ) { _DHCPSend(DHCP_REQUEST_MESSAGE); lastTryTick = TickGet(); smDHCPState = SM_DHCP_BIND; //debug(debug_putc,"\r\n\r\nDHCP: REQUEST TO BIND"); } break; case SM_DHCP_BIND: if ( UDPIsGetReady(DHCPSocket) ) { DHCPRecvReturnValue = _DHCPReceive(); if ( DHCPRecvReturnValue == DHCP_NAK_MESSAGE ) { // (RSS) NAK recieved. DHCP server didn't like our DHCP Request format DHCPReset(); // Start all over again return; } else if ( DHCPRecvReturnValue == DHCP_ACK_MESSAGE ) { // Once DCHP is successful, release the UDP socket // This will ensure that UDP layer discards any further DHCP related packets. UDPClose(DHCPSocket); DHCPSocket = INVALID_UDP_SOCKET; lastTryTick = TickGet(); smDHCPState = SM_DHCP_BOUND; if(ValidValues.bits.IPAddress) AppConfig.MyIPAddr = tempIPAddress; if(ValidValues.bits.Mask) AppConfig.MyMask = tempMask; if(ValidValues.bits.Gateway) AppConfig.MyGateway = tempGateway; #if STACK_USE_DNS if(ValidValues.bits.DNS) AppConfig.PrimaryDNSServer = tempDNS; #endif // if(ValidValues.bits.HostName) // memcpy(AppConfig.NetBIOSName, (void*)tempHostName, sizeof(AppConfig.NetBIOSName)); DHCPState.bits.bIsBound = TRUE; DHCPBindCount++; return; } } else if ( TickGetDiff(TickGet(), lastTryTick) >= DHCP_TIMEOUT ) smDHCPState = SM_DHCP_BROADCAST; break; case SM_DHCP_BOUND: // Keep track of how long we use this IP configuration. // When lease period expires, renew the configuration. tickDiff = TickGetDiff(TickGet(), lastTryTick); if(tickDiff >= TICKS_PER_SECOND) { do { DHCPLeaseTime.Val--; tickDiff -= TICKS_PER_SECOND; if(DHCPLeaseTime.Val == 0u) smDHCPState = SM_DHCP_INIT; } while(tickDiff >= TICKS_PER_SECOND); lastTryTick = TickGet() - tickDiff; } } /*if (debugLastState != smDHCPState) { debug_dhcp("\r\nDHCP TASK - ", ); DebugDHCPDisplayState(debugLastState); debug_dhcp(" -> "); DebugDHCPDisplayState(smDHCPState); }*/ }
/** * Fetches pending UDP packet from MAC receive buffer and dispatches it appropriate UDP socket. * If not UDP socket is matched, UDP packet is silently discarded. * Note: Caller must make sure that MAC receive buffer * access pointer is set to begining of UDP packet. * Required steps before calling this function is: * * If ( MACIsRxReady() ) * { * MACGetHeader() * If MACFrameType == IP * IPGetHeader() * if ( IPFrameType == IP_PROT_UDP ) * Call DHCPTask() * ... * } * * @@preCondition DHCPInit() is already called AND IPGetHeader() is called with * IPFrameType == IP_PROT_UDP */ void DHCPTask(void) { NODE_INFO DHCPServerNode; static TICK16 lastTryTick; BYTE DHCPRecvReturnValue; static BYTE broadcastCount; switch(smDHCPState) { case SM_DHCP_INIT_FIRST_TIME: tempIPAddress.Val = 0x0; // smDHCPState = SM_DHCP_INIT; // State automatically changes /* No break */ case SM_DHCP_INIT: broadcastCount = 3; DHCPServerNode.MACAddr.v[0] = 0xff; DHCPServerNode.MACAddr.v[1] = 0xff; DHCPServerNode.MACAddr.v[2] = 0xff; DHCPServerNode.MACAddr.v[3] = 0xff; DHCPServerNode.MACAddr.v[4] = 0xff; DHCPServerNode.MACAddr.v[5] = 0xff; DHCPServerNode.IPAddr.Val = 0xffffffff; DHCPSocket = UDPOpen(DHCP_CLIENT_PORT, &DHCPServerNode, DHCP_SERVER_PORT); if( DHCPSocket == INVALID_UDP_SOCKET ) { #if (DEBUG_DHCP >= LOG_ERROR) debugPutMsg(7); //@mxd:7:Could not open UDP socket #endif break; } lastTryTick = TickGet16bit(); smDHCPState = SM_DHCP_RESET_WAIT; /* No break */ case SM_DHCP_RESET_WAIT: //More then 200ms has passed if ( TickGetDiff16bit(lastTryTick) >= ((TICK16)TICKS_PER_SECOND / (TICK16)5) ) smDHCPState = SM_DHCP_BROADCAST; break; case SM_DHCP_BROADCAST: // Assume default IP Lease time of 60 seconds. // This should be minimum possible to make sure that if // server did not specify lease time, we try again after this minimum time. DHCPLeaseTime.Val = 60; //After a certian number of tries, give up, and assign a static IP address if (broadcastCount-- == 0) { //Once DCHP is successful, release the UDP socket //This will ensure that UDP layer discards any further DHCP related packets. UDPClose(DHCPSocket); DHCPSocket = INVALID_UDP_SOCKET; smDHCPState = SM_DHCP_BOUND; DHCPState.bits.bIsBound = TRUE; DHCPBindCount++; //Disable DHCP. No more attempts will be made to obtain a IP from the DHCP server, except //if the cable is unplugged. DHCPState.bits.bStaticIP = TRUE; MY_IP_BYTE1 = MY_STATIC_IP_BYTE1; MY_IP_BYTE2 = MY_STATIC_IP_BYTE2; MY_IP_BYTE3 = MY_STATIC_IP_BYTE3; MY_IP_BYTE4 = MY_STATIC_IP_BYTE4; #if (DEBUG_DHCP >= LOG_INFO) debugPutMsg(10); //@mxd:10:Maxumum Broadcast tries, assigned static IP address #endif return; } // If we have already obtained some IP address, renew it. if(DHCPState.bits.bIsBound) { smDHCPState = SM_DHCP_REQUEST; } else if ( UDPIsPutReady(DHCPSocket) ) { // To minimize code requirement, user must make sure that // above call will be successful by making at least one // UDP socket available. // Usually this will be the case, given that DHCP will be // the first one to use UDP socket. // Also, we will not check for transmitter readiness, // we assume it to be ready. _DHCPSend(DHCP_DISCOVER_MESSAGE); ValidValues.Val = 0x00; // DEBUG #if (DEBUG_DHCP >= LOG_INFO) debugPutMsg(1); //@mxd:1:Broadcast #endif lastTryTick = TickGet16bit(); smDHCPState = SM_DHCP_DISCOVER; } else { // DEBUG #if (DEBUG_DHCP >= LOG_INFO) debugPutMsg(8); //@mxd:8:Can not Broadcase, UDP Not ready! #endif } break; case SM_DHCP_DISCOVER: if ( TickGetDiff16bit(lastTryTick) >= DHCP_TIMEOUT) //Timeout has expired { smDHCPState = SM_DHCP_BROADCAST; // DEBUG #if (DEBUG_DHCP >= LOG_INFO) debugPutMsg(9); //@mxd:9:Discover time out #endif break; } if ( UDPIsGetReady(DHCPSocket) ) { // DEBUG #if (DEBUG_DHCP >= LOG_INFO) debugPutMsg(2); //@mxd:2:Discover #endif if ( _DHCPReceive() == DHCP_OFFER_MESSAGE ) { // DEBUG #if (DEBUG_DHCP >= LOG_INFO) debugPutMsg(3); //@mxd:3:Offer Message #endif smDHCPState = SM_DHCP_REQUEST; } else break; } else break; case SM_DHCP_REQUEST: if ( UDPIsPutReady(DHCPSocket) ) { _DHCPSend(DHCP_REQUEST_MESSAGE); lastTryTick = TickGet16bit(); smDHCPState = SM_DHCP_BIND; // DEBUG #if (DEBUG_DHCP >= LOG_INFO) debugPutMsg(12); //@mxd:12:Sending Request #endif } break; case SM_DHCP_BIND: if ( UDPIsGetReady(DHCPSocket) ) { DHCPRecvReturnValue = _DHCPReceive(); if ( DHCPRecvReturnValue == DHCP_NAK_MESSAGE ) { // (RSS) NAK recieved. DHCP server didn't like our DHCP Request (format wrong/IP address allocated to someone else/outside IP pool) #if (DEBUG_DHCP >= LOG_WARN) debugPutMsg(4); //@mxd:4:NAK recieved (RSS). DHCP server didn't like our DHCP Request format #endif DHCPReset(); // Start all over again return; } else if ( DHCPRecvReturnValue == DHCP_ACK_MESSAGE ) { // DEBUG #if (DEBUG_DHCP >= LOG_INFO) debugPutMsg(5); //@mxd:5:ACK Received #endif // Once DCHP is successful, release the UDP socket // This will ensure that UDP layer discards any further DHCP related packets. UDPClose(DHCPSocket); DHCPSocket = INVALID_UDP_SOCKET; lastTryTick = TickGet16bit(); smDHCPState = SM_DHCP_BOUND; if(ValidValues.bits.IPAddress) { MY_IP_BYTE1 = tempIPAddress.v[0]; MY_IP_BYTE2 = tempIPAddress.v[1]; MY_IP_BYTE3 = tempIPAddress.v[2]; MY_IP_BYTE4 = tempIPAddress.v[3]; } if(ValidValues.bits.Mask) { MY_MASK_BYTE1 = tempMask.v[0]; MY_MASK_BYTE2 = tempMask.v[1]; MY_MASK_BYTE3 = tempMask.v[2]; MY_MASK_BYTE4 = tempMask.v[3]; } if(ValidValues.bits.Gateway) { MY_GATE_BYTE1 = tempGateway.v[0]; MY_GATE_BYTE2 = tempGateway.v[1]; MY_GATE_BYTE3 = tempGateway.v[2]; MY_GATE_BYTE4 = tempGateway.v[3]; } #if defined(STACK_USE_DNS) if(ValidValues.bits.DNS) { MY_DNS_BYTE1_SET(tempDNS.v[0]); MY_DNS_BYTE2_SET(tempDNS.v[1]); MY_DNS_BYTE3_SET(tempDNS.v[2]); MY_DNS_BYTE4_SET(tempDNS.v[3]); } #endif // if(ValidValues.bits.HostName) // memcpy(AppConfig.NetBIOSName, (void*)tempHostName, sizeof(AppConfig.NetBIOSName)); DHCPState.bits.bIsBound = TRUE; DHCPBindCount++; return; } } else if ( TickGetDiff16bit(lastTryTick) >= DHCP_TIMEOUT ) //Timeout has expired { #if (DEBUG_DHCP >= LOG_WARN) debugPutMsg(6); //@mxd:6:Timeout #endif smDHCPState = SM_DHCP_BROADCAST; } break; case SM_DHCP_BOUND: //If a static IP was assigned, it never times out. Only when the cable is unplugged, will //the DHCP server be reset, and start looking for an IP again. if (DHCPState.bits.bStaticIP) return; // Keep track of how long we use this IP configuration. // When lease period expires, renew the configuration. while ( TickGetDiff16bit(lastTryTick) >= ((TICK16)TICKS_PER_SECOND) ) { DHCPLeaseTime.Val--; //Decrement lease time if ( DHCPLeaseTime.Val == 0 ) { smDHCPState = SM_DHCP_INIT; // DEBUG #if (DEBUG_DHCP >= LOG_INFO) debugPutMsg(11); //@mxd:11:Lease time expired #endif } //Add 1 seconds to lastTryTick - will cause this statement to execute in 1 second again lastTryTick += ((TICK16)TICKS_PER_SECOND); //Add 1 second to lastTryTick } } }