Esempio n. 1
0
ssize_t microchip_udp_read(UDP_SOCKET socket, uint8_t* buf, size_t len, uint32_t* addr, uint16_t* port) {
    ssize_t rlen;
#if NABTO_LOG_CHECK(NABTO_LOG_SEVERITY_TRACE)
    UDP_SOCKET_INFO* debug;
    uint32_t sourceIp;
#endif
    if (UDPIsGetReady(socket)) {
#if NABTO_LOG_CHECK(NABTO_LOG_SEVERITY_TRACE)
        debug = &UDPSocketInfo[socket];
        READ_U32(sourceIp, &debug->remote.remoteNode.IPAddr.Val);
#endif

        unabto_microchip_arp_add_resolved(&(UDPSocketInfo[socket].remote.remoteNode));
        //        *addr = ntohl(UDPSocketInfo[socket].remote.remoteNode.IPAddr.Val);
        WRITE_U32(addr, UDPSocketInfo[socket].remote.remoteNode.IPAddr.Val);
        *port = UDPSocketInfo[socket].remotePort;
        rlen = (ssize_t) UDPGetArray(buf, len);
        NABTO_LOG_TRACE(("UDP read length: %i, %" PRIu16 " <- " PRIip ":%" PRIu16, rlen, debug->localPort, MAKE_IP_PRINTABLE(sourceIp), debug->remotePort));

        NABTO_LOG_BUFFER(NABTO_LOG_SEVERITY_TRACE, ("UDP in datagram"), buf, rlen);

        return rlen;
    }

    return 0;
}
Esempio n. 2
0
/*****************************************************************************
  Function:
	int recv( SOCKET s, char* buf, int len, int flags )

  Summary:
	The recv() function is used to receive incoming data that has
	been queued for a socket.

  Description:
	The recv() function is used to receive incoming data that has
	been queued for a socket. This function can be used with both 
	datagram and stream socket. If the available data
	is too large to fit in the supplied application buffer buf,
	excess bytes are discarded in case of SOCK_DGRAM type
	sockets.  For SOCK_STREAM types, the data is buffered
	internally so the application can retreive all data by
	multiple calls of recvfrom.

  Precondition:
	connect function should be called for TCP and UDP sockets.
	Server side, accept function should be called.

  Parameters:
	s - Socket descriptor returned from a previous call to socket.
	buf - application data receive buffer.
	len - buffer length in bytes.
	flags - no significance in this implementation

  Returns:
	If recv is successful, the number of bytes copied to
	application buffer buf is returned. A value of zero indicates
	no data available. A return value of SOCKET_ERROR (-1)
	indicates an error condition. A return value of SOCKET_DISCONNECTED
	indicates the connection no longer exists.

  Remarks:
	None.
  ***************************************************************************/
int recv( SOCKET s, char* buf, int len, int flags )
{
	struct BSDSocket *socket;

	if( s >= BSD_SOCKET_COUNT )
		return SOCKET_ERROR;

	socket = &BSDSocketArray[s];

	if(socket->SocketType == SOCK_STREAM) //TCP
	{
		if(socket->bsdState != SKT_EST)
			return SOCKET_ERROR;

		if(HandlePossibleTCPDisconnection(s))
			return SOCKET_ERROR;

		return TCPGetArray(socket->SocketID, (BYTE*)buf, len);
	}
	else if(socket->SocketType == SOCK_DGRAM) //UDP
	{
		if(socket->bsdState != SKT_BOUND)
			return SOCKET_ERROR;

		if(UDPIsGetReady(socket->SocketID))
			return UDPGetArray((BYTE*)buf, len);
	}

	return 0;
}
Esempio n. 3
0
/*********************************************************************
 * Function:        void RebootTask(void)
 *
 * PreCondition:    Stack is initialized()
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Checks for incomming traffic on port 69.  
 *					Resets the PIC if a 'R' is received.
 *
 * Note:            This module is primarily for use with the 
 *					Ethernet bootloader.  By resetting, the Ethernet 
 *					bootloader can take control for a second and let
 *					a firmware upgrade take place.
 ********************************************************************/
void RebootTask(void)
{
	static UDP_SOCKET	MySocket = INVALID_UDP_SOCKET;
	struct
	{
		BYTE vMACAddress[6];
		DWORD dwIPAddress;
		WORD wChecksum;
	} BootloaderAddress;
	
	if(MySocket == INVALID_UDP_SOCKET)
		MySocket = UDPOpenEx(0,UDP_OPEN_SERVER,REBOOT_PORT,INVALID_UDP_PORT);
//		MySocket = UDPOpen(REBOOT_PORT, NULL, INVALID_UDP_PORT);

	if(MySocket == INVALID_UDP_SOCKET)
		return;

	// Do nothing if no data is waiting
	if(!UDPIsGetReady(MySocket))
		return;

	#if defined(REBOOT_SAME_SUBNET_ONLY)
		// Respond only to name requests sent to us from nodes on the same subnet
     	if((remoteNode.IPAddr.Val & AppConfig.MyMask.Val) != (AppConfig.MyIPAddr.Val & AppConfig.MyMask.Val))
		{
			UDPDiscard();
			return;
		}
	#endif

	// Get our MAC address, IP address, and compute a checksum of them 
	memcpy((void*)&BootloaderAddress.vMACAddress[0], (void*)&AppConfig.MyMACAddr.v[0], sizeof(AppConfig.MyMACAddr));
	BootloaderAddress.dwIPAddress = AppConfig.MyIPAddr.Val;
	BootloaderAddress.wChecksum = CalcIPChecksum((BYTE*)&BootloaderAddress, sizeof(BootloaderAddress) - sizeof(BootloaderAddress.wChecksum));
	
	// To enter the bootloader, we need to clear the /POR bit in RCON.
	// Otherwise, the bootloader will immediately hand off execution 
	// to us.
	#if defined(USE_LCD)
		strcpypgm2ram((char*)LCDText, "Bootloader Reset");
		LCDUpdate();
	#endif

#if !defined(__STM32F10X__)
	RCONbits.POR = 0;
	#if defined(__18CXX)
	{
		WORD_VAL wvPROD;

		wvPROD.Val = ((WORD)&BootloaderAddress);
		PRODH = wvPROD.v[1];
		PRODL = wvPROD.v[0];
	}
	#endif
#endif
	Reset();
}
Esempio n. 4
0
/*****************************************************************************
  Function:
	int recvfrom(SOCKET s, char* buf, int len, int flags, struct sockaddr* from, int* fromlen)

  Summary:
	The recvfrom() function is used to receive incoming data that
	has been queued for a socket.

  Description:
	The recvfrom() function is used to receive incoming data that
	has been queued for a socket. This function can be used with
	both datagram and stream type sockets. If the available data
	is too large to fit in the supplied application buffer buf,
	excess bytes are discarded in case of SOCK_DGRAM type
	sockets. For SOCK_STREAM types, the data is buffered
	internally so the application can retreive all data by
	multiple calls of recvfrom.

  Precondition:
	socket function should be called.

  Parameters:
	s - Socket descriptor returned from a previous call to socket.
	buf - application data receive buffer.
	len - buffer length in bytes.
	flags - message flags. Currently this is not supported.
	from - pointer to the sockaddr structure that will be
	filled in with the destination address.
	fromlen - size of buffer pointed by from.

  Returns:
	If recvfrom is successful, the number of bytes copied to
	application buffer buf is returned. A value of zero indicates
	no data available. A return value of SOCKET_ERROR (-1)
	indicates an error condition.

  Remarks:
	None.
  ***************************************************************************/
int recvfrom( SOCKET s, char* buf, int len, int flags, struct sockaddr* from, int* fromlen )
{
    struct BSDSocket *socket;
    struct sockaddr_in *rem_addr;
    SOCKET_INFO *remoteSockInfo;

    socket = &BSDSocketArray[s];
    rem_addr = (struct sockaddr_in *)from;

    if(socket->SocketType == SOCK_DGRAM) //UDP
    {
        // If this BSD socket doesn't have a Microchip UDP socket associated
        // with it yet, then no data can be received and we must not use the
        // socket->SocketID parameter, which isn't set yet.
        if(socket->bsdState != SKT_BOUND)
            return 0;

        if(UDPIsGetReady(socket->SocketID))
        {
            // Capture sender information (can change packet to packet)
            if(from && fromlen)
            {
                if((unsigned int)*fromlen >= sizeof(struct sockaddr_in))
                {
                    remoteSockInfo = TCPGetRemoteInfo(socket->SocketID);
                    rem_addr->sin_addr.S_un.S_addr = remoteSockInfo->remote.IPAddr.Val;
                    rem_addr->sin_port = remoteSockInfo->remotePort.Val;
                    *fromlen = sizeof(struct sockaddr_in);
                }
            }

            return UDPGetArray((BYTE*)buf, len);
        }
    }
    else  //TCP recieve from already connected socket.
    {
        if(from && fromlen)
        {
            // Capture sender information (will always match socket connection information)
            if((unsigned int)*fromlen >= sizeof(struct sockaddr_in))
            {
                remoteSockInfo = TCPGetRemoteInfo(socket->SocketID);
                rem_addr->sin_addr.S_un.S_addr = remoteSockInfo->remote.IPAddr.Val;
                rem_addr->sin_port = remoteSockInfo->remotePort.Val;
                *fromlen = sizeof(struct sockaddr_in);
            }
        }
        return recv(s, buf, len, 0);
    }
    return 0;
}
Esempio n. 5
0
/*********************************************************************
 * Function:        void TFTPCloseFile(void)
 *
 * Summary:         Sends file closing messages.
 *
 * PreCondition:    TFTPOpenFile() was called and TFTPIsFileOpened()
 *                  had returned with TFTP_OK.
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        If file is opened in read mode, it makes sure
 *                  that last ACK is sent to server
 *                  If file is opened in write mode, it makes sure
 *                  that last block is sent out to server and
 *                  waits for server to respond with ACK.
 *
 * Note:            TFTPIsFileClosed() must be called to confirm
 *                  if file was really closed.
 ********************************************************************/
void TFTPCloseFile(void)
{
    // If a file was opened for read, we can close it immediately.
    if ( _tftpFlags.bits.bIsReading )
    {
        // If this was premature close, make sure that we discard
        // current block.
        if ( !_tftpFlags.bits.bIsFlushed )
        {
            _tftpFlags.bits.bIsFlushed = TRUE;
            UDPIsGetReady(_tftpSocket);
            UDPDiscard();
        }

        if ( _tftpFlags.bits.bIsAcked )
        {
            _tftpFlags.bits.bIsClosed = TRUE;
            _tftpFlags.bits.bIsClosing = FALSE;
            return;
        }

        else
        {
            _tftpState = SM_TFTP_SEND_LAST_ACK;
            _tftpFlags.bits.bIsClosing = TRUE;
        }
        return;
    }

    // For write mode, if we have not flushed last block, do it now.
    if ( !_tftpFlags.bits.bIsFlushed )
    {
        _tftpFlags.bits.bIsFlushed = TRUE;
        UDPIsPutReady(_tftpSocket);
        UDPFlush();
    }

    // For write mode, if our last block was ack'ed by remote server,
    // file is said to be closed.
    if ( _tftpFlags.bits.bIsAcked )
    {
        _tftpFlags.bits.bIsClosed = TRUE;
        _tftpFlags.bits.bIsClosing = FALSE;
        return;
    }

    _tftpState = SM_TFTP_WAIT_FOR_ACK;
    _tftpFlags.bits.bIsClosing =  TRUE;

}
Esempio n. 6
0
/****************************************************************************
  Function:
   void ChipKITUDPClose(UDP_SOCKET hUDP)

  Description:
    reads the available bytes out of the UDP cache
 
  Parameters:
    hUDP        - the UDP socket to clsoe

 
  Returns:
    None
  Remarks:
    The socket is closed and the resources returned to the UDP stack. Also the cache buffers are released and freed.

  ***************************************************************************/
void ChipKITUDPClose(UDP_SOCKET hUDP)
{
    if(UDPIsGetReady(hUDP) > 0)
    {
        UDPDiscard();
    }

    UDPClose(hUDP);

	// delete our cache buffer
	if(rgUDPSocketBuffers[hUDP] != NULL)
	{
		free(rgUDPSocketBuffers[hUDP]);
		rgUDPSocketBuffers[hUDP] = NULL;
	}
}
Esempio n. 7
0
/*********************************************************************
 * Function:        void RebootTask(NET_CONFIG* pConfig)
 *
 * PreCondition:    Stack is initialized()
 *
 * Input:           pConfig   - interface 
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Checks for incomming traffic on port 69.  
 *					Resets the PIC if a 'R' is received.
 *
 * Note:            This module is primarily for use with the 
 *					Ethernet bootloader.  By resetting, the Ethernet 
 *					bootloader can take control for a second and let
 *					a firmware upgrade take place.
 ********************************************************************/
void RebootTask(NET_CONFIG* pConfig)
{
	struct
	{
		uint8_t vMACAddress[6];
		uint32_t dwIPAddress;
		uint16_t wChecksum;
	} BootloaderAddress;
    int netIx;

    netIx = _TCPIPStackNetIx(pConfig);

	
	if(MySocket[netIx] == INVALID_UDP_SOCKET)
    {
        MySocket[netIx] = UDPOpen(0,UDP_OPEN_SERVER,REBOOT_PORT,INVALID_UDP_PORT);

        if(MySocket[netIx] == INVALID_UDP_SOCKET)
        {
            return;
        }
        UDPSocketSetNet(MySocket[netIx], pConfig);
    }

	// Do nothing if no data is waiting
	if(!UDPIsGetReady(MySocket[netIx]))
		return;
    
	#if defined(REBOOT_SAME_SUBNET_ONLY)
		// Respond only to name requests sent to us from nodes on the same subnet
     	if((remoteNode.IPAddr.Val & pConfig->MyMask.Val) != (pConfig->MyIPAddr.Val & pConfig->MyMask.Val))
		{
			UDPDiscard(pConfig);
			return;
		}
	#endif

	// Get our MAC address, IP address, and compute a checksum of them 
	memcpy((void*)&BootloaderAddress.vMACAddress[0], (void*)&pConfig->MyMACAddr.v[0], sizeof(pConfig->MyMACAddr));
	BootloaderAddress.dwIPAddress = pConfig->MyIPAddr.Val;
	BootloaderAddress.wChecksum = CalcIPChecksum((uint8_t*)&BootloaderAddress, sizeof(BootloaderAddress) - sizeof(BootloaderAddress.wChecksum));
	
	// To enter the bootloader, we reset the system
	SYS_OUT_MESSAGE("Bootloader Reset");

	SYS_Reboot();
}
Esempio n. 8
0
/***	void UdpServer::close(void)
**
**	Synopsis:   
**      Stops Listening and closes all unaccepted sockets
**      and clears everything back to it's originally constructed state.
**      The datagram cache buffers remain in use as this is specified on the constuctor
**
**	Parameters:
**      None
**
**	Return Values:
**      None
**
**	Errors:
**      None
**
**  Notes:
**
**      Returns the UdpServer instance to 
**      a state just as if the instance had just been
**      constructed. It also, Close all connections
**      and releases all resources (sockets).
**
*/
void UdpServer::close(void)
{
    stopListening();

    for(int i = 0; i < _cMaxPendingAllowed; i++)
    {
        if(_rghUDP[i] < INVALID_UDP_SOCKET)
        {
            // clean out the buffer
            UDPIsGetReady(_rghUDP[i]);
            UDPDiscard();
            UDPClose(_rghUDP[i]);
            ExchangeCacheBuffer(_rghUDP[i], NULL, 0);
            _rghUDP[i] = INVALID_UDP_SOCKET;
        }
    }

    clear();
}
Esempio n. 9
0
/***	void UdpServer::stopListening(void)
**
**	Synopsis:   
**      This stops listening on the server port, but does not shutdown UdpServer
**
**	Parameters:
**     None
**
**	Return Values:
**      None
**
**	Errors:
**      None
**
**  Notes:
**      To resume listening, just call ResumeListening
**      This is a soft stop listening in that only the server stops listening on the port
**      however the instance is still valid and you can continue to accept pending client.
**      and you can resume the listening.
**
*/
void UdpServer::stopListening(void)
{
   // DO NOT blow away pending clients.
   // that will be done on a close()
   // update the pending count so we have them all.
    availableClients();

   // blow away any listening socket
   if(_cPending < _cPendingMax && _rghUDP[_cPending] < INVALID_UDP_SOCKET)
    {
        UDPIsGetReady(_rghUDP[_cPending]);
        UDPDiscard();
        UDPClose(_rghUDP[_cPending]);
        ExchangeCacheBuffer(_rghUDP[_cPending], NULL, 0);
        _rghUDP[_cPending] = INVALID_UDP_SOCKET;
    }

    // no longer listening
    _fListening = false;
}
Esempio n. 10
0
/****************************************************************************
  Function:
   void ChipKITUDPUpdateBufferCache(void)

  Description:
    This is called in PeriodicTasks to make sure that
    all UDP data is copied to the cache before the MAL 
    discards it on the next StackTasks

  Preconditions:

  Parameters:
    None

  Returns:
    None

  Remarks:
    By double buffering, we are able to save the UDP data before losing
    it on the next call to StackTasks
   
  ***************************************************************************/
static void ChipKITUDPUpdateBufferCache(void)
{
	UDP_SOCKET hUDP;
	WORD cbReady = 0;
	UDPSB * pUDPSB = NULL;
	UDP_SOCKET_INFO * pSocketInfo = NULL;

	for(hUDP = 0; hUDP < MAX_UDP_SOCKETS; hUDP++)
	{
		if((pUDPSB = rgUDPSocketBuffers[hUDP]) != NULL)
		{
			if((cbReady = UDPIsGetReady(hUDP)) > 0)
			{
				UDPSBWrite(pUDPSB, cbReady);
				pSocketInfo = PUDPSocketInfoFromUDPSocket(hUDP);
				pUDPSB->remoteNodeInfo = pSocketInfo->remoteNode;
				pUDPSB->remotePort = pSocketInfo->remotePort;;
			}
		}
	}
}
Esempio n. 11
0
/*****************************************************************************
  Function:
	int recvfrom(SOCKET s, char* buf, int len, int flags, struct sockaddr* from, int* fromlen)

  Summary:
	The recvfrom() function is used to receive incoming data that
    has been queued for a socket.

  Description:
	The recvfrom() function is used to receive incoming data that
    has been queued for a socket. This function can be used with
    both datagram and stream type sockets. If the available data
    is too large to fit in the supplied application buffer buf,
    excess bytes are discarded in case of SOCK_DGRAM type
    sockets. For SOCK_STREAM types, the data is buffered
    internally so the application can retreive all data by
    multiple calls of recvfrom.

  Precondition:
	socket function should be called.

  Parameters:
	s - Socket descriptor returned from a previous call to socket.
    buf - application data receive buffer.
    len - buffer length in bytes.
    flags - message flags. Currently this is not supported.
    from - pointer to the sockaddr structure that will be
    filled in with the destination address.
    fromlen - size of buffer pointed by from.

  Returns:
	If recvfrom is successful, the number of bytes copied to
    application buffer buf is returned. A value of zero indicates
    no data available. A return value of SOCKET_ERROR (-1)
    indicates an error condition.

  Remarks:
	None.
  ***************************************************************************/
int recvfrom( SOCKET s, char* buf, int len, int flags, struct sockaddr* from, int* fromlen )
{
    struct BSDSocket *socket;
    struct sockaddr_in *rem_addr;
    SOCKET_INFO *remoteSockInfo;
    
    socket = &BSDSocketArray[s];
    rem_addr = (struct sockaddr_in *)from;
    
    if(socket->SocketType == SOCK_DGRAM) //UDP
    {
        if(socket->bsdState != SKT_EST)
        {
            socket->SocketID = UDPOpen(socket->localPort, NULL, socket->localPort); //recieve on the same port.
            socket->bsdState = SKT_EST;
        }
        
        if(socket->bsdState == SKT_EST)
        {
            if(UDPIsGetReady(socket->SocketID) > 0)
            {
                return UDPGetArray((BYTE*)buf, len);
            }
        }
    }
    else  //TCP recieve from already connected socket.
    {
        if(from && fromlen && ((unsigned int)*fromlen >= sizeof(struct sockaddr_in)))
        {
            remoteSockInfo = TCPGetRemoteInfo(socket->SocketID);
            rem_addr->sin_addr.S_un.S_addr = remoteSockInfo->remote.IPAddr.Val;
            rem_addr->sin_port = remoteSockInfo->remotePort.Val;
            *fromlen = sizeof(struct sockaddr_in);
        }
        return recv(s, buf, len, 0);
    }
    return 0;
}
Esempio n. 12
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;
   }
}
Esempio n. 13
0
/*****************************************************************************
  Function:
	void DNSClientTask(void)

  Summary:
	DNS client state machine
	
  Description:
    Process the DNS client state machine
  
  Precondition:
	DNSClientInit has been called.

  Parameters:
    None
    
  Return Values:
    None

  ***************************************************************************/
void DNSClientTask(void)
{
	uint8_t 				i;
	TCPIP_UINT16_VAL			w;
	DNS_HEADER			DNSHeader;
	DNS_ANSWER_HEADER	DNSAnswerHeader;
    

    switch(smDNS)
	{
		case DNS_IDLE:
            break;  // nothing to do

		case DNS_START:
            smDNS = DNSRetry(DNS_START);
            stateStartTime = 0;  // flag the first Open try
			break;

		case DNS_OPEN_SOCKET:
            DNSSocket = UDPOpenClient(IP_ADDRESS_TYPE_IPV4, DNS_CLIENT_PORT, (IP_MULTI_ADDRESS*)(DNSServers + vDNSServerIx));
			if(DNSSocket == INVALID_UDP_SOCKET)
            {
                if(stateStartTime == 0)
                {
                    stateStartTime = SYS_TICK_Get();
                }
                else if(SYS_TICK_Get() - stateStartTime > (DNS_CLIENT_OPEN_TMO * SYS_TICK_TicksPerSecondGet()))
                {
					smDNS = DNS_FAIL_OPEN_TMO;
                }
                
                break;
            }
            
            // got a valid UDP socket
            UDPSocketSetNet(DNSSocket, pDNSNet);
            stateStartTime = SYS_TICK_Get();
            smDNS = DNS_QUERY;
            // no break, start sending the query;

		case DNS_QUERY:
            if(!UDPIsOpened(DNSSocket) || (UDPIsTxPutReady(DNSSocket, 18 + strlen (DNSHostName)) < (18 + strlen (DNSHostName))))
            {
                if(SYS_TICK_Get() - stateStartTime > (DNS_CLIENT_OPEN_TMO * SYS_TICK_TicksPerSecondGet()))
                {
					smDNS = DNS_FAIL_OPEN_TMO;
                }
                
				break;  // wait some more
            }
			
			// Put DNS query here
			SentTransactionID.Val = (uint16_t)rand();
			UDPPut(DNSSocket, SentTransactionID.v[1]);// User chosen transaction ID
			UDPPut(DNSSocket, SentTransactionID.v[0]);
			UDPPut(DNSSocket, 0x01);		// Standard query with recursion
			UDPPut(DNSSocket, 0x00);	
			UDPPut(DNSSocket, 0x00);		// 0x0001 questions
			UDPPut(DNSSocket, 0x01);
			UDPPut(DNSSocket, 0x00);		// 0x0000 answers
			UDPPut(DNSSocket, 0x00);
			UDPPut(DNSSocket, 0x00);		// 0x0000 name server resource records
			UDPPut(DNSSocket, 0x00);
			UDPPut(DNSSocket, 0x00);		// 0x0000 additional records
			UDPPut(DNSSocket, 0x00);

			// Put hostname string to resolve
            DNSPutString(DNSSocket, DNSHostName);

			UDPPut(DNSSocket, 0x00);		// Type: DNS_TYPE_A A (host address) or DNS_TYPE_MX for mail exchange
			UDPPut(DNSSocket, RecordType);
			UDPPut(DNSSocket, 0x00);		// Class: IN (Internet)
			UDPPut(DNSSocket, 0x01);

			UDPFlush(DNSSocket);
			stateStartTime = SYS_TICK_Get();
			smDNS = DNS_GET_RESULT;
			break;

		case DNS_GET_RESULT:
			if(!UDPIsGetReady(DNSSocket))
			{
				if(SYS_TICK_Get() - stateStartTime > (DNS_CLIENT_SERVER_TMO * SYS_TICK_TicksPerSecondGet()))
                {
					smDNS = DNS_FAIL_SERVER;
                }
				break;
			}


			// Retrieve the DNS header and de-big-endian it
			UDPGet(DNSSocket, &DNSHeader.TransactionID.v[1]);
			UDPGet(DNSSocket, &DNSHeader.TransactionID.v[0]);

			// Throw this packet away if it isn't in response to our last query
			if(DNSHeader.TransactionID.Val != SentTransactionID.Val)
			{
				UDPDiscard(DNSSocket);
				break;
			}

			UDPGet(DNSSocket, &DNSHeader.Flags.v[1]);
			UDPGet(DNSSocket, &DNSHeader.Flags.v[0]);
			UDPGet(DNSSocket, &DNSHeader.Questions.v[1]);
			UDPGet(DNSSocket, &DNSHeader.Questions.v[0]);
			UDPGet(DNSSocket, &DNSHeader.Answers.v[1]);
			UDPGet(DNSSocket, &DNSHeader.Answers.v[0]);
			UDPGet(DNSSocket, &DNSHeader.AuthoritativeRecords.v[1]);
			UDPGet(DNSSocket, &DNSHeader.AuthoritativeRecords.v[0]);
			UDPGet(DNSSocket, &DNSHeader.AdditionalRecords.v[1]);
			UDPGet(DNSSocket, &DNSHeader.AdditionalRecords.v[0]);

			// Remove all questions (queries)
			while(DNSHeader.Questions.Val--)
			{
				DNSDiscardName(DNSSocket);
				UDPGet(DNSSocket, &w.v[1]);		// Question type
				UDPGet(DNSSocket, &w.v[0]);
				UDPGet(DNSSocket, &w.v[1]);		// Question class
				UDPGet(DNSSocket, &w.v[0]);
			}
			
			// Scan through answers
			while(DNSHeader.Answers.Val--)
			{				
				DNSDiscardName(DNSSocket);					// Throw away response name
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseType.v[1]);		// Response type
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseType.v[0]);
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseClass.v[1]);	// Response class
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseClass.v[0]);
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[3]);		// Time to live
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[2]);
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[1]);
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[0]);
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseLen.v[1]);		// Response length
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseLen.v[0]);

				// Make sure that this is a 4 byte IP address, response type A or MX, class 1
				// Check if this is Type A, MX, or AAAA
				if( DNSAnswerHeader.ResponseClass.Val	== 0x0001u) // Internet class
				{
                    if (DNSAnswerHeader.ResponseType.Val	== 0x0001u &&
    					DNSAnswerHeader.ResponseLen.Val		== 0x0004u)
                    {
    					Flags.bits.AddressValid = true;
                        Flags.bits.AddressType = IP_ADDRESS_TYPE_IPV4;
    					UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[0]);
    					UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[1]);
    					UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[2]);
    					UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[3]);
    					goto DoneSearchingRecords;
                    }
                    else if (DNSAnswerHeader.ResponseType.Val == 0x001Cu &&
    					        DNSAnswerHeader.ResponseLen.Val	== 0x0010u)
                    {
                        if (RecordType != DNS_TYPE_AAAA)
                        {
        					while(DNSAnswerHeader.ResponseLen.Val--)
        					{
        						UDPGet(DNSSocket, &i);
        					}
                            break;
                        }
    					Flags.bits.AddressValid = true;
                        Flags.bits.AddressType = IP_ADDRESS_TYPE_IPV6;
                        UDPGetArray (DNSSocket, (void *)&ResolvedAddress.ipv6Address, sizeof (IPV6_ADDR));
    					goto DoneSearchingRecords;                        
                    }
                    else
                    {
    					while(DNSAnswerHeader.ResponseLen.Val--)
    					{
    						UDPGet(DNSSocket, &i);
    					}
                    }
				}
				else
				{
					while(DNSAnswerHeader.ResponseLen.Val--)
					{
						UDPGet(DNSSocket, &i);
					}
				}
			}

			// Remove all Authoritative Records
			while(DNSHeader.AuthoritativeRecords.Val--)
			{
				DNSDiscardName(DNSSocket);					// Throw away response name
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseType.v[1]);		// Response type
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseType.v[0]);
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseClass.v[1]);	// Response class
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseClass.v[0]);
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[3]);		// Time to live
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[2]);
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[1]);
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[0]);
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseLen.v[1]);		// Response length
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseLen.v[0]);

				// Make sure that this is a 4 byte IP address, response type A or MX, class 1
				// Check if this is Type A
				if( DNSAnswerHeader.ResponseClass.Val	== 0x0001u) // Internet class
				{
                    if (DNSAnswerHeader.ResponseType.Val	== 0x0001u &&
    					DNSAnswerHeader.ResponseLen.Val		== 0x0004u)
                    {
    					Flags.bits.AddressValid = true;
                        Flags.bits.AddressType = IP_ADDRESS_TYPE_IPV4;
    					UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[0]);
    					UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[1]);
    					UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[2]);
    					UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[3]);
    					goto DoneSearchingRecords;
                    }
                    else if (DNSAnswerHeader.ResponseType.Val == 0x001Cu &&
    					        DNSAnswerHeader.ResponseLen.Val	== 0x0010u)
                    {
                        if (RecordType != DNS_TYPE_AAAA)
                        {
        					while(DNSAnswerHeader.ResponseLen.Val--)
        					{
        						UDPGet(DNSSocket, &i);
        					}
                            break;
                        }
    					Flags.bits.AddressValid = true;
                        Flags.bits.AddressType = IP_ADDRESS_TYPE_IPV6;
                        UDPGetArray (DNSSocket, (void *)&ResolvedAddress.ipv6Address, sizeof (IPV6_ADDR));
    					goto DoneSearchingRecords;                        
                    }
                    else
                    {
    					while(DNSAnswerHeader.ResponseLen.Val--)
    					{
    						UDPGet(DNSSocket, &i);
    					}
                    }
				}
				else
				{
					while(DNSAnswerHeader.ResponseLen.Val--)
					{
						UDPGet(DNSSocket, &i);
					}
				}
			}

			// Remove all Additional Records
			while(DNSHeader.AdditionalRecords.Val--)
			{
				DNSDiscardName(DNSSocket);					// Throw away response name
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseType.v[1]);		// Response type
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseType.v[0]);
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseClass.v[1]);	// Response class
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseClass.v[0]);
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[3]);		// Time to live
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[2]);
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[1]);
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[0]);
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseLen.v[1]);		// Response length
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseLen.v[0]);

				// Make sure that this is a 4 byte IP address, response type A or MX, class 1
				// Check if this is Type A
				if( DNSAnswerHeader.ResponseClass.Val	== 0x0001u) // Internet class
				{
                    if (DNSAnswerHeader.ResponseType.Val	== 0x0001u &&
    					DNSAnswerHeader.ResponseLen.Val		== 0x0004u)
                    {
    					Flags.bits.AddressValid = true;
                        Flags.bits.AddressType = IP_ADDRESS_TYPE_IPV4;
    					UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[0]);
    					UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[1]);
    					UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[2]);
    					UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[3]);
    					goto DoneSearchingRecords;
                    }
                    else if (DNSAnswerHeader.ResponseType.Val == 0x001Cu &&
    					        DNSAnswerHeader.ResponseLen.Val	== 0x0010u)
                    {
                        if (RecordType != DNS_TYPE_AAAA)
                        {
        					while(DNSAnswerHeader.ResponseLen.Val--)
        					{
        						UDPGet(DNSSocket, &i);
        					}
                            break;
                        }
    					Flags.bits.AddressValid = true;
                        Flags.bits.AddressType = IP_ADDRESS_TYPE_IPV6;
                        UDPGetArray (DNSSocket, (void *)&ResolvedAddress.ipv6Address, sizeof (IPV6_ADDR));
    					goto DoneSearchingRecords;                        
                    }
                    else
                    {
    					while(DNSAnswerHeader.ResponseLen.Val--)
    					{
    						UDPGet(DNSSocket, &i);
    					}
                    }
				}
				else
				{
					while(DNSAnswerHeader.ResponseLen.Val--)
					{
						UDPGet(DNSSocket, &i);
					}
				}
			}

DoneSearchingRecords:

			UDPDiscard(DNSSocket);
            _DNSReleaseSocket();
			if(Flags.bits.AddressValid)
            {
                smDNS = DNS_DONE;
            }
            else
            {
                smDNS = DNSRetry(DNS_FAIL_SERVER);
            }
            break;  // done
            
		case DNS_FAIL_ARP:
            // see if there is other server we may try
            smDNS = DNSRetry(DNS_FAIL_ARP);
            break;

		case DNS_FAIL_SERVER:
            smDNS = DNSRetry(DNS_FAIL_SERVER);
			break;

        default:    // DNS_DONE, DNS_FAIL_ARP_TMO, DNS_FAIL_OPEN_TMO, DNS_FAIL_SERVER_TMO  
            // either done or some error state
            break;
	}
    
#if DNS_CLIENT_VERSION_NO >= 2
    dnsTickPending = 0;
#endif  // DNS_CLIENT_VERSION_NO >= 2
}
Esempio n. 14
0
void CmdCheck()
{
	#if MAX_UDP_SOCKETS_FREERTOS>0 //UDP Stack
	activeUdpSocket=0;
	while (activeUdpSocket < MAX_UDP_SOCKETS_FREERTOS) 
	{
		//Ring Buffer
		if(udpSocket[activeUdpSocket] != INVALID_UDP_SOCKET)
		{
			//reads udp data and adds in ring buffer
			udpRxLen[activeUdpSocket] = UDPIsGetReady(udpSocket[activeUdpSocket]);

			if (udpRxLen[activeUdpSocket] > BUFFER_UDP_LEN[activeUdpSocket])  //overflow
			{
				datadiscard = udpRxLen[activeUdpSocket];
			// Old debug string UARTWrite(1,"Overflow: ");
				while (datadiscard > BUFFER_UDP_LEN[activeUdpSocket])
				{
					datadiscard  -= BUFFER_UDP_LEN[activeUdpSocket];
					if ( datadiscard > BUFFER_UDP_LEN[activeUdpSocket])
						UDPGetArray(udpBuffer[activeUdpSocket], BUFFER_UDP_LEN[activeUdpSocket]);
					else
						UDPGetArray(udpBuffer[activeUdpSocket], datadiscard);

			// Old debug string UARTWrite(1,"Overflow While: ");
				}
				UDPoverflow = 1;
				UDPoverflowFlag[activeUdpSocket] = 1;
				udpRxLen[activeUdpSocket] = BUFFER_UDP_LEN[activeUdpSocket];
			}
			else
				UDPoverflow = 0;
				
			if (udpRxLen[activeUdpSocket] > 0)
			{
				if( (p_udp_wifiram[activeUdpSocket]+udpRxLen[activeUdpSocket]) <= (udpBuffer[activeUdpSocket]+BUFFER_UDP_LEN[activeUdpSocket]) ) //append to buffer
				{
					UDPGetArray(p_udp_wifiram[activeUdpSocket], udpRxLen[activeUdpSocket]); //data
					p_udp_wifiram[activeUdpSocket] += udpRxLen[activeUdpSocket];
				}
				else //append to buffer near end, or add to buffer from start
				{
					tmp_len[activeUdpSocket] = ((udpBuffer[activeUdpSocket]+BUFFER_UDP_LEN[activeUdpSocket]) - p_udp_wifiram[activeUdpSocket]);  //free space on ring buffer
					if(tmp_len[activeUdpSocket] > 0) //fill buffer and add data from start
					{
						UDPGetArray(p_udp_wifiram[activeUdpSocket], tmp_len[activeUdpSocket]);
						p_udp_wifiram[activeUdpSocket] = udpBuffer[activeUdpSocket];
						UDPGetArray(p_udp_wifiram[activeUdpSocket], udpRxLen[activeUdpSocket] - tmp_len[activeUdpSocket] );
						p_udp_wifiram[activeUdpSocket] += (udpRxLen[activeUdpSocket] - tmp_len[activeUdpSocket]);
					}
					else //add data to buffer from start
					{ 
						p_udp_wifiram[activeUdpSocket] = udpBuffer[activeUdpSocket];
						UDPGetArray(p_udp_wifiram[activeUdpSocket], udpRxLen[activeUdpSocket]);
						p_udp_wifiram[activeUdpSocket] += udpRxLen[activeUdpSocket];
					}
				}
				udpRxLenGlobal[activeUdpSocket] += udpRxLen[activeUdpSocket];	

/*
	udpBuffer1[50] = '\0';
	UARTWrite(1, udpBuffer1);
*/				
			} //end ring buffer
		}
		activeUdpSocket++;
	}
	#endif //UDP STACK

	if (Cmd != 0)
	{
		int fresult = 0;
		while (xSemaphoreTake(xSemFrontEnd,0) != pdTRUE);
		if (xFrontEndStat == 1)
		{
			fresult = FP[Cmd]();
			xFrontEndStat = xFrontEndStatRet;
			xSemaphoreGive(xSemFrontEnd);
			Cmd = 0;
			taskYIELD();
		}
	}
}
Esempio n. 15
0
File: DNS.c Progetto: CEIT-UQ/RGB
/*****************************************************************************
  Function:
	BOOL DNSIsResolved(IP_ADDR* HostIP)

  Summary:
	Determines if the DNS resolution is complete and provides the IP.
	
  Description:
	Call this function to determine if the DNS resolution of an address has
	been completed.  If so, the resolved address will be provided in HostIP.

  Precondition:
	DNSResolve or DNSResolveROM has been called.

  Parameters:
	HostIP - A pointer to an IP_ADDR structure in which to store the 
		resolved IP address once resolution is complete.

  Return Values:
  	TRUE - The DNS client has obtained an IP, or the DNS process
  		has encountered an error.  HostIP will be 0.0.0.0 on error.  Possible 
  		errors include server timeout (i.e. DNS server not available), hostname 
  		not in the DNS, or DNS server errors.
  	FALSE - The resolution process is still in progress.
  ***************************************************************************/
BOOL DNSIsResolved(IP_ADDR* HostIP)
{
	static DWORD		StartTime;
	static WORD_VAL		SentTransactionID __attribute__((persistent));
	static BYTE			vARPAttemptCount;
	static BYTE			vDNSAttemptCount;
	BYTE 				i;
	WORD_VAL			w;
	DNS_HEADER			DNSHeader;
	DNS_ANSWER_HEADER	DNSAnswerHeader;

	switch(smDNS)
	{
		case DNS_START:
			vARPAttemptCount = 0;
			vDNSAttemptCount = 0;
			// No break;

		case DNS_ARP_START_RESOLVE:
			ARPResolve(&AppConfig.PrimaryDNSServer);
			vARPAttemptCount++;
			StartTime = TickGet();
			smDNS = DNS_ARP_RESOLVE;
			break;

		case DNS_ARP_RESOLVE:
			if(!ARPIsResolved(&AppConfig.PrimaryDNSServer, &ResolvedInfo.MACAddr))
			{
				if(TickGet() - StartTime > DNS_TIMEOUT)
					smDNS = (vARPAttemptCount >= 3u) ? DNS_FAIL : DNS_ARP_START_RESOLVE;
				break;
			}
			ResolvedInfo.IPAddr.Val = AppConfig.PrimaryDNSServer.Val;
			smDNS = DNS_OPEN_SOCKET;
			// No break: DNS_OPEN_SOCKET is the correct next state
		
		case DNS_OPEN_SOCKET:
			MySocket = UDPOpen(0, &ResolvedInfo, DNS_PORT);
			if(MySocket == INVALID_UDP_SOCKET)
				break;

			smDNS = DNS_QUERY;
			// No need to break, we can immediately start resolution
			
		case DNS_QUERY:
			if(!UDPIsPutReady(MySocket))
				break;
			
			// Put DNS query here
			SentTransactionID.Val++;
			UDPPut(SentTransactionID.v[1]);// User chosen transaction ID
			UDPPut(SentTransactionID.v[0]);
			UDPPut(0x01);		// Standard query with recursion
			UDPPut(0x00);	
			UDPPut(0x00);		// 0x0001 questions
			UDPPut(0x01);
			UDPPut(0x00);		// 0x0000 answers
			UDPPut(0x00);
			UDPPut(0x00);		// 0x0000 name server resource records
			UDPPut(0x00);
			UDPPut(0x00);		// 0x0000 additional records
			UDPPut(0x00);

			// Put hostname string to resolve
			if(DNSHostName)
				DNSPutString(DNSHostName);
			else
				DNSPutROMString(DNSHostNameROM);

			UDPPut(0x00);		// Type: DNS_TYPE_A A (host address) or DNS_TYPE_MX for mail exchange
			UDPPut(RecordType);
			UDPPut(0x00);		// Class: IN (Internet)
			UDPPut(0x01);

			UDPFlush();
			StartTime = TickGet();
			smDNS = DNS_GET_RESULT;
			break;

		case DNS_GET_RESULT:
			if(!UDPIsGetReady(MySocket))
			{
				if(TickGet() - StartTime > DNS_TIMEOUT)
					smDNS = DNS_FAIL;
				break;
			}

			// Retrieve the DNS header and de-big-endian it
			UDPGet(&DNSHeader.TransactionID.v[1]);
			UDPGet(&DNSHeader.TransactionID.v[0]);

			// Throw this packet away if it isn't in response to our last query
			if(DNSHeader.TransactionID.Val != SentTransactionID.Val)
			{
				UDPDiscard();
				break;
			}

			UDPGet(&DNSHeader.Flags.v[1]);
			UDPGet(&DNSHeader.Flags.v[0]);
			UDPGet(&DNSHeader.Questions.v[1]);
			UDPGet(&DNSHeader.Questions.v[0]);
			UDPGet(&DNSHeader.Answers.v[1]);
			UDPGet(&DNSHeader.Answers.v[0]);
			UDPGet(&DNSHeader.AuthoritativeRecords.v[1]);
			UDPGet(&DNSHeader.AuthoritativeRecords.v[0]);
			UDPGet(&DNSHeader.AdditionalRecords.v[1]);
			UDPGet(&DNSHeader.AdditionalRecords.v[0]);

			// Remove all questions (queries)
			while(DNSHeader.Questions.Val--)
			{
				DNSDiscardName();
				UDPGet(&w.v[1]);		// Question type
				UDPGet(&w.v[0]);
				UDPGet(&w.v[1]);		// Question class
				UDPGet(&w.v[0]);
			}
			
			// Scan through answers
			while(DNSHeader.Answers.Val--)
			{				
				DNSDiscardName();					// Throw away response name
				UDPGet(&DNSAnswerHeader.ResponseType.v[1]);		// Response type
				UDPGet(&DNSAnswerHeader.ResponseType.v[0]);
				UDPGet(&DNSAnswerHeader.ResponseClass.v[1]);	// Response class
				UDPGet(&DNSAnswerHeader.ResponseClass.v[0]);
				UDPGet(&DNSAnswerHeader.ResponseTTL.v[3]);		// Time to live
				UDPGet(&DNSAnswerHeader.ResponseTTL.v[2]);
				UDPGet(&DNSAnswerHeader.ResponseTTL.v[1]);
				UDPGet(&DNSAnswerHeader.ResponseTTL.v[0]);
				UDPGet(&DNSAnswerHeader.ResponseLen.v[1]);		// Response length
				UDPGet(&DNSAnswerHeader.ResponseLen.v[0]);

				// Make sure that this is a 4 byte IP address, response type A or MX, class 1
				// Check if this is Type A or MX
				if( DNSAnswerHeader.ResponseType.Val	== 0x0001u &&
					DNSAnswerHeader.ResponseClass.Val	== 0x0001u && // Internet class
					DNSAnswerHeader.ResponseLen.Val		== 0x0004u)
				{
					Flags.bits.AddressValid = TRUE;
					UDPGet(&ResolvedInfo.IPAddr.v[0]);
					UDPGet(&ResolvedInfo.IPAddr.v[1]);
					UDPGet(&ResolvedInfo.IPAddr.v[2]);
					UDPGet(&ResolvedInfo.IPAddr.v[3]);
					goto DoneSearchingRecords;
				}
				else
				{
					while(DNSAnswerHeader.ResponseLen.Val--)
					{
						UDPGet(&i);
					}
				}
			}

			// Remove all Authoritative Records
			while(DNSHeader.AuthoritativeRecords.Val--)
			{
				DNSDiscardName();					// Throw away response name
				UDPGet(&DNSAnswerHeader.ResponseType.v[1]);		// Response type
				UDPGet(&DNSAnswerHeader.ResponseType.v[0]);
				UDPGet(&DNSAnswerHeader.ResponseClass.v[1]);	// Response class
				UDPGet(&DNSAnswerHeader.ResponseClass.v[0]);
				UDPGet(&DNSAnswerHeader.ResponseTTL.v[3]);		// Time to live
				UDPGet(&DNSAnswerHeader.ResponseTTL.v[2]);
				UDPGet(&DNSAnswerHeader.ResponseTTL.v[1]);
				UDPGet(&DNSAnswerHeader.ResponseTTL.v[0]);
				UDPGet(&DNSAnswerHeader.ResponseLen.v[1]);		// Response length
				UDPGet(&DNSAnswerHeader.ResponseLen.v[0]);

				// Make sure that this is a 4 byte IP address, response type A or MX, class 1
				// Check if this is Type A
				if( DNSAnswerHeader.ResponseType.Val	== 0x0001u &&
					DNSAnswerHeader.ResponseClass.Val	== 0x0001u && // Internet class
					DNSAnswerHeader.ResponseLen.Val		== 0x0004u)
				{
					Flags.bits.AddressValid = TRUE;
					UDPGet(&ResolvedInfo.IPAddr.v[0]);
					UDPGet(&ResolvedInfo.IPAddr.v[1]);
					UDPGet(&ResolvedInfo.IPAddr.v[2]);
					UDPGet(&ResolvedInfo.IPAddr.v[3]);
					goto DoneSearchingRecords;
				}
				else
				{
					while(DNSAnswerHeader.ResponseLen.Val--)
					{
						UDPGet(&i);
					}
				}
			}

			// Remove all Additional Records
			while(DNSHeader.AdditionalRecords.Val--)
			{
				DNSDiscardName();					// Throw away response name
				UDPGet(&DNSAnswerHeader.ResponseType.v[1]);		// Response type
				UDPGet(&DNSAnswerHeader.ResponseType.v[0]);
				UDPGet(&DNSAnswerHeader.ResponseClass.v[1]);	// Response class
				UDPGet(&DNSAnswerHeader.ResponseClass.v[0]);
				UDPGet(&DNSAnswerHeader.ResponseTTL.v[3]);		// Time to live
				UDPGet(&DNSAnswerHeader.ResponseTTL.v[2]);
				UDPGet(&DNSAnswerHeader.ResponseTTL.v[1]);
				UDPGet(&DNSAnswerHeader.ResponseTTL.v[0]);
				UDPGet(&DNSAnswerHeader.ResponseLen.v[1]);		// Response length
				UDPGet(&DNSAnswerHeader.ResponseLen.v[0]);

				// Make sure that this is a 4 byte IP address, response type A or MX, class 1
				// Check if this is Type A
				if( DNSAnswerHeader.ResponseType.Val	== 0x0001u &&
					DNSAnswerHeader.ResponseClass.Val	== 0x0001u && // Internet class
					DNSAnswerHeader.ResponseLen.Val		== 0x0004u)
				{
					Flags.bits.AddressValid = TRUE;
					UDPGet(&ResolvedInfo.IPAddr.v[0]);
					UDPGet(&ResolvedInfo.IPAddr.v[1]);
					UDPGet(&ResolvedInfo.IPAddr.v[2]);
					UDPGet(&ResolvedInfo.IPAddr.v[3]);
					goto DoneSearchingRecords;
				}
				else
				{
					while(DNSAnswerHeader.ResponseLen.Val--)
					{
						UDPGet(&i);
					}
				}
			}

DoneSearchingRecords:

			UDPDiscard();
			UDPClose(MySocket);
			MySocket = INVALID_UDP_SOCKET;
			smDNS = DNS_DONE;
			// No break, DNS_DONE is the correct step

		case DNS_DONE:
			// Return 0.0.0.0 if DNS resolution failed, otherwise return the 
			// resolved IP address
			if(!Flags.bits.AddressValid)
				ResolvedInfo.IPAddr.Val = 0;
			HostIP->Val = ResolvedInfo.IPAddr.Val;
			return TRUE;

		case DNS_FAIL:
			// If 3 attempts or more, quit
			if(vDNSAttemptCount >= 2u)
			{
				// Return an invalid IP address 0.0.0.0 if we can't finish ARP or DNS query step
				HostIP->Val = 0x00000000;
				return TRUE;
			}
			vDNSAttemptCount++;

			// Swap primary and secondary DNS servers if there is a secondary DNS server programmed
			if(AppConfig.SecondaryDNSServer.Val)
			{
				AppConfig.PrimaryDNSServer.Val ^= AppConfig.SecondaryDNSServer.Val;
				AppConfig.SecondaryDNSServer.Val ^= AppConfig.PrimaryDNSServer.Val;
				AppConfig.PrimaryDNSServer.Val ^= AppConfig.SecondaryDNSServer.Val;

				// Start another ARP resolution for the secondary server (now primary)
				vARPAttemptCount = 0;
				if(MySocket != INVALID_UDP_SOCKET)
				{
					UDPClose(MySocket);
					MySocket = INVALID_UDP_SOCKET;
				}
				smDNS = DNS_ARP_START_RESOLVE;
			}

			break;

	}
	
	return FALSE;
}
Esempio n. 16
0
/*****************************************************************************
  Function:
	void DHCPTask(void)

  Summary:
	Performs periodic DHCP tasks.

  Description:
	This function performs any periodic tasks requied by the DHCP module, 
	such as sending and receiving messages involved with obtaining and
	maintaining a lease.

  Precondition:
	None

  Parameters:
	None

  Returns:
  	None
  ***************************************************************************/
