/********************************************************************* * Function: void StackTask(void) * * PreCondition: StackInit() is already called. * * Input: None * * Output: Stack FSM is executed. * * Side Effects: None * * Note: This FSM checks for new incoming packets, * and routes it to appropriate stack components. * It also performs timed operations. * * This function must be called periodically to * ensure timely responses. * ********************************************************************/ void StackTask(void) { WORD dataCount; IP_ADDR tempLocalIP; BYTE cFrameType; BYTE cIPFrameType; #if defined( WF_CS_TRIS ) // This task performs low-level MAC processing specific to the MRF24WB0M MACProcess(); #if defined( STACK_USE_EZ_CONFIG ) && !defined(__18CXX) WFEasyConfigMgr(); #endif #if defined(STACK_USE_DHCP_CLIENT) // Normally, an application would not include DHCP module // if it is not enabled. But in case some one wants to disable // DHCP module at run-time, remember to not clear our IP // address if link is removed. if(AppConfig.Flags.bIsDHCPEnabled) { if(g_DhcpRenew == TRUE) { g_DhcpRenew = FALSE; AppConfig.MyIPAddr.Val = AppConfig.DefaultIPAddr.Val; AppConfig.MyMask.Val = AppConfig.DefaultMask.Val; AppConfig.Flags.bInConfigMode = TRUE; DHCPInit(0); } // DHCP must be called all the time even after IP configuration is // discovered. // DHCP has to account lease expiration time and renew the configuration // time. DHCPTask(); if(DHCPIsBound(0)) AppConfig.Flags.bInConfigMode = FALSE; } #endif // STACK_USE_DHCP_CLIENT #endif #if defined(STACK_USE_DHCP_CLIENT) && !defined(WF_CS_TRIS) // Normally, an application would not include DHCP module // if it is not enabled. But in case some one wants to disable // DHCP module at run-time, remember to not clear our IP // address if link is removed. if(AppConfig.Flags.bIsDHCPEnabled) { static BOOL bLastLinkState = FALSE; BOOL bCurrentLinkState; bCurrentLinkState = MACIsLinked(); if(bCurrentLinkState != bLastLinkState) { bLastLinkState = bCurrentLinkState; if(!bCurrentLinkState) { AppConfig.MyIPAddr.Val = AppConfig.DefaultIPAddr.Val; AppConfig.MyMask.Val = AppConfig.DefaultMask.Val; AppConfig.Flags.bInConfigMode = TRUE; DHCPInit(0); } } // DHCP must be called all the time even after IP configuration is // discovered. // DHCP has to account lease expiration time and renew the configuration // time. DHCPTask(); if(DHCPIsBound(0)) AppConfig.Flags.bInConfigMode = FALSE; } #endif #if defined (STACK_USE_AUTO_IP) AutoIPTasks(); #endif #if defined(STACK_USE_TCP) // Perform all TCP time related tasks (retransmit, send acknowledge, close connection, etc) TCPTick(); #endif #if defined(STACK_USE_UDP) UDPTask(); #endif // Process as many incomming packets as we can while(1) { //if using the random module, generate entropy #if defined(STACK_USE_RANDOM) RandomAdd(remoteNode.MACAddr.v[5]); #endif // We are about to fetch a new packet, make sure that the // UDP module knows that any old RX data it has laying // around will now be gone. #if defined(STACK_USE_UDP) UDPDiscard(); #endif // Fetch a packet (throws old one away, if not thrown away // yet) if(!MACGetHeader(&remoteNode.MACAddr, &cFrameType)) break; // When using a WiFi module, filter out all incoming packets that have // the same source MAC address as our own MAC address. This is to // prevent receiving and passing our own broadcast packets up to other // layers and avoid, for example, having our own gratuitous ARPs get // answered by ourself. #if defined(WF_CS_TRIS) if(memcmp((void*)&remoteNode.MACAddr, (void*)&AppConfig.MyMACAddr, 6) == 0u) continue; #endif // Dispatch the packet to the appropriate handler switch(cFrameType) { case MAC_ARP: ARPProcess(); break; case MAC_IP: if(!IPGetHeader(&tempLocalIP, &remoteNode, &cIPFrameType, &dataCount)) break; #if defined(STACK_USE_ICMP_SERVER) || defined(STACK_USE_ICMP_CLIENT) if(cIPFrameType == IP_PROT_ICMP) { #if defined(STACK_USE_IP_GLEANING) if(AppConfig.Flags.bInConfigMode && AppConfig.Flags.bIsDHCPEnabled) { // According to "IP Gleaning" procedure, // when we receive an ICMP packet with a valid // IP address while we are still in configuration // mode, accept that address as ours and conclude // configuration mode. if(tempLocalIP.Val != 0xffffffff) { AppConfig.Flags.bInConfigMode = FALSE; AppConfig.MyIPAddr = tempLocalIP; } } #endif // Process this ICMP packet if it the destination IP address matches our address or one of the broadcast IP addressees if( (tempLocalIP.Val == AppConfig.MyIPAddr.Val) || (tempLocalIP.Val == 0xFFFFFFFF) || #if defined(STACK_USE_ZEROCONF_LINK_LOCAL) || defined(STACK_USE_ZEROCONF_MDNS_SD) (tempLocalIP.Val == 0xFB0000E0) || #endif (tempLocalIP.Val == ((AppConfig.MyIPAddr.Val & AppConfig.MyMask.Val) | ~AppConfig.MyMask.Val))) { ICMPProcess(&remoteNode, dataCount); } break; } #endif #if defined(STACK_USE_TCP) if(cIPFrameType == IP_PROT_TCP) { TCPProcess(&remoteNode, &tempLocalIP, dataCount); break; } #endif #if defined(STACK_USE_UDP) if(cIPFrameType == IP_PROT_UDP) { // Stop processing packets if we came upon a UDP frame with application data in it if(UDPProcess(&remoteNode, &tempLocalIP, dataCount)) return; } #endif break; } } }
/** * This FSM checks for new incoming packets, and routes it to appropriate * stack components. It also performs timed operations. * * This function must be called periodically called * to make sure that timely response. * * @preCondition StackInit() is already called. * * side affect: Stack FSM is executed. */ void StackTask(void) { static WORD dataCount; #if defined(STACK_USE_ICMP) static BYTE data[MAX_ICMP_DATA_LEN]; static WORD ICMPId; static WORD ICMPSeq; #endif IP_ADDR destIP; //Is filled with the Destination IP address contained in the IP header union { BYTE MACFrameType; BYTE IPFrameType; ICMP_CODE ICMPCode; } type; BOOL lbContinue; do { lbContinue = FALSE; switch(smStack) { case SM_STACK_IDLE: case SM_STACK_MAC: //debugPutGenRomStr(2, (ROM char*)"1"); //@mxd:2:%s //Check if the MAC RX Buffer has any data, and if it does, read the header. //Get the next header from the NIC. The node who sent it's address will be copied to //'remoteNode.MACAddr'. //Header was NOT read if MACGetHeader returned FALSE if ( !MACGetHeader(&remoteNode.MACAddr, &type.MACFrameType) ) { //debugPutGenRomStr(2, (ROM char*)"2"); //@mxd:2:%s //MODIFIED DHCP BEGIN // ADDED #if defined(STACK_USE_DHCP) // Normally, an application would not include DHCP module // if it is not enabled. But in case some one wants to disable // DHCP module at run-time, remember to not clear our IP // address if link is removed. if(STACK_IS_DHCP_ENABLED) { if(!MACIsLinked()) { AppConfig.MyIPAddr.v[0] = MY_DEFAULT_IP_ADDR_BYTE1; AppConfig.MyIPAddr.v[1] = MY_DEFAULT_IP_ADDR_BYTE2; AppConfig.MyIPAddr.v[2] = MY_DEFAULT_IP_ADDR_BYTE3; AppConfig.MyIPAddr.v[3] = MY_DEFAULT_IP_ADDR_BYTE4; AppConfig.MyMask.v[0] = MY_DEFAULT_MASK_BYTE1; AppConfig.MyMask.v[1] = MY_DEFAULT_MASK_BYTE2; AppConfig.MyMask.v[2] = MY_DEFAULT_MASK_BYTE3; AppConfig.MyMask.v[3] = MY_DEFAULT_MASK_BYTE4; DHCPFlags.bits.bDHCPServerDetected = FALSE; stackFlags.bits.bInConfigMode = TRUE; DHCPReset(); } // DHCP must be called all the time even after IP configuration is // discovered. // DHCP has to account lease expiration time and renew the configuration // time. DHCPTask(); if(DHCPIsBound()) stackFlags.bits.bInConfigMode = FALSE; } #endif //MODIFIED DHCP END //MODIFIED DHCP BEGIN // Removed /* #if defined(STACK_USE_DHCP) // Normally, an application would not include DHCP module // if it is not enabled. But in case some one wants to disable // DHCP module at run-time, remember to not clear our IP // address if link is removed. //Set our IP to 0.0.0.0 if all the following are TRUE: // - DHCP is enabled // - MAC is not linked yet (or cable is unplugged) if (STACK_IS_DHCP_ENABLED) { if ( !MACIsLinked() ) { //debugPutGenRomStr(2, (ROM char*)"3"); //@mxd:2:%s #if (DEBUG_STACKTSK >= LOG_INFO) //debugPutMsg(1); //@mxd:1:DHCP Enabled but MAC not linked yet - set IP to 0.0.0.0 #endif //if (stackFlags.bits.bInConfigMode) { //IP address must be 0.0.0.0 before DHCP has obtained a valid IP address MY_IP_BYTE1 = 0; MY_IP_BYTE2 = 0; MY_IP_BYTE3 = 0; MY_IP_BYTE4 = 0; //} stackFlags.bits.bInConfigMode = TRUE; DHCPReset(); } } #endif */ //MODIFIED DHCP END break; //case SM_STACK_IDLE: AND case SM_STACK_MAC: } //debugPutGenRomStr(2, (ROM char*)"4"); //@mxd:2:%s lbContinue = TRUE; if ( type.MACFrameType == MAC_IP ) { smStack = SM_STACK_IP; #if (DEBUG_STACKTSK >= LOG_DEBUG) debugPutMsg(2); //@mxd:2:Reading MAC IP header #endif } else if ( type.MACFrameType == MAC_ARP ) { smStack = SM_STACK_ARP; #if (DEBUG_STACKTSK >= LOG_DEBUG) debugPutMsg(3); //@mxd:3:Reading MAC ARP header #endif } else { MACDiscardRx(); //Discard the contents of the current RX buffer #if (DEBUG_STACKTSK >= LOG_WARN) debugPutMsg(4); //@mxd:4:Unknown MAC header read, MAC Frame Type = 0x%x debugPutByteHex(type.MACFrameType); #endif } break; //case SM_STACK_IDLE: AND case SM_STACK_MAC: case SM_STACK_ARP: if ( ARPProcess() ) smStack = SM_STACK_IDLE; //lbContinue = FALSE; //Removed in latest Microchip TCP/IP stack break; case SM_STACK_IP: if ( IPGetHeader(&destIP, /* Get Destination IP Address as received in IP header */ &remoteNode, &type.IPFrameType, &dataCount) ) { lbContinue = TRUE; if ( type.IPFrameType == IP_PROT_ICMP ) { smStack = SM_STACK_ICMP; #if defined(STACK_USE_IP_GLEANING) if(stackFlags.bits.bInConfigMode && STACK_IS_DHCP_ENABLED) { // Accoriding to "IP Gleaning" procedure, // when we receive an ICMP packet with a valid // IP address while we are still in configuration // mode, accept that address as ours and conclude // configuration mode. if ( destIP.Val != 0xffffffff ) { stackFlags.bits.bInConfigMode = FALSE; MY_IP_BYTE1 = destIP.v[0]; MY_IP_BYTE2 = destIP.v[1]; MY_IP_BYTE3 = destIP.v[2]; MY_IP_BYTE4 = destIP.v[3]; myDHCPBindCount--; } } #endif } #if defined(STACK_USE_TCP) else if ( type.IPFrameType == IP_PROT_TCP ) smStack = SM_STACK_TCP; #endif #if defined(STACK_USE_UDP) else if ( type.IPFrameType == IP_PROT_UDP ) smStack = SM_STACK_UDP; #endif else // Unknown/unsupported higher level protocol { lbContinue = FALSE; MACDiscardRx(); //Discard the contents of the current RX buffer smStack = SM_STACK_IDLE; } } else // Improper IP header version or checksum { MACDiscardRx(); //Discard the contents of the current RX buffer smStack = SM_STACK_IDLE; } break; //case SM_STACK_IP: #if defined(STACK_USE_UDP) case SM_STACK_UDP: if ( UDPProcess(&remoteNode, &destIP, dataCount) ) smStack = SM_STACK_IDLE; //lbContinue = FALSE; //Removed in latest Microchip TCP/IP stack break; //case SM_STACK_UDP: #endif #if defined(STACK_USE_TCP) case SM_STACK_TCP: if ( TCPProcess(&remoteNode, &destIP, dataCount) ) //Will return TRUE if TCPProcess finished it's task, else FALSE smStack = SM_STACK_IDLE; //lbContinue = FALSE; //Removed in latest Microchip TCP/IP stack break; //case SM_STACK_TCP: #endif case SM_STACK_ICMP: smStack = SM_STACK_IDLE; #if defined(STACK_USE_ICMP) if ( dataCount <= (MAX_ICMP_DATA_LEN+9) ) { if ( ICMPGet(&type.ICMPCode, data, (BYTE*)&dataCount, &ICMPId, &ICMPSeq) ) { if ( type.ICMPCode == ICMP_ECHO_REQUEST ) { lbContinue = TRUE; smStack = SM_STACK_ICMP_REPLY; } } } #endif MACDiscardRx(); //Discard the contents of the current RX buffer break; //case SM_STACK_ICMP: #if defined(STACK_USE_ICMP) case SM_STACK_ICMP_REPLY: if ( ICMPIsTxReady() ) { ICMPPut(&remoteNode, ICMP_ECHO_REPLY, data, (BYTE)dataCount, ICMPId, ICMPSeq); smStack = SM_STACK_IDLE; } break; //case SM_STACK_ICMP_REPLY: #endif } //switch(smStack) FAST_USER_PROCESS(); } while(lbContinue); #if defined(STACK_USE_TCP) // Perform timed TCP FSM. TCPTick(); #endif //MODIFIED DHCP BEGIN // Removed this //#if defined(STACK_USE_DHCP) /* * DHCP must be called all the time even after IP configuration is * discovered. * DHCP has to account lease expiration time and renew the configuration * time. */ // DHCPTask(); // if(DHCPIsBound()) // stackFlags.bits.bInConfigMode = FALSE; //#endif //debugPutGenRomStr(2, (ROM char*)"MACTask"); //@mxd:2:%s //Perform routine MAC tasks MACTask(); }
/****************************************************************************** * Function: void StackTask(void) * PreCondition: StackInit() is already called. * Input: None * Output: Stack FSM is executed. * Side Effects: None * Note: This FSM checks for new incoming packets, * and routes it to appropriate stack components. * It also performs timed operations. * This function must be called periodically to * ensure timely responses. ******************************************************************************/ void StackTask(void) { static WORD dataCount; IP_ADDR tempLocalIP; BOOL lbContinue; #if defined(STACK_USE_ICMP) static BYTE data[MAX_ICMP_DATA_LEN]; static WORD ICMPId, ICMPSeq; #endif union { BYTE MACFrameType; BYTE IPFrameType; ICMP_CODE ICMPCode; } type; do { lbContinue = FALSE; switch(smStack) { case SM_STACK_IDLE: case SM_STACK_MAC: if ( !MACGetHeader(&remoteNode.MACAddr, &type.MACFrameType) ) { #if defined(STACK_USE_DHCP) // Normally, an application would not include DHCP module // if it is not enabled. But in case some one wants to disable // DHCP module at run-time, remember to not clear our IP // address if link is removed. if ( AppConfig.Flags.bIsDHCPEnabled ) { if ( !MACIsLinked() ) { AppConfig.MyIPAddr.Val = 0x00000000ul; AppConfig.Flags.bInConfigMode = TRUE; DHCPReset(); } } #endif break; } lbContinue = TRUE; if ( type.MACFrameType == MAC_IP ) smStack = SM_STACK_IP; else if ( type.MACFrameType == MAC_ARP ) smStack = SM_STACK_ARP; else MACDiscardRx(); break; case SM_STACK_ARP: if ( ARPProcess() ) smStack = SM_STACK_IDLE; break; case SM_STACK_IP: if ( IPGetHeader(&tempLocalIP,&remoteNode,&type.IPFrameType,&dataCount) ) { lbContinue = TRUE; if ( type.IPFrameType == IP_PROT_ICMP ) { smStack = SM_STACK_ICMP; #if defined(STACK_USE_IP_GLEANING) if(AppConfig.Flags.bInConfigMode && AppConfig.Flags.bIsDHCPEnabled) { /* * Accoriding to "IP Gleaning" procedure, * when we receive an ICMP packet with a valid * IP address while we are still in configuration * mode, accept that address as ours and conclude * configuration mode. */ if( tempLocalIP.Val != 0xffffffff ) { AppConfig.Flags.bInConfigMode = FALSE; AppConfig.MyIPAddr = tempLocalIP; myDHCPBindCount--; } } #endif } #if defined(STACK_USE_TCP) else if ( type.IPFrameType == IP_PROT_TCP ) smStack = SM_STACK_TCP; #endif #if defined(STACK_USE_UDP) else if ( type.IPFrameType == IP_PROT_UDP ) smStack = SM_STACK_UDP; #endif else // Unknown/unsupported higher level protocol { lbContinue = FALSE; MACDiscardRx(); smStack = SM_STACK_IDLE; } } else // Improper IP header version or checksum { MACDiscardRx(); smStack = SM_STACK_IDLE; } break; #if defined(STACK_USE_UDP) case SM_STACK_UDP: if ( UDPProcess(&remoteNode, &tempLocalIP, dataCount) ) smStack = SM_STACK_IDLE; break; #endif #if defined(STACK_USE_TCP) case SM_STACK_TCP: if ( TCPProcess(&remoteNode, &tempLocalIP, dataCount) ) smStack = SM_STACK_IDLE; break; #endif case SM_STACK_ICMP: smStack = SM_STACK_IDLE; #if defined(STACK_USE_ICMP) if ( dataCount <= (MAX_ICMP_DATA_LEN+8) ) { if ( ICMPGet(&type.ICMPCode,data,(BYTE*)&dataCount,&ICMPId,&ICMPSeq) ) { if ( type.ICMPCode == ICMP_ECHO_REQUEST ) { lbContinue = TRUE; smStack = SM_STACK_ICMP_REPLY; } } } #endif MACDiscardRx(); break; #if defined(STACK_USE_ICMP) case SM_STACK_ICMP_REPLY: if ( ICMPIsTxReady() ) { ICMPPut(&remoteNode,ICMP_ECHO_REPLY,data,(BYTE)dataCount,ICMPId,ICMPSeq); smStack = SM_STACK_IDLE; } break; #endif } } while(lbContinue); #if defined(STACK_USE_TCP) TCPTick(); // Perform timed TCP FSM. #endif #if defined(STACK_USE_DHCP) /* * DHCP must be called all the time even after IP configuration is * discovered. * DHCP has to account lease expiration time and renew the configuration * time. */ DHCPTask(); if(DHCPIsBound()) AppConfig.Flags.bInConfigMode = FALSE; #endif #if defined(STACK_USE_SNTP) SNTPTask(); // Execute SNTP client FSM #endif #if defined(STACK_USE_NBNS) NBNSTask(); // Execute NetBIOS name service task #endif }
void EthernetRun(void (*ProcessData)(BYTE *data, WORD dataLen)) { // Now that all items are initialized, begin the co-operative // multitasking loop. This infinite loop will continuously // execute all stack-related tasks, as well as your own // application's functions. Custom functions should be added // at the end of this loop. // Note that this is a "co-operative mult-tasking" mechanism // where every task performs its tasks (whether all in one shot // or part of it) and returns so that other tasks can do their // job. // If a task needs very long time to do its job, it must be broken // down into smaller pieces so that other tasks can have CPU time. // First prepare all UDP stuff. UDPTask(); WORD dataCount; IP_ADDR tempLocalIP; BYTE cFrameType; BYTE cIPFrameType; // And then process incoming data ending this loop once a valid packet is received. int cont = 1; while (cont) { // Before fetching new data, be sure all old UDP data is discarded. UDPDiscard(); // Fetch a packet. We stop receiving data if no data is waiting. if (!MACGetHeader(&remoteNode.MACAddr, &cFrameType)) { break; } // And now process the packet. switch(cFrameType) { // Process any ARP packets. These are used for determining a MAC-to-IP mapping. case MAC_ARP: ARPProcess(); break; // Process any IP packets (of which UDP is a type). case MAC_IP: // If the received packet is not a valid IP packet, ignore it. if (!IPGetHeader(&tempLocalIP, &remoteNode, &cIPFrameType, &dataCount)) { break; } // Now if we've found a valid UDP packet, quit processing data. if (cIPFrameType == IP_PROT_UDP) { // Stop processing data if we came upon a complete UDP packet. if (UDPProcess(&remoteNode, &tempLocalIP, dataCount)) { cont = 0; } } break; } } // Send new UDP data to processing function. if (ProcessData) { WORD dataLen = 0; if ((dataLen = UDPIsGetReady(localServerSocket))) { BYTE data[dataLen]; if (UDPGetArray(data, dataLen) == dataLen) { ProcessData(data, dataLen); } } } // Now run the DHCP server task. This needs to be run continuously as there's no way to tell // if any clients are connected to perform the lease once post-init. The default lease time // is also super short, 60s, so the server needs to be able to process new DHCP stuff. DHCPServerTask(); }
/********************************************************************* * Function: void StackTask(void) * * PreCondition: StackInit() is already called. * * Input: None * * Output: Stack FSM is executed. * * Side Effects: None * * Note: This FSM checks for new incoming packets, * and routes it to appropriate stack components. * It also performs timed operations. * * This function must be called periodically to * ensure timely responses. * ********************************************************************/ void StackTask(void) { WORD dataCount; IP_ADDR tempLocalIP; BYTE cFrameType; BYTE cIPFrameType; #if defined(STACK_USE_DHCP_CLIENT) // Normally, an application would not include DHCP module // if it is not enabled. But in case some one wants to disable // DHCP module at run-time, remember to not clear our IP // address if link is removed. if(AppConfig.Flags.bIsDHCPEnabled) { if(!MACIsLinked()) { AppConfig.MyIPAddr.Val = AppConfig.DefaultIPAddr.Val; AppConfig.MyMask.Val = AppConfig.DefaultMask.Val; DHCPFlags.bits.bDHCPServerDetected = FALSE; AppConfig.Flags.bInConfigMode = TRUE; DHCPReset(); } // DHCP must be called all the time even after IP configuration is // discovered. // DHCP has to account lease expiration time and renew the configuration // time. DHCPTask(); if(DHCPIsBound()) AppConfig.Flags.bInConfigMode = FALSE; } #endif #if defined(STACK_USE_TCP) // Perform all TCP time related tasks (retransmit, send acknowledge, close connection, etc) TCPTick(); #endif // Process as many incomming packets as we can while(MACGetHeader(&remoteNode.MACAddr, &cFrameType)) { switch(cFrameType) { case MAC_ARP: ARPProcess(); break; case MAC_IP: if(!IPGetHeader(&tempLocalIP, &remoteNode, &cIPFrameType, &dataCount)) break; #if defined(STACK_USE_ICMP_SERVER) || defined(STACK_USE_ICMP_CLIENT) if(cIPFrameType == IP_PROT_ICMP) { ICMPProcess(&remoteNode, dataCount); #if defined(STACK_USE_IP_GLEANING) if(AppConfig.Flags.bInConfigMode && AppConfig.Flags.bIsDHCPEnabled) { // Accoriding to "IP Gleaning" procedure, // when we receive an ICMP packet with a valid // IP address while we are still in configuration // mode, accept that address as ours and conclude // configuration mode. if(tempLocalIP.Val != 0xffffffff) { AppConfig.Flags.bInConfigMode = FALSE; AppConfig.MyIPAddr = tempLocalIP; myDHCPBindCount--; } } #endif break; } #endif #if defined(STACK_USE_TCP) if(cIPFrameType == IP_PROT_TCP) { TCPProcess(&remoteNode, &tempLocalIP, dataCount); break; } #endif #if defined(STACK_USE_UDP) if(cIPFrameType == IP_PROT_UDP) { UDPProcess(&remoteNode, &tempLocalIP, dataCount); break; } #endif break; } } }
/********************************************************************* * Function: void StackTask(void) * * PreCondition: StackInit() is already called. * * Input: None * * Output: Stack FSM is executed. * * Side Effects: None * * Note: This FSM checks for new incoming packets, * and routes it to appropriate stack components. * It also performs timed operations. * * This function must be called periodically to * ensure timely responses. * ********************************************************************/ void StackTask(void) { WORD dataCount; IP_ADDR tempLocalIP; BYTE cFrameType; BYTE cIPFrameType; #if defined(STACK_USE_DHCP_CLIENT) // Normally, an application would not include DHCP module // if it is not enabled. But in case some one wants to disable // DHCP module at run-time, remember to not clear our IP // address if link is removed. if(AppConfig.Flags.bIsDHCPEnabled) { if(!MACIsLinked()) { AppConfig.MyIPAddr.Val = AppConfig.DefaultIPAddr.Val; AppConfig.MyMask.Val = AppConfig.DefaultMask.Val; DHCPFlags.bits.bDHCPServerDetected = FALSE; AppConfig.Flags.bInConfigMode = TRUE; DHCPReset(); } // DHCP must be called all the time even after IP configuration is // discovered. // DHCP has to account lease expiration time and renew the configuration // time. DHCPTask(); if(DHCPIsBound()) AppConfig.Flags.bInConfigMode = FALSE; } #endif #if defined(STACK_USE_TCP) // Perform all TCP time related tasks (retransmit, send acknowledge, close connection, etc) TCPTick(); #endif #if defined(STACK_USE_UDP) UDPTask(); #endif // Process as many incomming packets as we can while(1) { //if using the random module, generate entropy #if defined(STACK_USE_RANDOM) RandomAdd(remoteNode.MACAddr.v[5]); #endif // We are about to fetch a new packet, make sure that the // UDP module knows that any old RX data it has laying // around will now be gone. #if defined(STACK_USE_UDP) UDPDiscard(); #endif // Fetch a packet (throws old one away, if not thrown away // yet) if(!MACGetHeader(&remoteNode.MACAddr, &cFrameType)) break; // Dispatch the packet to the appropriate handler switch(cFrameType) { case MAC_ARP: ARPProcess(); break; case MAC_IP: if(!IPGetHeader(&tempLocalIP, &remoteNode, &cIPFrameType, &dataCount)) break; #if defined(STACK_USE_ICMP_SERVER) || defined(STACK_USE_ICMP_CLIENT) if(cIPFrameType == IP_PROT_ICMP) { #if defined(STACK_USE_IP_GLEANING) if(AppConfig.Flags.bInConfigMode && AppConfig.Flags.bIsDHCPEnabled) { // Accoriding to "IP Gleaning" procedure, // when we receive an ICMP packet with a valid // IP address while we are still in configuration // mode, accept that address as ours and conclude // configuration mode. if(tempLocalIP.Val != 0xffffffff) { AppConfig.Flags.bInConfigMode = FALSE; AppConfig.MyIPAddr = tempLocalIP; myDHCPBindCount--; } } #endif // Process this ICMP packet if it the destination IP address matches our address or one of the broadcast IP addressees if( (tempLocalIP.Val == AppConfig.MyIPAddr.Val) || (tempLocalIP.Val == 0xFFFFFFFF) || (tempLocalIP.Val == ((AppConfig.MyIPAddr.Val & AppConfig.MyMask.Val) | ~AppConfig.MyMask.Val))) { ICMPProcess(&remoteNode, dataCount); } break; } #endif #if defined(STACK_USE_TCP) if(cIPFrameType == IP_PROT_TCP) { TCPProcess(&remoteNode, &tempLocalIP, dataCount); break; } #endif #if defined(STACK_USE_UDP) if(cIPFrameType == IP_PROT_UDP) { // Stop processing packets if we came upon a UDP frame with application data in it if(UDPProcess(&remoteNode, &tempLocalIP, dataCount)) return; } #endif break; } } }