A version of LWIP, provided for backwards compatibility.

Dependents:   AA_DemoBoard DemoBoard HelloServerDemo DemoBoard_RangeIndicator ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers tcp_in.c Source File

tcp_in.c

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