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;
}