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

📄 udp.c

📁 minux的源代码,一个非常小的操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
				*(udp_io_hdr_t *)ptr2acc_data(ipopt_pack)=
					*udp_io_hdr;
				udp_io_hdr= (udp_io_hdr_t *)
					ptr2acc_data(ipopt_pack);
				udp_io_hdr->uih_ip_opt_len= ip_hdr_size - 
					IP_MIN_HDR_SIZE;
				ipopt_pack->acc_next= bf_cut(ip_acc,
					(size_t)IP_MIN_HDR_SIZE,
					(size_t)udp_io_hdr->uih_ip_opt_len);
				for (tmp_acc= ipopt_pack; tmp_acc->acc_next;
					tmp_acc= tmp_acc->acc_next);
assert (tmp_acc->acc_linkC == 1);
				tmp_acc->acc_next= no_ipopt_pack->acc_next;
				if (tmp_acc->acc_next)
					tmp_acc->acc_next->acc_linkC++;
			}
			pack= ipopt_pack;
		}
		else
			pack= no_ipopt_pack;

		if (udp_fd->uf_rd_buf)
		{
			if ((flags & NWUO_ACC_MASK) == NWUO_SHARED)
			{
				share_fd= udp_fd;
				continue;
			}
#if DEBUG
 { where(); printf("throwing away packet\n"); }
#endif
			bf_afree(udp_fd->uf_rd_buf);
		}

		udp_fd->uf_rd_buf= pack;
		pack->acc_linkC++;
		udp_fd->uf_exp_tim= exp_tim;

		if ((flags & NWUO_ACC_MASK) == NWUO_SHARED ||
			(flags & NWUO_ACC_MASK) ==  NWUO_EXCL)
		{
			if (ipopt_pack)
			{
				bf_afree(ipopt_pack);
				ipopt_pack= 0;
			}
assert(no_ipopt_pack);
			bf_afree(no_ipopt_pack);
			no_ipopt_pack= 0;
		}

		if (udp_fd->uf_flags & UFF_READ_IP)
		{
#if DEBUG & 256
 { where(); printf("%d calling packet2user\n", i); }
#endif
			udp_packet2user(udp_fd);
		}
		else
		{
#if DEBUG & 256
 { where(); printf("%d not READ_IP\n", i); }
#endif
		}
		if ((flags & NWUO_ACC_MASK) == NWUO_SHARED ||
			(flags & NWUO_ACC_MASK) ==  NWUO_EXCL)
		{
			break;
		}
	}
	if (share_fd && no_ipopt_pack)
	{
		bf_afree(share_fd->uf_rd_buf);
		if (share_fd->uf_udpopt.nwuo_flags & NWUO_EN_IPOPT)
			pack= ipopt_pack;
		else
			pack= no_ipopt_pack;
		pack->acc_linkC++;
		share_fd->uf_rd_buf= pack;
		share_fd->uf_exp_tim= exp_tim;
		if (ipopt_pack)
		{
			bf_afree(ipopt_pack);
			ipopt_pack= 0;
		}
assert (no_ipopt_pack);
		bf_afree(no_ipopt_pack);
		no_ipopt_pack= 0;
	}
	else
	{
		if (ipopt_pack)
			bf_afree(ipopt_pack);
		if (no_ipopt_pack)
			bf_afree(no_ipopt_pack);
	}
assert (ip_acc);
	bf_afree(ip_acc);
assert (udp_acc);
	bf_afree(udp_acc);
}

PUBLIC void udp_close(fd)
int fd;
{
	udp_fd_t *udp_fd;

#if DEBUG
 { where(); printf("udp_close (%d)\n", fd); }
#endif
	udp_fd= &udp_fd_table[fd];

	assert (udp_fd->uf_flags & UFF_INUSE);

	udp_fd->uf_flags= UFF_EMPTY;
	if (udp_fd->uf_rd_buf)
	{
		bf_afree(udp_fd->uf_rd_buf);
		udp_fd->uf_rd_buf= 0;
	}
}

PUBLIC int udp_write(fd, count)
int fd;
size_t count;
{
	udp_fd_t *udp_fd;
	udp_port_t *udp_port;

	udp_fd= &udp_fd_table[fd];
	udp_port= udp_fd->uf_port;

	if (!(udp_fd->uf_flags & UFF_OPTSET))
	{
		reply_thr_get (udp_fd, EBADMODE, FALSE);
		return NW_OK;
	}

assert (!(udp_fd->uf_flags & UFF_WRITE_IP));

	udp_fd->uf_wr_count= count;

	udp_fd->uf_flags |= UFF_WRITE_IP;

	restart_write_fd(udp_fd);

	if (udp_fd->uf_flags & UFF_WRITE_IP)
	{
#if DEBUG 
 { where(); printf("replying NW_SUSPEND\n"); }
#endif
		return NW_SUSPEND;
	}
	else
	{
#if DEBUG & 256
 { where(); printf("replying NW_OK\n"); }
#endif
		return NW_OK;
	}
}

PRIVATE void restart_write_fd(udp_fd)
udp_fd_t *udp_fd;
{
	udp_port_t *udp_port;
	acc_t *pack, *ip_hdr_pack, *udp_hdr_pack, *ip_opt_pack, *user_data;
	udp_hdr_t *udp_hdr;
	udp_io_hdr_t *udp_io_hdr;
	ip_hdr_t *ip_hdr;
	size_t ip_opt_size, user_data_size;
	unsigned long flags;
	u16_t chksum;
	u8_t u16[2];
	int result;

	udp_port= udp_fd->uf_port;

	if (udp_port->up_flags & UPF_WRITE_IP)
	{
		udp_port->up_flags |= UPF_MORE2WRITE;
#if DEBUG
 { where(); printf("\n"); }
#endif
		return;
	}

assert (udp_fd->uf_flags & UFF_WRITE_IP);
	udp_fd->uf_flags &= ~UFF_WRITE_IP;

assert (!udp_port->up_wr_pack);

	pack= (*udp_fd->uf_get_userdata)(udp_fd->uf_srfd, 0,
		udp_fd->uf_wr_count, FALSE);
	if (!pack)
	{
		udp_fd->uf_flags &= ~UFF_WRITE_IP;
		reply_thr_get (udp_fd, EFAULT, FALSE);
#if DEBUG
 { where(); printf("\n"); }
#endif
		return;
	}

	flags= udp_fd->uf_udpopt.nwuo_flags;

	ip_hdr_pack= bf_memreq(IP_MIN_HDR_SIZE);
	ip_hdr= (ip_hdr_t *)ptr2acc_data(ip_hdr_pack);

	udp_hdr_pack= bf_memreq(UDP_HDR_SIZE);
	udp_hdr= (udp_hdr_t *)ptr2acc_data(udp_hdr_pack);

	if (flags & NWUO_RWDATALL)
	{
		pack= bf_packIffLess(pack, UDP_IO_HDR_SIZE);
		udp_io_hdr= (udp_io_hdr_t *)ptr2acc_data(pack);
		ip_opt_size= udp_io_hdr->uih_ip_opt_len;
		user_data_size= udp_io_hdr->uih_data_len;
		if (UDP_IO_HDR_SIZE+ip_opt_size>udp_fd->uf_wr_count)
		{
			bf_afree(ip_hdr_pack);
			bf_afree(udp_hdr_pack);
			bf_afree(pack);
			reply_thr_get (udp_fd, EINVAL, FALSE);
#if DEBUG
 { where(); printf("\n"); }
#endif
			return;
		}
		if (ip_opt_size & 3)
		{
			bf_afree(ip_hdr_pack);
			bf_afree(udp_hdr_pack);
			bf_afree(pack);
			reply_thr_get (udp_fd, EFAULT, FALSE);
#if DEBUG
 { where(); printf("\n"); }
#endif
			return;
		}
		if (ip_opt_size)
			ip_opt_pack= bf_cut(pack, UDP_IO_HDR_SIZE, ip_opt_size);
		else
			ip_opt_pack= 0;
		user_data_size= udp_fd->uf_wr_count-UDP_IO_HDR_SIZE-
			ip_opt_size;
		user_data= bf_cut(pack, UDP_IO_HDR_SIZE+ip_opt_size, 
			user_data_size);
		bf_afree(pack);
	}
	else
	{
		udp_io_hdr= 0;
		ip_opt_size= 0;
		user_data_size= udp_fd->uf_wr_count;
		ip_opt_pack= 0;
		user_data= pack;
	}

	ip_hdr->ih_vers_ihl= (IP_MIN_HDR_SIZE+ip_opt_size) >> 2;
	ip_hdr->ih_tos= UDP_TOS;
	ip_hdr->ih_flags_fragoff= HTONS(UDP_IP_FLAGS);
	ip_hdr->ih_ttl= UDP_TTL;
	ip_hdr->ih_proto= IPPROTO_UDP;
	if (flags & NWUO_RA_SET)
	{
#if DEBUG
 { where(); printf("NWUO_RA_SET\n"); }
#endif
		ip_hdr->ih_dst= udp_fd->uf_udpopt.nwuo_remaddr;
	}
	else
	{
assert (udp_io_hdr);
		ip_hdr->ih_dst= udp_io_hdr->uih_dst_addr;
	}
#if DEBUG & 256
 { where(); printf("ih_dst= "); writeIpAddr(ip_hdr->ih_dst); printf("\n"); }
#endif

	if ((flags & NWUO_LOCPORT_MASK) != NWUO_LP_ANY)
		udp_hdr->uh_src_port= udp_fd->uf_udpopt.nwuo_locport;
	else
	{
assert (udp_io_hdr);
		udp_hdr->uh_src_port= udp_io_hdr->uih_src_port;
	}

	if (flags & NWUO_RP_SET)
		udp_hdr->uh_dst_port= udp_fd->uf_udpopt.nwuo_remport;
	else
	{
assert (udp_io_hdr);
		udp_hdr->uh_dst_port= udp_io_hdr->uih_dst_port;
	}

	udp_hdr->uh_length= htons(UDP_HDR_SIZE+user_data_size);
	udp_hdr->uh_chksum= 0;

	udp_hdr_pack->acc_next= user_data;
	chksum= pack_oneCsum(udp_hdr_pack);
	chksum= oneC_sum(chksum, (u16_t *)&udp_fd->uf_port->up_ipaddr,
		sizeof(ipaddr_t));
	chksum= oneC_sum(chksum, (u16_t *)&ip_hdr->ih_dst, sizeof(ipaddr_t));
	u16[0]= 0;
	u16[1]= IPPROTO_UDP;
	chksum= oneC_sum(chksum, (u16_t *)u16, sizeof(u16));
	chksum= oneC_sum(chksum, (u16_t *)&udp_hdr->uh_length, sizeof(u16_t));
	if (~chksum)
		chksum= ~chksum;
	udp_hdr->uh_chksum= chksum;
	
	if (ip_opt_pack)
	{
		ip_opt_pack= bf_packIffLess(ip_opt_pack, ip_opt_size);
		ip_opt_pack->acc_next= udp_hdr_pack;
		udp_hdr_pack= ip_opt_pack;
	}
	ip_hdr_pack->acc_next= udp_hdr_pack;

assert (!udp_port->up_wr_pack);
assert (!(udp_port->up_flags & UPF_WRITE_IP));

	udp_port->up_wr_pack= ip_hdr_pack;
	udp_port->up_flags |= UPF_WRITE_IP;
#if DEBUG & 256
 { where(); printf("calling ip_write(%d, %d)\n", udp_port->up_ipfd,
	bf_bufsize(ip_hdr_pack)); }
#endif
	result= ip_write(udp_port->up_ipfd, bf_bufsize(ip_hdr_pack));
#if DEBUG & 256
 { where(); printf("ip_write done\n"); }
#endif
	if (result == NW_SUSPEND)
	{
		udp_port->up_flags |= UPF_WRITE_SP;
		udp_fd->uf_flags |= UFF_WRITE_IP;
		udp_port->up_write_fd= udp_fd;
	}
	else if (result<0)
		reply_thr_get(udp_fd, result, FALSE);
	else
		reply_thr_get (udp_fd, udp_fd->uf_wr_count, FALSE);
#if DEBUG & 256
 { where(); printf("\n"); }
#endif
}

