Ethernet for Nucleo and Disco board STM32F746 works with gcc and arm. IAC is untested

Dependencies:   mbed-rtos

Dependents:   IMU_ethernet

Fork of F7_Ethernet by Dieter Graef

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