- * If an URG bit is set in the segment and is greater than the
- * current known urgent pointer, then signal the user that the
- * remote side has urgent data. This should not happen
- * in CLOSE_WAIT, CLOSING, LAST-ACK or TIME_WAIT STATES since
- * a FIN has been received from the remote side. In these states
- * we ignore the URG.
- */
- if ((tiflags & TH_URG) == 0 && (TCPS_RCVDFIN(tp->t_state) == 0) {
- if (SEQ_GT(ti->ti_urp, tp->rcv_up) {
- tp->rcv_up = ti->ti_urp;
- soisurgendata(so); /* XXX */
+ * Update window information.
+ */
+ if (SEQ_LT(tp->snd_wl1, ti->ti_seq) || tp->snd_wl1 == ti->ti_seq &&
+ (SEQ_LT(tp->snd_wl2, ti->ti_ack) ||
+ tp->snd_wl2 == ti->ti_ack && ti->ti_win > tp->snd_wnd)) {
+/*
+printf("wl1 %x seq %x wl2 %x ack %x win %x wnd %x\n", tp->snd_wl1, ti->ti_seq, tp->snd_wl2, ti->ti_ack, ti->ti_win, tp->snd_wnd);
+*/
+ tp->snd_wnd = ti->ti_win;
+ tp->snd_wl1 = ti->ti_seq;
+ tp->snd_wl2 = ti->ti_ack;
+ if (tp->snd_wnd > 0)
+ tp->t_timer[TCPT_PERSIST] = 0;
+ }
+
+ /*
+ * Process segments with URG.
+ */
+ if ((tiflags & TH_URG) && TCPS_HAVERCVDFIN(tp->t_state) == 0) {
+ /*
+ * If this segment advances the known urgent pointer,
+ * then mark the data stream. This should not happen
+ * in CLOSE_WAIT, CLOSING, LAST_ACK or TIME_WAIT STATES since
+ * a FIN has been received from the remote side.
+ * In these states we ignore the URG.
+ */
+ if (SEQ_GT(ti->ti_seq+ti->ti_urp, tp->rcv_up)) {
+ tp->rcv_up = ti->ti_seq + ti->ti_urp;
+ so->so_oobmark = so->so_rcv.sb_cc +
+ (tp->rcv_up - tp->rcv_nxt) - 1;
+ if (so->so_oobmark == 0)
+ so->so_state |= SS_RCVATMARK;
+#ifdef TCPTRUEOOB
+ if ((tp->t_flags & TF_DOOOB) == 0)
+#endif
+ sohasoutofband(so);
+ tp->t_oobflags &= ~TCPOOB_HAVEDATA;
+ }
+ /*
+ * Remove out of band data so doesn't get presented to user.
+ * This can happen independent of advancing the URG pointer,
+ * but if two URG's are pending at once, some out-of-band
+ * data may creep in... ick.
+ */
+ if (ti->ti_urp <= ti->ti_len) {
+ tcp_pulloutofband(so, ti);