📄 udp.c
字号:
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 = 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;
}
/*********************************************************************
* Function: BOOL UDPIsGetReady(UDP_SOCKET s)
*
* PreCondition: UDPInit() is already called.
*
* Input: A valid UDP socket that is already "Listen"ed on
* or opened.
*
* Output: TRUE if given port contains any data.
* FALSE if given port does not contain any data.
*
* Side Effects: Given socket is set as an active UDP Socket.
*
* Overview: None
*
* Note: This function automatically sets supplied socket
* as an active socket. Caller need not call
* explicit function UDPSetActiveSocket(). All
* subsequent calls will us this socket as an
* active socket.
********************************************************************/
BOOL UDPIsGetReady(UDP_SOCKET s)
{
activeUDPSocket = s;
return ( UDPSocketInfo[activeUDPSocket].RxCount > 0 );
}
/*********************************************************************
* Function: BOOL UDPGet(BYTE *v)
*
* PreCondition: UDPInit() is already called AND
* UDPIsGetReady(s) == TRUE
*
* Input: v - Buffer to receive UDP data byte
*
* Output: TRUE if a data byte was read
* FALSE if no data byte was read or available
*
* Side Effects: None
*
* Overview: None
*
* Note: This function fetches data from an active UDP
* socket as set by UDPIsGetReady() call.
********************************************************************/
BOOL UDPGet(BYTE *v)
{
// CALLER MUST MAKE SURE THAT THERE IS ENOUGH DATA BYTE IN BUFFER
// BEFORE CALLING THIS FUNCTION.
// USE UDPIsGetReady() TO CONFIRM.
if ( UDPSocketInfo[activeUDPSocket].RxCount == 0 )
return FALSE;
// If if this very first read to packet, set MAC Rx Pointer to
// beginig of UDP data area.
if ( UDPSocketInfo[activeUDPSocket].Flags.bFirstRead )
{
UDPSocketInfo[activeUDPSocket].Flags.bFirstRead = FALSE;
UDPSetRxBuffer(0);
}
*v = MACGet();
UDPSocketInfo[activeUDPSocket].RxCount--;
if ( UDPSocketInfo[activeUDPSocket].RxCount == 0 )
{
MACDiscardRx();
}
return TRUE;
}
/*********************************************************************
* Function: void UDPDiscard(void)
*
* PreCondition: UDPInit() is already called AND
* UDPIsGetReady() == TRUE with desired UDP socket.
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: None
*
* Note: This function discards an active UDP socket content.
********************************************************************/
void UDPDiscard(void)
{
if ( UDPSocketInfo[activeUDPSocket].RxCount )
MACDiscardRx();
UDPSocketInfo[activeUDPSocket].RxCount = 0;
}
/*********************************************************************
* Function: BOOL UDPProcess(NODE_INFO* remoteNode,
* IP_ADDR *localIP,
* WORD len)
*
* PreCondition: UDPInit() is already called AND
* UDP segment is ready in MAC buffer
*
* Input: remoteNode - Remote node info
* len - Total length of UDP semgent.
*
* Output: TRUE if this function has completed its task
* FALSE otherwise
*
* Side Effects: None
*
* Overview: None
*
* Note: None
********************************************************************/
// Pseudo header as defined by rfc 793.
typedef struct _PSEUDO_HEADER
{
IP_ADDR SourceAddress;
IP_ADDR DestAddress;
BYTE Zero;
BYTE Protocol;
WORD Length;
} PSEUDO_HEADER;
#define SwapPseudoHeader(h) (h.Length = swaps(h.Length))
BOOL UDPProcess(NODE_INFO *remoteNode, IP_ADDR *localIP, WORD len)
{
UDP_HEADER h;
UDP_SOCKET s;
PSEUDO_HEADER pseudoHeader;
WORD_VAL checksum;
// Retrieve UDP header.
MACGetArray((BYTE*)&h, sizeof(h));
h.SourcePort = swaps(h.SourcePort);
h.DestinationPort = swaps(h.DestinationPort);
h.Length = swaps(h.Length) - sizeof(UDP_HEADER);
// See if we need to validate the checksum field (0x0000 is disabled)
if(h.Checksum)
{
h.Checksum = swaps(h.Checksum);
// Calculate IP pseudoheader checksum.
pseudoHeader.SourceAddress = remoteNode->IPAddr;
pseudoHeader.DestAddress.v[0] = localIP->v[0];
pseudoHeader.DestAddress.v[1] = localIP->v[1];
pseudoHeader.DestAddress.v[2] = localIP->v[2];
pseudoHeader.DestAddress.v[3] = localIP->v[3];
pseudoHeader.Zero = 0x0;
pseudoHeader.Protocol = IP_PROT_UDP;
pseudoHeader.Length = len;
SwapPseudoHeader(pseudoHeader);
checksum.Val = ~CalcIPChecksum((BYTE*)&pseudoHeader,
sizeof(pseudoHeader));
// Set UDP packet checksum = pseudo header checksum in MAC RAM.
IPSetRxBuffer(6);
MACPut(checksum.v[0]);
// In case if the end of the RX buffer is reached and a wraparound is needed, set the next address to prevent writing to the wrong address.
IPSetRxBuffer(7);
MACPut(checksum.v[1]);
IPSetRxBuffer(0);
// Now calculate UDP packet checksum in NIC RAM - including
// pesudo header.
checksum.Val = CalcIPBufferChecksum(len);
if ( checksum.Val != h.Checksum )
{
MACDiscardRx();
return TRUE;
}
}
s = FindMatchingSocket(&h, remoteNode, localIP);
if ( s == INVALID_UDP_SOCKET )
{
// If there is no matching socket, There is no one to handle
// this data. Discard it.
MACDiscardRx();
}
else
{
UDPSocketInfo[s].RxCount = h.Length;
UDPSocketInfo[s].Flags.bFirstRead = TRUE;
}
return TRUE;
}
/*********************************************************************
* Function: UDP_SOCKET FindMatchingSocket(UDP_HEADER *h,
* NODE_INFO *remoteNode,
* IP_ADDR *localIP)
*
* PreCondition: UDP Segment header has been retrieved from buffer
* The IP header has also been retrieved
*
* Input: remoteNode - Remote node info from IP header
* h - header of UDP semgent.
*
* Output: matching UDP socket or INVALID_UDP_SOCKET
*
* Side Effects: None
*
* Overview: None
*
* Note: None
********************************************************************/
#define BROADCAST_ADDRESS (0xffffffffL)
static UDP_SOCKET FindMatchingSocket(UDP_HEADER *h,
NODE_INFO *remoteNode,
IP_ADDR *localIP)
{
UDP_SOCKET s;
UDP_SOCKET partialMatch;
UDP_SOCKET_INFO *p;
partialMatch = INVALID_UDP_SOCKET;
p = UDPSocketInfo;
for ( s = 0; s < MAX_UDP_SOCKETS; s++ )
{
// This packet is said to be matching with current socket
// 1. If its destination port matches with our local port.
// 2. This socket does not have any data pending.
// 3. Packet source IP address matches with socket remote IP address.
// OR this socket had transmitted packet with destination address as broadcast.
if ( p->localPort == h->DestinationPort )
{
if ( (p->remotePort == h->SourcePort) && (p->RxCount == 0L) )
{
if ( (p->remoteNode.IPAddr.Val == remoteNode->IPAddr.Val) ||
(localIP->Val == BROADCAST_ADDRESS) )
{
return s;
}
}
partialMatch = s;
}
p++;
}
if ( partialMatch != INVALID_UDP_SOCKET )
{
p = &UDPSocketInfo[partialMatch];
memcpy((void*)&p->remoteNode,
(const void*)remoteNode, sizeof(p->remoteNode) );
p->remotePort = h->SourcePort;
}
return partialMatch;
}
#endif //#if defined(STACK_USE_UDP)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -