/***************************************************************************** Function: void SNTPClient(void) Summary: Periodically checks the current time from a pool of servers. Description: This function periodically checks a pool of time servers to obtain the current date/time. Precondition: UDP is initialized. Parameters: None Returns: None Remarks: This function requires once available UDP socket while processing, but frees that socket when the SNTP module is idle. ***************************************************************************/ void SNTPClient(void) { NTP_PACKET pkt; WORD w; // static NODE_INFO Server; static DWORD dwTimer; static UDP_SOCKET MySocket = INVALID_UDP_SOCKET; static enum { SM_HOME = 0, SM_UDP_IS_OPENED, //SM_NAME_RESOLVE, //SM_ARP_START_RESOLVE, //SM_ARP_RESOLVE, //SM_ARP_START_RESOLVE2, //SM_ARP_RESOLVE2, //SM_ARP_START_RESOLVE3, //SM_ARP_RESOLVE3, //SM_ARP_RESOLVE_FAIL, SM_UDP_SEND, SM_UDP_RECV, SM_SHORT_WAIT, SM_WAIT } SNTPState = SM_HOME; switch(SNTPState) { case SM_HOME: if(MySocket == INVALID_UDP_SOCKET) MySocket = UDPOpenEx((DWORD)(PTR_BASE)NTP_SERVER,UDP_OPEN_ROM_HOST,0,NTP_SERVER_PORT); SNTPState++; break; case SM_UDP_IS_OPENED: if(UDPIsOpened(MySocket) == TRUE) { SNTPState = SM_UDP_SEND; } /* else { UDPClose(MySocket); SNTPState = SM_HOME; MySocket = INVALID_UDP_SOCKET; } */ break; #if 0 // Obtain ownership of the DNS resolution module if(!DNSBeginUsage()) break; // Obtain the IP address associated with the server name DNSResolveROM((ROM BYTE*)NTP_SERVER, DNS_TYPE_A); dwTimer = TickGet(); SNTPState = SM_NAME_RESOLVE; break; case SM_NAME_RESOLVE: // Wait for DNS resolution to complete if(!DNSIsResolved(&Server.IPAddr)) { if((TickGet() - dwTimer) > (5 * TICK_SECOND)) { DNSEndUsage(); dwTimer = TickGetDiv64K(); SNTPState = SM_SHORT_WAIT; } break; } // Obtain DNS resolution result if(!DNSEndUsage()) { // No valid IP address was returned from the DNS // server. Quit and fail for a while if host is not valid. dwTimer = TickGetDiv64K(); SNTPState = SM_SHORT_WAIT; break; } SNTPState = SM_ARP_START_RESOLVE; // No need to break case SM_ARP_START_RESOLVE: case SM_ARP_START_RESOLVE2: case SM_ARP_START_RESOLVE3: // Obtain the MAC address associated with the server's IP address ARPResolve(&Server.IPAddr); dwTimer = TickGet(); SNTPState++; break; case SM_ARP_RESOLVE: case SM_ARP_RESOLVE2: case SM_ARP_RESOLVE3: // Wait for the MAC address to finish being obtained if(!ARPIsResolved(&Server.IPAddr, &Server.MACAddr)) { // Time out if too much time is spent in this state if(TickGet() - dwTimer > 1*TICK_SECOND) { // Retransmit ARP request by going to next SM_ARP_START_RESOLVE state or fail by going to SM_ARP_RESOLVE_FAIL state. SNTPState++; } break; } SNTPState = SM_UDP_SEND; break; case SM_ARP_RESOLVE_FAIL: // ARP failed after 3 tries, abort and wait for next time query dwTimer = TickGetDiv64K(); SNTPState = SM_SHORT_WAIT; break; #endif // case SM_UDP_IS_OPENED: case SM_UDP_SEND: // Open up the sending UDP socket //MySocket = UDPOpen(0, &Server, NTP_SERVER_PORT); #if 0 MySocket = UDPOpenEx(NTP_SERVER,UDP_OPEN_ROM_HOST,0,NTP_SERVER_PORT); if(MySocket == INVALID_UDP_SOCKET) break; #endif // Make certain the socket can be written to if(!UDPIsPutReady(MySocket)) { UDPClose(MySocket); SNTPState = SM_HOME; MySocket = INVALID_UDP_SOCKET; break; } // Transmit a time request packet memset(&pkt, 0, sizeof(pkt)); pkt.flags.versionNumber = 3; // NTP Version 3 pkt.flags.mode = 3; // NTP Client pkt.orig_ts_secs = swapl(NTP_EPOCH); UDPPutArray((BYTE*) &pkt, sizeof(pkt)); UDPFlush(); dwTimer = TickGet(); SNTPState = SM_UDP_RECV; break; case SM_UDP_RECV: // Look for a response time packet if(!UDPIsGetReady(MySocket)) { if((TickGet()) - dwTimer > NTP_REPLY_TIMEOUT) { // Abort the request and wait until the next timeout period UDPClose(MySocket); //dwTimer = TickGetDiv64K(); //SNTPState = SM_SHORT_WAIT; SNTPState = SM_HOME; MySocket = INVALID_UDP_SOCKET; break; } break; } // Get the response time packet w = UDPGetArray((BYTE*) &pkt, sizeof(pkt)); UDPClose(MySocket); dwTimer = TickGetDiv64K(); SNTPState = SM_WAIT; MySocket = INVALID_UDP_SOCKET; // Validate packet size if(w != sizeof(pkt)) { break; } // Set out local time to match the returned time dwLastUpdateTick = TickGet(); dwSNTPSeconds = swapl(pkt.tx_ts_secs) - NTP_EPOCH; // Do rounding. If the partial seconds is > 0.5 then add 1 to the seconds count. if(((BYTE*)&pkt.tx_ts_fraq)[0] & 0x80) dwSNTPSeconds++; #ifdef WIFI_NET_TEST wifi_net_test_print("SNTP: current time", dwSNTPSeconds); #endif break; case SM_SHORT_WAIT: // Attempt to requery the NTP server after a specified NTP_FAST_QUERY_INTERVAL time (ex: 8 seconds) has elapsed. if(TickGetDiv64K() - dwTimer > (NTP_FAST_QUERY_INTERVAL/65536ull)) { SNTPState = SM_HOME; MySocket = INVALID_UDP_SOCKET; } break; case SM_WAIT: // Requery the NTP server after a specified NTP_QUERY_INTERVAL time (ex: 10 minutes) has elapsed. if(TickGetDiv64K() - dwTimer > (NTP_QUERY_INTERVAL/65536ull)) { SNTPState = SM_HOME; MySocket = INVALID_UDP_SOCKET; } break; } }
/********************************************************************* * Function: LONG ICMPGetReply(void) * * PreCondition: ICMPBeginUsage() returned TRUE and ICMPSendPing() * was called * * Input: None * * Output: -3: Could not resolve hostname (DNS timeout or * hostname invalid) * -2: No response received yet * -1: Operation timed out (longer than ICMP_TIMEOUT) * has elapsed. * >=0: Number of TICKs that elapsed between * initial ICMP transmission and reception of * a valid echo. * * Side Effects: None * * Overview: None * * Note: None ********************************************************************/ LONG ICMPGetReply(void) { ICMP_PACKET ICMPPacket; switch(ICMPState) { #if defined(STACK_USE_DNS) case SM_DNS_SEND_QUERY: // Obtain DNS module ownership if(!DNSBeginUsage()) break; // Send DNS query if(ICMPFlags.bRemoteHostIsROM) DNSResolveROM(StaticVars.RemoteHost.szROM, DNS_TYPE_A); else DNSResolve(StaticVars.RemoteHost.szRAM, DNS_TYPE_A); ICMPState = SM_DNS_GET_RESPONSE; break; case SM_DNS_GET_RESPONSE: // See if DNS is done, and if so, get the remote IP address if(!DNSIsResolved(&StaticVars.ICMPRemote.IPAddr)) break; // Free the DNS module DNSEndUsage(); // Return error code if the DNS query failed if(StaticVars.ICMPRemote.IPAddr.Val == 0x00000000ul) { ICMPState = SM_IDLE; return -3; } ICMPState = SM_ARP_SEND_QUERY; // No break; #endif case SM_ARP_SEND_QUERY: ARPResolve(&StaticVars.ICMPRemote.IPAddr); ICMPState = SM_ARP_GET_RESPONSE; break; case SM_ARP_GET_RESPONSE: // See if the ARP reponse was successfully received if(!ARPIsResolved(&StaticVars.ICMPRemote.IPAddr, &StaticVars.ICMPRemote.MACAddr)) break; ICMPState = SM_ICMP_SEND_ECHO_REQUEST; // No break; case SM_ICMP_SEND_ECHO_REQUEST: if(!IPIsTxReady()) break; // Set up the ping packet ICMPPacket.vType = 0x08; // 0x08: Echo (ping) request ICMPPacket.vCode = 0x00; ICMPPacket.wChecksum = 0x0000; ICMPPacket.wIdentifier = 0xEFBE; wICMPSequenceNumber++; ICMPPacket.wSequenceNumber = wICMPSequenceNumber; ICMPPacket.wData = 0x2860; ICMPPacket.wChecksum = CalcIPChecksum((BYTE*)&ICMPPacket, sizeof(ICMPPacket)); // Record the current time. This will be used as a basis for // finding the echo response time, which exludes the ARP and DNS // steps ICMPTimer = TickGet(); // Position the write pointer for the next IPPutHeader operation MACSetWritePtr(BASE_TX_ADDR + sizeof(ETHER_HEADER)); // Create IP header in TX memory IPPutHeader(&StaticVars.ICMPRemote, IP_PROT_ICMP, sizeof(ICMPPacket)); MACPutArray((BYTE*)&ICMPPacket, sizeof(ICMPPacket)); MACFlush(); // Echo sent, advance state ICMPState = SM_ICMP_GET_ECHO_RESPONSE; break; case SM_ICMP_GET_ECHO_RESPONSE: // See if the echo was successfully received if(ICMPFlags.bReplyValid) return (LONG)ICMPTimer; break; // SM_IDLE or illegal/impossible state: default: return -1; } // See if the DNS/ARP/echo request timed out if(TickGet() - ICMPTimer > ICMP_TIMEOUT) { // Free DNS module if we have it in use #if defined(STACK_USE_DNS) if(ICMPState == SM_DNS_GET_RESPONSE) DNSEndUsage(); #endif // Stop ICMP echo test and return error to caller ICMPState = SM_IDLE; return -1; } // Still working. No response to report yet. return -2; }
/***************************************************************************** Function: void SMTPTask(void) Summary: Performs any pending SMTP client tasks Description: This function handles periodic tasks associated with the SMTP client, such as processing initial connections and command sequences. Precondition: None Parameters: None Returns: None Remarks: This function acts as a task (similar to one in an RTOS). It performs its task in a co-operative manner, and the main application must call this function repeatedly to ensure that all open or new connections are served in a timely fashion. ***************************************************************************/ void SMTPTask(void) { BYTE i; WORD w; BYTE vBase64Buffer[4]; static DWORD Timer; static BYTE RXBuffer[4]; static ROM BYTE *ROMStrPtr, *ROMStrPtr2; static BYTE *RAMStrPtr; static WORD wAddressLength; WORD tmp; switch(TransportState) { case TRANSPORT_HOME: // SMTPBeginUsage() is the only function which will kick // the state machine into the next state break; case TRANSPORT_BEGIN: // Wait for the user to program all the pointers and then // call SMTPSendMail() if(!SMTPFlags.bits.ReadyToStart) break; // Obtain ownership of the DNS resolution module if(!DNSBeginUsage()) break; // Obtain the IP address associated with the SMTP mail server if(SMTPClient.Server.szRAM || SMTPClient.Server.szROM) { if(SMTPClient.ROMPointers.Server) DNSResolveROM(SMTPClient.Server.szROM, DNS_TYPE_A); else DNSResolve(SMTPClient.Server.szRAM, DNS_TYPE_A); } else { // If we don't have a mail server, try to send the mail // directly to the destination SMTP server if(SMTPClient.To.szRAM && !SMTPClient.ROMPointers.To) { SMTPClient.Server.szRAM = (BYTE*)strchr((char*)SMTPClient.To.szRAM, '@'); SMTPClient.ROMPointers.Server = 0; } else if(SMTPClient.To.szROM && SMTPClient.ROMPointers.To) { SMTPClient.Server.szROM = (ROM BYTE*)strchrpgm((ROM char*)SMTPClient.To.szROM, '@'); SMTPClient.ROMPointers.Server = 1; } if(!(SMTPClient.Server.szRAM || SMTPClient.Server.szROM)) { if(SMTPClient.CC.szRAM && !SMTPClient.ROMPointers.CC) { SMTPClient.Server.szRAM = (BYTE*)strchr((char*)SMTPClient.CC.szRAM, '@'); SMTPClient.ROMPointers.Server = 0; } else if(SMTPClient.CC.szROM && SMTPClient.ROMPointers.CC) { SMTPClient.Server.szROM = (ROM BYTE*)strchrpgm((ROM char*)SMTPClient.CC.szROM, '@'); SMTPClient.ROMPointers.Server = 1; } } if(!(SMTPClient.Server.szRAM || SMTPClient.Server.szROM)) { if(SMTPClient.BCC.szRAM && !SMTPClient.ROMPointers.BCC) { SMTPClient.Server.szRAM = (BYTE*)strchr((char*)SMTPClient.BCC.szRAM, '@'); SMTPClient.ROMPointers.Server = 0; } else if(SMTPClient.BCC.szROM && SMTPClient.ROMPointers.BCC) { SMTPClient.Server.szROM = (ROM BYTE*)strchrpgm((ROM char*)SMTPClient.BCC.szROM, '@'); SMTPClient.ROMPointers.Server = 1; } } // See if we found a hostname anywhere which we could resolve if(!(SMTPClient.Server.szRAM || SMTPClient.Server.szROM)) { DNSEndUsage(); ResponseCode = SMTP_RESOLVE_ERROR; TransportState = TRANSPORT_HOME; break; } // Skip over the @ sign and resolve the host name if(SMTPClient.ROMPointers.Server) { SMTPClient.Server.szROM++; DNSResolveROM(SMTPClient.Server.szROM, DNS_TYPE_MX); } else { SMTPClient.Server.szRAM++; DNSResolve(SMTPClient.Server.szRAM, DNS_TYPE_MX); } } Timer = TickGet(); TransportState++; break; case TRANSPORT_NAME_RESOLVE: // Wait for the DNS server to return the requested IP address if(!DNSIsResolved(&SMTPServer)) { // Timeout after 6 seconds of unsuccessful DNS resolution if(TickGet() - Timer > 6*TICK_SECOND) { ResponseCode = SMTP_RESOLVE_ERROR; TransportState = TRANSPORT_HOME; DNSEndUsage(); } break; } // Release the DNS module, we no longer need it if(!DNSEndUsage()) { // An invalid IP address was returned from the DNS // server. Quit and fail permanantly if host is not valid. ResponseCode = SMTP_RESOLVE_ERROR; TransportState = TRANSPORT_HOME; break; } TransportState++; // No need to break here case TRANSPORT_OBTAIN_SOCKET: // Connect a TCP socket to the remote SMTP server MySocket = TCPOpen(SMTPServer.Val, TCP_OPEN_IP_ADDRESS, SMTPClient.ServerPort, TCP_PURPOSE_DEFAULT); // Abort operation if no TCP sockets are available // If this ever happens, add some more // TCP_PURPOSE_DEFAULT sockets in TCPIPConfig.h if(MySocket == INVALID_SOCKET) break; TransportState++; Timer = TickGet(); // No break; fall into TRANSPORT_SOCKET_OBTAINED #if defined(STACK_USE_SSL_CLIENT) case TRANSPORT_SECURING_SOCKET: if(!TCPIsConnected(MySocket)) { // Don't stick around in the wrong state if the // server was connected, but then disconnected us. // Also time out if we can't establish the connection // to the SMTP server if((LONG)(TickGet()-Timer) > (LONG)(SMTP_SERVER_REPLY_TIMEOUT)) { ResponseCode = SMTP_CONNECT_ERROR; TransportState = TRANSPORT_CLOSE; } break; } SMTPFlags.bits.ConnectedOnce = TRUE; // Start SSL if needed for this connection if(SMTPClient.UseSSL && !TCPStartSSLClient(MySocket,NULL)) break; // Move on to main state Timer = TickGet(); TransportState++; break; #endif case TRANSPORT_SOCKET_OBTAINED: if(!TCPIsConnected(MySocket)) { // Don't stick around in the wrong state if the // server was connected, but then disconnected us. // Also time out if we can't establish the connection // to the SMTP server if(SMTPFlags.bits.ConnectedOnce || ((LONG)(TickGet()-Timer) > (LONG)(SMTP_SERVER_REPLY_TIMEOUT))) { ResponseCode = SMTP_CONNECT_ERROR; TransportState = TRANSPORT_CLOSE; } break; } SMTPFlags.bits.ConnectedOnce = TRUE; #if defined(STACK_USE_SSL_CLIENT) // Make sure the SSL handshake has completed if(SMTPClient.UseSSL && TCPSSLIsHandshaking(MySocket)) break; #endif // See if the server sent us anything while(TCPIsGetReady(MySocket)) { TCPGet(MySocket, &i); switch(RXParserState) { case RX_BYTE_0: case RX_BYTE_1: case RX_BYTE_2: RXBuffer[RXParserState] = i; RXParserState++; break; case RX_BYTE_3: switch(i) { case ' ': SMTPFlags.bits.RXSkipResponse = FALSE; RXParserState++; break; case '-': SMTPFlags.bits.RXSkipResponse = TRUE; RXParserState++; break; case '\r': RXParserState = RX_SEEK_LF; break; } break; case RX_SEEK_CR: if(i == '\r') RXParserState++; break; case RX_SEEK_LF: // If we received the whole command if(i == '\n') { RXParserState = RX_BYTE_0; if(!SMTPFlags.bits.RXSkipResponse) { // The server sent us a response code // Null terminate the ASCII reponse code so we can convert it to an integer RXBuffer[3] = 0; ResponseCode = atoi((char*)RXBuffer); // Handle the response switch(SMTPState) { case SMTP_HELO_ACK: if(ResponseCode >= 200u && ResponseCode <= 299u) { if(SMTPClient.Username.szRAM || SMTPClient.Username.szROM) SMTPState = SMTP_AUTH_LOGIN; else SMTPState = SMTP_MAILFROM; } else SMTPState = SMTP_QUIT_INIT; break; case SMTP_AUTH_LOGIN_ACK: case SMTP_AUTH_USERNAME_ACK: if(ResponseCode == 334u) SMTPState++; else SMTPState = SMTP_QUIT_INIT; break; case SMTP_AUTH_PASSWORD_ACK: if(ResponseCode == 235u) SMTPState++; else SMTPState = SMTP_QUIT_INIT; break; case SMTP_HOME: case SMTP_MAILFROM_ACK: case SMTP_RCPTTO_ACK: case SMTP_RCPTTOCC_ACK: case SMTP_RCPTTOBCC_ACK: tmp = SMTPState; if(ResponseCode >= 200u && ResponseCode <= 299u) SMTPState++; else SMTPState = SMTP_QUIT_INIT; break; case SMTP_DATA_ACK: if(ResponseCode == 354u) SMTPState++; else SMTPState = SMTP_QUIT_INIT; break; case SMTP_DATA_BODY_ACK: if(ResponseCode >= 200u && ResponseCode <= 299u) SMTPFlags.bits.SentSuccessfully = TRUE; SMTPState = SMTP_QUIT_INIT; break; // Default case needed to supress compiler diagnostics default: break; } } } else if(i != '\r') RXParserState--; break; } } // Generate new data in the TX buffer, as needed, if possible if(TCPIsPutReady(MySocket) < 64u) break; switch(SMTPState) { case SMTP_HELO: if(SMTPClient.Username.szROM == NULL) TCPPutROMString(MySocket, (ROM BYTE*)"HELO MCHPBOARD\r\n"); else TCPPutROMString(MySocket, (ROM BYTE*)"EHLO MCHPBOARD\r\n"); TCPFlush(MySocket); SMTPState++; break; case SMTP_AUTH_LOGIN: // Note: This state is only entered from SMTP_HELO_ACK if the application // has specified a Username to use (either SMTPClient.Username.szROM or // SMTPClient.Username.szRAM is non-NULL) TCPPutROMString(MySocket, (ROM BYTE*)"AUTH LOGIN\r\n"); TCPFlush(MySocket); SMTPState++; break; case SMTP_AUTH_USERNAME: // Base 64 encode and transmit the username. if(SMTPClient.ROMPointers.Username) { ROMStrPtr = SMTPClient.Username.szROM; w = strlenpgm((ROM char*)ROMStrPtr); } else { RAMStrPtr = SMTPClient.Username.szRAM; w = strlen((char*)RAMStrPtr); } while(w) { i = 0; while((i < w) && (i < sizeof(vBase64Buffer)*3/4)) { if(SMTPClient.ROMPointers.Username) vBase64Buffer[i] = *ROMStrPtr++; else vBase64Buffer[i] = *RAMStrPtr++; i++; } w -= i; Base64Encode(vBase64Buffer, i, vBase64Buffer, sizeof(vBase64Buffer)); TCPPutArray(MySocket, vBase64Buffer, sizeof(vBase64Buffer)); } TCPPutROMString(MySocket, (ROM BYTE*)"\r\n"); TCPFlush(MySocket); SMTPState++; break; case SMTP_AUTH_PASSWORD: // Base 64 encode and transmit the password if(SMTPClient.ROMPointers.Password) { ROMStrPtr = SMTPClient.Password.szROM; w = strlenpgm((ROM char*)ROMStrPtr); } else { RAMStrPtr = SMTPClient.Password.szRAM; w = strlen((char*)RAMStrPtr); } while(w) { i = 0; while((i < w) && (i < sizeof(vBase64Buffer)*3/4)) { if(SMTPClient.ROMPointers.Password) vBase64Buffer[i] = *ROMStrPtr++; else vBase64Buffer[i] = *RAMStrPtr++; i++; } w -= i; Base64Encode(vBase64Buffer, i, vBase64Buffer, sizeof(vBase64Buffer)); TCPPutArray(MySocket, vBase64Buffer, sizeof(vBase64Buffer)); } TCPPutROMString(MySocket, (ROM BYTE*)"\r\n"); TCPFlush(MySocket); SMTPState++; break; case SMTP_MAILFROM: // Send MAIL FROM header. Note that this is for the SMTP server validation, // not what actually will be displayed in the recipients mail client as a // return address. TCPPutROMString(MySocket, (ROM BYTE*)"MAIL FROM:<"); if(SMTPClient.ROMPointers.From) { ROMStrPtr = FindROMEmailAddress(SMTPClient.From.szROM, &wAddressLength); TCPPutROMArray(MySocket, ROMStrPtr, wAddressLength); } else { RAMStrPtr = FindEmailAddress(SMTPClient.From.szRAM, &wAddressLength); TCPPutArray(MySocket, RAMStrPtr, wAddressLength); } TCPPutROMString(MySocket, (ROM BYTE*)">\r\n"); TCPFlush(MySocket); SMTPState++; break; case SMTP_RCPTTO_INIT: // See if there are any (To) recipients to process if(SMTPClient.To.szRAM && !SMTPClient.ROMPointers.To) { RAMStrPtr = FindEmailAddress(SMTPClient.To.szRAM, &wAddressLength); if(wAddressLength) { SMTPState = SMTP_RCPTTO; break; } } if(SMTPClient.To.szROM && SMTPClient.ROMPointers.To) { ROMStrPtr = FindROMEmailAddress(SMTPClient.To.szROM, &wAddressLength); if(wAddressLength) { SMTPState = SMTP_RCPTTO; break; } } SMTPState = SMTP_RCPTTOCC_INIT; break; case SMTP_RCPTTO: case SMTP_RCPTTOCC: case SMTP_RCPTTOBCC: TCPPutROMString(MySocket, (ROM BYTE*)"RCPT TO:<"); if( (SMTPClient.ROMPointers.To && (SMTPState == SMTP_RCPTTO)) || (SMTPClient.ROMPointers.CC && (SMTPState == SMTP_RCPTTOCC)) || (SMTPClient.ROMPointers.BCC && (SMTPState == SMTP_RCPTTOBCC)) ) TCPPutROMArray(MySocket, ROMStrPtr, wAddressLength); else TCPPutArray(MySocket, RAMStrPtr, wAddressLength); TCPPutROMString(MySocket, (ROM BYTE*)">\r\n"); TCPFlush(MySocket); SMTPState++; break; case SMTP_RCPTTO_ISDONE: // See if we have any more (To) recipients to process // If we do, we must roll back a couple of states if(SMTPClient.ROMPointers.To) ROMStrPtr = FindROMEmailAddress(ROMStrPtr+wAddressLength, &wAddressLength); else RAMStrPtr = FindEmailAddress(RAMStrPtr+wAddressLength, &wAddressLength); if(wAddressLength) { SMTPState = SMTP_RCPTTO; break; } // All done with To field SMTPState++; //No break case SMTP_RCPTTOCC_INIT: // See if there are any Carbon Copy (CC) recipients to process if(SMTPClient.CC.szRAM && !SMTPClient.ROMPointers.CC) { RAMStrPtr = FindEmailAddress(SMTPClient.CC.szRAM, &wAddressLength); if(wAddressLength) { SMTPState = SMTP_RCPTTOCC; break; } } if(SMTPClient.CC.szROM && SMTPClient.ROMPointers.CC) { ROMStrPtr = FindROMEmailAddress(SMTPClient.CC.szROM, &wAddressLength); if(wAddressLength) { SMTPState = SMTP_RCPTTOCC; break; } } SMTPState = SMTP_RCPTTOBCC_INIT; break; case SMTP_RCPTTOCC_ISDONE: // See if we have any more Carbon Copy (CC) recipients to process // If we do, we must roll back a couple of states if(SMTPClient.ROMPointers.CC) ROMStrPtr = FindROMEmailAddress(ROMStrPtr+wAddressLength, &wAddressLength); else RAMStrPtr = FindEmailAddress(RAMStrPtr+wAddressLength, &wAddressLength); if(wAddressLength) { SMTPState = SMTP_RCPTTOCC; break; } // All done with CC field SMTPState++; //No break case SMTP_RCPTTOBCC_INIT: // See if there are any Blind Carbon Copy (BCC) recipients to process if(SMTPClient.BCC.szRAM && !SMTPClient.ROMPointers.BCC) { RAMStrPtr = FindEmailAddress(SMTPClient.BCC.szRAM, &wAddressLength); if(wAddressLength) { SMTPState = SMTP_RCPTTOBCC; break; } } if(SMTPClient.BCC.szROM && SMTPClient.ROMPointers.BCC) { ROMStrPtr = FindROMEmailAddress(SMTPClient.BCC.szROM, &wAddressLength); if(wAddressLength) { SMTPState = SMTP_RCPTTOBCC; break; } } // All done with BCC field SMTPState = SMTP_DATA; break; case SMTP_RCPTTOBCC_ISDONE: // See if we have any more Blind Carbon Copy (CC) recipients to process // If we do, we must roll back a couple of states if(SMTPClient.ROMPointers.BCC) ROMStrPtr = FindROMEmailAddress(ROMStrPtr+wAddressLength, &wAddressLength); else RAMStrPtr = FindEmailAddress(RAMStrPtr+wAddressLength, &wAddressLength); if(wAddressLength) { SMTPState = SMTP_RCPTTOBCC; break; } // All done with BCC field SMTPState++; //No break case SMTP_DATA: TCPPutROMString(MySocket, (ROM BYTE*)"DATA\r\n"); SMTPState++; PutHeadersState = PUTHEADERS_FROM_INIT; TCPFlush(MySocket); break; case SMTP_DATA_HEADER: while((PutHeadersState != PUTHEADERS_DONE) && (TCPIsPutReady(MySocket) > 64u)) { switch(PutHeadersState) { case PUTHEADERS_FROM_INIT: if(SMTPClient.From.szRAM || SMTPClient.From.szROM) { PutHeadersState = PUTHEADERS_FROM; TCPPutROMString(MySocket, (ROM BYTE*)"From: "); } else { PutHeadersState = PUTHEADERS_TO_INIT; } break; case PUTHEADERS_FROM: if(SMTPClient.ROMPointers.From) { SMTPClient.From.szROM = TCPPutROMString(MySocket, SMTPClient.From.szROM); if(*SMTPClient.From.szROM == 0u) PutHeadersState = PUTHEADERS_TO_INIT; } else { SMTPClient.From.szRAM = TCPPutString(MySocket, SMTPClient.From.szRAM); if(*SMTPClient.From.szRAM == 0u) PutHeadersState = PUTHEADERS_TO_INIT; } break; case PUTHEADERS_TO_INIT: if(SMTPClient.To.szRAM || SMTPClient.To.szROM) { PutHeadersState = PUTHEADERS_TO; TCPPutROMString(MySocket, (ROM BYTE*)"\r\nTo: "); } else { PutHeadersState = PUTHEADERS_CC_INIT; } break; case PUTHEADERS_TO: if(SMTPClient.ROMPointers.To) { SMTPClient.To.szROM = TCPPutROMString(MySocket, SMTPClient.To.szROM); if(*SMTPClient.To.szROM == 0u) PutHeadersState = PUTHEADERS_CC_INIT; } else { SMTPClient.To.szRAM = TCPPutString(MySocket, SMTPClient.To.szRAM); if(*SMTPClient.To.szRAM == 0u) PutHeadersState = PUTHEADERS_CC_INIT; } break; case PUTHEADERS_CC_INIT: if(SMTPClient.CC.szRAM || SMTPClient.CC.szROM) { PutHeadersState = PUTHEADERS_CC; TCPPutROMString(MySocket, (ROM BYTE*)"\r\nCC: "); } else { PutHeadersState = PUTHEADERS_SUBJECT_INIT; } break; case PUTHEADERS_CC: if(SMTPClient.ROMPointers.CC) { SMTPClient.CC.szROM = TCPPutROMString(MySocket, SMTPClient.CC.szROM); if(*SMTPClient.CC.szROM == 0u) PutHeadersState = PUTHEADERS_SUBJECT_INIT; } else { SMTPClient.CC.szRAM = TCPPutString(MySocket, SMTPClient.CC.szRAM); if(*SMTPClient.CC.szRAM == 0u) PutHeadersState = PUTHEADERS_SUBJECT_INIT; } break; case PUTHEADERS_SUBJECT_INIT: if(SMTPClient.Subject.szRAM || SMTPClient.Subject.szROM) { PutHeadersState = PUTHEADERS_SUBJECT; TCPPutROMString(MySocket, (ROM BYTE*)"\r\nSubject: "); } else { PutHeadersState = PUTHEADERS_OTHER_INIT; } break; case PUTHEADERS_SUBJECT: if(SMTPClient.ROMPointers.Subject) { SMTPClient.Subject.szROM = TCPPutROMString(MySocket, SMTPClient.Subject.szROM); if(*SMTPClient.Subject.szROM == 0u) PutHeadersState = PUTHEADERS_OTHER_INIT; } else { SMTPClient.Subject.szRAM = TCPPutString(MySocket, SMTPClient.Subject.szRAM); if(*SMTPClient.Subject.szRAM == 0u) PutHeadersState = PUTHEADERS_OTHER_INIT; } break; case PUTHEADERS_OTHER_INIT: TCPPutROMArray(MySocket, (ROM BYTE*)"\r\n", 2); if(SMTPClient.OtherHeaders.szRAM || SMTPClient.OtherHeaders.szROM) { PutHeadersState = PUTHEADERS_OTHER; } else { TCPPutROMArray(MySocket, (ROM BYTE*)"\r\n", 2); PutHeadersState = PUTHEADERS_DONE; SMTPState++; } break; case PUTHEADERS_OTHER: if(SMTPClient.ROMPointers.OtherHeaders) { SMTPClient.OtherHeaders.szROM = TCPPutROMString(MySocket, SMTPClient.OtherHeaders.szROM); if(*SMTPClient.OtherHeaders.szROM == 0u) { TCPPutROMArray(MySocket, (ROM BYTE*)"\r\n", 2); PutHeadersState = PUTHEADERS_DONE; SMTPState++; } } else { SMTPClient.OtherHeaders.szRAM = TCPPutString(MySocket, SMTPClient.OtherHeaders.szRAM); if(*SMTPClient.OtherHeaders.szRAM == 0u) { TCPPutROMArray(MySocket, (ROM BYTE*)"\r\n", 2); PutHeadersState = PUTHEADERS_DONE; SMTPState++; } } break; // Default case needed to supress compiler diagnostics default: break; } } TCPFlush(MySocket); break; case SMTP_DATA_BODY_INIT: SMTPState++; RAMStrPtr = SMTPClient.Body.szRAM; ROMStrPtr2 = (ROM BYTE*)"\r\n.\r\n"; CRPeriod.Pos = NULL; if(RAMStrPtr) CRPeriod.Pos = (BYTE*)strstrrampgm((char*)RAMStrPtr, (ROM char*)"\r\n."); // No break here case SMTP_DATA_BODY: if(SMTPClient.Body.szRAM || SMTPClient.Body.szROM) { if(*ROMStrPtr2) { // Put the application data, doing the transparancy replacement of "\r\n." with "\r\n.." while(CRPeriod.Pos) { CRPeriod.Pos += 3; RAMStrPtr += TCPPutArray(MySocket, RAMStrPtr, CRPeriod.Pos-RAMStrPtr); if(RAMStrPtr == CRPeriod.Pos) { if(!TCPPut(MySocket, '.')) { CRPeriod.Pos -= 3; break; } } else { CRPeriod.Pos -= 3; break; } CRPeriod.Pos = (BYTE*)strstrrampgm((char*)RAMStrPtr, (ROM char*)"\r\n."); } // If we get down here, either all replacements have been made or there is no remaining space in the TCP output buffer RAMStrPtr = TCPPutString(MySocket, RAMStrPtr); ROMStrPtr2 = TCPPutROMString(MySocket, ROMStrPtr2); TCPFlush(MySocket); } } else { if(SMTPFlags.bits.ReadyToFinish) { if(*ROMStrPtr2) { ROMStrPtr2 = TCPPutROMString(MySocket, ROMStrPtr2); TCPFlush(MySocket); } } } if(*ROMStrPtr2 == 0u) { SMTPState++; } break; case SMTP_QUIT_INIT: SMTPState++; ROMStrPtr = (ROM BYTE*)"QUIT\r\n"; // No break here case SMTP_QUIT: if(*ROMStrPtr) { ROMStrPtr = TCPPutROMString(MySocket, ROMStrPtr); TCPFlush(MySocket); } if(*ROMStrPtr == 0u) { TransportState = TRANSPORT_CLOSE; } break; // Default case needed to supress compiler diagnostics default: break; } break; case TRANSPORT_CLOSE: // Close the socket so it can be used by other modules TCPDisconnect(MySocket); MySocket = INVALID_SOCKET; // Go back to doing nothing TransportState = TRANSPORT_HOME; break; } }
void NTPTask(void) { NTP_PACKET pkt; WORD w; switch(NTPState) { case NTP_HOME: debug_ntp(debug_putc, "\r\n\nRefreshing Time\r\n"); // Obtain ownership of the DNS resolution module if(!DNSBeginUsage()) break; // Obtain the IP address associated with the server name DNSResolveROM((ROM BYTE*)NTP_SERVER, DNS_TYPE_A); rtcTimer = time(NULL); NTPState = NTP_NAME_RESOLVE; break; case NTP_NAME_RESOLVE: // Wait for DNS resolution to complete if(!DNSIsResolved(&Server.IPAddr)) { if((time(NULL) - rtcTimer) >= NTP_RESOLVE_TIMEOUT) { DNSEndUsage(); rtcTimer = time(NULL); NTPState = NTP_SHORT_WAIT; } break; } // Obtain DNS resolution result if(!DNSEndUsage()) { // No valid IP address was returned from the DNS // server. Quit and fail for a while if host is not valid. rtcTimer = time(NULL); NTPState = NTP_SHORT_WAIT; break; } NTPState = NTP_ARP_START_RESOLVE; // No need to break case NTP_ARP_START_RESOLVE: case NTP_ARP_START_RESOLVE2: case NTP_ARP_START_RESOLVE3: // Obtain the MAC address associated with the server's IP address ARPResolve(&Server.IPAddr); rtcTimer = time(NULL); NTPState++; break; case NTP_ARP_RESOLVE: case NTP_ARP_RESOLVE2: case NTP_ARP_RESOLVE3: // Wait for the MAC address to finish being obtained if(!ARPIsResolved(&Server.IPAddr, &Server.MACAddr)) { // Time out if too much time is spent in this state if(time(NULL) - rtcTimer >= NTP_ARP_TIMEOUT) { // Retransmit ARP request by going to next SM_ARP_START_RESOLVE state or fail by going to SM_ARP_RESOLVE_FAIL state. NTPState++; } break; } NTPState = NTP_UDP_SEND; break; case NTP_ARP_RESOLVE_FAIL: // ARP failed after 3 tries, abort and wait for next time query rtcTimer = time(NULL); NTPState = NTP_SHORT_WAIT; break; case NTP_UDP_SEND: // Open up the sending UDP socket MySocket = UDPOpen(NTP_LOCAL_PORT, &Server, NTP_SERVER_PORT); if(MySocket == INVALID_UDP_SOCKET) break; // Make certain the socket can be written to if(!UDPIsPutReady(MySocket)) { UDPClose(MySocket); break; } // Transmit a time request packet memset(&pkt, 0, sizeof(pkt)); pkt.flags.versionNumber = 3; // NTP Version 3 pkt.flags.mode = 3; // NTP Client pkt.orig_ts_secs = swapl(NTP_EPOCH); UDPPutArray((BYTE*) &pkt, sizeof(pkt)); UDPFlush(); //dwTimer = TickGet(); rtcTimer = time(NULL); NTPState = NTP_UDP_RECV; break; case NTP_UDP_RECV: // Look for a response time packet if(!UDPIsGetReady(MySocket)) { if((time(NULL)) - rtcTimer >= NTP_REPLY_TIMEOUT) { // Abort the request and wait until the next timeout period UDPClose(MySocket); rtcTimer = time(NULL); NTPState = NTP_SHORT_WAIT; break; } break; } // Get the response time packet w = UDPGetArray((BYTE*) &pkt, sizeof(pkt)); UDPClose(MySocket); rtcTimer = time(NULL); // Validate packet size if(w != sizeof(pkt)) { NTPState = NTP_SHORT_WAIT; break; } g_NTPOk = TRUE; NTPState = NTP_WAIT; // Set out local time to match the returned time NTPLastUpdate = swapl(pkt.tx_ts_secs) - NTP_EPOCH; // Do rounding. If the partial seconds is > 0.5 then add 1 to the seconds count. if(((BYTE*)&pkt.tx_ts_fraq)[0] & 0x80) NTPLastUpdate++; SetTimeSec(NTPLastUpdate); break; case NTP_SHORT_WAIT: // Attempt to requery the NTP server after a specified NTP_FAST_QUERY_INTERVAL time (ex: 8 seconds) has elapsed. g_NTPOk = FALSE; if(time(NULL) - rtcTimer >= NTP_WAIT_INTERVAL) NTPState = NTP_HOME; break; case NTP_WAIT: // Requery the NTP server after a specified NTP_QUERY_INTERVAL time (ex: 10 minutes) has elapsed. if(time(NULL) - NTPLastUpdate >= NTP_QUERY_INTERVAL) NTPState = NTP_HOME; break; } }
/****************************************************************************** Function: void UDPTask(void) Summary: Performs periodic UDP tasks. Description: This function performs any required periodic UDP tasks. Each socket's state machine is checked, and any elapsed timeout periods are handled. Precondition: UDP is initialized. Parameters: None Returns: None ******************************************************************************/ void UDPTask(void) { UDP_SOCKET ss; for ( ss = 0; ss < MAX_UDP_SOCKETS; ss++ ) { // need to put Extra check if UDP has opened or NOT if((UDPSocketInfo[ss].smState == UDP_OPENED) || (UDPSocketInfo[ss].smState == UDP_CLOSED)) continue; // A timeout has occured. Respond to this timeout condition // depending on what state this socket is in. switch(UDPSocketInfo[ss].smState) { #if defined(STACK_CLIENT_MODE) #if defined(STACK_USE_DNS) case UDP_DNS_RESOLVE: if(DNSBeginUsage()) { // call DNS Resolve function and move to UDP next State machine UDPSocketInfo[ss].smState = UDP_DNS_IS_RESOLVED; if(UDPSocketInfo[ss].flags.bRemoteHostIsROM) DNSResolveROM((ROM BYTE*)(ROM_PTR_BASE)UDPSocketInfo[ss].remote.remoteHost, DNS_TYPE_A); else DNSResolve((BYTE*)(PTR_BASE)UDPSocketInfo[ss].remote.remoteHost, DNS_TYPE_A); } break; case UDP_DNS_IS_RESOLVED: { IP_ADDR ipResolvedDNSIP; // See if DNS resolution has finished. Note that if the DNS // fails, the &ipResolvedDNSIP will be written with 0x00000000. // MyTCB.remote.dwRemoteHost is unioned with // MyTCB.remote.niRemoteMACIP.IPAddr, so we can't directly write // the DNS result into MyTCB.remote.niRemoteMACIP.IPAddr. We // must copy it over only if the DNS is resolution step was // successful. if(DNSIsResolved(&ipResolvedDNSIP)) { if(DNSEndUsage()) { UDPSocketInfo[ss].remote.remoteNode.IPAddr.Val = ipResolvedDNSIP.Val; UDPSocketInfo[ss].smState = UDP_GATEWAY_SEND_ARP; UDPSocketInfo[ss].retryCount = 0; UDPSocketInfo[ss].retryInterval = (TICK_SECOND/4)/256; } else { UDPSocketInfo[ss].smState = UDP_DNS_RESOLVE; } } } break; #endif // #if defined(STACK_USE_DNS) case UDP_GATEWAY_SEND_ARP: // Obtain the MAC address associated with the server's IP address //(either direct MAC address on same subnet, or the MAC address of the Gateway machine) UDPSocketInfo[ss].eventTime = (WORD)TickGetDiv256(); ARPResolve(&UDPSocketInfo[ss].remote.remoteNode.IPAddr); UDPSocketInfo[ss].smState = UDP_GATEWAY_GET_ARP; break; case UDP_GATEWAY_GET_ARP: if(!ARPIsResolved(&UDPSocketInfo[ss].remote.remoteNode.IPAddr, &UDPSocketInfo[ss].remote.remoteNode.MACAddr)) { // Time out if too much time is spent in this state // Note that this will continuously send out ARP // requests for an infinite time if the Gateway // never responds if((WORD)TickGetDiv256() - UDPSocketInfo[ss].eventTime> (WORD)UDPSocketInfo[ss].retryInterval) { // Exponentially increase timeout until we reach 6 attempts then stay constant if(UDPSocketInfo[ss].retryCount < 6u) { UDPSocketInfo[ss].retryCount++; UDPSocketInfo[ss].retryInterval <<= 1; } // Retransmit ARP request UDPSocketInfo[ss].smState = UDP_GATEWAY_SEND_ARP; } } else { UDPSocketInfo[ss].smState = UDP_OPENED; } break; default: case UDP_OPENED: case UDP_CLOSED: // not used break; #endif // #if defined(STACK_CLIENT_MODE) } } }
/********************************************************************* * Function: void BerkeleyTCPClientDemo(void) * * PreCondition: Stack is initialized() * * Input: None * * Output: None * * Side Effects: None * * Overview: None * * Note: None ********************************************************************/ void BerkeleyTCPClientDemo(void) { #if defined(STACK_USE_DNS) static SOCKET bsdClientSocket; static struct sockaddr_in addr; char recvBuffer[9]; int i; int addrlen; static enum { DNS_START_RESOLUTION = 0, DNS_GET_RESULT, BSD_START, BSD_CONNECT, BSD_SEND, BSD_OPERATION, BSD_CLOSE, BSD_DONE } BSDClientState = BSD_DONE; switch(BSDClientState) { case DNS_START_RESOLUTION: if(DNSBeginUsage()) { DNSResolveROM(ServerName, DNS_TYPE_A); BSDClientState = DNS_GET_RESULT; } break; case DNS_GET_RESULT: if(!DNSIsResolved((IP_ADDR*)&addr.sin_addr.S_un.S_addr)) break; if(!DNSEndUsage()) { #if defined(STACK_USE_UART) putrsUART((ROM char*)"Could not resolve ServerName[] to IP address.\r\n"); #endif BSDClientState = BSD_DONE; break; } BSDClientState = BSD_START; // No break; here. case BSD_START: // Create a socket for this client to connect with if((bsdClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET ) return; #if defined(STACK_USE_UART) putrsUART((ROM char*)"\r\n\r\nConnecting using Berkeley Sockets TCP API...\r\n"); putrsUART((ROM char*)" Note: this demo will do nothing if an underlying TCP_PURPOSE_BERKELEY_CLIENT type \r\n" " socket is unavailable, as declared by the TCPSocketInitializer[] array in \r\n" " TCPIPConfig.h.\r\n\r\n"); #endif BSDClientState = BSD_CONNECT; break; case BSD_CONNECT: // addr.sin_addr.S_un.S_addr destination IP address was set earlier in DNS step addr.sin_port = PORTNUM; addrlen = sizeof(struct sockaddr); if(connect( bsdClientSocket, (struct sockaddr*)&addr, addrlen) < 0) return; BSDClientState = BSD_SEND; // No break needed case BSD_SEND: //send TCP data send(bsdClientSocket, (const char*)sendRequest, strlen((char*)sendRequest), 0); BSDClientState = BSD_OPERATION; break; case BSD_OPERATION: // Obtian and print the server reply while(1) { i = recv(bsdClientSocket, recvBuffer, sizeof(recvBuffer)-1, 0); //get the data from the recv queue if(i == 0) break; if(i< 0) //error condition { BSDClientState = BSD_CLOSE; break; } #if defined(STACK_USE_UART) recvBuffer[i] = '\0'; // Null terminate data putsUART((char*)recvBuffer); #endif if(BSDClientState == BSD_OPERATION) break; } break; case BSD_CLOSE: closesocket(bsdClientSocket); BSDClientState = BSD_DONE; // No break needed case BSD_DONE: if(BUTTON2_IO == 0u) BSDClientState = DNS_START_RESOLUTION; break; default: return; } //#if defined(STACK_USE_DNS) #else #warning You must define STACK_USE_DNS for BerkeleyTCPClientDemo to work #endif }
/***************************************************************************** Function: void BerkeleyUDPClientDemo(void) Summary: Periodically checks the current time from a pool of servers. Description: This function periodically checks a pool of time servers to obtain the current date/time. Precondition: UDP is initialized. Parameters: None Returns: None Remarks: This function requires once available UDP socket while processing, but frees that socket when the SNTP module is idle. ***************************************************************************/ void BerkeleyUDPClientDemo(void) { #if defined(STACK_USE_DNS) NTP_PACKET pkt; int i; static NODE_INFO Server; static DWORD dwTimer; static SOCKET bsdUdpClient = INVALID_SOCKET; int addrlen = sizeof(struct sockaddr_in); static struct sockaddr_in udpaddr; static enum { SM_HOME = 0, SM_NAME_RESOLVE, SM_UDP_SEND, SM_UDP_RECV, SM_SHORT_WAIT, SM_WAIT } SNTPState = SM_HOME; switch(SNTPState) { case SM_HOME: // Obtain ownership of the DNS resolution module if(!DNSBeginUsage()) break; // Obtain the IP address associated with the server name DNSResolveROM((ROM BYTE*)NTP_SERVER, DNS_TYPE_A); dwTimer = TickGet(); SNTPState = SM_NAME_RESOLVE; break; case SM_NAME_RESOLVE: // Wait for DNS resolution to complete if(!DNSIsResolved(&Server.IPAddr)) { if((TickGet() - dwTimer) > (5 * TICK_SECOND)) { DNSEndUsage(); dwTimer = TickGetDiv64K(); SNTPState = SM_SHORT_WAIT; } break; } // Obtain DNS resolution result if(!DNSEndUsage()) { // No valid IP address was returned from the DNS // server. Quit and fail for a while if host is not valid. dwTimer = TickGetDiv64K(); SNTPState = SM_SHORT_WAIT; break; } bsdUdpClient = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); udpaddr.sin_port = 0; udpaddr.sin_addr.S_un.S_addr = IP_ADDR_ANY; if( bind(bsdUdpClient, (struct sockaddr*)&udpaddr, addrlen) == SOCKET_ERROR ) break; SNTPState = SM_UDP_SEND; case SM_UDP_SEND: // Transmit a time request packet memset(&pkt, 0, sizeof(pkt)); pkt.flags.versionNumber = 3; // NTP Version 3 pkt.flags.mode = 3; // NTP Client pkt.orig_ts_secs = swapl(NTP_EPOCH); udpaddr.sin_port = NTP_SERVER_PORT; udpaddr.sin_addr.S_un.S_addr = Server.IPAddr.Val; if(sendto(bsdUdpClient, (const char*)&pkt, sizeof(pkt), 0, (struct sockaddr*)&udpaddr, addrlen)>0) { dwTimer = TickGet(); SNTPState = SM_UDP_RECV; } break; case SM_UDP_RECV: // Look for a response time packet i = recvfrom(bsdUdpClient, (char*)&pkt, sizeof(pkt), 0, (struct sockaddr*)&udpaddr, &addrlen); if(i < (int)sizeof(pkt)) { if((TickGet()) - dwTimer > NTP_REPLY_TIMEOUT) { // Abort the request and wait until the next timeout period closesocket(bsdUdpClient); dwTimer = TickGetDiv64K(); SNTPState = SM_SHORT_WAIT; break; } break; } closesocket(bsdUdpClient); dwTimer = TickGetDiv64K(); SNTPState = SM_WAIT; // Set out local time to match the returned time dwLastUpdateTick = TickGet(); dwSNTPSeconds = swapl(pkt.tx_ts_secs) - NTP_EPOCH; // Do rounding. If the partial seconds is > 0.5 then add 1 to the seconds count. if(((BYTE*)&pkt.tx_ts_fraq)[0] & 0x80) dwSNTPSeconds++; break; case SM_SHORT_WAIT: // Attempt to requery the NTP server after a specified NTP_FAST_QUERY_INTERVAL time (ex: 8 seconds) has elapsed. if(TickGetDiv64K() - dwTimer > (NTP_FAST_QUERY_INTERVAL/65536ull)) SNTPState = SM_HOME; break; case SM_WAIT: // Requery the NTP server after a specified NTP_QUERY_INTERVAL time (ex: 10 minutes) has elapsed. if(TickGetDiv64K() - dwTimer > (NTP_QUERY_INTERVAL/65536ull)) SNTPState = SM_HOME; break; } //#if defined(STACK_USE_DNS) #else #warning You must define STACK_USE_DNS for BerkeleyUDPClientDemo to work #endif }
/***************************************************************************** Function: CHAR TFTPGetUploadStatus(void) Summary: Returns the TFTP file upload status started by calling the TFTPUploadRAMFileToHost() or TFTPUploadFragmentedRAMFileToHost() functions. Description: Returns the TFTP file upload status started by calling the TFTPUploadRAMFileToHost() or TFTPUploadFragmentedRAMFileToHost() functions. Precondition: None Parameters: None Returns: A status code. Negative results are fatal errors. Positive results indicate the TFTP upload operation is still being processed. A zero result indicates successful file upload completion (TFTP API is now idle and available for further calls). Specific return values are as follows: 0 (TFTP_UPLOAD_COMPLETE): Upload completed successfully 1 (TFTP_UPLOAD_GET_DNS): Attempting to obtain DNS client module 2 (TFTP_UPLOAD_RESOLVE_HOST): Attempting to resolve TFTP hostname 3 (TFTP_UPLOAD_CONNECT): Attempting to ARP and contact the TFTP server 4 (TFTP_UPLOAD_SEND_FILENAME): Attempting to send the filename and receive acknowledgement. 5 (TFTP_UPLOAD_SEND_DATA): Attempting to send the file contents and receive acknowledgement. 6 (TFTP_UPLOAD_WAIT_FOR_CLOSURE): Attempting to send the final packet of file contents and receive acknowledgement. -1 (TFTP_UPLOAD_HOST_RESOLVE_TIMEOUT): Couldn't resolve hostname -2 (TFTP_UPLOAD_CONNECT_TIMEOUT): Couldn't finish ARP and reach server -3 (TFTP_UPLOAD_SERVER_ERROR): TFTP server returned an error (ex: access denial) or file upload failed due to a timeout (partial file may have been uploaded). Remarks: The DNS client module must be enabled to use this function. i.e. STACK_USE_DNS must be defined in TCPIPConfig.h. ***************************************************************************/ CHAR TFTPGetUploadStatus(void) { TFTP_RESULT result; IP_ADDR ipRemote; WORD w, w2; BYTE *vData; if(UDPIsOpened(_tftpSocket)== FALSE) { _tftpSocket = UDPOpenEx((DWORD)(ROM_PTR_BASE)vUploadRemoteHost, UDP_OPEN_ROM_HOST,TFTP_CLIENT_PORT, TFTP_SERVER_PORT); } switch(smUpload) { case TFTP_UPLOAD_GET_DNS: if(!DNSBeginUsage()) break; DNSResolveROM(vUploadRemoteHost, DNS_TYPE_A); smUpload = TFTP_UPLOAD_RESOLVE_HOST; break; case TFTP_UPLOAD_RESOLVE_HOST: if(!DNSIsResolved(&ipRemote)) break; DNSEndUsage(); if(ipRemote.Val == 0u) { smUpload = TFTP_UPLOAD_HOST_RESOLVE_TIMEOUT; break; } TFTPOpen(&ipRemote); smUpload = TFTP_UPLOAD_CONNECT; break; case TFTP_UPLOAD_CONNECT: switch(TFTPIsOpened()) { case TFTP_OK: TFTPOpenROMFile(vUploadFilename, TFTP_FILE_MODE_WRITE); smUpload = TFTP_UPLOAD_SEND_FILENAME; break; case TFTP_TIMEOUT: smUpload = TFTP_UPLOAD_CONNECT_TIMEOUT; break; default: break; } break; case TFTP_UPLOAD_SEND_FILENAME: result = TFTPIsFileOpened(); switch(result) { case TFTP_OK: smUpload = TFTP_UPLOAD_SEND_DATA; break; case TFTP_RETRY: TFTPOpenROMFile(vUploadFilename, TFTP_FILE_MODE_WRITE); break; case TFTP_TIMEOUT: smUpload = TFTP_UPLOAD_CONNECT_TIMEOUT; break; case TFTP_ERROR: smUpload = TFTP_UPLOAD_SERVER_ERROR; break; default: break; } if(result != TFTP_OK) break; // No break when TFTPIsFileOpened() returns TFTP_OK -- we need to immediately start sending data case TFTP_UPLOAD_SEND_DATA: switch(TFTPIsPutReady()) { case TFTP_OK: // Write blocksize bytes of data uploadChunkDescriptorForRetransmit = uploadChunkDescriptor; wUploadChunkOffsetForRetransmit = wUploadChunkOffset; vData = uploadChunkDescriptor->vDataPointer + wUploadChunkOffset; w = TFTP_BLOCK_SIZE; while(w) { w2 = uploadChunkDescriptor->wDataLength - wUploadChunkOffset; if(w2 > w) w2 = w; w -= w2; wUploadChunkOffset += w2; if(vData == NULL) { TFTPCloseFile(); smUpload = TFTP_UPLOAD_WAIT_FOR_CLOSURE; break; } while(w2--) { TFTPPut(*vData++); } if(wUploadChunkOffset == uploadChunkDescriptor->wDataLength) { uploadChunkDescriptor++; wUploadChunkOffset = 0; vData = uploadChunkDescriptor->vDataPointer; } } break; case TFTP_RETRY: uploadChunkDescriptor = uploadChunkDescriptorForRetransmit; wUploadChunkOffset = wUploadChunkOffsetForRetransmit; break; case TFTP_TIMEOUT: case TFTP_ERROR: smUpload = TFTP_UPLOAD_SERVER_ERROR; break; default: break; } break; case TFTP_UPLOAD_WAIT_FOR_CLOSURE: switch(TFTPIsFileClosed()) { case TFTP_OK: smUpload = TFTP_UPLOAD_COMPLETE; UDPClose(_tftpSocket); break; case TFTP_RETRY: uploadChunkDescriptor = uploadChunkDescriptorForRetransmit; wUploadChunkOffset = wUploadChunkOffsetForRetransmit; smUpload = TFTP_UPLOAD_SEND_DATA; break; case TFTP_TIMEOUT: case TFTP_ERROR: smUpload = TFTP_UPLOAD_SERVER_ERROR; break; default: break; } break; default: break; } return smUpload; }