/[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.29 by kieranm, Tue Jun 10 10:45:29 2003 UTC revision 1.30 by likewise, Wed Jun 11 22:34:51 2003 UTC
# Line 6  Line 6 
6    
7  /*  /*
8   * Copyright (c) 2001-2003 Swedish Institute of Computer Science.   * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
9   * All rights reserved.   * All rights reserved.
10   *   *
11   * Redistribution and use in source and binary forms, with or without modification,   * Redistribution and use in source and binary forms, with or without modification,
12   * are permitted provided that the following conditions are met:   * are permitted provided that the following conditions are met:
13   *   *
14   * 1. Redistributions of source code must retain the above copyright notice,   * 1. Redistributions of source code must retain the above copyright notice,
# Line 17  Line 17 
17   *    this list of conditions and the following disclaimer in the documentation   *    this list of conditions and the following disclaimer in the documentation
18   *    and/or other materials provided with the distribution.   *    and/or other materials provided with the distribution.
19   * 3. The name of the author may not be used to endorse or promote products   * 3. The name of the author may not be used to endorse or promote products
20   *    derived from this software without specific prior written permission.   *    derived from this software without specific prior written permission.
21   *   *
22   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
23   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24   * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT   * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
25   * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26   * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT   * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
27   * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS   * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30   * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY   * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
31   * OF SUCH DAMAGE.   * OF SUCH DAMAGE.
32   *   *
33   * This file is part of the lwIP TCP/IP stack.   * This file is part of the lwIP TCP/IP stack.
34   *   *
35   * Author: Adam Dunkels <adam@sics.se>   * Author: Adam Dunkels <adam@sics.se>
36   *   *
37   */   */
# Line 105  tcp_input(struct pbuf *p, struct netif * Line 105  tcp_input(struct pbuf *p, struct netif *
105    
106    PERF_START;    PERF_START;
107    
108      
109  #ifdef TCP_STATS  #ifdef TCP_STATS
110    ++lwip_stats.tcp.recv;    ++lwip_stats.tcp.recv;
111  #endif /* TCP_STATS */  #endif /* TCP_STATS */
# Line 113  tcp_input(struct pbuf *p, struct netif * Line 113  tcp_input(struct pbuf *p, struct netif *
113    iphdr = p->payload;    iphdr = p->payload;
114    tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4);    tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4);
115    
116    /* remove header from payload */    /* remove header from payload */
117    if (pbuf_header(p, -((s16_t)(IPH_HL(iphdr) * 4))) || (p->tot_len < sizeof(struct tcp_hdr))) {    if (pbuf_header(p, -((s16_t)(IPH_HL(iphdr) * 4))) || (p->tot_len < sizeof(struct tcp_hdr))) {
118      /* drop short packets */      /* drop short packets */
119      LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%u bytes) discarded\n", p->tot_len));      LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%u bytes) discarded\n", p->tot_len));
# Line 124  tcp_input(struct pbuf *p, struct netif * Line 124  tcp_input(struct pbuf *p, struct netif *
124      pbuf_free(p);      pbuf_free(p);
125      return;      return;
126    }    }
127      
128    /* Don't even process incoming broadcasts/multicasts. */    /* Don't even process incoming broadcasts/multicasts. */
129    if (ip_addr_isbroadcast(&(iphdr->dest), &(inp->netmask)) ||    if (ip_addr_isbroadcast(&(iphdr->dest), &(inp->netmask)) ||
130       ip_addr_ismulticast(&(iphdr->dest))) {       ip_addr_ismulticast(&(iphdr->dest))) {
# Line 136  tcp_input(struct pbuf *p, struct netif * Line 136  tcp_input(struct pbuf *p, struct netif *
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        LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04x\n", inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),        LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04x\n",
140        (struct ip_addr *)&(iphdr->dest),          inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src), (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);
# Line 166  tcp_input(struct pbuf *p, struct netif * Line 166  tcp_input(struct pbuf *p, struct netif *
166    
167    flags = TCPH_FLAGS(tcphdr) & TCP_FLAGS;    flags = TCPH_FLAGS(tcphdr) & TCP_FLAGS;
168    tcplen = p->tot_len + ((flags & TCP_FIN || flags & TCP_SYN)? 1: 0);    tcplen = p->tot_len + ((flags & TCP_FIN || flags & TCP_SYN)? 1: 0);
169      
170    /* Demultiplex an incoming segment. First, we check if it is destined    /* Demultiplex an incoming segment. First, we check if it is destined
171       for an active connection. */         for an active connection. */
172    prev = NULL;      prev = NULL;
173    for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {    for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
174      LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED);      LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED);
175      LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);      LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
# Line 178  tcp_input(struct pbuf *p, struct netif * Line 178  tcp_input(struct pbuf *p, struct netif *
178         pcb->local_port == tcphdr->dest &&         pcb->local_port == tcphdr->dest &&
179         ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&         ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
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). */
# Line 186  tcp_input(struct pbuf *p, struct netif * Line 186  tcp_input(struct pbuf *p, struct netif *
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 210  tcp_input(struct pbuf *p, struct netif * Line 210  tcp_input(struct pbuf *p, struct netif *
210    LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n"));    LWIP_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      
217    /* Finally, if we still did not get a match, we check all PCBs that    /* Finally, if we still did not get a match, we check all PCBs that
218       are LISTENing for incoming connections. */       are LISTENing for incoming connections. */
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). */
# Line 229  tcp_input(struct pbuf *p, struct netif * Line 229  tcp_input(struct pbuf *p, struct netif *
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    LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n"));    LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n"));
# Line 240  tcp_input(struct pbuf *p, struct netif * Line 240  tcp_input(struct pbuf *p, struct netif *
240        prev = (struct tcp_pcb *)lpcb;        prev = (struct tcp_pcb *)lpcb;
241      }      }
242    }    }
243      
244  #if TCP_INPUT_DEBUG  #if TCP_INPUT_DEBUG
245    LWIP_DEBUGF(TCP_INPUT_DEBUG, ("+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags "));    LWIP_DEBUGF(TCP_INPUT_DEBUG, ("+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags "));
246    tcp_debug_print_flags(TCPH_FLAGS(tcphdr));    tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
247    LWIP_DEBUGF(TCP_INPUT_DEBUG, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n"));    LWIP_DEBUGF(TCP_INPUT_DEBUG, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n"));
248  #endif /* TCP_INPUT_DEBUG */  #endif /* TCP_INPUT_DEBUG */
249    
250      
251    if (pcb != NULL) {    if (pcb != NULL) {
252      /* The incoming segment belongs to a connection. */      /* The incoming segment belongs to a connection. */
253  #if TCP_INPUT_DEBUG  #if TCP_INPUT_DEBUG
# Line 255  tcp_input(struct pbuf *p, struct netif * Line 255  tcp_input(struct pbuf *p, struct netif *
255      tcp_debug_print_state(pcb->state);      tcp_debug_print_state(pcb->state);
256  #endif /* TCP_DEBUG */  #endif /* TCP_DEBUG */
257  #endif /* TCP_INPUT_DEBUG */  #endif /* TCP_INPUT_DEBUG */
258        
259      /* Set up a tcp_seg structure. */      /* Set up a tcp_seg structure. */
260      inseg.next = NULL;      inseg.next = NULL;
261      inseg.len = p->tot_len;      inseg.len = p->tot_len;
262      inseg.dataptr = p->payload;      inseg.dataptr = p->payload;
263      inseg.p = p;      inseg.p = p;
264      inseg.tcphdr = tcphdr;      inseg.tcphdr = tcphdr;
265        
266      recv_data = NULL;      recv_data = NULL;
267      recv_flags = 0;      recv_flags = 0;
268    
# Line 278  tcp_input(struct pbuf *p, struct netif * Line 278  tcp_input(struct pbuf *p, struct netif *
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
# Line 298  tcp_input(struct pbuf *p, struct netif * Line 298  tcp_input(struct pbuf *p, struct netif *
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) {
# Line 310  tcp_input(struct pbuf *p, struct netif * Line 310  tcp_input(struct pbuf *p, struct netif *
310    }    }
311        }        }
312      }      }
313        
314    
315      /* We deallocate the incoming pbuf. If it was buffered by the      /* We deallocate the incoming pbuf. If it was buffered by the
316         application, the application should have called pbuf_ref() to         application, the application should have called pbuf_ref() to
# Line 323  tcp_input(struct pbuf *p, struct netif * Line 323  tcp_input(struct pbuf *p, struct netif *
323      tcp_debug_print_state(pcb->state);      tcp_debug_print_state(pcb->state);
324  #endif /* TCP_DEBUG */  #endif /* TCP_DEBUG */
325  #endif /* TCP_INPUT_DEBUG */  #endif /* TCP_INPUT_DEBUG */
326        
327    } else {    } else {
328      /* If no matching PCB was found, send a TCP RST (reset) to the      /* If no matching PCB was found, send a TCP RST (reset) to the
329         sender. */         sender. */
# Line 332  tcp_input(struct pbuf *p, struct netif * Line 332  tcp_input(struct pbuf *p, struct netif *
332  #ifdef TCP_STATS  #ifdef TCP_STATS
333        ++lwip_stats.tcp.proterr;        ++lwip_stats.tcp.proterr;
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);
# Line 340  tcp_input(struct pbuf *p, struct netif * Line 340  tcp_input(struct pbuf *p, struct netif *
340      pbuf_free(p);      pbuf_free(p);
341    }    }
342    
343    LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());      LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());
344    PERF_STOP("tcp_input");    PERF_STOP("tcp_input");
345  }  }
346  /*-----------------------------------------------------------------------------------*/  /*-----------------------------------------------------------------------------------*/
# Line 355  tcp_listen_input(struct tcp_pcb_listen * Line 355  tcp_listen_input(struct tcp_pcb_listen *
355  {  {
356    struct tcp_pcb *npcb;    struct tcp_pcb *npcb;
357    u32_t optdata;    u32_t optdata;
358        
359    /* In the LISTEN state, we check for incoming SYN segments,    /* In the LISTEN state, we check for incoming SYN segments,
360       creates a new PCB, and responds with a SYN|ACK. */       creates a new PCB, and responds with a SYN|ACK. */
361    if (flags & TCP_ACK) {    if (flags & TCP_ACK) {
# Line 366  tcp_listen_input(struct tcp_pcb_listen * Line 366  tcp_listen_input(struct tcp_pcb_listen *
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      LWIP_DEBUGF(DEMO_DEBUG, ("TCP connection request %d -> %d.\n", tcphdr->src, tcphdr->dest));      LWIP_DEBUGF(DEMO_DEBUG, ("TCP connection request %u -> %u.\n", tcphdr->src, tcphdr->dest));
370      npcb = tcp_alloc(pcb->prio);      npcb = tcp_alloc(pcb->prio);
371      /* If a new PCB could not be created (probably due to lack of memory),      /* If a new PCB could not be created (probably due to lack of memory),
372         we don't do anything, but rely on the sender will retransmit the         we don't do anything, but rely on the sender will retransmit the
# Line 392  tcp_listen_input(struct tcp_pcb_listen * Line 392  tcp_listen_input(struct tcp_pcb_listen *
392  #if LWIP_CALLBACK_API  #if LWIP_CALLBACK_API
393      npcb->accept = pcb->accept;      npcb->accept = pcb->accept;
394  #endif /* LWIP_CALLBACK_API */  #endif /* LWIP_CALLBACK_API */
395        
396      /* Register the new PCB so that we can begin receiving segments      /* Register the new PCB so that we can begin receiving segments
397         for it. */         for it. */
398      TCP_REG(&tcp_active_pcbs, npcb);      TCP_REG(&tcp_active_pcbs, npcb);
399        
400      /* Parse any options in the SYN. */      /* Parse any options in the SYN. */
401      tcp_parseopt(npcb);      tcp_parseopt(npcb);
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. */
# Line 444  tcp_process(struct tcp_pcb *pcb) Line 444  tcp_process(struct tcp_pcb *pcb)
444    struct tcp_seg *rseg;    struct tcp_seg *rseg;
445    u8_t acceptable = 0;    u8_t acceptable = 0;
446    err_t err;    err_t err;
447      
448    
449    err = ERR_OK;    err = ERR_OK;
450      
451    /* Process incoming RST segments. */    /* Process incoming RST segments. */
452    if (flags & TCP_RST) {    if (flags & TCP_RST) {
453      /* First, determine if the reset is acceptable. */      /* First, determine if the reset is acceptable. */
# Line 461  tcp_process(struct tcp_pcb *pcb) Line 461  tcp_process(struct tcp_pcb *pcb)
461    acceptable = 1;    acceptable = 1;
462        }        }
463      }      }
464        
465      if (acceptable) {      if (acceptable) {
466        LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n"));        LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n"));
467        LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED);        LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED);
# Line 479  tcp_process(struct tcp_pcb *pcb) Line 479  tcp_process(struct tcp_pcb *pcb)
479    
480    /* Update the PCB (in)activity timer. */    /* Update the PCB (in)activity timer. */
481    pcb->tmr = tcp_ticks;    pcb->tmr = tcp_ticks;
482      
483    /* Do different things depending on the TCP state. */    /* Do different things depending on the TCP state. */
484    switch (pcb->state) {    switch (pcb->state) {
485    case SYN_SENT:    case SYN_SENT:
# Line 493  tcp_process(struct tcp_pcb *pcb) Line 493  tcp_process(struct tcp_pcb *pcb)
493        pcb->state = ESTABLISHED;        pcb->state = ESTABLISHED;
494        pcb->cwnd = pcb->mss;        pcb->cwnd = pcb->mss;
495        --pcb->snd_queuelen;        --pcb->snd_queuelen;
496        LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %d\n", pcb->snd_queuelen));        LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %u\n", (unsigned int)pcb->snd_queuelen));
497        rseg = pcb->unacked;        rseg = pcb->unacked;
498        pcb->unacked = rseg->next;        pcb->unacked = rseg->next;
499        tcp_seg_free(rseg);        tcp_seg_free(rseg);
# Line 505  tcp_process(struct tcp_pcb *pcb) Line 505  tcp_process(struct tcp_pcb *pcb)
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      }          }
509      break;      break;
510    case SYN_RCVD:    case SYN_RCVD:
511      if (flags & TCP_ACK &&      if (flags & TCP_ACK &&
# Line 513  tcp_process(struct tcp_pcb *pcb) Line 513  tcp_process(struct tcp_pcb *pcb)
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          LWIP_DEBUGF(DEMO_DEBUG, ("TCP connection established %d -> %d.\n", inseg.tcphdr->src, inseg.tcphdr->dest));          LWIP_DEBUGF(DEMO_DEBUG, ("TCP connection established %u -> %u.\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);
# Line 522  tcp_process(struct tcp_pcb *pcb) Line 522  tcp_process(struct tcp_pcb *pcb)
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 561  tcp_process(struct tcp_pcb *pcb) Line 561  tcp_process(struct tcp_pcb *pcb)
561    case FIN_WAIT_2:    case FIN_WAIT_2:
562      tcp_receive(pcb);      tcp_receive(pcb);
563      if (flags & TCP_FIN) {      if (flags & TCP_FIN) {
564        LWIP_DEBUGF(DEMO_DEBUG, ("TCP connection closed %d -> %d.\n", inseg.tcphdr->src, inseg.tcphdr->dest));        LWIP_DEBUGF(DEMO_DEBUG, ("TCP connection closed %u -> %u.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
565        tcp_ack_now(pcb);        tcp_ack_now(pcb);
566        tcp_pcb_purge(pcb);        tcp_pcb_purge(pcb);
567        TCP_RMV(&tcp_active_pcbs, pcb);        TCP_RMV(&tcp_active_pcbs, pcb);
# Line 572  tcp_process(struct tcp_pcb *pcb) Line 572  tcp_process(struct tcp_pcb *pcb)
572    case CLOSING:    case CLOSING:
573      tcp_receive(pcb);      tcp_receive(pcb);
574      if (flags & TCP_ACK && ackno == pcb->snd_nxt) {      if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
575        LWIP_DEBUGF(DEMO_DEBUG, ("TCP connection closed %d -> %d.\n", inseg.tcphdr->src, inseg.tcphdr->dest));        LWIP_DEBUGF(DEMO_DEBUG, ("TCP connection closed %u -> %u.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
576        tcp_ack_now(pcb);        tcp_ack_now(pcb);
577        tcp_pcb_purge(pcb);        tcp_pcb_purge(pcb);
578        TCP_RMV(&tcp_active_pcbs, pcb);        TCP_RMV(&tcp_active_pcbs, pcb);
# Line 583  tcp_process(struct tcp_pcb *pcb) Line 583  tcp_process(struct tcp_pcb *pcb)
583    case LAST_ACK:    case LAST_ACK:
584      tcp_receive(pcb);      tcp_receive(pcb);
585      if (flags & TCP_ACK && ackno == pcb->snd_nxt) {      if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
586        LWIP_DEBUGF(DEMO_DEBUG, ("TCP connection closed %d -> %d.\n", inseg.tcphdr->src, inseg.tcphdr->dest));        LWIP_DEBUGF(DEMO_DEBUG, ("TCP connection closed %u -> %u.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
587        pcb->state = CLOSED;        pcb->state = CLOSED;
588        recv_flags = TF_CLOSED;        recv_flags = TF_CLOSED;
589      }      }
# Line 591  tcp_process(struct tcp_pcb *pcb) Line 591  tcp_process(struct tcp_pcb *pcb)
591    default:    default:
592      break;      break;
593    }    }
594      
595    return ERR_OK;    return ERR_OK;
596  }  }
597  /*-----------------------------------------------------------------------------------*/  /*-----------------------------------------------------------------------------------*/
# Line 619  tcp_receive(struct tcp_pcb *pcb) Line 619  tcp_receive(struct tcp_pcb *pcb)
619    int m;    int m;
620    u32_t right_wnd_edge;    u32_t right_wnd_edge;
621    
622          
623    if (flags & TCP_ACK) {    if (flags & TCP_ACK) {
624      right_wnd_edge = pcb->snd_wnd + pcb->snd_wl1;      right_wnd_edge = pcb->snd_wnd + pcb->snd_wl1;
625    
# Line 639  tcp_receive(struct tcp_pcb *pcb) Line 639  tcp_receive(struct tcp_pcb *pcb)
639        }        }
640  #endif /* TCP_WND_DEBUG */  #endif /* TCP_WND_DEBUG */
641      }      }
642        
643    
644      if (pcb->lastack == ackno) {      if (pcb->lastack == ackno) {
645        pcb->acked = 0;        pcb->acked = 0;
# Line 649  tcp_receive(struct tcp_pcb *pcb) Line 649  tcp_receive(struct tcp_pcb *pcb)
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        LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupacks %d (%lu), fast retransmit %lu\n",        LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupacks %u (%lu), fast retransmit %lu\n",
653            pcb->dupacks, pcb->lastack,            (unsigned int)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. */
# Line 670  tcp_receive(struct tcp_pcb *pcb) Line 670  tcp_receive(struct tcp_pcb *pcb)
670    }    }
671        } else {        } else {
672    LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupack averted %lu %lu\n",    LWIP_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 686  tcp_receive(struct tcp_pcb *pcb) Line 686  tcp_receive(struct tcp_pcb *pcb)
686    
687        /* Reset the number of retransmissions. */        /* Reset the number of retransmissions. */
688        pcb->nrtx = 0;        pcb->nrtx = 0;
689          
690        /* Reset the retransmission time-out. */        /* Reset the retransmission time-out. */
691        pcb->rto = (pcb->sa >> 3) + pcb->sv;        pcb->rto = (pcb->sa >> 3) + pcb->sv;
692          
693        /* Update the send buffer space. */        /* Update the send buffer space. */
694        pcb->acked = ackno - pcb->lastack;        pcb->acked = ackno - pcb->lastack;
695        pcb->snd_buf += pcb->acked;        pcb->snd_buf += pcb->acked;
# Line 697  tcp_receive(struct tcp_pcb *pcb) Line 697  tcp_receive(struct tcp_pcb *pcb)
697        /* Reset the fast retransmit variables. */        /* Reset the fast retransmit variables. */
698        pcb->dupacks = 0;        pcb->dupacks = 0;
699        pcb->lastack = ackno;        pcb->lastack = ackno;
700          
701        /* Update the congestion control variables (cwnd and        /* Update the congestion control variables (cwnd and
702           ssthresh). */           ssthresh). */
703        if (pcb->state >= ESTABLISHED) {        if (pcb->state >= ESTABLISHED) {
# Line 711  tcp_receive(struct tcp_pcb *pcb) Line 711  tcp_receive(struct tcp_pcb *pcb)
711      if (new_cwnd > pcb->cwnd) {      if (new_cwnd > pcb->cwnd) {
712        pcb->cwnd = new_cwnd;        pcb->cwnd = new_cwnd;
713      }      }
714            LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %u\n", pcb->cwnd));            LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %u\n", pcb->cwnd));
715          }          }
716        }        }
717        LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %lu, unacked->seqno %lu:%lu\n",        LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %lu, unacked->seqno %lu:%lu\n",
# Line 723  tcp_receive(struct tcp_pcb *pcb) Line 723  tcp_receive(struct tcp_pcb *pcb)
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    LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %lu:%lu from pcb->unacked\n",    LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %lu:%lu from pcb->unacked\n",
# Line 733  tcp_receive(struct tcp_pcb *pcb) Line 733  tcp_receive(struct tcp_pcb *pcb)
733    
734    next = pcb->unacked;    next = pcb->unacked;
735    pcb->unacked = pcb->unacked->next;    pcb->unacked = pcb->unacked->next;
736      
737    LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %d ... ", pcb->snd_queuelen));    LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %u ... ", (unsigned int)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    LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%d (after freeing unacked)\n", pcb->snd_queuelen));    LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%u (after freeing unacked)\n", (unsigned int)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;
# Line 753  tcp_receive(struct tcp_pcb *pcb) Line 753  tcp_receive(struct tcp_pcb *pcb)
753           rationale is that lwIP puts all outstanding segments on the           rationale is that lwIP puts all outstanding segments on the
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)) {
# Line 764  tcp_receive(struct tcp_pcb *pcb) Line 764  tcp_receive(struct tcp_pcb *pcb)
764    
765    next = pcb->unsent;    next = pcb->unsent;
766    pcb->unsent = pcb->unsent->next;    pcb->unsent = pcb->unsent->next;
767    LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %d ... ", pcb->snd_queuelen));    LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %u ... ", (unsigned int)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    LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%d (after freeing unsent)\n", pcb->snd_queuelen));    LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%u (after freeing unsent)\n", (unsigned int)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          }          }
779        }        }
780          
781      /* End of ACK for new data processing. */      /* End of ACK for new data processing. */
782        
783      LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %d rtseq %lu ackno %lu\n",      LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %u 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
788         round-trip time measurement. */         round-trip time measurement. */
789      if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) {      if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) {
790        m = tcp_ticks - pcb->rttest;        m = tcp_ticks - pcb->rttest;
791    
792        LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %d ticks (%d msec).\n",        LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %u ticks (%u 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) {
# Line 801  tcp_receive(struct tcp_pcb *pcb) Line 801  tcp_receive(struct tcp_pcb *pcb)
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        LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %d (%d miliseconds)\n",        LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %u (%u 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      }      }
810    }    }
811      
812    /* If the incoming segment contains data, we must process it    /* If the incoming segment contains data, we must process it
813       further. */       further. */
814    if (tcplen > 0) {    if (tcplen > 0) {
# Line 817  tcp_receive(struct tcp_pcb *pcb) Line 817  tcp_receive(struct tcp_pcb *pcb)
817       +) If the incoming segment contains data that is the next       +) If the incoming segment contains data that is the next
818          in-sequence data, this data is passed to the application. This          in-sequence data, this data is passed to the application. This
819          might involve trimming the first edge of the data. The rcv_nxt          might involve trimming the first edge of the data. The rcv_nxt
820          variable and the advertised window are adjusted.                variable and the advertised window are adjusted.
821    
822       +) If the incoming segment has data that is above the next       +) If the incoming segment has data that is above the next
823          sequence number expected (->rcv_nxt), the segment is placed on          sequence number expected (->rcv_nxt), the segment is placed on
# Line 847  tcp_receive(struct tcp_pcb *pcb) Line 847  tcp_receive(struct tcp_pcb *pcb)
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
# Line 857  tcp_receive(struct tcp_pcb *pcb) Line 857  tcp_receive(struct tcp_pcb *pcb)
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.*/
# Line 875  tcp_receive(struct tcp_pcb *pcb) Line 875  tcp_receive(struct tcp_pcb *pcb)
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    LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %lu\n", seqno));    LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %lu\n", seqno));
886    tcp_ack_now(pcb);    tcp_ack_now(pcb);
887        }        }
# 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. */
# Line 907  tcp_receive(struct tcp_pcb *pcb) Line 907  tcp_receive(struct tcp_pcb *pcb)
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
# Line 937  tcp_receive(struct tcp_pcb *pcb) Line 937  tcp_receive(struct tcp_pcb *pcb)
937      LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN."));      LWIP_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. */
# Line 946  tcp_receive(struct tcp_pcb *pcb) Line 946  tcp_receive(struct tcp_pcb *pcb)
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;
# Line 967  tcp_receive(struct tcp_pcb *pcb) Line 967  tcp_receive(struct tcp_pcb *pcb)
967      if (flags & TCP_FIN) {      if (flags & TCP_FIN) {
968        LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN."));        LWIP_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);
# Line 1025  tcp_receive(struct tcp_pcb *pcb) Line 1025  tcp_receive(struct tcp_pcb *pcb)
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)) {
# Line 1033  tcp_receive(struct tcp_pcb *pcb) Line 1033  tcp_receive(struct tcp_pcb *pcb)
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;
# Line 1060  tcp_receive(struct tcp_pcb *pcb) Line 1060  tcp_receive(struct tcp_pcb *pcb)
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)) {
# Line 1077  tcp_receive(struct tcp_pcb *pcb) Line 1077  tcp_receive(struct tcp_pcb *pcb)
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;
# Line 1088  tcp_receive(struct tcp_pcb *pcb) Line 1088  tcp_receive(struct tcp_pcb *pcb)
1088          }          }
1089        }        }
1090        prev = next;        prev = next;
1091      }          }
1092    }    }
1093  #endif /* TCP_QUEUE_OOSEQ */  #endif /* TCP_QUEUE_OOSEQ */
1094          
1095        }            }
1096      }      }
1097    } else {    } else {
1098      /* Segments with length 0 is taken care of here. Segments that      /* Segments with length 0 is taken care of here. Segments that
# Line 1100  tcp_receive(struct tcp_pcb *pcb) Line 1100  tcp_receive(struct tcp_pcb *pcb)
1100      if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) ||      if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) ||
1101         TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {         TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {
1102        tcp_ack_now(pcb);        tcp_ack_now(pcb);
1103      }            }
1104    }    }
1105  }  }
1106  /*-----------------------------------------------------------------------------------*/  /*-----------------------------------------------------------------------------------*/
# Line 1109  tcp_receive(struct tcp_pcb *pcb) Line 1109  tcp_receive(struct tcp_pcb *pcb)
1109   *   *
1110   * Parses the options contained in the incoming segment. (Code taken   * Parses the options contained in the incoming segment. (Code taken
1111   * from uIP with only small changes.)   * from uIP with only small changes.)
1112   *   *
1113   */   */
1114  /*-----------------------------------------------------------------------------------*/  /*-----------------------------------------------------------------------------------*/
1115  static void  static void
# Line 1120  tcp_parseopt(struct tcp_pcb *pcb) Line 1120  tcp_parseopt(struct tcp_pcb *pcb)
1120    u16_t mss;    u16_t mss;
1121    
1122    opts = (u8_t *)tcphdr + TCP_HLEN;    opts = (u8_t *)tcphdr + TCP_HLEN;
1123      
1124    /* Parse the TCP MSS option, if present. */    /* Parse the TCP MSS option, if present. */
1125    if ((TCPH_OFFSET(tcphdr) & 0xf0) > 0x50) {    if ((TCPH_OFFSET(tcphdr) & 0xf0) > 0x50) {
1126      for(c = 0; c < ((TCPH_OFFSET(tcphdr) >> 4) - 5) << 2 ;) {      for(c = 0; c < ((TCPH_OFFSET(tcphdr) >> 4) - 5) << 2 ;) {
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. */
1134        } else if (opt == 0x02 &&        } else if (opt == 0x02 &&
1135                  opts[c + 1] == 0x04) {                  opts[c + 1] == 0x04) {
1136          /* An MSS option with the right option length. */                /* An MSS option with the right option length. */
1137          mss = (opts[c + 2] << 8) | opts[c + 3];          mss = (opts[c + 2] << 8) | opts[c + 3];
1138          pcb->mss = mss > TCP_MSS? TCP_MSS: mss;          pcb->mss = mss > TCP_MSS? TCP_MSS: mss;
1139            
1140          /* And we are done processing options. */          /* And we are done processing options. */
1141          break;          break;
1142        } else {        } else {
# Line 1148  tcp_parseopt(struct tcp_pcb *pcb) Line 1148  tcp_parseopt(struct tcp_pcb *pcb)
1148          /* All other options have a length field, so that we easily          /* All other options have a length field, so that we easily
1149             can skip past them. */             can skip past them. */
1150          c += opts[c + 1];          c += opts[c + 1];
1151        }              }
1152      }      }
1153    }    }
1154  }  }
1155  #endif /* LWIP_TCP */  #endif /* LWIP_TCP */
1156  /*-----------------------------------------------------------------------------------*/  /*-----------------------------------------------------------------------------------*/
1157      

Legend:
Removed from v.1.29  
changed lines
  Added in v.1.30

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