Back to home page

Quest Cross Reference

 
 

    


Warning, cross-references for /kernel/lwip/core/tcp_in.c need to be fixed.

0001 /**
0002  * @file
0003  * Transmission Control Protocol, incoming traffic
0004  *
0005  * The input processing functions of the TCP layer.
0006  *
0007  * These functions are generally called in the order (ip_input() ->)
0008  * tcp_input() -> * tcp_process() -> tcp_receive() (-> application).
0009  * 
0010  */
0011 
0012 /*
0013  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
0014  * All rights reserved.
0015  *
0016  * Redistribution and use in source and binary forms, with or without modification,
0017  * are permitted provided that the following conditions are met:
0018  *
0019  * 1. Redistributions of source code must retain the above copyright notice,
0020  *    this list of conditions and the following disclaimer.
0021  * 2. Redistributions in binary form must reproduce the above copyright notice,
0022  *    this list of conditions and the following disclaimer in the documentation
0023  *    and/or other materials provided with the distribution.
0024  * 3. The name of the author may not be used to endorse or promote products
0025  *    derived from this software without specific prior written permission.
0026  *
0027  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
0028  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
0029  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
0030  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
0031  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
0032  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0033  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0034  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
0035  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
0036  * OF SUCH DAMAGE.
0037  *
0038  * This file is part of the lwIP TCP/IP stack.
0039  *
0040  * Author: Adam Dunkels <adam@sics.se>
0041  *
0042  */
0043 
0044 #include "lwip/opt.h"
0045 
0046 #if LWIP_TCP /* don't build if not configured for use in lwipopts.h */
0047 
0048 #include "lwip/tcp.h"
0049 #include "lwip/def.h"
0050 #include "lwip/ip_addr.h"
0051 #include "lwip/netif.h"
0052 #include "lwip/mem.h"
0053 #include "lwip/memp.h"
0054 #include "lwip/inet.h"
0055 #include "lwip/inet_chksum.h"
0056 #include "lwip/stats.h"
0057 #include "lwip/snmp.h"
0058 #include "arch/perf.h"
0059 
0060 /* These variables are global to all functions involved in the input
0061    processing of TCP segments. They are set by the tcp_input()
0062    function. */
0063 static struct tcp_seg inseg;
0064 static struct tcp_hdr *tcphdr;
0065 static struct ip_hdr *iphdr;
0066 static u32_t seqno, ackno;
0067 static u8_t flags;
0068 static u16_t tcplen;
0069 
0070 static u8_t recv_flags;
0071 static struct pbuf *recv_data;
0072 
0073 struct tcp_pcb *tcp_input_pcb;
0074 
0075 /* Forward declarations. */
0076 static err_t tcp_process(struct tcp_pcb *pcb);
0077 static void tcp_receive(struct tcp_pcb *pcb);
0078 static void tcp_parseopt(struct tcp_pcb *pcb);
0079 
0080 static err_t tcp_listen_input(struct tcp_pcb_listen *pcb);
0081 static err_t tcp_timewait_input(struct tcp_pcb *pcb);
0082 
0083 /**
0084  * The initial input processing of TCP. It verifies the TCP header, demultiplexes
0085  * the segment between the PCBs and passes it on to tcp_process(), which implements
0086  * the TCP finite state machine. This function is called by the IP layer (in
0087  * ip_input()).
0088  *
0089  * @param p received TCP segment to process (p->payload pointing to the IP header)
0090  * @param inp network interface on which this segment was received
0091  */
0092 void
0093 tcp_input(struct pbuf *p, struct netif *inp)
0094 {
0095   struct tcp_pcb *pcb, *prev;
0096   struct tcp_pcb_listen *lpcb;
0097   u8_t hdrlen;
0098   err_t err;
0099 
0100   PERF_START;
0101 
0102   TCP_STATS_INC(tcp.recv);
0103   snmp_inc_tcpinsegs();
0104 
0105   iphdr = p->payload;
0106   tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4);
0107 
0108 #if TCP_INPUT_DEBUG
0109   tcp_debug_print(tcphdr);
0110 #endif
0111 
0112   /* remove header from payload */
0113   if (pbuf_header(p, -((s16_t)(IPH_HL(iphdr) * 4))) || (p->tot_len < sizeof(struct tcp_hdr))) {
0114     /* drop short packets */
0115     LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len));
0116     TCP_STATS_INC(tcp.lenerr);
0117     TCP_STATS_INC(tcp.drop);
0118     snmp_inc_tcpinerrs();
0119     pbuf_free(p);
0120     return;
0121   }
0122 
0123   /* Don't even process incoming broadcasts/multicasts. */
0124   if (ip_addr_isbroadcast(&(iphdr->dest), inp) ||
0125       ip_addr_ismulticast(&(iphdr->dest))) {
0126     TCP_STATS_INC(tcp.proterr);
0127     TCP_STATS_INC(tcp.drop);
0128     snmp_inc_tcpinerrs();
0129     pbuf_free(p);
0130     return;
0131   }
0132 
0133 #if CHECKSUM_CHECK_TCP
0134   /* Verify TCP checksum. */
0135   if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
0136       (struct ip_addr *)&(iphdr->dest),
0137       IP_PROTO_TCP, p->tot_len) != 0) {
0138       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n",
0139         inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src), (struct ip_addr *)&(iphdr->dest),
0140       IP_PROTO_TCP, p->tot_len)));
0141 #if TCP_DEBUG
0142     tcp_debug_print(tcphdr);
0143 #endif /* TCP_DEBUG */
0144     TCP_STATS_INC(tcp.chkerr);
0145     TCP_STATS_INC(tcp.drop);
0146     snmp_inc_tcpinerrs();
0147     pbuf_free(p);
0148     return;
0149   }
0150 #endif
0151 
0152   /* Move the payload pointer in the pbuf so that it points to the
0153      TCP data instead of the TCP header. */
0154   hdrlen = TCPH_HDRLEN(tcphdr);
0155   if(pbuf_header(p, -(hdrlen * 4))){
0156     /* drop short packets */
0157     LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet\n"));
0158     TCP_STATS_INC(tcp.lenerr);
0159     TCP_STATS_INC(tcp.drop);
0160     snmp_inc_tcpinerrs();
0161     pbuf_free(p);
0162     return;
0163   }
0164 
0165   /* Convert fields in TCP header to host byte order. */
0166   tcphdr->src = ntohs(tcphdr->src);
0167   tcphdr->dest = ntohs(tcphdr->dest);
0168   seqno = tcphdr->seqno = ntohl(tcphdr->seqno);
0169   ackno = tcphdr->ackno = ntohl(tcphdr->ackno);
0170   tcphdr->wnd = ntohs(tcphdr->wnd);
0171 
0172   flags = TCPH_FLAGS(tcphdr);
0173   tcplen = p->tot_len + ((flags & (TCP_FIN | TCP_SYN)) ? 1 : 0);
0174 
0175   /* Demultiplex an incoming segment. First, we check if it is destined
0176      for an active connection. */
0177   prev = NULL;
0178 
0179   
0180   for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
0181     LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED);
0182     LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
0183     LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
0184     if (pcb->remote_port == tcphdr->src &&
0185        pcb->local_port == tcphdr->dest &&
0186        ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
0187        ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
0188 
0189       /* Move this PCB to the front of the list so that subsequent
0190          lookups will be faster (we exploit locality in TCP segment
0191          arrivals). */
0192       LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb);
0193       if (prev != NULL) {
0194         prev->next = pcb->next;
0195         pcb->next = tcp_active_pcbs;
0196         tcp_active_pcbs = pcb;
0197       }
0198       LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb);
0199       break;
0200     }
0201     prev = pcb;
0202   }
0203 
0204   if (pcb == NULL) {
0205     /* If it did not go to an active connection, we check the connections
0206        in the TIME-WAIT state. */
0207     for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
0208       LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
0209       if (pcb->remote_port == tcphdr->src &&
0210          pcb->local_port == tcphdr->dest &&
0211          ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
0212          ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
0213         /* We don't really care enough to move this PCB to the front
0214            of the list since we are not very likely to receive that
0215            many segments for connections in TIME-WAIT. */
0216         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n"));
0217         tcp_timewait_input(pcb);
0218         pbuf_free(p);
0219         return;
0220       }
0221     }
0222 
0223   /* Finally, if we still did not get a match, we check all PCBs that
0224      are LISTENing for incoming connections. */
0225     prev = NULL;
0226     for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
0227       if ((ip_addr_isany(&(lpcb->local_ip)) ||
0228         ip_addr_cmp(&(lpcb->local_ip), &(iphdr->dest))) &&
0229         lpcb->local_port == tcphdr->dest) {
0230         /* Move this PCB to the front of the list so that subsequent
0231            lookups will be faster (we exploit locality in TCP segment
0232            arrivals). */
0233         if (prev != NULL) {
0234           ((struct tcp_pcb_listen *)prev)->next = lpcb->next;
0235                 /* our successor is the remainder of the listening list */
0236           lpcb->next = tcp_listen_pcbs.listen_pcbs;
0237                 /* put this listening pcb at the head of the listening list */
0238           tcp_listen_pcbs.listen_pcbs = lpcb;
0239         }
0240       
0241         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n"));
0242         tcp_listen_input(lpcb);
0243         pbuf_free(p);
0244         return;
0245       }
0246       prev = (struct tcp_pcb *)lpcb;
0247     }
0248   }
0249 
0250 #if TCP_INPUT_DEBUG
0251   LWIP_DEBUGF(TCP_INPUT_DEBUG, ("+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags "));
0252   tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
0253   LWIP_DEBUGF(TCP_INPUT_DEBUG, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n"));
0254 #endif /* TCP_INPUT_DEBUG */
0255 
0256 
0257   if (pcb != NULL) {
0258     /* The incoming segment belongs to a connection. */
0259 #if TCP_INPUT_DEBUG
0260 #if TCP_DEBUG
0261     tcp_debug_print_state(pcb->state);
0262 #endif /* TCP_DEBUG */
0263 #endif /* TCP_INPUT_DEBUG */
0264 
0265     /* Set up a tcp_seg structure. */
0266     inseg.next = NULL;
0267     inseg.len = p->tot_len;
0268     inseg.dataptr = p->payload;
0269     inseg.p = p;
0270     inseg.tcphdr = tcphdr;
0271 
0272     recv_data = NULL;
0273     recv_flags = 0;
0274 
0275     /* If there is data which was previously "refused" by upper layer */
0276     if (pcb->refused_data != NULL) {
0277       /* Notify again application with data previously received. */
0278       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: notify kept packet\n"));
0279       TCP_EVENT_RECV(pcb, pcb->refused_data, ERR_OK, err);
0280       if (err == ERR_OK) {
0281         pcb->refused_data = NULL;
0282       } else {
0283         /* drop incoming packets, because pcb is "full" */
0284         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n"));
0285         TCP_STATS_INC(tcp.drop);
0286         snmp_inc_tcpinerrs();
0287         pbuf_free(p);
0288         return;
0289       }
0290     }
0291     tcp_input_pcb = pcb;
0292     err = tcp_process(pcb);
0293     /* A return value of ERR_ABRT means that tcp_abort() was called
0294        and that the pcb has been freed. If so, we don't do anything. */
0295     if (err != ERR_ABRT) {
0296       if (recv_flags & TF_RESET) {
0297         /* TF_RESET means that the connection was reset by the other
0298            end. We then call the error callback to inform the
0299            application that the connection is dead before we
0300            deallocate the PCB. */
0301         TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST);
0302         tcp_pcb_remove(&tcp_active_pcbs, pcb);
0303         memp_free(MEMP_TCP_PCB, pcb);
0304       } else if (recv_flags & TF_CLOSED) {
0305         /* The connection has been closed and we will deallocate the
0306            PCB. */
0307         tcp_pcb_remove(&tcp_active_pcbs, pcb);
0308         memp_free(MEMP_TCP_PCB, pcb);
0309       } else {
0310         err = ERR_OK;
0311         /* If the application has registered a "sent" function to be
0312            called when new send buffer space is available, we call it
0313            now. */
0314         if (pcb->acked > 0) {
0315           TCP_EVENT_SENT(pcb, pcb->acked, err);
0316         }
0317       
0318         if (recv_data != NULL) {
0319           if(flags & TCP_PSH) {
0320             recv_data->flags |= PBUF_FLAG_PUSH;
0321           }
0322 
0323           /* Notify application that data has been received. */
0324           TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err);
0325 
0326           /* If the upper layer can't receive this data, store it */
0327           if (err != ERR_OK) {
0328             pcb->refused_data = recv_data;
0329             LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: keep incoming packet, because pcb is \"full\"\n"));
0330           }
0331         }
0332 
0333         /* If a FIN segment was received, we call the callback
0334            function with a NULL buffer to indicate EOF. */
0335         if (recv_flags & TF_GOT_FIN) {
0336           TCP_EVENT_RECV(pcb, NULL, ERR_OK, err);
0337         }
0338 
0339         tcp_input_pcb = NULL;
0340         /* Try to send something out. */
0341         tcp_output(pcb);
0342 #if TCP_INPUT_DEBUG
0343 #if TCP_DEBUG
0344         tcp_debug_print_state(pcb->state);
0345 #endif /* TCP_DEBUG */
0346 #endif /* TCP_INPUT_DEBUG */
0347       }
0348     }
0349     tcp_input_pcb = NULL;
0350 
0351 
0352     /* give up our reference to inseg.p */
0353     if (inseg.p != NULL)
0354     {
0355       pbuf_free(inseg.p);
0356       inseg.p = NULL;
0357     }
0358   } else {
0359 
0360     /* If no matching PCB was found, send a TCP RST (reset) to the
0361        sender. */
0362     LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n"));
0363     if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) {
0364       TCP_STATS_INC(tcp.proterr);
0365       TCP_STATS_INC(tcp.drop);
0366       tcp_rst(ackno, seqno + tcplen,
0367         &(iphdr->dest), &(iphdr->src),
0368         tcphdr->dest, tcphdr->src);
0369     }
0370     pbuf_free(p);
0371   }
0372 
0373   LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());
0374   PERF_STOP("tcp_input");
0375 }
0376 
0377 /**
0378  * Called by tcp_input() when a segment arrives for a listening
0379  * connection (from tcp_input()).
0380  *
0381  * @param pcb the tcp_pcb_listen for which a segment arrived
0382  * @return ERR_OK if the segment was processed
0383  *         another err_t on error
0384  *
0385  * @note the return value is not (yet?) used in tcp_input()
0386  * @note the segment which arrived is saved in global variables, therefore only the pcb
0387  *       involved is passed as a parameter to this function
0388  */
0389 static err_t
0390 tcp_listen_input(struct tcp_pcb_listen *pcb)
0391 {
0392   struct tcp_pcb *npcb;
0393   err_t rc;
0394 
0395   /* In the LISTEN state, we check for incoming SYN segments,
0396      creates a new PCB, and responds with a SYN|ACK. */
0397   if (flags & TCP_ACK) {
0398     /* For incoming segments with the ACK flag set, respond with a
0399        RST. */
0400     LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n"));
0401     tcp_rst(ackno + 1, seqno + tcplen,
0402       &(iphdr->dest), &(iphdr->src),
0403       tcphdr->dest, tcphdr->src);
0404   } else if (flags & TCP_SYN) {
0405     LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest));
0406 #if TCP_LISTEN_BACKLOG
0407     if (pcb->accepts_pending >= pcb->backlog) {
0408       LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: listen backlog exceeded for port %"U16_F"\n", tcphdr->dest));
0409       return ERR_ABRT;
0410     }
0411 #endif /* TCP_LISTEN_BACKLOG */
0412     npcb = tcp_alloc(pcb->prio);
0413     /* If a new PCB could not be created (probably due to lack of memory),
0414        we don't do anything, but rely on the sender will retransmit the
0415        SYN at a time when we have more memory available. */
0416     if (npcb == NULL) {
0417       LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n"));
0418       TCP_STATS_INC(tcp.memerr);
0419       return ERR_MEM;
0420     }
0421 #if TCP_LISTEN_BACKLOG
0422     pcb->accepts_pending++;
0423 #endif /* TCP_LISTEN_BACKLOG */
0424     /* Set up the new PCB. */
0425     ip_addr_set(&(npcb->local_ip), &(iphdr->dest));
0426     npcb->local_port = pcb->local_port;
0427     ip_addr_set(&(npcb->remote_ip), &(iphdr->src));
0428     npcb->remote_port = tcphdr->src;
0429     npcb->state = SYN_RCVD;
0430     npcb->rcv_nxt = seqno + 1;
0431     npcb->rcv_ann_right_edge = npcb->rcv_nxt;
0432     npcb->snd_wnd = tcphdr->wnd;
0433     npcb->ssthresh = npcb->snd_wnd;
0434     npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */
0435     npcb->callback_arg = pcb->callback_arg;
0436 #if LWIP_CALLBACK_API
0437     npcb->accept = pcb->accept;
0438 #endif /* LWIP_CALLBACK_API */
0439     /* inherit socket options */
0440     npcb->so_options = pcb->so_options & (SOF_DEBUG|SOF_DONTROUTE|SOF_KEEPALIVE|SOF_OOBINLINE|SOF_LINGER);
0441     /* Register the new PCB so that we can begin receiving segments
0442        for it. */
0443     TCP_REG(&tcp_active_pcbs, npcb);
0444 
0445     /* Parse any options in the SYN. */
0446     tcp_parseopt(npcb);
0447 #if TCP_CALCULATE_EFF_SEND_MSS
0448     npcb->mss = tcp_eff_send_mss(npcb->mss, &(npcb->remote_ip));
0449 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
0450 
0451     snmp_inc_tcppassiveopens();
0452 
0453     /* Send a SYN|ACK together with the MSS option. */
0454     rc = tcp_enqueue(npcb, NULL, 0, TCP_SYN | TCP_ACK, 0, TF_SEG_OPTS_MSS
0455 #if LWIP_TCP_TIMESTAMPS
0456       /* and maybe include the TIMESTAMP option */
0457      | (npcb->flags & TF_TIMESTAMP ? TF_SEG_OPTS_TS : 0)
0458 #endif
0459       );
0460     if (rc != ERR_OK) {
0461       tcp_abandon(npcb, 0);
0462       return rc;
0463     }
0464     return tcp_output(npcb);
0465   }
0466   return ERR_OK;
0467 }
0468 
0469 /**
0470  * Called by tcp_input() when a segment arrives for a connection in
0471  * TIME_WAIT.
0472  *
0473  * @param pcb the tcp_pcb for which a segment arrived
0474  *
0475  * @note the segment which arrived is saved in global variables, therefore only the pcb
0476  *       involved is passed as a parameter to this function
0477  */
0478 static err_t
0479 tcp_timewait_input(struct tcp_pcb *pcb)
0480 {
0481   /* RFC 1337: in TIME_WAIT, ignore RST and ACK FINs + any 'acceptable' segments */
0482   /* RFC 793 3.9 Event Processing - Segment Arrives:
0483    * - first check sequence number - we skip that one in TIME_WAIT (always
0484    *   acceptable since we only send ACKs)
0485    * - second check the RST bit (... return) */
0486   if (flags & TCP_RST)  {
0487     return ERR_OK;
0488   }
0489   /* - fourth, check the SYN bit, */
0490   if (flags & TCP_SYN) {
0491     /* If an incoming segment is not acceptable, an acknowledgment
0492        should be sent in reply */
0493     if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) {
0494       /* If the SYN is in the window it is an error, send a reset */
0495       tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src),
0496         tcphdr->dest, tcphdr->src);
0497       return ERR_OK;
0498     }
0499   } else if (flags & TCP_FIN) {
0500     /* - eighth, check the FIN bit: Remain in the TIME-WAIT state.
0501          Restart the 2 MSL time-wait timeout.*/
0502     pcb->tmr = tcp_ticks;
0503   }
0504 
0505   if ((tcplen > 0))  {
0506     /* Acknowledge data, FIN or out-of-window SYN */
0507     pcb->flags |= TF_ACK_NOW;
0508     return tcp_output(pcb);
0509   }
0510   return ERR_OK;
0511 }
0512 
0513 /**
0514  * Implements the TCP state machine. Called by tcp_input. In some
0515  * states tcp_receive() is called to receive data. The tcp_seg
0516  * argument will be freed by the caller (tcp_input()) unless the
0517  * recv_data pointer in the pcb is set.
0518  *
0519  * @param pcb the tcp_pcb for which a segment arrived
0520  *
0521  * @note the segment which arrived is saved in global variables, therefore only the pcb
0522  *       involved is passed as a parameter to this function
0523  */
0524 static err_t
0525 tcp_process(struct tcp_pcb *pcb)
0526 {
0527   struct tcp_seg *rseg;
0528   u8_t acceptable = 0;
0529   err_t err;
0530 
0531   err = ERR_OK;
0532 
0533   /* Process incoming RST segments. */
0534   if (flags & TCP_RST) {
0535     /* First, determine if the reset is acceptable. */
0536     if (pcb->state == SYN_SENT) {
0537       if (ackno == pcb->snd_nxt) {
0538         acceptable = 1;
0539       }
0540     } else {
0541       if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, 
0542                           pcb->rcv_nxt+pcb->rcv_wnd)) {
0543         acceptable = 1;
0544       }
0545     }
0546 
0547     if (acceptable) {
0548       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n"));
0549       LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED);
0550       recv_flags |= TF_RESET;
0551       pcb->flags &= ~TF_ACK_DELAY;
0552       return ERR_RST;
0553     } else {
0554       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n",
0555        seqno, pcb->rcv_nxt));
0556       LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n",
0557        seqno, pcb->rcv_nxt));
0558       return ERR_OK;
0559     }
0560   }
0561 
0562   if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) { 
0563     /* Cope with new connection attempt after remote end crashed */
0564     tcp_ack_now(pcb);
0565     return ERR_OK;
0566   }
0567   
0568   /* Update the PCB (in)activity timer. */
0569   pcb->tmr = tcp_ticks;
0570   pcb->keep_cnt_sent = 0;
0571 
0572   tcp_parseopt(pcb);
0573 
0574   /* Do different things depending on the TCP state. */
0575   switch (pcb->state) {
0576   case SYN_SENT:
0577     LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno,
0578      pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno)));
0579     /* received SYN ACK with expected sequence number? */
0580     if ((flags & TCP_ACK) && (flags & TCP_SYN)
0581         && ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) {
0582       pcb->snd_buf++;
0583       pcb->rcv_nxt = seqno + 1;
0584       pcb->rcv_ann_right_edge = pcb->rcv_nxt;
0585       pcb->lastack = ackno;
0586       pcb->snd_wnd = tcphdr->wnd;
0587       pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */
0588       pcb->state = ESTABLISHED;
0589 
0590 #if TCP_CALCULATE_EFF_SEND_MSS
0591       pcb->mss = tcp_eff_send_mss(pcb->mss, &(pcb->remote_ip));
0592 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
0593 
0594       /* Set ssthresh again after changing pcb->mss (already set in tcp_connect
0595        * but for the default value of pcb->mss) */
0596       pcb->ssthresh = pcb->mss * 10;
0597 
0598       pcb->cwnd = ((pcb->cwnd == 1) ? (pcb->mss * 2) : pcb->mss);
0599       LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0));
0600       --pcb->snd_queuelen;
0601       LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"U16_F"\n", (u16_t)pcb->snd_queuelen));
0602       rseg = pcb->unacked;
0603       pcb->unacked = rseg->next;
0604 
0605       /* If there's nothing left to acknowledge, stop the retransmit
0606          timer, otherwise reset it to start again */
0607       if(pcb->unacked == NULL)
0608         pcb->rtime = -1;
0609       else {
0610         pcb->rtime = 0;
0611         pcb->nrtx = 0;
0612       }
0613 
0614       tcp_seg_free(rseg);
0615 
0616       /* Call the user specified function to call when sucessfully
0617        * connected. */
0618       TCP_EVENT_CONNECTED(pcb, ERR_OK, err);
0619       tcp_ack_now(pcb);
0620     }
0621     /* received ACK? possibly a half-open connection */
0622     else if (flags & TCP_ACK) {
0623       /* send a RST to bring the other side in a non-synchronized state. */
0624       tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src),
0625         tcphdr->dest, tcphdr->src);
0626     }
0627     break;
0628   case SYN_RCVD:
0629     if (flags & TCP_ACK) {
0630       /* expected ACK number? */
0631       if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) {
0632         u16_t old_cwnd;
0633         pcb->state = ESTABLISHED;
0634         LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
0635 #if LWIP_CALLBACK_API
0636         LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL);
0637 #endif
0638         /* Call the accept function. */
0639         TCP_EVENT_ACCEPT(pcb, ERR_OK, err);
0640         if (err != ERR_OK) {
0641           /* If the accept function returns with an error, we abort
0642            * the connection. */
0643           tcp_abort(pcb);
0644           return ERR_ABRT;
0645         }
0646         old_cwnd = pcb->cwnd;
0647         /* If there was any data contained within this ACK,
0648          * we'd better pass it on to the application as well. */
0649         tcp_receive(pcb);
0650 
0651         /* Prevent ACK for SYN to generate a sent event */
0652         if (pcb->acked != 0) {
0653           pcb->acked--;
0654         }
0655 
0656         pcb->cwnd = ((old_cwnd == 1) ? (pcb->mss * 2) : pcb->mss);
0657 
0658         if (recv_flags & TF_GOT_FIN) {
0659           tcp_ack_now(pcb);
0660           pcb->state = CLOSE_WAIT;
0661         }
0662       }
0663       /* incorrect ACK number */
0664       else {
0665         /* send RST */
0666         tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src),
0667                 tcphdr->dest, tcphdr->src);
0668       }
0669     } else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) {
0670       /* Looks like another copy of the SYN - retransmit our SYN-ACK */
0671       tcp_rexmit(pcb);
0672     }
0673     break;
0674   case CLOSE_WAIT:
0675     /* FALLTHROUGH */
0676   case ESTABLISHED:
0677     tcp_receive(pcb);
0678     if (recv_flags & TF_GOT_FIN) { /* passive close */
0679       tcp_ack_now(pcb);
0680       pcb->state = CLOSE_WAIT;
0681     }
0682     break;
0683   case FIN_WAIT_1:
0684     tcp_receive(pcb);
0685     if (recv_flags & TF_GOT_FIN) {
0686       if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) {
0687         LWIP_DEBUGF(TCP_DEBUG,
0688           ("TCP connection closed: FIN_WAIT_1 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
0689         tcp_ack_now(pcb);
0690         tcp_pcb_purge(pcb);
0691         TCP_RMV(&tcp_active_pcbs, pcb);
0692         pcb->state = TIME_WAIT;
0693         TCP_REG(&tcp_tw_pcbs, pcb);
0694       } else {
0695         tcp_ack_now(pcb);
0696         pcb->state = CLOSING;
0697       }
0698     } else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) {
0699       pcb->state = FIN_WAIT_2;
0700     }
0701     break;
0702   case FIN_WAIT_2:
0703     tcp_receive(pcb);
0704     if (recv_flags & TF_GOT_FIN) {
0705       LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: FIN_WAIT_2 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
0706       tcp_ack_now(pcb);
0707       tcp_pcb_purge(pcb);
0708       TCP_RMV(&tcp_active_pcbs, pcb);
0709       pcb->state = TIME_WAIT;
0710       TCP_REG(&tcp_tw_pcbs, pcb);
0711     }
0712     break;
0713   case CLOSING:
0714     tcp_receive(pcb);
0715     if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
0716       LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
0717       tcp_pcb_purge(pcb);
0718       TCP_RMV(&tcp_active_pcbs, pcb);
0719       pcb->state = TIME_WAIT;
0720       TCP_REG(&tcp_tw_pcbs, pcb);
0721     }
0722     break;
0723   case LAST_ACK:
0724     tcp_receive(pcb);
0725     if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
0726       LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: LAST_ACK %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
0727       /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */
0728       recv_flags |= TF_CLOSED;
0729     }
0730     break;
0731   default:
0732     break;
0733   }
0734   return ERR_OK;
0735 }
0736 
0737 #if TCP_QUEUE_OOSEQ
0738 /**
0739  * Insert segment into the list (segments covered with new one will be deleted)
0740  *
0741  * Called from tcp_receive()
0742  */
0743 static void
0744 tcp_oos_insert_segment(struct tcp_seg *cseg, struct tcp_seg *next)
0745 {
0746   struct tcp_seg *old_seg;
0747 
0748   if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
0749     /* received segment overlaps all following segments */
0750     tcp_segs_free(next);
0751     next = NULL;
0752   }
0753   else {
0754     /* delete some following segments
0755        oos queue may have segments with FIN flag */
0756     while (next &&
0757            TCP_SEQ_GEQ((seqno + cseg->len),
0758                       (next->tcphdr->seqno + next->len))) {
0759       /* cseg with FIN already processed */
0760       if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) {
0761         TCPH_FLAGS_SET(cseg->tcphdr, TCPH_FLAGS(cseg->tcphdr) | TCP_FIN);
0762       }
0763       old_seg = next;
0764       next = next->next;
0765       tcp_seg_free(old_seg);
0766     }
0767     if (next &&
0768         TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) {
0769       /* We need to trim the incoming segment. */
0770       cseg->len = (u16_t)(next->tcphdr->seqno - seqno);
0771       pbuf_realloc(cseg->p, cseg->len);
0772     }
0773   }
0774   cseg->next = next;
0775 }
0776 #endif
0777 
0778 /**
0779  * Called by tcp_process. Checks if the given segment is an ACK for outstanding
0780  * data, and if so frees the memory of the buffered data. Next, is places the
0781  * segment on any of the receive queues (pcb->recved or pcb->ooseq). If the segment
0782  * is buffered, the pbuf is referenced by pbuf_ref so that it will not be freed until
0783  * i it has been removed from the buffer.
0784  *
0785  * If the incoming segment constitutes an ACK for a segment that was used for RTT
0786  * estimation, the RTT is estimated here as well.
0787  *
0788  * Called from tcp_process().
0789  */
0790 static void
0791 tcp_receive(struct tcp_pcb *pcb)
0792 {
0793   struct tcp_seg *next;
0794 #if TCP_QUEUE_OOSEQ
0795   struct tcp_seg *prev, *cseg;
0796 #endif
0797   struct pbuf *p;
0798   s32_t off;
0799   s16_t m;
0800   u32_t right_wnd_edge;
0801   u16_t new_tot_len;
0802   int found_dupack = 0;
0803 
0804   if (flags & TCP_ACK) {
0805     right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2;
0806 
0807     /* Update window. */
0808     if (TCP_SEQ_LT(pcb->snd_wl1, seqno) ||
0809        (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) ||
0810        (pcb->snd_wl2 == ackno && tcphdr->wnd > pcb->snd_wnd)) {
0811       pcb->snd_wnd = tcphdr->wnd;
0812       pcb->snd_wl1 = seqno;
0813       pcb->snd_wl2 = ackno;
0814       if (pcb->snd_wnd > 0 && pcb->persist_backoff > 0) {
0815           pcb->persist_backoff = 0;
0816       }
0817       LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"U16_F"\n", pcb->snd_wnd));
0818 #if TCP_WND_DEBUG
0819     } else {
0820       if (pcb->snd_wnd != tcphdr->wnd) {
0821         LWIP_DEBUGF(TCP_WND_DEBUG, 
0822                     ("tcp_receive: no window update lastack %"U32_F" ackno %"
0823                      U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n",
0824                      pcb->lastack, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2));
0825       }
0826 #endif /* TCP_WND_DEBUG */
0827     }
0828 
0829     /* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a
0830      * duplicate ack if:
0831      * 1) It doesn't ACK new data 
0832      * 2) length of received packet is zero (i.e. no payload) 
0833      * 3) the advertised window hasn't changed 
0834      * 4) There is outstanding unacknowledged data (retransmission timer running)
0835      * 5) The ACK is == biggest ACK sequence number so far seen (snd_una)
0836      * 
0837      * If it passes all five, should process as a dupack: 
0838      * a) dupacks < 3: do nothing 
0839      * b) dupacks == 3: fast retransmit 
0840      * c) dupacks > 3: increase cwnd 
0841      * 
0842      * If it only passes 1-3, should reset dupack counter (and add to
0843      * stats, which we don't do in lwIP)
0844      *
0845      * If it only passes 1, should reset dupack counter
0846      *
0847      */
0848 
0849     /* Clause 1 */
0850     if (TCP_SEQ_LEQ(ackno, pcb->lastack)) {
0851       pcb->acked = 0;
0852       /* Clause 2 */
0853       if (tcplen == 0) {
0854         /* Clause 3 */
0855         if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge){
0856           /* Clause 4 */
0857           if (pcb->rtime >= 0) {
0858             /* Clause 5 */
0859             if (pcb->lastack == ackno) {
0860               found_dupack = 1;
0861               if (pcb->dupacks + 1 > pcb->dupacks)
0862                 ++pcb->dupacks;
0863               if (pcb->dupacks > 3) {
0864                 /* Inflate the congestion window, but not if it means that
0865                    the value overflows. */
0866                 if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
0867                   pcb->cwnd += pcb->mss;
0868                 }
0869               } else if (pcb->dupacks == 3) {
0870                 /* Do fast retransmit */
0871                 tcp_rexmit_fast(pcb);
0872               }
0873             }
0874           }
0875         }
0876       }
0877       /* If Clause (1) or more is true, but not a duplicate ack, reset
0878        * count of consecutive duplicate acks */
0879       if (!found_dupack) {
0880         pcb->dupacks = 0;
0881       }
0882     } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)){
0883       /* We come here when the ACK acknowledges new data. */
0884 
0885       /* Reset the "IN Fast Retransmit" flag, since we are no longer
0886          in fast retransmit. Also reset the congestion window to the
0887          slow start threshold. */
0888       if (pcb->flags & TF_INFR) {
0889         pcb->flags &= ~TF_INFR;
0890         pcb->cwnd = pcb->ssthresh;
0891       }
0892 
0893       /* Reset the number of retransmissions. */
0894       pcb->nrtx = 0;
0895 
0896       /* Reset the retransmission time-out. */
0897       pcb->rto = (pcb->sa >> 3) + pcb->sv;
0898 
0899       /* Update the send buffer space. Diff between the two can never exceed 64K? */
0900       pcb->acked = (u16_t)(ackno - pcb->lastack);
0901 
0902       pcb->snd_buf += pcb->acked;
0903 
0904       /* Reset the fast retransmit variables. */
0905       pcb->dupacks = 0;
0906       pcb->lastack = ackno;
0907 
0908       /* Update the congestion control variables (cwnd and
0909          ssthresh). */
0910       if (pcb->state >= ESTABLISHED) {
0911         if (pcb->cwnd < pcb->ssthresh) {
0912           if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
0913             pcb->cwnd += pcb->mss;
0914           }
0915           LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"U16_F"\n", pcb->cwnd));
0916         } else {
0917           u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd);
0918           if (new_cwnd > pcb->cwnd) {
0919             pcb->cwnd = new_cwnd;
0920           }
0921           LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"U16_F"\n", pcb->cwnd));
0922         }
0923       }
0924       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n",
0925                                     ackno,
0926                                     pcb->unacked != NULL?
0927                                     ntohl(pcb->unacked->tcphdr->seqno): 0,
0928                                     pcb->unacked != NULL?
0929                                     ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0));
0930 
0931       /* Remove segment from the unacknowledged list if the incoming
0932          ACK acknowlegdes them. */
0933       while (pcb->unacked != NULL &&
0934              TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) +
0935                          TCP_TCPLEN(pcb->unacked), ackno)) {
0936         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unacked\n",
0937                                       ntohl(pcb->unacked->tcphdr->seqno),
0938                                       ntohl(pcb->unacked->tcphdr->seqno) +
0939                                       TCP_TCPLEN(pcb->unacked)));
0940 
0941         next = pcb->unacked;
0942         pcb->unacked = pcb->unacked->next;
0943 
0944         LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen));
0945         LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
0946         /* Prevent ACK for FIN to generate a sent event */
0947         if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) {
0948           pcb->acked--;
0949         }
0950 
0951         pcb->snd_queuelen -= pbuf_clen(next->p);
0952         tcp_seg_free(next);
0953 
0954         LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unacked)\n", (u16_t)pcb->snd_queuelen));
0955         if (pcb->snd_queuelen != 0) {
0956           LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL ||
0957                       pcb->unsent != NULL);
0958         }
0959       }
0960 
0961       /* If there's nothing left to acknowledge, stop the retransmit
0962          timer, otherwise reset it to start again */
0963       if(pcb->unacked == NULL)
0964         pcb->rtime = -1;
0965       else
0966         pcb->rtime = 0;
0967 
0968       pcb->polltmr = 0;
0969     } else {
0970       /* Fix bug bug #21582: out of sequence ACK, didn't really ack anything */
0971       pcb->acked = 0;
0972     }
0973 
0974     /* We go through the ->unsent list to see if any of the segments
0975        on the list are acknowledged by the ACK. This may seem
0976        strange since an "unsent" segment shouldn't be acked. The
0977        rationale is that lwIP puts all outstanding segments on the
0978        ->unsent list after a retransmission, so these segments may
0979        in fact have been sent once. */
0980     while (pcb->unsent != NULL &&
0981            TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) + 
0982                            TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) {
0983       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n",
0984                                     ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) +
0985                                     TCP_TCPLEN(pcb->unsent)));
0986 
0987       next = pcb->unsent;
0988       pcb->unsent = pcb->unsent->next;
0989       LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen));
0990       LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
0991       /* Prevent ACK for FIN to generate a sent event */
0992       if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) {
0993         pcb->acked--;
0994       }
0995       pcb->snd_queuelen -= pbuf_clen(next->p);
0996       tcp_seg_free(next);
0997       LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unsent)\n", (u16_t)pcb->snd_queuelen));
0998       if (pcb->snd_queuelen != 0) {
0999         LWIP_ASSERT("tcp_receive: valid queue length",
1000           pcb->unacked != NULL || pcb->unsent != NULL);
1001       }
1002     }
1003     /* End of ACK for new data processing. */
1004 
1005     LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %"U32_F" rtseq %"U32_F" ackno %"U32_F"\n",
1006                                 pcb->rttest, pcb->rtseq, ackno));
1007 
1008     /* RTT estimation calculations. This is done by checking if the
1009        incoming segment acknowledges the segment we use to take a
1010        round-trip time measurement. */
1011     if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) {
1012       /* diff between this shouldn't exceed 32K since this are tcp timer ticks
1013          and a round-trip shouldn't be that long... */
1014       m = (s16_t)(tcp_ticks - pcb->rttest);
1015 
1016       LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %"U16_F" ticks (%"U16_F" msec).\n",
1017                                   m, m * TCP_SLOW_INTERVAL));
1018 
1019       /* This is taken directly from VJs original code in his paper */
1020       m = m - (pcb->sa >> 3);
1021       pcb->sa += m;
1022       if (m < 0) {
1023         m = -m;
1024       }
1025       m = m - (pcb->sv >> 2);
1026       pcb->sv += m;
1027       pcb->rto = (pcb->sa >> 3) + pcb->sv;
1028 
1029       LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %"U16_F" (%"U16_F" milliseconds)\n",
1030                                   pcb->rto, pcb->rto * TCP_SLOW_INTERVAL));
1031 
1032       pcb->rttest = 0;
1033     }
1034   }
1035 
1036   /* If the incoming segment contains data, we must process it
1037      further. */
1038   if (tcplen > 0) {
1039     /* This code basically does three things:
1040 
1041     +) If the incoming segment contains data that is the next
1042     in-sequence data, this data is passed to the application. This
1043     might involve trimming the first edge of the data. The rcv_nxt
1044     variable and the advertised window are adjusted.
1045 
1046     +) If the incoming segment has data that is above the next
1047     sequence number expected (->rcv_nxt), the segment is placed on
1048     the ->ooseq queue. This is done by finding the appropriate
1049     place in the ->ooseq queue (which is ordered by sequence
1050     number) and trim the segment in both ends if needed. An
1051     immediate ACK is sent to indicate that we received an
1052     out-of-sequence segment.
1053 
1054     +) Finally, we check if the first segment on the ->ooseq queue
1055     now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If
1056     rcv_nxt > ooseq->seqno, we must trim the first edge of the
1057     segment on ->ooseq before we adjust rcv_nxt. The data in the
1058     segments that are now on sequence are chained onto the
1059     incoming segment so that we only need to call the application
1060     once.
1061     */
1062 
1063     /* First, we check if we must trim the first edge. We have to do
1064        this if the sequence number of the incoming segment is less
1065        than rcv_nxt, and the sequence number plus the length of the
1066        segment is larger than rcv_nxt. */
1067     /*    if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){
1068           if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/
1069     if (TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno + 1, seqno + tcplen - 1)){
1070       /* Trimming the first edge is done by pushing the payload
1071          pointer in the pbuf downwards. This is somewhat tricky since
1072          we do not want to discard the full contents of the pbuf up to
1073          the new starting point of the data since we have to keep the
1074          TCP header which is present in the first pbuf in the chain.
1075 
1076          What is done is really quite a nasty hack: the first pbuf in
1077          the pbuf chain is pointed to by inseg.p. Since we need to be
1078          able to deallocate the whole pbuf, we cannot change this
1079          inseg.p pointer to point to any of the later pbufs in the
1080          chain. Instead, we point the ->payload pointer in the first
1081          pbuf to data in one of the later pbufs. We also set the
1082          inseg.data pointer to point to the right place. This way, the
1083          ->p pointer will still point to the first pbuf, but the
1084          ->p->payload pointer will point to data in another pbuf.
1085 
1086          After we are done with adjusting the pbuf pointers we must
1087          adjust the ->data pointer in the seg and the segment
1088          length.*/
1089 
1090       off = pcb->rcv_nxt - seqno;
1091       p = inseg.p;
1092       LWIP_ASSERT("inseg.p != NULL", inseg.p);
1093       LWIP_ASSERT("insane offset!", (off < 0x7fff));
1094       if (inseg.p->len < off) {
1095         LWIP_ASSERT("pbuf too short!", (((s32_t)inseg.p->tot_len) >= off));
1096         new_tot_len = (u16_t)(inseg.p->tot_len - off);
1097         while (p->len < off) {
1098           off -= p->len;
1099           /* KJM following line changed (with addition of new_tot_len var)
1100              to fix bug #9076
1101              inseg.p->tot_len -= p->len; */
1102           p->tot_len = new_tot_len;
1103           p->len = 0;
1104           p = p->next;
1105         }
1106         if(pbuf_header(p, (s16_t)-off)) {
1107           /* Do we need to cope with this failing?  Assert for now */
1108           LWIP_ASSERT("pbuf_header failed", 0);
1109         }
1110       } else {
1111         if(pbuf_header(inseg.p, (s16_t)-off)) {
1112           /* Do we need to cope with this failing?  Assert for now */
1113           LWIP_ASSERT("pbuf_header failed", 0);
1114         }
1115       }
1116       /* KJM following line changed to use p->payload rather than inseg->p->payload
1117          to fix bug #9076 */
1118       inseg.dataptr = p->payload;
1119       inseg.len -= (u16_t)(pcb->rcv_nxt - seqno);
1120       inseg.tcphdr->seqno = seqno = pcb->rcv_nxt;
1121     }
1122     else {
1123       if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){
1124         /* the whole segment is < rcv_nxt */
1125         /* must be a duplicate of a packet that has already been correctly handled */
1126 
1127         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno));
1128         tcp_ack_now(pcb);
1129       }
1130     }
1131 
1132     /* The sequence number must be within the window (above rcv_nxt
1133        and below rcv_nxt + rcv_wnd) in order to be further
1134        processed. */
1135     if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, 
1136                         pcb->rcv_nxt + pcb->rcv_wnd - 1)){
1137       if (pcb->rcv_nxt == seqno) {
1138         /* The incoming segment is the next in sequence. We check if
1139            we have to trim the end of the segment and update rcv_nxt
1140            and pass the data to the application. */
1141         tcplen = TCP_TCPLEN(&inseg);
1142 
1143         if (tcplen > pcb->rcv_wnd) {
1144           LWIP_DEBUGF(TCP_INPUT_DEBUG, 
1145                       ("tcp_receive: other end overran receive window"
1146                        "seqno %"U32_F" len %"U32_F" right edge %"U32_F"\n",
1147                        seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd));
1148           if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
1149             /* Must remove the FIN from the header as we're trimming 
1150              * that byte of sequence-space from the packet */
1151             TCPH_FLAGS_SET(inseg.tcphdr, TCPH_FLAGS(inseg.tcphdr) &~ TCP_FIN);
1152           }
1153           /* Adjust length of segment to fit in the window. */
1154           inseg.len = pcb->rcv_wnd;
1155           if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
1156             inseg.len -= 1;
1157           }
1158           pbuf_realloc(inseg.p, inseg.len);
1159           tcplen = TCP_TCPLEN(&inseg);
1160           LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n",
1161                       (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd));
1162         }
1163 #if TCP_QUEUE_OOSEQ
1164         if (pcb->ooseq != NULL) {
1165           if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
1166             LWIP_DEBUGF(TCP_INPUT_DEBUG, 
1167                         ("tcp_receive: received in-order FIN, binning ooseq queue\n"));
1168             /* Received in-order FIN means anything that was received
1169              * out of order must now have been received in-order, so
1170              * bin the ooseq queue
1171              * rcv_nxt
1172              * .    |--ooseq--|
1173              * .==seg============|FIN
1174              */
1175             while (pcb->ooseq != NULL) {
1176               struct tcp_seg *old_ooseq = pcb->ooseq;
1177               pcb->ooseq = pcb->ooseq->next;
1178               tcp_seg_free(old_ooseq);
1179             }               
1180           } 
1181           else {
1182             struct tcp_seg* next = pcb->ooseq;
1183             struct tcp_seg *old_seg;
1184             /* rcv_nxt
1185              * .    |--ooseq--|
1186              * .==seg============|
1187              */
1188             while (next &&
1189                    TCP_SEQ_GEQ(seqno + tcplen,
1190                                next->tcphdr->seqno + next->len)) {
1191               /* inseg doesn't have FIN (already processed) */
1192               if (TCPH_FLAGS(next->tcphdr) & TCP_FIN &&
1193                   (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) {
1194                 TCPH_FLAGS_SET(inseg.tcphdr, 
1195                                TCPH_FLAGS(inseg.tcphdr) | TCP_FIN);
1196                 tcplen = TCP_TCPLEN(&inseg);
1197               }
1198               old_seg = next;
1199               next = next->next;
1200               tcp_seg_free(old_seg);
1201             }
1202             /* rcv_nxt
1203              * .             |--ooseq--|
1204              * .==seg============|
1205              */
1206             if (next &&
1207                 TCP_SEQ_GT(seqno + tcplen,
1208                            next->tcphdr->seqno)) {
1209               /* FIN in inseg already handled by dropping whole ooseq queue */
1210               inseg.len = (u16_t)(pcb->ooseq->tcphdr->seqno - seqno);
1211               if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
1212                 inseg.len -= 1;
1213               }
1214               pbuf_realloc(inseg.p, inseg.len);
1215               tcplen = TCP_TCPLEN(&inseg);
1216               LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n",
1217                           (seqno + tcplen) == pcb->ooseq->tcphdr->seqno);
1218             }
1219             pcb->ooseq = next;
1220           }
1221         }
1222 #endif /* TCP_QUEUE_OOSEQ */
1223 
1224         pcb->rcv_nxt = seqno + tcplen;
1225 
1226         /* Update the receiver's (our) window. */
1227         LWIP_ASSERT("tcp_receive: tcplen > rcv_wnd\n", pcb->rcv_wnd >= tcplen);
1228         pcb->rcv_wnd -= tcplen;
1229 
1230         tcp_update_rcv_ann_wnd(pcb);
1231 
1232         /* If there is data in the segment, we make preparations to
1233            pass this up to the application. The ->recv_data variable
1234            is used for holding the pbuf that goes to the
1235            application. The code for reassembling out-of-sequence data
1236            chains its data on this pbuf as well.
1237 
1238            If the segment was a FIN, we set the TF_GOT_FIN flag that will
1239            be used to indicate to the application that the remote side has
1240            closed its end of the connection. */
1241         if (inseg.p->tot_len > 0) {
1242           recv_data = inseg.p;
1243           /* Since this pbuf now is the responsibility of the
1244              application, we delete our reference to it so that we won't
1245              (mistakingly) deallocate it. */
1246           inseg.p = NULL;
1247         }
1248         if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
1249           LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n"));
1250           recv_flags |= TF_GOT_FIN;
1251         }
1252 
1253 #if TCP_QUEUE_OOSEQ
1254         /* We now check if we have segments on the ->ooseq queue that
1255            is now in sequence. */
1256         while (pcb->ooseq != NULL &&
1257                pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) {
1258 
1259           cseg = pcb->ooseq;
1260           seqno = pcb->ooseq->tcphdr->seqno;
1261 
1262           pcb->rcv_nxt += TCP_TCPLEN(cseg);
1263           LWIP_ASSERT("tcp_receive: ooseq tcplen > rcv_wnd\n",
1264                       pcb->rcv_wnd >= TCP_TCPLEN(cseg));
1265           pcb->rcv_wnd -= TCP_TCPLEN(cseg);
1266 
1267           tcp_update_rcv_ann_wnd(pcb);
1268 
1269           if (cseg->p->tot_len > 0) {
1270             /* Chain this pbuf onto the pbuf that we will pass to
1271                the application. */
1272             if (recv_data) {
1273               pbuf_cat(recv_data, cseg->p);
1274             } else {
1275               recv_data = cseg->p;
1276             }
1277             cseg->p = NULL;
1278           }
1279           if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
1280             LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n"));
1281             recv_flags |= TF_GOT_FIN;
1282             if (pcb->state == ESTABLISHED) { /* force passive close or we can move to active close */
1283               pcb->state = CLOSE_WAIT;
1284             } 
1285           }
1286 
1287           pcb->ooseq = cseg->next;
1288           tcp_seg_free(cseg);
1289         }
1290 #endif /* TCP_QUEUE_OOSEQ */
1291 
1292 
1293         /* Acknowledge the segment(s). */
1294         tcp_ack(pcb);
1295 
1296       } else {
1297         /* We get here if the incoming segment is out-of-sequence. */
1298         tcp_send_empty_ack(pcb);
1299 #if TCP_QUEUE_OOSEQ
1300         /* We queue the segment on the ->ooseq queue. */
1301         if (pcb->ooseq == NULL) {
1302           pcb->ooseq = tcp_seg_copy(&inseg);
1303         } else {
1304           /* If the queue is not empty, we walk through the queue and
1305              try to find a place where the sequence number of the
1306              incoming segment is between the sequence numbers of the
1307              previous and the next segment on the ->ooseq queue. That is
1308              the place where we put the incoming segment. If needed, we
1309              trim the second edges of the previous and the incoming
1310              segment so that it will fit into the sequence.
1311 
1312              If the incoming segment has the same sequence number as a
1313              segment on the ->ooseq queue, we discard the segment that
1314              contains less data. */
1315 
1316           prev = NULL;
1317           for(next = pcb->ooseq; next != NULL; next = next->next) {
1318             if (seqno == next->tcphdr->seqno) {
1319               /* The sequence number of the incoming segment is the
1320                  same as the sequence number of the segment on
1321                  ->ooseq. We check the lengths to see which one to
1322                  discard. */
1323               if (inseg.len > next->len) {
1324                 /* The incoming segment is larger than the old
1325                    segment. We replace some segments with the new
1326                    one. */
1327                 cseg = tcp_seg_copy(&inseg);
1328                 if (cseg != NULL) {
1329                   if (prev != NULL) {
1330                     prev->next = cseg;
1331                   } else {
1332                     pcb->ooseq = cseg;
1333                   }
1334                   tcp_oos_insert_segment(cseg, next);
1335                 }
1336                 break;
1337               } else {
1338                 /* Either the lenghts are the same or the incoming
1339                    segment was smaller than the old one; in either
1340                    case, we ditch the incoming segment. */
1341                 break;
1342               }
1343             } else {
1344               if (prev == NULL) {
1345                 if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {
1346                   /* The sequence number of the incoming segment is lower
1347                      than the sequence number of the first segment on the
1348                      queue. We put the incoming segment first on the
1349                      queue. */
1350                   cseg = tcp_seg_copy(&inseg);
1351                   if (cseg != NULL) {
1352                     pcb->ooseq = cseg;
1353                     tcp_oos_insert_segment(cseg, next);
1354                   }
1355                   break;
1356                 }
1357               } else {
1358                 /*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) &&
1359                   TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/
1360                 if (TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)) {
1361                   /* The sequence number of the incoming segment is in
1362                      between the sequence numbers of the previous and
1363                      the next segment on ->ooseq. We trim trim the previous
1364                      segment, delete next segments that included in received segment
1365                      and trim received, if needed. */
1366                   cseg = tcp_seg_copy(&inseg);
1367                   if (cseg != NULL) {
1368                     if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) {
1369                       /* We need to trim the prev segment. */
1370                       prev->len = (u16_t)(seqno - prev->tcphdr->seqno);
1371                       pbuf_realloc(prev->p, prev->len);
1372                     }
1373                     prev->next = cseg;
1374                     tcp_oos_insert_segment(cseg, next);
1375                   }
1376                   break;
1377                 }
1378               }
1379               /* If the "next" segment is the last segment on the
1380                  ooseq queue, we add the incoming segment to the end
1381                  of the list. */
1382               if (next->next == NULL &&
1383                   TCP_SEQ_GT(seqno, next->tcphdr->seqno)) {
1384                 if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) {
1385                   /* segment "next" already contains all data */
1386                   break;
1387                 }
1388                 next->next = tcp_seg_copy(&inseg);
1389                 if (next->next != NULL) {
1390                   if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) {
1391                     /* We need to trim the last segment. */
1392                     next->len = (u16_t)(seqno - next->tcphdr->seqno);
1393                     pbuf_realloc(next->p, next->len);
1394                   }
1395                 }
1396                 break;
1397               }
1398             }
1399             prev = next;
1400           }
1401         }
1402 #endif /* TCP_QUEUE_OOSEQ */
1403 
1404       }
1405     } else {
1406       /* The incoming segment is not withing the window. */
1407       tcp_send_empty_ack(pcb);
1408     }
1409   } else {
1410     /* Segments with length 0 is taken care of here. Segments that
1411        fall out of the window are ACKed. */
1412     /*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) ||
1413       TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/
1414     if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){
1415       tcp_ack_now(pcb);
1416     }
1417   }
1418 }
1419 
1420 /**
1421  * Parses the options contained in the incoming segment. 
1422  *
1423  * Called from tcp_listen_input() and tcp_process().
1424  * Currently, only the MSS option is supported!
1425  *
1426  * @param pcb the tcp_pcb for which a segment arrived
1427  */
1428 static void
1429 tcp_parseopt(struct tcp_pcb *pcb)
1430 {
1431   u16_t c, max_c;
1432   u16_t mss;
1433   u8_t *opts, opt;
1434 #if LWIP_TCP_TIMESTAMPS
1435   u32_t tsval;
1436 #endif
1437 
1438   opts = (u8_t *)tcphdr + TCP_HLEN;
1439 
1440   /* Parse the TCP MSS option, if present. */
1441   if(TCPH_HDRLEN(tcphdr) > 0x5) {
1442     max_c = (TCPH_HDRLEN(tcphdr) - 5) << 2;
1443     for (c = 0; c < max_c; ) {
1444       opt = opts[c];
1445       switch (opt) {
1446       case 0x00:
1447         /* End of options. */
1448         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: EOL\n"));
1449         return;
1450       case 0x01:
1451         /* NOP option. */
1452         ++c;
1453         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: NOP\n"));
1454         break;
1455       case 0x02:
1456         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: MSS\n"));
1457         if (opts[c + 1] != 0x04 || c + 0x04 > max_c) {
1458           /* Bad length */
1459           LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
1460           return;
1461         }
1462         /* An MSS option with the right option length. */
1463         mss = (opts[c + 2] << 8) | opts[c + 3];
1464         /* Limit the mss to the configured TCP_MSS and prevent division by zero */
1465         pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss;
1466         /* Advance to next option */
1467         c += 0x04;
1468         break;
1469 #if LWIP_TCP_TIMESTAMPS
1470       case 0x08:
1471         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: TS\n"));
1472         if (opts[c + 1] != 0x0A || c + 0x0A > max_c) {
1473           /* Bad length */
1474           LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
1475           return;
1476         }
1477         /* TCP timestamp option with valid length */
1478         tsval = (opts[c+2]) | (opts[c+3] << 8) | 
1479           (opts[c+4] << 16) | (opts[c+5] << 24);
1480         if (flags & TCP_SYN) {
1481           pcb->ts_recent = ntohl(tsval);
1482           pcb->flags |= TF_TIMESTAMP;
1483         } else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno+tcplen)) {
1484           pcb->ts_recent = ntohl(tsval);
1485         }
1486         /* Advance to next option */
1487         c += 0x0A;
1488         break;
1489 #endif
1490       default:
1491         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: other\n"));
1492         if (opts[c + 1] == 0) {
1493           LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
1494           /* If the length field is zero, the options are malformed
1495              and we don't process them further. */
1496           return;
1497         }
1498         /* All other options have a length field, so that we easily
1499            can skip past them. */
1500         c += opts[c + 1];
1501       }
1502     }
1503   }
1504 }
1505 
1506 #endif /* LWIP_TCP */