📄 udp.c
字号:
*(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 + -