예제 #1
0
/*********************************************************************
 * Function:        void ICMPPut(NODE_INFO *remote,
 *                               ICMP_CODE code,
 *                               BYTE *data,
 *                               BYTE len,
 *                               WORD id,
 *                               WORD seq)
 *
 * PreCondition:    ICMPIsTxReady() == TRUE
 *
 * Input:           remote      - Remote node info
 *                  code        - ICMP_ECHO_REPLY or ICMP_ECHO_REQUEST
 *                  data        - Data bytes
 *                  len         - Number of bytes to send
 *                  id          - ICMP identifier
 *                  seq         - ICMP sequence number
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Note:            A ICMP packet is created and put on MAC.
 *
 ********************************************************************/
void ICMPPut(NODE_INFO *remote,
             ICMP_CODE code,
             BYTE *data,
             BYTE len,
             WORD id,
             WORD seq)
{
    ICMP_PACKET packet;

    packet.Code             = 0;
    packet.Type             = code;
    packet.Checksum         = 0;
    packet.Identifier       = id;
    packet.SequenceNumber   = seq;

    memcpy((void*)packet.Data, (void*)data, len);

    SwapICMPPacket(&packet);

    packet.Checksum         = CalcIPChecksum((BYTE*)&packet,
                                    (WORD)(ICMP_HEADER_SIZE + len));

    IPPutHeader(remote,
                IP_PROT_ICMP,
                (WORD)(ICMP_HEADER_SIZE + len));

    IPPutArray((BYTE*)&packet, (WORD)(ICMP_HEADER_SIZE + len));

    MACFlush();
}
예제 #2
0
/*********************************************************************
 * Function:        LONG ICMPGetReply(void)
 *
 * PreCondition:    ICMPBeginUsage() returned TRUE and ICMPSendPing() 
 *					was called
 *
 * Input:           None
 *
 * Output:          -2: No response received yet
 *					-1: Operation timed out (longer than ICMP_TIMEOUT) 
 *						has elapsed.
 *					>=0: Number of TICKs that elapsed between 
 *						 initial ICMP transmission and reception of 
 *						 a valid echo.
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 ********************************************************************/
LONG ICMPGetReply(void)
{
	switch(ICMPState)
	{
		case SM_ARP_RESOLVE:
			// See if the ARP reponse was successfully received
			if(ARPIsResolved(&ICMPRemote.IPAddr, &ICMPRemote.MACAddr))
			{
				// Position the write pointer for the next IPPutHeader operation
			    MACSetWritePtr(BASE_TX_ADDR + sizeof(ETHER_HEADER));
			
			    // Wait for TX hardware to become available (finish transmitting 
			    // any previous packet)
			    while(!IPIsTxReady());
			
				// Create IP header in TX memory
				IPPutHeader(&ICMPRemote, IP_PROT_ICMP, sizeof(ICMP_HEADER) + 2);
				MACPutArray((BYTE*)&ICMPHeader, sizeof(ICMPHeader));
				MACPut(0x00);	// Send two dummy bytes as ping payload 
				MACPut(0x00);	// (needed for compatibility with some buggy NAT routers)
				MACFlush();

				// MAC Address resolved and echo sent, advance state
				ICMPState = SM_GET_ECHO;
				return -2;
			}

			// See if the ARP/echo request timed out
			if(TickGet() - ICMPTimer > ICMP_TIMEOUT)
			{
				ICMPState = SM_IDLE;
				return -1;
			}

			// No ARP response back yet
			return -2;

		case SM_GET_ECHO:
			// See if the echo was successfully received
			if(ICMPFlags.bReplyValid)
			{
				return (LONG)ICMPTimer;
			}
		
			// See if the ARP/echo request timed out
			if(TickGet() - ICMPTimer > ICMP_TIMEOUT)
			{
				ICMPState = SM_IDLE;
				return -1;
			}
		
			// No echo response back yet
			return -2;
		
		// SM_IDLE or illegal/impossible state:
		default:
			return -1;
	}
}
예제 #3
0
/*********************************************************************
 * Function:        SHORT ICMPGetReply(void)
 *
 * PreCondition:    ICMPBeginUsage() returned TRUE and ICMPSendPing() 
 *					was called
 *
 * Input:           None
 *
 * Output:          -2: No response received yet
 *					-1: Operation timed out (longer than ICMP_TIMEOUT) 
 *						has elapsed.
 *					>=0: Number of TICKs that elapsed between 
 *						 initial ICMP transmission and reception of 
 *						 a valid echo.
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 ********************************************************************/
SHORT ICMPGetReply(void)
{
	switch(ICMPState)
	{
		case SM_IDLE:
			return -1;

		case SM_ARP_RESOLVE:
			// See if the ARP reponse was successfully received
			if(ARPIsResolved(&ICMPRemote.IPAddr, &ICMPRemote.MACAddr))
			{
				// Position the write pointer for the next IPPutHeader operation
			    MACSetWritePtr(BASE_TX_ADDR + sizeof(ETHER_HEADER));
			
			    // Wait for TX hardware to become available (finish transmitting 
			    // any previous packet)
			    while(!IPIsTxReady());
			
				// Create IP header in TX memory
				IPPutHeader(&ICMPRemote, IP_PROT_ICMP, sizeof(ICMP_HEADER));
				MACPutArray((BYTE*)&ICMPHeader, sizeof(ICMPHeader));
				MACFlush();

				// MAC Address resolved and echo sent, advance state
				ICMPState = SM_GET_ECHO;
				return -2;
			}

			// See if the ARP/echo request timed out
			if((WORD)TickGet() - ICMPTimer > ICMP_TIMEOUT)
			{
				ICMPState = SM_IDLE;
				return -1;
			}

			// No ARP response back yet
			return -2;

		case SM_GET_ECHO:
			// See if the echo was successfully received
			if(ICMPFlags.bReplyValid)
			{
				return (SHORT)ICMPTimer;
			}
		
			// See if the ARP/echo request timed out
			if((WORD)TickGet() - ICMPTimer > ICMP_TIMEOUT)
			{
				ICMPState = SM_IDLE;
				return -1;
			}
		
			// No echo response back yet
			return -2;
	}
}
예제 #4
0
파일: icmp.c 프로젝트: bartak32/wx-station
/**
 * A ICMP packet is created and put on MAC.
 *
 * @preCondition ICMPIsTxReady() == TRUE
 *
 * @param remote    Remote node info
 * @param code      ICMP_ECHO_REPLY or ICMP_ECHO_REQUEST
 * @param data      Data bytes
 * @param len       Number of bytes to send
 * @param id        ICMP identifier
 * @param seq       ICMP sequence number
 */
