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

📄 udp.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*udp.c*/#include "inet.h"#include "assert.h"#include "buf.h"#include "clock.h"#include "io.h"#include "ip.h"#include "sr.h"#include "type.h"#include "udp.h"INIT_PANIC();#define UDP_PORT_NR	1#define UDP_FD_NR	32typedef struct udp_port{	int up_flags;	int up_state;	int up_ipfd;	int up_minor;	int up_ipdev;	acc_t *up_wr_pack;	ipaddr_t up_ipaddr;	struct udp_fd *up_next_fd;	struct udp_fd *up_write_fd;} udp_port_t;#define UPF_EMPTY	0x0#define UPF_WRITE_IP	0x1#define UPF_WRITE_SP	0x2#define UPF_READ_IP	0x4#define UPF_READ_SP	0x8#define UPF_SUSPEND	0x10#define UPF_MORE2WRITE	0x20#define UPS_EMPTY	0#define UPS_SETPROTO	1#define UPS_GETCONF	2#define UPS_MAIN	3#define UPS_ERROR	4typedef struct udp_fd{	int uf_flags;	udp_port_t *uf_port;	int uf_ioreq;	int uf_srfd;	nwio_udpopt_t uf_udpopt;	get_userdata_t uf_get_userdata;	put_userdata_t uf_put_userdata;	acc_t *uf_pack;	acc_t *uf_rd_buf;	size_t uf_rd_count;	size_t uf_wr_count;	time_t uf_exp_tim;} udp_fd_t;#define UFF_EMPTY	0x0#define UFF_INUSE	0x1#define UFF_IOCTL_IP	0x2#define UFF_READ_IP	0x4#define UFF_WRITE_IP	0x8#define UFF_OPTSET	0x10FORWARD void read_ip_packets ARGS(( udp_port_t *udp_port ));FORWARD void udp_buffree ARGS(( int priority, size_t reqsize ));FORWARD void udp_main ARGS(( udp_port_t *udp_port ));FORWARD acc_t *udp_get_data ARGS(( int fd, size_t offset, size_t count, 	int for_ioctl ));FORWARD int udp_put_data ARGS(( int fd, size_t offset, acc_t *data, 		int for_ioctl ));FORWARD void udp_restart_write_port ARGS(( udp_port_t *udp_port ));FORWARD void process_inc_fragm ARGS(( udp_port_t *udp_port, acc_t *data ));FORWARD int reply_thr_put ARGS(( udp_fd_t *ucp_fd, int reply,	int for_ioctl ));FORWARD void reply_thr_get ARGS(( udp_fd_t *udp_fd, int reply,	int for_ioctl ));FORWARD int udp_setopt ARGS(( udp_fd_t *udp_fd ));FORWARD udpport_t find_unused_port ARGS(( int fd ));FORWARD int is_unused_port ARGS(( Udpport_t port ));FORWARD int udp_packet2user ARGS(( udp_fd_t *udp_fd ));FORWARD void restart_write_fd ARGS(( udp_fd_t *udp_fd ));FORWARD u16_t pack_oneCsum ARGS(( acc_t *pack ));PRIVATE udp_port_t udp_port_table[UDP_PORT_NR];PRIVATE udp_fd_t udp_fd_table[UDP_FD_NR];PUBLIC void udp_init(){	udp_fd_t *udp_fd;	udp_port_t *udp_port;	int i, result;	assert (BUF_S >= sizeof(struct nwio_ipopt));	assert (BUF_S >= sizeof(struct nwio_ipconf));	assert (BUF_S >= sizeof(struct nwio_udpopt));	assert (BUF_S >= sizeof(struct udp_io_hdr));	assert (UDP_HDR_SIZE == sizeof(udp_hdr_t));	assert (UDP_IO_HDR_SIZE == sizeof(udp_io_hdr_t));	udp_port_table[0].up_minor= UDP_DEV0;	udp_port_table[0].up_ipdev= IP0;	for (i= 0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++, udp_fd++)	{		udp_fd->uf_flags= UFF_EMPTY;	}	bf_logon(udp_buffree);	for (i= 0, udp_port= udp_port_table; i<UDP_PORT_NR; i++, udp_port++)	{		udp_port->up_flags= UPF_EMPTY;		udp_port->up_state= UPS_EMPTY;		udp_port->up_next_fd= udp_fd_table;		udp_port->up_write_fd= NULL;		result= sr_add_minor (udp_port->up_minor,			udp_port-udp_port_table, udp_open, udp_close, udp_read,			udp_write, udp_ioctl, udp_cancel);		assert (result >= 0);		udp_main(udp_port);	}}PRIVATE void udp_main(udp_port)udp_port_t *udp_port;{	udp_fd_t *udp_fd;	int result, i;	switch (udp_port->up_state)	{	case UPS_EMPTY:		udp_port->up_state= UPS_SETPROTO;		udp_port->up_ipfd= ip_open(udp_port->up_ipdev, 			udp_port-udp_port_table, udp_get_data, udp_put_data);		if (udp_port->up_ipfd < 0)		{			udp_port->up_state= UPS_ERROR;			printf("%s, %d: unable to open ip port\n", __FILE__,				__LINE__);			return;		}		result= ip_ioctl(udp_port->up_ipfd, NWIOSIPOPT);		if (result == NW_SUSPEND)			udp_port->up_flags |= UPF_SUSPEND;		if (result<0)		{			return;		}		if (udp_port->up_state != UPS_GETCONF)			return;		/* drops through */	case UPS_GETCONF:		udp_port->up_flags &= ~UPF_SUSPEND;		result= ip_ioctl(udp_port->up_ipfd, NWIOGIPCONF);		if (result == NW_SUSPEND)			udp_port->up_flags |= UPF_SUSPEND;		if (result<0)		{			return;		}		if (udp_port->up_state != UPS_MAIN)			return;		/* drops through */	case UPS_MAIN:		udp_port->up_flags &= ~UPF_SUSPEND;		for (i= 0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++, udp_fd++)		{			if (!(udp_fd->uf_flags & UFF_INUSE))				continue;			if (udp_fd->uf_port != udp_port)				continue;			if (udp_fd->uf_flags & UFF_IOCTL_IP)				udp_ioctl(i, udp_fd->uf_ioreq);		}		read_ip_packets(udp_port);		return;	default:#if DEBUG { where(); printf("udp_port_table[%d].up_state= %d\n", udp_port-udp_port_table,	udp_port->up_state); }#endif		ip_panic(( "unknown state" ));		break;	}}int udp_open (port, srfd, get_userdata, put_userdata)int port;int srfd;get_userdata_t get_userdata;put_userdata_t put_userdata;{	int i;	udp_fd_t *udp_fd;	for (i= 0; i<UDP_FD_NR && (udp_fd_table[i].uf_flags & UFF_INUSE);		i++);	if (i>= UDP_FD_NR)	{#if DEBUG { where(); printf("out of fds\n"); }#endif		return EOUTOFBUFS;	}	udp_fd= &udp_fd_table[i];	udp_fd->uf_flags= UFF_INUSE;	udp_fd->uf_port= &udp_port_table[port];	udp_fd->uf_srfd= srfd;	udp_fd->uf_udpopt.nwuo_flags= UDP_DEF_OPT;	udp_fd->uf_get_userdata= get_userdata;	udp_fd->uf_put_userdata= put_userdata;	udp_fd->uf_pack= 0;	return i;}PRIVATE acc_t *udp_get_data (port, offset, count, for_ioctl)int port;size_t offset;size_t count;int for_ioctl;{	udp_port_t *udp_port;	udp_fd_t *udp_fd;	int result;	udp_port= &udp_port_table[port];	switch(udp_port->up_state)	{	case UPS_SETPROTO:assert (for_ioctl);		if (!count)		{			result= (int)offset;			if (result<0)			{				udp_port->up_state= UPS_ERROR;				break;			}			udp_port->up_state= UPS_GETCONF;			if (udp_port->up_flags & UPF_SUSPEND)				udp_main(udp_port);			return NULL;		}		else		{			struct nwio_ipopt *ipopt;			acc_t *acc;assert (!offset);assert (count == sizeof(*ipopt));			acc= bf_memreq(sizeof(*ipopt));			ipopt= (struct nwio_ipopt *)ptr2acc_data(acc);			ipopt->nwio_flags= NWIO_COPY | NWIO_EN_LOC | 				NWIO_EN_BROAD | NWIO_REMANY | NWIO_PROTOSPEC |				NWIO_HDR_O_ANY | NWIO_RWDATALL;			ipopt->nwio_proto= IPPROTO_UDP;			return acc;		}	case UPS_MAIN:assert (!for_ioctl);assert (udp_port->up_flags & UPF_WRITE_IP);		if (!count)		{			result= (int)offset;#if DEBUG & 256 { where(); printf("result of ip_write is %d\n", result); }#endifassert (udp_port->up_wr_pack);			bf_afree(udp_port->up_wr_pack);			udp_port->up_wr_pack= 0;			if (udp_port->up_flags & UPF_WRITE_SP)			{				if (udp_port->up_write_fd)				{					udp_fd= udp_port->up_write_fd;					udp_port->up_write_fd= NULL;					udp_fd->uf_flags &= ~UFF_WRITE_IP;					reply_thr_get(udp_fd, result, FALSE);				}				udp_port->up_flags &= ~(UPF_WRITE_SP | 					UPF_WRITE_IP);				if (udp_port->up_flags & UPF_MORE2WRITE)				{					udp_restart_write_port(udp_port);				}			}			else				udp_port->up_flags &= ~UPF_WRITE_IP;		}		else		{			return bf_cut (udp_port->up_wr_pack, offset, count);		}		break;	default:		printf("udp_get_data(%d, 0x%x, 0x%x) called but up_state= 0x%x\n",			port, offset, count, udp_port->up_state);		break;	}	return NULL;}PRIVATE int udp_put_data (fd, offset, data, for_ioctl)int fd;size_t offset;acc_t *data;int for_ioctl;{	udp_port_t *udp_port;	int result;	udp_port= &udp_port_table[fd];	switch (udp_port->up_state)	{	case UPS_GETCONF:		if (!data)		{			result= (int)offset;			if (result<0)			{				udp_port->up_state= UPS_ERROR;				return NW_OK;			}			udp_port->up_state= UPS_MAIN;			if (udp_port->up_flags & UPF_SUSPEND)				udp_main(udp_port);		}		else		{			struct nwio_ipconf *ipconf;			data= bf_packIffLess(data, sizeof(*ipconf));			ipconf= (struct nwio_ipconf *)ptr2acc_data(data);assert (ipconf->nwic_flags & NWIC_IPADDR_SET);			udp_port->up_ipaddr= ipconf->nwic_ipaddr;			bf_afree(data);		}		break;	case UPS_MAIN:assert (udp_port->up_flags & UPF_READ_IP);		if (!data)		{			result= (int)offset;compare (result, >=, 0);			if (udp_port->up_flags & UPF_READ_SP)			{				udp_port->up_flags &= ~(UPF_READ_SP|					UPF_READ_IP);				read_ip_packets(udp_port);			}			else				udp_port->up_flags &= ~UPF_READ_IP;		}		else		{assert (!offset);	/* This isn't a valid assertion but ip sends only			 * whole datagrams up */			process_inc_fragm(udp_port, data);		}		break;	default:		ip_panic((		"udp_put_data(%d, 0x%x, 0x%x) called but up_state= 0x%x\n",					fd, offset, data, udp_port->up_state ));	}	return NW_OK;}int udp_ioctl (fd, req)int fd;int req;{	udp_fd_t *udp_fd;	udp_port_t *udp_port;	nwio_udpopt_t *udp_opt;	acc_t *opt_acc;	int type;	int result;	udp_fd= &udp_fd_table[fd];	type= req & IOCTYPE_MASK;assert (udp_fd->uf_flags & UFF_INUSE);	udp_port= udp_fd->uf_port;	udp_fd->uf_flags |= UFF_IOCTL_IP;	udp_fd->uf_ioreq= req;	if (udp_port->up_state != UPS_MAIN)		return NW_SUSPEND;	switch(type)	{	case NWIOSUDPOPT & IOCTYPE_MASK:		if (req != NWIOSUDPOPT)		{			reply_thr_get (udp_fd, EBADIOCTL, TRUE);			result= NW_OK;			break;		}		result= udp_setopt(udp_fd);		break;	case NWIOGUDPOPT & IOCTYPE_MASK:		if (req != NWIOGUDPOPT)		{			reply_thr_put(udp_fd, EBADIOCTL, TRUE);			result= NW_OK;			break;		}		opt_acc= bf_memreq(sizeof(*udp_opt));assert (opt_acc->acc_length == sizeof(*udp_opt));		udp_opt= (nwio_udpopt_t *)ptr2acc_data(opt_acc);		*udp_opt= udp_fd->uf_udpopt;		udp_opt->nwuo_locaddr= udp_fd->uf_port->up_ipaddr;		result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd, 0, opt_acc,			TRUE);		if (result == NW_OK)			reply_thr_put(udp_fd, NW_OK, TRUE);		break;	default:		reply_thr_get(udp_fd, EBADIOCTL, TRUE);		result= NW_OK;		break;	}	if (result != NW_SUSPEND)		udp_fd->uf_flags &= ~UFF_IOCTL_IP;	return result;}PRIVATE int udp_setopt(udp_fd)udp_fd_t *udp_fd;{	udp_fd_t *fd_ptr;	nwio_udpopt_t oldopt, newopt;	acc_t *data;	int result;	udpport_t port;	unsigned int new_en_flags, new_di_flags, old_en_flags, old_di_flags,		all_flags, flags;	unsigned long new_flags;	int i;#if DEBUG & 256 { where(); printf("in udp_setopt\n"); }#endif	data= (*udp_fd->uf_get_userdata)(udp_fd->uf_srfd, 0, 		sizeof(nwio_udpopt_t), TRUE);	if (!data)		return EFAULT;	data= bf_packIffLess(data, sizeof(nwio_udpopt_t));assert (data->acc_length == sizeof(nwio_udpopt_t));	newopt= *(nwio_udpopt_t *)ptr2acc_data(data);	bf_afree(data);	oldopt= udp_fd->uf_udpopt;#if DEBUG & 256 { where(); printf("newopt.nwuo_flags= 0x%x, newopt.nwuo_locport= %d, newopt.nwuo_remport= %d\n",	newopt.nwuo_flags, ntohs(newopt.nwuo_locport),	ntohs(newopt.nwuo_remport)); }#endif	old_en_flags= oldopt.nwuo_flags & 0xffff;	old_di_flags= (oldopt.nwuo_flags >> 16) & 0xffff;	new_en_flags= newopt.nwuo_flags & 0xffff;	new_di_flags= (newopt.nwuo_flags >> 16) & 0xffff;	if (new_en_flags & new_di_flags)	{#if DEBUG { where(); printf("returning EBADMODE\n"); }#endif		reply_thr_get(udp_fd, EBADMODE, TRUE);		return NW_OK;	}	/* NWUO_ACC_MASK */	if (new_di_flags & NWUO_ACC_MASK)	{#if DEBUG { where(); printf("returning EBADMODE\n"); }#endif		reply_thr_get(udp_fd, EBADMODE, TRUE);		return NW_OK;

⌨️ 快捷键说明

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