⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 udp.c

📁 在S3C2440上运行的"电子日历“(支持平年,闰年,星期自动调整). 开发环境是RVDS2.2
💻 C
字号:
/**---------------------版权 (c)----------------------------------------------------------***
***                     作者:颜章健                                                      ***
***                     邮件:jenkinyan@163.com                                           ***
***                                                                                       ***
***---------------------File Info---------------------------------------------------------***
*** 创 建 人:          颜章健                                                            ***
*** 创建日期:          2008-03-22                                                        ***
*** 创建版本:                                                                            ***
*** 文件描述:          UDP(User Data Protocol) 用户数据协议                              ***
***---------------------------------------------------------------------------------------***
*** 修 订 人:          颜章健                                                            ***
*** 修订日期:          2008-04-14                                                        ***
*** 修订版本:                                                                            ***
*** 修订描述:          增加UDP校验及支持大数据包分片                                     ***
***---------------------------------------------------------------------------------------**/
#include "config.h"


// UDP 接口链表第一个接口
static	UDP_SOCKET	*UdpFirstSocket;
/********************************************************************************************
*** 函数名称:	UdpCheckSum		
*** 函数描述:	UDP校验值计算		
*** 入    口:	
*** 出    口:	
********************************************************************************************/
static	uint16	UdpCheckSum(NET_PKT *Packet)
{
	__packed	uint16	*_ptr;
	uint16	i,len;
	uint32	sum = 0;
	
	_ptr = (__packed uint16 *)Packet->Data;
	while(Packet != NULL)
	{
		_ptr = (__packed uint16 *)Packet->Data;
		len = Packet->Length >> 1;
		for(i=0; i<len; i++)
		{
			sum += *_ptr++;
		}			
		if(Packet->Next == NULL)	
		{
			break;
		}
		
		Packet = Packet->Next;
	}	
	if(Packet->Length & 0x0001)
	{
		sum += ((*_ptr)&0xff);
	}
	
	sum = (sum & 0xffff) + ((sum>>16)&0xffff);
	if(sum&0xffff0000)	sum++;
	
	return	(uint16)(sum & 0xffff);
}

/********************************************************************************************
*** 函数名称:	UdpSocketSend		
*** 函数描述:	运输层发送 UDP 数据包		
*** 入    口:	This	:Socket接口
***				Data	:用户数据缓冲区指针
***				Length	:用户数据长度		
*** 出    口:	无		
********************************************************************************************/
void	UdpSocketSend(UDP_SOCKET *This,uint8 *Data,uint16 Length)
{
	NET_PKT	UdpHead,UdpData;
	uint8	i,head[20];
	uint16	value16;
	// 填充伪头部内容 TcpHead[] 的前12字节
	for(i=0; i<4; i++)
	{
		head[i]   = LinkLayer.Config.Ip[i];	// 本地地址
		head[i+4] = This->DestAddr[i];		// 目的地址
	}
	head[ 8] = 0;			head[ 9] = 17;
	while(Length)
	{
		if(Length > 1472)
		{
			value16 = 1472;
			Length -= 1472;
		}
		else
		{
			value16 = Length;
			Length = 0;
		}
		UdpData.Data   = Data;
		UdpData.Length = value16;
		UdpData.Next   = NULL;
				
		value16 += 8;
		head[10] = (value16 >> 8);	head[11] = (uint8)value16;	
		
		value16  = This->LocalPort;
		head[12] = (value16 >> 8);	head[13] = (uint8)value16;
		
		value16  = This->DestPort;
		head[14] = (value16 >> 8);	head[15] = (uint8)value16;		
		head[16] = head[10];		head[17] = head[11];				
		head[18] = 0x00;			head[19] = 0x00;
		
		UdpHead.Data   = head;
		UdpHead.Length = 20;
		UdpHead.Next   = &UdpData;
		value16  = ~UdpCheckSum(&UdpHead);		
		head[18] = (uint8)value16;	head[19] = (value16 >> 8);		
		
		UdpHead.Data   = head + 12;
		UdpHead.Length = 8;
		UdpHead.Next   = &UdpData;		
		
		NetLayer.SendPacket(IPF_UDP,This->DestAddr,&UdpHead);
	}
}

