/[lwip]/lwip/src/core/tcp_in.c
ViewVC logotype

Diff of /lwip/src/core/tcp_in.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.27 by jani, Tue May 27 13:44:08 2003 UTC revision 1.28 by likewise, Mon Jun 9 21:14:47 2003 UTC
# Line 134  tcp_input(struct pbuf *p, struct netif * Line 134  tcp_input(struct pbuf *p, struct netif *
134    
135    /* Verify TCP checksum. */    /* Verify TCP checksum. */
136    if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),    if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
137                          (struct ip_addr *)&(iphdr->dest),        (struct ip_addr *)&(iphdr->dest),
138                          IP_PROTO_TCP, p->tot_len) != 0) {        IP_PROTO_TCP, p->tot_len) != 0) {
139      DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04x\n", inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),      DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04x\n", inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
140                          (struct ip_addr *)&(iphdr->dest),        (struct ip_addr *)&(iphdr->dest),
141                          IP_PROTO_TCP, p->tot_len)));        IP_PROTO_TCP, p->tot_len)));
142  #if TCP_DEBUG  #if TCP_DEBUG
143      tcp_debug_print(tcphdr);      tcp_debug_print(tcphdr);
144  #endif /* TCP_DEBUG */  #endif /* TCP_DEBUG */
# Line 180  tcp_input(struct pbuf *p, struct netif * Line 180  tcp_input(struct pbuf *p, struct netif *
180         ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {         ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
181                
182        /* Move this PCB to the front of the list so that subsequent        /* Move this PCB to the front of the list so that subsequent
183           lookups will be faster (we exploit locality in TCP segment     lookups will be faster (we exploit locality in TCP segment
184           arrivals). */     arrivals). */
185        LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb);        LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb);
186        if (prev != NULL) {        if (prev != NULL) {
187          prev->next = pcb->next;    prev->next = pcb->next;
188          pcb->next = tcp_active_pcbs;    pcb->next = tcp_active_pcbs;
189          tcp_active_pcbs = pcb;    tcp_active_pcbs = pcb;
190        }        }
191        LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb);        LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb);
192        break;        break;
# Line 201  tcp_input(struct pbuf *p, struct netif * Line 201  tcp_input(struct pbuf *p, struct netif *
201      for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {      for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
202        LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);        LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
203        if (pcb->remote_port == tcphdr->src &&        if (pcb->remote_port == tcphdr->src &&
204           pcb->local_port == tcphdr->dest &&     pcb->local_port == tcphdr->dest &&
205           ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&     ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
206           ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {           ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
207          /* We don't really care enough to move this PCB to the front    /* We don't really care enough to move this PCB to the front
208             of the list since we are not very likely to receive that       of the list since we are not very likely to receive that
209             many segments for connections in TIME-WAIT. */       many segments for connections in TIME-WAIT. */
210          DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n"));    DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n"));
211          tcp_timewait_input(pcb);    tcp_timewait_input(pcb);
212          pbuf_free(p);    pbuf_free(p);
213          return;      return;    
214        }        }
215      }        }  
216        
# Line 219  tcp_input(struct pbuf *p, struct netif * Line 219  tcp_input(struct pbuf *p, struct netif *
219      prev = NULL;        prev = NULL;  
220      for(lpcb = tcp_listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {      for(lpcb = tcp_listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
221        if ((ip_addr_isany(&(lpcb->local_ip)) ||        if ((ip_addr_isany(&(lpcb->local_ip)) ||
222            ip_addr_cmp(&(lpcb->local_ip), &(iphdr->dest))) &&      ip_addr_cmp(&(lpcb->local_ip), &(iphdr->dest))) &&
223           lpcb->local_port == tcphdr->dest) {           lpcb->local_port == tcphdr->dest) {    
224          /* Move this PCB to the front of the list so that subsequent    /* Move this PCB to the front of the list so that subsequent
225             lookups will be faster (we exploit locality in TCP segment       lookups will be faster (we exploit locality in TCP segment
226             arrivals). */       arrivals). */
227          if (prev != NULL) {    if (prev != NULL) {
228            ((struct tcp_pcb_listen *)prev)->next = lpcb->next;      ((struct tcp_pcb_listen *)prev)->next = lpcb->next;
229            /* our successor is the remainder of the listening list */            /* our successor is the remainder of the listening list */
230            lpcb->next = tcp_listen_pcbs;      lpcb->next = tcp_listen_pcbs;
231            /* put this listening pcb at the head of the listening list */            /* put this listening pcb at the head of the listening list */
232            tcp_listen_pcbs = lpcb;      tcp_listen_pcbs = lpcb;
233          }    }
234    
235          DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n"));    DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n"));
236          tcp_listen_input(lpcb);    tcp_listen_input(lpcb);
237          pbuf_free(p);    pbuf_free(p);
238          return;    return;
239        }        }
240        prev = (struct tcp_pcb *)lpcb;        prev = (struct tcp_pcb *)lpcb;
241      }      }
# Line 273  tcp_input(struct pbuf *p, struct netif * Line 273  tcp_input(struct pbuf *p, struct netif *
273         and that the pcb has been freed. If so, we don't do anything. */         and that the pcb has been freed. If so, we don't do anything. */
274      if (err != ERR_ABRT) {      if (err != ERR_ABRT) {
275        if (recv_flags & TF_RESET) {        if (recv_flags & TF_RESET) {
276          /* TF_RESET means that the connection was reset by the other    /* TF_RESET means that the connection was reset by the other
277             end. We then call the error callback to inform the       end. We then call the error callback to inform the
278             application that the connection is dead before we       application that the connection is dead before we
279             deallocate the PCB. */       deallocate the PCB. */
280          TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST);    TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST);
281          tcp_pcb_remove(&tcp_active_pcbs, pcb);                tcp_pcb_remove(&tcp_active_pcbs, pcb);            
282          memp_free(MEMP_TCP_PCB, pcb);    memp_free(MEMP_TCP_PCB, pcb);
283        } else if (recv_flags & TF_CLOSED) {        } else if (recv_flags & TF_CLOSED) {
284          /* The connection has been closed and we will deallocate the    /* The connection has been closed and we will deallocate the
285             PCB. */       PCB. */
286          tcp_pcb_remove(&tcp_active_pcbs, pcb);    tcp_pcb_remove(&tcp_active_pcbs, pcb);
287          memp_free(MEMP_TCP_PCB, pcb);    memp_free(MEMP_TCP_PCB, pcb);
288        } else {        } else {
289          err = ERR_OK;    err = ERR_OK;
290          /* If the application has registered a "sent" function to be    /* If the application has registered a "sent" function to be
291             called when new send buffer space is available, we call it       called when new send buffer space is available, we call it
292             now. */       now. */
293          if (pcb->acked > 0) {    if (pcb->acked > 0) {
294            TCP_EVENT_SENT(pcb, pcb->acked, err);      TCP_EVENT_SENT(pcb, pcb->acked, err);
295          }    }
296    
297          if (recv_data != NULL) {    if (recv_data != NULL) {
298            /* Notify application that data has been received. */      /* Notify application that data has been received. */
299            TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err);      TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err);
300          }    }
301              
302          /* If a FIN segment was received, we call the callback    /* If a FIN segment was received, we call the callback
303             function with a NULL buffer to indicate EOF. */       function with a NULL buffer to indicate EOF. */
304          if (recv_flags & TF_GOT_FIN) {    if (recv_flags & TF_GOT_FIN) {
305            TCP_EVENT_RECV(pcb, NULL, ERR_OK, err);      TCP_EVENT_RECV(pcb, NULL, ERR_OK, err);
306          }    }
307          /* If there were no errors, we try to send something out. */    /* If there were no errors, we try to send something out. */
308          if (err == ERR_OK) {    if (err == ERR_OK) {
309            tcp_output(pcb);      tcp_output(pcb);
310          }    }
311        }        }
312      }      }
313            
# Line 334  tcp_input(struct pbuf *p, struct netif * Line 334  tcp_input(struct pbuf *p, struct netif *
334        ++lwip_stats.tcp.drop;        ++lwip_stats.tcp.drop;
335  #endif /* TCP_STATS */        #endif /* TCP_STATS */      
336        tcp_rst(ackno, seqno + tcplen,        tcp_rst(ackno, seqno + tcplen,
337                &(iphdr->dest), &(iphdr->src),          &(iphdr->dest), &(iphdr->src),
338                tcphdr->dest, tcphdr->src);          tcphdr->dest, tcphdr->src);
339      }      }
340      pbuf_free(p);      pbuf_free(p);
341    }    }
# Line 363  tcp_listen_input(struct tcp_pcb_listen * Line 363  tcp_listen_input(struct tcp_pcb_listen *
363         RST. */         RST. */
364      DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n"));      DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n"));
365      tcp_rst(ackno + 1, seqno + tcplen,      tcp_rst(ackno + 1, seqno + tcplen,
366              &(iphdr->dest), &(iphdr->src),        &(iphdr->dest), &(iphdr->src),
367              tcphdr->dest, tcphdr->src);        tcphdr->dest, tcphdr->src);
368    } else if (flags & TCP_SYN) {    } else if (flags & TCP_SYN) {
369      DEBUGF(DEMO_DEBUG, ("TCP connection request %d -> %d.\n", tcphdr->src, tcphdr->dest));      DEBUGF(DEMO_DEBUG, ("TCP connection request %d -> %d.\n", tcphdr->src, tcphdr->dest));
370      npcb = tcp_alloc(pcb->prio);      npcb = tcp_alloc(pcb->prio);
# Line 402  tcp_listen_input(struct tcp_pcb_listen * Line 402  tcp_listen_input(struct tcp_pcb_listen *
402            
403      /* Build an MSS option. */      /* Build an MSS option. */
404      optdata = htonl(((u32_t)2 << 24) |      optdata = htonl(((u32_t)2 << 24) |
405                      ((u32_t)4 << 16) |          ((u32_t)4 << 16) |
406                      (((u32_t)npcb->mss / 256) << 8) |          (((u32_t)npcb->mss / 256) << 8) |
407                      (npcb->mss & 255));          (npcb->mss & 255));
408      /* Send a SYN|ACK together with the MSS option. */      /* Send a SYN|ACK together with the MSS option. */
409      tcp_enqueue(npcb, NULL, 0, TCP_SYN | TCP_ACK, 0, (u8_t *)&optdata, 4);      tcp_enqueue(npcb, NULL, 0, TCP_SYN | TCP_ACK, 0, (u8_t *)&optdata, 4);
410      return tcp_output(npcb);      return tcp_output(npcb);
# Line 453  tcp_process(struct tcp_pcb *pcb) Line 453  tcp_process(struct tcp_pcb *pcb)
453      /* First, determine if the reset is acceptable. */      /* First, determine if the reset is acceptable. */
454      if (pcb->state == SYN_SENT) {      if (pcb->state == SYN_SENT) {
455        if (ackno == pcb->snd_nxt) {        if (ackno == pcb->snd_nxt) {
456          acceptable = 1;    acceptable = 1;
457        }        }
458      } else {      } else {
459        if (TCP_SEQ_GEQ(seqno, pcb->rcv_nxt) &&        if (TCP_SEQ_GEQ(seqno, pcb->rcv_nxt) &&
460           TCP_SEQ_LEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {     TCP_SEQ_LEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {
461          acceptable = 1;    acceptable = 1;
462        }        }
463      }      }
464            
# Line 470  tcp_process(struct tcp_pcb *pcb) Line 470  tcp_process(struct tcp_pcb *pcb)
470        return ERR_RST;        return ERR_RST;
471      } else {      } else {
472        DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %lu rcv_nxt %lu\n",        DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %lu rcv_nxt %lu\n",
473               seqno, pcb->rcv_nxt));         seqno, pcb->rcv_nxt));
474        DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %lu rcv_nxt %lu\n",        DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %lu rcv_nxt %lu\n",
475               seqno, pcb->rcv_nxt));         seqno, pcb->rcv_nxt));
476        return ERR_OK;        return ERR_OK;
477      }      }
478    }    }
# Line 484  tcp_process(struct tcp_pcb *pcb) Line 484  tcp_process(struct tcp_pcb *pcb)
484    switch (pcb->state) {    switch (pcb->state) {
485    case SYN_SENT:    case SYN_SENT:
486      DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %lu pcb->snd_nxt %lu unacked %lu\n", ackno,      DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %lu pcb->snd_nxt %lu unacked %lu\n", ackno,
487             pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno)));       pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno)));
488      if (flags & (TCP_ACK | TCP_SYN) &&      if (flags & (TCP_ACK | TCP_SYN) &&
489         ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) {         ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) {
490        pcb->rcv_nxt = seqno + 1;        pcb->rcv_nxt = seqno + 1;
# Line 502  tcp_process(struct tcp_pcb *pcb) Line 502  tcp_process(struct tcp_pcb *pcb)
502        tcp_parseopt(pcb);        tcp_parseopt(pcb);
503    
504        /* Call the user specified function to call when sucessfully        /* Call the user specified function to call when sucessfully
505           connected. */     connected. */
506        TCP_EVENT_CONNECTED(pcb, ERR_OK, err);        TCP_EVENT_CONNECTED(pcb, ERR_OK, err);
507        tcp_ack(pcb);        tcp_ack(pcb);
508      }          }    
# Line 511  tcp_process(struct tcp_pcb *pcb) Line 511  tcp_process(struct tcp_pcb *pcb)
511      if (flags & TCP_ACK &&      if (flags & TCP_ACK &&
512         !(flags & TCP_RST)) {         !(flags & TCP_RST)) {
513        if (TCP_SEQ_LT(pcb->lastack, ackno) &&        if (TCP_SEQ_LT(pcb->lastack, ackno) &&
514           TCP_SEQ_LEQ(ackno, pcb->snd_nxt)) {     TCP_SEQ_LEQ(ackno, pcb->snd_nxt)) {
515          pcb->state = ESTABLISHED;          pcb->state = ESTABLISHED;
516          DEBUGF(DEMO_DEBUG, ("TCP connection established %d -> %d.\n", inseg.tcphdr->src, inseg.tcphdr->dest));          DEBUGF(DEMO_DEBUG, ("TCP connection established %d -> %d.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
517          LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL);    LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL);
518          /* Call the accept function. */    /* Call the accept function. */
519          TCP_EVENT_ACCEPT(pcb, ERR_OK, err);    TCP_EVENT_ACCEPT(pcb, ERR_OK, err);
520          if (err != ERR_OK) {    if (err != ERR_OK) {
521            /* If the accept function returns with an error, we abort      /* If the accept function returns with an error, we abort
522               the connection. */         the connection. */
523            tcp_abort(pcb);      tcp_abort(pcb);
524            return ERR_ABRT;      return ERR_ABRT;
525          }          }  
526          /* If there was any data contained within this ACK,    /* If there was any data contained within this ACK,
527             we'd better pass it on to the application as well. */       we'd better pass it on to the application as well. */
528          tcp_receive(pcb);    tcp_receive(pcb);
529          pcb->cwnd = pcb->mss;    pcb->cwnd = pcb->mss;
530        }        }  
531      }        }  
532      break;      break;
533    case CLOSE_WAIT:    case CLOSE_WAIT:
534      /* FALLTHROUGH */      /* FALLTHROUGH */
535    case ESTABLISHED:    case ESTABLISHED:
536      tcp_receive(pcb);          tcp_receive(pcb);    
537      if (flags & TCP_FIN) {      if (flags & TCP_FIN) {
538        tcp_ack_now(pcb);        tcp_ack_now(pcb);
539        pcb->state = CLOSE_WAIT;        pcb->state = CLOSE_WAIT;
# Line 544  tcp_process(struct tcp_pcb *pcb) Line 544  tcp_process(struct tcp_pcb *pcb)
544      if (flags & TCP_FIN) {      if (flags & TCP_FIN) {
545        if (flags & TCP_ACK && ackno == pcb->snd_nxt) {        if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
546          DEBUGF(DEMO_DEBUG,          DEBUGF(DEMO_DEBUG,
547                 ("TCP connection closed %d -> %d.\n", inseg.tcphdr->src, inseg.tcphdr->dest));           ("TCP connection closed %d -> %d.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
548          tcp_ack_now(pcb);    tcp_ack_now(pcb);
549          tcp_pcb_purge(pcb);    tcp_pcb_purge(pcb);
550          TCP_RMV(&tcp_active_pcbs, pcb);    TCP_RMV(&tcp_active_pcbs, pcb);
551          pcb->state = TIME_WAIT;    pcb->state = TIME_WAIT;
552          TCP_REG(&tcp_tw_pcbs, pcb);    TCP_REG(&tcp_tw_pcbs, pcb);
553        } else {        } else {
554          tcp_ack_now(pcb);    tcp_ack_now(pcb);
555          pcb->state = CLOSING;    pcb->state = CLOSING;
556        }        }
557      } else if (flags & TCP_ACK && ackno == pcb->snd_nxt) {      } else if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
558        pcb->state = FIN_WAIT_2;        pcb->state = FIN_WAIT_2;
# Line 645  tcp_receive(struct tcp_pcb *pcb) Line 645  tcp_receive(struct tcp_pcb *pcb)
645        pcb->acked = 0;        pcb->acked = 0;
646    
647        if (pcb->snd_wl1 + pcb->snd_wnd == right_wnd_edge){        if (pcb->snd_wl1 + pcb->snd_wnd == right_wnd_edge){
648          ++pcb->dupacks;    ++pcb->dupacks;
649          if (pcb->dupacks >= 3 && pcb->unacked != NULL) {    if (pcb->dupacks >= 3 && pcb->unacked != NULL) {
650            if (!(pcb->flags & TF_INFR)) {      if (!(pcb->flags & TF_INFR)) {
651              /* This is fast retransmit. Retransmit the first unacked segment. */        /* This is fast retransmit. Retransmit the first unacked segment. */
652              DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupacks %d (%lu), fast retransmit %lu\n",        DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupacks %d (%lu), fast retransmit %lu\n",
653                                    pcb->dupacks, pcb->lastack,            pcb->dupacks, pcb->lastack,
654                                    ntohl(pcb->unacked->tcphdr->seqno)));            ntohl(pcb->unacked->tcphdr->seqno)));
655              tcp_rexmit(pcb);        tcp_rexmit(pcb);
656              /* Set ssthresh to max (FlightSize / 2, 2*SMSS) */        /* Set ssthresh to max (FlightSize / 2, 2*SMSS) */
657              pcb->ssthresh = LWIP_MAX((pcb->snd_max -        pcb->ssthresh = LWIP_MAX((pcb->snd_max -
658                                    pcb->lastack) / 2,            pcb->lastack) / 2,
659                                   2 * pcb->mss);           2 * pcb->mss);
660                      
661              pcb->cwnd = pcb->ssthresh + 3 * pcb->mss;        pcb->cwnd = pcb->ssthresh + 3 * pcb->mss;
662              pcb->flags |= TF_INFR;                  pcb->flags |= TF_INFR;          
663            } else {      } else {
664              /* Inflate the congestion window, but not if it means that        /* Inflate the congestion window, but not if it means that
665                 the value overflows. */           the value overflows. */
666              if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {        if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
667                pcb->cwnd += pcb->mss;          pcb->cwnd += pcb->mss;
668              }        }
669            }      }
670          }    }
671        } else {        } else {
672          DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupack averted %lu %lu\n",    DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupack averted %lu %lu\n",
673                                pcb->snd_wl1 + pcb->snd_wnd, right_wnd_edge));                  pcb->snd_wl1 + pcb->snd_wnd, right_wnd_edge));  
674        }        }
675      } else if (TCP_SEQ_LT(pcb->lastack, ackno) &&      } else if (TCP_SEQ_LT(pcb->lastack, ackno) &&
676                TCP_SEQ_LEQ(ackno, pcb->snd_max)) {                TCP_SEQ_LEQ(ackno, pcb->snd_max)) {
# Line 680  tcp_receive(struct tcp_pcb *pcb) Line 680  tcp_receive(struct tcp_pcb *pcb)
680           in fast retransmit. Also reset the congestion window to the           in fast retransmit. Also reset the congestion window to the
681           slow start threshold. */           slow start threshold. */
682        if (pcb->flags & TF_INFR) {        if (pcb->flags & TF_INFR) {
683          pcb->flags &= ~TF_INFR;    pcb->flags &= ~TF_INFR;
684          pcb->cwnd = pcb->ssthresh;    pcb->cwnd = pcb->ssthresh;
685        }        }
686    
687        /* Reset the number of retransmissions. */        /* Reset the number of retransmissions. */
# Line 702  tcp_receive(struct tcp_pcb *pcb) Line 702  tcp_receive(struct tcp_pcb *pcb)
702           ssthresh). */           ssthresh). */
703        if (pcb->state >= ESTABLISHED) {        if (pcb->state >= ESTABLISHED) {
704          if (pcb->cwnd < pcb->ssthresh) {          if (pcb->cwnd < pcb->ssthresh) {
705            if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {      if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
706              pcb->cwnd += pcb->mss;        pcb->cwnd += pcb->mss;
707            }      }
708            DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %u\n", pcb->cwnd));            DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %u\n", pcb->cwnd));
709          } else {          } else {
710            u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd);      u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd);
711            if (new_cwnd > pcb->cwnd) {      if (new_cwnd > pcb->cwnd) {
712              pcb->cwnd = new_cwnd;        pcb->cwnd = new_cwnd;
713            }      }
714            DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %u\n", pcb->cwnd));            DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %u\n", pcb->cwnd));
715          }          }
716        }        }
# Line 722  tcp_receive(struct tcp_pcb *pcb) Line 722  tcp_receive(struct tcp_pcb *pcb)
722                                 ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0));                                 ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0));
723    
724        /* Remove segment from the unacknowledged list if the incoming        /* Remove segment from the unacknowledged list if the incoming
725           ACK acknowlegdes them. */     ACK acknowlegdes them. */
726        while (pcb->unacked != NULL &&        while (pcb->unacked != NULL &&
727              TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) +        TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) +
728                          TCP_TCPLEN(pcb->unacked), ackno)) {        TCP_TCPLEN(pcb->unacked), ackno)) {
729          DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %lu:%lu from pcb->unacked\n",    DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %lu:%lu from pcb->unacked\n",
730                                   ntohl(pcb->unacked->tcphdr->seqno),           ntohl(pcb->unacked->tcphdr->seqno),
731                                   ntohl(pcb->unacked->tcphdr->seqno) +           ntohl(pcb->unacked->tcphdr->seqno) +
732                                   TCP_TCPLEN(pcb->unacked)));           TCP_TCPLEN(pcb->unacked)));
733    
734          next = pcb->unacked;    next = pcb->unacked;
735          pcb->unacked = pcb->unacked->next;    pcb->unacked = pcb->unacked->next;
736              
737          DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %d ... ", pcb->snd_queuelen));    DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %d ... ", pcb->snd_queuelen));
738          pcb->snd_queuelen -= pbuf_clen(next->p);    pcb->snd_queuelen -= pbuf_clen(next->p);
739          tcp_seg_free(next);    tcp_seg_free(next);
740              
741          DEBUGF(TCP_QLEN_DEBUG, ("%d (after freeing unacked)\n", pcb->snd_queuelen));    DEBUGF(TCP_QLEN_DEBUG, ("%d (after freeing unacked)\n", pcb->snd_queuelen));
742          if (pcb->snd_queuelen != 0) {    if (pcb->snd_queuelen != 0) {
743            LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL ||      LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL ||
744                   pcb->unsent != NULL);             pcb->unsent != NULL);      
745          }    }
746        }        }
747        pcb->polltmr = 0;        pcb->polltmr = 0;
748      }      }
# Line 754  tcp_receive(struct tcp_pcb *pcb) Line 754  tcp_receive(struct tcp_pcb *pcb)
754           ->unsent list after a retransmission, so these segments may           ->unsent list after a retransmission, so these segments may
755           in fact have been sent once. */           in fact have been sent once. */
756        while (pcb->unsent != NULL &&        while (pcb->unsent != NULL &&
757              TCP_SEQ_LEQ(ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent),        TCP_SEQ_LEQ(ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent),
758                          ackno) &&                          ackno) &&
759              TCP_SEQ_LEQ(ackno, pcb->snd_max)) {        TCP_SEQ_LEQ(ackno, pcb->snd_max)) {
760          DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %lu:%lu from pcb->unsent\n",    DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %lu:%lu from pcb->unsent\n",
761                                   ntohl(pcb->unsent->tcphdr->seqno),           ntohl(pcb->unsent->tcphdr->seqno),
762                                   ntohl(pcb->unsent->tcphdr->seqno) +           ntohl(pcb->unsent->tcphdr->seqno) +
763                                   TCP_TCPLEN(pcb->unsent)));           TCP_TCPLEN(pcb->unsent)));
764    
765          next = pcb->unsent;    next = pcb->unsent;
766          pcb->unsent = pcb->unsent->next;    pcb->unsent = pcb->unsent->next;
767          DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %d ... ", pcb->snd_queuelen));    DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %d ... ", pcb->snd_queuelen));
768          pcb->snd_queuelen -= pbuf_clen(next->p);    pcb->snd_queuelen -= pbuf_clen(next->p);
769          tcp_seg_free(next);    tcp_seg_free(next);
770          DEBUGF(TCP_QLEN_DEBUG, ("%d (after freeing unsent)\n", pcb->snd_queuelen));    DEBUGF(TCP_QLEN_DEBUG, ("%d (after freeing unsent)\n", pcb->snd_queuelen));
771          if (pcb->snd_queuelen != 0) {    if (pcb->snd_queuelen != 0) {
772            LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL ||      LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL ||
773                   pcb->unsent != NULL);             pcb->unsent != NULL);      
774          }    }
775              
776          if (pcb->unsent != NULL) {          if (pcb->unsent != NULL) {
777            pcb->snd_nxt = htonl(pcb->unsent->tcphdr->seqno);            pcb->snd_nxt = htonl(pcb->unsent->tcphdr->seqno);
778          }          }
# Line 781  tcp_receive(struct tcp_pcb *pcb) Line 781  tcp_receive(struct tcp_pcb *pcb)
781      /* End of ACK for new data processing. */      /* End of ACK for new data processing. */
782            
783      DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %d rtseq %lu ackno %lu\n",      DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %d rtseq %lu ackno %lu\n",
784             pcb->rttest, pcb->rtseq, ackno));       pcb->rttest, pcb->rtseq, ackno));
785            
786      /* RTT estimation calculations. This is done by checking if the      /* RTT estimation calculations. This is done by checking if the
787         incoming segment acknowledges the segment we use to take a         incoming segment acknowledges the segment we use to take a
# Line 790  tcp_receive(struct tcp_pcb *pcb) Line 790  tcp_receive(struct tcp_pcb *pcb)
790        m = tcp_ticks - pcb->rttest;        m = tcp_ticks - pcb->rttest;
791    
792        DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %d ticks (%d msec).\n",        DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %d ticks (%d msec).\n",
793               m, m * TCP_SLOW_INTERVAL));         m, m * TCP_SLOW_INTERVAL));
794    
795        /* This is taken directly from VJs original code in his paper */              /* This is taken directly from VJs original code in his paper */      
796        m = m - (pcb->sa >> 3);        m = m - (pcb->sa >> 3);
797        pcb->sa += m;        pcb->sa += m;
798        if (m < 0) {        if (m < 0) {
799          m = -m;    m = -m;
800        }        }
801        m = m - (pcb->sv >> 2);        m = m - (pcb->sv >> 2);
802        pcb->sv += m;        pcb->sv += m;
803        pcb->rto = (pcb->sa >> 3) + pcb->sv;        pcb->rto = (pcb->sa >> 3) + pcb->sv;
804                
805        DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %d (%d miliseconds)\n",        DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %d (%d miliseconds)\n",
806                               pcb->rto, pcb->rto * TCP_SLOW_INTERVAL));             pcb->rto, pcb->rto * TCP_SLOW_INTERVAL));
807    
808        pcb->rttest = 0;        pcb->rttest = 0;
809      }      }
# Line 842  tcp_receive(struct tcp_pcb *pcb) Line 842  tcp_receive(struct tcp_pcb *pcb)
842         segment is larger than rcv_nxt. */         segment is larger than rcv_nxt. */
843      if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){      if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){
844        if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {        if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {
845          /* Trimming the first edge is done by pushing the payload    /* Trimming the first edge is done by pushing the payload
846             pointer in the pbuf downwards. This is somewhat tricky since       pointer in the pbuf downwards. This is somewhat tricky since
847             we do not want to discard the full contents of the pbuf up to       we do not want to discard the full contents of the pbuf up to
848             the new starting point of the data since we have to keep the       the new starting point of the data since we have to keep the
849             TCP header which is present in the first pbuf in the chain.       TCP header which is present in the first pbuf in the chain.
850                  
851             What is done is really quite a nasty hack: the first pbuf in       What is done is really quite a nasty hack: the first pbuf in
852             the pbuf chain is pointed to by inseg.p. Since we need to be       the pbuf chain is pointed to by inseg.p. Since we need to be
853             able to deallocate the whole pbuf, we cannot change this       able to deallocate the whole pbuf, we cannot change this
854             inseg.p pointer to point to any of the later pbufs in the       inseg.p pointer to point to any of the later pbufs in the
855             chain. Instead, we point the ->payload pointer in the first       chain. Instead, we point the ->payload pointer in the first
856             pbuf to data in one of the later pbufs. We also set the       pbuf to data in one of the later pbufs. We also set the
857             inseg.data pointer to point to the right place. This way, the       inseg.data pointer to point to the right place. This way, the
858             ->p pointer will still point to the first pbuf, but the       ->p pointer will still point to the first pbuf, but the
859             ->p->payload pointer will point to data in another pbuf.       ->p->payload pointer will point to data in another pbuf.
860                  
861             After we are done with adjusting the pbuf pointers we must       After we are done with adjusting the pbuf pointers we must
862             adjust the ->data pointer in the seg and the segment       adjust the ->data pointer in the seg and the segment
863             length.*/       length.*/
864          off = pcb->rcv_nxt - seqno;    off = pcb->rcv_nxt - seqno;
865          if (inseg.p->len < off) {    if (inseg.p->len < off) {
866            p = inseg.p;      p = inseg.p;
867            while (p->len < off) {      while (p->len < off) {
868              off -= p->len;        off -= p->len;
869              inseg.p->tot_len -= p->len;        inseg.p->tot_len -= p->len;
870              p->len = 0;        p->len = 0;
871              p = p->next;        p = p->next;
872            }      }
873            pbuf_header(p, -off);      pbuf_header(p, -off);
874          } else {    } else {
875            pbuf_header(inseg.p, -off);      pbuf_header(inseg.p, -off);
876          }    }
877          inseg.dataptr = inseg.p->payload;    inseg.dataptr = inseg.p->payload;
878          inseg.len -= pcb->rcv_nxt - seqno;          inseg.len -= pcb->rcv_nxt - seqno;      
879          inseg.tcphdr->seqno = seqno = pcb->rcv_nxt;    inseg.tcphdr->seqno = seqno = pcb->rcv_nxt;
880        }        }
881        else{        else{
882          /* the whole segment is < rcv_nxt */    /* the whole segment is < rcv_nxt */
883          /* must be a duplicate of a packet that has already been correctly handled */    /* must be a duplicate of a packet that has already been correctly handled */
884              
885          DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %lu\n", seqno));    DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %lu\n", seqno));
886          tcp_ack_now(pcb);    tcp_ack_now(pcb);
887        }        }
888      }      }
889    
# Line 892  tcp_receive(struct tcp_pcb *pcb) Line 892  tcp_receive(struct tcp_pcb *pcb)
892         processed. */         processed. */
893      if (TCP_SEQ_GEQ(seqno, pcb->rcv_nxt) &&      if (TCP_SEQ_GEQ(seqno, pcb->rcv_nxt) &&
894         TCP_SEQ_LT(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {         TCP_SEQ_LT(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {
895        if (pcb->rcv_nxt == seqno) {                              if (pcb->rcv_nxt == seqno) {      
896          /* The incoming segment is the next in sequence. We check if    /* The incoming segment is the next in sequence. We check if
897             we have to trim the end of the segment and update rcv_nxt             we have to trim the end of the segment and update rcv_nxt
898             and pass the data to the application. */             and pass the data to the application. */
899  #if TCP_QUEUE_OOSEQ  #if TCP_QUEUE_OOSEQ
900          if (pcb->ooseq != NULL &&    if (pcb->ooseq != NULL &&
901             TCP_SEQ_LEQ(pcb->ooseq->tcphdr->seqno, seqno + inseg.len)) {       TCP_SEQ_LEQ(pcb->ooseq->tcphdr->seqno, seqno + inseg.len)) {
902            /* We have to trim the second edge of the incoming      /* We have to trim the second edge of the incoming
903               segment. */               segment. */
904            inseg.len = pcb->ooseq->tcphdr->seqno - seqno;      inseg.len = pcb->ooseq->tcphdr->seqno - seqno;
905            pbuf_realloc(inseg.p, inseg.len);      pbuf_realloc(inseg.p, inseg.len);
906          }    }
907  #endif /* TCP_QUEUE_OOSEQ */  #endif /* TCP_QUEUE_OOSEQ */
908    
909          tcplen = TCP_TCPLEN(&inseg);    tcplen = TCP_TCPLEN(&inseg);
910              
911          pcb->rcv_nxt += tcplen;    pcb->rcv_nxt += tcplen;
912              
913          /* Update the receiver's (our) window. */    /* Update the receiver's (our) window. */
914          if (pcb->rcv_wnd < tcplen) {    if (pcb->rcv_wnd < tcplen) {
915            pcb->rcv_wnd = 0;      pcb->rcv_wnd = 0;
916          } else {    } else {
917            pcb->rcv_wnd -= tcplen;      pcb->rcv_wnd -= tcplen;
918          }    }
919              
920          /* If there is data in the segment, we make preparations to    /* If there is data in the segment, we make preparations to
921             pass this up to the application. The ->recv_data variable       pass this up to the application. The ->recv_data variable
922             is used for holding the pbuf that goes to the       is used for holding the pbuf that goes to the
923             application. The code for reassembling out-of-sequence data       application. The code for reassembling out-of-sequence data
924             chains its data on this pbuf as well.       chains its data on this pbuf as well.
925                  
926             If the segment was a FIN, we set the TF_GOT_FIN flag that will       If the segment was a FIN, we set the TF_GOT_FIN flag that will
927             be used to indicate to the application that the remote side has       be used to indicate to the application that the remote side has
928             closed its end of the connection. */             closed its end of the connection. */      
929          if (inseg.p->tot_len > 0) {    if (inseg.p->tot_len > 0) {
930            recv_data = inseg.p;      recv_data = inseg.p;
931            /* Since this pbuf now is the responsibility of the      /* Since this pbuf now is the responsibility of the
932               application, we delete our reference to it so that we won't         application, we delete our reference to it so that we won't
933               (mistakingly) deallocate it. */         (mistakingly) deallocate it. */
934            inseg.p = NULL;      inseg.p = NULL;
935          }    }
936          if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {    if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
937            DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN."));      DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN."));
938            recv_flags = TF_GOT_FIN;      recv_flags = TF_GOT_FIN;
939          }    }
940              
941  #if TCP_QUEUE_OOSEQ  #if TCP_QUEUE_OOSEQ
942          /* We now check if we have segments on the ->ooseq queue that    /* We now check if we have segments on the ->ooseq queue that
943             is now in sequence. */             is now in sequence. */
944          while (pcb->ooseq != NULL &&    while (pcb->ooseq != NULL &&
945                pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) {          pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) {
946    
947            cseg = pcb->ooseq;      cseg = pcb->ooseq;
948            seqno = pcb->ooseq->tcphdr->seqno;      seqno = pcb->ooseq->tcphdr->seqno;
949                  
950            pcb->rcv_nxt += TCP_TCPLEN(cseg);      pcb->rcv_nxt += TCP_TCPLEN(cseg);
951            if (pcb->rcv_wnd < TCP_TCPLEN(cseg)) {      if (pcb->rcv_wnd < TCP_TCPLEN(cseg)) {
952              pcb->rcv_wnd = 0;        pcb->rcv_wnd = 0;
953            } else {      } else {
954              pcb->rcv_wnd -= TCP_TCPLEN(cseg);        pcb->rcv_wnd -= TCP_TCPLEN(cseg);
955            }      }
956            if (cseg->p->tot_len > 0) {      if (cseg->p->tot_len > 0) {
957              /* Chain this pbuf onto the pbuf that we will pass to        /* Chain this pbuf onto the pbuf that we will pass to
958                 the application. */           the application. */
959              if (recv_data) {        if (recv_data) {
960                pbuf_chain(recv_data, cseg->p);                pbuf_chain(recv_data, cseg->p);
961                pbuf_free(cseg->p);                pbuf_free(cseg->p);
962              } else {              } else {
963                recv_data = cseg->p;          recv_data = cseg->p;
964              }        }
965              cseg->p = NULL;        cseg->p = NULL;
966            }      }
967            if (flags & TCP_FIN) {      if (flags & TCP_FIN) {
968              DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN."));        DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN."));
969              recv_flags = TF_GOT_FIN;        recv_flags = TF_GOT_FIN;
970            }              }      
971                  
972    
973            pcb->ooseq = cseg->next;      pcb->ooseq = cseg->next;
974            tcp_seg_free(cseg);      tcp_seg_free(cseg);
975          }    }
976  #endif /* TCP_QUEUE_OOSEQ */  #endif /* TCP_QUEUE_OOSEQ */
977    
978    
979          /* Acknowledge the segment(s). */    /* Acknowledge the segment(s). */
980          tcp_ack(pcb);    tcp_ack(pcb);
981    
982        } else {        } else {
983          /* We get here if the incoming segment is out-of-sequence. */    /* We get here if the incoming segment is out-of-sequence. */
984          tcp_ack_now(pcb);    tcp_ack_now(pcb);
985  #if TCP_QUEUE_OOSEQ  #if TCP_QUEUE_OOSEQ
986          /* We queue the segment on the ->ooseq queue. */    /* We queue the segment on the ->ooseq queue. */
987          if (pcb->ooseq == NULL) {    if (pcb->ooseq == NULL) {
988            pcb->ooseq = tcp_seg_copy(&inseg);      pcb->ooseq = tcp_seg_copy(&inseg);
989          } else {    } else {
990            /* If the queue is not empty, we walk through the queue and      /* If the queue is not empty, we walk through the queue and
991            try to find a place where the sequence number of the      try to find a place where the sequence number of the
992            incoming segment is between the sequence numbers of the      incoming segment is between the sequence numbers of the
993            previous and the next segment on the ->ooseq queue. That is      previous and the next segment on the ->ooseq queue. That is
994            the place where we put the incoming segment. If needed, we      the place where we put the incoming segment. If needed, we
995            trim the second edges of the previous and the incoming      trim the second edges of the previous and the incoming
996            segment so that it will fit into the sequence.      segment so that it will fit into the sequence.
997    
998            If the incoming segment has the same sequence number as a      If the incoming segment has the same sequence number as a
999            segment on the ->ooseq queue, we discard the segment that      segment on the ->ooseq queue, we discard the segment that
1000            contains less data. */      contains less data. */
1001    
1002            prev = NULL;      prev = NULL;
1003            for(next = pcb->ooseq; next != NULL; next = next->next) {      for(next = pcb->ooseq; next != NULL; next = next->next) {
1004              if (seqno == next->tcphdr->seqno) {        if (seqno == next->tcphdr->seqno) {
1005                /* The sequence number of the incoming segment is the          /* The sequence number of the incoming segment is the
1006                   same as the sequence number of the segment on                   same as the sequence number of the segment on
1007                   ->ooseq. We check the lengths to see which one to                   ->ooseq. We check the lengths to see which one to
1008                   discard. */                   discard. */
1009                if (inseg.len > next->len) {          if (inseg.len > next->len) {
1010                  /* The incoming segment is larger than the old      /* The incoming segment is larger than the old
1011                     segment. We replace the old segment with the new                     segment. We replace the old segment with the new
1012                     one. */                     one. */
1013                  cseg = tcp_seg_copy(&inseg);      cseg = tcp_seg_copy(&inseg);
1014                  if (cseg != NULL) {      if (cseg != NULL) {
1015                    cseg->next = next->next;        cseg->next = next->next;
1016                    if (prev != NULL) {        if (prev != NULL) {
1017                      prev->next = cseg;          prev->next = cseg;
1018                    } else {        } else {
1019                      pcb->ooseq = cseg;          pcb->ooseq = cseg;
1020                    }        }
1021                  }      }
1022                  break;      break;
1023                } else {          } else {
1024                  /* Either the lenghts are the same or the incoming      /* Either the lenghts are the same or the incoming
1025                     segment was smaller than the old one; in either                     segment was smaller than the old one; in either
1026                     case, we ditch the incoming segment. */                     case, we ditch the incoming segment. */
1027                  break;      break;
1028                }          }
1029              } else {        } else {
1030                if (prev == NULL) {          if (prev == NULL) {
1031                  if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {      if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {
1032                    /* The sequence number of the incoming segment is lower        /* The sequence number of the incoming segment is lower
1033                       than the sequence number of the first segment on the           than the sequence number of the first segment on the
1034                       queue. We put the incoming segment first on the           queue. We put the incoming segment first on the
1035                       queue. */           queue. */
1036                            
1037                    if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) {        if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) {
1038                      /* We need to trim the incoming segment. */          /* We need to trim the incoming segment. */
1039                      inseg.len = next->tcphdr->seqno - seqno;          inseg.len = next->tcphdr->seqno - seqno;
1040                      pbuf_realloc(inseg.p, inseg.len);          pbuf_realloc(inseg.p, inseg.len);
1041                    }        }
1042                    cseg = tcp_seg_copy(&inseg);        cseg = tcp_seg_copy(&inseg);
1043                    if (cseg != NULL) {        if (cseg != NULL) {
1044                      cseg->next = next;          cseg->next = next;
1045                      pcb->ooseq = cseg;          pcb->ooseq = cseg;
1046                    }        }
1047                    break;        break;
1048                  }      }
1049                } else if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) &&          } else if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) &&
1050                   TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {       TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {
1051                  /* The sequence number of the incoming segment is in      /* The sequence number of the incoming segment is in
1052                     between the sequence numbers of the previous and                     between the sequence numbers of the previous and
1053                     the next segment on ->ooseq. We trim and insert the                     the next segment on ->ooseq. We trim and insert the
1054                     incoming segment and trim the previous segment, if                     incoming segment and trim the previous segment, if
1055                     needed. */                     needed. */
1056                  if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) {      if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) {
1057                    /* We need to trim the incoming segment. */        /* We need to trim the incoming segment. */
1058                    inseg.len = next->tcphdr->seqno - seqno;        inseg.len = next->tcphdr->seqno - seqno;
1059                    pbuf_realloc(inseg.p, inseg.len);        pbuf_realloc(inseg.p, inseg.len);
1060                  }      }
1061    
1062                  cseg = tcp_seg_copy(&inseg);      cseg = tcp_seg_copy(&inseg);
1063                  if (cseg != NULL) {                                    if (cseg != NULL) {          
1064                    cseg->next = next;        cseg->next = next;
1065                    prev->next = cseg;        prev->next = cseg;
1066                    if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) {        if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) {
1067                      /* We need to trim the prev segment. */          /* We need to trim the prev segment. */
1068                      prev->len = seqno - prev->tcphdr->seqno;          prev->len = seqno - prev->tcphdr->seqno;
1069                      pbuf_realloc(prev->p, prev->len);          pbuf_realloc(prev->p, prev->len);
1070                    }        }
1071                  }      }
1072                  break;      break;
1073                  }      }
1074                /* If the "next" segment is the last segment on the          /* If the "next" segment is the last segment on the
1075                   ooseq queue, we add the incoming segment to the end                   ooseq queue, we add the incoming segment to the end
1076                   of the list. */                   of the list. */
1077                if (next->next == NULL &&          if (next->next == NULL &&
1078                   TCP_SEQ_GT(seqno, next->tcphdr->seqno)) {       TCP_SEQ_GT(seqno, next->tcphdr->seqno)) {
1079                  next->next = tcp_seg_copy(&inseg);      next->next = tcp_seg_copy(&inseg);
1080                  if (next->next != NULL) {                    if (next->next != NULL) {    
1081                    if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) {        if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) {
1082                      /* We need to trim the last segment. */          /* We need to trim the last segment. */
1083                      next->len = seqno - next->tcphdr->seqno;          next->len = seqno - next->tcphdr->seqno;
1084                      pbuf_realloc(next->p, next->len);          pbuf_realloc(next->p, next->len);
1085                    }        }
1086                  }      }
1087                  break;      break;
1088                }          }
1089              }        }
1090              prev = next;        prev = next;
1091            }          }    
1092          }    }
1093  #endif /* TCP_QUEUE_OOSEQ */  #endif /* TCP_QUEUE_OOSEQ */
1094                      
1095        }            }    
1096      }      }
1097    } else {    } else {
# Line 1127  tcp_parseopt(struct tcp_pcb *pcb) Line 1127  tcp_parseopt(struct tcp_pcb *pcb)
1127        opt = opts[c];        opt = opts[c];
1128        if (opt == 0x00) {        if (opt == 0x00) {
1129          /* End of options. */            /* End of options. */  
1130          break;    break;
1131        } else if (opt == 0x01) {        } else if (opt == 0x01) {
1132          ++c;          ++c;
1133          /* NOP option. */          /* NOP option. */
# Line 1140  tcp_parseopt(struct tcp_pcb *pcb) Line 1140  tcp_parseopt(struct tcp_pcb *pcb)
1140          /* And we are done processing options. */          /* And we are done processing options. */
1141          break;          break;
1142        } else {        } else {
1143          if (opts[c + 1] == 0) {    if (opts[c + 1] == 0) {
1144            /* If the length field is zero, the options are malformed            /* If the length field is zero, the options are malformed
1145               and we don't process them further. */               and we don't process them further. */
1146            break;            break;

Legend:
Removed from v.1.27  
changed lines
  Added in v.1.28

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26