PRIVATE u16_t pack_oneCsum(pack)
acc_t *pack;
{
	u16_t prev;
	int odd_byte;
	char *data_ptr;
	int length;
	char byte_buf[2];

	assert (pack);

	prev= 0;

	odd_byte= FALSE;
	for (; pack; pack= pack->acc_next)
	{
		
		data_ptr= ptr2acc_data(pack);
		length= pack->acc_length;

		if (!length)
			continue;
		if (odd_byte)
		{
			byte_buf[1]= *data_ptr;
			prev= oneC_sum(prev, (u16_t *)byte_buf, 2);
			data_ptr++;
			length--;
			odd_byte= FALSE;
		}
		if (length & 1)
		{
			odd_byte= TRUE;
			length--;
			byte_buf[0]= data_ptr[length];
		}
		if (!length)
			continue;
		prev= oneC_sum (prev, (u16_t *)data_ptr, length);
	}
	if (odd_byte)
		prev= oneC_sum (prev, (u16_t *)byte_buf, 1);
	return prev;
}

PRIVATE void udp_restart_write_port(udp_port )
udp_port_t *udp_port;
{
	udp_fd_t *udp_fd;
	int i;

assert (!udp_port->up_wr_pack);
assert (!(udp_port->up_flags & (UPF_WRITE_IP|UPF_WRITE_SP)));

	while (udp_port->up_flags & UPF_MORE2WRITE)
	{
		udp_port->up_flags &= ~UPF_MORE2WRITE;

		for (i= 0, udp_fd= udp_port->up_next_fd; i<UDP_FD_NR;
			i++, udp_fd++)
		{
			if (udp_fd == &udp_fd_table[UDP_FD_NR])
				udp_fd= udp_fd_table;

			if (!(udp_fd->uf_flags & UFF_INUSE))
				continue;
			if (!(udp_fd->uf_flags & UFF_WRITE_IP))
				continue;
			if (udp_fd->uf_port != udp_port)
				continue;
			restart_write_fd(udp_fd);
			if (udp_port->up_flags & UPF_WRITE_IP)
			{
				udp_port->up_next_fd= udp_fd+1;
				udp_port->up_flags |= UPF_MORE2WRITE;
				return;
			}
		}
	}
}