void DHCPTask(void)
{
    static TICK eventTime;

    switch(smDHCPState)
    {
		case SM_DHCP_GET_SOCKET:
			// Open a socket to send and receive broadcast messages on
	        DHCPSocket = UDPOpen(DHCP_CLIENT_PORT, NULL, DHCP_SERVER_PORT);
			if(DHCPSocket == INVALID_UDP_SOCKET)
				break;

			smDHCPState = SM_DHCP_SEND_DISCOVERY;
			// No break

		case SM_DHCP_SEND_DISCOVERY:
			if(UDPIsPutReady(DHCPSocket) < 300u)
				break;

			// Ensure that we transmit to the broadcast IP and MAC addresses
			// The UDP Socket remembers who it was last talking to
			memset((void*)&UDPSocketInfo[DHCPSocket].remoteNode, 0xFF, sizeof(UDPSocketInfo[DHCPSocket].remoteNode));

		    // Assume default IP Lease time of 60 seconds.
		    // This should be minimum possible to make sure that if
		    // server did not specify lease time, we try again after this minimum time.
		    DHCPLeaseTime.Val = 60;
			ValidValues.Val = 0x00;
			DHCPBindCount = 0;
			DHCPFlags.bits.bIsBound = FALSE;	
			DHCPFlags.bits.bOfferReceived = FALSE;
			
			// Send the DHCP Discover broadcast
			_DHCPSend(DHCP_DISCOVER_MESSAGE, FALSE);
			
			// Start a timer and begin looking for a response
			eventTime = TickGet();
			smDHCPState = SM_DHCP_GET_OFFER;
	        break;

		case SM_DHCP_GET_OFFER:
			// Check to see if a packet has arrived
			if(UDPIsGetReady(DHCPSocket) < 250u)
			{
				// Go back and transmit a new discovery if we didn't get an offer after 2 seconds
				if(TickGet() - eventTime >= DHCP_TIMEOUT)
					smDHCPState = SM_DHCP_SEND_DISCOVERY;
				break;
			}

			// Let the DHCP server module know that there is a DHCP server 
			// on this network
			DHCPFlags.bits.bDHCPServerDetected = TRUE;

			// Check to see if we received an offer
			if(_DHCPReceive() != DHCP_OFFER_MESSAGE)
				break;

			smDHCPState = SM_DHCP_SEND_REQUEST;
			// No break

		case SM_DHCP_SEND_REQUEST:
			if(UDPIsPutReady(DHCPSocket) < 258u)
				break;

			// Send the DHCP request message
			_DHCPSend(DHCP_REQUEST_MESSAGE, FALSE);
			
			// Start a timer and begin looking for a response
			eventTime = TickGet();
			smDHCPState = SM_DHCP_GET_REQUEST_ACK;
	        break;

		case SM_DHCP_GET_REQUEST_ACK:
			// Check to see if a packet has arrived
			if(UDPIsGetReady(DHCPSocket) < 250u)
			{
				// Go back and transmit a new discovery if we didn't get an ACK after 2 seconds
				if(TickGet() - eventTime >= DHCP_TIMEOUT)
					smDHCPState = SM_DHCP_SEND_DISCOVERY;
				break;
			}

			// Check to see if we received an offer
			switch(_DHCPReceive())
			{
				case DHCP_ACK_MESSAGE:
					UDPClose(DHCPSocket);
					DHCPSocket = INVALID_UDP_SOCKET;
					eventTime = TickGet();
					smDHCPState = SM_DHCP_BOUND;

	                DHCPFlags.bits.bIsBound = TRUE;	
	                DHCPBindCount++;
					if(ValidValues.bits.IPAddress)
		                AppConfig.MyIPAddr = tempIPAddress;
					if(ValidValues.bits.Mask)
						AppConfig.MyMask = tempMask;
					if(ValidValues.bits.Gateway)
						AppConfig.MyGateway = tempGateway;
					#if defined(STACK_USE_DNS)
						if(ValidValues.bits.DNS)
							AppConfig.PrimaryDNSServer = tempDNS;
						AppConfig.SecondaryDNSServer.Val = ValidValues.bits.DNS2 ? tempDNS2.Val : 0x00000000ul;
					#endif
//					if(ValidValues.bits.HostName)
//						memcpy(AppConfig.NetBIOSName, (void*)tempHostName, sizeof(AppConfig.NetBIOSName));

					break;

				case DHCP_NAK_MESSAGE:
					smDHCPState = SM_DHCP_SEND_DISCOVERY;
					break;
			}
			break;

		case SM_DHCP_BOUND:
	        if(TickGet() - eventTime < TICK_SECOND)
				break;

			// Check to see if our lease is still valid, if so, decrement lease 
			// time
			if(DHCPLeaseTime.Val >= 2ul)
			{
				eventTime += TICK_SECOND;
				DHCPLeaseTime.Val--;
				break;
			}
			
			// Open a socket to send and receive DHCP messages on
	        DHCPSocket = UDPOpen(DHCP_CLIENT_PORT, NULL, DHCP_SERVER_PORT);
			if(DHCPSocket == INVALID_UDP_SOCKET)
				break;
			
			smDHCPState = SM_DHCP_SEND_RENEW;
			// No break

		case SM_DHCP_SEND_RENEW:
		case SM_DHCP_SEND_RENEW2:
		case SM_DHCP_SEND_RENEW3:
			if(UDPIsPutReady(DHCPSocket) < 258u)
				break;

			// Send the DHCP request message
			_DHCPSend(DHCP_REQUEST_MESSAGE, TRUE);
			DHCPFlags.bits.bOfferReceived = FALSE;
			
			// Start a timer and begin looking for a response
			eventTime = TickGet();
			smDHCPState++;
			break;

		case SM_DHCP_GET_RENEW_ACK:
		case SM_DHCP_GET_RENEW_ACK2:
		case SM_DHCP_GET_RENEW_ACK3:
			// Check to see if a packet has arrived
			if(UDPIsGetReady(DHCPSocket) < 250u)
			{
				// Go back and transmit a new discovery if we didn't get an ACK after 2 seconds
				if(TickGet() - eventTime >=  DHCP_TIMEOUT)
				{
					if(++smDHCPState > SM_DHCP_GET_RENEW_ACK3)
						smDHCPState = SM_DHCP_SEND_DISCOVERY;
				}
				break;
			}

			// Check to see if we received an offer
			switch(_DHCPReceive())
			{
				case DHCP_ACK_MESSAGE:
					UDPClose(DHCPSocket);
					DHCPSocket = INVALID_UDP_SOCKET;
					eventTime = TickGet();
					DHCPBindCount++;
					smDHCPState = SM_DHCP_BOUND;
					break;

				case DHCP_NAK_MESSAGE:
					smDHCPState = SM_DHCP_SEND_DISCOVERY;
					break;
			}
			break;

		// Handle SM_DHCP_DISABLED state by doing nothing.  Default case needed 
		// to supress compiler diagnostic.
		default:	
			break;
	}
}
Esempio n. 17
0
//
// Main application entry point.
//
int main(void)
{

#if defined(HOST_CM_TEST)
    DWORD t1 = 0;
    char st[80];
    BOOL host_scan = FALSE;
    UINT16 scan_count = 0;
#endif

    static IPV4_ADDR dwLastIP[sizeof (TCPIP_HOSTS_CONFIGURATION) / sizeof (*TCPIP_HOSTS_CONFIGURATION)];
    int i, nNets;

#if defined(SYS_USERIO_ENABLE)    
    static SYS_TICK startTick = 0;
    int32_t LEDstate=SYS_USERIO_LED_DEASSERTED;
#endif  // defined(SYS_USERIO_ENABLE)

    TCPIP_NET_HANDLE netH;
    const char  *netName=0;
    const char  *netBiosName;

#if defined (TCPIP_STACK_USE_ZEROCONF_MDNS_SD)
    char mDNSServiceName[] = "MyWebServiceNameX ";     // base name of the service Must not exceed 16 bytes long
                                                       // the last digit will be incremented by interface
#endif  // defined (TCPIP_STACK_USE_ZEROCONF_MDNS_SD)

    // perform system initialization
    if(!SYS_Initialize())
    {
        return 0;
    }


    SYS_CONSOLE_MESSAGE("\r\n\n\n ---  TCPIP Demo Starts!  --- \r\n");
    SYS_OUT_MESSAGE("TCPIPStack " TCPIP_STACK_VERSION "  ""                ");

    // Initialize the TCPIP stack
    if (!TCPIP_STACK_Init(TCPIP_HOSTS_CONFIGURATION, sizeof (TCPIP_HOSTS_CONFIGURATION) / sizeof (*TCPIP_HOSTS_CONFIGURATION),
            TCPIP_STACK_MODULE_CONFIG_TBL, sizeof (TCPIP_STACK_MODULE_CONFIG_TBL) / sizeof (*TCPIP_STACK_MODULE_CONFIG_TBL)))
    {
        return 0;
    }

    // Display the names associated with each interface
    // Perform mDNS registration if mDNS is enabled
    nNets = TCPIP_STACK_NetworksNo();
    for(i = 0; i < nNets; i++)
    {
        netH = TCPIP_STACK_IxToNet(i);
        netName = TCPIP_STACK_NetName(netH);
        netBiosName = TCPIP_STACK_NetBIOSName(netH);

#if defined(TCPIP_STACK_USE_NBNS)
        SYS_CONSOLE_PRINT("    Interface %s on host %s - NBNS enabled\r\n", netName, netBiosName);
#else
        SYS_CONSOLE_PRINT("    Interface %s on host %s - NBNS disabled\r\n", netName, netBiosName);
#endif  // defined(TCPIP_STACK_USE_NBNS)

#if defined (TCPIP_STACK_USE_ZEROCONF_MDNS_SD)
        mDNSServiceName[sizeof(mDNSServiceName) - 2] = '1' + i;
        mDNSServiceRegister( netH
            , mDNSServiceName                   // name of the service
            ,"_http._tcp.local"                 // type of the service
            ,80                                 // TCP or UDP port, at which this service is available
            ,((const BYTE *)"path=/index.htm")  // TXT info
            ,1                                  // auto rename the service when if needed
            ,NULL                               // no callback function
            ,NULL);                             // no application context
#endif //TCPIP_STACK_USE_ZEROCONF_MDNS_SD
    }

#if defined (TCPIP_STACK_USE_IPV6)
    TCPIP_ICMPV6_RegisterCallback(ICMPv6Callback);
#endif

#if defined(TCPIP_STACK_USE_ICMP_CLIENT)
    ICMPRegisterCallback(PingProcessIPv4);
#endif


#if defined(TCPIP_STACK_USE_EVENT_NOTIFICATION)
    TCPIP_NET_HANDLE hWiFi = TCPIP_STACK_NetHandle("MRF24W");
    if (hWiFi)
    {
       TCPIP_STACK_RegisterHandler(hWiFi, TCPIP_EV_RX_ALL | TCPIP_EV_TX_ALL | TCPIP_EV_RXTX_ERRORS, StackNotification, 0);
    }
#endif  // defined(TCPIP_STACK_USE_EVENT_NOTIFICATION)

#if defined(WF_UPDATE_FIRMWARE_UART_24G)
    extern bool    WF_FirmwareUpdate_Uart_24G(void);
    WF_FirmwareUpdate_Uart_24G();
#endif

  

    // Now that all items are initialized, begin the co-operative
    // multitasking loop.  This infinite loop will continuously
    // execute all stack-related tasks, as well as your own
    // application's functions.  Custom functions should be added
    // at the end of this loop.
    // Note that this is a "co-operative mult-tasking" mechanism
    // where every task performs its tasks (whether all in one shot
    // or part of it) and returns so that other tasks can do their
    // job.
    // If a task needs very long time to do its job, it must be broken
    // down into smaller pieces so that other tasks can have CPU time.
    while (1)
    {
        SYS_Tasks();

       
#if defined(SYS_USERIO_ENABLE)    
        // Blink LED0 (right most one) every second.
        if (SYS_TICK_Get() - startTick >= SYS_TICK_TicksPerSecondGet() / 2ul)
        {
            startTick = SYS_TICK_Get();
            LEDstate ^= SYS_USERIO_LED_ASSERTED;
            SYS_USERIO_SetLED(SYS_USERIO_LED_0, LEDstate);
        }
#endif  // defined(SYS_USERIO_ENABLE)   

        // This task performs normal stack task including checking
        // for incoming packet, type of packet and calling
        // appropriate stack entity to process it.
        TCPIP_STACK_Task();

        // Process application specific tasks here.
        // For this demo app, this will include the Generic TCP
        // client and servers, and the SNMP, Ping, and SNMP Trap
        // demos.  Following that, we will process any IO from
        // the inputs on the board itself.
        // Any custom modules or processing you need to do should
        // go here.
#if defined(TCPIP_STACK_USE_TCP) && defined(APP_USE_FTP_CLIENT_DEMO)
        FTPClient();
#endif        
#if defined(TCPIP_STACK_USE_TCP) && defined(APP_USE_GENERIC_TCP_CLIENT_DEMO)
        GenericTCPClient();
#endif

#if defined(TCPIP_STACK_USE_TCP) && defined(APP_USE_GENERIC_TCP_SERVER_DEMO)
        GenericTCPServer();
#endif

#if defined(TCPIP_STACK_USE_SMTP_CLIENT) && defined(APP_USE_SMTP_CLIENT_DEMO)
        SMTPDemo();
#endif

#if (defined(TCPIP_STACK_USE_ICMP_CLIENT) || defined (TCPIP_STACK_USE_IPV6)) && defined(APP_USE_PING_DEMO)
        // use ping on the default interface
        PingDemoTask();
#endif

#if defined(TCPIP_STACK_USE_SNMP_SERVER) && !defined(SNMP_TRAP_DISABLED)

        // User should use one of the following SNMP demo
        // This routine demonstrates V1 or V2 trap formats with one variable binding.

        //SNMPTrapDemo(); //This function sends the both SNMP trap version1 and 2 type of notifications

        #if defined(SNMP_STACK_USE_V2_TRAP) || defined(SNMP_V1_V2_TRAP_WITH_SNMPV3)
        //This routine provides V2 format notifications with multiple (3) variable bindings
        //User should modify this routine to send v2 trap format notifications with the required varbinds.
            SNMPV2TrapDemo(); //This function sends the SNMP trap version 2 type of notifications
        #endif

         /*
         SNMPSendTrap() is used to send trap notification to previously configured ip address if trap notification is enabled.
         There are different trap notification code. The current implementation sends trap for authentication failure (4).
           PreCondition: If application defined event occurs to send the trap. Declare a notification flag and update as the event occurs.
           Uncomment the below function if the application requires.

         if(notification flag is updated by the application as a predefined event occured)
        {
            SNMPSendTrap();
        }

        */

#endif 


#if defined(TCPIP_STACK_USE_BERKELEY_API) && defined(APP_USE_BERKELEY_API_DEMO)
        BerkeleyTCPClientDemo();
        BerkeleyTCPServerDemo();
        BerkeleyUDPClientDemo(0);
#endif

        // If the local IP address has changed (ex: due to DHCP lease change)
        // write the new IP address to the console display, UART, and Announce
        // service
        // We use the default interface
        for (i = 0; i < sizeof (TCPIP_HOSTS_CONFIGURATION) / sizeof (*TCPIP_HOSTS_CONFIGURATION); i++)
        {
            netH = TCPIP_STACK_NetHandle(TCPIP_HOSTS_CONFIGURATION[i].interface);
            if ((uint32_t) dwLastIP[i].Val != TCPIP_STACK_NetAddress(netH))
            {
                dwLastIP[i].Val = TCPIP_STACK_NetAddress(netH);

                SYS_CONSOLE_PRINT("Interface Name is: %s\r\n", TCPIP_HOSTS_CONFIGURATION[i].interface);
                SYS_CONSOLE_MESSAGE("New IP Address is: "); DisplayIPValue(dwLastIP[i]);
                SYS_CONSOLE_MESSAGE("\r\n");
            }
        }

#if defined(TCPIP_STACK_USE_EVENT_NOTIFICATION)
        if (stackNotifyCnt)
        {
            stackNotifyCnt = 0;
            ProcessNotification(stackNotifyHandle);
        }
#endif  // defined(TCPIP_STACK_USE_EVENT_NOTIFICATION)

#if defined(WF_UPDATE_FIRMWARE_TCPCLIENT_24G)
    void WF_FirmwareUpdate_TcpClient_24G(void);
    WF_FirmwareUpdate_TcpClient_24G();
#endif //defined(WF_UPDATE_FIRMWARE_TCPCLIENT_24G)

#if defined(HOST_CM_TEST)
       switch (g_event)
        {
            case WF_EVENT_CONNECTION_PERMANENTLY_LOST:
            case WF_EVENT_CONNECTION_FAILED:
                g_event = 0xff;             // clear current event
                // if host scan is active, it can be forced inactive by connection/re-connection process
                // so just reset host scan state to inactive.
                host_scan = FALSE;          // host scan inactive
                SYS_CONSOLE_MESSAGE("Reconnecting....\r\n");
                WF_Connect();
                break;
            case WF_EVENT_CONNECTION_SUCCESSFUL:
                g_event = 0xff;             // clear current event
                // if host scan is active, it can be forced inactive by connection/re-connection process
                // so just reset host scan state to inactive.
                host_scan = FALSE;          // host scan inactive
                break;
            case WF_EVENT_SCAN_RESULTS_READY:
                g_event = 0xff;             // clear current event
                host_scan = FALSE;          // host scan inactive
                // Scan results are valid - OK to retrieve
                if (SCANCXT.numScanResults > 0)
                {
                    SCAN_SET_DISPLAY(SCANCXT.scanState);
                    SCANCXT.displayIdx = 0;
                    while (IS_SCAN_STATE_DISPLAY(SCANCXT.scanState))
                         WFDisplayScanMgr();
                }
                break;
           case WF_EVENT_CONNECTION_TEMPORARILY_LOST:
                // This event can happened when CM in module is enabled.
                g_event = 0xff;         // clear current event
                // if host scan is active, it can be forced inactive by connection/re-connection process
                // so just reset host scan state to inactive.
                host_scan = FALSE;      // host scan inactive
                break;
            default:
                //sprintf(st,"skip event = %d\r\n",g_event);
                //SYS_CONSOLE_MESSAGE(st);
                break;
        }

       if (g_DhcpSuccessful)
       {

       /* Send and Receive UDP packets */
        if(UDPIsOpened(socket1))
        {
            // UDP TX every 10 msec
            if(SYS_TICK_Get() - timeudp >= SYS_TICK_TicksPerSecondGet() / 100)
            {
                timeudp = SYS_TICK_Get();
                tx_number++;
                LED0_IO ^= 1;
                sprintf(str,"rem=%12lu",tx_number);
                for(cntstr=16;cntstr<999;cntstr++)
                    str[cntstr]=cntstr;
                str[999]=0;
                // Send tx_number (formatted in a string)
                if(UDPIsTxPutReady(socket1,1000)!=0)
                {
                    UDPPutString(socket1,(BYTE *)str);
                    UDPFlush(socket1);
                    SYS_CONSOLE_MESSAGE(".");
                }
            }

            // UDP RX tx_number of remote board
            if(UDPIsGetReady(socket1)!=0)
            {
                LED1_IO ^= 1;
                UDPGetArray(socket1,(BYTE *)str,1000);
                str[16]=0;
                //sprintf((char*)LCDText,"%sloc=%12lu",str,tx_number); // Write on EXP16 LCD local and remote TX number
                //strcpypgm2ram(LCDText,str);
                //LCDUpdate();
                SYS_CONSOLE_MESSAGE("Rx");

            }
        }

        // Do host scan
         if((SYS_TICK_Get() - t1) >= SYS_TICK_TicksPerSecondGet() * 20)
        {
            t1 = SYS_TICK_Get();
            if (!host_scan)             // allow host scan if currently inactive
            {
                sprintf(st,"%d Scanning ..... event = %d\r\n",++scan_count, g_event);
                SYS_CONSOLE_MESSAGE(st);
                host_scan = TRUE;       // host scan active
                WF_Scan(0xff);          // scan on all channels
            }
        }
       } // DHCP status
       
#endif  //HOST_CM_TEST


    }
}
Esempio n. 18
0
/*****************************************************************************
  Function:
	void DHCPServerTask(NET_CONFIG* pConfig)

  Summary:
	Performs periodic DHCP server tasks.

  Description:
	This function performs any periodic tasks requied by the DHCP server 
	module, such as processing DHCP requests and distributing IP addresses.

  Precondition:
	None

  Parameters:
	pConfig   - interface

  Returns:
  	None
  ***************************************************************************/
