Exemple #1
0
/****************************************************************************
  Function:
     WORD UDPSendPacket(UDP_SOCKET hUDP, BYTE * rgbBuf, WORD cbBuff, IP_ADDR ipAddr, WORD port, unsigned int cSecTimeout)

  Description:
    This is the core UDP send API, it will adjust the socket to the remote address we want to send to
    and then blast the data out.

  Precondition:
    UDP stack has to be up an running

  Parameters:
    hUDP        - An opened UDP socket to use to send on

    rgbBuf      - pointer to an array of bytes to send
                        
    cbBuff      - number of bytes in the buffer to send

    ipAddr      - the remote ip address to write to

    port        - the remote port to write to.
                       
    cSecTimout  - The maximum number of seconds to wait for the arp or write to take
                    before just returning with the number of bytes actually written, which could be 0.

  Returns:
    The number of bytes actually written to the remote target

  Remarks:
    UDP does not guarantee success, this could just go out on the wire to deaf ears.
  ***************************************************************************/
static WORD UDPSendPacket(UDP_SOCKET hUDP, BYTE * rgbBuf, WORD cbBuff, IP_ADDR ipAddr, WORD port, unsigned int cSecTimeout)
{

    WORD cbReady = 0;
    WORD cbSent = 0;
	DWORD t = 0;
 	
    if(!UDPAdjustSocketToMe(hUDP, ipAddr, port, cSecTimeout))
    {
        return(0);
    }

    t = TickGet();
    while(cbSent < cbBuff) 
    {
        if((cbReady = UDPIsPutReady(hUDP)) > 0)
        {
			WORD cb = cbBuff - cbSent;

			cb = cb < cbReady ? cb : cbReady;
            cbSent += UDPPutArray(&rgbBuf[cbSent], cb);
            UDPFlush();
 
            t = TickGet();
        }
        else if((TickGet() - t) >= (cSecTimeout * TICK_SECOND))
        {
            break;
        }

        ChipKITPeriodicTasks();
    }

    return(cbSent);
}
Exemple #2
0
/***	int UdpClient::writeDatagram(const byte *rgbWrite, size_t cbWrite)
**
**
**	Synopsis:   
**      Writes the buffer out as a datagram and sends it to the instances remote endpoint
**
**	Parameters:
**      rgbWrite     A pointer to an array of bytes that composes the datagram
**
**      cbWrite     The number of bytes in the datagram.
**
**	Return Values:
**      The number of bytes actually written. 0 is returned if no bytes were written or an error occured.
**
**	Errors:
**
**  Notes:
**
**      Because Udp is a datagram protocol, this always transmits the buffer immediately
**      as a complete datagram.
**
*/
long int UdpClient::writeDatagram(const byte *rgbWrite, size_t cbWrite)
{
    int cbMax = 0;
    // isDNETcK::EndPointResolved will call periodic tasks
    if(isEndPointResolved(DNETcK::msImmediate))
    {
        cbMax = (int) ((unsigned int) UDPIsPutReady(_hUDP));

        if(cbMax >= cbWrite)
        {
            // write the datagram out and flush it
            cbMax = UDPPutArray(rgbWrite, cbWrite);
            UDPFlush();
            return(cbMax);
        }

        // our output buffer is not big enough
        else
        {
            return(-cbMax);
        }      
    }

    // endpoint not resolved
    else
    {
        return(0);
    }

    EthernetPeriodicTasks();
}
Exemple #3
0
/*****************************************************************************
  Function:
	static void DNSPutString(BYTE* String)

  Summary:
	Writes a string to the DNS socket.
	
  Description:
	This function writes a string to the DNS socket, ensuring that it is
	properly formatted.

  Precondition:
	UDP socket is obtained and ready for writing.

  Parameters:
	String - the string to write to the UDP socket.

  Returns:
  	None
  ***************************************************************************/
static void DNSPutString(BYTE* String)
{
	BYTE *RightPtr;
	BYTE i;
	BYTE Len;

	RightPtr = String;

	while(1)
	{
		do
		{
			i = *RightPtr++;
		} while((i != 0x00u) && (i != '.') && (i != '/') && (i != ',') && (i != '>'));
	
		// Put the length and data
		// Also, skip over the '.' in the input string
		Len = (BYTE)(RightPtr-String-1);
		UDPPut(Len);
		String += UDPPutArray(String, Len) + 1;

		if(i == 0x00u || i == '/' || i == ',' || i == '>')
			break;
	}
	
	// Put the string null terminator character (zero length label)
	UDPPut(0x00);
}
Exemple #4
0
/*****************************************************************************
  Function:
	static void DNSPutString(UDP_SOCKET s, const char* String)

  Summary:
	Writes a string to the DNS socket.
	
  Description:
	This function writes a string to the DNS socket, ensuring that it is
	properly formatted.

  Precondition:
	UDP socket is obtained and ready for writing.

  Parameters:
	String - the string to write to the UDP socket.

  Returns:
  	None
  ***************************************************************************/
static void DNSPutString(UDP_SOCKET s, const char* String)
{
	const char *RightPtr;
	uint8_t i;
	uint8_t Len;

	RightPtr = String;

	while(1)
	{
		do
		{
			i = *RightPtr++;
		} while((i != 0x00u) && (i != '.') && (i != '/') && (i != ',') && (i != '>'));
	
		// Put the length and data
		// Also, skip over the '.' in the input string
		Len = (uint8_t)(RightPtr-String-1);
		UDPPut(s, Len);
		String += UDPPutArray(s, (uint8_t*)String, Len) + 1;

		if(i == 0x00u || i == '/' || i == ',' || i == '>')
			break;
	}
	
	// Put the string null terminator character (zero length label)
	UDPPut(s, 0x00);
}
/****************************************************************************************************
  Function:
            void AnnounceIP(void)
    
  Summary:
    Transmits an Announce packet.
  Conditions:
    Stack is initialized()
  Return:
    None
  Side Effects:
    None
  Description:
    AnnounceIP opens a UDP socket and transmits a broadcast packet to port
    \30303. If a computer is on the same subnet and a utility is looking
    for packets on the UDP port, it will receive the broadcast. For this
    application, it is used to announce the change of this board's IP
    address. The messages can be viewed with the TCP/IP Discoverer
    software tool.
  Remarks:
    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 AnnounceIP(void)
{
	UDP_SOCKET	MySocket;
	BYTE 		i;

	if(!MACIsLinked())  // Check for link before blindly opening and transmitting (similar to DHCP case)
		return;

	// Open a UDP socket for outbound broadcast transmission
	//MySocket = UDPOpen(2860, NULL, ANNOUNCE_PORT);
	MySocket = UDPOpenEx(0,UDP_OPEN_SERVER,2860, ANNOUNCE_PORT);
            LED1_IO = 0;

	// Abort operation if no UDP sockets are available
	// If this ever happens, incrementing MAX_UDP_SOCKETS in 
	// StackTsk.h may help (at the expense of more global memory 
	// resources).
	if(MySocket == INVALID_UDP_SOCKET)
		return;
	
	// Make certain the socket can be written to
	while(!UDPIsPutReady(MySocket));
	
	// 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('-');
	}

	// Send some other human readable information.
	UDPPutROMString((ROM BYTE*)"\r\nDHCP/Power event occurred");

	// Send the packet
	UDPFlush();
	
	// Close the socket so it can be used by other modules
	UDPClose(MySocket);
}
Exemple #6
0
void EthernetTransmit(BYTE *data, WORD dataLen)
{
	// If a remote server socket exists and the local socket is allowing new data, send it.
	if (remoteServerSocket != INVALID_UDP_SOCKET) {
		if (UDPIsPutReady(remoteServerSocket) >= dataLen) {
			if (UDPPutArray(data, dataLen) < dataLen) {
				FATAL_ERROR();
			}
			UDPFlush();
		}
	}
}
/*****************************************************************************
  Function:
	void UDPPerformanceTask(void)

  Summary:
	Tests the transmit performance of the UDP module.

  Description:
	This function tests the transmit performance of the UDP module.  At boot,
	this module will transmit 1024 large UDP broadcast packets of 1024 bytes
	each.  Using a packet sniffer, one can determine how long this process 
	takes and calculate the transmit rate of the stack.  This function tests 
	true UDP performance in that it will open a socket, transmit one packet, 
	and close the socket for each loop.  After this initial transmission, the
	module can be re-enabled by holding button 3.
	
	This function is particularly useful after development to determine the
	impact of your application code on the stack's performance.  A before and
	after comparison will indicate if your application is unacceptably
	blocking the processor or taking too long to execute.

  Precondition:
	UDP is initialized.

  Parameters:
	None

  Returns:
	None
  ***************************************************************************/
void UDPPerformanceTask(void)
{
	UDP_SOCKET	MySocket;
	NODE_INFO	Remote;
	WORD		wTemp;
	static DWORD dwCounter = 1;

	if((BUTTON3_IO) && (dwCounter > 1024))
		return;

	// Suppress transmissions if we don't have an Ethernet link so our counter starts correctly at 0x00000001
	if(!MACIsLinked())
		return;
	
	// Set the socket's destination to be a broadcast over our IP 
	// subnet
	// Set the MAC destination to be a broadcast
	memset(&Remote, 0xFF, sizeof(Remote));
	
	// Open a UDP socket for outbound transmission
	MySocket = UDPOpen(0, &Remote, PERFORMANCE_PORT);
	
	// Abort operation if no UDP sockets are available
	// If this ever happens, incrementing MAX_UDP_SOCKETS in 
	// StackTsk.h may help (at the expense of more global memory 
	// resources).
	if(MySocket == INVALID_UDP_SOCKET)
		return;
	
	// Make certain the socket can be written to
	if(!UDPIsPutReady(MySocket))
	{
		UDPClose(MySocket);
		return;
	}
	
	// Put counter value into first 4 bytes of the packet
	UDPPutArray((BYTE*)&dwCounter, sizeof(dwCounter));
	dwCounter++;
	
	wTemp = UDPPutROMArray((ROM BYTE*)
			"The quick brown fox tried to jump over the yellow dog.  Unfortunately, the yellow dog stood up while the fox was in mid-jump.  As a result, the two collided.  Then, the dog, being the omnivore that it is, ate the quick brown fox.  This line is 256 bytes.\r\n"
			"The quick brown fox tried to jump over the yellow dog.  Unfortunately, the yellow dog stood up while the fox was in mid-jump.  As a result, the two collided.  Then, the dog, being the omnivore that it is, ate the quick brown fox.  This line is 256 bytes.\r\n"
			"The quick brown fox tried to jump over the yellow dog.  Unfortunately, the yellow dog stood up while the fox was in mid-jump.  As a result, the two collided.  Then, the dog, being the omnivore that it is, ate the quick brown fox.  This line is 256 bytes.\r\n"
			"The quick brown fox tried to jump over the yellow dog.  Unfortunately, the yellow dog stood up while the fox was in mid-jump.  As a result, the two collided.  Then, the dog, being the omnivore that it is, ate the quick brown fox.  This line is 252b. \r\n", 1020);

	// Send the packet
	UDPFlush();
	
	// Close the socket so it can be used by other modules
	UDPClose(MySocket);
}
Exemple #8
0
/// @cond debug
int cUDPWrite()
{
	//reads udp data and adds in ring buffer
	if ( UDPIsPutReady(udpSocket[callbackUdpSocket-1]) )
	{
		udpWord = UDPPutArray(udpByte,udpInt);
		UDPFlush();
		return 0;
	} else {
		udpWord = 0;
		return 1; //error
	}
}
ssize_t microchip_udp_write(UDP_SOCKET socket, const uint8_t* buf, size_t len, uint32_t addr, uint16_t port) {
    NODE_INFO remoteInfo;
    ssize_t size;
    uint32_t addrNetworkOrder;
#if NABTO_LOG_CHECK(NABTO_LOG_SEVERITY_TRACE)
    UDP_SOCKET_INFO* debug;
    uint32_t sourceIp;
#endif

    if (addr == 0 || port == 0) {
        return 0;
    }
    
    WRITE_U32(&addrNetworkOrder, addr);

    if (unabto_microchip_arp_resolve(addrNetworkOrder, &remoteInfo.MACAddr)) {
        remoteInfo.IPAddr.Val = addrNetworkOrder;
        memcpy((void*) &UDPSocketInfo[socket].remote.remoteNode, (void*) &remoteInfo, sizeof (NODE_INFO));
    } else {
        if (UDPSocketInfo[socket].remote.remoteNode.IPAddr.Val != addrNetworkOrder) {
            return 0;
        }
        // the arp resolve is not finished but the socket already knows
        // a mac address, lets just use it.
    }
    if (UDPIsPutReady(socket) >= len) {
#if NABTO_LOG_CHECK(NABTO_LOG_SEVERITY_TRACE)
        debug = &UDPSocketInfo[socket];
        READ_U32(sourceIp, &debug->remote.remoteNode.IPAddr.Val);
#endif

        UDPSocketInfo[socket].remotePort = port;
        size = (ssize_t) UDPPutArray((BYTE*) buf, len);
        UDPFlush();
        NABTO_LOG_TRACE(("UDP write length: %i, %" PRIu16 " -> " PRIip ":%" PRIu16, size, debug->localPort, MAKE_IP_PRINTABLE(sourceIp), debug->remotePort));

        NABTO_LOG_BUFFER(NABTO_LOG_SEVERITY_TRACE, ("UDP out datagram"), buf, len);

        return size;
    } else {
        NABTO_LOG_TRACE(("Socket was not put ready %i", socket));
    }

    return 0;
}
Exemple #10
0
/*****************************************************************************
  Function:
	static void DHCPReplyToDiscovery(BOOTP_HEADER *Header, int netIx)

  Summary:
	Replies to a DHCP Discover message.

  Description:
	This function replies to a DHCP Discover message by sending out a 
	DHCP Offer message.

  Precondition:
	None

  Parameters:
	Header - the BootP header this is in response to.
    netIx   - interface index

  Returns:
  	None
  ***************************************************************************/
static void DHCPReplyToDiscovery(BOOTP_HEADER *Header, 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);

	// 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));
	UDPPut(s, 0x00);				// Your (client) IP Address: 0.0.0.0 (none yet assigned)
	UDPPut(s, 0x00);				// Your (client) IP Address: 0.0.0.0 (none yet assigned)
	UDPPut(s, 0x00);				// Your (client) IP Address: 0.0.0.0 (none yet assigned)
	UDPPut(s, 0x00);				// Your (client) IP Address: 0.0.0.0 (none yet assigned)
	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 Offer
	UDPPut(s, DHCP_MESSAGE_TYPE);	
	UDPPut(s, 1);
	UDPPut(s, DHCP_OFFER_MESSAGE);

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

	// 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: 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);
}
Exemple #11
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();
}
/*****************************************************************************
  Function:
	void UDPPerformanceTask(NET_CONFIG* pConfig)

  Summary:
	Tests the transmit performance of the UDP module.

  Description:
	This function tests the transmit performance of the UDP module.  At boot,
	this module will transmit 1024 large UDP broadcast packets of 1024 bytes
	each.  Using a packet sniffer, one can determine how long this process 
	takes and calculate the transmit rate of the stack.  This function tests 
	true UDP performance in that it will open a socket, transmit one packet, 
	and close the socket for each loop.  After this initial transmission, the
	module can be re-enabled by holding button 3.
	
	This function is particularly useful after development to determine the
	impact of your application code on the stack's performance.  A before and
	after comparison will indicate if your application is unacceptably
	blocking the processor or taking too long to execute.

  Precondition:
	UDP is initialized.

  Parameters:
	pConfig - network to run on

  Returns:
	None
  ***************************************************************************/
void UDPPerformanceTask(NET_CONFIG* pConfig)
{
	UDP_SOCKET	MySocket;
	NODE_INFO	Remote;
	uint16_t		wTemp;
	static uint32_t dwCounter = 1;

	if((BUTTON3_IO) && (dwCounter > 1024u))
		return;

	// Suppress transmissions if we don't have an Ethernet link so our counter starts correctly at 0x00000001
	if(!MACIsLinked(_TCPIPStackNetToMac(pConfig)))
		return;
	
	#if defined(TCPIP_STACK_USE_DHCP_CLIENT) && defined(DELAY_UDP_PERFORMANCE_TEST)
	{
		static SYS_TICK dwTimer = 0;
		
		// Wait until DHCP module is finished
		if(!DHCPIsBound(pConfig))
		{
			dwTimer = SYS_TICK_Get();
			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(SYS_TICK_Get() - dwTimer < SYS_TICK_TicksPerSecondGet()/2)
			return;
	}
	#endif

	// Set the socket's destination to be a broadcast over our IP 
	// subnet
	// Set the MAC destination to be a broadcast
	memset(&Remote, 0xFF, sizeof(Remote));
	
	// Open a UDP socket for outbound transmission
	MySocket = UDPOpen((uint32_t)&Remote,UDP_OPEN_NODE_INFO,0,PERFORMANCE_PORT);
	
	// Abort operation if no UDP sockets are available
	// If this ever happens, incrementing UDP_MAX_SOCKETS in 
	// udp_config.h may help (at the expense of more global memory 
	// resources).
	if(MySocket == INVALID_UDP_SOCKET)
		return;
    UDPSocketSetNet(MySocket, pConfig);

	// Make certain the socket can be written to
	if(!UDPIsPutReady(MySocket))
	{
		UDPClose(MySocket);
		return;
	}
	
	// Put counter value into first 4 bytes of the packet
	UDPPutArray(MySocket, (uint8_t*)&dwCounter, sizeof(dwCounter));
	dwCounter++;
	
	wTemp = UDPPutArray(MySocket, (const uint8_t*)
			"The quick brown fox tried to jump over the yellow dog.  Unfortunately, the yellow dog stood up while the fox was in mid-jump.  As a result, the two collided.  Then, the dog, being the omnivore that it is, ate the quick brown fox.  This line is 256 bytes.\r\n"
			"The quick brown fox tried to jump over the yellow dog.  Unfortunately, the yellow dog stood up while the fox was in mid-jump.  As a result, the two collided.  Then, the dog, being the omnivore that it is, ate the quick brown fox.  This line is 256 bytes.\r\n"
			"The quick brown fox tried to jump over the yellow dog.  Unfortunately, the yellow dog stood up while the fox was in mid-jump.  As a result, the two collided.  Then, the dog, being the omnivore that it is, ate the quick brown fox.  This line is 256 bytes.\r\n"
			"The quick brown fox tried to jump over the yellow dog.  Unfortunately, the yellow dog stood up while the fox was in mid-jump.  As a result, the two collided.  Then, the dog, being the omnivore that it is, ate the quick brown fox.  This line is 252b. \r\n", 1020);

	// Send the packet
	UDPFlush(MySocket);
	
	// Close the socket so it can be used by other modules
	UDPClose(MySocket);
}
Exemple #13
0
/*****************************************************************************
  Function:
	int sendto(SOCKET s, const char* buf, int len, int flags, const struct sockaddr* to, int tolen)

  Summary:
	This function used to send the data for both connection oriented and connection-less
	sockets.

  Description:
	The sendto function is used to send outgoing data on a socket.
	The destination address is given by to and tolen. Both 
	Datagram and stream sockets are supported.

  Precondition:
	socket function should be called.

  Parameters:
	s - Socket descriptor returned from a previous call to socket.
	buf - application data buffer containing data to transmit.
	len - length of data in bytes.
	flags - message flags. Currently this field is not supported.
	to - Optional pointer to the the sockaddr structure containing the
		destination address.  If NULL, the currently bound remote port and IP 
		address are used as the destination.
	tolen - length of the sockaddr structure.

  Returns:
	On success, sendto returns number of bytes sent. In case of
	error returns SOCKET_ERROR

  Remarks:
	None.
  ***************************************************************************/
int sendto( SOCKET s, const char* buf, int len, int flags, const struct sockaddr* to, int tolen )
{
	struct BSDSocket *socket;
	int size = SOCKET_ERROR;
	NODE_INFO remoteInfo;
//	static DWORD startTick;		// NOTE: startTick really should be a per socket BSDSocket structure member since other BSD calls can interfere with the ARP cycles
	WORD wRemotePort;
	struct sockaddr_in local;

	if( s >= BSD_SOCKET_COUNT )
		return SOCKET_ERROR;

	socket = &BSDSocketArray[s];

	if(socket->bsdState == SKT_CLOSED)
		return SOCKET_ERROR;

	if(socket->SocketType == SOCK_DGRAM) //UDP
	{
		// Decide the destination IP address and port
		remoteInfo.IPAddr.Val = socket->remoteIP;
		wRemotePort = socket->remotePort;
		if(to)
		{
			if((unsigned int)tolen != sizeof(struct sockaddr_in))
				return SOCKET_ERROR;
			wRemotePort = ((struct sockaddr_in*)to)->sin_port;
			remoteInfo.IPAddr.Val = ((struct sockaddr_in*)to)->sin_addr.s_addr;
			
			// Implicitly bind the socket if it isn't already
			if(socket->bsdState == SKT_CREATED)
			{
				memset(&local, 0x00, sizeof(local));
				if(bind(s, (struct sockaddr*)&local, sizeof(local)) == SOCKET_ERROR)
					return SOCKET_ERROR;
			}
		}
		if(UDPIsOpened((UDP_SOCKET)s) != TRUE)
			return SOCKET_ERROR;
		
		if(remoteInfo.IPAddr.Val == IP_ADDR_ANY)
			remoteInfo.IPAddr.Val = 0xFFFFFFFFu;

#if 0
		// Set the remote IP and MAC address if it is different from what we already have stored in the UDP socket
		if(UDPSocketInfo[socket->SocketID].remoteNode.IPAddr.Val != remoteInfo.IPAddr.Val)
		{
			if(ARPIsResolved(&remoteInfo.IPAddr, &remoteInfo.MACAddr))
			{
				memcpy((void*)&UDPSocketInfo[socket->SocketID].remoteNode, (void*)&remoteInfo, sizeof(remoteInfo));
			}
			else
			{
				if(TickGet() - startTick > 1*TICK_SECOND)
				{
					ARPResolve(&remoteInfo.IPAddr);
					startTick = TickGet();
				}
				return SOCKET_ERROR;
			}
		}
#endif		
		// Select the UDP socket and see if we can write to it
		if(UDPIsPutReady(socket->SocketID))
		{
			// Set the proper remote port
			UDPSocketInfo[socket->SocketID].remotePort = wRemotePort;

			// Write data and send UDP datagram
			size = UDPPutArray((BYTE*)buf, len);
			UDPFlush();
			return size;
		}
	}
	else if(socket->SocketType == SOCK_STREAM) //TCP will only send to the already established socket.
	{
		if(socket->bsdState != SKT_EST)
			return SOCKET_ERROR;

		if(HandlePossibleTCPDisconnection(s))
			return SOCKET_ERROR;
			
		// Handle special case were 0 return value is okay
		if(len == 0)
			return 0;

		// Write data to the socket. If one or more bytes were written, then 
		// return this value.  Otherwise, fail and return SOCKET_ERROR.
		size = TCPPutArray(socket->SocketID, (BYTE*)buf, len);
		if(size)
			return size;
	}
	return SOCKET_ERROR;
}
Exemple #14
0
/*****************************************************************************
  Function:
	static void DHCPReplyToRequest(BOOTP_HEADER *Header, BOOL bAccept)

  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

  Returns:
  	None
  
  Internal:
	Needs to support more than one simultaneous lease in the future.
  ***************************************************************************/
static void DHCPReplyToRequest(BOOTP_HEADER *Header, BOOL bAccept, BOOL bRenew)
{
	BYTE i;
	INT8 indexOfPool = 255;
	IP_ADDR       ipAddr;
	// Set the correct socket to active and ensure that 
	// enough space is available to generate the DHCP response
	if(UDPIsPutReady(MySocket) < 300u)
		return;

	// Search through all remaining options and look for the Requested IP address field
	// Obtain options
	
	
	while(UDPIsGetReady(MySocket))
	{
		BYTE Option, Len;
		DWORD dw;
		MAC_ADDR tmp_MacAddr;
		
		// Get option type
		if(!UDPGet(&Option))
			break;
		if(Option == DHCP_END_OPTION)
			break;

		// Get option length
		UDPGet(&Len);
		if(bRenew)
		{
			if((Option == DHCP_PARAM_REQUEST_CLIENT_ID) && (Len == 7u))
			{
				// 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.
				UDPGet(&i);
				UDPGetArray((UINT8*)&tmp_MacAddr, 6);
				Len -= 7;
				indexOfPool = getIndexByMacaddr_DhcpPool(&tmp_MacAddr);//(&tmp_MacAddr,(IPV4_ADDR*)&Header->);
				if(-1 != indexOfPool)
				{
					if(GetIPAddrFromIndex_DhcpPool(indexOfPool).Val ==	Header->ClientIP.Val)
						postAssign_ToDHCPClient_FromPool(&tmp_MacAddr, &(Header->ClientIP));
					else
						bAccept = FALSE;
				}
				else
				{
					bAccept = FALSE;
				}
				
				break;
			}
		}
		else
		{
		//
			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((UINT8*)&dw, 4);
				Len -= 4;
				indexOfPool = postAssign_ToDHCPClient_FromPool(&(Header->ClientMAC),(IP_ADDR*)&dw);
				if( -1 == indexOfPool)
				{
					bAccept = FALSE;
				}
				break;
			}
		}

		

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

	// Begin putting the BOOTP Header and DHCP options
	UDPPut(BOOT_REPLY);			// Message Type: 2 (BOOTP Reply)
	// Reply with the same Hardware Type, Hardware Address Length, Hops, and Transaction ID fields
	UDPPutArray((BYTE*)&(Header->HardwareType), 7);
	UDPPut(0x00);				// Seconds Elapsed: 0 (Not used)
	UDPPut(0x00);				// Seconds Elapsed: 0 (Not used)
	UDPPutArray((BYTE*)&(Header->BootpFlags), sizeof(Header->BootpFlags));
	UDPPutArray((BYTE*)&(Header->ClientIP), sizeof(IP_ADDR));// Your (client) IP Address:
	//UDPPutArray((BYTE*)&DHCPNextLease, sizeof(IP_ADDR));	// Lease IP address to give out
	if(bAccept)		ipAddr = GetIPAddrFromIndex_DhcpPool(indexOfPool);
	else 			ipAddr.Val=0u;
	UDPPutArray((UINT8*)&ipAddr, sizeof(IP_ADDR));	// Lease IP address to give out
	UDPPut(0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPutArray((BYTE*)&(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(0x00);									// Boot filename: Null string (not used)
	UDPPut(0x63);				// Magic Cookie: 0x63538263
	UDPPut(0x82);				// Magic Cookie: 0x63538263
	UDPPut(0x53);				// Magic Cookie: 0x63538263
	UDPPut(0x63);				// Magic Cookie: 0x63538263
	
	// Options: DHCP lease ACKnowledge
	if(bAccept)
	{
		UDPPut(DHCP_OPTION_ACK_MESSAGE);	
		UDPPut(1);
		UDPPut(DHCP_ACK_MESSAGE);
	}
	else	// Send a NACK
	{
		UDPPut(DHCP_OPTION_ACK_MESSAGE);	
		UDPPut(1);
		UDPPut(DHCP_NAK_MESSAGE);
	}

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

	// Option: Server identifier
	UDPPut(DHCP_SERVER_IDENTIFIER);	
	UDPPut(sizeof(IP_ADDR));
	UDPPutArray((BYTE*)&AppConfig.MyIPAddr, sizeof(IP_ADDR));

	// Option: Subnet Mask
	UDPPut(DHCP_SUBNET_MASK);
	UDPPut(sizeof(IP_ADDR));
	UDPPutArray((BYTE*)&AppConfig.MyMask, sizeof(IP_ADDR));

	// Option: Router/Gateway address
	UDPPut(DHCP_ROUTER);		
	UDPPut(sizeof(IP_ADDR));
	UDPPutArray((BYTE*)&AppConfig.MyIPAddr, sizeof(IP_ADDR));

	// Option: DNS server address
	UDPPut(DHCP_DNS);
	UDPPut(sizeof(IP_ADDR));
	UDPPutArray((BYTE*)&AppConfig.MyIPAddr, sizeof(IP_ADDR));

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

	// Add zero padding to ensure compatibility with old BOOTP relays that discard small packets (<300 UDP octets)
	while(UDPTxCount < 300u)
		UDPPut(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*)&UDPSocketInfo[MySocket].remote.remoteNode, 0xFF, sizeof(NODE_INFO));

	// Transmit the packet
	UDPFlush();
}
Exemple #15
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;
   }
}
Exemple #16
0
/*****************************************************************************
  Function:
	BYTE* UDPPutString(BYTE *strData)

  Summary:
	Writes null-terminated string to the currently active socket.
	
  Description:
	This function writes a null-terminated string to the currently active 
	UDP socket, while incrementing the buffer length.  UDPIsPutReady should 
	be used before calling this function to specify the currently active
	socket.

  Precondition:
	UDPIsPutReady() was previously called to specify the current socket.

  Parameters:
	cData - Pointer to the string to be written to the socket.
	
  Returns:
  	A pointer to the byte following the last byte written.  Note that this
  	is different than the UDPPutArray functions.  If this pointer does not
  	dereference to a NULL byte, then the buffer became full and the input
  	data was truncated.
  ***************************************************************************/
BYTE* UDPPutString(BYTE *strData)
{
	return strData + UDPPutArray(strData, strlen((char*)strData));
}
Exemple #17
0
void ANNOUNCE_Send(void)
{
    UDP_SOCKET  announceSocket;
    int         netIx;
    uint16_t    dataLen;
    uint16_t    minimumDataLen;
    uint16_t    txLen;
    bool truncated;
    NET_CONFIG * pNetIf;
    ANNOUNCE_LIST_NODE *  node = (ANNOUNCE_LIST_NODE *)announceEvents.head;
    ANNOUNCE_FIELD_PAYLOAD payloadType;
    uint16_t terminatorLen = strlen ((const char *)announceFieldTerminator);

#if defined (TCPIP_STACK_USE_IPV6)
    IPV6_ADDR_STRUCT * addressPointer;
#endif

    while (node != NULL)
    {    
        pNetIf = (NET_CONFIG *)node->handle;

        netIx = TCPIP_STACK_NetIx (pNetIf);

        truncated = false;

        dataLen = ((terminatorLen + 1) * 4) + sizeof (IPV4_ADDR) + sizeof (MAC_ADDR);

        dataLen += strlen(TCPIP_HOSTS_CONFIGURATION[netIx].interface);
        dataLen += strlen((char *)pNetIf->NetBIOSName);
    
        minimumDataLen = dataLen + 1 + terminatorLen;
    
        if(!MACIsLinked(_TCPIPStackNetToMac(pNetIf)))  // Check for link before blindly opening and transmitting (similar to DHCP case)
        {
            return;
        }
    
        announceSocket = UDPOpenClient(IP_ADDRESS_TYPE_IPV4, ANNOUNCE_PORT, 0);
    
        if (announceSocket == INVALID_UDP_SOCKET)
        {
            return;
        }
    
        UDPSocketSetNet (announceSocket, pNetIf);
    
    #if defined (TCPIP_STACK_USE_IPV6)
        addressPointer = (IPV6_ADDR_STRUCT *)ipv6Config[netIx].listIpv6UnicastAddresses.head;
    
        while(addressPointer != NULL)
        {
            dataLen += sizeof (IPV6_ADDR) + 1 + terminatorLen;
            addressPointer = addressPointer->next;
        }
    
        addressPointer = (IPV6_ADDR_STRUCT *)ipv6Config[netIx].listIpv6MulticastAddresses.head;
    
        while(addressPointer != NULL)
        {
            dataLen += sizeof (IPV6_ADDR) + 1 + terminatorLen;
            addressPointer = addressPointer->next;
        }
    #endif
    
        if (dataLen > ANNOUNCE_MAX_PAYLOAD)
        {
            dataLen = ANNOUNCE_MAX_PAYLOAD;
        }
    
        if ((txLen = UDPIsTxPutReady(announceSocket, dataLen)) < dataLen)
        {
            truncated = true;
            if ((txLen = UDPIsTxPutReady(announceSocket, minimumDataLen)) < minimumDataLen)
            {
                UDPClose (announceSocket);
                return;
            }
        }
    
        // Put Mac Address
        payloadType = ANNOUNCE_FIELD_MAC_ADDR;
        UDPPut (announceSocket, payloadType);
        UDPPutArray(announceSocket, (const uint8_t *)&pNetIf->MyMACAddr, sizeof (MAC_ADDR));
        UDPPutArray (announceSocket, announceFieldTerminator, terminatorLen);

        if (truncated)
        {
            payloadType = ANNOUNCE_FIELD_TRUNCATED;
            UDPPut (announceSocket, payloadType);
            UDPPutArray (announceSocket, announceFieldTerminator, terminatorLen);
        }

        // Put Mac Type
        payloadType = ANNOUNCE_FIELD_MAC_TYPE;
        UDPPut (announceSocket, payloadType);
        UDPPutArray(announceSocket, (const uint8_t *)TCPIP_HOSTS_CONFIGURATION[netIx].interface, strlen ((const char *)TCPIP_HOSTS_CONFIGURATION[netIx].interface));
        UDPPutArray (announceSocket, announceFieldTerminator, terminatorLen);

        // Put Host Name
        payloadType = ANNOUNCE_FIELD_HOST_NAME;
        UDPPut (announceSocket, payloadType);
        UDPPutArray(announceSocket, (const uint8_t *)&pNetIf->NetBIOSName, strlen((char*)pNetIf->NetBIOSName));
        UDPPutArray (announceSocket, announceFieldTerminator, terminatorLen);

        // Put IPv4 Address
        payloadType = ANNOUNCE_FIELD_IPV4_ADDRESS;
        UDPPut (announceSocket, payloadType);
        UDPPutArray(announceSocket, (const uint8_t *)&pNetIf->MyIPAddr, sizeof (IP_ADDR));
        UDPPutArray (announceSocket, announceFieldTerminator, terminatorLen);
    
#if defined (TCPIP_STACK_USE_IPV6)
    
        // Put IPv6 unicast addresses
        minimumDataLen = sizeof (IPV6_ADDR) + 1 + terminatorLen;
    
        addressPointer = (IPV6_ADDR_STRUCT *)ipv6Config[netIx].listIpv6UnicastAddresses.head;
    
        payloadType = ANNOUNCE_FIELD_IPV6_UNICAST;

        while(addressPointer != NULL && (UDPIsTxPutReady(announceSocket, minimumDataLen) >= minimumDataLen))
        {
            UDPPut (announceSocket, payloadType);
            UDPPutArray(announceSocket, (const uint8_t *)&addressPointer->address, sizeof (IPV6_ADDR));
            UDPPutArray (announceSocket, announceFieldTerminator, terminatorLen);
            addressPointer = addressPointer->next;
        }
    
        // Put IPv6 multicast listeners    
        addressPointer = (IPV6_ADDR_STRUCT *)ipv6Config[netIx].listIpv6MulticastAddresses.head;
    
        payloadType = ANNOUNCE_FIELD_IPV6_MULTICAST;

        while(addressPointer != NULL && (UDPIsTxPutReady(announceSocket, minimumDataLen) >= minimumDataLen))
        {
            UDPPut (announceSocket, payloadType);
            UDPPutArray(announceSocket, (const uint8_t *)&addressPointer->address, sizeof (IPV6_ADDR));
            UDPPutArray (announceSocket, announceFieldTerminator, terminatorLen);
            addressPointer = addressPointer->next;
        }
#endif
    
        UDPFlush (announceSocket);
    
        UDPClose (announceSocket);

        SingleListRemoveHead(&announceEvents);

        TCPIP_HEAP_Free (announceMemH, node);

        node = (ANNOUNCE_LIST_NODE *)announceEvents.head;

        if (node == NULL)
        {
            announceEventPending = false;
        }
    }
}
Exemple #18
0
/*****************************************************************************
  Function:
	static void DHCPReplyToRequest(BOOTP_HEADER *Header, BOOL bAccept)

  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

  Returns:
  	None
  
  Internal:
	Needs to support more than one simultaneous lease in the future.
  ***************************************************************************/
static void DHCPReplyToRequest(BOOTP_HEADER *Header, BOOL bAccept)
{
	BYTE i;

	// Set the correct socket to active and ensure that 
	// enough space is available to generate the DHCP response
	if(UDPIsPutReady(MySocket) < 300u)
		return;

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

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

		// Get option length
		UDPGet(&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((BYTE*)&dw, 4);
			Len -= 4;
			if(dw != DHCPNextLease.Val)
			{
				bAccept = FALSE;
			}
			break;
		}

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


#if defined(STACK_USE_DHCP_CLIENT)
	// Someone is using our DHCP server, start using a static 
	// IP address and update the bind count so it displays on 
	// the LCD
	AppConfig.Flags.bInConfigMode = FALSE;
	DHCPBindCount++;
#endif

	// Begin putting the BOOTP Header and DHCP options
	UDPPut(BOOT_REPLY);			// Message Type: 2 (BOOTP Reply)
	// Reply with the same Hardware Type, Hardware Address Length, Hops, and Transaction ID fields
	UDPPutArray((BYTE*)&(Header->HardwareType), 7);
	UDPPut(0x00);				// Seconds Elapsed: 0 (Not used)
	UDPPut(0x00);				// Seconds Elapsed: 0 (Not used)
	UDPPutArray((BYTE*)&(Header->BootpFlags), sizeof(Header->BootpFlags));
	UDPPutArray((BYTE*)&(Header->ClientIP), sizeof(IP_ADDR));// Your (client) IP Address:
	UDPPutArray((BYTE*)&DHCPNextLease, sizeof(IP_ADDR));	// Lease IP address to give out
	UDPPut(0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPutArray((BYTE*)&(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(0x00);									// Boot filename: Null string (not used)
	UDPPut(0x63);				// Magic Cookie: 0x63538263
	UDPPut(0x82);				// Magic Cookie: 0x63538263
	UDPPut(0x53);				// Magic Cookie: 0x63538263
	UDPPut(0x63);				// Magic Cookie: 0x63538263
	
	// Options: DHCP lease ACKnowledge
	if(bAccept)
	{
		UDPPut(DHCP_OPTION_ACK_MESSAGE);	
		UDPPut(1);
		UDPPut(DHCP_ACK_MESSAGE);
	}
	else	// Send a NACK
	{
		UDPPut(DHCP_OPTION_ACK_MESSAGE);	
		UDPPut(1);
		UDPPut(DHCP_NAK_MESSAGE);
	}

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

	// Option: Server identifier
	UDPPut(DHCP_SERVER_IDENTIFIER);	
	UDPPut(sizeof(IP_ADDR));
	UDPPutArray((BYTE*)&AppConfig.MyIPAddr, sizeof(IP_ADDR));

	// Option: Subnet Mask
	UDPPut(DHCP_SUBNET_MASK);
	UDPPut(sizeof(IP_ADDR));
	UDPPutArray((BYTE*)&AppConfig.MyMask, sizeof(IP_ADDR));

	// Option: Router/Gateway address
	UDPPut(DHCP_ROUTER);		
	UDPPut(sizeof(IP_ADDR));
	UDPPutArray((BYTE*)&AppConfig.MyIPAddr, sizeof(IP_ADDR));

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

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

	// Transmit the packet
	UDPFlush();
}
Exemple #19
0
/*****************************************************************************
  Function:
	static void DHCPReplyToDiscovery(BOOTP_HEADER *Header)

  Summary:
	Replies to a DHCP Discover message.

  Description:
	This function replies to a DHCP Discover message by sending out a 
	DHCP Offer message.

  Precondition:
	None

  Parameters:
	Header - the BootP header this is in response to.

  Returns:
  	None
  ***************************************************************************/
static void DHCPReplyToDiscovery(BOOTP_HEADER *Header)
{
	BYTE i;

	// Set the correct socket to active and ensure that 
	// enough space is available to generate the DHCP response
	if(UDPIsPutReady(MySocket) < 300u)
		return;

	// Begin putting the BOOTP Header and DHCP options
	UDPPut(BOOT_REPLY);			// Message Type: 2 (BOOTP Reply)
	// Reply with the same Hardware Type, Hardware Address Length, Hops, and Transaction ID fields
	UDPPutArray((BYTE*)&(Header->HardwareType), 7);
	UDPPut(0x00);				// Seconds Elapsed: 0 (Not used)
	UDPPut(0x00);				// Seconds Elapsed: 0 (Not used)
	UDPPutArray((BYTE*)&(Header->BootpFlags), sizeof(Header->BootpFlags));
	UDPPut(0x00);				// Your (client) IP Address: 0.0.0.0 (none yet assigned)
	UDPPut(0x00);				// Your (client) IP Address: 0.0.0.0 (none yet assigned)
	UDPPut(0x00);				// Your (client) IP Address: 0.0.0.0 (none yet assigned)
	UDPPut(0x00);				// Your (client) IP Address: 0.0.0.0 (none yet assigned)
	UDPPutArray((BYTE*)&DHCPNextLease, sizeof(IP_ADDR));	// Lease IP address to give out
	UDPPut(0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPutArray((BYTE*)&(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(0x00);									// Boot filename: Null string (not used)
	UDPPut(0x63);				// Magic Cookie: 0x63538263
	UDPPut(0x82);				// Magic Cookie: 0x63538263
	UDPPut(0x53);				// Magic Cookie: 0x63538263
	UDPPut(0x63);				// Magic Cookie: 0x63538263
	
	// Options: DHCP Offer
	UDPPut(DHCP_MESSAGE_TYPE);	
	UDPPut(1);
	UDPPut(DHCP_OFFER_MESSAGE);

	// Option: Subnet Mask
	UDPPut(DHCP_SUBNET_MASK);
	UDPPut(sizeof(IP_ADDR));
	UDPPutArray((BYTE*)&AppConfig.MyMask, sizeof(IP_ADDR));

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

	// Option: Server identifier
	UDPPut(DHCP_SERVER_IDENTIFIER);	
	UDPPut(sizeof(IP_ADDR));
	UDPPutArray((BYTE*)&AppConfig.MyIPAddr, sizeof(IP_ADDR));

	// Option: Router/Gateway address
	UDPPut(DHCP_ROUTER);		
	UDPPut(sizeof(IP_ADDR));
	UDPPutArray((BYTE*)&AppConfig.MyIPAddr, sizeof(IP_ADDR));

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

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

	// Transmit the packet
	UDPFlush();
}
Exemple #20
0
/*****************************************************************************
  Function:
	int sendto(SOCKET s, const char* buf, int len, int flags, const struct sockaddr* to, int tolen)

  Summary:
	This function used to send the data for both connection oriented and connection-less
	sockets.

  Description:
	The sendto function is used to send outgoing data on a socket.
	The destination address is given by to and tolen. Both
	Datagram and stream sockets are supported.

  Precondition:
	socket function should be called.

  Parameters:
	s - Socket descriptor returned from a previous call to socket.
	buf - application data buffer containing data to transmit.
	len - length of data in bytes.
	flags - message flags. Currently this field is not supported.
	to - Optional pointer to the the sockaddr structure containing the
		destination address.  If NULL, the currently bound remote port and IP
		address are used as the destination.
	tolen - length of the sockaddr structure.

  Returns:
	On success, sendto returns number of bytes sent. In case of
	error returns SOCKET_ERROR (and errno set accordingly).

  Remarks:
	None.
  ***************************************************************************/
int sendto( SOCKET s, const char* buf, int len, int flags, const struct sockaddr* to, int tolen )
{
    struct BSDSocket *socket;
    UDP_SOCKET_DCPT*  udpSkt;
    int size = SOCKET_ERROR;
    NODE_INFO remoteInfo;
    uint16_t wRemotePort;
    struct sockaddr_in local;

    if( s >= BSD_SOCKET_COUNT )
    {
        errno = EBADF;
        return SOCKET_ERROR;
    }

    socket = &BSDSocketArray[s];

    if(socket->bsdState == SKT_CLOSED)
    {
        errno = EBADF;
        return SOCKET_ERROR;
    }

    if(socket->SocketType == SOCK_DGRAM) //UDP
    {
        // Decide the destination IP address and port
        remoteInfo.IPAddr.Val = socket->remoteIP;
        wRemotePort = socket->remotePort;
        if(to)
        {
            if((unsigned int)tolen != sizeof(struct sockaddr_in))
            {
                errno = EFAULT;
                return SOCKET_ERROR;
            }
            wRemotePort = ((struct sockaddr_in*)to)->sin_port;
            remoteInfo.IPAddr.Val = ((struct sockaddr_in*)to)->sin_addr.s_addr;

            // Implicitly bind the socket if it isn't already
            if(socket->bsdState == SKT_CREATED)
            {
                memset(&local, 0x00, sizeof(local));
                if(bind(s, (struct sockaddr*)&local, sizeof(local)) == SOCKET_ERROR)
                    return SOCKET_ERROR;
            }
        }

        if(remoteInfo.IPAddr.Val == IP_ADDR_ANY)
            remoteInfo.IPAddr.Val = 0xFFFFFFFFu;

        // Set the remote IP and MAC address if it is different from what we already have stored in the UDP socket
        udpSkt = UDPSocketDcpt + socket->SocketID;
        if(TCPIP_IPV4_GetDestAddress(udpSkt->pTxPkt).Val != remoteInfo.IPAddr.Val)
        {
            TCPIP_IPV4_SetDestAddress(udpSkt->pTxPkt, remoteInfo.IPAddr.Val);
            if(!ARPIsResolved(UDPSocketGetNet(socket->SocketID), &remoteInfo.IPAddr, &((IPV4_PACKET*)udpSkt->pTxPkt)->remoteMACAddr))
            {
                errno = EINPROGRESS;
                return SOCKET_ERROR;
            }
        }
        // Select the UDP socket and see if we can write to it
        if(UDPIsTxPutReady(socket->SocketID, len))
        {
            // Set the proper remote port
            udpSkt->remotePort = wRemotePort;

            // Write data and send UDP datagram
            size = UDPPutArray(socket->SocketID, (uint8_t*)buf, len);
            UDPFlush(socket->SocketID);
            return size;
        }
    }
    else if(socket->SocketType == SOCK_STREAM) //TCP will only send to the already established socket.
    {
        if(socket->bsdState != SKT_EST)
        {
            errno = ENOTCONN;
            return SOCKET_ERROR;
        }

        if(HandlePossibleTCPDisconnection(s))
        {
            errno = ECONNRESET;
            return SOCKET_ERROR;
        }

        // Handle special case were 0 return value is okay
        if(len == 0)
            return 0;

        // Write data to the socket. If one or more bytes were written, then
        // return this value.  Otherwise, fail and return SOCKET_ERROR.
        size = TCPPutArray(socket->SocketID, (uint8_t*)buf, len);
        if(size)
            return size;
    }
    errno = EWOULDBLOCK;
    return SOCKET_ERROR;
}
Exemple #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);
}
Exemple #22
0
/**
 * Must be called every couple of ms.
 */
void evtTask(void) {
    static TICK8 tEvt = 0;
    static BYTE heartbeat = 20;

    //Buffer
    char buf[64];
    BYTE buf2Tx;


    /////////////////////////////////////////////////
    //Events
    switch(smEvt) {
    //UDP Event port has not been initialized yet, still waiting for MAC and IP address of remote host
    case SM_EVT_INIT:
        //Is there any data waiting for us on the "UDP Event port"?
        //Because of the design of the Modtronix TCP/IP stack we have to consume all data sent to us
        //as soon as we detect it. Store all data to a buffer as soon as it is detected
        if (UDPIsGetReady(udpSocketEvt)) {
            UDPGetArray((BYTE *)buf, 2);    //Read first 2 bytes from UDP message, indicates what event ports are active. Bit0=UDP Event Port
            UDPDiscard();           //Not using receive, so discart msg
            if (hextob( (char *)buf, &activeEventPorts) == 0) {
                activeEventPorts = 0;     //If error, disable all event ports
            }

            smEvt = SM_EVT_INIT_MSG;
        }
        break;
    case SM_EVT_INIT_MSG:
        //UDP Event port is active
        if ( ((activeEventPorts & EVT_PORT_UDP)!=0) && UDPIsPutReady(udpSocketEvt) ) {
            strcpypgm2ram(buf, (ROM char*)"l40=1;");
            UDPPutArray((BYTE *)buf, strlen(buf));

            // Now transmit it.
            UDPFlush();
            smEvt = SM_EVT_IDLE;
        }
        break;
    case SM_EVT_IDLE:
        buf2Tx = 0;
        
        //Is there any data waiting for us on the "UDP Event port"?
        //Because of the design of the Modtronix TCP/IP stack we have to consume all data sent to us
        //as soon as we detect it. Store all data to a buffer as soon as it is detected
        if (UDPIsGetReady(udpSocketEvt)) {
            UDPGetArray((BYTE *)buf, 2);    //Read first 2 bytes from UDP message, indicates what event ports are active. Bit0=UDP Event Port
            UDPDiscard();           //Not using receive, so discart msg
            if (hextob( (char *)buf, &activeEventPorts) == 0) {
                activeEventPorts = 0;     //If error, disable all event ports
            }
            break;          //Have to break, so stack task can be called, and UDPDiscart is executed
        }

        //Enter every 50ms
        if ( TickGetDiff8bit(tEvt) >= ((TICK8)TICKS_PER_SECOND / (TICK8)20) )
        {
            tEvt = TickGet8bit();

            //Every second
            if (--heartbeat == 0) {
                heartbeat = 20;
                //UDP Event port is active
                if ( ((activeEventPorts & EVT_PORT_UDP)!=0) && UDPIsPutReady(udpSocketEvt) ) {
                    strcpypgm2ram(buf, (ROM char*)"l40=2;");
                    UDPPutArray((BYTE *)buf, strlen(buf));
                    buf2Tx |= EVT_PORT_UDP;     //Indicate that data was added to UDP event port, and it must be TXed
                }
            }

            //Check LCD display every 50ms
            buf2Tx |= chkLCD();

            //Check Expansion Board every 50ms
            buf2Tx |= chkXboard();
        }

        //Was anything added to UDP event port
        if (buf2Tx & EVT_PORT_UDP) {
            UDPFlush(); //Transmit contents of UDP buffer
        }
        break;
    }
}
Exemple #23
0
/*****************************************************************************
  Function:
    uint8_t* UDPPutString(uint8_t *strData)

  Summary:
    Writes null-terminated string to the currently active socket.

  Description:
    This function writes a null-terminated string to the currently active
    UDP socket, while incrementing the buffer length.  UDPIsPutReady should
    be used before calling this function to specify the currently active
    socket.

  Precondition:
    UDPIsPutReady() was previously called to specify the current socket.

  Parameters:
    cData - Pointer to the string to be written to the socket.

  Returns:
    A pointer to the byte following the last byte written.  Note that this
    is different than the UDPPutArray functions.  If this pointer does not
    dereference to a NULL byte, then the buffer became full and the input
    data was truncated.
  ***************************************************************************/
uint8_t* UDPPutString(uint8_t *strData)
{
    return strData + UDPPutArray(strData, strlen((char*)strData));
}
/*****************************************************************************
  Function:
	int send( SOCKET s, const char* buf, int len, int flags )
	
  Summary:
	The send function is used to send outgoing data on an already
    connected socket.

  Description:
	The send function is used to send outgoing data on an already
    connected socket. This function is used to send a reliable,
    ordered stream of data bytes on a socket of type SOCK_STREAM
    but can also be used to send datagrams on a socket of type SOCK_DGRAM.

  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 buffer containing data to transmit.
    len - length of data in bytes.
    flags - message flags. Currently this field is not supported.
  
  Returns:
	On success, send returns number of bytes sent. In case of
    error, returns SOCKET_ERROR. a zero indicates no data send.

  Remarks:
	None.
  ***************************************************************************/
int send( SOCKET s, const char* buf, int len, int flags )
{
    struct BSDSocket *socket;
    WORD size;
    NODE_INFO remoteInfo;
    static DWORD startTick;

    if( s >= BSD_SOCKET_COUNT )
        return SOCKET_ERROR;

    socket = &BSDSocketArray[s];

    if( socket->bsdState < SKT_BOUND )
        return SOCKET_ERROR;

    if(!TCPIsConnected(socket->SocketID))
        return SOCKET_ERROR; //Indicates the socket is disconnected.
      
    if(socket->SocketType == SOCK_STREAM) //TCP
    {
        // Make certain the socket can be written to
        if(TCPIsPutReady(socket->SocketID) > 0)
        {
            return TCPPutArray(socket->SocketID, (BYTE*)buf, len);
        }
        else
        {
            return SOCKET_ERROR;
        }
    }
    else if(socket->SocketType == SOCK_DGRAM) //UDP
    {
        if((socket->bsdState >= SKT_READY) && (socket->bsdState != SKT_EST))//making sure that connect function is called
        {
            if(socket->bsdState != SKT_ARP_VERIFY)
            {
                remoteInfo.IPAddr.Val = socket->remoteIP;
                ARPResolve(&remoteInfo.IPAddr);
                startTick = TickGet();
                socket->bsdState = SKT_ARP_VERIFY;
            }
            else if(socket->bsdState == SKT_ARP_VERIFY)
            {
                // Wait for the MAC address to finish being obtained
                remoteInfo.IPAddr.Val = socket->remoteIP;
                if(!ARPIsResolved(&remoteInfo.IPAddr, &remoteInfo.MACAddr))
                {
                    // Time out if too much time is spent in this state
    			    if(TickGet()- startTick > 1*TICK_SECOND)
    			    {
                        // Retransmit ARP request
                        socket->bsdState = SKT_ARP_RESOLVE;
    			    }
                 }
                 socket->SocketID = UDPOpen(socket->localPort, &remoteInfo, socket->remotePort);
                 socket->bsdState = SKT_EST;
            } 
        }
        
        if(socket->bsdState == SKT_EST)
        {
            if(UDPIsPutReady(socket->SocketID) > 0)
            {
                size = UDPPutArray((BYTE*)buf, len);
                UDPFlush();
                return size;
            }
        }
        else
        {
            return SOCKET_ERROR;
        }
    }
    return SOCKET_ERROR;
}
Exemple #25
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;
	}	

}
Exemple #26
0
/*****************************************************************************
  Function:
	static void _DHCPSend(BYTE messageType, BOOL bRenewing)

  Description:
	Sends a DHCP message.

  Precondition:
	UDP is ready to write a DHCP packet.

  Parameters:
	messageType - One of the DHCP_TYPE constants
	bRenewing - Whether or not this is a renewal request

  Returns:
  	None
  ***************************************************************************/
static void _DHCPSend(BYTE messageType, BOOL bRenewing)
{
    BYTE i;
	IP_ADDR	MyIP;


    UDPPut(BOOT_REQUEST);                       // op
    UDPPut(BOOT_HW_TYPE);                       // htype
    UDPPut(BOOT_LEN_OF_HW_TYPE);                // hlen
    UDPPut(0);                                  // hops
    UDPPut(0x12);                               // xid[0]
    UDPPut(0x23);                               // xid[1]
    UDPPut(0x34);                               // xid[2]
    UDPPut(0x56);                               // xid[3]
    UDPPut(0);                                  // secs[0]
    UDPPut(0);                                  // secs[1]
    UDPPut(0x80);                               // flags[0] with BF set
    UDPPut(0);                                  // flags[1]

    // If this is DHCP REQUEST message, use previously allocated IP address.
    if((messageType == DHCP_REQUEST_MESSAGE) && bRenewing)
    {
		UDPPutArray((BYTE*)&tempIPAddress, sizeof(tempIPAddress));
    }
    else
    {
        UDPPut(0x00);
        UDPPut(0x00);
        UDPPut(0x00);
        UDPPut(0x00);
    }

    // Set yiaddr, siaddr, giaddr as zeros,
    for ( i = 0; i < 12u; i++ )
        UDPPut(0x00);

    // Load chaddr - Client hardware address.
	UDPPutArray((BYTE*)&AppConfig.MyMACAddr, sizeof(AppConfig.MyMACAddr));

    // Set chaddr[6..15], sname and file as zeros.
    for ( i = 0; i < 202u; i++ )
        UDPPut(0);

    // Load magic cookie as per RFC 1533.
    UDPPut(99);
    UDPPut(130);
    UDPPut(83);
    UDPPut(99);

    // Load message type.
    UDPPut(DHCP_MESSAGE_TYPE);
    UDPPut(DHCP_MESSAGE_TYPE_LEN);
    UDPPut(messageType);

	if(messageType == DHCP_DISCOVER_MESSAGE)
	{
		// Reset offered flag so we know to act upon the next valid offer
		DHCPFlags.bits.bOfferReceived = FALSE;
	}


    if((messageType == DHCP_REQUEST_MESSAGE) && !bRenewing)
    {
         // DHCP REQUEST message must include server identifier the first time
         // to identify the server we are talking to.
         // _DHCPReceive() would populate "serverID" when it
         // receives DHCP OFFER message. We will simply use that
         // when we are replying to server.
         // If this is a renwal request, we must not include server id.
         UDPPut(DHCP_SERVER_IDENTIFIER);
         UDPPut(DHCP_SERVER_IDENTIFIER_LEN);
         UDPPut(DHCPServerID.v[3]);
         UDPPut(DHCPServerID.v[2]);
         UDPPut(DHCPServerID.v[1]);
         UDPPut(DHCPServerID.v[0]);
     }

    // Load our interested parameters
    // This is hardcoded list.  If any new parameters are desired,
    // new lines must be added here.
    UDPPut(DHCP_PARAM_REQUEST_LIST);
    UDPPut(DHCP_PARAM_REQUEST_LIST_LEN);
    UDPPut(DHCP_SUBNET_MASK);
    UDPPut(DHCP_ROUTER);
	UDPPut(DHCP_DNS);
	UDPPut(DHCP_HOST_NAME);

     // Add requested IP address to DHCP Request Message
    if( ((messageType == DHCP_REQUEST_MESSAGE) && !bRenewing) || 
    	((messageType == DHCP_DISCOVER_MESSAGE) && tempIPAddress.Val))
    {
        UDPPut(DHCP_PARAM_REQUEST_IP_ADDRESS);
        UDPPut(DHCP_PARAM_REQUEST_IP_ADDRESS_LEN);
		UDPPutArray((BYTE*)&tempIPAddress, DHCP_PARAM_REQUEST_IP_ADDRESS_LEN);
    }

    // Add any new paramter request here.

    // End of Options.
    UDPPut(DHCP_END_OPTION);

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

	// Make sure we advirtise a 0.0.0.0 IP address so all DHCP servers will respond.  If we have a static IP outside the DHCP server's scope, it may simply ignore discover messages.
	MyIP.Val = AppConfig.MyIPAddr.Val;
	if(!bRenewing)
		AppConfig.MyIPAddr.Val = 0x00000000;
    UDPFlush();
	AppConfig.MyIPAddr.Val = MyIP.Val;
	
}
/*****************************************************************************
  Function:
	int sendto(SOCKET s, const char* buf, int len, int flags, const struct sockaddr* to, int tolen)

  Summary:
	This function used to send the data for both connection oriented and connection-less
	sockets.

  Description:
	The sendto function is used to send outgoing data on a socket.
    The destination address is given by to and tolen. Both 
    Datagram and stream sockets are supported.

  Precondition:
	socket function should be called.

  Parameters:
	s - Socket descriptor returned from a previous call to socket.
    buf - application data buffer containing data to transmit.
    len - length of data in bytes.
    flags - message flags. Currently this field is not supported.
    to - pointer to the the sockaddr structure containing the
    destination address.
    tolen - length of the sockaddr structure.
  
  Returns:
	On success, sendto returns number of bytes sent. In case of
    error returns SOCKET_ERROR

  Remarks:
	None.
  ***************************************************************************/
int sendto( SOCKET s, const char* buf, int len, int flags, const struct sockaddr* to, int tolen )
{
    struct BSDSocket *socket;
    struct sockaddr_in *addr;
    int size=0;
    NODE_INFO remoteInfo;
    static DWORD startTick;

    socket = &BSDSocketArray[s];
    addr = (struct sockaddr_in *)to;
    socket->remotePort = addr->sin_port;
    socket->remoteIP = addr->sin_addr.s_addr;
    
    if(socket->SocketType == SOCK_DGRAM) //UDP
    {
        if(socket->bsdState != SKT_EST)
        {
            if((addr == NULL) || (addr->sin_addr.s_addr == IP_ADDR_ANY) || (tolen == 0)) //broadcast
            {
                socket->SocketID = UDPOpen(socket->localPort, NULL, socket->remotePort);
            }
            else
            {
                if(socket->bsdState != SKT_ARP_VERIFY)
                {
                    remoteInfo.IPAddr.Val = socket->remoteIP;
                    ARPResolve(&remoteInfo.IPAddr);
                    startTick = TickGet();
                    socket->bsdState = SKT_ARP_VERIFY;
                }
                else if(socket->bsdState == SKT_ARP_VERIFY)
                {
                    // Wait for the MAC address to finish being obtained
                    remoteInfo.IPAddr.Val = socket->remoteIP;
                    if(!ARPIsResolved(&remoteInfo.IPAddr, &remoteInfo.MACAddr))
                    {
                        // Time out if too much time is spent in this state
    			        if(TickGet()- startTick > 1*TICK_SECOND)
    			        {
                            // Retransmit ARP request
                            socket->bsdState = SKT_ARP_RESOLVE;
    			        }
                    }
                    socket->SocketID = UDPOpen(socket->localPort, &remoteInfo, socket->remotePort);
                    socket->bsdState = SKT_EST;
                }
            }
        }
        
        if(socket->bsdState == SKT_EST)
        {
            if(UDPIsPutReady(socket->SocketID) > 0)
            {
                size = UDPPutArray((BYTE*)buf, len);
                UDPFlush();
                return size;
            }
        }
    }
    else if(socket->SocketType == SOCK_STREAM) //TCP will send to the already established socket.
    {
        return send(s, buf, len, 0);
    }
    return SOCKET_ERROR;
}
/*****************************************************************************
  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;
	}
}
Exemple #29
0
/*********************************************************************
 * Function:        void DNSServerTask(NET_CONFIG* pNet)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Sends dummy responses that point to ourself for DNS requests
 *
 * Note:            None
 ********************************************************************/
void DNSServerTask(NET_CONFIG* pNet)
{
	static UDP_SOCKET	MySocket = INVALID_UDP_SOCKET;
	static struct
	{
		uint16_t wTransactionID;
		uint16_t wFlags;
		uint16_t wQuestions;
		uint16_t wAnswerRRs;
		uint16_t wAuthorityRRs;
		uint16_t wAdditionalRRs;
	} DNSHeader;

    switch(dnssState)
    {
        case DNSS_STATE_START:

            // Create a socket to listen on if this is the first time calling this function
            if(MySocket == INVALID_UDP_SOCKET)
            {
                MySocket = UDPOpen(0,UDP_OPEN_SERVER,DNS_PORT,0);
                if(MySocket == INVALID_UDP_SOCKET)
                    break;
            }
            
            UDPSocketSetNet(MySocket, pNet);
            dnssState = DNSS_STATE_WAIT_REQUEST;
            break;

        case DNSS_STATE_WAIT_REQUEST:

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

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

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

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

            dnssState = DNSS_STATE_PUT_REQUEST;
            break;

        case DNSS_STATE_PUT_REQUEST:

            // check that we can transmit a DNS response packet
            if(!UDPIsPutReady(MySocket))
            {
                break;
            }

            // Write DNS response packet
            UDPPutArray(MySocket, (uint8_t*)&DNSHeader.wTransactionID, 2);	// 2 byte Transaction ID
            if(DNSHeader.wFlags & 0x0100)
                UDPPut(MySocket, 0x81);	// Message is a response with recursion desired
            else
                UDPPut(MySocket, 0x80);	// Message is a response without recursion desired flag set
            
            UDPPut(MySocket, 0x80);	// Recursion available
            UDPPut(MySocket, 0x00);	// 0x0000 Questions
            UDPPut(MySocket, 0x00);
            UDPPut(MySocket, 0x00);	// 0x0001 Answers RRs
            UDPPut(MySocket, 0x01);
            UDPPut(MySocket, 0x00);	// 0x0000 Authority RRs
            UDPPut(MySocket, 0x00);
            UDPPut(MySocket, 0x00);	// 0x0000 Additional RRs
            UDPPut(MySocket, 0x00);
            DNSCopyRXNameToTX(MySocket, pNet);	// Copy hostname of first question over to TX packet
            UDPPut(MySocket, 0x00);	// Type A Host address
            UDPPut(MySocket, 0x01);
            UDPPut(MySocket, 0x00);	// Class INternet
            UDPPut(MySocket, 0x01);
            UDPPut(MySocket, 0x00);	// Time to Live 10 seconds
            UDPPut(MySocket, 0x00);
            UDPPut(MySocket, 0x00);
            UDPPut(MySocket, 0x0A);
            UDPPut(MySocket, 0x00);	// Data Length 4 bytes
            UDPPut(MySocket, 0x04);
            UDPPutArray(MySocket, (uint8_t*)&pNet->MyIPAddr.Val, 4);	// Our IP address

            UDPFlush(MySocket);

            dnssState = DNSS_STATE_DONE;
            break;
            
         case DNSS_STATE_DONE:
            break;
    }
            
           
}