示例#1
0
/****************************************************************************
  Function:
   WORD ChipKITUDPSendPacketURL(UDP_SOCKET hUDP, BYTE * rgbBuf, WORD cbBuff, const char * szURL, WORD port, unsigned int cSecTimeout)

  Description:
    Implementes the Arduino UDP SendPacket function.
 
  Parameters:
    hUDP        - the UDP socket to use

    rgbBuf      - a pointer to a buffer of bytes to send

    cbBuff      - the number of bytes to send

    szURL       - The URL to send the packet to. This is a hostname or string IP address

    port        - the remote port to send it data to

    cSecTimeout - the ARP may take too long, after this many seconds it wil fail and return with 0 bytes sent.
                    It may be somehow possible for the UDP transmit to fail as well and this function will abort if
                    the timeout is exceeded.
 
  Returns:
    The actually number of bytes sent, this may be 0 if the ARP failed, or less than cbBuff if something went wrong.

  Remarks:
    If the ARP succeeds, the data will typically just be blasted on the wire as UDP is an unreliable protocol and will rarely fail to transmit

  ***************************************************************************/
WORD ChipKITUDPSendPacketURL(UDP_SOCKET hUDP, BYTE * rgbBuf, WORD cbBuff, const char * szURL, WORD port, unsigned int cSecTimeout)
{
	DWORD 	t = 0;
	IP_ADDR	ipAddr;


// This will add full URL support (like HTTP=>port 80, TCPIP does not do this, so I am not implementing it for UDP either.
// that is, the URL is really just a hostname
#if 0
	BYTE * 	szHostName[256];	// max allowed for a host name
	WORD	cbHostNameBuff = sizeof(szHostName);
	WORD	wPort = INVALID_UDP_PORT;

	// parse the URL
	if(ExtractURLFields((BYTE *) szURL, NULL, NULL, NULL, NULL, NULL, (BYTE *) szHostName, &cbHostNameBuff, &wPort, NULL, NULL) != 0 )
	{
		return(0);
	}	
 
	// see if we should get the port from the URL
	if(port == INVALID_UDP_PORT)
	{
		port = wPort;
	}
#endif

    // but we do support DNS lookup
	t = TickGet();
	while(!DNSBeginUsage())
	{
		ChipKITPeriodicTasks();

		if((TickGet() - t) >= (cSecTimeout * TICK_SECOND))
		{
			return(0);
		}
	}

	DNSResolve((BYTE *) szURL, DNS_TYPE_A);

	t = TickGet();
	while(!DNSIsResolved(&ipAddr))
	{
		ChipKITPeriodicTasks();

		if((TickGet() - t) >= (cSecTimeout * TICK_SECOND))
		{
			DNSEndUsage();
			return(0);
		}
	}

	// if we actually resolved the URL
	if(DNSEndUsage())
	{
		return(UDPSendPacket(hUDP, rgbBuf, cbBuff, ipAddr, port, cSecTimeout));
	}

	return(0);
}
示例#2
0
/*****************************************************************************
  Function:
	WORD SMTPEndUsage(void)

  Summary:
	Releases control of the SMTP client module.

  Description:
	Call this function to release control of the SMTP client module once
	an application is finished using it.  This function releases the lock
	obtained by SMTPBeginUsage, and frees the SMTP client to be used by 
	another application.

  Precondition:
	SMTPBeginUsage returned TRUE on a previous call.

  Parameters:
	None

  Return Values:
	SMTP_SUCCESS - A message was successfully sent
	SMTP_RESOLVE_ERROR - The SMTP server could not be resolved
	SMTP_CONNECT_ERROR - The connection to the SMTP server failed or was
		prematurely terminated
	1-199 and 300-399 - The last SMTP server response code
  ***************************************************************************/
WORD SMTPEndUsage(void)
{
	if(!SMTPFlags.bits.SMTPInUse)
		return 0xFFFF;

	// Release the DNS module, if in use
	if(TransportState == TRANSPORT_NAME_RESOLVE)
		DNSEndUsage();
	
	// Release the TCP socket, if in use
	if(MySocket != INVALID_SOCKET)
	{
		TCPDisconnect(MySocket);
		MySocket = INVALID_SOCKET;
	}
	
	// Release the SMTP module
	SMTPFlags.bits.SMTPInUse = FALSE;
	TransportState = TRANSPORT_HOME;

	if(SMTPFlags.bits.SentSuccessfully)
	{
		return 0;
	}
	else
	{
		return ResponseCode;
	}
}
示例#3
0
/*****************************************************************************
  Function:
	void DNSClientDeInit(const TCPIP_STACK_MODULE_CTRL* const stackData);

  Summary:
	De-Initializes the DNS module.
	
  Description:
	This function perform the de-initialization of the DNS client module.
    It is used to release all the resources that are in use by the DNS client.
    
  Precondition:
	Stack is initialized.

  Parameters:
	stackData   - interface to use
                Normally should be a default DNS interface
                
  Return Values:
  	None
  	
  Remarks:
	None
  ***************************************************************************/
void DNSClientDeInit(const TCPIP_STACK_MODULE_CTRL* const stackData)
{
    // interface going down
    if(pDNSNet == stackData->pNetIf)
    {   // my interface is shut down
        DNSEndUsage(0);
    }
        
    if(stackData->stackAction == TCPIP_STACK_ACTION_DEINIT)
    {   // stack shut down
        if(dnsInitCount > 0)
        {   // we're up and running

            if(--dnsInitCount == 0)
            {   // all closed
                // release resources
#if DNS_CLIENT_VERSION_NO >= 2
                if(dnsTimerHandle)
                {
                    SYS_TICK_TimerDelete(dnsTimerHandle);
                    dnsTimerHandle = 0;
                    dnsTickPending = 0;
                }
#endif  // DNS_CLIENT_VERSION_NO >= 2
            }
        }
    }


}
示例#4
0
/*****************************************************************************
  Function:
	void TFTPUploadFragmentedRAMFileToHost(ROM BYTE *vRemoteHost, 
										   ROM BYTE *vFilename, 
										   TFTP_CHUNK_DESCRIPTOR *vFirstChunkDescriptor)
  Summary:
	Uploads an random, potentially non-contiguous, array of RAM bytes as a file 
	to a remote TFTP server.
	
  Description:
	Uploads an random, potentially non-contiguous, array of RAM bytes as a file 
	to a remote TFTP server.
	
  Precondition:
	None

  Parameters:
	vRemoteHost: ROM string of the remote TFTP server to upload to (ex: 
		"www.myserver.com").  For device architectures that make no distinction 
		between RAM and ROM pointers (PIC24, dsPIC and PIC32), this string must 
		remain allocated and unmodified in RAM until the TFTP upload process 
		completes (as indicated by TFTPGetUploadStatus()).  
	vFilename: ROM string of the remote file to create/overwrite (ex: 
		"status.txt").  For device architectures that make no distinction 
		between RAM and ROM pointers (PIC24, dsPIC and PIC32), this string must 
		remain allocated and unmodified in RAM until the TFTP upload process 
		completes (as indicated by TFTPGetUploadStatus()).
	vFirstChunkDescriptor: Pointer to a static or global (persistent) array of 
		TFTP_CHUNK_DESCRIPTOR structures describing what RAM memory addresses 
		the file contents should be obtained from.  The 
		TFTP_CHUNK_DESCRIPTOR.vDataPointer field should be set to the memory 
		address of the data to transmit, and the 
		TFTP_CHUNK_DESCRIPTOR.wDataLength field should be set to the number of 
		bytes to transmit from the given pointer.  The TFTP_CHUNK_DESCRIPTOR 
		array must be terminated by a dummy descriptor whos 
		TFTP_CHUNK_DESCRIPTOR.vDataPointer pointer is set to NULL.  Refer to the 
		TFTPUploadRAMFileToHost() API for an example calling sequence since it 
		merely a wrapper to this TFTPUploadFragmentedRAMFileToHost() function.

  Returns:
  	None
  
  Remarks:
	The DNS client module must be enabled to use this function.  i.e. 
	STACK_USE_DNS must be defined in TCPIPConfig.h.

  	Call the TFTPGetUploadStatus() function to determine the status of the file 
  	upload.
  	
  	It is only possible to have one TFTP operation active at any given time.  
  	After starting a TFTP operation by calling TFTPUploadRAMFileToHost() or 
  	TFTPUploadFragmentedRAMFileToHost(), you must wait until 
  	TFTPGetUploadStatus() returns a completion status code (<=0) before calling 
  	any other TFTP API functions.
  ***************************************************************************/
void TFTPUploadFragmentedRAMFileToHost(ROM BYTE *vRemoteHost, ROM BYTE *vFilename, TFTP_CHUNK_DESCRIPTOR *vFirstChunkDescriptor)
{
	vUploadRemoteHost = vRemoteHost;
	vUploadFilename = vFilename;
	uploadChunkDescriptor = vFirstChunkDescriptor;
	uploadChunkDescriptorForRetransmit = vFirstChunkDescriptor;
	wUploadChunkOffset = 0;
	wUploadChunkOffsetForRetransmit = 0;
	if(smUpload == TFTP_UPLOAD_RESOLVE_HOST)
		DNSEndUsage();
	smUpload = TFTP_UPLOAD_GET_DNS;
}
示例#5
0
文件: ICMP.c 项目: CEIT-UQ/RGB
/*********************************************************************
 * 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;
}
示例#6
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;
   }
}
示例#7
0
文件: UDP.c 项目: KiwiJaune/RecMiwiPi
/******************************************************************************
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)
		}
	}
} 
示例#8
0
/*********************************************************************
 * 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())
	    	{
//ML		    	DNSResolveROM(ServerName, DNS_TYPE_A);
		    	DNSResolve(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
}
示例#9
0
/*********************************************************************
 * Function:        void GenericTCPClient(void)
 *
 * PreCondition:    Stack is initialized()
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 ********************************************************************/
void GenericTCPClient(void)
{
	BYTE 				i;
	BYTE 				*StringPtr;
	static TICK			Timer;
	static TCP_SOCKET	MySocket = INVALID_SOCKET;
	static NODE_INFO	Server;
	static enum _GenericTCPExampleState
	{
		SM_HOME = 0,
		SM_NAME_RESOLVE,
		SM_ARP_START_RESOLVE,
		SM_ARP_RESOLVE,
		SM_SOCKET_OBTAIN,
		SM_SOCKET_OBTAINED,
		SM_PROCESS_RESPONSE,
		SM_DISCONNECT,
		SM_DONE
	} GenericTCPExampleState = SM_DONE;

	switch(GenericTCPExampleState)
	{
		case SM_HOME:
			// Obtain ownership of the DNS resolution module
			if(!DNSBeginUsage())
				break;

			// Obtain the IP address associated with the common ServerName
			DNSResolve(ServerName, DNS_TYPE_A);
			GenericTCPExampleState++;
			break;

		case SM_NAME_RESOLVE:
			// Wait for the DNS server to return the requested IP address
			if(!DNSIsResolved(&Server.IPAddr))
				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.
				GenericTCPExampleState = SM_DONE;
				break;
			}

			GenericTCPExampleState++;

		case SM_ARP_START_RESOLVE:
			// 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)
			ARPResolve(&Server.IPAddr);
			Timer = TickGet();
			GenericTCPExampleState++;
			break;

		case SM_ARP_RESOLVE:
			// 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()-Timer > 1*TICK_SECOND)
				{
					// Retransmit ARP request
					GenericTCPExampleState--;
				}
				break;
			}
			GenericTCPExampleState++;

		case SM_SOCKET_OBTAIN:
			// Connect a socket to the remote TCP server
			MySocket = TCPConnect(&Server, ServerPort);
			
			// Abort operation if no TCP sockets are available
			// If this ever happens, incrementing MAX_TCP_SOCKETS in 
			// StackTsk.h may help (at the expense of more global memory 
			// resources).
			if(MySocket == INVALID_SOCKET)
				break;

			GenericTCPExampleState++;
			Timer = TickGet();
			break;

		case SM_SOCKET_OBTAINED:
			// Wait for the remote server to accept our connection request
			if(!TCPIsConnected(MySocket))
			{
				// Time out if too much time is spent in this state
				if(TickGet()-Timer > 5*TICK_SECOND)
				{
					// Close the socket so it can be used by other modules
					TCPDisconnect(MySocket);
					MySocket = INVALID_SOCKET;
					GenericTCPExampleState--;
				}
				break;
			}

			Timer = TickGet();

			// Make certain the socket can be written to
			if(!TCPIsPutReady(MySocket))
				break;
			
			// Place the application protocol data into the transmit buffer.  For this example, we are connected to an HTTP server, so we'll send an HTTP GET request.
			TCPPutROMString(MySocket, (ROM BYTE*)"GET ");
			TCPPutROMString(MySocket, RemoteURL);
			TCPPutROMString(MySocket, (ROM BYTE*)" HTTP/1.1\r\nHost: ");
			TCPPutString(MySocket, ServerName);
			TCPPutROMString(MySocket, (ROM BYTE*)"\r\n\r\n");

			// Send the packet
			TCPFlush(MySocket);
			GenericTCPExampleState++;

		case SM_PROCESS_RESPONSE:
			// Check to see if the remote node has disconnected from us or sent us any application data
			// If application data is available, write it to the UART
			if(!TCPIsConnected(MySocket))
			{
				GenericTCPExampleState++;
			}
	
			if(!TCPIsGetReady(MySocket))
				break;
	
			// Obtain the server reply
			while(TCPGet(MySocket, &i))
			{
				while(BusyUART());
				WriteUART(i);
			}
	
			break;
	
		case SM_DISCONNECT:
			// Close the socket so it can be used by other modules
			// For this application, we wish to stay connected, but this state will still get entered if the remote server decides to disconnect
			TCPDisconnect(MySocket);
			MySocket = INVALID_SOCKET;
			GenericTCPExampleState = SM_DONE;
			break;
	
		case SM_DONE:
			// Do nothing unless the user pushes BUTTON1 and wants to restart the whole connection/download process
			if(BUTTON1_IO == 0u)
				GenericTCPExampleState = SM_HOME;
			break;
	}
}
/*****************************************************************************
  Function:
	void BerkeleyUDPClientDemo(uint32_t localIP)

  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:
	localIP   - the local interface to use

  Returns:
  	None
  	
  Remarks:
	This function requires once available UDP socket while processing, but
	frees that socket when the SNTP module is idle.
  ***************************************************************************/