void ICMPPut(NODE_INFO *remote,
             ICMP_CODE code,
             BYTE *data,
             BYTE len,
             WORD id,
             WORD seq)
{
    ICMP_PACKET    packet;
    WORD ICMPLen;
    BUFFER MyTxBuffer;
    MyTxBuffer = MACGetTxBuffer(TRUE);

    // Abort if there is no where in the Ethernet controller to 
    // store this packet.
    if(MyTxBuffer == INVALID_BUFFER)
        return;

    IPSetTxBuffer(MyTxBuffer, 0);


    ICMPLen = ICMP_HEADER_SIZE + (WORD)len;

    packet.Code             = 0;
    packet.Type             = code;
    packet.Checksum         = 0;
    packet.Identifier       = id;
    packet.SequenceNumber   = seq;

    memcpy((void*)packet.Data, (void*)data, len);

    SwapICMPPacket(&packet);

#if defined(NON_MCHP_MAC)   //This is NOT a Microchip MAC
    packet.Checksum         = CalcIPChecksum((BYTE*)&packet,
                                    ICMPLen);
#endif

    IPPutHeader(remote,
                IP_PROT_ICMP,
                (WORD)(ICMP_HEADER_SIZE + len));

    IPPutArray((BYTE*)&packet, ICMPLen);

#if !defined(NON_MCHP_MAC)  //This is a Microchip MAC
    // Calculate and write the ICMP checksum using the Microchip MAC's DMA
    packet.Checksum = MACCalcTxChecksum(sizeof(IP_HEADER), ICMPLen);
    IPSetTxBuffer(MyTxBuffer, 2);
    MACPutArray((BYTE*)&packet.Checksum, 2);
#endif


    MACFlush();
}
예제 #5
0
/*********************************************************************
 * Function:        BOOL UDPFlush(void)
 *
 * PreCondition:    UDPPut() is already called and desired UDP socket
 *                  is set as an active socket by calling
 *                  UDPIsPutReady().
 *
 * Input:           None
 *
 * Output:          All and any data associated with active UDP socket
 *                  buffer is marked as ready for transmission.
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            This function transmit all data from
 *                  an active UDP socket.
 ********************************************************************/
