📄 tcp_recv.c
字号:
hdr_acc= bf_memreq(tcp_hdr_len); /* make fresh header */
if (tcp_conn->tc_state == TCS_CLOSED)
{
#if DEBUG
{ where(); printf("connection closed while inuse\n"); }
#endif
bf_afree(hdr_acc);
return;
}
assert (hdr_acc->acc_length == tcp_hdr_len);
tmp_hdr= (tcp_hdr_t *)ptr2acc_data(hdr_acc);
#if DEBUG & 256
{ where(); printf("doing memcpy\n"); }
#endif
memcpy ((char *)tmp_hdr, (char *)tcp_hdr, tcp_hdr_len);
tcp_hdr= tmp_hdr;
data_acc= bf_cut (tcp_data, tcp_hdr_len, data_len);
seg_seq= ntohl(tcp_hdr->th_seq_nr);
tcp_hdr->th_seq_nr= seg_seq; /* seq_nr in host format */
if (tcp_hdr->th_flags & THF_URG)
{
seg_up= ntohs(tcp_hdr->th_urgptr);
tcp_hdr->th_urgptr= seg_up;
/* urgptr in host format */
tcp_conn->tc_RCV_HI= tcp_conn->tc_RCV_LO+
tcp_conn->tc_rcv_wnd+tcp_conn->tc_urg_wnd;
}
assert (!(tcp_hdr->th_flags & THF_SYN));
assert (tcp_Gmod4G(seg_seq, tcp_conn->tc_RCV_NXT));
tcp_hdr->th_flags &= ~THF_FIN; /* it is too difficult to
preserve a FIN */
seg_hi= seg_seq + data_len;
if (tcp_Gmod4G(seg_hi, tcp_conn->tc_RCV_HI))
{
seg_hi= tcp_conn->tc_RCV_HI;
data_len= seg_hi-seg_seq;
if (!data_len)
{
bf_afree(hdr_acc);
bf_afree(data_acc);
return;
}
#if DEBUG
{ where(); printf("Cutting packet\n"); }
#endif
tmp_acc= bf_cut(data_acc, 0, data_len);
bf_afree(data_acc);
data_acc= tmp_acc;
}
hdr_acc->acc_next= data_acc;
hdr_acc->acc_ext_link= 0;
head_acc= tcp_conn->tc_rcv_queue;
tcp_conn->tc_rcv_queue= 0;
tail_acc_ptr= 0;
next_acc= head_acc;
while (next_acc)
{
assert (next_acc->acc_length >= TCP_MIN_HDR_SIZE);
tmp_hdr= (tcp_hdr_t *)ptr2acc_data(next_acc);
if (tcp_Lmod4G(seg_seq, tmp_hdr->th_seq_nr))
{
#if DEBUG & 256
{ where(); printf("calling merge_packs\n"); }
#endif
next_acc= merge_packs(hdr_acc, next_acc);
hdr_acc= 0;
if (tail_acc_ptr)
{
assert (*tail_acc_ptr);
(*tail_acc_ptr)->acc_ext_link= 0;
#if DEBUG & 256
{ where(); printf("calling merge_packs\n"); }
#endif
*tail_acc_ptr= merge_packs(
*tail_acc_ptr, next_acc);
}
else
head_acc= next_acc;
break;
}
if (!tail_acc_ptr)
tail_acc_ptr= &head_acc;
else
tail_acc_ptr= &(*tail_acc_ptr)->acc_ext_link;
next_acc= next_acc->acc_ext_link;
}
if (hdr_acc)
{
next_acc= hdr_acc;
hdr_acc= 0;
if (tail_acc_ptr)
{
if (*tail_acc_ptr)
{
(*tail_acc_ptr)->acc_ext_link= 0;
#if DEBUG & 256
{ where(); printf("calling merge_packs\n"); }
#endif
*tail_acc_ptr= merge_packs(
*tail_acc_ptr, next_acc);
}
else
*tail_acc_ptr= next_acc;
}
else
head_acc= next_acc;
}
if (tcp_conn->tc_state == TCS_CLOSED)
{
while (head_acc)
{
next_acc= head_acc->acc_ext_link;
bf_afree(head_acc);
head_acc= next_acc;
}
return;
}
tcp_conn->tc_rcv_queue= head_acc;
}
PRIVATE acc_t *merge_packs(first, next)
acc_t *first;
acc_t *next;
{
tcp_hdr_t *first_hdr, *next_hdr;
int first_hdr_len, next_hdr_len, first_data_len, next_data_len;
acc_t *next_acc, *tmp_acc;
assert (first->acc_length >= TCP_MIN_HDR_SIZE);
assert (next->acc_length >= TCP_MIN_HDR_SIZE);
first_hdr= (tcp_hdr_t *)ptr2acc_data(first);
next_hdr= (tcp_hdr_t *)ptr2acc_data(next);
first_hdr_len= (first_hdr->th_data_off & TH_DO_MASK) >>2;
next_hdr_len= (next_hdr->th_data_off & TH_DO_MASK) >> 2;
first_data_len= first_hdr->th_chksum-first_hdr_len;
next_data_len= next_hdr->th_chksum-next_hdr_len;
assert (tcp_LEmod4G(first_hdr->th_seq_nr, next_hdr->th_seq_nr));
assert (first_hdr_len + first_data_len == bf_bufsize(first));
#if DEBUG
if (next_hdr_len + next_data_len != bf_bufsize(next))
{ ip_panic(( "fatal error: %d + %d != %d\n", next_hdr_len, next_data_len,
bf_bufsize(next) )); }
#endif
assert (next_hdr_len + next_data_len == bf_bufsize(next));
if (tcp_Lmod4G(first_hdr->th_seq_nr+first_data_len,
next_hdr->th_seq_nr))
{
first->acc_ext_link= next;
return first;
}
if (first_hdr->th_seq_nr == next_hdr->th_seq_nr)
if (first_data_len <= next_data_len)
{
bf_afree(first);
return next;
}
else
{
first->acc_ext_link= next->acc_ext_link;
bf_afree(next);
return first;
}
if (tcp_GEmod4G(first_hdr->th_seq_nr+first_data_len,
next_hdr->th_seq_nr+next_data_len))
{
first->acc_ext_link= next->acc_ext_link;
bf_afree(next);
return first;
}
first_data_len= next_hdr->th_seq_nr-first_hdr->th_seq_nr;
first_hdr->th_chksum= first_data_len+first_hdr_len+
next_data_len;
tmp_acc= bf_cut(first, 0, first_hdr_len + first_data_len);
bf_afree(first);
first= tmp_acc;
if (next_hdr->th_flags & THF_PSH)
first_hdr->th_flags |= THF_PSH;
if (next_hdr->th_flags & THF_URG)
{
if (!(first_hdr->th_flags & THF_URG))
{
first_hdr->th_flags |= THF_URG;
first_hdr->th_urgptr= next_hdr->th_seq_nr+
next_hdr->th_urgptr-
first_hdr->th_seq_nr;
}
else if (next_hdr->th_seq_nr+next_hdr->th_urgptr-
first_hdr->th_seq_nr > first_hdr->th_urgptr)
first_hdr->th_urgptr= next_hdr->th_seq_nr+
next_hdr->th_urgptr-
first_hdr->th_seq_nr;
}
next_acc= next->acc_ext_link;
tmp_acc= bf_cut(next, next_hdr_len ,next_data_len);
bf_afree(next);
next= tmp_acc;
tmp_acc= bf_append (first, next);
tmp_acc->acc_ext_link= next_acc;
return tmp_acc;
}
PRIVATE void create_RST(tcp_conn, ip_hdr, tcp_hdr)
tcp_conn_t *tcp_conn;
ip_hdr_t *ip_hdr;
tcp_hdr_t *tcp_hdr;
{
acc_t *tmp_ipopt, *tmp_tcpopt;
ip_hdropt_t ip_hdropt;
tcp_hdropt_t tcp_hdropt;
acc_t *RST_acc;
ip_hdr_t *RST_ip_hdr;
tcp_hdr_t *RST_tcp_hdr;
char *ptr2RSThdr;
size_t pack_size;
tmp_ipopt= tcp_conn->tc_remipopt;
if (tmp_ipopt)
tmp_ipopt->acc_linkC++;
tmp_tcpopt= tcp_conn->tc_remtcpopt;
if (tmp_tcpopt)
tmp_tcpopt->acc_linkC++;
tcp_extract_ipopt (tcp_conn, ip_hdr);
tcp_extract_tcpopt (tcp_conn, tcp_hdr);
RST_acc= tcp_make_header (tcp_conn, &RST_ip_hdr, &RST_tcp_hdr,
(acc_t *)0);
if (!RST_acc)
{
#if DEBUG
{ where(); printf("connection closed while inuse\n"); }
#endif
return;
}
if (tcp_conn->tc_remipopt)
bf_afree(tcp_conn->tc_remipopt);
tcp_conn->tc_remipopt= tmp_ipopt;
if (tcp_conn->tc_remtcpopt)
bf_afree(tcp_conn->tc_remtcpopt);
tcp_conn->tc_remtcpopt= tmp_tcpopt;
RST_ip_hdr->ih_src= ip_hdr->ih_dst;
RST_ip_hdr->ih_dst= ip_hdr->ih_src;
RST_tcp_hdr->th_srcport= tcp_hdr->th_dstport;
RST_tcp_hdr->th_dstport= tcp_hdr->th_srcport;
if (tcp_hdr->th_flags & THF_ACK)
{
RST_tcp_hdr->th_seq_nr= tcp_hdr->th_ack_nr;
RST_tcp_hdr->th_flags= THF_RST;
}
else
{
RST_tcp_hdr->th_seq_nr= 0;
RST_tcp_hdr->th_ack_nr= htonl(ntohl(tcp_hdr->th_seq_nr)+
tcp_hdr->th_chksum-((tcp_hdr->th_data_off &
TH_DO_MASK) >> 2)+ (tcp_hdr->th_flags &
THF_SYN ? 1 : 0) + (tcp_hdr->th_flags &
THF_FIN ? 1 : 0));
RST_tcp_hdr->th_flags= THF_RST|THF_ACK;
}
pack_size= bf_bufsize(RST_acc);
RST_ip_hdr->ih_length= htons(pack_size);
RST_tcp_hdr->th_window= htons(tcp_conn->tc_rcv_wnd);
RST_tcp_hdr->th_chksum= 0;
RST_tcp_hdr->th_chksum= ~tcp_pack_oneCsum (RST_acc, pack_size);
if (tcp_conn->tc_frag2send)
bf_afree(tcp_conn->tc_frag2send);
tcp_conn->tc_frag2send= RST_acc;
}
PUBLIC void tcp_restart_fd_read (tcp_conn)
tcp_conn_t *tcp_conn;
{
tcp_fd_t *new_fd, *hi_fd, *urgent_fd, *normal_fd, *tcp_fd;
#if DEBUG & 256
{ where(); printf("tcp_restart_fd_read called\n"); }
#endif
do
{
tcp_fd= tcp_conn->tc_readuser;
if (tcp_fd)
fd_read (tcp_fd);
else
tcp_fd= &tcp_fd_table[TCP_FD_NR-1];
if (!tcp_conn->tc_readuser)
{
urgent_fd= 0;
normal_fd= 0;
for (new_fd= tcp_fd+1, hi_fd=
&tcp_fd_table[TCP_FD_NR]; new_fd<hi_fd;
new_fd++)
switch_read_fd(tcp_conn, new_fd,
&urgent_fd, &normal_fd);
for (new_fd= tcp_fd_table, hi_fd= tcp_fd+1;
new_fd < hi_fd; new_fd++)
switch_read_fd(tcp_conn, new_fd,
&urgent_fd, &normal_fd);
if (urgent_fd)
tcp_fd= urgent_fd;
else
tcp_fd= normal_fd;
tcp_conn->tc_readuser= tcp_fd;
}
else
return;
} while (tcp_conn->tc_readuser);
}
PRIVATE void switch_read_fd (tcp_conn, new_fd, ref_urg_fd,
ref_norm_fd)
tcp_conn_t *tcp_conn;
tcp_fd_t *new_fd, **ref_urg_fd, **ref_norm_fd;
{
if (!(new_fd->tf_flags & TFF_INUSE))
return;
if (new_fd->tf_conn != tcp_conn)
return;
if (!(new_fd->tf_flags & TFF_READ_IP))
return;
if (new_fd->tf_flags & TFF_RECV_URG)
{
if (!*ref_urg_fd)
*ref_urg_fd= new_fd;
}
else
{
if (!*ref_norm_fd)
*ref_norm_fd= new_fd;
}
}
PRIVATE void fd_read(tcp_fd)
tcp_fd_t *tcp_fd;
{
tcp_conn_t *tcp_conn;
size_t data_size, read_size;
acc_t * data;
int urg, result;
int more2write;
more2write= FALSE;
tcp_conn= tcp_fd->tf_conn;
assert (tcp_fd->tf_flags & TFF_READ_IP);
if (tcp_conn->tc_state == TCS_CLOSED)
{
tcp_conn->tc_readuser= 0;
#if DEBUG
{ where(); printf("calling tcp_reply_read\n"); }
#endif
if (tcp_fd->tf_read_offset)
tcp_reply_read (tcp_fd, tcp_fd->tf_read_offset);
else
tcp_reply_read (tcp_fd, tcp_conn->tc_error);
return;
}
#if URG_PROPERLY_IMPLEMENTED
urg= (tcp_GEmod4G(tcp_conn->tc_RCV_UP, tcp_conn->tc_RCV_LO) &&
tcp_Lmod4G(tcp_conn->tc_RCV_UP, tcp_conn->tc_RCV_NXT));
#else
#define urg 0
#endif
if (urg && !(tcp_fd->tf_flags & TFF_RECV_URG))
{
tcp_conn->tc_readuser= 0;
#if DEBUG
{ where(); printf("calling tcp_reply_read\n"); }
#endif
if (tcp_fd->tf_read_offset)
tcp_reply_read (tcp_fd, tcp_fd->tf_read_offset);
else
tcp_reply_read (tcp_fd, EURG);
return;
}
else if (!urg && (tcp_fd->tf_flags & TFF_RECV_URG))
{
tcp_conn->tc_readuser= 0;
#if DEBUG
{ where(); printf("calling tcp_reply_read\n"); }
#endif
if (tcp_fd->tf_read_offset)
tcp_reply_read (tcp_fd, tcp_fd->tf_read_offset);
else
tcp_reply_read(tcp_fd, ENOURG);
return;
}
data_size= tcp_conn->tc_RCV_NXT-tcp_conn->tc_RCV_LO;
if (tcp_conn->tc_flags & TCF_FIN_RECV)
data_size--;
if (urg)
read_size= tcp_conn->tc_RCV_UP+1-tcp_conn->tc_RCV_LO;
else
read_size= data_size;
if (read_size>tcp_fd->tf_read_count)
read_size= tcp_fd->tf_read_count;
if (read_size)
{
if (read_size == data_size)
data= bf_dupacc(tcp_conn->tc_rcvd_data);
else
data= bf_cut(tcp_conn->tc_rcvd_data, 0, read_size);
result= (*tcp_fd->tf_put_userdata) (tcp_fd->tf_srfd,
tcp_fd->tf_read_offset, data, FALSE);
if (tcp_conn->tc_state == TCS_CLOSED)
{
#if DEBUG
{ where(); printf("connection closed while inuse\n"); }
#endif
return;
}
if (result<0)
{
tcp_conn->tc_readuser= 0;
#if DEBUG
{ where(); printf("calling tcp_reply_read\n"); }
#endif
if (tcp_fd->tf_read_offset)
tcp_reply_read(tcp_fd, tcp_fd->
tf_read_offset);
else
tcp_reply_read(tcp_fd, result);
return;
}
tcp_fd->tf_read_offset += read_size;
tcp_fd->tf_read_count -= read_size;
if (data_size == read_size)
{
bf_afree(tcp_conn->tc_rcvd_data);
tcp_conn->tc_rcvd_data= 0;
}
else
{
data= tcp_conn->tc_rcvd_data;
tcp_conn->tc_rcvd_data= bf_cut(data,
read_size, data_size-read_size);
bf_afree(data);
}
tcp_conn->tc_RCV_LO += read_size;
data_size -= read_size;
}
if (tcp_conn->tc_RCV_HI-tcp_conn->tc_RCV_LO < (tcp_conn->
tc_rcv_wnd >> 2))
{
tcp_conn->tc_RCV_HI= tcp_conn->tc_RCV_LO +
tcp_conn->tc_rcv_wnd;
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
more2write= TRUE;
}
if (!data_size && (tcp_conn->tc_flags & TCF_RCV_PUSH))
{
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_fd->tf_read_offset)
{
tcp_conn->tc_readuser= 0;
#if DEBUG & 256
{ where(); printf("calling tcp_reply_read\n"); }
#endif
tcp_reply_read (tcp_fd, tcp_fd->tf_read_offset);
if (more2write)
tcp_restart_write(tcp_conn);
return;
}
}
if ((tcp_conn->tc_flags & TCF_FIN_RECV) ||
!tcp_fd->tf_read_count)
{
tcp_conn->tc_readuser= 0;
#if DEBUG & 256
{ where(); printf("calling tcp_reply_read\n"); }
#endif
tcp_reply_read (tcp_fd, tcp_fd->tf_read_offset);
if (more2write)
tcp_restart_write(tcp_conn);
return;
}
if (more2write)
tcp_restart_write(tcp_conn);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -