-rcv_text(tp, t)
- register struct tcb *tp;
- register struct th *t;
-{
- register i;
- register struct th *p, *q;
- register struct mbuf *m, *n;
- struct th *savq;
- int last, j, k;
-COUNT(RCV_TEXT);
-
- /* throw away any data we have already received */
- if ((i = tp->rcv_nxt - t->t_seq) > 0) {
- if (i >= t->t_len)
- return;
- t->t_seq += i;
- t->t_len -= i;
- m_adj(dtom(t), i);
- }
-
- last = t_end(t); /* last seq # in incoming seg */
- i = rcv_resource(tp); /* # buffers available to con */
-
- /* count buffers in segment */
-
- for (m = dtom(t), j = 0; m != NULL; m = m->m_next)
- if (m->m_len != 0) {
- j++;
- if (m->m_off > MMAXOFF)
- j += NMBPG;
- }
-
- /* not enough resources to process segment */
-
- if (j > i && netcb.n_bufs < netcb.n_lowat) {
-
- /* if segment preceeds top of seqeuncing queue, try to take
- buffers from bottom of queue */
-
- q = tp->t_rcv_next;
- if (q != (struct th *)tp && tp->rcv_nxt < q->t_seq &&
- t->t_seq < q->t_seq)
-
- for (k=j-i, p = tp->t_rcv_prev; k > 0 &&
- p != (struct th *)tp; k--) {
- savq = p->t_prev;
- tcp_deq(p);
- i += m_freem(dtom(p));
- p = savq;
- }
-
- /* if still not enough room, drop text from end of segment */
-
- if (j > i) {
-
- for (m = dtom(t); i > 0 && m != NULL; i--)
- m = m->m_next;
-
- while (m != NULL) {
- t->t_len -= m->m_len;
- last -= m->m_len;
- m->m_len = 0;
- m = m->m_next;
- }
- tp->tc_flags |= TC_DROPPED_TXT;
- if (last < t->t_seq)
- return;
- }
- }
-
- /* merge incoming data into the sequence queue */
-
- q = tp->t_rcv_next; /* -> top of sequencing queue */
-
- /* skip frags which new doesn't overlap at end */
-
- while ((q != (struct th *)tp) && (t->t_seq > t_end(q)))
- q = q->t_next;
-
- if (q == (struct th *)tp) { /* frag at end of chain */
-
- if (last >= tp->rcv_nxt) {
- tp->tc_flags |= TC_NET_KEEP;
- tcp_enq(t, tp->t_rcv_prev);
- }
-
- } else {
-
- /* frag doesn't overlap any on chain */
-
- if (last < q->t_seq) {
- tp->tc_flags |= TC_NET_KEEP;
- tcp_enq(t, q->t_prev);
-
- /* new overlaps beginning of next frag only */
-
- } else if (last < t_end(q)) {
- if ((i = last - q->t_seq + 1) < t->t_len) {
- t->t_len -= i;
- m_adj(dtom(t), -i);
- tp->tc_flags |= TC_NET_KEEP;
- tcp_enq(t, q->t_prev);
- }
-
- /* new overlaps end of previous frag */
-
- } else {
- savq = q;
- if (t->t_seq <= q->t_seq) { /* complete cover */
- savq = q->t_prev;
- tcp_deq(q);
- m_freem(dtom(q));
-
- } else { /* overlap */
- if ((i = t_end(q) - t->t_seq + 1) < t->t_len) {
- t->t_seq += i;
- t->t_len -= i;
- m_adj(dtom(t), i);
- } else
- t->t_len = 0;
- }
-
- /* new overlaps at beginning of successor frags */
-
- q = savq->t_next;
- while ((q != (struct th *)tp) && (t->t_len != 0) &&
- (q->t_seq < last))
-
- /* complete cover */
-
- if (t_end(q) <= last) {
- p = q->t_next;
- tcp_deq(q);
- m_freem(dtom(q));
- q = p;
-
- } else { /* overlap */
-
- if ((i = last - q->t_seq + 1) < t->t_len) {
- t->t_len -= i;
- m_adj(dtom(t), -i);
- } else
- t->t_len = 0;
- break;
- }
-
- /* enqueue whatever is left of new before successors */
-
- if (t->t_len != 0) {
- tp->tc_flags |= TC_NET_KEEP;
- tcp_enq(t, savq);
- }
- }
- }
-
- /* set to ack completed data (no gaps) */
-
- tp->rcv_nxt = firstempty(tp);
- tp->tc_flags |= TC_ACK_DUE;
-
-#ifdef notdef
- /* THIS CODE CANT POSSIBLY WORK */
- /* if any room remaining in rcv buf, take any unprocessed
- messages and schedule for later processing */
-
- i = rcv_resource(tp);
-
- while ((m = tp->t_rcv_unack) != NULL && i > 0) {
-
- /* schedule work request */
-
- t = (struct th *)((int)m + m->m_off);
- j = (t->t_off << 2) + sizeof(struct ip);
- m->m_off += j;
- m->m_len -= j;
- tp->t_rcv_unack = m->m_act;
- m->m_act = (struct mbuf *)0;
- netstat.t_unack++;
- tcp_work(INRECV, 0, tp, t);
-
- /* remaining buffer space */
-
- for (n = m; n != NULL; n = n->m_next)
- i--;
- }
-#endif
-}
-