void UDPFlush(void)
{
    UDP_HEADER      h;
    UDP_SOCKET_INFO *p;

    /*
     * When using SLIP (USART), packet transmission takes some time
     * and hence before sending another packet, we must make sure
     * that, last packet is transmitted.
     * When using ethernet controller, transmission occurs very fast
     * and by the time next packet is transmitted, previous is
     * transmitted and we do not need to check for last packet.
     */
    //while( !IPIsTxReady() );

    p = &UDPSocketInfo[activeUDPSocket];

    h.SourcePort        = swaps(p->localPort);
    h.DestinationPort   = swaps(p->remotePort);
    h.Length            = (WORD)((WORD)p->TxCount + (WORD)sizeof(UDP_HEADER));
    // Do not swap h.Length yet.  It is needed in IPPutHeader.
    h.Checksum          = 0x00;

    IPSetTxBuffer(p->TxBuffer, 0);

    /*
     * Load IP header.
     */
    IPPutHeader( &p->remoteNode,
                 IP_PROT_UDP,
                 h.Length );


    // Now swap h.Length.
    h.Length            = swaps(h.Length);

    /*
     * Now load UDP header.
     */
    IPPutArray((BYTE*)&h, sizeof(h));

    /*
     * Update checksum.
     * TO BE IMPLEMENTED
     */

    MACFlush();

    p->TxBuffer         = INVALID_BUFFER;
    p->TxCount          = 0;

}
예제 #6
0
/**
 * This function transmit all data from the active UDP socket.
 *
 * @preCondition    UDPPut() is already called and desired UDP socket
 *                  is set as an active socket by calling
 *                  UDPIsPutReady().
 *
 * @return          All and any data associated with active UDP socket
 *                  buffer is marked as ready for transmission.
 *
 */
void UDPFlush(void)
{
    UDP_HEADER      h;
    UDP_SOCKET_INFO *p;

    // Wait for TX hardware to become available (finish transmitting 
    // any previous packet)
    while( !IPIsTxReady(TRUE) ) FAST_USER_PROCESS();

    p = &UDPSocketInfo[activeUDPSocket];

    h.SourcePort.Val        = swaps(p->localPort);
    h.DestinationPort.Val   = swaps(p->remotePort);
    h.Length.Val            = (WORD)((WORD)p->TxCount + (WORD)sizeof(UDP_HEADER));
    // Do not swap h.Length yet.  It is needed in IPPutHeader.
    h.Checksum.Val      = 0x00;

    //Makes the given TX Buffer active, and set's the pointer to the first byte after the IP
    //header. This is the first byte of the UDP header. The UDP header follows the IP header.
    IPSetTxBuffer(p->TxBuffer, 0);

    //Load IP header.
    IPPutHeader( &p->remoteNode,
                 IP_PROT_UDP,
                 h.Length.Val );


    //Now swap h.Length.Val
    h.Length.Val        = swaps(h.Length.Val);

    //Now load UDP header.
    IPPutArray((BYTE*)&h, sizeof(h));

    //Update checksum. !!!!!!!!!!!!!!! TO BE IMPLEMENTED !!!!!!!!!!!!!!!!!!!

    //Send data contained in TX Buffer via MAC
    MACFlush();

    // The buffer was reserved with AutoFree, so we can immediately 
    // discard it.  The MAC layer will free it after transmission.
    p->TxBuffer         = INVALID_BUFFER;
    p->TxCount          = 0;

}
예제 #7
0
파일: ICMP.c 프로젝트: CEIT-UQ/RGB
/*********************************************************************
 * Function:        LONG ICMPGetReply(void)
 *
 * PreCondition:    ICMPBeginUsage() returned TRUE and ICMPSendPing() 
 *					was called
 *
 * Input:           None
 *
 * Output:          -3: Could not resolve hostname (DNS timeout or 
 *			    	    hostname invalid)
 *					-2: No response received yet
 *					-1: Operation timed out (longer than ICMP_TIMEOUT) 
 *						has elapsed.
 *					>=0: Number of TICKs that elapsed between 
 *						 initial ICMP transmission and reception of 
 *						 a valid echo.
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 ********************************************************************/
LONG ICMPGetReply(void)
{
	ICMP_PACKET ICMPPacket;

	switch(ICMPState)
	{
#if defined(STACK_USE_DNS)
		case SM_DNS_SEND_QUERY:
			// Obtain DNS module ownership
			if(!DNSBeginUsage())
				break;
			
			// Send DNS query
			if(ICMPFlags.bRemoteHostIsROM)
				DNSResolveROM(StaticVars.RemoteHost.szROM, DNS_TYPE_A);
			else
				DNSResolve(StaticVars.RemoteHost.szRAM, DNS_TYPE_A);
			
			ICMPState = SM_DNS_GET_RESPONSE;
			break;
				
		case SM_DNS_GET_RESPONSE:
			// See if DNS is done, and if so, get the remote IP address
			if(!DNSIsResolved(&StaticVars.ICMPRemote.IPAddr))
				break;
			
			// Free the DNS module
			DNSEndUsage();
			
			// Return error code if the DNS query failed
			if(StaticVars.ICMPRemote.IPAddr.Val == 0x00000000ul)
			{
				ICMPState = SM_IDLE;
				return -3;
			}

			ICMPState = SM_ARP_SEND_QUERY;	
			// No break;	
#endif

		case SM_ARP_SEND_QUERY:
			ARPResolve(&StaticVars.ICMPRemote.IPAddr);
			ICMPState = SM_ARP_GET_RESPONSE;
			break;
			
		case SM_ARP_GET_RESPONSE:
			// See if the ARP reponse was successfully received
			if(!ARPIsResolved(&StaticVars.ICMPRemote.IPAddr, &StaticVars.ICMPRemote.MACAddr))
				break;
			
			ICMPState = SM_ICMP_SEND_ECHO_REQUEST;
			// No break; 
		
		case SM_ICMP_SEND_ECHO_REQUEST:
		    if(!IPIsTxReady())
		    	break;

			// Set up the ping packet
			ICMPPacket.vType = 0x08;	// 0x08: Echo (ping) request
			ICMPPacket.vCode = 0x00;
			ICMPPacket.wChecksum = 0x0000;
			ICMPPacket.wIdentifier = 0xEFBE;
			wICMPSequenceNumber++; 
			ICMPPacket.wSequenceNumber = wICMPSequenceNumber;
			ICMPPacket.wData = 0x2860;
			ICMPPacket.wChecksum = CalcIPChecksum((BYTE*)&ICMPPacket, sizeof(ICMPPacket));
		
			// Record the current time.  This will be used as a basis for 
			// finding the echo response time, which exludes the ARP and DNS 
			// steps
			ICMPTimer = TickGet();

			// Position the write pointer for the next IPPutHeader operation
		    MACSetWritePtr(BASE_TX_ADDR + sizeof(ETHER_HEADER));
		
			// Create IP header in TX memory
			IPPutHeader(&StaticVars.ICMPRemote, IP_PROT_ICMP, sizeof(ICMPPacket));
			MACPutArray((BYTE*)&ICMPPacket, sizeof(ICMPPacket));
			MACFlush();

			// Echo sent, advance state
			ICMPState = SM_ICMP_GET_ECHO_RESPONSE;
			break;

		case SM_ICMP_GET_ECHO_RESPONSE:
			// See if the echo was successfully received
			if(ICMPFlags.bReplyValid)
				return (LONG)ICMPTimer;
		
			break;
		
		// SM_IDLE or illegal/impossible state:
		default:
			return -1;
	}

	// See if the DNS/ARP/echo request timed out
	if(TickGet() - ICMPTimer > ICMP_TIMEOUT)
	{
		// Free DNS module if we have it in use
		#if defined(STACK_USE_DNS)
			if(ICMPState == SM_DNS_GET_RESPONSE)
				DNSEndUsage();
		#endif
		
		// Stop ICMP echo test and return error to caller
		ICMPState = SM_IDLE;
		return -1;
	}

	// Still working.  No response to report yet.
	return -2;
}
예제 #8
0
파일: ICMP.c 프로젝트: CEIT-UQ/RGB
/*********************************************************************
 * Function:        void ICMPProcess(void)
 *
 * PreCondition:    MAC buffer contains ICMP type packet.
 *
 * Input:           *remote: Pointer to a NODE_INFO structure of the 
 *					ping requester
 *					len: Count of how many bytes the ping header and 
 *					payload are in this IP packet
 *
 * Output:          Generates an echo reply, if requested
 *					Validates and sets ICMPFlags.bReplyValid if a 
 *					correct ping response to one of ours is received.
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 ********************************************************************/
void ICMPProcess(NODE_INFO *remote, WORD len)
{
	DWORD_VAL dwVal;

    // Obtain the ICMP header Type, Code, and Checksum fields
    MACGetArray((BYTE*)&dwVal, sizeof(dwVal));
	
	// See if this is an ICMP echo (ping) request
	if(dwVal.w[0] == 0x0008u)
	{
		// Validate the checksum using the Microchip MAC's DMA module
		// The checksum data includes the precomputed checksum in the 
		// header, so a valid packet will always have a checksum of 
		// 0x0000 if the packet is not disturbed.
		if(MACCalcRxChecksum(0+sizeof(IP_HEADER), len))
			return;
	
		// Calculate new Type, Code, and Checksum values
		dwVal.v[0] = 0x00;	// Type: 0 (ICMP echo/ping reply)
		dwVal.v[2] += 8;	// Subtract 0x0800 from the checksum
		if(dwVal.v[2] < 8u)
		{
			dwVal.v[3]++;
			if(dwVal.v[3] == 0u)
				dwVal.v[2]++;
		}
	
	    // Wait for TX hardware to become available (finish transmitting 
	    // any previous packet)
	    while(!IPIsTxReady());

		// Position the write pointer for the next IPPutHeader operation
		// NOTE: do not put this before the IPIsTxReady() call for WF compatbility
	    MACSetWritePtr(BASE_TX_ADDR + sizeof(ETHER_HEADER));
        	
		// Create IP header in TX memory
		IPPutHeader(remote, IP_PROT_ICMP, len);
	
		// Copy ICMP response into the TX memory
		MACPutArray((BYTE*)&dwVal, sizeof(dwVal));
		MACMemCopyAsync(-1, -1, len-4);
		while(!MACIsMemCopyDone());
	
		// Transmit the echo reply packet
	    MACFlush();
	}
#if defined(STACK_USE_ICMP_CLIENT)
	else if(dwVal.w[0] == 0x0000u)	// See if this an ICMP Echo reply to our request
	{
		// Get the sequence number and identifier fields
		MACGetArray((BYTE*)&dwVal, sizeof(dwVal));
		
		// See if the identifier matches the one we sent
		if(dwVal.w[0] != 0xEFBE)	
			return;
	
		if(dwVal.w[1] != wICMPSequenceNumber)
			return;

		// Validate the ICMP checksum field
	    IPSetRxBuffer(0);
		if(CalcIPBufferChecksum(sizeof(ICMP_PACKET)))	// Two bytes of payload were sent in the echo request
			return;
		
		// Flag that we received the response and stop the timer ticking
		ICMPFlags.bReplyValid = 1;
		ICMPTimer = TickGet() - ICMPTimer;
	}
#endif
}
예제 #9
0
/*********************************************************************
 * Function:        BOOL UDPFlush(void)
 *
 * PreCondition:    UDPPut() is already called and desired UDP socket
 *                  is set as an active socket by calling
 *                  UDPIsPutReady().
 *
 * Input:           None
 *
 * Output:          All and any data associated with active UDP socket
 *                  buffer is marked as ready for transmission.
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            This function transmit all data from
 *                  an active UDP socket.
 ********************************************************************/
