www.pudn.com > uCOSII上实现的tcpip.rar > zudp.c


#include "include/zarp.h"
#include "include/zudp.h"



udp_pcb_t	_udp_pcb_table[ZNET_MAX_USER + 1];


void udp_init(void)
{
	u8_t	i, j;

	for ( i = 0; i <= ZNET_MAX_USER ; i++)
	{
		_udp_pcb_table[i]._psocket = NULL;
		
		for (j = 0 ; j < UDP_BUFFER_LEN; j++)
			_udp_pcb_table[i]._data[j] = NULL;
		_udp_pcb_table[i]._udp_state = 0x00;
		_udp_pcb_table[i]._rindex = 0;
		_udp_pcb_table[i]._windex = 0;
	}
}

u8_t udp_open(zsocket_t *psocket)
{
	sys_sem_t new_sem;
	if ( _udp_pcb_table[psocket->_id]._psocket != NULL)
	{
		return -1;
	}
	new_sem = sys_new_sem(0);
	_udp_pcb_table[psocket->_id]._sem = new_sem;
	_udp_pcb_table[psocket->_id]._udp_state = 0x00;
	_udp_pcb_table[psocket->_id]._psocket = psocket;
	_udp_pcb_table[psocket->_id]._rindex = 0;
	_udp_pcb_table[psocket->_id]._windex = 0;
	return 0;
}

u8_t	udp_close(zsocket_t *psocket)
{
	u8_t	i;
	if ( _udp_pcb_table[psocket->_id]._psocket != NULL)
	{
		return -1;
	}
	
	sys_enter_critical();	
	_udp_pcb_table[psocket->_id]._psocket = NULL;
	sys_exit_critical();
	_udp_pcb_table[psocket->_id]._rindex = 0;
	_udp_pcb_table[psocket->_id]._windex = 0;
	for ( i = 0; i < UDP_BUFFER_LEN; i++)
	{
		_udp_pcb_table[ psocket->_id ]._data[i] = NULL;
	}
	_udp_pcb_table[psocket->_id]._udp_state = 0x00;
	return 0;
}

void udp_input(znetif_t * pnetif , zbuffer_t *pbuffer)
{
	ip_header_t     *pipheader;
	eth_header_t    *pethheader;
	udp_header_t    *pudpheader;
	u16_t           offset;
	u8_t			i;
	zsocket_t		*psocket;
	zbuffer_t*		*ppbuffer;
	udp_pcb_t		*pudp;
	
	
	pethheader = (eth_header_t *)(pbuffer->pdata);
	pipheader = (ip_header_t *)( (u8_t *)pbuffer->pdata + ETH_HEAD_LEN);
	offset =  IPH_HL(pipheader) * 4 + ETH_HEAD_LEN;
	pudpheader = (udp_header_t *)((u8_t *)pbuffer->pdata + offset);

	for ( i = 1; i <= ZNET_MAX_USER; i++)
	{
		if ( _udp_pcb_table[i]._psocket != NULL)
		{
			psocket = _udp_pcb_table[i]._psocket;
			if ( psocket->_lport == pudpheader->dest_port && 
				 psocket->_lipaddr == pipheader->dest_ipaddr)
			{
				break;
			}
		}
	}

	add_arp_item( &pipheader->src_ipaddr,&pethheader->src_hwaddr);
	

	if ( i > ZNET_MAX_USER)
	{
		zbuffer_delete(pbuffer);
		return;
	}
	
	psocket = _udp_pcb_table[i]._psocket;
	pudp = &_udp_pcb_table[i];
	ppbuffer =  _udp_pcb_table[i]._data;

	if ( pudp->_udp_state == UDP_STATE_WAIT)
	{
		pudp->_udp_state = 0;				/*we just wackup once*/
		sys_signal_sem( pudp->_sem );	
	}
	
	if ( ppbuffer[pudp->_windex] == NULL)
	{
		ppbuffer[pudp->_windex] = pbuffer;
		pudp->_windex ++;
		if ( pudp->_windex >= UDP_BUFFER_LEN)
		{
			_udp_pcb_table[i]._windex = 0;
		}
	}
	else
		zbuffer_delete(pbuffer);
	
	return;
}



u8_t udp_recv(zsocket_t *psocket , ipaddr_t *remote_ip, u16_t *remote_port, zbuffer_t **pdata, u8_t flags)
{
	zbuffer_t	**ppbuffer;
	udp_pcb_t 	*pudp_pcb;
	ip_header_t     *pipheader;
	udp_header_t    *pudpheader;
	u16_t           offset;
	u8_t			err;

	if ( _udp_pcb_table[ psocket->_id ]._psocket != psocket)
	{
		return -1;
	}

	
	ppbuffer = (zbuffer_t **)pdata;
	pudp_pcb = &_udp_pcb_table[ psocket->_id ];

	if ( pudp_pcb->_data[ pudp_pcb->_rindex ] == NULL)
	{
		if ( flags ==  UDP_FLAGS_WAIT )
		{
			sys_enter_critical();
			pudp_pcb->_udp_state = UDP_STATE_WAIT;
			sys_wait_sem( pudp_pcb->_sem, 0 ,&err);
			if ( err != 0)
				return -1;
		}
		else		
			return -1;
	}
	
	*ppbuffer = pudp_pcb->_data[ pudp_pcb->_rindex ];
	pudp_pcb->_data[ pudp_pcb->_rindex ] = NULL;
	pudp_pcb->_rindex++;
	if (pudp_pcb->_rindex >= UDP_BUFFER_LEN)
		pudp_pcb->_rindex = 0;
	
	pipheader = (ip_header_t *)( (u8_t *)((*ppbuffer)->pdata) + ETH_HEAD_LEN);
	offset =  IPH_HL(pipheader) * 4 + ETH_HEAD_LEN;
	pudpheader = (udp_header_t *)((u8_t *)((*ppbuffer)->pdata) + offset);

	*remote_ip = pipheader->src_ipaddr;
	*remote_port = pudpheader->src_port;
	
	*ppbuffer = zbuffer_adjust(*ppbuffer, (-1) * (offset + UDP_HEAD_LEN) ,0);
	
	if ((*ppbuffer) != NULL)
		return 0;
	else
		return -1;

}


u8_t udp_send(zsocket_t *psocket , ipaddr_t *remote_ip, u16_t *remote_port, void *pdata, u16_t *psize)
{

  	ip_header_t     *pipheader;
	eth_header_t    *pethheader;
	udp_header_t    *pudpheader;
		
	zbuffer_t 	*pbuffer;
	ethaddr_t 	remote_eth;
	u16_t		len;
	u8_t		i;
	s16_t		offset;
	s32_t		ret;
	
	if ( arp_lookup( &remote_eth, remote_ip) != 0 )
	{
		if ( arp_query(&remote_eth, remote_ip) != 0 )
			return -1;
	}		
	
	
	pbuffer = zbuffer_new( IP_HEAD_LEN + ETH_HEAD_LEN + sizeof(udp_header_t) + *psize );
	if ( pbuffer == NULL)
		return -1;
	offset = (s16_t)(0 - (IP_HEAD_LEN + ETH_HEAD_LEN + sizeof(udp_header_t)));
	
	if (zbuffer_head_adjust( pbuffer, offset) != 0)
		return -1;
	

	len = *psize;
	zbuffer_write(pbuffer, pdata, &len);
	if ( *psize != len)
	{
		zbuffer_delete(pbuffer);
		return -1;
	}
	
	offset *= -1;


	if (zbuffer_head_adjust( pbuffer, offset) != 0)
			return -1;
	
	pethheader = (eth_header_t *)(pbuffer->pdata);
	pipheader = (ip_header_t *)( (u8_t *)pbuffer->pdata + ETH_HEAD_LEN);
	pudpheader = (udp_header_t *)((u8_t *)pbuffer->pdata + IP_HEAD_LEN + ETH_HEAD_LEN);

/*ethenet header*/	
	for ( i = 0; i < 6 ; i ++)
	{
		pethheader->dest_hwaddr.addr[i] = remote_eth.addr[i];
		pethheader->src_hwaddr.addr[i] = psocket->_pnetif->hwaddr.addr[i];
	}
	pethheader->eth_type = ETHTYPE_IP;
	

/*ip header*/	
	IPH_VHLTOS_SET(pipheader, 4, IP_HEAD_LEN / 4, 0);
	IPH_LEN_SET(pipheader, pbuffer->tot_len - ETH_HEAD_LEN );
	IPH_OFFSET_SET(pipheader, IP_DF);
	IPH_ID_SET(pipheader, ++ip_id);
	IPH_TTL_SET(pipheader, 255);
    IPH_PROTO_SET(pipheader, IP_PROTO_UDP);
	IPH_CHKSUM_SET(pipheader, 0);
	pipheader->src_ipaddr = psocket->_lipaddr;
	pipheader->dest_ipaddr = *remote_ip;
	
	IPH_CHKSUM_SET(pipheader, inet_chksum(pipheader, IP_HEAD_LEN));

/*udp header*/
	pudpheader->src_port = psocket->_lport;
	pudpheader->dest_port = *remote_port;
	pudpheader->len = *psize + UDP_HEAD_LEN;
	pudpheader->chksum = 0x0000;

 	if ( psocket->_pnetif->netif_tx(psocket->_pnetif, pbuffer) == 0)
	{
		ret = 0;
	}
	else
		ret = -1;	
	

	zbuffer_delete(pbuffer);
	return ret;
}