📄 tinyudp.c
字号:
}
int udplib_close(void)
{
udp_close(&listen);
gl_srcport = gl_dstport = 0;
return 0;
}
/*
* udp_open
*
* Description: Open the specified UDP port for send/receive. NOTE: under
* the current implementation, only one port can bo open at a time;
* if this function is called while another port is already open, that
* port will be closed so that the requested port may be opened.
* Parameters:
* p (in) - Port to open.
* Returns:
* 0 if port successfully opened,
* 1 if error.
*/
int udp_open(udp_Socket *s, word srcport, longword ina, word dstport, procref dataHandler, procref application)
{
udp_close(s);
sys_memset(s, 0, sizeof(udp_Socket));
s->rdata = s->rddata;
s->maxrdatalen = udp_MaxBufSize;
s->ip_type = UDP_PROTO;
s->myport = srcport;
/* check for broadcast */
if ((long)(ina) == -1 || !ina)
sys_memset(s->hisethaddr, 0xff, sizeof(eth_HwAddress));
else {
if (!sar_MapIn2Eth(ina, (eth_HwAddress *)&s->hisethaddr[0]))
{
/*sys_printf( "Couldn't resolve it!\n" );*/
return 0;
}
}
s->hisaddr = ina;
s->hisport = dstport;
s->dataHandler = dataHandler;
s->appHandler = application;
s->next = udp_allsocs;
udp_allsocs = s;
return 1;
}
/*
* udp_close
*
* Description: Shutdown the currently open port (if any).
*
* Returns:
* 0 if successful,
* 1 if an error occurred.
*/
int udp_close(udp_Socket *ds)
{
udp_Socket *s, **sp;
sp = &udp_allsocs;
for(;;)
{
s = *sp;
if (s == ds)
{
*sp = s->next;
break;
}
if (s == NULL)
break;
sp = &s->next;
}
return 1;
}
/*
* udp_init
*
* Description: Initialize the driver.
*
* Returns:
* 0 if successful
*/
int udplib_init(in_HwAddress my_ip)
{
sin_lclINAddr = my_ip;
udp_allsocs = NULL;
gl_srcport = gl_dstport = 0;
udp_id = 0;
return 1;
}
/*
* udp_deinit
*
* Description: Shut down the driver.
*
* Returns:
* 0 if successful
*/
int udplib_deinit(void)
{
if (gl_srcport)
udplib_close();
gl_srcport = gl_dstport = 0;
udp_allsocs = NULL;
return 1;
}
int udp_receive(unsigned int *ipaddress, void *data, int len, int Client)
{
int ret_length;
GetAnotherPacket:
if (Client == TRUE)
ip_Handler();
/* assume no packets will be waiting */
ret_length = 0;
/*
* check the packet buffers for new data
* if more than one packet is waiting, return the oldest one */
if (rxpacket.validData == 0)
return 0;
/* point to the packet we're working on */
if (rxpacket.length > MTU)
{
/* whoa - packet is too big!?!?!?!? */
rxpacket.validData = 0;
goto GetAnotherPacket;
}
/* copy the data into the xfer buffer */
*ipaddress = rxpacket.src;
ret_length = rxpacket.length;
if (ret_length > len)
ret_length = len;
sys_memcpy(data, rxpacket.data, rxpacket.length);
rxpacket.validData = 0;
return ret_length; /* success */
}
/*
* udplib_send
*
* Description: Send the data in the transfer buffer to the node specified in
* the transfer buffer's node field.
*
* Returns:
* 0 if successful,
* 1 if an error occurred.
*/
int udp_send(unsigned int ipaddr, int len, void * data)
{
static PacketBuffer sendbuf; /* where outgoing packets are assembled */
if (!gl_srcport)
return (1); /* D'OHH! Gotta open the port before you send */
/* set up the packet for transmission */
sendbuf.validData = 1;
sendbuf.src = ipaddr;
sendbuf.length = len;
sys_memcpy(sendbuf.data, data, len);
/* this sequence is equivalent to a BSD sendto() call*/
if (udp_open(&talk, gl_srcport, ipaddr, gl_dstport, udp_dataHandler, NULL))
{
udp_write(&talk, (unsigned char *)sendbuf.data, len, 0);
udp_close(&talk);
return (1);
}
return (0);
}
/* udp_write() handles fragmented UDP by assuming it'll be called once for all
* fragments with no intervening calls. This is the case in sock_write().
* Handles upto a hair-under 32K datagrams. Could be made to handle upto
* a hair-under 64K easily... wanna Erick?
* Might be possible to test 'offset' for non/zero fewer times to be more
* efficient. Might also be more efficient to use the old UDP checksum() call
* when more_frags is false in the first frag (i.e., not a fragmented dgram).
* Uses _mss to decide splits which defaults to 1400. Could pack more
* into an Ethernet packet.*/
#define IP_MF 0x0020 /* more fragments, net ubyte order */
int udp_write(udp_Socket *s, byte *datap, int len, word offset)
{
/* special pseudo header because need to compute checksum in two
* parts (may not have all of datagram built at once).*/
tcp_PseudoHeader ph;
struct _pkt
{
in_Header in;
udp_Header udp;
int data;
} *pkt;
byte *dp;
in_Header *inp;
udp_Header *udpp = NULL;
word maxlen;
int more_frags;
pkt = (struct _pkt *)sed_FormatPacket(&s->hisethaddr[0], 0x800);
if (offset)
{
/* this is not the first fragment data goes right after IP header */
dp = (byte *) &pkt->udp;
}
else
{
dp = (byte *) &pkt->data;
udpp = &pkt->udp;
/* udp header */
udpp->srcPort = wfix(s->myport);
udpp->dstPort = wfix(s->hisport);
udpp->checksum = 0;
udpp->length = wfix(UDP_LENGTH + len);
}
inp = &pkt->in;
sys_memset(inp, 0, sizeof(in_Header));
maxlen = ETH_MSS & 0xFFF8; /* make a multiple of 8 */
if (!offset)
maxlen -= UDP_LENGTH; /* note UDP_LENGTH is 8, so ok */
if (len > maxlen)
{
len = maxlen;
more_frags = 1;
}
else
more_frags = 0;
inp->length = wfix(sizeof(in_Header) + (offset ? 0 : UDP_LENGTH) + len);
MoveW(datap, dp, len);
/* internet header */
inp->vht = wfix(0x4500); /* version 4, hdrlen 5, tos 0*/
/* if offset non-zero, then is part of a prev datagram so don't incr ID */
inp->identification = wfix(offset ? udp_id : ++udp_id); /* was post inc */
inp->frag = (offset ? wfix((offset + UDP_LENGTH) >> 3) : 0);
if (more_frags)
inp->frag |= IP_MF;
inp->ttlProtocol = wfix((250<<8) + UDP_PROTO);
inp->checksum = 0;
inp->source = lfix(sin_lclINAddr);
inp->destination = lfix(s->hisaddr);
inp->checksum = wfix(~checksum(inp, sizeof(in_Header)));
/* compute udp checksum if desired */
if(!offset)
{
ph.src = inp->source;
ph.dst = inp->destination;
ph.mbz = 0;
ph.protocol = UDP_PROTO; /* udp */
ph.length = wfix(wfix(pkt->in.length) - sizeof(in_Header));
/* can't use since may not have the whole dgram built at once this
* way handles it */
ph.checksum = wfix(checksum(udpp, wfix(ph.length)));
udpp->checksum = wfix(~checksum(&ph, sizeof(ph)));
}
sed_Send(wfix(inp->length));
return (len);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -