- /* don't send a reset in response to a reset */
- if (n->th_flags&TH_RST)
- return;
- tp->tc_flags |= TC_SND_RST;
- if (n->th_flags&TH_ACK)
- tp->snd_nxt = n->t_ackno;
- tp->tc_flags &= ~TC_SYN_RCVD;
- tcp_sndnull(tp);
- tp->tc_flags &= ~TC_SND_RST;
-}
+ /*
+ * TCP window updates are not reliable, rather a polling protocol
+ * using ``persist'' packets is used to insure receipt of window
+ * updates. The three ``states'' for the output side are:
+ * idle not doing retransmits or persists
+ * persisting to move a zero window
+ * (re)transmitting and thereby not persisting
+ *
+ * tp->t_timer[TCPT_PERSIST]
+ * is set when we are in persist state.
+ * tp->t_force
+ * is set when we are called to send a persist packet.
+ * tp->t_timer[TCPT_REXMT]
+ * is set when we are retransmitting
+ * The output side is idle when both timers are zero.
+ *
+ * If send window is closed, there is data to transmit, and no
+ * retransmit or persist is pending, then go to persist state,
+ * arranging to force out a byte to get more current window information
+ * if nothing happens soon.
+ */
+ if (tp->snd_wnd == 0 && so->so_snd.sb_cc &&
+ tp->t_timer[TCPT_REXMT] == 0 && tp->t_timer[TCPT_PERSIST] == 0) {
+ tp->t_rxtshift = 0;
+ tcp_setpersist(tp);
+ }