void DHCPServerTask(NET_CONFIG* pConfig)
{
	uint8_t 				i;
	uint8_t				Option, Len;
	BOOTP_HEADER		BOOTPHeader;
	uint32_t				dw;
	bool				bAccept;
    int                 netIx;
    UDP_SOCKET          s;
    

#if defined(TCPIP_STACK_USE_DHCP_CLIENT)
	// Make sure we don't clobber anyone else's DHCP server
	if(DHCPIsServerDetected(pConfig))
		return;
#endif

    netIx = _TCPIPStackNetIx(pConfig);
	if(!bDHCPServerEnabled[netIx])
		return;

    s = MySocket[netIx];

	switch(smDHCPServer[netIx])
	{
		case DHCP_OPEN_SOCKET:
			// Obtain a UDP socket to listen/transmit on
			MySocket[netIx] = UDPOpen(0,UDP_OPEN_SERVER,DHCP_SERVER_PORT, DHCP_CLIENT_PORT);
			if(MySocket[netIx] == INVALID_UDP_SOCKET)
				break;

            UDPSocketSetNet(MySocket[netIx], pConfig);
			// Decide which address to lease out
			// Note that this needs to be changed if we are to 
			// support more than one lease
			DHCPNextLease[netIx].Val = (pConfig->MyIPAddr.Val & pConfig->MyMask.Val) + 0x02000000;
			if(DHCPNextLease[netIx].v[3] == 255u)
				DHCPNextLease[netIx].v[3] += 0x03;
			if(DHCPNextLease[netIx].v[3] == 0u)
				DHCPNextLease[netIx].v[3] += 0x02;

			smDHCPServer[netIx]++;

		case DHCP_LISTEN:
			// Check to see if a valid DHCP packet has arrived
			if(UDPIsGetReady(s) < 241u)
				break;

			// Retrieve the BOOTP header
			UDPGetArray(s, (uint8_t*)&BOOTPHeader, sizeof(BOOTPHeader));

			bAccept = (BOOTPHeader.ClientIP.Val == DHCPNextLease[netIx].Val) || (BOOTPHeader.ClientIP.Val == 0x00000000u);

			// Validate first three fields
			if(BOOTPHeader.MessageType != 1u)
				break;
			if(BOOTPHeader.HardwareType != 1u)
				break;
			if(BOOTPHeader.HardwareLen != 6u)
				break;

			// Throw away 10 unused bytes of hardware address,
			// server host name, and boot file name -- unsupported/not needed.
			for(i = 0; i < 64+128+(16-sizeof(MAC_ADDR)); i++)
				UDPGet(s, &Option);

			// Obtain Magic Cookie and verify
			UDPGetArray(s, (uint8_t*)&dw, sizeof(uint32_t));
			if(dw != 0x63538263ul)
				break;

			// Obtain options
			while(1)
			{
				// Get option type
				if(!UDPGet(s, &Option))
					break;
				if(Option == DHCP_END_OPTION)
					break;

				// Get option length
				UDPGet(s, &Len);
	
				// Process option
				switch(Option)
				{
					case DHCP_MESSAGE_TYPE:
						UDPGet(s, &i);
						switch(i)
						{
							case DHCP_DISCOVER_MESSAGE:
								DHCPReplyToDiscovery(&BOOTPHeader, netIx);
								break;

							case DHCP_REQUEST_MESSAGE:
							// NOTE : This #if section was missing from 5.36
                                #if defined(TCPIP_STACK_USE_ZEROCONF_LINK_LOCAL)
								if ( (BOOTPHeader.ClientIP.Val == 0x00000000u) &&
									 (bLeaseAvailable[netIx] == false) )
								{
									// Lease available only to the current lease holder
									break;
								}
								#endif

								DHCPReplyToRequest(&BOOTPHeader, bAccept, netIx);

							// NOTE : This #if section was missing from 5.36
                                #if defined(TCPIP_STACK_USE_ZEROCONF_LINK_LOCAL)
								bLeaseAvailable[netIx] = false;
								#endif

								break;

							// Need to handle these if supporting more than one DHCP lease
							case DHCP_RELEASE_MESSAGE:
							case DHCP_DECLINE_MESSAGE:
								break;
						}
						break;

					case DHCP_PARAM_REQUEST_IP_ADDRESS:
						if(Len == 4u)
						{
							// Get the requested IP address and see if it is the one we have on offer.
							UDPGetArray(s, (uint8_t*)&dw, 4);
							Len -= 4;
							bAccept = (dw == DHCPNextLease[netIx].Val);
						}
						break;

					case DHCP_END_OPTION:
						UDPDiscard(s);
						return;
				}

				// Remove any unprocessed bytes that we don't care about
				while(Len--)
				{
					UDPGet(s, &i);
				}
			}			

			UDPDiscard(s);
			break;
	}
}
Esempio n. 19
0
bool NBNSTask(TCPIP_NET_IF* pNetIf)
{
	uint8_t 			i;
	TCPIP_UINT16_VAL    Type, Class;
	NBNS_HEADER			NBNSHeader;
	uint8_t				NameString[16];
    UDP_SOCKET          s;
    int                 nbnsRxSize;
    int                 nbnsTxSize;

    s = nbnsDcpt.uSkt;

	switch(nbnsDcpt.sm)
    {
        case NBNS_HOME:
            nbnsDcpt.sm++;
            break;

        case NBNS_OPEN_SOCKET:
            s = UDPOpenServer(IP_ADDRESS_TYPE_IPV4, NBNS_PORT, 0);
            if(s == INVALID_UDP_SOCKET)
                break;

            if(!UDPRemoteBind(s, IP_ADDRESS_TYPE_IPV4, NBNS_PORT,  0))
            {
                UDPClose(s);
                break;
            }

            nbnsDcpt.uSkt = s;
            nbnsDcpt.sm++;

        case NBNS_LISTEN:
            //if(!UDPIsGetReady(s))
            nbnsRxSize = UDPIsGetReady(s);
            if(!nbnsRxSize)
            {
                break;
            }


            // Respond only to name requests sent to us from nodes on the same subnet
            // This prevents us from sending out the wrong IP address information if 
            // we haven't gotten a DHCP lease yet.
            if((remoteNode.IPAddr.Val & pNetIf->netMask.Val) != (pNetIf->netIPAddr.Val & pNetIf->netMask.Val))
            {
                UDPDiscard(s);
                break;
            }

#ifdef _NBNS_DEBUG
            nbnsRxOks++;
            if(nbnsRxSize > nbnsRxMaxSize)
            {
                nbnsRxMaxSize = nbnsRxSize;
            }
#endif  // _NBNS_DEBUG
            // Retrieve the NBNS header and de-big-endian it
            UDPGet(s, &NBNSHeader.TransactionID.v[1]);
            UDPGet(s, &NBNSHeader.TransactionID.v[0]);
            UDPGet(s, &NBNSHeader.Flags.v[1]);
            UDPGet(s, &NBNSHeader.Flags.v[0]);
            UDPGet(s, &NBNSHeader.Questions.v[1]);
            UDPGet(s, &NBNSHeader.Questions.v[0]);
            UDPGet(s, &NBNSHeader.Answers.v[1]);
            UDPGet(s, &NBNSHeader.Answers.v[0]);
            UDPGet(s, &NBNSHeader.AuthoritativeRecords.v[1]);
            UDPGet(s, &NBNSHeader.AuthoritativeRecords.v[0]);
            UDPGet(s, &NBNSHeader.AdditionalRecords.v[1]);
            UDPGet(s, &NBNSHeader.AdditionalRecords.v[0]);

            // Remove all questions
            while(NBNSHeader.Questions.Val--)
            {
                NBNSGetName(s, NameString);
                UDPGet(s, &i);				// <??> Trailing character on string
                UDPGet(s, &Type.v[1]);		// Question type
                UDPGet(s, &Type.v[0]);
                UDPGet(s, &Class.v[1]);	// Question class
                UDPGet(s, &Class.v[0]);

                if(Type.Val == 0x0020u && Class.Val == 0x0001u)
                {
                    int nIfs, nIx;
                    TCPIP_NET_IF*   pIf;
                    const char*     netbName;

                    nIfs = TCPIP_STACK_NetworksNo();
                    for(nIx = 0; nIx < nIfs; nIx++)
                    { 
                        pIf = (TCPIP_NET_IF*)TCPIP_STACK_IxToNet(nIx); 
                        netbName = TCPIP_STACK_NetBIOSName(pIf);    // this checks the IF is up!
                        if(memcmp((void*)NameString, netbName, sizeof(pIf->NetBIOSName)) == 0)
                        {   // one of our interfaces has this name
                            nbnsTxSize = UDPIsTxPutReady(s, 64);
                            if(nbnsTxSize)
                            {   
#ifdef _NBNS_DEBUG
                                nbnsTxOks++;    
                                if(nbnsTxSize > nbnsTxMaxSize)
                                {
                                    nbnsTxMaxSize = nbnsTxSize;
                                }
#endif  // _NBNS_DEBUG

                                NBNSHeader.Flags.Val = 0x8400;

                                UDPPut(s, NBNSHeader.TransactionID.v[1]);
                                UDPPut(s, NBNSHeader.TransactionID.v[0]);
                                UDPPut(s, NBNSHeader.Flags.v[1]);
                                UDPPut(s, NBNSHeader.Flags.v[0]);
                                UDPPut(s, 0x00);	// 0x0000 Questions
                                UDPPut(s, 0x00);
                                UDPPut(s, 0x00);	// 0x0001 Answers
                                UDPPut(s, 0x01);
                                UDPPut(s, 0x00);	// 0x0000 Athoritative records
                                UDPPut(s, 0x00);
                                UDPPut(s, 0x00);	// 0x0000 Additional records
                                UDPPut(s, 0x00);

                                NBNSPutName(s, netbName);
                                UDPPut(s, 0x00);	// 0x0020 Type: NetBIOS
                                UDPPut(s, 0x20);
                                UDPPut(s, 0x00);	// 0x0001 Class: Internet
                                UDPPut(s, 0x01);
                                UDPPut(s, 0x00);	// 0x00000000 Time To Live
                                UDPPut(s, 0x00);
                                UDPPut(s, 0x00);
                                UDPPut(s, 0x00);

                                UDPPut(s, 0x00);	// 0x0006 Data length
                                UDPPut(s, 0x06);	
                                UDPPut(s, 0x60);	// 0x6000 Flags: H-node, Unique
                                UDPPut(s, 0x00);
                                UDPPut(s, pIf->netIPAddr.v[0]);	// Put out IP address
                                UDPPut(s, pIf->netIPAddr.v[1]);
                                UDPPut(s, pIf->netIPAddr.v[2]);
                                UDPPut(s, pIf->netIPAddr.v[3]);

                                // Change the destination address to the unicast address of the last received packet
                                UDPSetDestinationIPAddress(s, IP_ADDRESS_TYPE_IPV4, (IP_MULTI_ADDRESS*)&remoteNode.IPAddr);
                                memcpy((void*)&((IPV4_PACKET*)UDPSocketDcpt[s].pTxPkt)->remoteMACAddr, (const void*)&remoteNode.MACAddr, sizeof(remoteNode.MACAddr));
                                UDPFlush(s);				
                            }
#ifdef _NBNS_DEBUG
                            else
                            {
                                nbnsTxFails++;
                            }
#endif  // _NBNS_DEBUG
                            break;
                        }
                    }
                }
            }

            UDPDiscard(s);

            break;
    }

    return true;
}
Esempio n. 20
0
/*********************************************************************
 * Function:        void DNSServerTask(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Sends dummy responses that point to ourself for DNS requests
 *
 * Note:            None
 ********************************************************************/
