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

📄 tinyudp.c

📁 ADAM2 sources (modified by Oleg)
💻 C
📖 第 1 页 / 共 2 页
字号:
}

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 + -