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