Port of LwIP performed by Ralf in 2010. Not recommended for use with recent mbed libraries, but good demos of raw LwIP possible

Dependents:   LwIP_raw_API_serverExample tiny-dtls

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers tcp_in.c Source File

tcp_in.c

Go to the documentation of this file.
00001 /**
00002  * @file
00003  * Transmission Control Protocol, incoming traffic
00004  *
00005  * The input processing functions of the TCP layer.
00006  *
00007  * These functions are generally called in the order (ip_input() ->)
00008  * tcp_input() -> * tcp_process() -> tcp_receive() (-> application).
00009  * 
00010  */
00011 
00012 /*
00013  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
00014  * All rights reserved.
00015  *
00016  * Redistribution and use in source and binary forms, with or without modification,
00017  * are permitted provided that the following conditions are met:
00018  *
00019  * 1. Redistributions of source code must retain the above copyright notice,
00020  *    this list of conditions and the following disclaimer.
00021  * 2. Redistributions in binary form must reproduce the above copyright notice,
00022  *    this list of conditions and the following disclaimer in the documentation
00023  *    and/or other materials provided with the distribution.
00024  * 3. The name of the author may not be used to endorse or promote products
00025  *    derived from this software without specific prior written permission.
00026  *
00027  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
00028  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00029  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
00030  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00031  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
00032  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00033  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00034  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
00035  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
00036  * OF SUCH DAMAGE.
00037  *
00038  * This file is part of the lwIP TCP/IP stack.
00039  *
00040  * Author: Adam Dunkels <adam@sics.se>
00041  *
00042  */
00043 
00044 #include "lwip/opt.h"
00045 
00046 #if LWIP_TCP /* don't build if not configured for use in lwipopts.h */
00047 
00048 #include "lwip/tcp.h"
00049 #include "lwip/def.h"
00050 #include "lwip/ip_addr.h"
00051 #include "lwip/netif.h"
00052 #include "lwip/mem.h"
00053 #include "lwip/memp.h"
00054 #include "lwip/inet.h"
00055 #include "lwip/inet_chksum.h"
00056 #include "lwip/stats.h"
00057 #include "lwip/snmp.h"
00058 #include "arch/perf.h"
00059 
00060 /* These variables are global to all functions involved in the input
00061    processing of TCP segments. They are set by the tcp_input()
00062    function. */
00063 static struct tcp_seg inseg;
00064 static struct tcp_hdr *tcphdr;
00065 static struct ip_hdr *iphdr;
00066 static u32_t seqno, ackno;
00067 static u8_t flags;
00068 static u16_t tcplen;
00069 
00070 static u8_t recv_flags;
00071 static struct pbuf *recv_data;
00072 
00073 struct tcp_pcb *tcp_input_pcb;
00074 
00075 /* Forward declarations. */
00076 static err_t tcp_process(struct tcp_pcb *pcb);
00077 static u8_t tcp_receive(struct tcp_pcb *pcb);
00078 static void tcp_parseopt(struct tcp_pcb *pcb);
00079 
00080 static err_t tcp_listen_input(struct tcp_pcb_listen *pcb);
00081 static err_t tcp_timewait_input(struct tcp_pcb *pcb);
00082 
00083 /**
00084  * The initial input processing of TCP. It verifies the TCP header, demultiplexes
00085  * the segment between the PCBs and passes it on to tcp_process(), which implements
00086  * the TCP finite state machine. This function is called by the IP layer (in
00087  * ip_input()).
00088  *
00089  * @param p received TCP segment to process (p->payload pointing to the IP header)
00090  * @param inp network interface on which this segment was received
00091  */
00092 void
00093 tcp_input(struct pbuf *p, struct netif *inp)
00094 {
00095   struct tcp_pcb *pcb, *prev;
00096   struct tcp_pcb_listen *lpcb;
00097   u8_t hdrlen;
00098   err_t err;
00099 
00100   PERF_START;
00101 
00102   TCP_STATS_INC(tcp.recv);
00103   snmp_inc_tcpinsegs();
00104 
00105   iphdr = (struct ip_hdr *)p->payload;
00106   tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4);
00107 
00108 #if TCP_INPUT_DEBUG
00109   tcp_debug_print(tcphdr);
00110 #endif
00111 
00112   /* remove header from payload */
00113   if (pbuf_header(p, -((s16_t)(IPH_HL(iphdr) * 4))) || (p->tot_len < sizeof(struct tcp_hdr))) {
00114     /* drop short packets */
00115     LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len));
00116     TCP_STATS_INC(tcp.lenerr);
00117     TCP_STATS_INC(tcp.drop);
00118     snmp_inc_tcpinerrs();
00119     pbuf_free(p);
00120     return;
00121   }
00122 
00123   /* Don't even process incoming broadcasts/multicasts. */
00124   if (ip_addr_isbroadcast(&(iphdr->dest), inp) ||
00125       ip_addr_ismulticast(&(iphdr->dest))) {
00126     TCP_STATS_INC(tcp.proterr);
00127     TCP_STATS_INC(tcp.drop);
00128     snmp_inc_tcpinerrs();
00129     pbuf_free(p);
00130     return;
00131   }
00132 
00133 #if CHECKSUM_CHECK_TCP
00134   /* Verify TCP checksum. */
00135   if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
00136       (struct ip_addr *)&(iphdr->dest),
00137       IP_PROTO_TCP, p->tot_len) != 0) {
00138       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n",
00139         inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src), (struct ip_addr *)&(iphdr->dest),
00140       IP_PROTO_TCP, p->tot_len)));
00141 #if TCP_DEBUG
00142     tcp_debug_print(tcphdr);
00143 #endif /* TCP_DEBUG */
00144     TCP_STATS_INC(tcp.chkerr);
00145     TCP_STATS_INC(tcp.drop);
00146     snmp_inc_tcpinerrs();
00147     pbuf_free(p);
00148     return;
00149   }
00150 #endif
00151 
00152   /* Move the payload pointer in the pbuf so that it points to the
00153      TCP data instead of the TCP header. */
00154   hdrlen = TCPH_HDRLEN(tcphdr);
00155   if(pbuf_header(p, -(hdrlen * 4))){
00156     /* drop short packets */
00157     LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet\n"));
00158     TCP_STATS_INC(tcp.lenerr);
00159     TCP_STATS_INC(tcp.drop);
00160     snmp_inc_tcpinerrs();
00161     pbuf_free(p);
00162     return;
00163   }
00164 
00165   /* Convert fields in TCP header to host byte order. */
00166   tcphdr->src = ntohs(tcphdr->src);
00167   tcphdr->dest = ntohs(tcphdr->dest);
00168   seqno = tcphdr->seqno = ntohl(tcphdr->seqno);
00169   ackno = tcphdr->ackno = ntohl(tcphdr->ackno);
00170   tcphdr->wnd = ntohs(tcphdr->wnd);
00171 
00172   flags = TCPH_FLAGS(tcphdr);
00173   tcplen = p->tot_len + ((flags & (TCP_FIN | TCP_SYN)) ? 1 : 0);
00174 
00175   /* Demultiplex an incoming segment. First, we check if it is destined
00176      for an active connection. */
00177   prev = NULL;
00178 
00179   
00180   for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
00181     LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED);
00182     LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
00183     LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
00184     if (pcb->remote_port == tcphdr->src &&
00185        pcb->local_port == tcphdr->dest &&
00186        ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
00187        ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
00188 
00189       /* Move this PCB to the front of the list so that subsequent
00190          lookups will be faster (we exploit locality in TCP segment
00191          arrivals). */
00192       LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb);
00193       if (prev != NULL) {
00194         prev->next = pcb->next;
00195         pcb->next = tcp_active_pcbs;
00196         tcp_active_pcbs = pcb;
00197       }
00198       LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb);
00199       break;
00200     }
00201     prev = pcb;
00202   }
00203 
00204   if (pcb == NULL) {
00205     /* If it did not go to an active connection, we check the connections
00206        in the TIME-WAIT state. */
00207     for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
00208       LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
00209       if (pcb->remote_port == tcphdr->src &&
00210          pcb->local_port == tcphdr->dest &&
00211          ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
00212          ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
00213         /* We don't really care enough to move this PCB to the front
00214            of the list since we are not very likely to receive that
00215            many segments for connections in TIME-WAIT. */
00216         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n"));
00217         tcp_timewait_input(pcb);
00218         pbuf_free(p);
00219         return;
00220       }
00221     }
00222 
00223   /* Finally, if we still did not get a match, we check all PCBs that
00224      are LISTENing for incoming connections. */
00225     prev = NULL;
00226     for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
00227       if ((ip_addr_isany(&(lpcb->local_ip)) ||
00228         ip_addr_cmp(&(lpcb->local_ip), &(iphdr->dest))) &&
00229         lpcb->local_port == tcphdr->dest) {
00230         /* Move this PCB to the front of the list so that subsequent
00231            lookups will be faster (we exploit locality in TCP segment
00232            arrivals). */
00233         if (prev != NULL) {
00234           ((struct tcp_pcb_listen *)prev)->next = lpcb->next;
00235                 /* our successor is the remainder of the listening list */
00236           lpcb->next = tcp_listen_pcbs.listen_pcbs;
00237                 /* put this listening pcb at the head of the listening list */
00238           tcp_listen_pcbs.listen_pcbs = lpcb;
00239         }
00240       
00241         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n"));
00242         tcp_listen_input(lpcb);
00243         pbuf_free(p);
00244         return;
00245       }
00246       prev = (struct tcp_pcb *)lpcb;
00247     }
00248   }
00249 
00250 #if TCP_INPUT_DEBUG
00251   LWIP_DEBUGF(TCP_INPUT_DEBUG, ("+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags "));
00252   tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
00253   LWIP_DEBUGF(TCP_INPUT_DEBUG, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n"));
00254 #endif /* TCP_INPUT_DEBUG */
00255 
00256 
00257   if (pcb != NULL) {
00258     /* The incoming segment belongs to a connection. */
00259 #if TCP_INPUT_DEBUG
00260 #if TCP_DEBUG
00261     tcp_debug_print_state(pcb->state);
00262 #endif /* TCP_DEBUG */
00263 #endif /* TCP_INPUT_DEBUG */
00264 
00265     /* Set up a tcp_seg structure. */
00266     inseg.next = NULL;
00267     inseg.len = p->tot_len;
00268     inseg.dataptr = p->payload;
00269     inseg.p = p;
00270     inseg.tcphdr = tcphdr;
00271 
00272     recv_data = NULL;
00273     recv_flags = 0;
00274 
00275     /* If there is data which was previously "refused" by upper layer */
00276     if (pcb->refused_data != NULL) {
00277       /* Notify again application with data previously received. */
00278       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: notify kept packet\n"));
00279       TCP_EVENT_RECV(pcb, pcb->refused_data, ERR_OK, err);
00280       if (err == ERR_OK) {
00281         pcb->refused_data = NULL;
00282       } else {
00283         /* drop incoming packets, because pcb is "full" */
00284         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n"));
00285         TCP_STATS_INC(tcp.drop);
00286         snmp_inc_tcpinerrs();
00287         pbuf_free(p);
00288         return;
00289       }
00290     }
00291     tcp_input_pcb = pcb;
00292     err = tcp_process(pcb);
00293     tcp_input_pcb = NULL;
00294     /* A return value of ERR_ABRT means that tcp_abort() was called
00295        and that the pcb has been freed. If so, we don't do anything. */
00296     if (err != ERR_ABRT) {
00297       if (recv_flags & TF_RESET) {
00298         /* TF_RESET means that the connection was reset by the other
00299            end. We then call the error callback to inform the
00300            application that the connection is dead before we
00301            deallocate the PCB. */
00302         TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST);
00303         tcp_pcb_remove(&tcp_active_pcbs, pcb);
00304         memp_free(MEMP_TCP_PCB, pcb);
00305       } else if (recv_flags & TF_CLOSED) {
00306         /* The connection has been closed and we will deallocate the
00307            PCB. */
00308         tcp_pcb_remove(&tcp_active_pcbs, pcb);
00309         memp_free(MEMP_TCP_PCB, pcb);
00310       } else {
00311         err = ERR_OK;
00312         /* If the application has registered a "sent" function to be
00313            called when new send buffer space is available, we call it
00314            now. */
00315         if (pcb->acked > 0) {
00316           TCP_EVENT_SENT(pcb, pcb->acked, err);
00317         }
00318       
00319         if (recv_data != NULL) {
00320           if(flags & TCP_PSH) {
00321             recv_data->flags |= PBUF_FLAG_PUSH;
00322           }
00323 
00324           /* Notify application that data has been received. */
00325           TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err);
00326 
00327           /* If the upper layer can't receive this data, store it */
00328           if (err != ERR_OK) {
00329             pcb->refused_data = recv_data;
00330             LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: keep incoming packet, because pcb is \"full\"\n"));
00331           }
00332         }
00333 
00334         /* If a FIN segment was received, we call the callback
00335            function with a NULL buffer to indicate EOF. */
00336         if (recv_flags & TF_GOT_FIN) {
00337           TCP_EVENT_RECV(pcb, NULL, ERR_OK, err);
00338         }
00339 
00340         /* If there were no errors, we try to send something out. */
00341         if (err == ERR_OK) {
00342           tcp_output(pcb);
00343         }
00344       }
00345     }
00346 
00347 
00348     /* give up our reference to inseg.p */
00349     if (inseg.p != NULL)
00350     {
00351       pbuf_free(inseg.p);
00352       inseg.p = NULL;
00353     }
00354 #if TCP_INPUT_DEBUG
00355 #if TCP_DEBUG
00356     tcp_debug_print_state(pcb->state);
00357 #endif /* TCP_DEBUG */
00358 #endif /* TCP_INPUT_DEBUG */
00359       
00360   } else {
00361 
00362     /* If no matching PCB was found, send a TCP RST (reset) to the
00363        sender. */
00364     LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n"));
00365     if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) {
00366       TCP_STATS_INC(tcp.proterr);
00367       TCP_STATS_INC(tcp.drop);
00368       tcp_rst(ackno, seqno + tcplen,
00369         &(iphdr->dest), &(iphdr->src),
00370         tcphdr->dest, tcphdr->src);
00371     }
00372     pbuf_free(p);
00373   }
00374 
00375   LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());
00376   PERF_STOP("tcp_input");
00377 }
00378 
00379 /**
00380  * Called by tcp_input() when a segment arrives for a listening
00381  * connection (from tcp_input()).
00382  *
00383  * @param pcb the tcp_pcb_listen for which a segment arrived
00384  * @return ERR_OK if the segment was processed
00385  *         another err_t on error
00386  *
00387  * @note the return value is not (yet?) used in tcp_input()
00388  * @note the segment which arrived is saved in global variables, therefore only the pcb
00389  *       involved is passed as a parameter to this function
00390  */
00391 static err_t
00392 tcp_listen_input(struct tcp_pcb_listen *pcb)
00393 {
00394   struct tcp_pcb *npcb;
00395   err_t rc;
00396 
00397   /* In the LISTEN state, we check for incoming SYN segments,
00398      creates a new PCB, and responds with a SYN|ACK. */
00399   if (flags & TCP_ACK) {
00400     /* For incoming segments with the ACK flag set, respond with a
00401        RST. */
00402     LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n"));
00403     tcp_rst(ackno + 1, seqno + tcplen,
00404       &(iphdr->dest), &(iphdr->src),
00405       tcphdr->dest, tcphdr->src);
00406   } else if (flags & TCP_SYN) {
00407     LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest));
00408 #if TCP_LISTEN_BACKLOG
00409     if (pcb->accepts_pending >= pcb->backlog) {
00410       LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: listen backlog exceeded for port %"U16_F"\n", tcphdr->dest));
00411       return ERR_ABRT;
00412     }
00413 #endif /* TCP_LISTEN_BACKLOG */
00414     npcb = tcp_alloc(pcb->prio);
00415     /* If a new PCB could not be created (probably due to lack of memory),
00416        we don't do anything, but rely on the sender will retransmit the
00417        SYN at a time when we have more memory available. */
00418     if (npcb == NULL) {
00419       LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n"));
00420       TCP_STATS_INC(tcp.memerr);
00421       return ERR_MEM;
00422     }
00423 #if TCP_LISTEN_BACKLOG
00424     pcb->accepts_pending++;
00425 #endif /* TCP_LISTEN_BACKLOG */
00426     /* Set up the new PCB. */
00427     ip_addr_set(&(npcb->local_ip), &(iphdr->dest));
00428     npcb->local_port = pcb->local_port;
00429     ip_addr_set(&(npcb->remote_ip), &(iphdr->src));
00430     npcb->remote_port = tcphdr->src;
00431     npcb->state = SYN_RCVD;
00432     npcb->rcv_nxt = seqno + 1;
00433     npcb->rcv_ann_right_edge = npcb->rcv_nxt;
00434     npcb->snd_wnd = tcphdr->wnd;
00435     npcb->ssthresh = npcb->snd_wnd;
00436     npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */
00437     npcb->callback_arg = pcb->callback_arg;
00438 #if LWIP_CALLBACK_API
00439     npcb->accept = pcb->accept;
00440 #endif /* LWIP_CALLBACK_API */
00441     /* inherit socket options */
00442     npcb->so_options = pcb->so_options & (SOF_DEBUG|SOF_DONTROUTE|SOF_KEEPALIVE|SOF_OOBINLINE|SOF_LINGER);
00443     /* Register the new PCB so that we can begin receiving segments
00444        for it. */
00445     TCP_REG(&tcp_active_pcbs, npcb);
00446 
00447     /* Parse any options in the SYN. */
00448     tcp_parseopt(npcb);
00449 #if TCP_CALCULATE_EFF_SEND_MSS
00450     npcb->mss = tcp_eff_send_mss(npcb->mss, &(npcb->remote_ip));
00451 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
00452 
00453     snmp_inc_tcppassiveopens();
00454 
00455     /* Send a SYN|ACK together with the MSS option. */
00456     rc = tcp_enqueue(npcb, NULL, 0, TCP_SYN | TCP_ACK, 0, TF_SEG_OPTS_MSS
00457 #if LWIP_TCP_TIMESTAMPS
00458       /* and maybe include the TIMESTAMP option */
00459      | (npcb->flags & TF_TIMESTAMP ? TF_SEG_OPTS_TS : 0)
00460 #endif
00461       );
00462     if (rc != ERR_OK) {
00463       tcp_abandon(npcb, 0);
00464       return rc;
00465     }
00466     return tcp_output(npcb);
00467   }
00468   return ERR_OK;
00469 }
00470 
00471 /**
00472  * Called by tcp_input() when a segment arrives for a connection in
00473  * TIME_WAIT.
00474  *
00475  * @param pcb the tcp_pcb for which a segment arrived
00476  *
00477  * @note the segment which arrived is saved in global variables, therefore only the pcb
00478  *       involved is passed as a parameter to this function
00479  */
00480 static err_t
00481 tcp_timewait_input(struct tcp_pcb *pcb)
00482 {
00483   /* RFC 1337: in TIME_WAIT, ignore RST and ACK FINs + any 'acceptable' segments */
00484   /* RFC 793 3.9 Event Processing - Segment Arrives:
00485    * - first check sequence number - we skip that one in TIME_WAIT (always
00486    *   acceptable since we only send ACKs)
00487    * - second check the RST bit (... return) */
00488   if (flags & TCP_RST)  {
00489     return ERR_OK;
00490   }
00491   /* - fourth, check the SYN bit, */
00492   if (flags & TCP_SYN) {
00493     /* If an incoming segment is not acceptable, an acknowledgment
00494        should be sent in reply */
00495     if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) {
00496       /* If the SYN is in the window it is an error, send a reset */
00497       tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src),
00498         tcphdr->dest, tcphdr->src);
00499       return ERR_OK;
00500     }
00501   } else if (flags & TCP_FIN) {
00502     /* - eighth, check the FIN bit: Remain in the TIME-WAIT state.
00503          Restart the 2 MSL time-wait timeout.*/
00504     pcb->tmr = tcp_ticks;
00505   }
00506 
00507   if ((tcplen > 0))  {
00508     /* Acknowledge data, FIN or out-of-window SYN */
00509     pcb->flags |= TF_ACK_NOW;
00510     return tcp_output(pcb);
00511   }
00512   return ERR_OK;
00513 }
00514 
00515 /**
00516  * Implements the TCP state machine. Called by tcp_input. In some
00517  * states tcp_receive() is called to receive data. The tcp_seg
00518  * argument will be freed by the caller (tcp_input()) unless the
00519  * recv_data pointer in the pcb is set.
00520  *
00521  * @param pcb the tcp_pcb for which a segment arrived
00522  *
00523  * @note the segment which arrived is saved in global variables, therefore only the pcb
00524  *       involved is passed as a parameter to this function
00525  */
00526 static err_t
00527 tcp_process(struct tcp_pcb *pcb)
00528 {
00529   struct tcp_seg *rseg;
00530   u8_t acceptable = 0;
00531   err_t err;
00532 
00533   err = ERR_OK;
00534 
00535   /* Process incoming RST segments. */
00536   if (flags & TCP_RST) {
00537     /* First, determine if the reset is acceptable. */
00538     if (pcb->state == SYN_SENT) {
00539       if (ackno == pcb->snd_nxt) {
00540         acceptable = 1;
00541       }
00542     } else {
00543       if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, 
00544                           pcb->rcv_nxt+pcb->rcv_wnd)) {
00545         acceptable = 1;
00546       }
00547     }
00548 
00549     if (acceptable) {
00550       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n"));
00551       LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED);
00552       recv_flags |= TF_RESET;
00553       pcb->flags &= ~TF_ACK_DELAY;
00554       return ERR_RST;
00555     } else {
00556       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n",
00557        seqno, pcb->rcv_nxt));
00558       LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n",
00559        seqno, pcb->rcv_nxt));
00560       return ERR_OK;
00561     }
00562   }
00563 
00564   if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) { 
00565     /* Cope with new connection attempt after remote end crashed */
00566     tcp_ack_now(pcb);
00567     return ERR_OK;
00568   }
00569   
00570   /* Update the PCB (in)activity timer. */
00571   pcb->tmr = tcp_ticks;
00572   pcb->keep_cnt_sent = 0;
00573 
00574   tcp_parseopt(pcb);
00575 
00576   /* Do different things depending on the TCP state. */
00577   switch (pcb->state) {
00578   case SYN_SENT:
00579     LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno,
00580      pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno)));
00581     /* received SYN ACK with expected sequence number? */
00582     if ((flags & TCP_ACK) && (flags & TCP_SYN)
00583         && ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) {
00584       pcb->snd_buf++;
00585       pcb->rcv_nxt = seqno + 1;
00586       pcb->rcv_ann_right_edge = pcb->rcv_nxt;
00587       pcb->lastack = ackno;
00588       pcb->snd_wnd = tcphdr->wnd;
00589       pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */
00590       pcb->state = ESTABLISHED;
00591 
00592 #if TCP_CALCULATE_EFF_SEND_MSS
00593       pcb->mss = tcp_eff_send_mss(pcb->mss, &(pcb->remote_ip));
00594 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
00595 
00596       /* Set ssthresh again after changing pcb->mss (already set in tcp_connect
00597        * but for the default value of pcb->mss) */
00598       pcb->ssthresh = pcb->mss * 10;
00599 
00600       pcb->cwnd = ((pcb->cwnd == 1) ? (pcb->mss * 2) : pcb->mss);
00601       LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0));
00602       --pcb->snd_queuelen;
00603       LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"U16_F"\n", (u16_t)pcb->snd_queuelen));
00604       rseg = pcb->unacked;
00605       pcb->unacked = rseg->next;
00606 
00607       /* If there's nothing left to acknowledge, stop the retransmit
00608          timer, otherwise reset it to start again */
00609       if(pcb->unacked == NULL)
00610         pcb->rtime = -1;
00611       else {
00612         pcb->rtime = 0;
00613         pcb->nrtx = 0;
00614       }
00615 
00616       tcp_seg_free(rseg);
00617 
00618       /* Call the user specified function to call when sucessfully
00619        * connected. */
00620       TCP_EVENT_CONNECTED(pcb, ERR_OK, err);
00621       tcp_ack_now(pcb);
00622     }
00623     /* received ACK? possibly a half-open connection */
00624     else if (flags & TCP_ACK) {
00625       /* send a RST to bring the other side in a non-synchronized state. */
00626       tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src),
00627         tcphdr->dest, tcphdr->src);
00628     }
00629     break;
00630   case SYN_RCVD:
00631     if (flags & TCP_ACK) {
00632       /* expected ACK number? */
00633       if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) {
00634         u16_t old_cwnd;
00635         pcb->state = ESTABLISHED;
00636         LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
00637 #if LWIP_CALLBACK_API
00638         LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL);
00639 #endif
00640         /* Call the accept function. */
00641         TCP_EVENT_ACCEPT(pcb, ERR_OK, err);
00642         if (err != ERR_OK) {
00643           /* If the accept function returns with an error, we abort
00644            * the connection. */
00645           tcp_abort(pcb);
00646           return ERR_ABRT;
00647         }
00648         old_cwnd = pcb->cwnd;
00649         /* If there was any data contained within this ACK,
00650          * we'd better pass it on to the application as well. */
00651         tcp_receive(pcb);
00652 
00653         /* Prevent ACK for SYN to generate a sent event */
00654         if (pcb->acked != 0) {
00655           pcb->acked--;
00656         }
00657 
00658         pcb->cwnd = ((old_cwnd == 1) ? (pcb->mss * 2) : pcb->mss);
00659 
00660         if (recv_flags & TF_GOT_FIN) {
00661           tcp_ack_now(pcb);
00662           pcb->state = CLOSE_WAIT;
00663         }
00664       }
00665       /* incorrect ACK number */
00666       else {
00667         /* send RST */
00668         tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src),
00669                 tcphdr->dest, tcphdr->src);
00670       }
00671     } else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) {
00672       /* Looks like another copy of the SYN - retransmit our SYN-ACK */
00673       tcp_rexmit(pcb);
00674     }
00675     break;
00676   case CLOSE_WAIT:
00677     /* FALLTHROUGH */
00678   case ESTABLISHED:
00679     tcp_receive(pcb);
00680     if (recv_flags & TF_GOT_FIN) { /* passive close */
00681       tcp_ack_now(pcb);
00682       pcb->state = CLOSE_WAIT;
00683     }
00684     break;
00685   case FIN_WAIT_1:
00686     tcp_receive(pcb);
00687     if (recv_flags & TF_GOT_FIN) {
00688       if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) {
00689         LWIP_DEBUGF(TCP_DEBUG,
00690           ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
00691         tcp_ack_now(pcb);
00692         tcp_pcb_purge(pcb);
00693         TCP_RMV(&tcp_active_pcbs, pcb);
00694         pcb->state = TIME_WAIT;
00695         TCP_REG(&tcp_tw_pcbs, pcb);
00696       } else {
00697         tcp_ack_now(pcb);
00698         pcb->state = CLOSING;
00699       }
00700     } else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) {
00701       pcb->state = FIN_WAIT_2;
00702     }
00703     break;
00704   case FIN_WAIT_2:
00705     tcp_receive(pcb);
00706     if (recv_flags & TF_GOT_FIN) {
00707       LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
00708       tcp_ack_now(pcb);
00709       tcp_pcb_purge(pcb);
00710       TCP_RMV(&tcp_active_pcbs, pcb);
00711       pcb->state = TIME_WAIT;
00712       TCP_REG(&tcp_tw_pcbs, pcb);
00713     }
00714     break;
00715   case CLOSING:
00716     tcp_receive(pcb);
00717     if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
00718       LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
00719       tcp_pcb_purge(pcb);
00720       TCP_RMV(&tcp_active_pcbs, pcb);
00721       pcb->state = TIME_WAIT;
00722       TCP_REG(&tcp_tw_pcbs, pcb);
00723     }
00724     break;
00725   case LAST_ACK:
00726     tcp_receive(pcb);
00727     if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
00728       LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
00729       /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */
00730       recv_flags |= TF_CLOSED;
00731     }
00732     break;
00733   default:
00734     break;
00735   }
00736   return ERR_OK;
00737 }
00738 
00739 /**
00740  * Called by tcp_process. Checks if the given segment is an ACK for outstanding
00741  * data, and if so frees the memory of the buffered data. Next, is places the
00742  * segment on any of the receive queues (pcb->recved or pcb->ooseq). If the segment
00743  * is buffered, the pbuf is referenced by pbuf_ref so that it will not be freed until
00744  * i it has been removed from the buffer.
00745  *
00746  * If the incoming segment constitutes an ACK for a segment that was used for RTT
00747  * estimation, the RTT is estimated here as well.
00748  *
00749  * Called from tcp_process().
00750  *
00751  * @return 1 if the incoming segment is the next in sequence, 0 if not
00752  */
00753 static u8_t
00754 tcp_receive(struct tcp_pcb *pcb)
00755 {
00756   struct tcp_seg *next;
00757 #if TCP_QUEUE_OOSEQ
00758   struct tcp_seg *prev, *cseg;
00759 #endif
00760   struct pbuf *p;
00761   s32_t off;
00762   s16_t m;
00763   u32_t right_wnd_edge;
00764   u16_t new_tot_len;
00765   u8_t accepted_inseq = 0;
00766   int found_dupack = 0;
00767 
00768   if (flags & TCP_ACK) {
00769     right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2;
00770 
00771     /* Update window. */
00772     if (TCP_SEQ_LT(pcb->snd_wl1, seqno) ||
00773        (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) ||
00774        (pcb->snd_wl2 == ackno && tcphdr->wnd > pcb->snd_wnd)) {
00775       pcb->snd_wnd = tcphdr->wnd;
00776       pcb->snd_wl1 = seqno;
00777       pcb->snd_wl2 = ackno;
00778       if (pcb->snd_wnd > 0 && pcb->persist_backoff > 0) {
00779           pcb->persist_backoff = 0;
00780       }
00781       LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"U16_F"\n", pcb->snd_wnd));
00782 #if TCP_WND_DEBUG
00783     } else {
00784       if (pcb->snd_wnd != tcphdr->wnd) {
00785         LWIP_DEBUGF(TCP_WND_DEBUG, 
00786                     ("tcp_receive: no window update lastack %"U32_F" ackno %"
00787                      U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n",
00788                      pcb->lastack, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2));
00789       }
00790 #endif /* TCP_WND_DEBUG */
00791     }
00792 
00793     /* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a
00794      * duplicate ack if:
00795      * 1) It doesn't ACK new data 
00796      * 2) length of received packet is zero (i.e. no payload) 
00797      * 3) the advertised window hasn't changed 
00798      * 4) There is outstanding unacknowledged data (retransmission timer running)
00799      * 5) The ACK is == biggest ACK sequence number so far seen (snd_una)
00800      * 
00801      * If it passes all five, should process as a dupack: 
00802      * a) dupacks < 3: do nothing 
00803      * b) dupacks == 3: fast retransmit 
00804      * c) dupacks > 3: increase cwnd 
00805      * 
00806      * If it only passes 1-3, should reset dupack counter (and add to
00807      * stats, which we don't do in lwIP)
00808      *
00809      * If it only passes 1, should reset dupack counter
00810      *
00811      */
00812 
00813     /* Clause 1 */
00814     if (TCP_SEQ_LEQ(ackno, pcb->lastack)) {
00815       pcb->acked = 0;
00816       /* Clause 2 */
00817       if (tcplen == 0) {
00818         /* Clause 3 */
00819         if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge){
00820           /* Clause 4 */
00821           if (pcb->rtime >= 0) {
00822             /* Clause 5 */
00823             if (pcb->lastack == ackno) {
00824               found_dupack = 1;
00825               if (pcb->dupacks + 1 > pcb->dupacks)
00826                 ++pcb->dupacks;
00827               if (pcb->dupacks > 3) {
00828                 /* Inflate the congestion window, but not if it means that
00829                    the value overflows. */
00830                 if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
00831                   pcb->cwnd += pcb->mss;
00832                 }
00833               } else if (pcb->dupacks == 3) {
00834                 /* Do fast retransmit */
00835                 tcp_rexmit_fast(pcb);
00836               }
00837             }
00838           }
00839         }
00840       }
00841       /* If Clause (1) or more is true, but not a duplicate ack, reset
00842        * count of consecutive duplicate acks */
00843       if (!found_dupack) {
00844         pcb->dupacks = 0;
00845       }
00846     } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)){
00847       /* We come here when the ACK acknowledges new data. */
00848 
00849       /* Reset the "IN Fast Retransmit" flag, since we are no longer
00850          in fast retransmit. Also reset the congestion window to the
00851          slow start threshold. */
00852       if (pcb->flags & TF_INFR) {
00853         pcb->flags &= ~TF_INFR;
00854         pcb->cwnd = pcb->ssthresh;
00855       }
00856 
00857       /* Reset the number of retransmissions. */
00858       pcb->nrtx = 0;
00859 
00860       /* Reset the retransmission time-out. */
00861       pcb->rto = (pcb->sa >> 3) + pcb->sv;
00862 
00863       /* Update the send buffer space. Diff between the two can never exceed 64K? */
00864       pcb->acked = (u16_t)(ackno - pcb->lastack);
00865 
00866       pcb->snd_buf += pcb->acked;
00867 
00868       /* Reset the fast retransmit variables. */
00869       pcb->dupacks = 0;
00870       pcb->lastack = ackno;
00871 
00872       /* Update the congestion control variables (cwnd and
00873          ssthresh). */
00874       if (pcb->state >= ESTABLISHED) {
00875         if (pcb->cwnd < pcb->ssthresh) {
00876           if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
00877             pcb->cwnd += pcb->mss;
00878           }
00879           LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"U16_F"\n", pcb->cwnd));
00880         } else {
00881           u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd);
00882           if (new_cwnd > pcb->cwnd) {
00883             pcb->cwnd = new_cwnd;
00884           }
00885           LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"U16_F"\n", pcb->cwnd));
00886         }
00887       }
00888       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n",
00889                                     ackno,
00890                                     pcb->unacked != NULL?
00891                                     ntohl(pcb->unacked->tcphdr->seqno): 0,
00892                                     pcb->unacked != NULL?
00893                                     ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0));
00894 
00895       /* Remove segment from the unacknowledged list if the incoming
00896          ACK acknowlegdes them. */
00897       while (pcb->unacked != NULL &&
00898              TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) +
00899                          TCP_TCPLEN(pcb->unacked), ackno)) {
00900         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unacked\n",
00901                                       ntohl(pcb->unacked->tcphdr->seqno),
00902                                       ntohl(pcb->unacked->tcphdr->seqno) +
00903                                       TCP_TCPLEN(pcb->unacked)));
00904 
00905         next = pcb->unacked;
00906         pcb->unacked = pcb->unacked->next;
00907 
00908         LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen));
00909         LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
00910         /* Prevent ACK for FIN to generate a sent event */
00911         if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) {
00912           pcb->acked--;
00913         }
00914 
00915         pcb->snd_queuelen -= pbuf_clen(next->p);
00916         tcp_seg_free(next);
00917 
00918         LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unacked)\n", (u16_t)pcb->snd_queuelen));
00919         if (pcb->snd_queuelen != 0) {
00920           LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL ||
00921                       pcb->unsent != NULL);
00922         }
00923       }
00924 
00925       /* If there's nothing left to acknowledge, stop the retransmit
00926          timer, otherwise reset it to start again */
00927       if(pcb->unacked == NULL)
00928         pcb->rtime = -1;
00929       else
00930         pcb->rtime = 0;
00931 
00932       pcb->polltmr = 0;
00933     } else {
00934       /* Fix bug bug #21582: out of sequence ACK, didn't really ack anything */
00935       pcb->acked = 0;
00936     }
00937 
00938     /* We go through the ->unsent list to see if any of the segments
00939        on the list are acknowledged by the ACK. This may seem
00940        strange since an "unsent" segment shouldn't be acked. The
00941        rationale is that lwIP puts all outstanding segments on the
00942        ->unsent list after a retransmission, so these segments may
00943        in fact have been sent once. */
00944     while (pcb->unsent != NULL &&
00945            TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) + 
00946                            TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) {
00947       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n",
00948                                     ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) +
00949                                     TCP_TCPLEN(pcb->unsent)));
00950 
00951       next = pcb->unsent;
00952       pcb->unsent = pcb->unsent->next;
00953       LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen));
00954       LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
00955       /* Prevent ACK for FIN to generate a sent event */
00956       if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) {
00957         pcb->acked--;
00958       }
00959       pcb->snd_queuelen -= pbuf_clen(next->p);
00960       tcp_seg_free(next);
00961       LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unsent)\n", (u16_t)pcb->snd_queuelen));
00962       if (pcb->snd_queuelen != 0) {
00963         LWIP_ASSERT("tcp_receive: valid queue length",
00964           pcb->unacked != NULL || pcb->unsent != NULL);
00965       }
00966     }
00967     /* End of ACK for new data processing. */
00968 
00969     LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %"U32_F" rtseq %"U32_F" ackno %"U32_F"\n",
00970                                 pcb->rttest, pcb->rtseq, ackno));
00971 
00972     /* RTT estimation calculations. This is done by checking if the
00973        incoming segment acknowledges the segment we use to take a
00974        round-trip time measurement. */
00975     if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) {
00976       /* diff between this shouldn't exceed 32K since this are tcp timer ticks
00977          and a round-trip shouldn't be that long... */
00978       m = (s16_t)(tcp_ticks - pcb->rttest);
00979 
00980       LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %"U16_F" ticks (%"U16_F" msec).\n",
00981                                   m, m * TCP_SLOW_INTERVAL));
00982 
00983       /* This is taken directly from VJs original code in his paper */
00984       m = m - (pcb->sa >> 3);
00985       pcb->sa += m;
00986       if (m < 0) {
00987         m = -m;
00988       }
00989       m = m - (pcb->sv >> 2);
00990       pcb->sv += m;
00991       pcb->rto = (pcb->sa >> 3) + pcb->sv;
00992 
00993       LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %"U16_F" (%"U16_F" milliseconds)\n",
00994                                   pcb->rto, pcb->rto * TCP_SLOW_INTERVAL));
00995 
00996       pcb->rttest = 0;
00997     }
00998   }
00999 
01000   /* If the incoming segment contains data, we must process it
01001      further. */
01002   if (tcplen > 0) {
01003     /* This code basically does three things:
01004 
01005     +) If the incoming segment contains data that is the next
01006     in-sequence data, this data is passed to the application. This
01007     might involve trimming the first edge of the data. The rcv_nxt
01008     variable and the advertised window are adjusted.
01009 
01010     +) If the incoming segment has data that is above the next
01011     sequence number expected (->rcv_nxt), the segment is placed on
01012     the ->ooseq queue. This is done by finding the appropriate
01013     place in the ->ooseq queue (which is ordered by sequence
01014     number) and trim the segment in both ends if needed. An
01015     immediate ACK is sent to indicate that we received an
01016     out-of-sequence segment.
01017 
01018     +) Finally, we check if the first segment on the ->ooseq queue
01019     now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If
01020     rcv_nxt > ooseq->seqno, we must trim the first edge of the
01021     segment on ->ooseq before we adjust rcv_nxt. The data in the
01022     segments that are now on sequence are chained onto the
01023     incoming segment so that we only need to call the application
01024     once.
01025     */
01026 
01027     /* First, we check if we must trim the first edge. We have to do
01028        this if the sequence number of the incoming segment is less
01029        than rcv_nxt, and the sequence number plus the length of the
01030        segment is larger than rcv_nxt. */
01031     /*    if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){
01032           if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/
01033     if (TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno + 1, seqno + tcplen - 1)){
01034       /* Trimming the first edge is done by pushing the payload
01035          pointer in the pbuf downwards. This is somewhat tricky since
01036          we do not want to discard the full contents of the pbuf up to
01037          the new starting point of the data since we have to keep the
01038          TCP header which is present in the first pbuf in the chain.
01039 
01040          What is done is really quite a nasty hack: the first pbuf in
01041          the pbuf chain is pointed to by inseg.p. Since we need to be
01042          able to deallocate the whole pbuf, we cannot change this
01043          inseg.p pointer to point to any of the later pbufs in the
01044          chain. Instead, we point the ->payload pointer in the first
01045          pbuf to data in one of the later pbufs. We also set the
01046          inseg.data pointer to point to the right place. This way, the
01047          ->p pointer will still point to the first pbuf, but the
01048          ->p->payload pointer will point to data in another pbuf.
01049 
01050          After we are done with adjusting the pbuf pointers we must
01051          adjust the ->data pointer in the seg and the segment
01052          length.*/
01053 
01054       off = pcb->rcv_nxt - seqno;
01055       p = inseg.p;
01056       LWIP_ASSERT("inseg.p != NULL", inseg.p);
01057       LWIP_ASSERT("insane offset!", (off < 0x7fff));
01058       if (inseg.p->len < off) {
01059         LWIP_ASSERT("pbuf too short!", (((s32_t)inseg.p->tot_len) >= off));
01060         new_tot_len = (u16_t)(inseg.p->tot_len - off);
01061         while (p->len < off) {
01062           off -= p->len;
01063           /* KJM following line changed (with addition of new_tot_len var)
01064              to fix bug #9076
01065              inseg.p->tot_len -= p->len; */
01066           p->tot_len = new_tot_len;
01067           p->len = 0;
01068           p = p->next;
01069         }
01070         if(pbuf_header(p, (s16_t)-off)) {
01071           /* Do we need to cope with this failing?  Assert for now */
01072           LWIP_ASSERT("pbuf_header failed", 0);
01073         }
01074       } else {
01075         if(pbuf_header(inseg.p, (s16_t)-off)) {
01076           /* Do we need to cope with this failing?  Assert for now */
01077           LWIP_ASSERT("pbuf_header failed", 0);
01078         }
01079       }
01080       /* KJM following line changed to use p->payload rather than inseg->p->payload
01081          to fix bug #9076 */
01082       inseg.dataptr = p->payload;
01083       inseg.len -= (u16_t)(pcb->rcv_nxt - seqno);
01084       inseg.tcphdr->seqno = seqno = pcb->rcv_nxt;
01085     }
01086     else {
01087       if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){
01088         /* the whole segment is < rcv_nxt */
01089         /* must be a duplicate of a packet that has already been correctly handled */
01090 
01091         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno));
01092         tcp_ack_now(pcb);
01093       }
01094     }
01095 
01096     /* The sequence number must be within the window (above rcv_nxt
01097        and below rcv_nxt + rcv_wnd) in order to be further
01098        processed. */
01099     if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, 
01100                         pcb->rcv_nxt + pcb->rcv_wnd - 1)){
01101       if (pcb->rcv_nxt == seqno) {
01102         accepted_inseq = 1; 
01103         /* The incoming segment is the next in sequence. We check if
01104            we have to trim the end of the segment and update rcv_nxt
01105            and pass the data to the application. */
01106         tcplen = TCP_TCPLEN(&inseg);
01107 
01108         if (tcplen > pcb->rcv_wnd) {
01109           LWIP_DEBUGF(TCP_INPUT_DEBUG, 
01110                       ("tcp_receive: other end overran receive window"
01111                        "seqno %"U32_F" len %"U32_F" right edge %"U32_F"\n",
01112                        seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd));
01113           if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
01114             /* Must remove the FIN from the header as we're trimming 
01115              * that byte of sequence-space from the packet */
01116             TCPH_FLAGS_SET(inseg.tcphdr, TCPH_FLAGS(inseg.tcphdr) &~ TCP_FIN);
01117           }
01118           /* Adjust length of segment to fit in the window. */
01119           inseg.len = pcb->rcv_wnd;
01120           if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
01121             inseg.len -= 1;
01122           }
01123           pbuf_realloc(inseg.p, inseg.len);
01124           tcplen = TCP_TCPLEN(&inseg);
01125           LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n",
01126                       (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd));
01127         }
01128 #if TCP_QUEUE_OOSEQ
01129         if (pcb->ooseq != NULL) {
01130           if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
01131             LWIP_DEBUGF(TCP_INPUT_DEBUG, 
01132                         ("tcp_receive: received in-order FIN, binning ooseq queue\n"));
01133             /* Received in-order FIN means anything that was received
01134              * out of order must now have been received in-order, so
01135              * bin the ooseq queue */
01136             while (pcb->ooseq != NULL) {
01137               struct tcp_seg *old_ooseq = pcb->ooseq;
01138               pcb->ooseq = pcb->ooseq->next;
01139               memp_free(MEMP_TCP_SEG, old_ooseq);
01140             }               
01141           } else if (TCP_SEQ_LEQ(pcb->ooseq->tcphdr->seqno, seqno + tcplen)) {
01142             if (pcb->ooseq->len > 0) {
01143               /* We have to trim the second edge of the incoming segment. */
01144               LWIP_ASSERT("tcp_receive: trimmed segment would have zero length\n",
01145                           TCP_SEQ_GT(pcb->ooseq->tcphdr->seqno, seqno));
01146               /* FIN in inseg already handled by dropping whole ooseq queue */
01147               inseg.len = (u16_t)(pcb->ooseq->tcphdr->seqno - seqno);
01148               if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
01149                 inseg.len -= 1;
01150               }
01151               pbuf_realloc(inseg.p, inseg.len);
01152               tcplen = TCP_TCPLEN(&inseg);
01153               LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n",
01154                           (seqno + tcplen) == pcb->ooseq->tcphdr->seqno);
01155             } else {
01156               /* does the ooseq segment contain only flags that are in inseg also? */
01157               if ((TCPH_FLAGS(inseg.tcphdr) & (TCP_FIN|TCP_SYN)) ==
01158                   (TCPH_FLAGS(pcb->ooseq->tcphdr) & (TCP_FIN|TCP_SYN))) {
01159                 struct tcp_seg *old_ooseq = pcb->ooseq;
01160                 pcb->ooseq = pcb->ooseq->next;
01161                 memp_free(MEMP_TCP_SEG, old_ooseq);
01162               }
01163             }
01164           }
01165         }
01166 #endif /* TCP_QUEUE_OOSEQ */
01167 
01168         pcb->rcv_nxt = seqno + tcplen;
01169 
01170         /* Update the receiver's (our) window. */
01171         LWIP_ASSERT("tcp_receive: tcplen > rcv_wnd\n", pcb->rcv_wnd >= tcplen);
01172         pcb->rcv_wnd -= tcplen;
01173 
01174         tcp_update_rcv_ann_wnd(pcb);
01175 
01176         /* If there is data in the segment, we make preparations to
01177            pass this up to the application. The ->recv_data variable
01178            is used for holding the pbuf that goes to the
01179            application. The code for reassembling out-of-sequence data
01180            chains its data on this pbuf as well.
01181 
01182            If the segment was a FIN, we set the TF_GOT_FIN flag that will
01183            be used to indicate to the application that the remote side has
01184            closed its end of the connection. */
01185         if (inseg.p->tot_len > 0) {
01186           recv_data = inseg.p;
01187           /* Since this pbuf now is the responsibility of the
01188              application, we delete our reference to it so that we won't
01189              (mistakingly) deallocate it. */
01190           inseg.p = NULL;
01191         }
01192         if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
01193           LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n"));
01194           recv_flags |= TF_GOT_FIN;
01195         }
01196 
01197 #if TCP_QUEUE_OOSEQ
01198         /* We now check if we have segments on the ->ooseq queue that
01199            is now in sequence. */
01200         while (pcb->ooseq != NULL &&
01201                pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) {
01202 
01203           cseg = pcb->ooseq;
01204           seqno = pcb->ooseq->tcphdr->seqno;
01205 
01206           pcb->rcv_nxt += TCP_TCPLEN(cseg);
01207           LWIP_ASSERT("tcp_receive: ooseq tcplen > rcv_wnd\n",
01208                       pcb->rcv_wnd >= TCP_TCPLEN(cseg));
01209           pcb->rcv_wnd -= TCP_TCPLEN(cseg);
01210 
01211           tcp_update_rcv_ann_wnd(pcb);
01212 
01213           if (cseg->p->tot_len > 0) {
01214             /* Chain this pbuf onto the pbuf that we will pass to
01215                the application. */
01216             if (recv_data) {
01217               pbuf_cat(recv_data, cseg->p);
01218             } else {
01219               recv_data = cseg->p;
01220             }
01221             cseg->p = NULL;
01222           }
01223           if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
01224             LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n"));
01225             recv_flags |= TF_GOT_FIN;
01226             if (pcb->state == ESTABLISHED) { /* force passive close or we can move to active close */
01227               pcb->state = CLOSE_WAIT;
01228             } 
01229           }
01230 
01231 
01232           pcb->ooseq = cseg->next;
01233           tcp_seg_free(cseg);
01234         }
01235 #endif /* TCP_QUEUE_OOSEQ */
01236 
01237 
01238         /* Acknowledge the segment(s). */
01239         tcp_ack(pcb);
01240 
01241       } else {
01242         /* We get here if the incoming segment is out-of-sequence. */
01243         tcp_ack_now(pcb);
01244 #if TCP_QUEUE_OOSEQ
01245         /* We queue the segment on the ->ooseq queue. */
01246         if (pcb->ooseq == NULL) {
01247           pcb->ooseq = tcp_seg_copy(&inseg);
01248         } else {
01249           /* If the queue is not empty, we walk through the queue and
01250              try to find a place where the sequence number of the
01251              incoming segment is between the sequence numbers of the
01252              previous and the next segment on the ->ooseq queue. That is
01253              the place where we put the incoming segment. If needed, we
01254              trim the second edges of the previous and the incoming
01255              segment so that it will fit into the sequence.
01256 
01257              If the incoming segment has the same sequence number as a
01258              segment on the ->ooseq queue, we discard the segment that
01259              contains less data. */
01260 
01261           prev = NULL;
01262           for(next = pcb->ooseq; next != NULL; next = next->next) {
01263             if (seqno == next->tcphdr->seqno) {
01264               /* The sequence number of the incoming segment is the
01265                  same as the sequence number of the segment on
01266                  ->ooseq. We check the lengths to see which one to
01267                  discard. */
01268               if (inseg.len > next->len) {
01269                 /* The incoming segment is larger than the old
01270                    segment. We replace the old segment with the new
01271                    one. */
01272                 cseg = tcp_seg_copy(&inseg);
01273                 if (cseg != NULL) {
01274                   cseg->next = next->next;
01275                   if (prev != NULL) {
01276                     prev->next = cseg;
01277                   } else {
01278                     pcb->ooseq = cseg;
01279                   }
01280                   tcp_seg_free(next);
01281                   if (cseg->next != NULL) {
01282                     next = cseg->next;
01283                     if (TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) {
01284                       /* We need to trim the incoming segment. */
01285                       cseg->len = (u16_t)(next->tcphdr->seqno - seqno);
01286                       pbuf_realloc(cseg->p, cseg->len);
01287                     }
01288                   }
01289                 }
01290                 break;
01291               } else {
01292                 /* Either the lenghts are the same or the incoming
01293                    segment was smaller than the old one; in either
01294                    case, we ditch the incoming segment. */
01295                 break;
01296               }
01297             } else {
01298               if (prev == NULL) {
01299                 if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {
01300                   /* The sequence number of the incoming segment is lower
01301                      than the sequence number of the first segment on the
01302                      queue. We put the incoming segment first on the
01303                      queue. */
01304 
01305                   if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) {
01306                     /* We need to trim the incoming segment. */
01307                     inseg.len = (u16_t)(next->tcphdr->seqno - seqno);
01308                     pbuf_realloc(inseg.p, inseg.len);
01309                   }
01310                   cseg = tcp_seg_copy(&inseg);
01311                   if (cseg != NULL) {
01312                     cseg->next = next;
01313                     pcb->ooseq = cseg;
01314                   }
01315                   break;
01316                 }
01317               } else 
01318                 /*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) &&
01319                   TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/
01320                 if(TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)){
01321                 /* The sequence number of the incoming segment is in
01322                    between the sequence numbers of the previous and
01323                    the next segment on ->ooseq. We trim and insert the
01324                    incoming segment and trim the previous segment, if
01325                    needed. */
01326                 if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) {
01327                   /* We need to trim the incoming segment. */
01328                   inseg.len = (u16_t)(next->tcphdr->seqno - seqno);
01329                   pbuf_realloc(inseg.p, inseg.len);
01330                 }
01331 
01332                 cseg = tcp_seg_copy(&inseg);
01333                 if (cseg != NULL) {
01334                   cseg->next = next;
01335                   prev->next = cseg;
01336                   if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) {
01337                     /* We need to trim the prev segment. */
01338                     prev->len = (u16_t)(seqno - prev->tcphdr->seqno);
01339                     pbuf_realloc(prev->p, prev->len);
01340                   }
01341                 }
01342                 break;
01343               }
01344               /* If the "next" segment is the last segment on the
01345                  ooseq queue, we add the incoming segment to the end
01346                  of the list. */
01347               if (next->next == NULL &&
01348                   TCP_SEQ_GT(seqno, next->tcphdr->seqno)) {
01349                 next->next = tcp_seg_copy(&inseg);
01350                 if (next->next != NULL) {
01351                   if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) {
01352                     /* We need to trim the last segment. */
01353                     next->len = (u16_t)(seqno - next->tcphdr->seqno);
01354                     pbuf_realloc(next->p, next->len);
01355                   }
01356                 }
01357                 break;
01358               }
01359             }
01360             prev = next;
01361           }
01362         }
01363 #endif /* TCP_QUEUE_OOSEQ */
01364 
01365       }
01366     } else {
01367       tcp_ack_now(pcb);
01368     }
01369   } else {
01370     /* Segments with length 0 is taken care of here. Segments that
01371        fall out of the window are ACKed. */
01372     /*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) ||
01373       TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/
01374     if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){
01375       tcp_ack_now(pcb);
01376     }
01377   }
01378   return accepted_inseq;
01379 }
01380 
01381 /**
01382  * Parses the options contained in the incoming segment. 
01383  *
01384  * Called from tcp_listen_input() and tcp_process().
01385  * Currently, only the MSS option is supported!
01386  *
01387  * @param pcb the tcp_pcb for which a segment arrived
01388  */
01389 static void
01390 tcp_parseopt(struct tcp_pcb *pcb)
01391 {
01392   u16_t c, max_c;
01393   u16_t mss;
01394   u8_t *opts, opt;
01395 #if LWIP_TCP_TIMESTAMPS
01396   u32_t tsval;
01397 #endif
01398 
01399   opts = (u8_t *)tcphdr + TCP_HLEN;
01400 
01401   /* Parse the TCP MSS option, if present. */
01402   if(TCPH_HDRLEN(tcphdr) > 0x5) {
01403     max_c = (TCPH_HDRLEN(tcphdr) - 5) << 2;
01404     for (c = 0; c < max_c; ) {
01405       opt = opts[c];
01406       switch (opt) {
01407       case 0x00:
01408         /* End of options. */
01409         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: EOL\n"));
01410         return;
01411       case 0x01:
01412         /* NOP option. */
01413         ++c;
01414         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: NOP\n"));
01415         break;
01416       case 0x02:
01417         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: MSS\n"));
01418         if (opts[c + 1] != 0x04 || c + 0x04 > max_c) {
01419           /* Bad length */
01420           LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
01421           return;
01422         }
01423         /* An MSS option with the right option length. */
01424         mss = (opts[c + 2] << 8) | opts[c + 3];
01425         /* Limit the mss to the configured TCP_MSS and prevent division by zero */
01426         pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss;
01427         /* Advance to next option */
01428         c += 0x04;
01429         break;
01430 #if LWIP_TCP_TIMESTAMPS
01431       case 0x08:
01432         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: TS\n"));
01433         if (opts[c + 1] != 0x0A || c + 0x0A > max_c) {
01434           /* Bad length */
01435           LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
01436           return;
01437         }
01438         /* TCP timestamp option with valid length */
01439         tsval = (opts[c+2]) | (opts[c+3] << 8) | 
01440           (opts[c+4] << 16) | (opts[c+5] << 24);
01441         if (flags & TCP_SYN) {
01442           pcb->ts_recent = ntohl(tsval);
01443           pcb->flags |= TF_TIMESTAMP;
01444         } else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno+tcplen)) {
01445           pcb->ts_recent = ntohl(tsval);
01446         }
01447         /* Advance to next option */
01448         c += 0x0A;
01449         break;
01450 #endif
01451       default:
01452         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: other\n"));
01453         if (opts[c + 1] == 0) {
01454           LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
01455           /* If the length field is zero, the options are malformed
01456              and we don't process them further. */
01457           return;
01458         }
01459         /* All other options have a length field, so that we easily
01460            can skip past them. */
01461         c += opts[c + 1];
01462       }
01463     }
01464   }
01465 }
01466 
01467 #endif /* LWIP_TCP */