📄 tcp_recv.c
字号:
{ where(); printf("calling tcp_close_connection\n"); }#endif tcp_close_connection(tcp_conn, ECONNRESET); if (connuser) (void)tcp_su4listen(connuser); break; }#if DEBUG { where(); printf("calling tcp_close_connection\n"); }#endif tcp_close_connection(tcp_conn, ECONNRESET); break; }/* !ACK ? discard packet exit*/#if DEBUG & 256 { where(); printf("\n"); }#endif if (!(tcp_hdr_flags & THF_ACK)) break;/* state == SYN-RECEIVED ? SND.UNA <= SEG.ACK <= SND.NXT ? state= ESTABLISHED : <SEG=SEG.ACK><CTL=RST> exit*/#if DEBUG & 256 { where(); printf("\n"); }#endif if (tcp_conn->tc_state == TCS_SYN_RECEIVED) { if (tcp_LEmod4G(tcp_conn->tc_SND_UNA, seg_ack) && tcp_LEmod4G(seg_ack, tcp_conn->tc_SND_NXT)) { tcp_conn->tc_state= TCS_ESTABLISHED;assert (tcp_check_conn(tcp_conn));#if DEBUG & 2 { where(); tcp_write_state(tcp_conn); }#endifassert(tcp_conn->tc_connuser); tcp_restart_connect(tcp_conn->tc_connuser); if (tcp_conn->tc_state == TCS_CLOSED) {#if DEBUG { where(); printf("connection closed while inuse\n"); }#endif break; } } else { create_RST (tcp_conn, ip_hdr, tcp_hdr); tcp_restart_write(tcp_conn); break; } }/* state == ESTABLISHED || state == FIN-WAIT-1 || state == FIN-WAIT-2 || state == CLOSE-WAIT || state == LAST-ACK || state == TIME_WAIT || state == CLOSING ? SND.UNA < SEG.ACK <= SND.NXT ? SND.UNA= SEG.ACK reply "send ok" SND.WL1 < SEG.SEQ || (SND.WL1 == SEG.SEQ && SND.WL2 <= SEG.ACK ? SND.WND= SEG.WND SND.Wl1= SEG.SEQ SND.WL2= SEG.ACK SEG.ACK <= SND.UNA ? ignore ACK SEG.ACK > SND.NXT ? <SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK> discard packet exit*/#if DEBUG & 256 { where(); printf("\n"); }#endif if (tcp_conn->tc_state == TCS_ESTABLISHED || tcp_conn->tc_state == TCS_FIN_WAIT_1 || tcp_conn->tc_state == TCS_FIN_WAIT_2 || tcp_conn->tc_state == TCS_CLOSE_WAIT || tcp_conn->tc_state == TCS_LAST_ACK || tcp_conn->tc_state == TCS_TIME_WAIT || tcp_conn->tc_state == TCS_CLOSING) { if (tcp_LEmod4G(tcp_conn->tc_SND_UNA, seg_ack) && tcp_LEmod4G(seg_ack, tcp_conn-> tc_SND_NXT)) { if (tcp_Lmod4G(tcp_conn->tc_SND_WL1, seg_seq) || (tcp_conn-> tc_SND_WL1==seg_seq && tcp_LEmod4G(tcp_conn-> tc_SND_WL2, seg_ack))) { if (seg_wnd > TCP_MAX_WND_SIZE) seg_wnd= TCP_MAX_WND_SIZE; if (!seg_wnd) seg_wnd++; tcp_conn->tc_SND_WL1= seg_seq; tcp_conn->tc_SND_WL2= seg_ack;#if SUN_0WND_BUG if (seg_wnd && seg_ack == tcp_conn-> tc_SND_UNA && tcp_LEmod4G( seg_ack + seg_wnd, tcp_conn->tc_SND_NXT) && tcp_LEmod4G(seg_ack + seg_wnd, tcp_conn->tc_snd_cwnd)) seg_wnd= 0;#endif } else { seg_wnd= tcp_conn->tc_mss; /* assume 1 segment if not a valid * window */ } tcp_release_retrans(tcp_conn, seg_ack, seg_wnd); if (tcp_conn->tc_state == TCS_CLOSED) {#if DEBUG { where(); printf("connection closed while inuse\n"); }#endif break; } } else if (tcp_Gmod4G(seg_ack, tcp_conn->tc_SND_NXT)) { tcp_set_ack_timer(tcp_conn);#if DEBUG { where(); printf("got an ack of something I haven't send\n"); printf("seg_ack= %lu, SND_NXT= %lu\n", seg_ack, tcp_conn->tc_SND_NXT); }#endif break; }#if DEBUG & 256 if (!seg_wnd) { where(); printf("SND_UNA= %lu, SND_NXT= %lu\n", tcp_conn->tc_SND_UNA, tcp_conn->tc_SND_NXT); }#endif if (!seg_wnd && /* tcp_GEmod4G(seg_wnd, tcp_conn->tc_SND_UNA) && */ tcp_Lmod4G(tcp_conn->tc_SND_UNA, tcp_conn->tc_SND_NXT)) { /* zero window */#if DEBUG & 256 { where(); printf("setting 0wnd_to\n"); }#endif clck_untimer(&tcp_conn->tc_minor_timer); if (!tcp_conn->tc_0wnd_to) {assert (tcp_conn->tc_rtt); tcp_conn->tc_0wnd_to= tcp_conn->tc_rtt; } clck_timer(&tcp_conn->tc_major_timer, get_time()+tcp_conn->tc_0wnd_to, tcp_zero_wnd_to, tcp_conn- tcp_conn_table); } else {#if DEBUG & 256 { where(); printf("not setting 0wnd_to\n"); }#endif if (tcp_conn->tc_0wnd_to) {#if DEBUG & 256 { where(); printf("resetting 0wnd_to\n"); }#endif tcp_conn->tc_0wnd_to= 0; tcp_conn->tc_SND_TRM= tcp_conn->tc_SND_UNA; clck_untimer(&tcp_conn-> tc_major_timer); tcp_restart_write (tcp_conn); } } }/* state == FIN-WAIT-1 && FIN acknowledged ? state= FIN-WAIT-2 state == CLOSING && FIN acknowledged ? state= TIME-WAIT state == LAST-ACK && FIN acknowledged ? state= CLOSED state == TIME-WAIT ? <SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK> restart 2 MSL timeout*/#if DEBUG & 256 { where(); printf("\n"); }#endif if (tcp_conn->tc_SND_UNA == tcp_conn->tc_SND_NXT) { switch (tcp_conn->tc_state) { case TCS_FIN_WAIT_1: tcp_conn->tc_state= TCS_FIN_WAIT_2;assert (tcp_check_conn(tcp_conn));#if DEBUG { where(); tcp_write_state(tcp_conn); }#endif break; case TCS_CLOSING: tcp_conn->tc_state= TCS_TIME_WAIT;assert (tcp_check_conn(tcp_conn));#if DEBUG { where(); tcp_write_state(tcp_conn); }#endif tcp_set_time_wait_timer(tcp_conn); break; case TCS_LAST_ACK:#if DEBUG & 256 { where(); printf("calling tcp_close_connection\n"); }#endif tcp_close_connection(tcp_conn, ENOCONN); break; } if (!tcp_conn->tc_mainuser) { tcp_close_connection(tcp_conn, ENOCONN); break; } } if (tcp_conn->tc_state == TCS_TIME_WAIT) { tcp_set_ack_timer(tcp_conn); tcp_set_time_wait_timer(tcp_conn); }/* process data...*/#if DEBUG & 256 { where(); printf("\n"); }#endif tcp_extract_ipopt(tcp_conn, ip_hdr); tcp_extract_tcpopt(tcp_conn, tcp_hdr); if (data_length) { if (tcp_LEmod4G(seg_seq, tcp_conn->tc_RCV_NXT)) process_data (tcp_conn, tcp_hdr, tcp_hdr_len, tcp_pack, data_length); else process_advanced_data (tcp_conn, tcp_hdr, tcp_hdr_len, tcp_pack, data_length); if (tcp_conn->tc_state == TCS_CLOSED) break; 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); if (tcp_conn->tc_state == TCS_CLOSED) break; }/* FIN ? reply pending receives advace RCV.NXT over the FIN <SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK> state == SYN-RECEIVED || state == ESTABLISHED ? state= CLOSE-WAIT state == FIN-WAIT-1 ? state= CLOSING state == FIN-WAIT-2 ? state= TIME-WAIT state == TIME-WAIT ? restart the TIME-WAIT timer exit*/#if DEBUG & 256 { where(); printf("\n"); }#endif if ((tcp_hdr_flags & THF_FIN) && tcp_LEmod4G(seg_seq, tcp_conn->tc_RCV_NXT)) { switch (tcp_conn->tc_state) { case TCS_SYN_RECEIVED: break; case TCS_ESTABLISHED: tcp_conn->tc_state= TCS_CLOSE_WAIT;assert (tcp_check_conn(tcp_conn));#if DEBUG { where(); tcp_write_state(tcp_conn); }#endif break; case TCS_FIN_WAIT_1: tcp_conn->tc_state= TCS_CLOSING;assert (tcp_check_conn(tcp_conn));#if DEBUG { where(); tcp_write_state(tcp_conn); }#endif break; case TCS_FIN_WAIT_2: tcp_conn->tc_state= TCS_TIME_WAIT;assert (tcp_check_conn(tcp_conn));#if DEBUG { where(); tcp_write_state(tcp_conn); }#endif /* drops through */ case TCS_TIME_WAIT: tcp_set_time_wait_timer(tcp_conn); break; } if (!(tcp_conn->tc_flags & TCF_FIN_RECV)) { tcp_conn->tc_RCV_NXT++; 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_set_ack_timer(tcp_conn); if (tcp_conn->tc_readuser) tcp_restart_fd_read(tcp_conn); } break; default: printf("unknown state: tcp_conn->tc_state== %d\n", tcp_conn->tc_state); break; } bf_afree(ip_pack); bf_afree(tcp_pack);}PRIVATE void process_data(tcp_conn, tcp_hdr, tcp_hdr_len, tcp_data, data_len)tcp_conn_t *tcp_conn;tcp_hdr_t *tcp_hdr;int tcp_hdr_len;acc_t *tcp_data;int data_len;{ u32_t lo_seq, hi_seq, urg_seq, seq_nr; u16_t urgptr; int tcp_hdr_flags; unsigned int offset; acc_t *all_data, *tmp_data, *rcvd_data;#if DEBUG & 256 { where(); printf("in process data\n"); }#endif seq_nr= ntohl(tcp_hdr->th_seq_nr); urgptr= ntohs(tcp_hdr->th_urgptr); while (tcp_data) {assert (tcp_check_conn(tcp_conn)); all_data= bf_cut(tcp_data, tcp_hdr_len, data_len); tcp_data= 0; lo_seq= seq_nr; tcp_hdr_flags= tcp_hdr->th_flags & TH_FLAGS_MASK; if (tcp_hdr_flags & THF_URG) { urg_seq= lo_seq+ urgptr; tcp_conn->tc_RCV_HI= tcp_conn->tc_RCV_LO+ tcp_conn->tc_rcv_wnd+tcp_conn-> tc_urg_wnd; if (tcp_GEmod4G(urg_seq, tcp_conn->tc_RCV_HI)) urg_seq= tcp_conn->tc_RCV_HI; if (tcp_Gmod4G(urg_seq, tcp_conn->tc_RCV_UP)) tcp_conn->tc_RCV_UP= urg_seq; } if (tcp_hdr_flags & THF_SYN) lo_seq++; if (tcp_hdr_flags & THF_PSH) { tcp_conn->tc_flags |= TCF_RCV_PUSH;#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 (tcp_Lmod4G(lo_seq, tcp_conn->tc_RCV_NXT)) { offset= tcp_conn->tc_RCV_NXT-lo_seq; tmp_data= bf_cut(all_data, offset, data_len- offset); bf_afree(all_data); lo_seq += offset; data_len -= offset; all_data= tmp_data; tmp_data= 0; } assert (lo_seq == tcp_conn->tc_RCV_NXT); hi_seq= lo_seq+data_len; if (tcp_Gmod4G(hi_seq, tcp_conn->tc_RCV_HI)) { data_len= tcp_conn->tc_RCV_HI-lo_seq; tmp_data= bf_cut(all_data, 0, data_len); bf_afree(all_data); all_data= tmp_data; hi_seq= lo_seq+data_len; tcp_hdr_flags &= ~THF_FIN; } assert (tcp_LEmod4G (hi_seq, tcp_conn->tc_RCV_HI));#if DEBUG & 256 { where(); printf("in process data: lo_seq= %lu, hi_seq= %lu\n", lo_seq, hi_seq); }#endif rcvd_data= tcp_conn->tc_rcvd_data; tcp_conn->tc_rcvd_data= 0; tmp_data= bf_append(rcvd_data, all_data); if (tcp_conn->tc_state == TCS_CLOSED) {#if DEBUG { where(); printf("connection closed while inuse\n"); }#endif bf_afree(tmp_data); return; } tcp_conn->tc_rcvd_data= tmp_data; tcp_conn->tc_RCV_NXT= hi_seq; assert (tcp_conn->tc_RCV_LO + bf_bufsize(tcp_conn-> tc_rcvd_data) == tcp_conn->tc_RCV_NXT); if (tcp_hdr_flags & THF_FIN) {#if DEBUG { where(); printf("got a FIN\n"); }#endif tcp_conn->tc_RCV_NXT++; tcp_conn->tc_flags |= TCF_FIN_RECV;#if DEBUG & 16 { where(); printf("tcp_conn_table[%d].tc_flags= 0x%x\n", tcp_conn-tcp_conn_table, tcp_conn->tc_flags); }#endif } tcp_set_ack_timer(tcp_conn); while (tcp_conn->tc_rcv_queue) { tmp_data= tcp_conn->tc_rcv_queue; assert (tmp_data->acc_length >= TCP_MIN_HDR_SIZE); tcp_hdr= (tcp_hdr_t *)ptr2acc_data(tmp_data); lo_seq= tcp_hdr->th_seq_nr; /* th_seq_nr is changed to host byte order */ if (tcp_Gmod4G(lo_seq, tcp_conn->tc_RCV_NXT)) break; tcp_hdr_len= (tcp_hdr->th_data_off & TH_DO_MASK) >> 2; data_len= tcp_hdr->th_chksum-tcp_hdr_len; if (tcp_LEmod4G(lo_seq+data_len, tcp_conn-> tc_RCV_NXT)) { tcp_conn->tc_rcv_queue= tmp_data-> acc_ext_link; bf_afree(tmp_data); continue; } tcp_data= tmp_data; seq_nr= tcp_hdr->th_seq_nr; urgptr= tcp_hdr->th_urgptr; break; } }assert (tcp_check_conn(tcp_conn)); if (tcp_conn->tc_readuser) tcp_restart_fd_read(tcp_conn); else if (!tcp_conn->tc_mainuser) {#if DEBUG { where(); printf("calling tcp_close_connection\n"); }#endif tcp_close_connection (tcp_conn, ENOCONN); }assert (tcp_check_conn(tcp_conn));}PRIVATE void process_advanced_data(tcp_conn, tcp_hdr, tcp_hdr_len, tcp_data, data_len)tcp_conn_t *tcp_conn;tcp_hdr_t *tcp_hdr;int tcp_hdr_len;acc_t *tcp_data;int data_len;{ u32_t seg_seq, seg_hi; u16_t seg_up; acc_t *hdr_acc, *next_acc, **tail_acc_ptr, *head_acc, *data_acc, *tmp_acc; tcp_hdr_t *tmp_hdr; int tmp_hdr_len;#if DEBUG & 256 { where(); printf ("processing advanced data\n"); }#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -