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