void UDPFlush(void)
{
    UDP_HEADER      h;
    UDP_SOCKET_INFO *p;

    // Wait for TX hardware to become available (finish transmitting
    // any previous packet)
    while( !IPIsTxReady(TRUE) );

    p = &UDPSocketInfo[activeUDPSocket];

    debug_udp("\r\nUDP FLUSH - Sok:%U TxC:%LU SP:%LU DP:%LU ",
         activeUDPSocket,
         p->TxCount,
         p->localPort,
         p->remotePort
      );
    debug_udp("MAC-%X:%X:%X:%X:%X:%X",
         p->remoteNode.MACAddr.v[0],
         p->remoteNode.MACAddr.v[1],
         p->remoteNode.MACAddr.v[2],
         p->remoteNode.MACAddr.v[3],
         p->remoteNode.MACAddr.v[4],
         p->remoteNode.MACAddr.v[5]
      );


    h.SourcePort        = swaps(p->localPort);
    h.DestinationPort   = swaps(p->remotePort);
    h.Length            = (WORD)((WORD)p->TxCount + (WORD)sizeof(UDP_HEADER));
    // Do not swap h.Length yet.  It is needed in IPPutHeader.
    h.Checksum          = 0x0000;

    IPSetTxBuffer(p->TxBuffer, 0);

    /*
     * Load IP header.
     */

    IPPutHeader( &p->remoteNode,
                 IP_PROT_UDP,
                 h.Length );


    // Now swap h.Length.
    h.Length            = swaps(h.Length);

    // Now load UDP header.
    IPPutArray((BYTE*)&h, sizeof(h));

     // Update checksum.
     // TO BE IMPLEMENTED

    MACFlush();

    // The buffer was reserved with AutoFree, so we can immediately
   // discard it.  The MAC layer will free it after transmission.
    p->TxBuffer         = INVALID_BUFFER;
    p->TxCount          = 0;

}
예제 #10
0
파일: UDP.c 프로젝트: KiwiJaune/RecMiwiPi
/*****************************************************************************
  Function:
	void UDPFlush(void)

  Summary:
	Transmits all pending data in a UDP socket.
	
  Description:
	This function builds a UDP packet with the pending TX data and marks it 
	for transmission over the network interface.  Since UDP is a frame-based
	protocol, this function must be called before returning to the main
	stack loop whenever any data is written.

  Precondition:
	UDPIsPutReady() was previously called to specify the current socket, and
	data has been written to the socket using the UDPPut family of functions.

  Parameters:
	None
	
  Returns:
  	None

  Remarks:
	Note that unlike TCPFlush, UDPFlush must be called before returning to 
	the main stack loop.  There is no auto transmit for UDP segments.
  ***************************************************************************/
void UDPFlush(void)
{
    UDP_HEADER      h;
    UDP_SOCKET_INFO *p;
    WORD			wUDPLength;

    p = &UDPSocketInfo[activeUDPSocket];

	wUDPLength = UDPTxCount + sizeof(UDP_HEADER);

	// Generate the correct UDP header
    h.SourcePort        = swaps(p->localPort);
    h.DestinationPort   = swaps(p->remotePort);
    h.Length            = swaps(wUDPLength);
	h.Checksum 			= 0x0000;
    
	// Calculate IP pseudoheader checksum if we are going to enable 
	// the checksum field
	#if defined(UDP_USE_TX_CHECKSUM)
	{
		PSEUDO_HEADER   pseudoHeader;
		
		pseudoHeader.SourceAddress	= AppConfig.MyIPAddr;
		pseudoHeader.DestAddress    = p->remote.remoteNode.IPAddr;
		pseudoHeader.Zero           = 0x0;
		pseudoHeader.Protocol       = IP_PROT_UDP;
		pseudoHeader.Length			= wUDPLength;
		SwapPseudoHeader(pseudoHeader);
		h.Checksum = ~CalcIPChecksum((BYTE*)&pseudoHeader, sizeof(pseudoHeader));
	}
	#endif

	// Position the hardware write pointer where we will need to 
	// begin writing the IP header
	MACSetWritePtr(BASE_TX_ADDR + sizeof(ETHER_HEADER));
	
	// Write IP header to packet
	IPPutHeader(&p->remote.remoteNode, IP_PROT_UDP, wUDPLength);

    // Write UDP header to packet
    MACPutArray((BYTE*)&h, sizeof(h));
    
	// Calculate the final UDP checksum and write it in, if enabled
	#if defined(UDP_USE_TX_CHECKSUM)
	{
        PTR_BASE	wReadPtrSave;
        WORD		wChecksum;

		wReadPtrSave = MACSetReadPtr(BASE_TX_ADDR + sizeof(ETHER_HEADER) + sizeof(IP_HEADER));
		wChecksum = CalcIPBufferChecksum(wUDPLength);
		if(wChecksum == 0x0000u)
			wChecksum = 0xFFFF;
		MACSetReadPtr(wReadPtrSave);
		MACSetWritePtr(BASE_TX_ADDR + sizeof(ETHER_HEADER) + sizeof(IP_HEADER) + 6);	// 6 is the offset to the Checksum field in UDP_HEADER
		MACPutArray((BYTE*)&wChecksum, sizeof(wChecksum));
	}
	#endif
    
	// Transmit the packet
    MACFlush();

	// Reset packet size counter for the next TX operation
    UDPTxCount = 0;
	LastPutSocket = INVALID_UDP_SOCKET;
}
예제 #11
0
/**
 * This function transmit all data from the active UDP socket.
 *
 * @preCondition    UDPPut() is already called and desired UDP socket
 *                  is set as an active socket by calling
 *                  UDPIsPutReady().
 *
 * @return          All and any data associated with active UDP socket
 *                  buffer is marked as ready for transmission.
 *
 */