PUBLIC int udp_cancel(fd, which_operation)
int fd;
int which_operation;
{
	udp_fd_t *udp_fd;

#if DEBUG
 { where(); printf("udp_cancel(%d, %d)\n", fd, which_operation); }
#endif
	udp_fd= &udp_fd_table[fd];

	switch (which_operation)
	{
	case SR_CANCEL_READ:
assert (udp_fd->uf_flags & UFF_READ_IP);
		udp_fd->uf_flags &= ~UFF_READ_IP;
		reply_thr_put(udp_fd, EINTR, FALSE);
		break;
	case SR_CANCEL_WRITE:
assert (udp_fd->uf_flags & UFF_WRITE_IP);
		udp_fd->uf_flags &= ~UFF_WRITE_IP;
		if (udp_fd->uf_port->up_write_fd == udp_fd)
			udp_fd->uf_port->up_write_fd= NULL;
		reply_thr_get(udp_fd, EINTR, FALSE);
		break;
	case SR_CANCEL_IOCTL:
assert (udp_fd->uf_flags & UFF_IOCTL_IP);
		udp_fd->uf_flags &= ~UFF_IOCTL_IP;
		reply_thr_get(udp_fd, EINTR, TRUE);
		break;
	default:
		ip_panic(( "got unknown cancel request" ));
	}
	return NW_OK;
}

PRIVATE void udp_buffree (priority, reqsize)
int priority;
size_t reqsize;
{
	int i;
	time_t curr_tim;


	if (priority <UDP_PRI_EXP_FDBUFS)
		return;

	curr_tim= get_time();
	for (i=0; i<UDP_FD_NR; i++)
	{
		if (!(udp_fd_table[i].uf_flags & UFF_INUSE) )
			continue;
		if (udp_fd_table[i].uf_rd_buf &&
			udp_fd_table[i].uf_exp_tim < curr_tim)
		{
			bf_afree(udp_fd_table[i].uf_rd_buf);
			udp_fd_table[i].uf_rd_buf= 0;
			if (bf_free_buffsize >= reqsize)
				return;
		}
	}

	if (priority <UDP_PRI_FDBUFS)
		return;

	for (i=0; i<UDP_FD_NR; i++)
	{
		if (!(udp_fd_table[i].uf_flags & UFF_INUSE))
			continue;
		if (udp_fd_table[i].uf_rd_buf)
		{
			bf_afree(udp_fd_table[i].uf_rd_buf);
			udp_fd_table[i].uf_rd_buf= 0;
			if (bf_free_buffsize >= reqsize)
				return;
		}
	}
}

⌨️ 快捷键说明

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