void BerkeleyUDPClientDemo(uint32_t localIP)
{
	#if defined(TCPIP_STACK_USE_DNS)
	NTP_PACKET			pkt;
	int			 		i;
	static uint32_t		dwServerIP;
	static SYS_TICK		udpTick;
    static SOCKET		bsdUdpClient;
    int                 udpSkt;
    int 				addrlen = sizeof(struct sockaddr_in);
    static struct sockaddr_in	udpaddr;
    DNS_RESULT  dnsRes;
    
	static enum
	{
		SM_HOME = 0,
		SM_NAME_RESOLVE,
		SM_CREATE_SOCKET,
		SM_BIND,	
		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(0) != DNS_RES_OK)
            {
				break;
            }

			// Obtain the IP address associated with the server name
			DNSResolve(NTP_SERVER, DNS_TYPE_A);
			udpTick = SYS_TICK_Get();
			SNTPState = SM_NAME_RESOLVE;
			break;

		case SM_NAME_RESOLVE:
			// Wait for DNS resolution to complete
			dnsRes = DNSIsResolved(NTP_SERVER, (IP_ADDR*)&dwServerIP);
            if(dnsRes == DNS_RES_PENDING)
            {   // still waiting
                break;
            }
            
            // release the DNS module
	    	DNSEndUsage(0);

            if(dnsRes < 0)
            {   // some error
                udpTick = SYS_TICK_Get();
                SNTPState = SM_SHORT_WAIT;
                break;
            }
			
            // DNS_RES_OK
			SNTPState = SM_CREATE_SOCKET;
			// No break needed

		case SM_CREATE_SOCKET:
			udpSkt = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
			if(udpSkt == SOCKET_ERROR)
            {
				return;
            }
            else
            {
                bsdUdpClient = (SOCKET)udpSkt;
            }

// Usually no explicit binding is necessary since we are going to be the first one 
// sending a UDP packet.  sendto() will do implicit binding.  Explicit binding 
// is necessary only when creating UDP servers that will be receiving the first 
// packet.
// However, when using this example with multi-homed hosts we want to use
// a specified network connection specified by the localIP parameter
			SNTPState = SM_BIND;
			// No break needed
			
		case SM_BIND:
            udpaddr.sin_port = 0;
            udpaddr.sin_addr.S_un.S_addr = localIP;
            if( bind(bsdUdpClient, (struct sockaddr*)&udpaddr, addrlen) == SOCKET_ERROR )
                break;

            SNTPState = SM_UDP_SEND;
            // No break needed
            
		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 = dwServerIP;
			if(sendto(bsdUdpClient, (const char*)&pkt, sizeof(pkt), 0, (struct sockaddr*)&udpaddr, addrlen)>0)
            {
				udpTick = SYS_TICK_Get();
                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((SYS_TICK_Get()) - udpTick > NTP_REPLY_TIMEOUT * SYS_TICK_TicksPerSecondGet())
				{
					// Abort the request and wait until the next timeout period
					closesocket(bsdUdpClient);
					udpTick = SYS_TICK_Get();
					SNTPState = SM_SHORT_WAIT;
					break;
				}
				break;
			}
			closesocket(bsdUdpClient);
			udpTick = SYS_TICK_Get();
			SNTPState = SM_WAIT;

			// Set out local time to match the returned time
			dwLastUpdateTick = SYS_TICK_Get();
			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(((uint8_t*)&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(SYS_TICK_Get() - udpTick > (NTP_FAST_QUERY_INTERVAL * SYS_TICK_TicksPerSecondGet() ))
				SNTPState = SM_HOME;	
			break;

		case SM_WAIT:
			// Requery the NTP server after a specified NTP_QUERY_INTERVAL time (ex: 10 minutes) has elapsed.
			if(SYS_TICK_Get() - udpTick > (NTP_QUERY_INTERVAL * SYS_TICK_TicksPerSecondGet()))
				SNTPState = SM_HOME;	

			break;
	}

	//#if defined(TCPIP_STACK_USE_DNS)
	#else
		#warning You must define TCPIP_STACK_USE_DNS for BerkeleyUDPClientDemo 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
}
示例#12
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;
}
示例#13
0
/*****************************************************************************
  Function:
    void GenericTCPClient(void)

  Summary:
    Implements a simple HTTP client (over TCP).

  Description:
    This function implements a simple HTTP client, which operates over TCP.
    The function is called periodically by the stack, and waits for BUTTON1
    to be pressed.  When the button is pressed, the application opens a TCP
    connection to an Internet search engine, performs a search for the word
    "Microchip" on "microchip.com", and prints the resulting HTML page to
    the UART.

    This example can be used as a model for many TCP and HTTP client
    applications.

  Precondition:
    TCP is initialized.

  Parameters:
    None

  Returns:
      None
  ***************************************************************************/
void GenericTCPClient(void)
{
    uint8_t                 i;
    uint16_t                w;
    DNS_RESULT          dnsRes;
    uint8_t                vBuffer[9];
    static TCPIP_NET_HANDLE    netH;
    static uint32_t        clientTimer;
    static TCP_SOCKET    MySocket = INVALID_SOCKET;
    static uint32_t nAttempts =0;

    static enum _GenericTCPExampleState
    {
        SM_HOME = 0,
        SM_WAIT_DNS,
        SM_DNS_RESOLVED,
        SM_SOCKET_OBTAINED,
        SM_PROCESS_RESPONSE,
        SM_DISCONNECT,
        SM_DONE
    } GenericTCPExampleState = SM_DONE;

    //DBPRINTF("    Starting TCP client\n");

    switch(GenericTCPExampleState)
    {

        case SM_HOME:

            DBPRINTF("  SM_HOME\n");
            netH = TCPIP_STACK_GetDefaultNet();
            if(DNSBeginUsage(netH) != DNS_RES_OK)
            {
                break;
            }
            DNSResolve(ServerName, DNS_TYPE_A); 
            GenericTCPExampleState++;
            break;

        case SM_WAIT_DNS:

            DBPRINTF("  SM_WAIT_DNS\n");
            dnsRes = DNSIsResolved(ServerName, &serverIP);
            if(dnsRes == DNS_RES_PENDING)
            {   // ongoing operation;
                break;
            }
            else if(dnsRes < 0)
            {   // some DNS error occurred; retry
                DBPRINTF((const char*)"\r\n\r\nGeneric TCP client: DNS name resolving failed...\r\n");
                TCPClose(MySocket);
                MySocket = INVALID_SOCKET;
                GenericTCPExampleState = SM_HOME;
                nAttempts++;
                if(nAttempts>8) // After 8 attempts give-up
                {
                    GenericTCPExampleState = SM_DONE;
                    nAttempts=0;
                }
            }
            else
            {
                clientTimer = SYS_TICK_Get();
                GenericTCPExampleState++;
            }
            DNSEndUsage(netH);
            break;

        case SM_DNS_RESOLVED:
            DBPRINTF("  SM_DNS_RESOLVED\n");
            // Connect the socket to the remote TCP server
            MySocket = TCPOpenClient(IP_ADDRESS_TYPE_IPV4, ServerPort, (IP_MULTI_ADDRESS*)&serverIP);

			// Abort operation if no TCP socket could be opened.
			// If this ever happens, you need to update your tcp_config.h
            if(MySocket == INVALID_SOCKET)
            {   // retry
                break;
            }

            GenericTCPExampleState++;
            clientTimer = SYS_TICK_Get();
            break;

        case SM_SOCKET_OBTAINED:

            DBPRINTF("  SM_SOCKET_OBTAINED\n");
            // Wait for the remote server to accept our connection request
            if(!TCPIsConnected(MySocket))
            {
                // Time out if more than 5 seconds is spent in this state
                if((SYS_TICK_Get()-clientTimer) > 5 * SYS_TICK_TicksPerSecondGet() )
                {
                    // Close the socket so it can be used by other modules
                    TCPClose(MySocket);
                    MySocket = INVALID_SOCKET;
                    GenericTCPExampleState--;
                    DBPRINTF((const char*)"\r\n\r\nGeneric TCP client: Failed connecting to the remote server...\r\n");
                }
                break;
            }

            clientTimer = SYS_TICK_Get();

            // Make certain the socket can be written to
            if(TCPIsPutReady(MySocket) < 125u)
                break;

            // Place the application protocol data into the transmit buffer.  For this example, we are connected to an HTTP server, so we'll send an HTTP GET request.
            TCPPutString(MySocket, (const uint8_t*)"GET ");
            TCPPutString(MySocket, RemoteURL);
            TCPPutString(MySocket, (const uint8_t*)" HTTP/1.0\r\nHost: ");
            TCPPutString(MySocket, (const uint8_t*)ServerName);
            TCPPutString(MySocket, (const uint8_t*)"\r\nConnection: close\r\n\r\n");

            // Send the packet
            TCPFlush(MySocket);
            GenericTCPExampleState++;
            break;

        case SM_PROCESS_RESPONSE:
            //DBPRINTF("  SM_PROCESS_RESPONSE\n");
            // Check to see if the remote node has disconnected from us or sent us any application data
            // If application data is available, write it to the UART
            if(!TCPIsConnected(MySocket))
            {
                GenericTCPExampleState = SM_DISCONNECT;
                // Do not break;  We might still have data in the TCP RX FIFO waiting for us
            }

            // Get count of RX bytes waiting
            w = TCPIsGetReady(MySocket);

            // Obtian and print the server reply
            i = sizeof(vBuffer)-1;
            vBuffer[i] = '\0';
            while(w)
            {
                if(w < i)
                {
                    i = w;
                    vBuffer[i] = '\0';
                }
                w -= TCPGetArray(MySocket, vBuffer, i);
#if defined(GENERIC_TCP_CLIENT_ENABLE_UART_DUMP)
                DBPRINTF((char*)vBuffer);
#endif
                // SYS_CONSOLE_MESSAGE is a blocking call which will slow down the rest of the stack
                // if we shovel the whole TCP RX FIFO into the serial port all at once.
                // Therefore, let's break out after only one chunk most of the time.  The
                // only exception is when the remote node disconncets from us and we need to
                // use up all the data before changing states.
                if(GenericTCPExampleState == SM_PROCESS_RESPONSE)
                    break;
            }

            break;

        case SM_DISCONNECT:
            DBPRINTF("  SM_DISCONNECT\n");
            // Close the socket so it can be used by other modules
            // For this application, we wish to stay connected, but this state will still get entered if the remote server decides to disconnect
            TCPClose(MySocket);
            MySocket = INVALID_SOCKET;
            GenericTCPExampleState = SM_DONE;
            break;

        case SM_DONE:
            //DBPRINTF("  SM_DONE\n");
            // Do nothing unless the user pushes BUTTON1 and wants to restart the whole connection/download process
            // On many boards, SYS_USERIO_BUTTON_0 is assigned to sw1
            // SYS_USERIO_BUTTON_1=sw2 and SYS_USERIO_BUTTON_2=sw3
            if(SYS_USERIO_ButtonGet((SYS_USERIO_BUTTON_1),SYS_USERIO_BUTTON_ASSERTED))
                GenericTCPExampleState = SM_HOME;
            break;
    }
}
示例#14
0
/*****************************************************************************
  Function:
    void GenericSSLClient(void)

  Summary:
    Implements a simple HTTP client (over TCP).

  Description:
    This function implements a simple HTTP client, which operates over TCP.  
    The function is called periodically by the stack, and waits for BUTTON1 
    to be pressed.  When the button is pressed, the application opens a TCP
    connection to an Internet search engine, performs a search for the word
    "Microchip" on "microchip.com", and prints the resulting HTML page to
    the UART.  
    
    To add this to an existing application, make the call to GenericSSLClient 
    from StackTasks.
    
    This example can be used as a model for many TCP and HTTP client
    applications.

  Precondition:
    TCP is initialized.

  Parameters:
    None

  Returns:
    None
  ***************************************************************************/
void GenericSSLClient(void)
{
    uint8_t             i;
    uint16_t            w;
    DNS_RESULT          dnsRes;
    uint8_t             vBuffer[9];
    static TCPIP_NET_HANDLE    netH;
    static uint32_t     clientTimer;
    static TCP_SOCKET   MySocket = INVALID_SOCKET;
    static enum _GenericTCPExampleState
    {
        SM_HOME = 0,
        SM_WAIT_DNS,
        SM_DNS_RESOLVED,
        SM_SOCKET_OBTAINED,
        SM_START_SSL,
        SM_PROCESS_RESPONSE,
        SM_DISCONNECT,
        SM_DONE
    } GenericTCPExampleState = SM_DONE;

    switch(GenericTCPExampleState)
    {

        case SM_HOME:
            
            netH = TCPIP_STACK_GetDefaultNet();
            dnsRes = DNSBeginUsage(netH);
            if(dnsRes != DNS_RES_OK)
                break;
            DNSResolve(SSLServerName, DNS_TYPE_A);
            GenericTCPExampleState++;
            break;

        case SM_WAIT_DNS:
            
            dnsRes = DNSIsResolved(SSLServerName, &serverIP_SSL);
            if(dnsRes == DNS_RES_PENDING)
            {   // ongoing operation;
                break;
            }
            else if(dnsRes < 0)
            {   // some DNS error occurred; retry
                SYS_CONSOLE_MESSAGE((const char*)"\r\n\r\nDNS name resolving failed...\r\n");
                TCPClose(MySocket);
                MySocket = INVALID_SOCKET;
                GenericTCPExampleState = SM_HOME;
            }
            else
            {
                clientTimer = SYS_TICK_Get();
                GenericTCPExampleState++;
            }
            DNSEndUsage(netH);
            break;

        case SM_DNS_RESOLVED:
            // Connect the socket to the remote TCP server
            MySocket = TCPOpenClient(IP_ADDRESS_TYPE_IPV4, SSLServerPort, (IP_MULTI_ADDRESS*)&serverIP_SSL);
            
			// Abort operation if no TCP socket could be opened.
			// If this ever happens, you need to update your tcp_config.h
            if(MySocket == INVALID_SOCKET)
            {   // retry
                break;
            }

            SYS_CONSOLE_MESSAGE((const char*)"\r\n\r\nConnecting using Microchip TCP API...\r\n");

            GenericTCPExampleState++;
            clientTimer = SYS_TICK_Get();
            break;

        case SM_SOCKET_OBTAINED:

            // Wait for the remote server to accept our connection request
            if(!TCPIsConnected(MySocket))
            {
                // Time out if more than 5 seconds is spent in this state
                if((SYS_TICK_Get()-clientTimer) > 5 * SYS_TICK_TicksPerSecondGet() )
                {
                    // Close the socket so it can be used by other modules
                    TCPClose(MySocket);
                    MySocket = INVALID_SOCKET;
                    GenericTCPExampleState--;
                    SYS_CONSOLE_MESSAGE((const char*)"\r\n\r\nFailed connecting to the remote server...\r\n");
                }
                break;
            }

            clientTimer = SYS_TICK_Get();

            if(!TCPStartSSLClient(MySocket,(uint8_t *)"thishost"))
                break;

            GenericTCPExampleState++;
            break;

        case SM_START_SSL:
            if (TCPSSLIsHandshaking(MySocket)) 
            {
                // Handshaking may fail if the SSL_RSA_CLIENT_SIZE is not large enough
                // for the server’s certificate
                if(SYS_TICK_Get()-clientTimer > 10*SYS_TICK_TicksPerSecondGet())
                {
                    // Close the socket so it can be used by other modules
                    TCPClose(MySocket);
                    MySocket = INVALID_SOCKET;
                    GenericTCPExampleState=SM_HOME;
                }
                break;
            }


            // Make certain the socket can be written to
            if(TCPIsPutReady(MySocket) < 125u)
                break;
            
            // Place the application protocol data into the transmit buffer.  For this example, we are connected to an HTTP server, so we'll send an HTTP GET request.
            TCPPutString(MySocket, (const uint8_t*)"GET ");
            TCPPutString(MySocket, SSLRemoteURL);
            TCPPutString(MySocket, (const uint8_t*)" HTTP/1.0\r\nHost: ");
            TCPPutString(MySocket, (const uint8_t*)SSLServerName);
            TCPPutString(MySocket, (const uint8_t*)"\r\nConnection: close\r\n\r\n");

            // Send the packet
            TCPFlush(MySocket);
            GenericTCPExampleState++;
            break;

        case SM_PROCESS_RESPONSE:
            // Check to see if the remote node has disconnected from us or sent us any application data
            // If application data is available, write it to the UART
            if(!TCPIsConnected(MySocket))
            {
                GenericTCPExampleState = SM_DISCONNECT;
                // Do not break;  We might still have data in the TCP RX FIFO waiting for us
            }
    
            // Get count of RX bytes waiting
            w = TCPIsGetReady(MySocket);    
    
            // Obtian and print the server reply
            i = sizeof(vBuffer)-1;
            vBuffer[i] = '\0';
            while(w)
            {
                if(w < i)
                {
                    i = w;
                    vBuffer[i] = '\0';
                }
                w -= TCPGetArray(MySocket, vBuffer, i);
                SYS_CONSOLE_MESSAGE((char*)vBuffer);
                
                // SYS_CONSOLE_MESSAGE is a blocking call which will slow down the rest of the stack 
                // if we shovel the whole TCP RX FIFO into the serial port all at once.  
                // Therefore, let's break out after only one chunk most of the time.  The 
                // only exception is when the remote node disconncets from us and we need to 
                // use up all the data before changing states.
                if(GenericTCPExampleState == SM_PROCESS_RESPONSE)
                    break;
            }
    
            break;
    
        case SM_DISCONNECT:
            // Close the socket so it can be used by other modules
            // For this application, we wish to stay connected, but this state will still get entered if the remote server decides to disconnect
            TCPClose(MySocket);
            MySocket = INVALID_SOCKET;
            GenericTCPExampleState = SM_DONE;
            break;
    
        case SM_DONE:
            // Do nothing unless the user pushes BUTTON1 and wants to restart the whole connection/download process
            if(BUTTON1_IO == 0u)
                GenericTCPExampleState = SM_HOME;
            break;
    }
}
示例#15
0
/*****************************************************************************
  Function:
	void SMTPClientTask(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 SMTPClientTask(void)
{
    uint8_t			i;
    uint16_t			w;
    uint8_t			vBase64Buffer[4];
    static SYS_TICK	SMTPTimer;
    static uint8_t		RXBuffer[4];
    static const uint8_t *ROMStrPtr, *ROMStrPtr2;
    static const uint8_t *RAMStrPtr;
    static uint16_t		wAddressLength;
    DNS_RESULT      dnsRes;

    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(0) != DNS_RES_OK)
        {
            break;
        }

        // Obtain the IP address associated with the SMTP mail server
        if(SMTPClient.Server)
        {
            DNSResolve((const char*)SMTPClient.Server, 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)
            {
                SMTPClient.Server = strchr((char*)SMTPClient.To, '@');
            }

            if(!(SMTPClient.Server))
            {
                if(SMTPClient.CC)
                {
                    SMTPClient.Server = strchr((char*)SMTPClient.CC, '@');
                }
            }

            if(!(SMTPClient.Server))
            {
                if(SMTPClient.BCC)
                {
                    SMTPClient.Server = strchr((char*)SMTPClient.BCC, '@');
                }
            }

            // See if we found a hostname anywhere which we could resolve
            if(!(SMTPClient.Server))
            {
                DNSEndUsage(0);
                ResponseCode = SMTP_RESOLVE_ERROR;
                TransportState = TRANSPORT_HOME;
                break;
            }

            // Skip over the @ sign and resolve the host name
            SMTPClient.Server++;
            DNSResolve((const char*)SMTPClient.Server, DNS_TYPE_MX);
        }

        SMTPTimer = SYS_TICK_Get();
        TransportState++;
        break;

    case TRANSPORT_NAME_RESOLVE:
        // Wait for the DNS server to return the requested IP address
        dnsRes = DNSIsResolved((const char*)SMTPClient.Server, &SMTPServer);

        if(dnsRes == DNS_RES_PENDING)
        {
            break;
        }

        // Release the DNS module
        DNSEndUsage(0);

        if(dnsRes < 0)
        {   // some error occurred
            ResponseCode = SMTP_RESOLVE_ERROR;
            TransportState = TRANSPORT_HOME;
            break;
        }

        // DNS_RES_OK
        TransportState++;
    // No need to break here

    case TRANSPORT_OBTAIN_SOCKET:
        // Connect a TCP socket to the remote SMTP server
        MySocket = TCPOpenClient(IP_ADDRESS_TYPE_IPV4, SMTPClient.ServerPort, (IP_MULTI_ADDRESS*)&SMTPServer.Val);

        // Abort operation if no TCP socket could be opened.
        // If this ever happens, you need to update your tcp_config.h
        if(MySocket == INVALID_SOCKET)
            break;

        TransportState++;
        SMTPTimer = SYS_TICK_Get();
        // No break; fall into TRANSPORT_SOCKET_OBTAINED

#if defined(TCPIP_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((SYS_TICK_Get()-SMTPTimer) > (SMTP_SERVER_REPLY_TIMEOUT * SYS_TICK_TicksPerSecondGet()))
            {
                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
        SMTPTimer = SYS_TICK_Get();
        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 || ((SYS_TICK_Get()-SMTPTimer) > (SMTP_SERVER_REPLY_TIMEOUT * SYS_TICK_TicksPerSecondGet())))
            {
                ResponseCode = SMTP_CONNECT_ERROR;
                TransportState = TRANSPORT_CLOSE;
            }

            break;
        }
        SMTPFlags.bits.ConnectedOnce = true;

#if defined(TCPIP_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)
                                    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:
                            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 == NULL)
                TCPPutString(MySocket, (uint8_t*)"HELO MCHPBOARD\r\n");
            else
                TCPPutString(MySocket, (uint8_t*)"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 (SMTPClient.Username is non-NULL)
            TCPPutString(MySocket, (uint8_t*)"AUTH LOGIN\r\n");
            TCPFlush(MySocket);
            SMTPState++;
            break;

        case SMTP_AUTH_USERNAME:
            // Base 64 encode and transmit the username.
            RAMStrPtr = (uint8_t*)SMTPClient.Username;
            w = strlen((char*)RAMStrPtr);

            while(w)
            {
                i = 0;
                while((i < w) && (i < sizeof(vBase64Buffer)*3/4))
                {
                    vBase64Buffer[i] = *RAMStrPtr++;
                    i++;
                }
                w -= i;
                TCPIP_Helper_Base64Encode(vBase64Buffer, i, vBase64Buffer, sizeof(vBase64Buffer));
                TCPPutArray(MySocket, vBase64Buffer, sizeof(vBase64Buffer));
            }
            TCPPutString(MySocket, (uint8_t*)"\r\n");
            TCPFlush(MySocket);
            SMTPState++;
            break;

        case SMTP_AUTH_PASSWORD:
            // Base 64 encode and transmit the password
            RAMStrPtr = (uint8_t*)SMTPClient.Password;
            w = strlen((char*)RAMStrPtr);

            while(w)
            {
                i = 0;
                while((i < w) && (i < sizeof(vBase64Buffer)*3/4))
                {
                    vBase64Buffer[i] = *RAMStrPtr++;
                    i++;
                }
                w -= i;
                TCPIP_Helper_Base64Encode(vBase64Buffer, i, vBase64Buffer, sizeof(vBase64Buffer));
                TCPPutArray(MySocket, vBase64Buffer, sizeof(vBase64Buffer));
            }
            TCPPutString(MySocket, (uint8_t*)"\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.
            TCPPutString(MySocket, (uint8_t*)"MAIL FROM:<");
            RAMStrPtr = FindEmailAddress((uint8_t*)SMTPClient.From, &wAddressLength);
            TCPPutArray(MySocket, RAMStrPtr, wAddressLength);
            TCPPutString(MySocket, (uint8_t*)">\r\n");
            TCPFlush(MySocket);
            SMTPState++;
            break;

        case SMTP_RCPTTO_INIT:
            // See if there are any (To) recipients to process
            if(SMTPClient.To)
            {
                RAMStrPtr = FindEmailAddress((uint8_t*)SMTPClient.To, &wAddressLength);
                if(wAddressLength)
                {
                    SMTPState = SMTP_RCPTTO;
                    break;
                }
            }

            SMTPState = SMTP_RCPTTOCC_INIT;
            break;

        case SMTP_RCPTTO:
        case SMTP_RCPTTOCC:
        case SMTP_RCPTTOBCC:
            TCPPutString(MySocket, (uint8_t*)"RCPT TO:<");
            TCPPutArray(MySocket, RAMStrPtr, wAddressLength);
            TCPPutString(MySocket, (uint8_t*)">\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
            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)
            {
                RAMStrPtr = FindEmailAddress((uint8_t*)SMTPClient.CC, &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
            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)
            {
                RAMStrPtr = FindEmailAddress((uint8_t*)SMTPClient.BCC, &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
            RAMStrPtr = FindEmailAddress(RAMStrPtr+wAddressLength, &wAddressLength);

            if(wAddressLength)
            {
                SMTPState = SMTP_RCPTTOBCC;
                break;
            }

            // All done with BCC field
            SMTPState++;
        //No break

        case SMTP_DATA:
            TCPPutString(MySocket, (uint8_t*)"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)
                    {
                        PutHeadersState = PUTHEADERS_FROM;
                        TCPPutString(MySocket, (uint8_t*)"From: ");
                    }
                    else
                    {
                        PutHeadersState = PUTHEADERS_TO_INIT;
                    }
                    break;

                case PUTHEADERS_FROM:
                    SMTPClient.From = (char*)TCPPutString(MySocket, (uint8_t*)SMTPClient.From);
                    if(*SMTPClient.From == 0u)
                        PutHeadersState = PUTHEADERS_TO_INIT;
                    break;

                case PUTHEADERS_TO_INIT:
                    if(SMTPClient.To)
                    {
                        PutHeadersState = PUTHEADERS_TO;
                        TCPPutString(MySocket, (uint8_t*)"\r\nTo: ");
                    }
                    else
                    {
                        PutHeadersState = PUTHEADERS_CC_INIT;
                    }
                    break;

                case PUTHEADERS_TO:
                    SMTPClient.To = (char*)TCPPutString(MySocket, (uint8_t*)SMTPClient.To);
                    if(*SMTPClient.To == 0u)
                        PutHeadersState = PUTHEADERS_CC_INIT;
                    break;

                case PUTHEADERS_CC_INIT:
                    if(SMTPClient.CC)
                    {
                        PutHeadersState = PUTHEADERS_CC;
                        TCPPutString(MySocket, (uint8_t*)"\r\nCC: ");
                    }
                    else
                    {
                        PutHeadersState = PUTHEADERS_SUBJECT_INIT;
                    }
                    break;

                case PUTHEADERS_CC:
                    SMTPClient.CC = (char*)TCPPutString(MySocket, (uint8_t*)SMTPClient.CC);
                    if(*SMTPClient.CC == 0u)
                        PutHeadersState = PUTHEADERS_SUBJECT_INIT;
                    break;

                case PUTHEADERS_SUBJECT_INIT:
                    if(SMTPClient.Subject)
                    {
                        PutHeadersState = PUTHEADERS_SUBJECT;
                        TCPPutString(MySocket, (uint8_t*)"\r\nSubject: ");
                    }
                    else
                    {
                        PutHeadersState = PUTHEADERS_OTHER_INIT;
                    }
                    break;

                case PUTHEADERS_SUBJECT:
                    SMTPClient.Subject = (char*)TCPPutString(MySocket, (uint8_t*)SMTPClient.Subject);
                    if(*SMTPClient.Subject == 0u)
                        PutHeadersState = PUTHEADERS_OTHER_INIT;
                    break;

                case PUTHEADERS_OTHER_INIT:
                    TCPPutArray(MySocket, (uint8_t*)"\r\n", 2);
                    if(SMTPClient.OtherHeaders)
                    {
                        PutHeadersState = PUTHEADERS_OTHER;
                    }
                    else
                    {
                        TCPPutArray(MySocket, (uint8_t*)"\r\n", 2);
                        PutHeadersState = PUTHEADERS_DONE;
                        SMTPState++;
                    }
                    break;

                case PUTHEADERS_OTHER:
                    SMTPClient.OtherHeaders = (char*)TCPPutString(MySocket, (uint8_t*)SMTPClient.OtherHeaders);
                    if(*SMTPClient.OtherHeaders == 0u)
                    {
                        TCPPutArray(MySocket, (uint8_t*)"\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 = (uint8_t*)SMTPClient.Body;
            ROMStrPtr2 = (const uint8_t*)"\r\n.\r\n";
            CRPeriod.Pos = NULL;
            if(RAMStrPtr)
                CRPeriod.Pos = (uint8_t*)strstr((char*)RAMStrPtr, (const char*)"\r\n.");
        // No break here

        case SMTP_DATA_BODY:
            if(SMTPClient.Body)
            {
                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 = (uint8_t*)strstr((char*)RAMStrPtr, (const 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 = TCPPutString(MySocket, (uint8_t*)ROMStrPtr2);
                    TCPFlush(MySocket);
                }
            }
            else
            {
                if(SMTPFlags.bits.ReadyToFinish)
                {
                    if(*ROMStrPtr2)
                    {
                        ROMStrPtr2 = TCPPutString(MySocket, (uint8_t*)ROMStrPtr2);
                        TCPFlush(MySocket);
                    }

                }
            }

            if(*ROMStrPtr2 == 0u)
            {
                SMTPState++;
            }
            break;

        case SMTP_QUIT_INIT:
            SMTPState++;
            ROMStrPtr = (const uint8_t*)"QUIT\r\n";
        // No break here

        case SMTP_QUIT:
            if(*ROMStrPtr)
            {
                ROMStrPtr = TCPPutString(MySocket, (uint8_t*)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
        TCPClose(MySocket);
        MySocket = INVALID_SOCKET;

        // Go back to doing nothing
        TransportState = TRANSPORT_HOME;
        break;
    }
}
示例#16
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;
	}
}
示例#17
0
/*****************************************************************************
  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;
	}
}
示例#18
0
/*****************************************************************************
  Function:
	void PingDemoTask (void)

  Summary:
	Handles state machine for ping demo processes.
	
  Description:
	This function performs state processing for the ping demo.
	
	This function can be used as a model for applications requiring Ping6 
	capabilities to check if a host is reachable.

  Precondition:
	None.

  Parameters:
	None

  Returns:
  	None
  ***************************************************************************/
void PingDemoTask (void)
{
    switch (pingState)
    {
#if defined (TCPIP_STACK_USE_ICMP_CLIENT)
        case STATE_DNS_SEND_QUERY_IPV4:
            if (!DNSBeginUsage(pNetIf))
                return;

            if (DNSResolve((const char *)targetHostName, DNS_TYPE_A) != DNS_RES_OK)
                return;

            pingTimer = SYS_TICK_Get() + (SYS_TICK_ResolutionGet() * TCPIP_PING_DNS_TIMEOUT);
            pingState = STATE_DNS_GET_RESPONSE_IPV4;
            break;
        case STATE_DNS_GET_RESPONSE_IPV4:
            {
                DNS_RESULT res;
                if ((long)(SYS_TICK_Get() - pingTimer) > 0)
                {
                    SYS_OUT_MESSAGE_LINE("Couldn't resolve", 2);
                    DNSEndUsage(pNetIf);
                    pingState = STATE_IDLE;
                    return;
                } 
    
                res = DNSIsResolved((const char *)targetHostName, &targetAddressIPv4);

                switch (res)
                {
                    case DNS_RES_OK:
                        DNSEndUsage(pNetIf);
                        pingState = STATE_RESOLVE_ARP;
                        break;
                    case DNS_RES_PENDING:
                        
                        break;
                    default:
                        SYS_OUT_MESSAGE_LINE ("Couldn't resolve", 1);
                        DNSEndUsage(pNetIf);
                        pingState = STATE_IDLE;
                        break;
                }
            }
            break;
		case STATE_RESOLVE_ARP:
            if ((targetAddressIPv4.Val & pNetIf->MyMask.Val) == pNetIf->MyMask.Val)
                firstHopAddress.Val = targetAddressIPv4.Val;
            else
                firstHopAddress.Val = pNetIf->MyGateway.Val;
  			ARPResolve(pNetIf, &firstHopAddress);
			pingTimer = SYS_TICK_Get();
			pingState = STATE_ARP_RESOLVED;
			break;

		case STATE_ARP_RESOLVED:
			if(!ARPIsResolved(pNetIf, &firstHopAddress, &targetMACAddr))
			{
				if(SYS_TICK_Get() - pingTimer > (TCPIP_PING_DNS_TIMEOUT * SYS_TICK_TicksPerSecondGet()))
                {
                    SYS_OUT_MESSAGE_LINE ("Couldn't ARP", 1);
					pingState = STATE_IDLE;
                }
				break;
			}

			pingState = STATE_SEND_ECHO_REQUEST_IPV4;
            break;
#endif
#if defined (TCPIP_STACK_USE_IPV6)
        case STATE_DNS_SEND_QUERY_IPV6:
            if (!DNSBeginUsage(pNetIf))
                return;

            if (DNSResolve((const char *)targetHostName, DNS_TYPE_AAAA) != DNS_RES_OK)
                return;

            pingTimer = SYS_TICK_Get() + (SYS_TICK_ResolutionGet() * TCPIP_PING_DNS_TIMEOUT);
            pingState = STATE_DNS_GET_RESPONSE_IPV6;
            break;
        case STATE_DNS_GET_RESPONSE_IPV6:
            {
                DNS_RESULT res;
                if ((long)(SYS_TICK_Get() - pingTimer) > 0)
                {
                    SYS_OUT_MESSAGE_LINE ("Couldn't resolve", 1);
                    DNSEndUsage(pNetIf);
                    pingState = STATE_IDLE;
                    return;
                } 
    
                res = DNSIsResolved((const char *)targetHostName, &targetAddressIPv6);

                switch (res)
                {
                    case DNS_RES_OK:
                        DNSEndUsage(pNetIf);
                        pingState = STATE_SEND_ECHO_REQUEST_IPV6;
                        break;
                    case DNS_RES_PENDING:
                        
                        break;
                    default:
                        SYS_OUT_MESSAGE_LINE ("Couldn't resolve", 1);
                        DNSEndUsage(pNetIf);
                        pingState = STATE_IDLE;
                        break;
                }
            }
            break;
#endif
#if defined(TCPIP_STACK_USE_ICMP_CLIENT)
        case STATE_SEND_ECHO_REQUEST_IPV4:
            {
                NODE_INFO info;

                info.IPAddr = targetAddressIPv4;
                memcpy (&info.MACAddr, &targetMACAddr, sizeof (MAC_ADDR));
                ICMPSendEchoRequest (&info, ++wICMPSequenceNumber, 0xBEEF);

    			// Record the current time.  This will be used as a basis for 
    			// finding the echo response time, which exludes the ARP and DNS 
    			// steps
   			    pingTimer = SYS_TICK_Get();
    
                pingCount++;

                SYS_OUT_MESSAGE_LINE ("Pinging...", 1);

    			// Echo sent, advance state
    			pingState = STATE_GET_RESPONSE_IPV4;
            }
            break;
#endif
#if defined (TCPIP_STACK_USE_IPV6)
        case STATE_SEND_ECHO_REQUEST_IPV6:
            {
                IP_PACKET * pkt;
                IPV6_ADDR_STRUCT * localAddress;

                localAddress = TCPIP_IPV6_DAS_SelectSourceAddress (pNetIf, &targetAddressIPv6, NULL);

                if (localAddress == NULL)
                {
                    SYS_OUT_MESSAGE_LINE ("No local addr!", 1);
                    pingState = STATE_IDLE;
                    break;
                }
    
                pkt = TCPIP_ICMPV6_PutHeaderEchoRequest (pNetIf, &localAddress->address, &targetAddressIPv6, ICMPV6_INFO_ECHO_REQUEST, 
                                                    0xEFBE, ++wICMPSequenceNumber);
    
                if (TCPIP_IP_IsTxPutReady(pkt, 4) < 4)
                {
                    TCPIP_IP_FreePacket (pkt);
                    return;
                }
    
                TCPIP_IP_PutArray (pkt, (uint8_t *)&miscData, sizeof (uint32_t));
    
                // Just let the IPv6 module figure out the next hop neighbor and its MAC address
                TCPIP_ICMPV6_Flush (pkt);
    		
    			// Record the current time.  This will be used as a basis for 
    			// finding the echo response time, which exludes the ARP and DNS 
    			// steps
   			    pingTimer = SYS_TICK_Get();
    
                pingCount++;

                SYS_OUT_MESSAGE_LINE ("Pinging...", 1);

    			// Echo sent, advance state
    			pingState = STATE_GET_RESPONSE_IPV6;
            }
            break;
#endif
#if defined (TCPIP_STACK_USE_ICMP_CLIENT)
        case STATE_GET_RESPONSE_IPV4:
            if ((long)(SYS_TICK_Get() - pingTimer) > (SYS_TICK_ResolutionGet() * TCPIP_PING_TIMEOUT))
            {
                SYS_OUT_MESSAGE_LINE("Ping timeout", 1);
                pingState = STATE_IDLE;
            }            
            break;
#endif
#if defined (TCPIP_STACK_USE_IPV6)
        case STATE_GET_RESPONSE_IPV6:
            if ((long)(SYS_TICK_Get() - pingTimer) > (SYS_TICK_ResolutionGet() * TCPIP_PING_TIMEOUT))
            {
                SYS_OUT_MESSAGE_LINE ("Ping timeout", 1);
                pingState = STATE_IDLE;
            }
            break;
#endif
        default:
        case STATE_IDLE:
            break;
        
    }
}