📄 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); }
#endif
assert(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 + -