📄 tcp_send.c
字号:
{ tcp_conn->tc_rtt= tcp_conn->tc_rtt/2+1;assert (tcp_conn->tc_rtt); } if (seg_ack == tcp_conn->tc_SND_NXT) tcp_conn->tc_ett= 0; else { tcp_conn->tc_ett += (seg_ack-tcp_conn-> tc_SND_UNA) * tcp_conn->tc_rtt / (tcp_conn->tc_SND_NXT-tcp_conn-> tc_SND_UNA); } queue_lo= tcp_conn->tc_SND_UNA; queue_hi= tcp_conn->tc_SND_NXT; tcp_conn->tc_SND_UNA= seg_ack; if (tcp_Lmod4G(tcp_conn->tc_SND_TRM, seg_ack)) tcp_conn->tc_SND_TRM= seg_ack; if (tcp_Lmod4G(tcp_conn->tc_snd_cwnd, seg_ack)) { tcp_conn->tc_snd_cwnd= seg_ack;#if DEBUG & 256 { where(); printf("snd_cwnd is now %d\n", tcp_conn->tc_snd_cwnd); }#endif } if (queue_lo == tcp_conn->tc_ISS) queue_lo++; if (tcp_conn->tc_flags & TCF_FIN_SENT) { if (seg_ack == queue_hi) seg_ack--; if (queue_lo == queue_hi) queue_lo--; queue_hi--; } offset= seg_ack - queue_lo; size= queue_hi - seg_ack; old_pack= tcp_conn->tc_send_data; tcp_conn->tc_send_data= 0; if (!size) { new_pack= 0; tcp_conn->tc_snd_cwnd= tcp_conn->tc_SND_UNA + 2*tcp_conn->tc_mss; /* Reset window if a write is completed */#if DEBUG & 256 { where(); printf("snd_cwnd is now %d\n", tcp_conn->tc_snd_cwnd); }#endif } else new_pack= bf_cut(old_pack, offset, size); bf_afree(old_pack); tcp_conn->tc_send_data= new_pack;assert (tcp_check_conn(tcp_conn)); if (tcp_conn->tc_state == TCS_CLOSED) { { where(); printf("connection closed while inuse\n"); } return; } if (tcp_conn->tc_ett) {#if DEBUG & 256 { where(); printf("setting major_to\n"); }#endif clck_timer(&tcp_conn->tc_major_timer, tcp_conn->tc_ett + tcp_conn->tc_rtt, major_to, tcp_conn-tcp_conn_table); } } mss= tcp_conn->tc_mss; cthresh= tcp_conn->tc_snd_cthresh; mss2= 2*mss; if (new_win < mss2) { cwnd= 0; if (new_win >= mss) incr= mss; else { if (new_win) incr= new_win; else incr= 1; } } else { cwnd= tcp_conn->tc_snd_cwnd - tcp_conn->tc_SND_UNA; incr= mss2; if (cwnd+incr > new_win) { incr= mss; if (cwnd+incr > new_win) incr= 0; } }assert (cthresh >= mss2); if (incr && cwnd+incr > cthresh) { incr -= mss; if (incr && cwnd+incr > cthresh) incr -= mss; } if (cwnd+incr+mss>cthresh && cthresh<tcp_conn->tc_snd_wnd) tcp_conn->tc_snd_cthresh += tcp_conn->tc_snd_cinc; tcp_conn->tc_snd_cwnd= tcp_conn->tc_SND_UNA+cwnd+incr;#if DEBUG & 256 { where(); printf("snd_cwnd is now 0x%x\n", tcp_conn->tc_snd_cwnd); }#endif if (tcp_Gmod4G(tcp_conn->tc_SND_TRM, tcp_conn->tc_snd_cwnd)) tcp_conn->tc_SND_TRM= tcp_conn->tc_snd_cwnd; if (tcp_Gmod4G(tcp_conn->tc_snd_cwnd, tcp_conn->tc_SND_TRM) && tcp_Gmod4G(tcp_conn->tc_SND_NXT, tcp_conn->tc_SND_TRM)) tcp_restart_write(tcp_conn); if (tcp_conn->tc_writeuser) tcp_restart_fd_write(tcp_conn);assert (tcp_check_conn(tcp_conn));}PUBLIC void tcp_restart_fd_write(tcp_conn)tcp_conn_t *tcp_conn;{ tcp_fd_t *urgent_fd, *normal_fd, *shutdown_fd, *new_fd, *hi_fd, *tcp_fd; int closed_connection;#if DEBUG & 256 { where(); printf("in restart_fd_write\n"); }#endif do { tcp_fd= tcp_conn->tc_writeuser; closed_connection= (tcp_conn->tc_state == TCS_CLOSED); if (tcp_fd) fd_write(tcp_fd); else tcp_fd= &tcp_fd_table[TCP_FD_NR-1]; if (!closed_connection && tcp_conn->tc_state == TCS_CLOSED) {#if DEBUG { where(); printf("connection closed while inuse\n"); }#endif return; } if (!tcp_conn->tc_writeuser) { urgent_fd= 0; normal_fd= 0; shutdown_fd= 0; for (new_fd= tcp_fd+1, hi_fd= &tcp_fd_table[TCP_FD_NR]; new_fd<hi_fd; new_fd++) switch_write_fd(tcp_conn, new_fd, &urgent_fd, &normal_fd, &shutdown_fd); for (new_fd= tcp_fd_table, hi_fd= tcp_fd+1; new_fd < hi_fd; new_fd++) switch_write_fd(tcp_conn, new_fd, &urgent_fd, &normal_fd, &shutdown_fd); if (urgent_fd) tcp_fd= urgent_fd; else if (normal_fd) tcp_fd= normal_fd; else tcp_fd= shutdown_fd; tcp_conn->tc_writeuser= tcp_fd; } else return; } while (tcp_conn->tc_writeuser);}PRIVATE void switch_write_fd (tcp_conn, new_fd, ref_urg_fd, ref_norm_fd, ref_shut_fd)tcp_conn_t *tcp_conn;tcp_fd_t *new_fd, **ref_urg_fd, **ref_norm_fd, **ref_shut_fd;{ if (!(new_fd->tf_flags & TFF_INUSE)) return; if (new_fd->tf_conn != tcp_conn) return; if (new_fd->tf_flags & TFF_WRITE_IP) if (new_fd->tf_flags & TFF_WR_URG) { if (!*ref_urg_fd) *ref_urg_fd= new_fd; } else { if (!*ref_norm_fd) *ref_norm_fd= new_fd; } else if ((new_fd->tf_flags & TFF_IOCTL_IP) && new_fd->tf_ioreq == NWIOTCPSHUTDOWN) if (!*ref_shut_fd) *ref_shut_fd= new_fd;}PRIVATE void fd_write (tcp_fd)tcp_fd_t *tcp_fd;{ tcp_conn_t *tcp_conn; int urg, push; u32_t max_seq; size_t max_count, max_trans, write_count, send_count; acc_t *data, *tmp_acc, *send_data; int restart_write; restart_write= FALSE; tcp_conn= tcp_fd->tf_conn; if (tcp_fd->tf_flags & TFF_IOCTL_IP) {assert (tcp_fd->tf_ioreq == NWIOTCPSHUTDOWN); if (tcp_conn->tc_state == TCS_CLOSED) { tcp_conn->tc_writeuser= 0; tcp_reply_ioctl (tcp_fd, tcp_conn->tc_error); return; } tcp_conn->tc_writeuser= 0; tcp_reply_ioctl (tcp_fd, NW_OK); tcp_shutdown (tcp_conn); return; } assert (tcp_fd->tf_flags & TFF_WRITE_IP); if (tcp_conn->tc_state == TCS_CLOSED) { tcp_conn->tc_writeuser= 0;#if DEBUG & 256 { where(); printf("calling tcp_reply_write()\n"); }#endif if (tcp_fd->tf_write_offset) tcp_reply_write(tcp_fd, tcp_fd->tf_write_offset); else tcp_reply_write(tcp_fd, tcp_conn->tc_error); return; }assert (!(tcp_conn->tc_flags & TCF_FIN_SENT));assert (tcp_conn->tc_SND_UNA != tcp_conn->tc_ISS); urg= (tcp_fd->tf_flags & TFF_WR_URG); push= (tcp_fd->tf_flags & TFF_PUSH_DATA);#if DEBUG & 256 if (push) { where(); printf("pushing data\n"); }#endif max_seq= tcp_conn->tc_SND_UNA + tcp_conn->tc_snd_wnd; if (urg) max_seq += tcp_conn->tc_urg_wnd; max_count= max_seq - tcp_conn->tc_SND_UNA; max_trans= max_seq - tcp_conn->tc_SND_NXT; if (tcp_fd->tf_write_count <= max_trans) write_count= tcp_fd->tf_write_count; else if (!urg && max_trans < max_count/2) return; else write_count= max_trans; if (write_count) { data= (*tcp_fd->tf_get_userdata) (tcp_fd->tf_srfd, tcp_fd->tf_write_offset, write_count, FALSE); if (tcp_conn->tc_state == TCS_CLOSED) { { where(); printf("connection closed while inuse\n"); } if (data) bf_afree(data); return; } if (!data) { tcp_conn->tc_writeuser= 0;assert(data);#if DEBUG { where(); printf("calling tcp_reply_write()\n"); }#endif if (tcp_fd->tf_write_offset) tcp_reply_write(tcp_fd, tcp_fd->tf_write_offset); else tcp_reply_write(tcp_fd, EFAULT); return; } tcp_fd->tf_write_offset += write_count; tcp_fd->tf_write_count -= write_count; send_data= tcp_conn->tc_send_data; tcp_conn->tc_send_data= 0; send_data= bf_append(send_data, data); if (tcp_conn->tc_state == TCS_CLOSED) { { where(); printf("connection closed while inuse\n"); } bf_afree(send_data); return; } tcp_conn->tc_send_data= send_data; tcp_conn->tc_SND_NXT += write_count; if (urg) tcp_conn->tc_SND_UP= tcp_conn->tc_SND_NXT; if (push && !tcp_fd->tf_write_count) tcp_conn->tc_SND_PSH= tcp_conn->tc_SND_NXT;assert (tcp_check_conn(tcp_conn)); if (tcp_Gmod4G(tcp_conn->tc_SND_NXT, tcp_conn->tc_SND_TRM) && tcp_Lmod4G(tcp_conn->tc_SND_TRM, tcp_conn->tc_snd_cwnd)) restart_write= TRUE; } if (!tcp_fd->tf_write_count) { tcp_conn->tc_writeuser= 0;#if DEBUG & 256 { where(); printf("calling tcp_reply_write()\n"); }#endif tcp_reply_write(tcp_fd, tcp_fd->tf_write_offset); } if (restart_write) tcp_restart_write(tcp_conn);}PUBLIC void tcp_shutdown(tcp_conn)tcp_conn_t *tcp_conn;{ int closed_connection;#if DEBUG & 256 { where(); printf("in tcp_shutdown\n"); }#endif if (tcp_conn->tc_flags & TCF_FIN_SENT) return; tcp_conn->tc_flags |= TCF_FIN_SENT;#if DEBUG & 256 { where(); printf("tcp_conn_table[%d].tc_flags= 0x%x\n", tcp_conn-tcp_conn_table, tcp_conn->tc_flags); }#endif tcp_conn->tc_SND_NXT++; switch (tcp_conn->tc_state) { case TCS_CLOSED: case TCS_LISTEN: case TCS_SYN_SENT: case TCS_SYN_RECEIVED:#if DEBUG & 256 { where(); printf("calling tcp_close_connection\n"); }#endif tcp_close_connection(tcp_conn, ENOTCONN); break; case TCS_ESTABLISHED: tcp_conn->tc_state= TCS_FIN_WAIT_1;#if DEBUG { where(); tcp_write_state(tcp_conn); }#endif break; case TCS_CLOSE_WAIT: tcp_conn->tc_state= TCS_LAST_ACK;#if DEBUG { where(); tcp_write_state(tcp_conn); }#endif break; } closed_connection= (tcp_conn->tc_state == TCS_CLOSED);assert (tcp_check_conn(tcp_conn));#if DEBUG & 256 { where(); printf("calling tcp_restart_write\n"); }#endif tcp_restart_write(tcp_conn);}PUBLIC void tcp_set_time_wait_timer(tcp_conn)tcp_conn_t *tcp_conn;{ assert (tcp_conn->tc_state == TCS_TIME_WAIT);#if DEBUG & 256 { where(); printf("tcp_set_time_wait_timer, ttl= %d\n", tcp_conn->tc_ttl); }#endif clck_timer(&tcp_conn->tc_time_wait_timer, get_time() + tcp_conn->tc_ttl * 2L * HZ, time_wait_to, tcp_conn- tcp_conn_table);}PUBLIC void tcp_set_ack_timer (tcp_conn)tcp_conn_t *tcp_conn;{ if (tcp_conn->tc_flags & TCF_ACK_TIMER_SET) return; tcp_conn->tc_flags |= TCF_ACK_TIMER_SET;#if DEBUG & 256 { where(); printf("tcp_conn_table[%d].tc_flags= 0x%x\n", tcp_conn-tcp_conn_table, tcp_conn->tc_flags); }#endif#if DEBUG & 256 { where(); printf("setting ack_timer\n"); };#endif clck_timer(&tcp_conn->tc_ack_timer, get_time() + TCP_ACK_DELAY, ack_to, tcp_conn-tcp_conn_table);}/*tcp_close_connection*/PUBLIC void tcp_close_connection(tcp_conn, error)tcp_conn_t *tcp_conn;int error;{#if DEBUG & 256 { where(); printf("closing connection\n"); }#endifassert (tcp_check_conn(tcp_conn));assert (tcp_conn->tc_flags & TCF_INUSE); tcp_conn->tc_error= error; if (tcp_conn->tc_state == TCS_CLOSED) return; clck_untimer (&tcp_conn->tc_major_timer); clck_untimer (&tcp_conn->tc_minor_timer);#if DEBUG & 256 { where(); printf("clearing ack_timer\n"); }#endif clck_untimer (&tcp_conn->tc_ack_timer); clck_untimer (&tcp_conn->tc_time_wait_timer); tcp_conn->tc_state= TCS_CLOSED;#if DEBUG & 16 { where(); tcp_write_state(tcp_conn); }#endif if (tcp_conn->tc_readuser) tcp_restart_fd_read (tcp_conn);assert (!tcp_conn->tc_readuser); if (tcp_conn->tc_writeuser) tcp_restart_fd_write (tcp_conn);assert (!tcp_conn->tc_writeuser); if (tcp_conn->tc_connuser) {#if DEBUG & 256 { where(); printf("closing and connuser present\n"); }#endif tcp_restart_connect (tcp_conn->tc_connuser); }assert (!tcp_conn->tc_connuser); if (tcp_conn->tc_rcvd_data) { bf_afree(tcp_conn->tc_rcvd_data); tcp_conn->tc_rcvd_data= 0; } tcp_conn->tc_flags &= ~TCF_FIN_RECV;#if DEBUG & 256 { where(); printf("tcp_conn_table[%d].tc_flags= 0x%x\n", tcp_conn-tcp_conn_table, tcp_conn->tc_flags); }#endif tcp_conn->tc_RCV_LO= tcp_conn->tc_RCV_NXT; if (tcp_conn->tc_rcv_queue) { bf_afree(tcp_conn->tc_rcv_queue); tcp_conn->tc_rcv_queue= 0; } if (tcp_conn->tc_send_data) {#if DEBUG & 256 { where(); printf("releasing data\n"); }#endif#if DEBUG & 256 { where(); printf("SND_TRM= 0x%lx, tc_SND_NXT= 0x%lx, SND_UNA= 0x%lx\n", tcp_conn->tc_SND_TRM, tcp_conn->tc_SND_NXT, tcp_conn->tc_SND_UNA); }#endif bf_afree(tcp_conn->tc_send_data); tcp_conn->tc_send_data= 0; tcp_conn->tc_SND_TRM= tcp_conn->tc_SND_NXT= tcp_conn->tc_SND_UNA; } tcp_conn->tc_SND_TRM= tcp_conn->tc_SND_NXT= tcp_conn->tc_SND_UNA; if (tcp_conn->tc_remipopt) { bf_afree(tcp_conn->tc_remipopt); tcp_conn->tc_remipopt= 0; } if (tcp_conn->tc_remtcpopt) { bf_afree(tcp_conn->tc_remtcpopt); tcp_conn->tc_remtcpopt= 0; } if (tcp_conn->tc_frag2send) { bf_afree(tcp_conn->tc_frag2send); tcp_conn->tc_remtcpopt= 0; } /* clear all flags but TCF_INUSE */ tcp_conn->tc_flags &= TCF_INUSE;#if DEBUG & 256 { where(); printf("tcp_conn_table[%d].tc_flags= 0x%x\n", tcp_conn-tcp_conn_table, tcp_conn->tc_flags); }#endifassert (tcp_check_conn(tcp_conn));}PRIVATE void ack_to(conn, timer)int conn;struct timer *timer;{ tcp_conn_t *tcp_conn;#if DEBUG & 256 { where(); printf("in ack_to\n"); }#endif tcp_conn= &tcp_conn_table[conn]; assert (&tcp_conn->tc_ack_timer == timer); assert (tcp_conn->tc_flags & TCF_ACK_TIMER_SET); tcp_conn->tc_flags &= ~TCF_ACK_TIMER_SET;#if DEBUG & 256 { where(); printf("tcp_conn_table[%d].tc_flags= 0x%x\n", tcp_conn-tcp_conn_table, tcp_conn->tc_flags); }#endif tcp_conn->tc_flags |= TCF_SEND_ACK;#if DEBUG & 256 { where(); printf("tcp_conn_table[%d].tc_flags= 0x%x\n", tcp_conn-tcp_conn_table, tcp_conn->tc_flags); }#endif tcp_restart_write (tcp_conn);}PRIVATE void time_wait_to(conn, timer)int conn;struct timer *timer;{ tcp_conn_t *tcp_conn; tcp_conn= &tcp_conn_table[conn]; assert (tcp_conn->tc_state == TCS_TIME_WAIT); assert (&tcp_conn->tc_time_wait_timer == timer);#if DEBUG { where(); printf("calling tcp_close_connection\n"); }#endif tcp_close_connection (tcp_conn, ENOCONN);}PUBLIC void tcp_zero_wnd_to(conn, timer)int conn;struct timer *timer;{ tcp_conn_t *tcp_conn;#if DEBUG & 256 { where(); printf("in tcp_zero_wnd_to\n"); }#endif tcp_conn= &tcp_conn_table[conn]; assert (&tcp_conn->tc_major_timer == timer); assert (tcp_conn->tc_0wnd_to); tcp_conn->tc_0wnd_to *= 2; tcp_conn->tc_SND_TRM= tcp_conn->tc_SND_UNA; tcp_restart_write (tcp_conn);}#if DEBUGPRIVATE void tcp_delay_to(ref, timer)int ref;timer_t *timer;{ tcp_port_t *tcp_port;assert(ref >= 0 && ref < TCP_PORT_NR); tcp_port= &tcp_port_table[ref];assert(timer == &tcp_port->tp_delay_tim); tcp_port->tp_flags &= ~(TPF_WRITE_SP|TPF_WRITE_IP); tcp_port->tp_flags |= TPF_DELAY_TCP; if (tcp_port->tp_flags & TPF_MORE2WRITE) {#if DEBUG & 256{ where(); printf("calling tcp_restart_write_port\n"); }#endif write2port(tcp_port, tcp_port->tp_pack); }}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -