STM32F7 Ethernet interface for nucleo STM32F767

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers lwip_tcp_in.c Source File

lwip_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/priv/tcp_priv.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_chksum.h"
00055 #include "lwip/stats.h"
00056 #include "lwip/ip6.h"
00057 #include "lwip/ip6_addr.h"
00058 #if LWIP_ND6_TCP_REACHABILITY_HINTS
00059 #include "lwip/nd6.h"
00060 #endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */
00061 
00062 /** Initial CWND calculation as defined RFC 2581 */
00063 #define LWIP_TCP_CALC_INITIAL_CWND(mss) LWIP_MIN((4U * (mss)), LWIP_MAX((2U * (mss)), 4380U));
00064 
00065 /* These variables are global to all functions involved in the input
00066    processing of TCP segments. They are set by the tcp_input()
00067    function. */
00068 static struct tcp_seg inseg;
00069 static struct tcp_hdr *tcphdr;
00070 static u16_t tcphdr_optlen;
00071 static u16_t tcphdr_opt1len;
00072 static u8_t* tcphdr_opt2;
00073 static u16_t tcp_optidx;
00074 static u32_t seqno, ackno;
00075 static tcpwnd_size_t recv_acked;
00076 static u16_t tcplen;
00077 static u8_t flags;
00078 
00079 static u8_t recv_flags;
00080 static struct pbuf *recv_data;
00081 
00082 struct tcp_pcb *tcp_input_pcb;
00083 
00084 /* Forward declarations. */
00085 static err_t tcp_process(struct tcp_pcb *pcb);
00086 static void tcp_receive(struct tcp_pcb *pcb);
00087 static void tcp_parseopt(struct tcp_pcb *pcb);
00088 
00089 static void tcp_listen_input(struct tcp_pcb_listen *pcb);
00090 static void tcp_timewait_input(struct tcp_pcb *pcb);
00091 
00092 /**
00093  * The initial input processing of TCP. It verifies the TCP header, demultiplexes
00094  * the segment between the PCBs and passes it on to tcp_process(), which implements
00095  * the TCP finite state machine. This function is called by the IP layer (in
00096  * ip_input()).
00097  *
00098  * @param p received TCP segment to process (p->payload pointing to the TCP header)
00099  * @param inp network interface on which this segment was received
00100  */
00101 void
00102 tcp_input(struct pbuf *p, struct netif *inp)
00103 {
00104   struct tcp_pcb *pcb, *prev;
00105   struct tcp_pcb_listen *lpcb;
00106 #if SO_REUSE
00107   struct tcp_pcb *lpcb_prev = NULL;
00108   struct tcp_pcb_listen *lpcb_any = NULL;
00109 #endif /* SO_REUSE */
00110   u8_t hdrlen_bytes;
00111   err_t err;
00112 
00113   LWIP_UNUSED_ARG(inp);
00114 
00115   PERF_START;
00116 
00117   TCP_STATS_INC(tcp.recv);
00118   MIB2_STATS_INC(mib2.tcpinsegs);
00119 
00120   tcphdr = (struct tcp_hdr *)p->payload;
00121 
00122 #if TCP_INPUT_DEBUG
00123   tcp_debug_print(tcphdr);
00124 #endif
00125 
00126   /* Check that TCP header fits in payload */
00127   if (p->len < TCP_HLEN) {
00128     /* drop short packets */
00129     LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len));
00130     TCP_STATS_INC(tcp.lenerr);
00131     goto dropped;
00132   }
00133 
00134   /* Don't even process incoming broadcasts/multicasts. */
00135   if (ip_addr_isbroadcast(ip_current_dest_addr(), ip_current_netif()) ||
00136       ip_addr_ismulticast(ip_current_dest_addr())) {
00137     TCP_STATS_INC(tcp.proterr);
00138     goto dropped;
00139   }
00140 
00141 #if CHECKSUM_CHECK_TCP
00142   IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_TCP) {
00143     /* Verify TCP checksum. */
00144     u16_t chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len,
00145                                ip_current_src_addr(), ip_current_dest_addr());
00146     if (chksum != 0) {
00147         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n",
00148           chksum));
00149       tcp_debug_print(tcphdr);
00150       TCP_STATS_INC(tcp.chkerr);
00151       goto dropped;
00152     }
00153   }
00154 #endif /* CHECKSUM_CHECK_TCP */
00155 
00156   /* sanity-check header length */
00157   hdrlen_bytes = TCPH_HDRLEN(tcphdr) * 4;
00158   if ((hdrlen_bytes < TCP_HLEN) || (hdrlen_bytes > p->tot_len)) {
00159     LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: invalid header length (%"U16_F")\n", (u16_t)hdrlen_bytes));
00160     TCP_STATS_INC(tcp.lenerr);
00161     goto dropped;
00162   }
00163 
00164   /* Move the payload pointer in the pbuf so that it points to the
00165      TCP data instead of the TCP header. */
00166   tcphdr_optlen = hdrlen_bytes - TCP_HLEN;
00167   tcphdr_opt2 = NULL;
00168   if (p->len >= hdrlen_bytes) {
00169     /* all options are in the first pbuf */
00170     tcphdr_opt1len = tcphdr_optlen;
00171     pbuf_header(p, -(s16_t)hdrlen_bytes); /* cannot fail */
00172   } else {
00173     u16_t opt2len;
00174     /* TCP header fits into first pbuf, options don't - data is in the next pbuf */
00175     /* there must be a next pbuf, due to hdrlen_bytes sanity check above */
00176     LWIP_ASSERT("p->next != NULL", p->next != NULL);
00177 
00178     /* advance over the TCP header (cannot fail) */
00179     pbuf_header(p, -TCP_HLEN);
00180 
00181     /* determine how long the first and second parts of the options are */
00182     tcphdr_opt1len = p->len;
00183     opt2len = tcphdr_optlen - tcphdr_opt1len;
00184 
00185     /* options continue in the next pbuf: set p to zero length and hide the
00186         options in the next pbuf (adjusting p->tot_len) */
00187     pbuf_header(p, -(s16_t)tcphdr_opt1len);
00188 
00189     /* check that the options fit in the second pbuf */
00190     if (opt2len > p->next->len) {
00191       /* drop short packets */
00192       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: options overflow second pbuf (%"U16_F" bytes)\n", p->next->len));
00193       TCP_STATS_INC(tcp.lenerr);
00194       goto dropped;
00195     }
00196 
00197     /* remember the pointer to the second part of the options */
00198     tcphdr_opt2 = (u8_t*)p->next->payload;
00199 
00200     /* advance p->next to point after the options, and manually
00201         adjust p->tot_len to keep it consistent with the changed p->next */
00202     pbuf_header(p->next, -(s16_t)opt2len);
00203     p->tot_len -= opt2len;
00204 
00205     LWIP_ASSERT("p->len == 0", p->len == 0);
00206     LWIP_ASSERT("p->tot_len == p->next->tot_len", p->tot_len == p->next->tot_len);
00207   }
00208 
00209   /* Convert fields in TCP header to host byte order. */
00210   tcphdr->src = lwip_ntohs(tcphdr->src);
00211   tcphdr->dest = lwip_ntohs(tcphdr->dest);
00212   seqno = tcphdr->seqno = lwip_ntohl(tcphdr->seqno);
00213   ackno = tcphdr->ackno = lwip_ntohl(tcphdr->ackno);
00214   tcphdr->wnd = lwip_ntohs(tcphdr->wnd);
00215 
00216   flags = TCPH_FLAGS(tcphdr);
00217   tcplen = p->tot_len + ((flags & (TCP_FIN | TCP_SYN)) ? 1 : 0);
00218 
00219   /* Demultiplex an incoming segment. First, we check if it is destined
00220      for an active connection. */
00221   prev = NULL;
00222 
00223   for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
00224     LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED);
00225     LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
00226     LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
00227     if (pcb->remote_port == tcphdr->src &&
00228         pcb->local_port == tcphdr->dest &&
00229         ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()) &&
00230         ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) {
00231       /* Move this PCB to the front of the list so that subsequent
00232          lookups will be faster (we exploit locality in TCP segment
00233          arrivals). */
00234       LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb);
00235       if (prev != NULL) {
00236         prev->next = pcb->next;
00237         pcb->next = tcp_active_pcbs;
00238         tcp_active_pcbs = pcb;
00239       } else {
00240         TCP_STATS_INC(tcp.cachehit);
00241       }
00242       LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb);
00243       break;
00244     }
00245     prev = pcb;
00246   }
00247 
00248   if (pcb == NULL) {
00249     /* If it did not go to an active connection, we check the connections
00250        in the TIME-WAIT state. */
00251     for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
00252       LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
00253       if (pcb->remote_port == tcphdr->src &&
00254           pcb->local_port == tcphdr->dest &&
00255           ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()) &&
00256           ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) {
00257         /* We don't really care enough to move this PCB to the front
00258            of the list since we are not very likely to receive that
00259            many segments for connections in TIME-WAIT. */
00260         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n"));
00261         tcp_timewait_input(pcb);
00262         pbuf_free(p);
00263         return;
00264       }
00265     }
00266 
00267     /* Finally, if we still did not get a match, we check all PCBs that
00268        are LISTENing for incoming connections. */
00269     prev = NULL;
00270     for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
00271       if (lpcb->local_port == tcphdr->dest) {
00272         if (IP_IS_ANY_TYPE_VAL(lpcb->local_ip)) {
00273           /* found an ANY TYPE (IPv4/IPv6) match */
00274 #if SO_REUSE
00275           lpcb_any = lpcb;
00276           lpcb_prev = prev;
00277 #else /* SO_REUSE */
00278           break;
00279 #endif /* SO_REUSE */
00280         } else if (IP_ADDR_PCB_VERSION_MATCH_EXACT(lpcb, ip_current_dest_addr())) {
00281           if (ip_addr_cmp(&lpcb->local_ip, ip_current_dest_addr())) {
00282             /* found an exact match */
00283             break;
00284           } else if (ip_addr_isany(&lpcb->local_ip)) {
00285             /* found an ANY-match */
00286 #if SO_REUSE
00287             lpcb_any = lpcb;
00288             lpcb_prev = prev;
00289 #else /* SO_REUSE */
00290             break;
00291  #endif /* SO_REUSE */
00292           }
00293         }
00294       }
00295       prev = (struct tcp_pcb *)lpcb;
00296     }
00297 #if SO_REUSE
00298     /* first try specific local IP */
00299     if (lpcb == NULL) {
00300       /* only pass to ANY if no specific local IP has been found */
00301       lpcb = lpcb_any;
00302       prev = lpcb_prev;
00303     }
00304 #endif /* SO_REUSE */
00305     if (lpcb != NULL) {
00306       /* Move this PCB to the front of the list so that subsequent
00307          lookups will be faster (we exploit locality in TCP segment
00308          arrivals). */
00309       if (prev != NULL) {
00310         ((struct tcp_pcb_listen *)prev)->next = lpcb->next;
00311               /* our successor is the remainder of the listening list */
00312         lpcb->next = tcp_listen_pcbs.listen_pcbs;
00313               /* put this listening pcb at the head of the listening list */
00314         tcp_listen_pcbs.listen_pcbs = lpcb;
00315       } else {
00316         TCP_STATS_INC(tcp.cachehit);
00317       }
00318 
00319       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n"));
00320       tcp_listen_input(lpcb);
00321       pbuf_free(p);
00322       return;
00323     }
00324   }
00325 
00326 #if TCP_INPUT_DEBUG
00327   LWIP_DEBUGF(TCP_INPUT_DEBUG, ("+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags "));
00328   tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
00329   LWIP_DEBUGF(TCP_INPUT_DEBUG, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n"));
00330 #endif /* TCP_INPUT_DEBUG */
00331 
00332 
00333   if (pcb != NULL) {
00334     /* The incoming segment belongs to a connection. */
00335 #if TCP_INPUT_DEBUG
00336     tcp_debug_print_state(pcb->state);
00337 #endif /* TCP_INPUT_DEBUG */
00338 
00339     /* Set up a tcp_seg structure. */
00340     inseg.next = NULL;
00341     inseg.len = p->tot_len;
00342     inseg.p = p;
00343     inseg.tcphdr = tcphdr;
00344 
00345     recv_data = NULL;
00346     recv_flags = 0;
00347     recv_acked = 0;
00348 
00349     if (flags & TCP_PSH) {
00350       p->flags |= PBUF_FLAG_PUSH;
00351     }
00352 
00353     /* If there is data which was previously "refused" by upper layer */
00354     if (pcb->refused_data != NULL) {
00355       if ((tcp_process_refused_data(pcb) == ERR_ABRT) ||
00356         ((pcb->refused_data != NULL) && (tcplen > 0))) {
00357         /* pcb has been aborted or refused data is still refused and the new
00358            segment contains data */
00359         if (pcb->rcv_ann_wnd == 0) {
00360           /* this is a zero-window probe, we respond to it with current RCV.NXT
00361           and drop the data segment */
00362           tcp_send_empty_ack(pcb);
00363         }
00364         TCP_STATS_INC(tcp.drop);
00365         MIB2_STATS_INC(mib2.tcpinerrs);
00366         goto aborted;
00367       }
00368     }
00369     tcp_input_pcb = pcb;
00370     err = tcp_process(pcb);
00371     /* A return value of ERR_ABRT means that tcp_abort() was called
00372        and that the pcb has been freed. If so, we don't do anything. */
00373     if (err != ERR_ABRT) {
00374       if (recv_flags & TF_RESET) {
00375         /* TF_RESET means that the connection was reset by the other
00376            end. We then call the error callback to inform the
00377            application that the connection is dead before we
00378            deallocate the PCB. */
00379         TCP_EVENT_ERR(pcb->state, pcb->errf, pcb->callback_arg, ERR_RST);
00380         tcp_pcb_remove(&tcp_active_pcbs, pcb);
00381         memp_free(MEMP_TCP_PCB, pcb);
00382       } else {
00383         err = ERR_OK;
00384         /* If the application has registered a "sent" function to be
00385            called when new send buffer space is available, we call it
00386            now. */
00387         if (recv_acked > 0) {
00388           u16_t acked16;
00389 #if LWIP_WND_SCALE
00390           /* recv_acked is u32_t but the sent callback only takes a u16_t,
00391              so we might have to call it multiple times. */
00392           u32_t acked = recv_acked;
00393           while (acked > 0) {
00394             acked16 = (u16_t)LWIP_MIN(acked, 0xffffu);
00395             acked -= acked16;
00396 #else
00397           {
00398             acked16 = recv_acked;
00399 #endif
00400             TCP_EVENT_SENT(pcb, (u16_t)acked16, err);
00401             if (err == ERR_ABRT) {
00402               goto aborted;
00403             }
00404           }
00405           recv_acked = 0;
00406         }
00407         if (recv_flags & TF_CLOSED) {
00408           /* The connection has been closed and we will deallocate the
00409              PCB. */
00410           if (!(pcb->flags & TF_RXCLOSED)) {
00411             /* Connection closed although the application has only shut down the
00412                tx side: call the PCB's err callback and indicate the closure to
00413                ensure the application doesn't continue using the PCB. */
00414             TCP_EVENT_ERR(pcb->state, pcb->errf, pcb->callback_arg, ERR_CLSD);
00415           }
00416           tcp_pcb_remove(&tcp_active_pcbs, pcb);
00417           memp_free(MEMP_TCP_PCB, pcb);
00418           goto aborted;
00419         }
00420 #if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
00421         while (recv_data != NULL) {
00422           struct pbuf *rest = NULL;
00423           pbuf_split_64k(recv_data, &rest);
00424 #else /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */
00425         if (recv_data != NULL) {
00426 #endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */
00427 
00428           LWIP_ASSERT("pcb->refused_data == NULL", pcb->refused_data == NULL);
00429           if (pcb->flags & TF_RXCLOSED) {
00430             /* received data although already closed -> abort (send RST) to
00431                notify the remote host that not all data has been processed */
00432             pbuf_free(recv_data);
00433 #if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
00434             if (rest != NULL) {
00435               pbuf_free(rest);
00436             }
00437 #endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */
00438             tcp_abort(pcb);
00439             goto aborted;
00440           }
00441 
00442           /* Notify application that data has been received. */
00443           TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err);
00444           if (err == ERR_ABRT) {
00445 #if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
00446             if (rest != NULL) {
00447               pbuf_free(rest);
00448             }
00449 #endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */
00450             goto aborted;
00451           }
00452 
00453           /* If the upper layer can't receive this data, store it */
00454           if (err != ERR_OK) {
00455 #if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
00456             if (rest != NULL) {
00457               pbuf_cat(recv_data, rest);
00458             }
00459 #endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */
00460             pcb->refused_data = recv_data;
00461             LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: keep incoming packet, because pcb is \"full\"\n"));
00462 #if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
00463             break;
00464           } else {
00465             /* Upper layer received the data, go on with the rest if > 64K */
00466             recv_data = rest;
00467 #endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */
00468           }
00469         }
00470 
00471         /* If a FIN segment was received, we call the callback
00472            function with a NULL buffer to indicate EOF. */
00473         if (recv_flags & TF_GOT_FIN) {
00474           if (pcb->refused_data != NULL) {
00475             /* Delay this if we have refused data. */
00476             pcb->refused_data->flags |= PBUF_FLAG_TCP_FIN;
00477           } else {
00478             /* correct rcv_wnd as the application won't call tcp_recved()
00479                for the FIN's seqno */
00480             if (pcb->rcv_wnd != TCP_WND_MAX(pcb)) {
00481               pcb->rcv_wnd++;
00482             }
00483             TCP_EVENT_CLOSED(pcb, err);
00484             if (err == ERR_ABRT) {
00485               goto aborted;
00486             }
00487           }
00488         }
00489 
00490         tcp_input_pcb = NULL;
00491         /* Try to send something out. */
00492         tcp_output(pcb);
00493 #if TCP_INPUT_DEBUG
00494 #if TCP_DEBUG
00495         tcp_debug_print_state(pcb->state);
00496 #endif /* TCP_DEBUG */
00497 #endif /* TCP_INPUT_DEBUG */
00498       }
00499     }
00500     /* Jump target if pcb has been aborted in a callback (by calling tcp_abort()).
00501        Below this line, 'pcb' may not be dereferenced! */
00502 aborted:
00503     tcp_input_pcb = NULL;
00504     recv_data = NULL;
00505 
00506     /* give up our reference to inseg.p */
00507     if (inseg.p != NULL)
00508     {
00509       pbuf_free(inseg.p);
00510       inseg.p = NULL;
00511     }
00512   } else {
00513 
00514     /* If no matching PCB was found, send a TCP RST (reset) to the
00515        sender. */
00516     LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n"));
00517     if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) {
00518       TCP_STATS_INC(tcp.proterr);
00519       TCP_STATS_INC(tcp.drop);
00520       tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(),
00521         ip_current_src_addr(), tcphdr->dest, tcphdr->src);
00522     }
00523     pbuf_free(p);
00524   }
00525 
00526   LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());
00527   PERF_STOP("tcp_input");
00528   return;
00529 dropped:
00530   TCP_STATS_INC(tcp.drop);
00531   MIB2_STATS_INC(mib2.tcpinerrs);
00532   pbuf_free(p);
00533 }
00534 
00535 /**
00536  * Called by tcp_input() when a segment arrives for a listening
00537  * connection (from tcp_input()).
00538  *
00539  * @param pcb the tcp_pcb_listen for which a segment arrived
00540  *
00541  * @note the segment which arrived is saved in global variables, therefore only the pcb
00542  *       involved is passed as a parameter to this function
00543  */
00544 static void
00545 tcp_listen_input(struct tcp_pcb_listen *pcb)
00546 {
00547   struct tcp_pcb *npcb;
00548   u32_t iss;
00549   err_t rc;
00550 
00551   if (flags & TCP_RST) {
00552     /* An incoming RST should be ignored. Return. */
00553     return;
00554   }
00555 
00556   /* In the LISTEN state, we check for incoming SYN segments,
00557      creates a new PCB, and responds with a SYN|ACK. */
00558   if (flags & TCP_ACK) {
00559     /* For incoming segments with the ACK flag set, respond with a
00560        RST. */
00561     LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n"));
00562     tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(),
00563       ip_current_src_addr(), tcphdr->dest, tcphdr->src);
00564   } else if (flags & TCP_SYN) {
00565     LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest));
00566 #if TCP_LISTEN_BACKLOG
00567     if (pcb->accepts_pending >= pcb->backlog) {
00568       LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: listen backlog exceeded for port %"U16_F"\n", tcphdr->dest));
00569       return;
00570     }
00571 #endif /* TCP_LISTEN_BACKLOG */
00572     npcb = tcp_alloc(pcb->prio);
00573     /* If a new PCB could not be created (probably due to lack of memory),
00574        we don't do anything, but rely on the sender will retransmit the
00575        SYN at a time when we have more memory available. */
00576     if (npcb == NULL) {
00577       err_t err;
00578       LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n"));
00579       TCP_STATS_INC(tcp.memerr);
00580       TCP_EVENT_ACCEPT(pcb, NULL, pcb->callback_arg, ERR_MEM, err);
00581       LWIP_UNUSED_ARG(err); /* err not useful here */
00582       return;
00583     }
00584 #if TCP_LISTEN_BACKLOG
00585     pcb->accepts_pending++;
00586     npcb->flags |= TF_BACKLOGPEND;
00587 #endif /* TCP_LISTEN_BACKLOG */
00588     /* Set up the new PCB. */
00589     ip_addr_copy(npcb->local_ip, *ip_current_dest_addr());
00590     ip_addr_copy(npcb->remote_ip, *ip_current_src_addr());
00591     npcb->local_port = pcb->local_port;
00592     npcb->remote_port = tcphdr->src;
00593     npcb->state = SYN_RCVD;
00594     npcb->rcv_nxt = seqno + 1;
00595     npcb->rcv_ann_right_edge = npcb->rcv_nxt;
00596     iss = tcp_next_iss(npcb);
00597     npcb->snd_wl2 = iss;
00598     npcb->snd_nxt = iss;
00599     npcb->lastack = iss;
00600     npcb->snd_lbb = iss;
00601     npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */
00602     npcb->callback_arg = pcb->callback_arg;
00603 #if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG
00604     npcb->listener = pcb;
00605 #endif /* LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG */
00606     /* inherit socket options */
00607     npcb->so_options = pcb->so_options & SOF_INHERITED;
00608     /* Register the new PCB so that we can begin receiving segments
00609        for it. */
00610     TCP_REG_ACTIVE(npcb);
00611 
00612     /* Parse any options in the SYN. */
00613     tcp_parseopt(npcb);
00614     npcb->snd_wnd = tcphdr->wnd;
00615     npcb->snd_wnd_max = npcb->snd_wnd;
00616 
00617 #if TCP_CALCULATE_EFF_SEND_MSS
00618     npcb->mss = tcp_eff_send_mss(npcb->mss, &npcb->local_ip, &npcb->remote_ip);
00619 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
00620 
00621     MIB2_STATS_INC(mib2.tcppassiveopens);
00622 
00623     /* Send a SYN|ACK together with the MSS option. */
00624     rc = tcp_enqueue_flags(npcb, TCP_SYN | TCP_ACK);
00625     if (rc != ERR_OK) {
00626       tcp_abandon(npcb, 0);
00627       return;
00628     }
00629     tcp_output(npcb);
00630   }
00631   return;
00632 }
00633 
00634 /**
00635  * Called by tcp_input() when a segment arrives for a connection in
00636  * TIME_WAIT.
00637  *
00638  * @param pcb the tcp_pcb for which a segment arrived
00639  *
00640  * @note the segment which arrived is saved in global variables, therefore only the pcb
00641  *       involved is passed as a parameter to this function
00642  */
00643 static void
00644 tcp_timewait_input(struct tcp_pcb *pcb)
00645 {
00646   /* RFC 1337: in TIME_WAIT, ignore RST and ACK FINs + any 'acceptable' segments */
00647   /* RFC 793 3.9 Event Processing - Segment Arrives:
00648    * - first check sequence number - we skip that one in TIME_WAIT (always
00649    *   acceptable since we only send ACKs)
00650    * - second check the RST bit (... return) */
00651   if (flags & TCP_RST) {
00652     return;
00653   }
00654   /* - fourth, check the SYN bit, */
00655   if (flags & TCP_SYN) {
00656     /* If an incoming segment is not acceptable, an acknowledgment
00657        should be sent in reply */
00658     if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd)) {
00659       /* If the SYN is in the window it is an error, send a reset */
00660       tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(),
00661         ip_current_src_addr(), tcphdr->dest, tcphdr->src);
00662       return;
00663     }
00664   } else if (flags & TCP_FIN) {
00665     /* - eighth, check the FIN bit: Remain in the TIME-WAIT state.
00666          Restart the 2 MSL time-wait timeout.*/
00667     pcb->tmr = tcp_ticks;
00668   }
00669 
00670   if ((tcplen > 0)) {
00671     /* Acknowledge data, FIN or out-of-window SYN */
00672     pcb->flags |= TF_ACK_NOW;
00673     tcp_output(pcb);
00674   }
00675   return;
00676 }
00677 
00678 /**
00679  * Implements the TCP state machine. Called by tcp_input. In some
00680  * states tcp_receive() is called to receive data. The tcp_seg
00681  * argument will be freed by the caller (tcp_input()) unless the
00682  * recv_data pointer in the pcb is set.
00683  *
00684  * @param pcb the tcp_pcb for which a segment arrived
00685  *
00686  * @note the segment which arrived is saved in global variables, therefore only the pcb
00687  *       involved is passed as a parameter to this function
00688  */
00689 static err_t
00690 tcp_process(struct tcp_pcb *pcb)
00691 {
00692   struct tcp_seg *rseg;
00693   u8_t acceptable = 0;
00694   err_t err;
00695 
00696   err = ERR_OK;
00697 
00698   /* Process incoming RST segments. */
00699   if (flags & TCP_RST) {
00700     /* First, determine if the reset is acceptable. */
00701     if (pcb->state == SYN_SENT) {
00702       /* "In the SYN-SENT state (a RST received in response to an initial SYN),
00703           the RST is acceptable if the ACK field acknowledges the SYN." */
00704       if (ackno == pcb->snd_nxt) {
00705         acceptable = 1;
00706       }
00707     } else {
00708       /* "In all states except SYN-SENT, all reset (RST) segments are validated
00709           by checking their SEQ-fields." */
00710       if (seqno == pcb->rcv_nxt) {
00711         acceptable = 1;
00712       } else  if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
00713                                   pcb->rcv_nxt + pcb->rcv_wnd)) {
00714         /* If the sequence number is inside the window, we only send an ACK
00715            and wait for a re-send with matching sequence number.
00716            This violates RFC 793, but is required to protection against
00717            CVE-2004-0230 (RST spoofing attack). */
00718         tcp_ack_now(pcb);
00719       }
00720     }
00721 
00722     if (acceptable) {
00723       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n"));
00724       LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED);
00725       recv_flags |= TF_RESET;
00726       pcb->flags &= ~TF_ACK_DELAY;
00727       return ERR_RST;
00728     } else {
00729       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n",
00730        seqno, pcb->rcv_nxt));
00731       LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n",
00732        seqno, pcb->rcv_nxt));
00733       return ERR_OK;
00734     }
00735   }
00736 
00737   if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) {
00738     /* Cope with new connection attempt after remote end crashed */
00739     tcp_ack_now(pcb);
00740     return ERR_OK;
00741   }
00742 
00743   if ((pcb->flags & TF_RXCLOSED) == 0) {
00744     /* Update the PCB (in)activity timer unless rx is closed (see tcp_shutdown) */
00745     pcb->tmr = tcp_ticks;
00746   }
00747   pcb->keep_cnt_sent = 0;
00748 
00749   tcp_parseopt(pcb);
00750 
00751   /* Do different things depending on the TCP state. */
00752   switch (pcb->state) {
00753   case SYN_SENT:
00754     LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno,
00755      pcb->snd_nxt, lwip_ntohl(pcb->unacked->tcphdr->seqno)));
00756     /* received SYN ACK with expected sequence number? */
00757     if ((flags & TCP_ACK) && (flags & TCP_SYN)
00758         && (ackno == pcb->lastack + 1)) {
00759       pcb->rcv_nxt = seqno + 1;
00760       pcb->rcv_ann_right_edge = pcb->rcv_nxt;
00761       pcb->lastack = ackno;
00762       pcb->snd_wnd = tcphdr->wnd;
00763       pcb->snd_wnd_max = pcb->snd_wnd;
00764       pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */
00765       pcb->state = ESTABLISHED;
00766 
00767 #if TCP_CALCULATE_EFF_SEND_MSS
00768       pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip);
00769 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
00770 
00771       pcb->cwnd = LWIP_TCP_CALC_INITIAL_CWND(pcb->mss);
00772       LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_process (SENT): cwnd %"TCPWNDSIZE_F
00773                                    " ssthresh %"TCPWNDSIZE_F"\n",
00774                                    pcb->cwnd, pcb->ssthresh));
00775       LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0));
00776       --pcb->snd_queuelen;
00777       LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"TCPWNDSIZE_F"\n", (tcpwnd_size_t)pcb->snd_queuelen));
00778       rseg = pcb->unacked;
00779       if (rseg == NULL) {
00780         /* might happen if tcp_output fails in tcp_rexmit_rto()
00781            in which case the segment is on the unsent list */
00782         rseg = pcb->unsent;
00783         LWIP_ASSERT("no segment to free", rseg != NULL);
00784         pcb->unsent = rseg->next;
00785       } else {
00786         pcb->unacked = rseg->next;
00787       }
00788       tcp_seg_free(rseg);
00789 
00790       /* If there's nothing left to acknowledge, stop the retransmit
00791          timer, otherwise reset it to start again */
00792       if (pcb->unacked == NULL) {
00793         pcb->rtime = -1;
00794       } else {
00795         pcb->rtime = 0;
00796         pcb->nrtx = 0;
00797       }
00798 
00799       /* Call the user specified function to call when successfully
00800        * connected. */
00801       TCP_EVENT_CONNECTED(pcb, ERR_OK, err);
00802       if (err == ERR_ABRT) {
00803         return ERR_ABRT;
00804       }
00805       tcp_ack_now(pcb);
00806     }
00807     /* received ACK? possibly a half-open connection */
00808     else if (flags & TCP_ACK) {
00809       /* send a RST to bring the other side in a non-synchronized state. */
00810       tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(),
00811         ip_current_src_addr(), tcphdr->dest, tcphdr->src);
00812       /* Resend SYN immediately (don't wait for rto timeout) to establish
00813         connection faster, but do not send more SYNs than we otherwise would
00814         have, or we might get caught in a loop on loopback interfaces. */
00815       if (pcb->nrtx < TCP_SYNMAXRTX) {
00816         pcb->rtime = 0;
00817         tcp_rexmit_rto(pcb);
00818       }
00819     }
00820     break;
00821   case SYN_RCVD:
00822     if (flags & TCP_ACK) {
00823       /* expected ACK number? */
00824       if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) {
00825         pcb->state = ESTABLISHED;
00826         LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
00827 #if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG
00828 #if LWIP_CALLBACK_API
00829         LWIP_ASSERT("pcb->listener->accept != NULL",
00830           (pcb->listener == NULL) || (pcb->listener->accept != NULL));
00831 #endif
00832         if (pcb->listener == NULL) {
00833           /* listen pcb might be closed by now */
00834           err = ERR_VAL;
00835         } else
00836 #endif /* LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG */
00837         {
00838           tcp_backlog_accepted(pcb);
00839           /* Call the accept function. */
00840           TCP_EVENT_ACCEPT(pcb->listener, pcb, pcb->callback_arg, ERR_OK, err);
00841         }
00842         if (err != ERR_OK) {
00843           /* If the accept function returns with an error, we abort
00844            * the connection. */
00845           /* Already aborted? */
00846           if (err != ERR_ABRT) {
00847             tcp_abort(pcb);
00848           }
00849           return ERR_ABRT;
00850         }
00851         /* If there was any data contained within this ACK,
00852          * we'd better pass it on to the application as well. */
00853         tcp_receive(pcb);
00854 
00855         /* Prevent ACK for SYN to generate a sent event */
00856         if (recv_acked != 0) {
00857           recv_acked--;
00858         }
00859 
00860         pcb->cwnd = LWIP_TCP_CALC_INITIAL_CWND(pcb->mss);
00861         LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_process (SYN_RCVD): cwnd %"TCPWNDSIZE_F
00862                                      " ssthresh %"TCPWNDSIZE_F"\n",
00863                                      pcb->cwnd, pcb->ssthresh));
00864 
00865         if (recv_flags & TF_GOT_FIN) {
00866           tcp_ack_now(pcb);
00867           pcb->state = CLOSE_WAIT;
00868         }
00869       } else {
00870         /* incorrect ACK number, send RST */
00871         tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(),
00872           ip_current_src_addr(), tcphdr->dest, tcphdr->src);
00873       }
00874     } else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) {
00875       /* Looks like another copy of the SYN - retransmit our SYN-ACK */
00876       tcp_rexmit(pcb);
00877     }
00878     break;
00879   case CLOSE_WAIT:
00880     /* FALLTHROUGH */
00881   case ESTABLISHED:
00882     tcp_receive(pcb);
00883     if (recv_flags & TF_GOT_FIN) { /* passive close */
00884       tcp_ack_now(pcb);
00885       pcb->state = CLOSE_WAIT;
00886     }
00887     break;
00888   case FIN_WAIT_1:
00889     tcp_receive(pcb);
00890     if (recv_flags & TF_GOT_FIN) {
00891       if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt) &&
00892           pcb->unsent == NULL) {
00893         LWIP_DEBUGF(TCP_DEBUG,
00894           ("TCP connection closed: FIN_WAIT_1 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
00895         tcp_ack_now(pcb);
00896         tcp_pcb_purge(pcb);
00897         TCP_RMV_ACTIVE(pcb);
00898         pcb->state = TIME_WAIT;
00899         TCP_REG(&tcp_tw_pcbs, pcb);
00900       } else {
00901         tcp_ack_now(pcb);
00902         pcb->state = CLOSING;
00903       }
00904     } else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt) &&
00905                pcb->unsent == NULL) {
00906       pcb->state = FIN_WAIT_2;
00907     }
00908     break;
00909   case FIN_WAIT_2:
00910     tcp_receive(pcb);
00911     if (recv_flags & TF_GOT_FIN) {
00912       LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: FIN_WAIT_2 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
00913       tcp_ack_now(pcb);
00914       tcp_pcb_purge(pcb);
00915       TCP_RMV_ACTIVE(pcb);
00916       pcb->state = TIME_WAIT;
00917       TCP_REG(&tcp_tw_pcbs, pcb);
00918     }
00919     break;
00920   case CLOSING:
00921     tcp_receive(pcb);
00922     if ((flags & TCP_ACK) && ackno == pcb->snd_nxt && pcb->unsent == NULL) {
00923       LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
00924       tcp_pcb_purge(pcb);
00925       TCP_RMV_ACTIVE(pcb);
00926       pcb->state = TIME_WAIT;
00927       TCP_REG(&tcp_tw_pcbs, pcb);
00928     }
00929     break;
00930   case LAST_ACK:
00931     tcp_receive(pcb);
00932     if ((flags & TCP_ACK) && ackno == pcb->snd_nxt && pcb->unsent == NULL) {
00933       LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: LAST_ACK %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
00934       /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */
00935       recv_flags |= TF_CLOSED;
00936     }
00937     break;
00938   default:
00939     break;
00940   }
00941   return ERR_OK;
00942 }
00943 
00944 #if TCP_QUEUE_OOSEQ
00945 /**
00946  * Insert segment into the list (segments covered with new one will be deleted)
00947  *
00948  * Called from tcp_receive()
00949  */
00950 static void
00951 tcp_oos_insert_segment(struct tcp_seg *cseg, struct tcp_seg *next)
00952 {
00953   struct tcp_seg *old_seg;
00954 
00955   if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
00956     /* received segment overlaps all following segments */
00957     tcp_segs_free(next);
00958     next = NULL;
00959   } else {
00960     /* delete some following segments
00961        oos queue may have segments with FIN flag */
00962     while (next &&
00963            TCP_SEQ_GEQ((seqno + cseg->len),
00964                       (next->tcphdr->seqno + next->len))) {
00965       /* cseg with FIN already processed */
00966       if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) {
00967         TCPH_SET_FLAG(cseg->tcphdr, TCP_FIN);
00968       }
00969       old_seg = next;
00970       next = next->next;
00971       tcp_seg_free(old_seg);
00972     }
00973     if (next &&
00974         TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) {
00975       /* We need to trim the incoming segment. */
00976       cseg->len = (u16_t)(next->tcphdr->seqno - seqno);
00977       pbuf_realloc(cseg->p, cseg->len);
00978     }
00979   }
00980   cseg->next = next;
00981 }
00982 #endif /* TCP_QUEUE_OOSEQ */
00983 
00984 /**
00985  * Called by tcp_process. Checks if the given segment is an ACK for outstanding
00986  * data, and if so frees the memory of the buffered data. Next, it places the
00987  * segment on any of the receive queues (pcb->recved or pcb->ooseq). If the segment
00988  * is buffered, the pbuf is referenced by pbuf_ref so that it will not be freed until
00989  * it has been removed from the buffer.
00990  *
00991  * If the incoming segment constitutes an ACK for a segment that was used for RTT
00992  * estimation, the RTT is estimated here as well.
00993  *
00994  * Called from tcp_process().
00995  */
00996 static void
00997 tcp_receive(struct tcp_pcb *pcb)
00998 {
00999   struct tcp_seg *next;
01000 #if TCP_QUEUE_OOSEQ
01001   struct tcp_seg *prev, *cseg;
01002 #endif /* TCP_QUEUE_OOSEQ */
01003   s32_t off;
01004   s16_t m;
01005   u32_t right_wnd_edge;
01006   u16_t new_tot_len;
01007   int found_dupack = 0;
01008 #if TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS
01009   u32_t ooseq_blen;
01010   u16_t ooseq_qlen;
01011 #endif /* TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS */
01012 
01013   LWIP_ASSERT("tcp_receive: wrong state", pcb->state >= ESTABLISHED);
01014 
01015   if (flags & TCP_ACK) {
01016     right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2;
01017 
01018     /* Update window. */
01019     if (TCP_SEQ_LT(pcb->snd_wl1, seqno) ||
01020        (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) ||
01021        (pcb->snd_wl2 == ackno && (u32_t)SND_WND_SCALE(pcb, tcphdr->wnd) > pcb->snd_wnd)) {
01022       pcb->snd_wnd = SND_WND_SCALE(pcb, tcphdr->wnd);
01023       /* keep track of the biggest window announced by the remote host to calculate
01024          the maximum segment size */
01025       if (pcb->snd_wnd_max < pcb->snd_wnd) {
01026         pcb->snd_wnd_max = pcb->snd_wnd;
01027       }
01028       pcb->snd_wl1 = seqno;
01029       pcb->snd_wl2 = ackno;
01030       if (pcb->snd_wnd == 0) {
01031         if (pcb->persist_backoff == 0) {
01032           /* start persist timer */
01033           pcb->persist_cnt = 0;
01034           pcb->persist_backoff = 1;
01035         }
01036       } else if (pcb->persist_backoff > 0) {
01037         /* stop persist timer */
01038           pcb->persist_backoff = 0;
01039       }
01040       LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"TCPWNDSIZE_F"\n", pcb->snd_wnd));
01041 #if TCP_WND_DEBUG
01042     } else {
01043       if (pcb->snd_wnd != (tcpwnd_size_t)SND_WND_SCALE(pcb, tcphdr->wnd)) {
01044         LWIP_DEBUGF(TCP_WND_DEBUG,
01045                     ("tcp_receive: no window update lastack %"U32_F" ackno %"
01046                      U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n",
01047                      pcb->lastack, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2));
01048       }
01049 #endif /* TCP_WND_DEBUG */
01050     }
01051 
01052     /* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a
01053      * duplicate ack if:
01054      * 1) It doesn't ACK new data
01055      * 2) length of received packet is zero (i.e. no payload)
01056      * 3) the advertised window hasn't changed
01057      * 4) There is outstanding unacknowledged data (retransmission timer running)
01058      * 5) The ACK is == biggest ACK sequence number so far seen (snd_una)
01059      *
01060      * If it passes all five, should process as a dupack:
01061      * a) dupacks < 3: do nothing
01062      * b) dupacks == 3: fast retransmit
01063      * c) dupacks > 3: increase cwnd
01064      *
01065      * If it only passes 1-3, should reset dupack counter (and add to
01066      * stats, which we don't do in lwIP)
01067      *
01068      * If it only passes 1, should reset dupack counter
01069      *
01070      */
01071 
01072     /* Clause 1 */
01073     if (TCP_SEQ_LEQ(ackno, pcb->lastack)) {
01074       /* Clause 2 */
01075       if (tcplen == 0) {
01076         /* Clause 3 */
01077         if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge) {
01078           /* Clause 4 */
01079           if (pcb->rtime >= 0) {
01080             /* Clause 5 */
01081             if (pcb->lastack == ackno) {
01082               found_dupack = 1;
01083               if ((u8_t)(pcb->dupacks + 1) > pcb->dupacks) {
01084                 ++pcb->dupacks;
01085               }
01086               if (pcb->dupacks > 3) {
01087                 /* Inflate the congestion window, but not if it means that
01088                    the value overflows. */
01089                 if ((tcpwnd_size_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
01090                   pcb->cwnd += pcb->mss;
01091                 }
01092               } else if (pcb->dupacks == 3) {
01093                 /* Do fast retransmit */
01094                 tcp_rexmit_fast(pcb);
01095               }
01096             }
01097           }
01098         }
01099       }
01100       /* If Clause (1) or more is true, but not a duplicate ack, reset
01101        * count of consecutive duplicate acks */
01102       if (!found_dupack) {
01103         pcb->dupacks = 0;
01104       }
01105     } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) {
01106       /* We come here when the ACK acknowledges new data. */
01107 
01108       /* Reset the "IN Fast Retransmit" flag, since we are no longer
01109          in fast retransmit. Also reset the congestion window to the
01110          slow start threshold. */
01111       if (pcb->flags & TF_INFR) {
01112         pcb->flags &= ~TF_INFR;
01113         pcb->cwnd = pcb->ssthresh;
01114       }
01115 
01116       /* Reset the number of retransmissions. */
01117       pcb->nrtx = 0;
01118 
01119       /* Reset the retransmission time-out. */
01120       pcb->rto = (pcb->sa >> 3) + pcb->sv;
01121 
01122       /* Reset the fast retransmit variables. */
01123       pcb->dupacks = 0;
01124       pcb->lastack = ackno;
01125 
01126       /* Update the congestion control variables (cwnd and
01127          ssthresh). */
01128       if (pcb->state >= ESTABLISHED) {
01129         if (pcb->cwnd < pcb->ssthresh) {
01130           if ((tcpwnd_size_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
01131             pcb->cwnd += pcb->mss;
01132           }
01133           LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"TCPWNDSIZE_F"\n", pcb->cwnd));
01134         } else {
01135           tcpwnd_size_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd);
01136           if (new_cwnd > pcb->cwnd) {
01137             pcb->cwnd = new_cwnd;
01138           }
01139           LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"TCPWNDSIZE_F"\n", pcb->cwnd));
01140         }
01141       }
01142       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n",
01143                                     ackno,
01144                                     pcb->unacked != NULL?
01145                                     lwip_ntohl(pcb->unacked->tcphdr->seqno): 0,
01146                                     pcb->unacked != NULL?
01147                                     lwip_ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0));
01148 
01149       /* Remove segment from the unacknowledged list if the incoming
01150          ACK acknowledges them. */
01151       while (pcb->unacked != NULL &&
01152              TCP_SEQ_LEQ(lwip_ntohl(pcb->unacked->tcphdr->seqno) +
01153                          TCP_TCPLEN(pcb->unacked), ackno)) {
01154         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unacked\n",
01155                                       lwip_ntohl(pcb->unacked->tcphdr->seqno),
01156                                       lwip_ntohl(pcb->unacked->tcphdr->seqno) +
01157                                       TCP_TCPLEN(pcb->unacked)));
01158 
01159         next = pcb->unacked;
01160         pcb->unacked = pcb->unacked->next;
01161 
01162         LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"TCPWNDSIZE_F" ... ", (tcpwnd_size_t)pcb->snd_queuelen));
01163         LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
01164 
01165         pcb->snd_queuelen -= pbuf_clen(next->p);
01166         recv_acked += next->len;
01167         tcp_seg_free(next);
01168 
01169         LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"TCPWNDSIZE_F" (after freeing unacked)\n", (tcpwnd_size_t)pcb->snd_queuelen));
01170         if (pcb->snd_queuelen != 0) {
01171           LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL ||
01172                       pcb->unsent != NULL);
01173         }
01174       }
01175 
01176       /* If there's nothing left to acknowledge, stop the retransmit
01177          timer, otherwise reset it to start again */
01178       if (pcb->unacked == NULL) {
01179         pcb->rtime = -1;
01180       } else {
01181         pcb->rtime = 0;
01182       }
01183 
01184       pcb->polltmr = 0;
01185 
01186 #if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS
01187       if (ip_current_is_v6()) {
01188         /* Inform neighbor reachability of forward progress. */
01189         nd6_reachability_hint(ip6_current_src_addr());
01190       }
01191 #endif /* LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS*/
01192     } else {
01193       /* Out of sequence ACK, didn't really ack anything */
01194       tcp_send_empty_ack(pcb);
01195     }
01196 
01197     /* We go through the ->unsent list to see if any of the segments
01198        on the list are acknowledged by the ACK. This may seem
01199        strange since an "unsent" segment shouldn't be acked. The
01200        rationale is that lwIP puts all outstanding segments on the
01201        ->unsent list after a retransmission, so these segments may
01202        in fact have been sent once. */
01203     while (pcb->unsent != NULL &&
01204            TCP_SEQ_BETWEEN(ackno, lwip_ntohl(pcb->unsent->tcphdr->seqno) +
01205                            TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) {
01206       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n",
01207                                     lwip_ntohl(pcb->unsent->tcphdr->seqno), lwip_ntohl(pcb->unsent->tcphdr->seqno) +
01208                                     TCP_TCPLEN(pcb->unsent)));
01209 
01210       next = pcb->unsent;
01211       pcb->unsent = pcb->unsent->next;
01212 #if TCP_OVERSIZE
01213       if (pcb->unsent == NULL) {
01214         pcb->unsent_oversize = 0;
01215       }
01216 #endif /* TCP_OVERSIZE */
01217       LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"TCPWNDSIZE_F" ... ", (tcpwnd_size_t)pcb->snd_queuelen));
01218       LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
01219       /* Prevent ACK for FIN to generate a sent event */
01220       pcb->snd_queuelen -= pbuf_clen(next->p);
01221       recv_acked += next->len;
01222       tcp_seg_free(next);
01223       LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"TCPWNDSIZE_F" (after freeing unsent)\n", (tcpwnd_size_t)pcb->snd_queuelen));
01224       if (pcb->snd_queuelen != 0) {
01225         LWIP_ASSERT("tcp_receive: valid queue length",
01226           pcb->unacked != NULL || pcb->unsent != NULL);
01227       }
01228     }
01229     pcb->snd_buf += recv_acked;
01230     /* End of ACK for new data processing. */
01231 
01232     LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %"U32_F" rtseq %"U32_F" ackno %"U32_F"\n",
01233                                 pcb->rttest, pcb->rtseq, ackno));
01234 
01235     /* RTT estimation calculations. This is done by checking if the
01236        incoming segment acknowledges the segment we use to take a
01237        round-trip time measurement. */
01238     if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) {
01239       /* diff between this shouldn't exceed 32K since this are tcp timer ticks
01240          and a round-trip shouldn't be that long... */
01241       m = (s16_t)(tcp_ticks - pcb->rttest);
01242 
01243       LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %"U16_F" ticks (%"U16_F" msec).\n",
01244                                   m, (u16_t)(m * TCP_SLOW_INTERVAL)));
01245 
01246       /* This is taken directly from VJs original code in his paper */
01247       m = m - (pcb->sa >> 3);
01248       pcb->sa += m;
01249       if (m < 0) {
01250         m = -m;
01251       }
01252       m = m - (pcb->sv >> 2);
01253       pcb->sv += m;
01254       pcb->rto = (pcb->sa >> 3) + pcb->sv;
01255 
01256       LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %"U16_F" (%"U16_F" milliseconds)\n",
01257                                   pcb->rto, (u16_t)(pcb->rto * TCP_SLOW_INTERVAL)));
01258 
01259       pcb->rttest = 0;
01260     }
01261   }
01262 
01263   /* If the incoming segment contains data, we must process it
01264      further unless the pcb already received a FIN.
01265      (RFC 793, chapter 3.9, "SEGMENT ARRIVES" in states CLOSE-WAIT, CLOSING,
01266      LAST-ACK and TIME-WAIT: "Ignore the segment text.") */
01267   if ((tcplen > 0) && (pcb->state < CLOSE_WAIT)) {
01268     /* This code basically does three things:
01269 
01270     +) If the incoming segment contains data that is the next
01271     in-sequence data, this data is passed to the application. This
01272     might involve trimming the first edge of the data. The rcv_nxt
01273     variable and the advertised window are adjusted.
01274 
01275     +) If the incoming segment has data that is above the next
01276     sequence number expected (->rcv_nxt), the segment is placed on
01277     the ->ooseq queue. This is done by finding the appropriate
01278     place in the ->ooseq queue (which is ordered by sequence
01279     number) and trim the segment in both ends if needed. An
01280     immediate ACK is sent to indicate that we received an
01281     out-of-sequence segment.
01282 
01283     +) Finally, we check if the first segment on the ->ooseq queue
01284     now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If
01285     rcv_nxt > ooseq->seqno, we must trim the first edge of the
01286     segment on ->ooseq before we adjust rcv_nxt. The data in the
01287     segments that are now on sequence are chained onto the
01288     incoming segment so that we only need to call the application
01289     once.
01290     */
01291 
01292     /* First, we check if we must trim the first edge. We have to do
01293        this if the sequence number of the incoming segment is less
01294        than rcv_nxt, and the sequence number plus the length of the
01295        segment is larger than rcv_nxt. */
01296     /*    if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)) {
01297           if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/
01298     if (TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno + 1, seqno + tcplen - 1)) {
01299       /* Trimming the first edge is done by pushing the payload
01300          pointer in the pbuf downwards. This is somewhat tricky since
01301          we do not want to discard the full contents of the pbuf up to
01302          the new starting point of the data since we have to keep the
01303          TCP header which is present in the first pbuf in the chain.
01304 
01305          What is done is really quite a nasty hack: the first pbuf in
01306          the pbuf chain is pointed to by inseg.p. Since we need to be
01307          able to deallocate the whole pbuf, we cannot change this
01308          inseg.p pointer to point to any of the later pbufs in the
01309          chain. Instead, we point the ->payload pointer in the first
01310          pbuf to data in one of the later pbufs. We also set the
01311          inseg.data pointer to point to the right place. This way, the
01312          ->p pointer will still point to the first pbuf, but the
01313          ->p->payload pointer will point to data in another pbuf.
01314 
01315          After we are done with adjusting the pbuf pointers we must
01316          adjust the ->data pointer in the seg and the segment
01317          length.*/
01318 
01319       struct pbuf *p = inseg.p;
01320       off = pcb->rcv_nxt - seqno;
01321       LWIP_ASSERT("inseg.p != NULL", inseg.p);
01322       LWIP_ASSERT("insane offset!", (off < 0x7fff));
01323       if (inseg.p->len < off) {
01324         LWIP_ASSERT("pbuf too short!", (((s32_t)inseg.p->tot_len) >= off));
01325         new_tot_len = (u16_t)(inseg.p->tot_len - off);
01326         while (p->len < off) {
01327           off -= p->len;
01328           /* KJM following line changed (with addition of new_tot_len var)
01329              to fix bug #9076
01330              inseg.p->tot_len -= p->len; */
01331           p->tot_len = new_tot_len;
01332           p->len = 0;
01333           p = p->next;
01334         }
01335         if (pbuf_header(p, (s16_t)-off)) {
01336           /* Do we need to cope with this failing?  Assert for now */
01337           LWIP_ASSERT("pbuf_header failed", 0);
01338         }
01339       } else {
01340         if (pbuf_header(inseg.p, (s16_t)-off)) {
01341           /* Do we need to cope with this failing?  Assert for now */
01342           LWIP_ASSERT("pbuf_header failed", 0);
01343         }
01344       }
01345       inseg.len -= (u16_t)(pcb->rcv_nxt - seqno);
01346       inseg.tcphdr->seqno = seqno = pcb->rcv_nxt;
01347     }
01348     else {
01349       if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)) {
01350         /* the whole segment is < rcv_nxt */
01351         /* must be a duplicate of a packet that has already been correctly handled */
01352 
01353         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno));
01354         tcp_ack_now(pcb);
01355       }
01356     }
01357 
01358     /* The sequence number must be within the window (above rcv_nxt
01359        and below rcv_nxt + rcv_wnd) in order to be further
01360        processed. */
01361     if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
01362                         pcb->rcv_nxt + pcb->rcv_wnd - 1)) {
01363       if (pcb->rcv_nxt == seqno) {
01364         /* The incoming segment is the next in sequence. We check if
01365            we have to trim the end of the segment and update rcv_nxt
01366            and pass the data to the application. */
01367         tcplen = TCP_TCPLEN(&inseg);
01368 
01369         if (tcplen > pcb->rcv_wnd) {
01370           LWIP_DEBUGF(TCP_INPUT_DEBUG,
01371                       ("tcp_receive: other end overran receive window"
01372                        "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n",
01373                        seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd));
01374           if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
01375             /* Must remove the FIN from the header as we're trimming
01376              * that byte of sequence-space from the packet */
01377             TCPH_FLAGS_SET(inseg.tcphdr, TCPH_FLAGS(inseg.tcphdr) & ~(unsigned int)TCP_FIN);
01378           }
01379           /* Adjust length of segment to fit in the window. */
01380           TCPWND_CHECK16(pcb->rcv_wnd);
01381           inseg.len = (u16_t)pcb->rcv_wnd;
01382           if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
01383             inseg.len -= 1;
01384           }
01385           pbuf_realloc(inseg.p, inseg.len);
01386           tcplen = TCP_TCPLEN(&inseg);
01387           LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n",
01388                       (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd));
01389         }
01390 #if TCP_QUEUE_OOSEQ
01391         /* Received in-sequence data, adjust ooseq data if:
01392            - FIN has been received or
01393            - inseq overlaps with ooseq */
01394         if (pcb->ooseq != NULL) {
01395           if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
01396             LWIP_DEBUGF(TCP_INPUT_DEBUG,
01397                         ("tcp_receive: received in-order FIN, binning ooseq queue\n"));
01398             /* Received in-order FIN means anything that was received
01399              * out of order must now have been received in-order, so
01400              * bin the ooseq queue */
01401             while (pcb->ooseq != NULL) {
01402               struct tcp_seg *old_ooseq = pcb->ooseq;
01403               pcb->ooseq = pcb->ooseq->next;
01404               tcp_seg_free(old_ooseq);
01405             }
01406           } else {
01407             next = pcb->ooseq;
01408             /* Remove all segments on ooseq that are covered by inseg already.
01409              * FIN is copied from ooseq to inseg if present. */
01410             while (next &&
01411                    TCP_SEQ_GEQ(seqno + tcplen,
01412                                next->tcphdr->seqno + next->len)) {
01413               /* inseg cannot have FIN here (already processed above) */
01414               if ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0 &&
01415                   (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) {
01416                 TCPH_SET_FLAG(inseg.tcphdr, TCP_FIN);
01417                 tcplen = TCP_TCPLEN(&inseg);
01418               }
01419               prev = next;
01420               next = next->next;
01421               tcp_seg_free(prev);
01422             }
01423             /* Now trim right side of inseg if it overlaps with the first
01424              * segment on ooseq */
01425             if (next &&
01426                 TCP_SEQ_GT(seqno + tcplen,
01427                            next->tcphdr->seqno)) {
01428               /* inseg cannot have FIN here (already processed above) */
01429               inseg.len = (u16_t)(next->tcphdr->seqno - seqno);
01430               if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
01431                 inseg.len -= 1;
01432               }
01433               pbuf_realloc(inseg.p, inseg.len);
01434               tcplen = TCP_TCPLEN(&inseg);
01435               LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n",
01436                           (seqno + tcplen) == next->tcphdr->seqno);
01437             }
01438             pcb->ooseq = next;
01439           }
01440         }
01441 #endif /* TCP_QUEUE_OOSEQ */
01442 
01443         pcb->rcv_nxt = seqno + tcplen;
01444 
01445         /* Update the receiver's (our) window. */
01446         LWIP_ASSERT("tcp_receive: tcplen > rcv_wnd\n", pcb->rcv_wnd >= tcplen);
01447         pcb->rcv_wnd -= tcplen;
01448 
01449         tcp_update_rcv_ann_wnd(pcb);
01450 
01451         /* If there is data in the segment, we make preparations to
01452            pass this up to the application. The ->recv_data variable
01453            is used for holding the pbuf that goes to the
01454            application. The code for reassembling out-of-sequence data
01455            chains its data on this pbuf as well.
01456 
01457            If the segment was a FIN, we set the TF_GOT_FIN flag that will
01458            be used to indicate to the application that the remote side has
01459            closed its end of the connection. */
01460         if (inseg.p->tot_len > 0) {
01461           recv_data = inseg.p;
01462           /* Since this pbuf now is the responsibility of the
01463              application, we delete our reference to it so that we won't
01464              (mistakingly) deallocate it. */
01465           inseg.p = NULL;
01466         }
01467         if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
01468           LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n"));
01469           recv_flags |= TF_GOT_FIN;
01470         }
01471 
01472 #if TCP_QUEUE_OOSEQ
01473         /* We now check if we have segments on the ->ooseq queue that
01474            are now in sequence. */
01475         while (pcb->ooseq != NULL &&
01476                pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) {
01477 
01478           cseg = pcb->ooseq;
01479           seqno = pcb->ooseq->tcphdr->seqno;
01480 
01481           pcb->rcv_nxt += TCP_TCPLEN(cseg);
01482           LWIP_ASSERT("tcp_receive: ooseq tcplen > rcv_wnd\n",
01483                       pcb->rcv_wnd >= TCP_TCPLEN(cseg));
01484           pcb->rcv_wnd -= TCP_TCPLEN(cseg);
01485 
01486           tcp_update_rcv_ann_wnd(pcb);
01487 
01488           if (cseg->p->tot_len > 0) {
01489             /* Chain this pbuf onto the pbuf that we will pass to
01490                the application. */
01491             /* With window scaling, this can overflow recv_data->tot_len, but
01492                that's not a problem since we explicitly fix that before passing
01493                recv_data to the application. */
01494             if (recv_data) {
01495               pbuf_cat(recv_data, cseg->p);
01496             } else {
01497               recv_data = cseg->p;
01498             }
01499             cseg->p = NULL;
01500           }
01501           if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
01502             LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n"));
01503             recv_flags |= TF_GOT_FIN;
01504             if (pcb->state == ESTABLISHED) { /* force passive close or we can move to active close */
01505               pcb->state = CLOSE_WAIT;
01506             }
01507           }
01508 
01509           pcb->ooseq = cseg->next;
01510           tcp_seg_free(cseg);
01511         }
01512 #endif /* TCP_QUEUE_OOSEQ */
01513 
01514 
01515         /* Acknowledge the segment(s). */
01516         tcp_ack(pcb);
01517 
01518 #if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS
01519         if (ip_current_is_v6()) {
01520           /* Inform neighbor reachability of forward progress. */
01521           nd6_reachability_hint(ip6_current_src_addr());
01522         }
01523 #endif /* LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS*/
01524 
01525       } else {
01526         /* We get here if the incoming segment is out-of-sequence. */
01527         tcp_send_empty_ack(pcb);
01528 #if TCP_QUEUE_OOSEQ
01529         /* We queue the segment on the ->ooseq queue. */
01530         if (pcb->ooseq == NULL) {
01531           pcb->ooseq = tcp_seg_copy(&inseg);
01532         } else {
01533           /* If the queue is not empty, we walk through the queue and
01534              try to find a place where the sequence number of the
01535              incoming segment is between the sequence numbers of the
01536              previous and the next segment on the ->ooseq queue. That is
01537              the place where we put the incoming segment. If needed, we
01538              trim the second edges of the previous and the incoming
01539              segment so that it will fit into the sequence.
01540 
01541              If the incoming segment has the same sequence number as a
01542              segment on the ->ooseq queue, we discard the segment that
01543              contains less data. */
01544 
01545           prev = NULL;
01546           for (next = pcb->ooseq; next != NULL; next = next->next) {
01547             if (seqno == next->tcphdr->seqno) {
01548               /* The sequence number of the incoming segment is the
01549                  same as the sequence number of the segment on
01550                  ->ooseq. We check the lengths to see which one to
01551                  discard. */
01552               if (inseg.len > next->len) {
01553                 /* The incoming segment is larger than the old
01554                    segment. We replace some segments with the new
01555                    one. */
01556                 cseg = tcp_seg_copy(&inseg);
01557                 if (cseg != NULL) {
01558                   if (prev != NULL) {
01559                     prev->next = cseg;
01560                   } else {
01561                     pcb->ooseq = cseg;
01562                   }
01563                   tcp_oos_insert_segment(cseg, next);
01564                 }
01565                 break;
01566               } else {
01567                 /* Either the lengths are the same or the incoming
01568                    segment was smaller than the old one; in either
01569                    case, we ditch the incoming segment. */
01570                 break;
01571               }
01572             } else {
01573               if (prev == NULL) {
01574                 if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {
01575                   /* The sequence number of the incoming segment is lower
01576                      than the sequence number of the first segment on the
01577                      queue. We put the incoming segment first on the
01578                      queue. */
01579                   cseg = tcp_seg_copy(&inseg);
01580                   if (cseg != NULL) {
01581                     pcb->ooseq = cseg;
01582                     tcp_oos_insert_segment(cseg, next);
01583                   }
01584                   break;
01585                 }
01586               } else {
01587                 /*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) &&
01588                   TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/
01589                 if (TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)) {
01590                   /* The sequence number of the incoming segment is in
01591                      between the sequence numbers of the previous and
01592                      the next segment on ->ooseq. We trim trim the previous
01593                      segment, delete next segments that included in received segment
01594                      and trim received, if needed. */
01595                   cseg = tcp_seg_copy(&inseg);
01596                   if (cseg != NULL) {
01597                     if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) {
01598                       /* We need to trim the prev segment. */
01599                       prev->len = (u16_t)(seqno - prev->tcphdr->seqno);
01600                       pbuf_realloc(prev->p, prev->len);
01601                     }
01602                     prev->next = cseg;
01603                     tcp_oos_insert_segment(cseg, next);
01604                   }
01605                   break;
01606                 }
01607               }
01608               /* If the "next" segment is the last segment on the
01609                  ooseq queue, we add the incoming segment to the end
01610                  of the list. */
01611               if (next->next == NULL &&
01612                   TCP_SEQ_GT(seqno, next->tcphdr->seqno)) {
01613                 if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) {
01614                   /* segment "next" already contains all data */
01615                   break;
01616                 }
01617                 next->next = tcp_seg_copy(&inseg);
01618                 if (next->next != NULL) {
01619                   if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) {
01620                     /* We need to trim the last segment. */
01621                     next->len = (u16_t)(seqno - next->tcphdr->seqno);
01622                     pbuf_realloc(next->p, next->len);
01623                   }
01624                   /* check if the remote side overruns our receive window */
01625                   if (TCP_SEQ_GT((u32_t)tcplen + seqno, pcb->rcv_nxt + (u32_t)pcb->rcv_wnd)) {
01626                     LWIP_DEBUGF(TCP_INPUT_DEBUG,
01627                                 ("tcp_receive: other end overran receive window"
01628                                  "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n",
01629                                  seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd));
01630                     if (TCPH_FLAGS(next->next->tcphdr) & TCP_FIN) {
01631                       /* Must remove the FIN from the header as we're trimming
01632                        * that byte of sequence-space from the packet */
01633                       TCPH_FLAGS_SET(next->next->tcphdr, TCPH_FLAGS(next->next->tcphdr) & ~TCP_FIN);
01634                     }
01635                     /* Adjust length of segment to fit in the window. */
01636                     next->next->len = (u16_t)(pcb->rcv_nxt + pcb->rcv_wnd - seqno);
01637                     pbuf_realloc(next->next->p, next->next->len);
01638                     tcplen = TCP_TCPLEN(next->next);
01639                     LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n",
01640                                 (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd));
01641                   }
01642                 }
01643                 break;
01644               }
01645             }
01646             prev = next;
01647           }
01648         }
01649 #if TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS
01650         /* Check that the data on ooseq doesn't exceed one of the limits
01651            and throw away everything above that limit. */
01652         ooseq_blen = 0;
01653         ooseq_qlen = 0;
01654         prev = NULL;
01655         for (next = pcb->ooseq; next != NULL; prev = next, next = next->next) {
01656           struct pbuf *p = next->p;
01657           ooseq_blen += p->tot_len;
01658           ooseq_qlen += pbuf_clen(p);
01659           if ((ooseq_blen > TCP_OOSEQ_MAX_BYTES) ||
01660               (ooseq_qlen > TCP_OOSEQ_MAX_PBUFS)) {
01661              /* too much ooseq data, dump this and everything after it */
01662              tcp_segs_free(next);
01663              if (prev == NULL) {
01664                /* first ooseq segment is too much, dump the whole queue */
01665                pcb->ooseq = NULL;
01666              } else {
01667                /* just dump 'next' and everything after it */
01668                prev->next = NULL;
01669              }
01670              break;
01671           }
01672         }
01673 #endif /* TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS */
01674 #endif /* TCP_QUEUE_OOSEQ */
01675       }
01676     } else {
01677       /* The incoming segment is not within the window. */
01678       tcp_send_empty_ack(pcb);
01679     }
01680   } else {
01681     /* Segments with length 0 is taken care of here. Segments that
01682        fall out of the window are ACKed. */
01683     if (!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd - 1)) {
01684       tcp_ack_now(pcb);
01685     }
01686   }
01687 }
01688 
01689 static u8_t
01690 tcp_getoptbyte(void)
01691 {
01692   if ((tcphdr_opt2 == NULL) || (tcp_optidx < tcphdr_opt1len)) {
01693     u8_t* opts = (u8_t *)tcphdr + TCP_HLEN;
01694     return opts[tcp_optidx++];
01695   } else {
01696     u8_t idx = (u8_t)(tcp_optidx++ - tcphdr_opt1len);
01697     return tcphdr_opt2[idx];
01698   }
01699 }
01700 
01701 /**
01702  * Parses the options contained in the incoming segment.
01703  *
01704  * Called from tcp_listen_input() and tcp_process().
01705  * Currently, only the MSS option is supported!
01706  *
01707  * @param pcb the tcp_pcb for which a segment arrived
01708  */
01709 static void
01710 tcp_parseopt(struct tcp_pcb *pcb)
01711 {
01712   u8_t data;
01713   u16_t mss;
01714 #if LWIP_TCP_TIMESTAMPS
01715   u32_t tsval;
01716 #endif
01717 
01718   /* Parse the TCP MSS option, if present. */
01719   if (tcphdr_optlen != 0) {
01720     for (tcp_optidx = 0; tcp_optidx < tcphdr_optlen; ) {
01721       u8_t opt = tcp_getoptbyte();
01722       switch (opt) {
01723       case LWIP_TCP_OPT_EOL:
01724         /* End of options. */
01725         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: EOL\n"));
01726         return;
01727       case LWIP_TCP_OPT_NOP:
01728         /* NOP option. */
01729         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: NOP\n"));
01730         break;
01731       case LWIP_TCP_OPT_MSS:
01732         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: MSS\n"));
01733         if (tcp_getoptbyte() != LWIP_TCP_OPT_LEN_MSS || (tcp_optidx - 2 + LWIP_TCP_OPT_LEN_MSS) > tcphdr_optlen) {
01734           /* Bad length */
01735           LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
01736           return;
01737         }
01738         /* An MSS option with the right option length. */
01739         mss = (tcp_getoptbyte() << 8);
01740         mss |= tcp_getoptbyte();
01741         /* Limit the mss to the configured TCP_MSS and prevent division by zero */
01742         pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss;
01743         break;
01744 #if LWIP_WND_SCALE
01745       case LWIP_TCP_OPT_WS:
01746         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: WND_SCALE\n"));
01747         if (tcp_getoptbyte() != LWIP_TCP_OPT_LEN_WS || (tcp_optidx - 2 + LWIP_TCP_OPT_LEN_WS) > tcphdr_optlen) {
01748           /* Bad length */
01749           LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
01750           return;
01751         }
01752         /* If syn was received with wnd scale option,
01753            activate wnd scale opt, but only if this is not a retransmission */
01754         if ((flags & TCP_SYN) && !(pcb->flags & TF_WND_SCALE)) {
01755           /* An WND_SCALE option with the right option length. */
01756           data = tcp_getoptbyte();
01757           pcb->snd_scale = data;
01758           if (pcb->snd_scale > 14U) {
01759             pcb->snd_scale = 14U;
01760           }
01761           pcb->rcv_scale = TCP_RCV_SCALE;
01762           pcb->flags |= TF_WND_SCALE;
01763           /* window scaling is enabled, we can use the full receive window */
01764           LWIP_ASSERT("window not at default value", pcb->rcv_wnd == TCPWND_MIN16(TCP_WND));
01765           LWIP_ASSERT("window not at default value", pcb->rcv_ann_wnd == TCPWND_MIN16(TCP_WND));
01766           pcb->rcv_wnd = pcb->rcv_ann_wnd = TCP_WND;
01767         }
01768         break;
01769 #endif
01770 #if LWIP_TCP_TIMESTAMPS
01771       case LWIP_TCP_OPT_TS:
01772         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: TS\n"));
01773         if (tcp_getoptbyte() != LWIP_TCP_OPT_LEN_TS || (tcp_optidx - 2 + LWIP_TCP_OPT_LEN_TS) > tcphdr_optlen) {
01774           /* Bad length */
01775           LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
01776           return;
01777         }
01778         /* TCP timestamp option with valid length */
01779         tsval = tcp_getoptbyte();
01780         tsval |= (tcp_getoptbyte() << 8);
01781         tsval |= (tcp_getoptbyte() << 16);
01782         tsval |= (tcp_getoptbyte() << 24);
01783         if (flags & TCP_SYN) {
01784           pcb->ts_recent = lwip_ntohl(tsval);
01785           /* Enable sending timestamps in every segment now that we know
01786              the remote host supports it. */
01787           pcb->flags |= TF_TIMESTAMP;
01788         } else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno+tcplen)) {
01789           pcb->ts_recent = lwip_ntohl(tsval);
01790         }
01791         /* Advance to next option (6 bytes already read) */
01792         tcp_optidx += LWIP_TCP_OPT_LEN_TS - 6;
01793         break;
01794 #endif
01795       default:
01796         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: other\n"));
01797         data = tcp_getoptbyte();
01798         if (data < 2) {
01799           LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
01800           /* If the length field is zero, the options are malformed
01801              and we don't process them further. */
01802           return;
01803         }
01804         /* All other options have a length field, so that we easily
01805            can skip past them. */
01806         tcp_optidx += data - 2;
01807       }
01808     }
01809   }
01810 }
01811 
01812 void
01813 tcp_trigger_input_pcb_close(void)
01814 {
01815   recv_flags |= TF_CLOSED;
01816 }
01817 
01818 #endif /* LWIP_TCP */