void DNSServerTask(void)
{
	static UDP_SOCKET	MySocket = INVALID_UDP_SOCKET;
	struct
	{
		WORD wTransactionID;
		WORD wFlags;
		WORD wQuestions;
		WORD wAnswerRRs;
		WORD wAuthorityRRs;
		WORD wAdditionalRRs;
	} DNSHeader;


	// Create a socket to listen on if this is the first time calling this function
	if(MySocket == INVALID_UDP_SOCKET)
	{
		//MySocket = UDPOpen(DNS_PORT, NULL, 0);
		
		MySocket = UDPOpenEx(0,UDP_OPEN_SERVER,DNS_PORT,0);
		return;
	}

	// See if a DNS query packet has arrived
	if(UDPIsGetReady(MySocket) < sizeof(DNSHeader))
		return;

	// Read DNS header
	UDPGetArray((BYTE*)&DNSHeader, sizeof(DNSHeader));

	// Ignore this packet if it isn't a query
	if((DNSHeader.wFlags & 0x8000) == 0x8000u)
		return;

	// Ignore this packet if there are no questions in it
	if(DNSHeader.wQuestions == 0u)
		return;

	// Block until we can transmit a DNS response packet
	while(!UDPIsPutReady(MySocket));

	// Write DNS response packet
	UDPPutArray((BYTE*)&DNSHeader.wTransactionID, 2);	// 2 byte Transaction ID
	if(DNSHeader.wFlags & 0x0100)
		UDPPut(0x81);	// Message is a response with recursion desired
	else
		UDPPut(0x80);	// Message is a response without recursion desired flag set
	UDPPut(0x80);	// Recursion available
	UDPPut(0x00);	// 0x0000 Questions
	UDPPut(0x00);
	UDPPut(0x00);	// 0x0001 Answers RRs
	UDPPut(0x01);
	UDPPut(0x00);	// 0x0000 Authority RRs
	UDPPut(0x00);
	UDPPut(0x00);	// 0x0000 Additional RRs
	UDPPut(0x00);
	DNSCopyRXNameToTX();	// Copy hostname of first question over to TX packet
	UDPPut(0x00);	// Type A Host address
	UDPPut(0x01);
	UDPPut(0x00);	// Class INternet
	UDPPut(0x01);
	UDPPut(0x00);	// Time to Live 10 seconds
	UDPPut(0x00);
	UDPPut(0x00);
	UDPPut(0x0A);
	UDPPut(0x00);	// Data Length 4 bytes
	UDPPut(0x04);
	UDPPutArray((BYTE*)&AppConfig.MyIPAddr.Val, 4);	// Our IP address
	#warning tim had added extra code here
	UDPFlush();
}
Esempio n. 21
0
/*****************************************************************************
  Function:
	static void DHCPReplyToRequest(BOOTP_HEADER *Header, bool bAccept, int netIx)

  Summary:
	Replies to a DHCP Request message.

  Description:
	This function replies to a DHCP Request message by sending out a 
	DHCP Acknowledge message.

  Precondition:
	None

  Parameters:
	Header - the BootP header this is in response to.
	bAccept - whether or not we've accepted this request
    netIx   - interface index

  Returns:
  	None
  
  Internal:
	Needs to support more than one simultaneous lease in the future.
  ***************************************************************************/