/********************************************************************************************
*** 函数名称:	UdpSocketCreate		
*** 函数描述:	创建UDP接口		
*** 入    口:  DstAddr	:目的地址
***				DstPort	:目的端口
***				SrcPort	:本地端口
***				Hook	:数据处理钩子函数				
*** 出    口:	
********************************************************************************************/
//UDP_SOCKET 	*UdpSocketCreate
uint8 	UdpSocketCreate
	(	UDP_SOCKET	*Socket,
		uint8 	*DstAddr,		uint16 	DstPort,
		uint16 	SrcPort,		void 	(*Hook)(UDP_SOCKET *This)
	)
{
	uint8 i;
	UDP_SOCKET	*sock;//,*Socket;
	
	/*
	if((Socket = (UDP_SOCKET *)malloc(sizeof(UDP_SOCKET))) == NULL)
	{
		return	NULL;
	}
	
	// 入口参数过滤
	if(DstPort == 0)
	{
		free(Socket);
		return	NULL;
	}*/
	
	// 设置Socket属性
	for(i=0; i<4; i++)	Socket->DestAddr[i] = *DstAddr++;
	Socket->This = Socket;
	Socket->LocalPort = SrcPort;
	Socket->DestPort  = DstPort;
	Socket->Rxd  = NULL;
	Socket->Rxl  = 0;
	//Socket->Send = UdpSendPacket;
	Socket->Hook = Hook;

	sock = UdpFirstSocket;
	while(sock != NULL)
	{
		if(sock->LocalPort == SrcPort)	
		{	/*		
			free(Socket);
			return	NULL;
			*/
			return		UDP_ERR_PORT_INUSED;
		}
		sock = sock->Next;
	}
	
	
	// Socket插入链表
	Socket->Next = UdpFirstSocket;
	UdpFirstSocket = Socket;
	
	//return	Socket;
	return		UDP_ERR_NONE;
}

/********************************************************************************************
*** 函数名称:	UdpSocketDelete		
*** 函数描述:	删除已经创建的UDP接口		
*** 入    口:	Socket	:要删除的接口		
*** 出    口:	错误信息		
********************************************************************************************/
uint8	UdpSocketDelete(UDP_SOCKET	*Socket)
{
	UDP_SOCKET	*sock,*next;

	if(Socket != NULL)
	{
		//free(Socket);
	}
	else
	{
		return	UDP_ERR_USER;
	}
	if(UdpFirstSocket == NULL)		
	{
		return	UDP_ERR_USER;
	}
	if(Socket == UdpFirstSocket)
	{
		UdpFirstSocket = UdpFirstSocket->Next;
		return	UDP_ERR_NONE;
	}
	if(UdpFirstSocket->Next == NULL)
	{
		return	UDP_ERR_USER;
	}
	
	sock = UdpFirstSocket;
	next = sock->Next;	
	while(next != NULL)
	{
		if(next == Socket)
		{
			sock->Next = next->Next;			
			return	UDP_ERR_NONE;
		}
		next = next->Next;
		sock = sock->Next;		
	}	
	
	return	UDP_ERR_USER;
}

/********************************************************************************************
*** 函数名称:	UdpReceiveTask		
*** 函数描述:	UDP 协议接收处理:查找用户创建的接口,将数据从该接口输出给用户Hook处理	
*** 入    口:	无		
*** 出    口:	无		
********************************************************************************************/
void	UdpReceiveTask(void)
{
	UDP_SOCKET	*sock;
	uint8		*UdpData;
	uint16		UdpDataLength;
	uint16		DestPort;
	uint16		SourcePort;
//	uint8		SourceIp[4];
		
	
	UdpDataLength = *NetLayer.Rxd;	
	UdpDataLength = (UdpDataLength & 0x000f) << 2;	
	UdpData = NetLayer.Rxd + UdpDataLength;
	
//	SourceIp[0] = NetLayer.Rxd[12];
//	SourceIp[1] = NetLayer.Rxd[13];
//	SourceIp[2] = NetLayer.Rxd[14];
//	SourceIp[3] = NetLayer.Rxd[15];
	
	SourcePort   = UdpData[0];
	SourcePort <<= 8;
	SourcePort  |= UdpData[1];	
	
	DestPort   = UdpData[2];
	DestPort <<= 8;
	DestPort  |= UdpData[3];
	
	UdpDataLength   = UdpData[4];
	UdpDataLength <<= 8;
	UdpDataLength  |= UdpData[5];
	
	UdpDataLength  -= 8;
	UdpData += 8;

	sock = UdpFirstSocket;
	while(sock != NULL)
	{
		if(	(DestPort == sock->LocalPort) 					// IP包目的端口与Socket的源端口匹配
			//&& (SourcePort == sock->DestPort)				// IP包的源端口与Socket目的端口匹配
			//&& (InetMemCmp(SourceIp,sock->DestAddr,4))	// IP包的源地址与Socket目的地址匹配
			)
		{
			sock->Rxd = UdpData;
			sock->Rxl = UdpDataLength;
			if(sock->Hook != NULL)
			{
				sock->Hook(sock->This);
				// 把最近活跃的端口排列到链表最前面
				if(sock != UdpFirstSocket)
				{
					UdpSocketDelete(sock);
					sock->Next = UdpFirstSocket;
					UdpFirstSocket = sock;
				}
			}
			sock->Rxd = NULL;
			sock->Rxl = 0;
			break;
		}
		sock = sock->Next;
	}
}

/********************************************************************************************
*** 函数名称:	UdpInit		
*** 函数描述:	UDP 协议初始化		
*** 入    口:	无		
*** 出    口:	无		
********************************************************************************************/
void	UdpInit(void)
{
	UdpFirstSocket  = NULL;
}

/********************************************************************************************
*** 					文件结束														  ***	
********************************************************************************************/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -