- while (n->t_seq == tp->rcv_nxt) {
- /* present data belongs here */
- tp->rcv_nxt += n->t_len;
- n = n->t_next;
- if (n == (struct th *)tp)
- break;
- }
- tp->tc_flags |= (TC_ACK_DUE|TC_NET_KEEP);
- }
-notext:
-/* urg */
-
- if (thflags & (TH_URG|TH_EOL|TH_FIN)) {
- if (thflags&TH_URG) {
- unsigned urgent;
-
- urgent = n->t_urp + n->t_seq;
- if (tp->rcv_nxt < urgent) {
- if (tp->rcv_urp <= tp->rcv_nxt) {
- /* DO SOMETHING WITH URGENT!!! ### */
- }
- tp->rcv_urp = urgent;
- }
- }
-/* eol */
- if ((thflags&TH_EOL) &&
- (tp->tc_flags&TC_DROPPED_TXT) == 0 &&
- tp->tcb_hd.seg_prev != (struct th *)tp) {
- /* mark last mbuf */
- m = dtom(tp->tcb_hd.seg_prev);
- if (m != NULL) {
- while (m->m_next != NULL)
- m = m->m_next;
- m->m_act =
- (struct mbuf *)(m->m_off + m->m_len - 1);
- }
- }
-ctlonly:
-/* fin */
- if ((thflags&TH_FIN) &&
- (tp->tc_flags&TC_DROPPED_TXT) == 0) {
- seq_t last;
-
- if ((tp->tc_flags&TC_FIN_RCVD) == 0) {
- /* do we really have fin ? */
- last = firstempty(tp);
- if (tp->tcb_hd.seg_prev == (struct th *)tp ||
- last == t_end(tp->tcb_hd.seg_prev)) {
- tp->tc_flags |= TC_FIN_RCVD;
- sowakeup(tp->t_socket); /* ### */
- }
- if ((tp->tc_flags&TC_FIN_RCVD) &&
- tp->rcv_nxt >= last) {
- tp->rcv_nxt = last + 1;
- tp->tc_flags |= TC_ACK_DUE;
- }
- } else
- tp->tc_flags |= TC_ACK_DUE;
- }
- }
-/* respond */
- sent = 0;
- if (tp->tc_flags&TC_ACK_DUE)
- sent = tcp_sndctl(tp);
- else if ((tp->tc_flags&TC_NEW_WINDOW))
- if (tp->snd_nxt <= tp->snd_off + tp->t_socket->so_snd.sb_cc ||
- (tp->tc_flags&TC_SND_FIN))
- sent = tcp_send(tp);
-
-/* set for retrans */
- if (!sent && tp->snd_una < tp->snd_nxt &&
- (tp->tc_flags&TC_CANCELLED)) {
- tp->t_rexmt = tp->t_xmtime;
- tp->t_rexmttl = T_REXMTTL;
- tp->t_rexmt_val = tp->t_rtl_val = tp->snd_lst;
- tp->tc_flags &= ~TC_CANCELLED;
- }
-/* present data to user */
- { register struct mbuf **mp;
- register struct socket *so = tp->t_socket;
- seq_t ready;
-
- /* connection must be synced and data available for user */
- if ((tp->tc_flags&TC_SYN_ACKED) == 0)
- return;
- so = tp->t_socket;
- mp = &so->so_rcv.sb_mb;
- while (*mp)
- mp = &(*mp)->m_next;
- n = tp->tcb_hd.seg_next;
- /* SHOULD PACK DATA IN HERE */
- while (n != (struct th *)tp && n->t_seq < tp->rcv_nxt) {
- remque(n);
- m = dtom(n);
- so->so_rcv.sb_cc += n->t_len;
- tp->seqcnt -= n->t_len;
- if (tp->seqcnt < 0) panic("present_data");
- n = n->t_next;
- while (m) {
- if (m->m_len == 0) {
- MFREE(m, *mp);
- } else {
- *mp = m;
- mp = &m->m_next;
- }
- m = *mp;
- }
- }
- sowakeup(so); /* should be macro/conditional */
- }
-}
-
-tcp_drain()
-{
-
+ if (TCPS_HAVERCVDSYN(tp->t_state) == 0)
+ return (0);
+ ti = tp->seg_next;
+ if (ti == (struct tcpiphdr *)tp || ti->ti_seq != tp->rcv_nxt)
+ return (0);
+ if (tp->t_state == TCPS_SYN_RECEIVED && ti->ti_len)
+ return (0);
+ do {
+ tp->rcv_nxt += ti->ti_len;
+ flags = ti->ti_flags & TH_FIN;
+ remque(ti);
+ m = dtom(ti);
+ ti = (struct tcpiphdr *)ti->ti_next;
+ if (so->so_state & SS_CANTRCVMORE)
+ m_freem(m);
+ else
+ sbappend(&so->so_rcv, m);
+ } while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt);
+ sorwakeup(so);
+ return (flags);
+drop:
+ m_freem(dtom(ti));
+ return (0);