static void DHCPReplyToRequest(BOOTP_HEADER *Header, bool bAccept, int netIx)
{
	uint8_t         i;
    NET_CONFIG*     pConfig;
    UDP_SOCKET      s;
    
	// Set the correct socket to active and ensure that 
	// enough space is available to generate the DHCP response
    s = MySocket[netIx];
    if(UDPIsPutReady(s) < 300u)
		return;
    
    pConfig = UDPSocketGetNet(s);

	// Search through all remaining options and look for the Requested IP address field
	// Obtain options
	while(UDPIsGetReady(s))
	{
		uint8_t Option, Len;
		uint32_t dw;

		// Get option type
		if(!UDPGet(s, &Option))
			break;
		if(Option == DHCP_END_OPTION)
			break;

		// Get option length
		UDPGet(s, &Len);

		// Process option
		if((Option == DHCP_PARAM_REQUEST_IP_ADDRESS) && (Len == 4u))
		{
			// Get the requested IP address and see if it is the one we have on offer.  If not, we should send back a NAK, but since there could be some other DHCP server offering this address, we'll just silently ignore this request.
			UDPGetArray(s, (uint8_t*)&dw, 4);
			Len -= 4;
			if(dw != DHCPNextLease[netIx].Val)
			{
				bAccept = false;
			}
			break;
		}

		// Remove the unprocessed bytes that we don't care about
		while(Len--)
		{
			UDPGet(s, &i);
		}
	}			

	// Begin putting the BOOTP Header and DHCP options
	UDPPut(s, BOOT_REPLY);			// Message Type: 2 (BOOTP Reply)
	// Reply with the same Hardware Type, Hardware Address Length, Hops, and Transaction ID fields
	UDPPutArray(s, (uint8_t*)&(Header->HardwareType), 7);
	UDPPut(s, 0x00);				// Seconds Elapsed: 0 (Not used)
	UDPPut(s, 0x00);				// Seconds Elapsed: 0 (Not used)
	UDPPutArray(s, (uint8_t*)&(Header->BootpFlags), sizeof(Header->BootpFlags));
	UDPPutArray(s, (uint8_t*)&(Header->ClientIP), sizeof(IP_ADDR));// Your (client) IP Address:
	UDPPutArray(s, (uint8_t*)&DHCPNextLease[netIx], sizeof(IP_ADDR));	// Lease IP address to give out
	UDPPut(s, 0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(s, 0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(s, 0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(s, 0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(s, 0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPut(s, 0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPut(s, 0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPut(s, 0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPutArray(s, (uint8_t*)&(Header->ClientMAC), sizeof(MAC_ADDR));	// Client MAC address: Same as given by client
	for(i = 0; i < 64+128+(16-sizeof(MAC_ADDR)); i++)	// Remaining 10 bytes of client hardware address, server host name: Null string (not used)
		UDPPut(s, 0x00);									// Boot filename: Null string (not used)
	UDPPut(s, 0x63);				// Magic Cookie: 0x63538263
	UDPPut(s, 0x82);				// Magic Cookie: 0x63538263
	UDPPut(s, 0x53);				// Magic Cookie: 0x63538263
	UDPPut(s, 0x63);				// Magic Cookie: 0x63538263
	
	// Options: DHCP lease ACKnowledge
	if(bAccept)
	{
		UDPPut(s, DHCP_OPTION_ACK_MESSAGE);	
		UDPPut(s, 1);
		UDPPut(s, DHCP_ACK_MESSAGE);
	}
	else	// Send a NACK
	{
		UDPPut(s, DHCP_OPTION_ACK_MESSAGE);	
		UDPPut(s, 1);
		UDPPut(s, DHCP_NAK_MESSAGE);
	}

	// Option: Lease duration
	UDPPut(s, DHCP_IP_LEASE_TIME);
	UDPPut(s, 4);
	UDPPut(s, (DHCP_LEASE_DURATION>>24) & 0xFF);
	UDPPut(s, (DHCP_LEASE_DURATION>>16) & 0xFF);
	UDPPut(s, (DHCP_LEASE_DURATION>>8) & 0xFF);
	UDPPut(s, (DHCP_LEASE_DURATION) & 0xFF);

	// Option: Server identifier
	UDPPut(s, DHCP_SERVER_IDENTIFIER);	
	UDPPut(s, sizeof(IP_ADDR));
	UDPPutArray(s, (uint8_t*)&pConfig->MyIPAddr, sizeof(IP_ADDR));

	// Option: Subnet Mask
	UDPPut(s, DHCP_SUBNET_MASK);
	UDPPut(s, sizeof(IP_ADDR));
	UDPPutArray(s, (uint8_t*)&pConfig->MyMask, sizeof(IP_ADDR));

	// Option: Router/Gateway address
	UDPPut(s, DHCP_ROUTER);		
	UDPPut(s, sizeof(IP_ADDR));
	UDPPutArray(s, (uint8_t*)&pConfig->MyIPAddr, sizeof(IP_ADDR));

	// Option: DNS server address
	UDPPut(s, DHCP_DNS);
	UDPPut(s, sizeof(IP_ADDR));
	UDPPutArray(s, (uint8_t*)&pConfig->MyIPAddr, sizeof(IP_ADDR));

	// No more options, mark ending
	UDPPut(s, DHCP_END_OPTION);

	// Add zero padding to ensure compatibility with old BOOTP relays that discard small packets (<300 UDP octets)
	while(UDPGetTxCount(s) < 300u)
		UDPPut(s, 0); 

	// Force remote destination address to be the broadcast address, regardless 
	// of what the node's source IP address was (to ensure we don't try to 
	// unicast to 0.0.0.0).
	memset((void*)&UDPSocketDcpt[s].remoteNode, 0xFF, sizeof(NODE_INFO));

	// Transmit the packet
	UDPFlush(s);
}
Esempio n. 22
0
/**
 * Call DNSIsResolved() until the host is resolved.
 * You cannot start two DNS resolution proceedures concurrently.
 * You must not modify *Hostname until DNSIsResolved() returns TRUE.
 *
 * @preCondition        DNSResolve() was called.
 *
 * @param HostIP        4 byte IP address
 */
BOOL DNSIsResolved(IP_ADDR *HostIP)
{
    static UDP_SOCKET   MySocket;
    static NODE_INFO    Remote;
    static TICK         StartTime;
    BYTE                i;
    WORD_VAL            w;
    DNS_HEADER          DNSHeader;
    DNS_ANSWER_HEADER   DNSAnswerHeader;
    IP_ADDR             tmpIpAddr;

    switch(smDNS)
    {
        case DNS_HOME:
            tmpIpAddr.v[0] = MY_DNS_BYTE1;
            tmpIpAddr.v[1] = MY_DNS_BYTE2;
            tmpIpAddr.v[2] = MY_DNS_BYTE3;
            tmpIpAddr.v[3] = MY_DNS_BYTE4;
            ARPResolve(&tmpIpAddr);
            StartTime = TickGet();
            smDNS++;
            break;
        case DNS_RESOLVE_ARP:
            if(!ARPIsResolved(&tmpIpAddr, &Remote.MACAddr))
            {
                if(TickGet() - StartTime > DNS_TIMEOUT)
                {
                    smDNS--;
                }
                break;
            }
            Remote.IPAddr.Val = tmpIpAddr.Val;
            smDNS++;
            // No need to break, we can immediately start resolution

        case DNS_OPEN_SOCKET:
            MySocket = UDPOpen(0, &Remote, DNS_PORT);
            if(MySocket == INVALID_UDP_SOCKET) {
                #if (DEBUG_DNS >= LOG_ERROR)
                debugPutMsg(1); //@mxd:1:Could not open UDP socket
                #endif

                break;
            }

            smDNS++;
            // No need to break, we can immediately start resolution
            
        case DNS_QUERY:
            if(!UDPIsPutReady(MySocket))
                break;
            
            // Put DNS query here
            UDPPut(0x12);        // User chosen ID
            UDPPut(0x34);
            UDPPut(0x01);        // Standard query with recursion
            UDPPut(0x00);    
            UDPPut(0x00);        // 0x0001 questions
            UDPPut(0x01);
            UDPPut(0x00);        // 0x0000 answers
            UDPPut(0x00);
            UDPPut(0x00);        // 0x0000 name server resource records
            UDPPut(0x00);
            UDPPut(0x00);        // 0x0000 additional records
            UDPPut(0x00);

            // Put hostname string to resolve
            DNSPutString(DNSHostName);

            UDPPut(0x00);        // Type: A (host address)
            UDPPut(0x01);
            UDPPut(0x00);        // Class: IN (Internet)
            UDPPut(0x01);

            UDPFlush();
            StartTime = TickGet();
            smDNS++;
            break;

        case DNS_GET_RESULT:
            if(!UDPIsGetReady(MySocket))
            {
                if(TickGet() - StartTime > DNS_TIMEOUT)
                {
                    smDNS--;
                }
                break;
            }

            // Retrieve the DNS header and de-big-endian it
            UDPGet(&DNSHeader.TransactionID.v[1]);
            UDPGet(&DNSHeader.TransactionID.v[0]);
            UDPGet(&DNSHeader.Flags.v[1]);
            UDPGet(&DNSHeader.Flags.v[0]);
            UDPGet(&DNSHeader.Questions.v[1]);
            UDPGet(&DNSHeader.Questions.v[0]);
            UDPGet(&DNSHeader.Answers.v[1]);
            UDPGet(&DNSHeader.Answers.v[0]);
            UDPGet(&DNSHeader.AuthoritativeRecords.v[1]);
            UDPGet(&DNSHeader.AuthoritativeRecords.v[0]);
            UDPGet(&DNSHeader.AdditionalRecords.v[1]);
            UDPGet(&DNSHeader.AdditionalRecords.v[0]);

            // Remove all questions
            while(DNSHeader.Questions.Val--)
            {
                DNSGetString(NULL);
                UDPGet(&w.v[1]);        // Question type
                UDPGet(&w.v[0]);
                UDPGet(&w.v[1]);        // Question class
                UDPGet(&w.v[0]);
            }
            
            // Scan through answers
            while(DNSHeader.Answers.Val--)
            {
                UDPGet(&DNSAnswerHeader.ResponseName.v[1]);        // Response name
                UDPGet(&DNSAnswerHeader.ResponseName.v[0]);
                UDPGet(&DNSAnswerHeader.ResponseType.v[1]);        // Response type
                UDPGet(&DNSAnswerHeader.ResponseType.v[0]);
                UDPGet(&DNSAnswerHeader.ResponseClass.v[1]);    // Response class
                UDPGet(&DNSAnswerHeader.ResponseClass.v[0]);
                UDPGet(&DNSAnswerHeader.ResponseTTL.v[3]);        // Time to live
                UDPGet(&DNSAnswerHeader.ResponseTTL.v[2]);
                UDPGet(&DNSAnswerHeader.ResponseTTL.v[1]);
                UDPGet(&DNSAnswerHeader.ResponseTTL.v[0]);
                UDPGet(&DNSAnswerHeader.ResponseLen.v[1]);        // Response length
                UDPGet(&DNSAnswerHeader.ResponseLen.v[0]);

                // Make sure that this is a 4 byte IP address, response type A, class 1
                // Check if this is Type A
                if(    DNSAnswerHeader.ResponseType.Val    == 0x0001u && 
                    DNSAnswerHeader.ResponseClass.Val    == 0x0001u && // Internet class
                    DNSAnswerHeader.ResponseLen.Val        == 0x0004u)
                {
                    UDPGet(&HostIP->v[0]);
                    UDPGet(&HostIP->v[1]);
                    UDPGet(&HostIP->v[2]);
                    UDPGet(&HostIP->v[3]);
                    break;
                }
                else
                {
                    while(DNSAnswerHeader.ResponseLen.Val--)
                    {
                        UDPGet(&i);
                    }
                }
            }

            UDPDiscard();
            UDPClose(MySocket);
            MySocket = INVALID_UDP_SOCKET;
            smDNS++;
            // No need to break, we are done and need to return TRUE

        case DNS_DONE:
            return TRUE;
    }
    
    return FALSE;
}
Esempio n. 23
0
void EthernetRun(void (*ProcessData)(BYTE *data, WORD dataLen))
{
    // Now that all items are initialized, begin the co-operative
    // multitasking loop.  This infinite loop will continuously 
    // execute all stack-related tasks, as well as your own
    // application's functions.  Custom functions should be added
    // at the end of this loop.
    // Note that this is a "co-operative mult-tasking" mechanism
    // where every task performs its tasks (whether all in one shot
    // or part of it) and returns so that other tasks can do their
    // job.
    // If a task needs very long time to do its job, it must be broken
    // down into smaller pieces so that other tasks can have CPU time.

	// First prepare all UDP stuff.
	UDPTask();

	WORD dataCount;
	IP_ADDR tempLocalIP;
	BYTE cFrameType;
	BYTE cIPFrameType;

	// And then process incoming data ending this loop once a valid packet is received.
	int cont = 1;
	while (cont) {
		// Before fetching new data, be sure all old UDP data is discarded.
		UDPDiscard();

		// Fetch a packet. We stop receiving data if no data is waiting.
		if (!MACGetHeader(&remoteNode.MACAddr, &cFrameType)) {
			break;
		}

		// And now process the packet.
		switch(cFrameType) {
			// Process any ARP packets. These are used for determining a MAC-to-IP mapping.
			case MAC_ARP:
				ARPProcess();
				break;

			// Process any IP packets (of which UDP is a type).
			case MAC_IP:
				// If the received packet is not a valid IP packet, ignore it.
				if (!IPGetHeader(&tempLocalIP, &remoteNode, &cIPFrameType, &dataCount)) {
					break;
				}

				// Now if we've found a valid UDP packet, quit processing data.
				if (cIPFrameType == IP_PROT_UDP) {
					// Stop processing data if we came upon a complete UDP packet.
					if (UDPProcess(&remoteNode, &tempLocalIP, dataCount)) {
						cont = 0;
					}
				}

				break;
		}
	}

	// Send new UDP data to processing function.
	if (ProcessData) {
		WORD dataLen = 0;
		if ((dataLen = UDPIsGetReady(localServerSocket))) {
			BYTE data[dataLen];
			if (UDPGetArray(data, dataLen) == dataLen) {
				ProcessData(data, dataLen);
			}
		}
	}

	// Now run the DHCP server task. This needs to be run continuously as there's no way to tell
	// if any clients are connected to perform the lease once post-init. The default lease time
	// is also super short, 60s, so the server needs to be able to process new DHCP stuff.
	DHCPServerTask();
}
Esempio n. 24
0
/*****************************************************************************
  Function:
	void DHCPServerTask(void)

  Summary:
	Performs periodic DHCP server tasks.

  Description:
	This function performs any periodic tasks requied by the DHCP server 
	module, such as processing DHCP requests and distributing IP addresses.

  Precondition:
	None

  Parameters:
	None

  Returns:
  	None
  ***************************************************************************/
void DHCPServerTask(void)
{
	BYTE 				i;
	BYTE				Option, Len;
	BOOTP_HEADER		BOOTPHeader;
	DWORD				dw;
	BOOL				bAccept;
	static enum
	{
		DHCP_OPEN_SOCKET,
		DHCP_LISTEN
	} smDHCPServer = DHCP_OPEN_SOCKET;

#if defined(STACK_USE_DHCP_CLIENT)
	// Make sure we don't clobber anyone else's DHCP server
	if(DHCPIsServerDetected(0))
		return;
#endif

	if(!bDHCPServerEnabled)
		return;

	switch(smDHCPServer)
	{
		case DHCP_OPEN_SOCKET:
			// Obtain a UDP socket to listen/transmit on
			//MySocket = UDPOpen(DHCP_SERVER_PORT, NULL, DHCP_CLIENT_PORT);
			MySocket = UDPOpenEx(0,UDP_OPEN_SERVER,DHCP_SERVER_PORT, DHCP_CLIENT_PORT);
			if(MySocket == INVALID_UDP_SOCKET)
				break;


			// Decide which address to lease out
			// Note that this needs to be changed if we are to 
			// support more than one lease
			DHCPNextLease.Val = (AppConfig.MyIPAddr.Val & AppConfig.MyMask.Val) + 0x02000000;
			if(DHCPNextLease.v[3] == 255u)
				DHCPNextLease.v[3] += 0x03;
			if(DHCPNextLease.v[3] == 0u)
				DHCPNextLease.v[3] += 0x02;

			smDHCPServer++;

		case DHCP_LISTEN:
			// Check to see if a valid DHCP packet has arrived
			if(UDPIsGetReady(MySocket) < 241u)
				break;

			// Retrieve the BOOTP header
			UDPGetArray((BYTE*)&BOOTPHeader, sizeof(BOOTPHeader));

			bAccept = (BOOTPHeader.ClientIP.Val == DHCPNextLease.Val) || (BOOTPHeader.ClientIP.Val == 0x00000000u);

			// Validate first three fields
			if(BOOTPHeader.MessageType != 1u)
				break;
			if(BOOTPHeader.HardwareType != 1u)
				break;
			if(BOOTPHeader.HardwareLen != 6u)
				break;

			// Throw away 10 unused bytes of hardware address,
			// server host name, and boot file name -- unsupported/not needed.
			for(i = 0; i < 64+128+(16-sizeof(MAC_ADDR)); i++)
				UDPGet(&Option);

			// Obtain Magic Cookie and verify
			UDPGetArray((BYTE*)&dw, sizeof(DWORD));
			if(dw != 0x63538263ul)
				break;

			// Obtain options
			while(1)
			{
				// Get option type
				if(!UDPGet(&Option))
					break;
				if(Option == DHCP_END_OPTION)
					break;

				// Get option length
				UDPGet(&Len);
	
				// Process option
				switch(Option)
				{
					case DHCP_MESSAGE_TYPE:
						UDPGet(&i);
						switch(i)
						{
							case DHCP_DISCOVER_MESSAGE:
								DHCPReplyToDiscovery(&BOOTPHeader);
								break;

							case DHCP_REQUEST_MESSAGE:
								DHCPReplyToRequest(&BOOTPHeader, bAccept);
								break;

							// Need to handle these if supporting more than one DHCP lease
							case DHCP_RELEASE_MESSAGE:
							case DHCP_DECLINE_MESSAGE:
								break;
						}
						break;

					case DHCP_PARAM_REQUEST_IP_ADDRESS:
						if(Len == 4u)
						{
							// Get the requested IP address and see if it is the one we have on offer.
							UDPGetArray((BYTE*)&dw, 4);
							Len -= 4;
							bAccept = (dw == DHCPNextLease.Val);
						}
						break;

					case DHCP_END_OPTION:
						UDPDiscard();
						return;
				}

				// Remove any unprocessed bytes that we don't care about
				while(Len--)
				{
					UDPGet(&i);
				}
			}			

			UDPDiscard();
			break;
	}
}
Esempio n. 25
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;
	}
}
Esempio n. 26
0
/*********************************************************************
 * Function:        TFTP_RESULT TFTPIsGetReady(void)
 *
 * PreCondition:    TFTPOpenFile() is called with TFTP_FILE_MODE_READ
 *                  and TFTPIsFileOpened() returned with TRUE.
 *
 * Input:           None
 *
 * Output:          TFTP_OK if it there is more data byte available
 *                  to read
 *
 *                  TFTP_TIMEOUT if timeout occurred waiting for
 *                  new data.
 *
 *                  TFTP_END_OF_FILE if end of file has reached.
 *
 *                  TFTP_ERROR if remote server returned ERROR.
 *                      Actual error code may be read by calling
 *                      TFTPGetError()
 *
 *                  TFTP_NOT_READY if still waiting for new data.
 *
 * Side Effects:    None
 *
 * Overview:        Waits for data block.  If data block does not
 *                  arrive within specified timeout, it automatically
 *                  sends out ack for previous block to remind
 *                  server to send next data block.
 *                  If all attempts are exhausted, it returns with
 *                  TFTP_TIMEOUT.
 *
 * Note:            By default, this funciton uses "octet" or binary
 *                  mode of file transfer.
 ********************************************************************/
TFTP_RESULT TFTPIsGetReady(void)
{
    WORD_VAL opCode;
    WORD_VAL blockNumber;
    BOOL bTimeOut;


    // Check to see if timeout has occurred.
    bTimeOut = FALSE;
    if ( TickGetDiff(TickGet(), _tftpStartTick) >= TFTP_GET_TIMEOUT_VAL )
    {
        bTimeOut = TRUE;
        _tftpStartTick = TickGet();
    }


    switch(_tftpState)
    {
    case SM_TFTP_WAIT_FOR_DATA:
        // If timeout occurs in this state, it may be because, we have not
        // even received very first data block or some in between block.
        if ( bTimeOut == TRUE )
        {
            bTimeOut = FALSE;

            if ( _tftpRetries++ > (TFTP_MAX_RETRIES-1) )
            {
                DEBUG(printf("TFTPIsGetReady(): Timeout.\n"));

                // Forget about all previous attempts.
                _tftpRetries = 1;

                return TFTP_TIMEOUT;
            }

            // If we have not even received first block, ask application
            // retry.
            if ( MutExVar.group2._tftpBlockNumber.Val == 1 )
            {
                DEBUG(printf("TFTPIsGetReady(): TFTPOpen Retry.\n"));
                return TFTP_RETRY;
            }
            else
            {
                DEBUG(printf("TFTPIsGetReady(): ACK Retry #%d...,\n", _tftpRetries));

                // Block number was already incremented in last ACK attempt,
                // so decrement it.
                MutExVar.group2._tftpBlockNumber.Val--;

                // Do it.
                _tftpState = SM_TFTP_SEND_ACK;
                break;
            }
        }

        // For Read operation, server will respond with data block.
        if ( !UDPIsGetReady(_tftpSocket) )
            break;

        // Get opCode
        UDPGet(&opCode.byte.MSB);
        UDPGet(&opCode.byte.LSB);

        // Get block number.
        UDPGet(&blockNumber.byte.MSB);
        UDPGet(&blockNumber.byte.LSB);

        // In order to read file, this must be data with block number of 0.
        if ( opCode.Val == TFTP_OPCODE_DATA )
        {
            // Make sure that this is not a duplicate block.
            if ( MutExVar.group2._tftpBlockNumber.Val == blockNumber.Val )
            {
                // Mark that we have not acked this block.
                _tftpFlags.bits.bIsAcked = FALSE;

                // Since we have a packet, forget about previous retry count.
                _tftpRetries = 1;

                _tftpState = SM_TFTP_READY;
                return TFTP_OK;
            }

            // If received block has already been received, simply ack it
            // so that Server can "get over" it and send next block.
            else if ( MutExVar.group2._tftpBlockNumber.Val > blockNumber.Val )
            {
                DEBUG(printf("TFTPIsGetReady(): "\
                            "Duplicate block %d received - droping it...\n", \
                            blockNumber.Val));
                MutExVar.group2._tftpDuplicateBlock.Val = blockNumber.Val;
                _tftpState = SM_TFTP_DUPLICATE_ACK;
            }
#if defined(TFTP_DEBUG)
            else
            {
                DEBUG(printf("TFTPIsGetReady(): "\
                             "Unexpected block %d received - droping it...\n", \
                             blockNumber.Val));
            }
#endif
        }
        // Discard all unexpected and error blocks.
        UDPDiscard();

        // If this was an error, remember error code for later delivery.
        if ( opCode.Val == TFTP_OPCODE_ERROR )
        {
            _tftpError = blockNumber.Val;
            return TFTP_ERROR;
        }

        break;

    case SM_TFTP_DUPLICATE_ACK:
        if ( UDPIsPutReady(_tftpSocket) )
        {
            _TFTPSendAck(MutExVar.group2._tftpDuplicateBlock);
            _tftpState = SM_TFTP_WAIT_FOR_DATA;
        }
        break;

    case SM_TFTP_READY:
        if ( UDPIsGetReady(_tftpSocket) )
        {
            _tftpStartTick = TickGet();
            return TFTP_OK;
        }

        // End of file is reached when data block is less than 512 bytes long.
        // To reduce code, only MSB compared against 0x02 (of 0x200 = 512) to
        // determine if block is less than 512 bytes long or not.
        else if ( MutExVar.group2._tftpBlockLength.Val == 0 ||
                  MutExVar.group2._tftpBlockLength.byte.MSB < TFTP_BLOCK_SIZE_MSB )
            _tftpState = SM_TFTP_SEND_LAST_ACK;
        else
            break;


    case SM_TFTP_SEND_LAST_ACK:
    case SM_TFTP_SEND_ACK:
        if ( UDPIsPutReady(_tftpSocket) )
        {
            _TFTPSendAck(MutExVar.group2._tftpBlockNumber);

            // This is the next block we are expecting.
            MutExVar.group2._tftpBlockNumber.Val++;

            // Remember that we have already acked current block.
            _tftpFlags.bits.bIsAcked = TRUE;

            if ( _tftpState == SM_TFTP_SEND_LAST_ACK )
                return TFTP_END_OF_FILE;

            _tftpState = SM_TFTP_WAIT_FOR_DATA;
        }
        break;
    }



    return TFTP_NOT_READY;
}
void Command()
{
	switch (Cmd_Read_Switch)
	{
		case	0	:	if(UDPIsGetReady(socket2))
						{
							SuccesFull_Read = UDPGetArray(Cmd, 0x3);
							if (Cmd[0] == Enter || Cmd[0] == 0 || SuccesFull_Read < 3)
							{
								Cmd_Read_Switch = 0;
								Cmd[0] = 0;
								break;
							}							
							else if (Cmd[2] == Enter)
							{
								Cmd_Read_Switch = 0;
								Command_Exe(Cmd);									
							}
							Cmd_Read_Switch = 0;
							Cmd[0] = 0;
							Cmd[1] = 0;
							Cmd[2] = 0;
							break;
						}
						break;
						
		case	20	:	if(!MACIsLinked())
						{
							return;
						}
						
						#if defined(STACK_USE_DHCP_CLIENT)
						{
							static DWORD dwTimer = 0;
							
							// Wait until DHCP module is finished
							if(!DHCPIsBound(0))
							{
								dwTimer = TickGet();
								return;
							}
					
							// Wait an additional half second after DHCP is finished to let the announce module and any other stack state machines to reach normal operation
							if(TickGet() - dwTimer < TICK_SECOND/2)
								return;
						}
						#endif
						Cmd_Read_Switch = 21;
						break;
						
		case	21	:	socket2 = UDPOpen(0x6FFF, NULL, 0x6FFF);  //open the socket 
			            
			            if(socket2 == 0xFF) //Invalid socket
			            {
				            break;
				        }
				        else{Cmd_Read_Switch = 0;}
				        
				        Led1=1;
				        Output_Enable = 1; 
				        
				        break;				        
		
		default		:	break;
	}
	
}
Esempio n. 28
0
/*********************************************************************
 * Function:        TFTP_RESULT TFTPIsPutReady(void)
 *
 * PreCondition:    TFTPOpenFile() is called with TFTP_FILE_MODE_WRITE
 *                  and TFTPIsFileOpened() returned with TRUE.
 *
 * Input:           None
 *
 * Output:          TFTP_OK if it is okay to write more data byte.
 *
 *                  TFTP_TIMEOUT if timeout occurred waiting for
 *                  ack from server
 *
 *                  TFTP_RETRY if all server did not send ack
 *                  on time and application needs to resend
 *                  last block.
 *
 *                  TFTP_ERROR if remote server returned ERROR.
 *                  Actual error code may be read by calling
 *                  TFTPGetError()
 *
 *                  TFTP_NOT_READY if still waiting...
 *
 * Side Effects:    None
 *
 * Overview:        Waits for ack from server.  If ack does not
 *                  arrive within specified timeout, it it instructs
 *                  application to retry last block by returning
 *                  TFTP_RETRY.
 *
 *                  If all attempts are exhausted, it returns with
 *                  TFTP_TIMEOUT.
 *
 * Note:            None
 ********************************************************************/
TFTP_RESULT TFTPIsPutReady(void)
{
    WORD_VAL opCode;
    WORD_VAL blockNumber;
    BOOL bTimeOut;

    // Check to see if timeout has occurred.
    bTimeOut = FALSE;
    if ( TickGetDiff(TickGet(), _tftpStartTick) >= TFTP_GET_TIMEOUT_VAL )
    {
        bTimeOut = TRUE;
        _tftpStartTick = TickGet();
    }

    switch(_tftpState)
    {
    case SM_TFTP_WAIT_FOR_ACK:
        // When timeout occurs in this state, application must retry.
        if ( bTimeOut )
        {
            if ( _tftpRetries++ > (TFTP_MAX_RETRIES-1) )
            {
                DEBUG(printf("TFTPIsPutReady(): Timeout.\n"));

                // Forget about all previous attempts.
                _tftpRetries = 1;

                return TFTP_TIMEOUT;
            }

            else
            {
                DEBUG(printf("TFTPIsPutReady(): Retry.\n"));
                return TFTP_RETRY;
            }
        }

        // Must wait for ACK from server before we transmit next block.
        if ( !UDPIsGetReady(_tftpSocket) )
            break;

        // Get opCode.
        UDPGet(&opCode.byte.MSB);
        UDPGet(&opCode.byte.LSB);

        // Get block number.
        UDPGet(&blockNumber.byte.MSB);
        UDPGet(&blockNumber.byte.LSB);

        // Discard everything else.
        UDPDiscard();

        // This must be ACK or else there is a problem.
        if ( opCode.Val == TFTP_OPCODE_ACK )
        {
            // Also the block number must match with what we are expecting.
            if ( MutExVar.group2._tftpBlockNumber.Val == blockNumber.Val )
            {
                // Mark that block we sent previously has been ack'ed.
                _tftpFlags.bits.bIsAcked = TRUE;

                // Since we have ack, forget about previous retry count.
                _tftpRetries = 1;

                // If this file is being closed, this must be last ack.
                // Declare it as closed.
                if ( _tftpFlags.bits.bIsClosing )
                {
                    _tftpFlags.bits.bIsClosed = TRUE;
                    return TFTP_OK;
                }

                // Or else, wait for put to become ready so that caller
                // can transfer more data blocks.
                _tftpState = SM_TFTP_WAIT;
            }

            else
            {
                DEBUG(printf("TFTPIsPutReady(): "\
                    "Unexpected block %d received - droping it...\n", \
                    blockNumber.Val));
                return TFTP_NOT_READY;
            }
        }

        else if ( opCode.Val == TFTP_OPCODE_ERROR )
        {
            // For error opCode, remember error code so that application
            // can read it later.
            _tftpError = blockNumber.Val;

            // Declare error.
            return TFTP_ERROR;
        }
        else
            break;


    case SM_TFTP_WAIT:
        // Wait for UDP is to be ready to transmit.
        if ( UDPIsPutReady(_tftpSocket) )
        {
            // Put next block of data.
            MutExVar.group2._tftpBlockNumber.Val++;
            UDPPut(0);
            UDPPut(TFTP_OPCODE_DATA);

            UDPPut(MutExVar.group2._tftpBlockNumber.byte.MSB);
            UDPPut(MutExVar.group2._tftpBlockNumber.byte.LSB);

            // Remember that this block is not yet flushed.
            _tftpFlags.bits.bIsFlushed = FALSE;

            // Remember that this block is not acknowledged.
            _tftpFlags.bits.bIsAcked = FALSE;

            // Now, TFTP module is ready to put more data.
            _tftpState = SM_TFTP_READY;

            return TFTP_OK;
        }
        break;

    case SM_TFTP_READY:
        // TFTP module is said to be ready only when underlying UDP
        // is ready to transmit.
        if ( UDPIsPutReady(_tftpSocket) )
            return TFTP_OK;
    }

    return TFTP_NOT_READY;
}
Esempio n. 29
0
/*****************************************************************************
  Function:
	void DHCPTask(void)

  Summary:
	Performs periodic DHCP tasks for all interfaces.

  Description:
	This function performs any periodic tasks requied by the DHCP module, 
	such as sending and receiving messages involved with obtaining and
	maintaining a lease.

  Precondition:
	None

  Parameters:
	None

  Returns:
	None
***************************************************************************/
void DHCPTask(void)
{
	BYTE i;
	
	for(i = 0; i < NETWORK_INTERFACES; i++)
	{
		LoadState(i);
		switch(DHCPClient.smState)
		{
			case SM_DHCP_DISABLED:
				// When the module is disabled, do absolutely nothing
				break;
			
			case SM_DHCP_GET_SOCKET:
				// Open a socket to send and receive broadcast messages on
				DHCPClient.hDHCPSocket = UDPOpen(DHCP_CLIENT_PORT, NULL, DHCP_SERVER_PORT);
				if(DHCPClient.hDHCPSocket == INVALID_UDP_SOCKET)
					break;
	
				DHCPClient.smState = SM_DHCP_SEND_DISCOVERY;
				// No break
	
			case SM_DHCP_SEND_DISCOVERY:
				// Assume default IP Lease time of 60 seconds.
				// This should be minimum possible to make sure that if the
				// server did not specify lease time, we try again after this 
				// minimum time.
				DHCPClient.dwLeaseTime = 60;
				DHCPClient.validValues.val = 0x00;
				DHCPClient.flags.bits.bIsBound = FALSE;	
				DHCPClient.flags.bits.bOfferReceived = FALSE;
	
				// No point in wasting time transmitting a discovery if we are 
				// unlinked.  No one will see it.  
				if(!MACIsLinked())
					break;
	
				// Ensure transmitter is ready to accept data
				if(UDPIsPutReady(DHCPClient.hDHCPSocket) < 300u)
					break;

				// Toggle the BOOTP Broadcast flag to ensure compatibility with 
				// bad DHCP servers that don't know how to handle broadcast 
				// responses.  This results in the next discovery attempt to be 
				// made using the opposite mode.
				DHCPClient.flags.bits.bUseUnicastMode ^= 1;
	
				// Ensure that we transmit to the broadcast IP and MAC addresses
				// The UDP Socket remembers who it was last talking to
				memset((void*)&UDPSocketInfo[DHCPClient.hDHCPSocket].remoteNode, 0xFF, sizeof(UDPSocketInfo[0].remoteNode));
	
				// Send the DHCP Discover broadcast
				_DHCPSend(DHCP_DISCOVER_MESSAGE, FALSE);
	
				// Start a timer and begin looking for a response
				DHCPClient.dwTimer = TickGet();
				DHCPClient.smState = SM_DHCP_GET_OFFER;
				break;
	
			case SM_DHCP_GET_OFFER:
				// Check to see if a packet has arrived
				if(UDPIsGetReady(DHCPClient.hDHCPSocket) < 250u)
				{
					// Go back and transmit a new discovery if we didn't get an offer after 2 seconds
					if(TickGet() - DHCPClient.dwTimer >= DHCP_TIMEOUT)
						DHCPClient.smState = SM_DHCP_SEND_DISCOVERY;
					break;
				}
	
				// Let the DHCP server module know that there is a DHCP server 
				// on this network
				DHCPClient.flags.bits.bDHCPServerDetected = TRUE;
	
				// Check to see if we received an offer
				if(_DHCPReceive() != DHCP_OFFER_MESSAGE)
					break;
	
				DHCPClient.smState = SM_DHCP_SEND_REQUEST;
				// No break
	
			case SM_DHCP_SEND_REQUEST:
				if(UDPIsPutReady(DHCPClient.hDHCPSocket) < 258u)
					break;

				// Ensure that we transmit to the broadcast IP and MAC addresses
				// The UDP Socket remembers who it was last talking to, so 
				// we must set this back to the broadcast address since the 
				// current socket values are the unicast addresses of the DHCP 
				// server.
				memset((void*)&UDPSocketInfo[DHCPClient.hDHCPSocket].remoteNode, 0xFF, sizeof(UDPSocketInfo[0].remoteNode));
	
				// Send the DHCP request message
				_DHCPSend(DHCP_REQUEST_MESSAGE, FALSE);
	
				// Start a timer and begin looking for a response
				DHCPClient.dwTimer = TickGet();
				DHCPClient.smState = SM_DHCP_GET_REQUEST_ACK;
				break;
	
			case SM_DHCP_GET_REQUEST_ACK:
				// Check to see if a packet has arrived
				if(UDPIsGetReady(DHCPClient.hDHCPSocket) < 250u)
				{
					// Go back and transmit a new discovery if we didn't get an ACK after 2 seconds
					if(TickGet() - DHCPClient.dwTimer >= DHCP_TIMEOUT)
						DHCPClient.smState = SM_DHCP_SEND_DISCOVERY;
					break;
				}
	
				// Check to see if we received an offer
				switch(_DHCPReceive())
				{
					case DHCP_ACK_MESSAGE:
						UDPClose(DHCPClient.hDHCPSocket);
						DHCPClient.hDHCPSocket = INVALID_UDP_SOCKET;
						DHCPClient.dwTimer = TickGet();
						DHCPClient.smState = SM_DHCP_BOUND;
						DHCPClient.flags.bits.bEvent = 1;
						DHCPClient.flags.bits.bIsBound = TRUE;	

						if(DHCPClient.validValues.bits.IPAddress)
							AppConfig.MyIPAddr = DHCPClient.tempIPAddress;
						if(DHCPClient.validValues.bits.Mask)
							AppConfig.MyMask = DHCPClient.tempMask;
						if(DHCPClient.validValues.bits.Gateway)
							AppConfig.MyGateway = DHCPClient.tempGateway;
						#if defined(STACK_USE_DNS)
							if(DHCPClient.validValues.bits.DNS)
								AppConfig.PrimaryDNSServer.Val = DHCPClient.tempDNS.Val;
							AppConfig.SecondaryDNSServer.Val = 0x00000000ul;
							if(DHCPClient.validValues.bits.DNS2)
								AppConfig.SecondaryDNSServer.Val = DHCPClient.tempDNS2.Val;
						#endif
						//if(DHCPClient.validValues.bits.HostName)
						//	memcpy(AppConfig.NetBIOSName, (void*)DHCPClient.tempHostName, sizeof(AppConfig.NetBIOSName));
	
						break;
	
					case DHCP_NAK_MESSAGE:
						DHCPClient.smState = SM_DHCP_SEND_DISCOVERY;
						break;
				}
				break;
	
			case SM_DHCP_BOUND:
				if(TickGet() - DHCPClient.dwTimer < TICK_SECOND)
					break;
	
				// Check to see if our lease is still valid, if so, decrement lease 
				// time
				if(DHCPClient.dwLeaseTime >= 2ul)
				{
					DHCPClient.dwTimer += TICK_SECOND;
					DHCPClient.dwLeaseTime--;
					break;
				}
	
				// Open a socket to send and receive DHCP messages on
				DHCPClient.hDHCPSocket = UDPOpen(DHCP_CLIENT_PORT, NULL, DHCP_SERVER_PORT);
				if(DHCPClient.hDHCPSocket == INVALID_UDP_SOCKET)
					break;
	
				DHCPClient.smState = SM_DHCP_SEND_RENEW;
				// No break
	
			case SM_DHCP_SEND_RENEW:
			case SM_DHCP_SEND_RENEW2:
			case SM_DHCP_SEND_RENEW3:
				if(UDPIsPutReady(DHCPClient.hDHCPSocket) < 258u)
					break;
	
				// Send the DHCP request message
				_DHCPSend(DHCP_REQUEST_MESSAGE, TRUE);
				DHCPClient.flags.bits.bOfferReceived = FALSE;
	
				// Start a timer and begin looking for a response
				DHCPClient.dwTimer = TickGet();
				DHCPClient.smState++;
				break;
	
			case SM_DHCP_GET_RENEW_ACK:
			case SM_DHCP_GET_RENEW_ACK2:
			case SM_DHCP_GET_RENEW_ACK3:
				// Check to see if a packet has arrived
				if(UDPIsGetReady(DHCPClient.hDHCPSocket) < 250u)
				{
					// Go back and transmit a new discovery if we didn't get an ACK after 2 seconds
					if(TickGet() - DHCPClient.dwTimer >=  DHCP_TIMEOUT)
					{
						if(++DHCPClient.smState > SM_DHCP_GET_RENEW_ACK3)
							DHCPClient.smState = SM_DHCP_SEND_DISCOVERY;
					}
					break;
				}
	
				// Check to see if we received an offer
				switch(_DHCPReceive())
				{
					case DHCP_ACK_MESSAGE:
						UDPClose(DHCPClient.hDHCPSocket);
						DHCPClient.hDHCPSocket = INVALID_UDP_SOCKET;
						DHCPClient.dwTimer = TickGet();
						DHCPClient.smState = SM_DHCP_BOUND;
						DHCPClient.flags.bits.bEvent = 1;
						break;
		
					case DHCP_NAK_MESSAGE:
						DHCPClient.smState = SM_DHCP_SEND_DISCOVERY;
						break;
				}
				break;
		}
	}
}
Esempio n. 30
0
/*********************************************************************
 * Function:        void DiscoveryTask(void)
 *
 * Summary:         Announce callback task.
 *
 * PreCondition:    Stack is initialized()
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Recurring task used to listen for Discovery
 *                  messages on the specified ANNOUNCE_PORT.  These
 *                  messages can be sent using the Microchip Device
 *                  Discoverer tool. If one is received, this
 *                  function will transmit a reply.
 *
 * Note:            A UDP socket must be available before this 
 *					function is called.  It is freed at the end of 
 *					the function.  MAX_UDP_SOCKETS may need to be 
 *					increased if other modules use UDP sockets.
 ********************************************************************/
void DiscoveryTask(void)
{
	static enum {
		DISCOVERY_HOME = 0,
		DISCOVERY_LISTEN,
		DISCOVERY_REQUEST_RECEIVED,
		DISCOVERY_DISABLED
	} DiscoverySM = DISCOVERY_HOME;

	static UDP_SOCKET	MySocket;
	BYTE 				i;
	
	switch(DiscoverySM)
	{
		case DISCOVERY_HOME:
			// Open a UDP socket for inbound and outbound transmission
			// Since we expect to only receive broadcast packets and 
			// only send unicast packets directly to the node we last 
			// received from, the remote NodeInfo parameter can be anything
			MySocket = UDPOpen(ANNOUNCE_PORT, NULL, ANNOUNCE_PORT);

			if(MySocket == INVALID_UDP_SOCKET)
				return;
			else
				DiscoverySM++;
			break;

		case DISCOVERY_LISTEN:
			// Do nothing if no data is waiting
			if(!UDPIsGetReady(MySocket))
				return;
			
			// See if this is a discovery query or reply
			UDPGet(&i);
			UDPDiscard();
			if(i != 'D')
				return;

			// We received a discovery request, reply when we can
			DiscoverySM++;

			// Change the destination to the unicast address of the last received packet
        	memcpy((void*)&UDPSocketInfo[MySocket].remoteNode, (const void*)&remoteNode, sizeof(remoteNode));
			
			// No break needed.  If we get down here, we are now ready for the DISCOVERY_REQUEST_RECEIVED state

		case DISCOVERY_REQUEST_RECEIVED:
			if(!UDPIsPutReady(MySocket))
				return;

			// Begin sending our MAC address in human readable form.
			// The MAC address theoretically could be obtained from the 
			// packet header when the computer receives our UDP packet, 
			// however, in practice, the OS will abstract away the useful
			// information and it would be difficult to obtain.  It also 
			// would be lost if this broadcast packet were forwarded by a
			// router to a different portion of the network (note that 
			// broadcasts are normally not forwarded by routers).
			UDPPutArray((BYTE*)AppConfig.NetBIOSName, sizeof(AppConfig.NetBIOSName)-1);
			UDPPut('\r');
			UDPPut('\n');
		
			// Convert the MAC address bytes to hex (text) and then send it
			i = 0;
			while(1)
			{
				UDPPut(btohexa_high(AppConfig.MyMACAddr.v[i]));
			    UDPPut(btohexa_low(AppConfig.MyMACAddr.v[i]));
			    if(++i == 6u)
			    	break;
			    UDPPut('-');
			}
			UDPPut('\r');
			UDPPut('\n');

			// Send the packet
			UDPFlush();

			// Listen for other discovery requests
			DiscoverySM = DISCOVERY_LISTEN;
			break;

		case DISCOVERY_DISABLED:
			break;
	}	

}