/*****************************************************************************
  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;
	}
}
Beispiel #2
0
/*********************************************************************
 * 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;
}
Beispiel #3
0
/*****************************************************************************
  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;
	}
}
Beispiel #4
0
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;
   }
}
Beispiel #5
0
/******************************************************************************
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
}
Beispiel #8
0
/*****************************************************************************
  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;
}