void UDPFlush(void)
{
    UDP_HEADER      h;
    UDP_SOCKET_INFO *p;
    WORD csLength;
	DWORD_VAL csChecksum;
    // Wait for TX hardware to become available (finish transmitting 
    // any previous packet)
    while( !IPIsTxReady(TRUE) ) FAST_USER_PROCESS();

    p = &UDPSocketInfo[activeUDPSocket];

    h.SourcePort.Val        = swaps(p->localPort);
    h.DestinationPort.Val   = swaps(p->remotePort);
    h.Length.Val            = (WORD)((WORD)p->TxCount + (WORD)sizeof(UDP_HEADER));
    // Do not swap h.Length yet.  It is needed in IPPutHeader.
    h.Checksum.Val      = 0x00;

    //Makes the given TX Buffer active, and set's the pointer to the first byte after the IP
    //header. This is the first byte of the UDP header. The UDP header follows the IP header.
    IPSetTxBuffer(p->TxBuffer, 0);

    //Load IP header.
    IPPutHeader( &p->remoteNode,
                 IP_PROT_UDP,
                 h.Length.Val );

    // save length before swap for checksum calculation
    csLength			= p->TxCount;

    //Now swap h.Length.Val
    h.Length.Val        = swaps(h.Length.Val);

    //Now load UDP header.
    IPPutArray((BYTE*)&h, sizeof(h));

    //Update checksum. !!!!!!!!!!!!!!! TO BE IMPLEMENTED !!!!!!!!!!!!!!!!!!!
	// Update checksum.
    
	// start the checksum with value for UDP protocol & length from pseudo header (and in the actual packet)
	csChecksum.Val = (WORD)IP_PROT_UDP + (WORD)csLength + sizeof(UDP_HEADER);
	// add in my address and the remoteNode address
	csChecksum.Val += ((WORD)MY_IP_BYTE1 << 8) + MY_IP_BYTE2;
	csChecksum.Val += ((WORD)MY_IP_BYTE3 << 8) + MY_IP_BYTE4;
	csChecksum.Val += ((WORD)p->remoteNode.IPAddr.v[0] << 8) +  ((WORD)p->remoteNode.IPAddr.v[1] ) +
					  ((WORD)p->remoteNode.IPAddr.v[2] << 8) +  ((WORD)p->remoteNode.IPAddr.v[3] );
			

    // set mac pointer to the ip_addr of the source, so all of pseudo header but length is included.
    // length of pseudo header is already included in previous instruction.
    //MACSetRxBuffer( sizeof(IP_HEADER)+sizeof(UDP_HEADER) );
	

	csChecksum.Val += (WORD)p->localPort;
	csChecksum.Val += (WORD)p->remotePort;
	csChecksum.Val += (WORD)csLength + sizeof(UDP_HEADER);

	//IPSetRxBuffer(BASE_TX_ADDR + sizeof(ETHER_HEADER) + sizeof(IP_HEADER) - ( sizeof(IP_ADDR) * 2 ) );
	
    // handled in UdpPut routines
	csChecksum.Val += udpChecksum;

	// add any carry over to the last word
	while((DWORD)csChecksum.word.MSW) {
		csChecksum.Val = (DWORD)csChecksum.word.LSW + (DWORD)csChecksum.word.MSW;
	}	
	// add any carry over from adding the carry over
	//csChecksum.Val = (DWORD)csChecksum.word.LSW + (DWORD)csChecksum.word.MSW;
	
	// invert
	csChecksum.Val = ~csChecksum.Val;
	
	// set write pointer to location of checksum in packet
	//MACSetWritePtr( sizeof(ETHER_HEADER) + sizeof(IP_HEADER) + sizeof(UDP_HEADER) - 2 );
	IPSetTxBuffer(p->TxBuffer,   sizeof(UDP_HEADER) - 2);
	// write the swapped checksum to the packet
	
	
	//MACPut(	csChecksum.v[1] );
	//MACPut(	csChecksum.v[0] );
	MACPut(0);
	MACPut(0);
    //Send data contained in TX Buffer via MAC
    MACFlush();

    // The buffer was reserved with AutoFree, so we can immediately 
    // discard it.  The MAC layer will free it after transmission.
    p->TxBuffer         = INVALID_BUFFER;
    p->TxCount          = 0;

}