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 = (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 = (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 = (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 = (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 = (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 = (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 = (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 = (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   err_t rc;
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->rcv_ann_right_edge = npcb->rcv_nxt;
00442     npcb->snd_wnd = tcphdr->wnd;
00443     npcb->ssthresh = npcb->snd_wnd;
00444     npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */
00445     npcb->callback_arg = pcb->callback_arg;
00446 #if LWIP_CALLBACK_API
00447     npcb->accept = pcb->accept;
00448 #endif /* LWIP_CALLBACK_API */
00449     /* inherit socket options */
00450     npcb->so_options = pcb->so_options & (SOF_DEBUG|SOF_DONTROUTE|SOF_KEEPALIVE|SOF_OOBINLINE|SOF_LINGER);
00451     /* Register the new PCB so that we can begin receiving segments
00452        for it. */
00453     TCP_REG(&tcp_active_pcbs, npcb);
00454 
00455     /* Parse any options in the SYN. */
00456     tcp_parseopt(npcb);
00457 #if TCP_CALCULATE_EFF_SEND_MSS
00458     npcb->mss = tcp_eff_send_mss(npcb->mss, &(npcb->remote_ip));
00459 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
00460 
00461     snmp_inc_tcppassiveopens();
00462 
00463     /* Send a SYN|ACK together with the MSS option. */
00464     rc = tcp_enqueue(npcb, NULL, 0, TCP_SYN | TCP_ACK, 0, TF_SEG_OPTS_MSS
00465 #if LWIP_TCP_TIMESTAMPS
00466       /* and maybe include the TIMESTAMP option */
00467      | (npcb->flags & TF_TIMESTAMP ? TF_SEG_OPTS_TS : 0)
00468 #endif
00469       );
00470     if (rc != ERR_OK) {
00471       tcp_abandon(npcb, 0);
00472       return rc;
00473     }
00474     return tcp_output(npcb);
00475   }
00476   return ERR_OK;
00477 }
00478 
00479 /**
00480  * Called by tcp_input() when a segment arrives for a connection in
00481  * TIME_WAIT.
00482  *
00483  * @param pcb the tcp_pcb for which a segment arrived
00484  *
00485  * @note the segment which arrived is saved in global variables, therefore only the pcb
00486  *       involved is passed as a parameter to this function
00487  */
00488 static err_t
00489 tcp_timewait_input(struct tcp_pcb *pcb)
00490 {
00491   if (TCP_SEQ_GT(seqno + tcplen, pcb->rcv_nxt)) {
00492     pcb->rcv_nxt = seqno + tcplen;
00493   }
00494   if (tcplen > 0) {
00495     tcp_ack_now(pcb);
00496   }
00497   return tcp_output(pcb);
00498 }
00499 
00500 /**
00501  * Implements the TCP state machine. Called by tcp_input. In some
00502  * states tcp_receive() is called to receive data. The tcp_seg
00503  * argument will be freed by the caller (tcp_input()) unless the
00504  * recv_data pointer in the pcb is set.
00505  *
00506  * @param pcb the tcp_pcb for which a segment arrived
00507  *
00508  * @note the segment which arrived is saved in global variables, therefore only the pcb
00509  *       involved is passed as a parameter to this function
00510  */
00511 static err_t
00512 tcp_process(struct tcp_pcb *pcb)
00513 {
00514   struct tcp_seg *rseg;
00515   u8_t acceptable = 0;
00516   err_t err;
00517   u8_t accepted_inseq;
00518 
00519   err = ERR_OK;
00520 
00521   /* Process incoming RST segments. */
00522   if (flags & TCP_RST) {
00523     /* First, determine if the reset is acceptable. */
00524     if (pcb->state == SYN_SENT) {
00525       if (ackno == pcb->snd_nxt) {
00526         acceptable = 1;
00527       }
00528     } else {
00529       if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, 
00530                           pcb->rcv_nxt+pcb->rcv_wnd)) {
00531         acceptable = 1;
00532       }
00533     }
00534 
00535     if (acceptable) {
00536       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n"));
00537       LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED);
00538       recv_flags = TF_RESET;
00539       pcb->flags &= ~TF_ACK_DELAY;
00540       return ERR_RST;
00541     } else {
00542       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n",
00543        seqno, pcb->rcv_nxt));
00544       LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n",
00545        seqno, pcb->rcv_nxt));
00546       return ERR_OK;
00547     }
00548   }
00549 
00550   if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) { 
00551     /* Cope with new connection attempt after remote end crashed */
00552     tcp_ack_now(pcb);
00553     return ERR_OK;
00554   }
00555   
00556   /* Update the PCB (in)activity timer. */
00557   pcb->tmr = tcp_ticks;
00558   pcb->keep_cnt_sent = 0;
00559 
00560   tcp_parseopt(pcb);
00561 
00562   /* Do different things depending on the TCP state. */
00563   switch (pcb->state) {
00564   case SYN_SENT:
00565     LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno,
00566      pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno)));
00567     /* received SYN ACK with expected sequence number? */
00568     if ((flags & TCP_ACK) && (flags & TCP_SYN)
00569         && ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) {
00570       pcb->snd_buf++;
00571       pcb->rcv_nxt = seqno + 1;
00572       pcb->rcv_ann_right_edge = pcb->rcv_nxt;
00573       pcb->lastack = ackno;
00574       pcb->snd_wnd = tcphdr->wnd;
00575       pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */
00576       pcb->state = ESTABLISHED;
00577 
00578 #if TCP_CALCULATE_EFF_SEND_MSS
00579       pcb->mss = tcp_eff_send_mss(pcb->mss, &(pcb->remote_ip));
00580 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
00581 
00582       /* Set ssthresh again after changing pcb->mss (already set in tcp_connect
00583        * but for the default value of pcb->mss) */
00584       pcb->ssthresh = pcb->mss * 10;
00585 
00586       pcb->cwnd = ((pcb->cwnd == 1) ? (pcb->mss * 2) : pcb->mss);
00587       LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0));
00588       --pcb->snd_queuelen;
00589       LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"U16_F"\n", (u16_t)pcb->snd_queuelen));
00590       rseg = pcb->unacked;
00591       pcb->unacked = rseg->next;
00592 
00593       /* If there's nothing left to acknowledge, stop the retransmit
00594          timer, otherwise reset it to start again */
00595       if(pcb->unacked == NULL)
00596         pcb->rtime = -1;
00597       else {
00598         pcb->rtime = 0;
00599         pcb->nrtx = 0;
00600       }
00601 
00602       tcp_seg_free(rseg);
00603 
00604       /* Call the user specified function to call when sucessfully
00605        * connected. */
00606       TCP_EVENT_CONNECTED(pcb, ERR_OK, err);
00607       tcp_ack_now(pcb);
00608     }
00609     /* received ACK? possibly a half-open connection */
00610     else if (flags & TCP_ACK) {
00611       /* send a RST to bring the other side in a non-synchronized state. */
00612       struct ip_addr iphdrdest;
00613       iphdrdest.addr = iphdr->dest.addr;
00614       struct ip_addr iphdrsrc;
00615       iphdrsrc.addr = iphdr->src.addr;
00616       tcp_rst(ackno, seqno + tcplen, &(iphdrdest), &(iphdrsrc),
00617         tcphdr->dest, tcphdr->src);
00618     }
00619     break;
00620   case SYN_RCVD:
00621     if (flags & TCP_ACK) {
00622       /* expected ACK number? */
00623       if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) {
00624         u16_t old_cwnd;
00625         pcb->state = ESTABLISHED;
00626         LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
00627 #if LWIP_CALLBACK_API
00628         LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL);
00629 #endif
00630         /* Call the accept function. */
00631         TCP_EVENT_ACCEPT(pcb, ERR_OK, err);
00632         if (err != ERR_OK) {
00633           /* If the accept function returns with an error, we abort
00634            * the connection. */
00635           tcp_abort(pcb);
00636           return ERR_ABRT;
00637         }
00638         old_cwnd = pcb->cwnd;
00639         /* If there was any data contained within this ACK,
00640          * we'd better pass it on to the application as well. */
00641         accepted_inseq = tcp_receive(pcb);
00642 
00643         pcb->cwnd = ((old_cwnd == 1) ? (pcb->mss * 2) : pcb->mss);
00644 
00645         if ((flags & TCP_FIN) && accepted_inseq) {
00646           tcp_ack_now(pcb);
00647           pcb->state = CLOSE_WAIT;
00648         }
00649       }
00650       /* incorrect ACK number */
00651       else {
00652         /* send RST */
00653         struct ip_addr iphdrdest;
00654         iphdrdest.addr = iphdr->dest.addr;
00655         struct ip_addr iphdrsrc;
00656         iphdrsrc.addr = iphdr->src.addr;
00657         tcp_rst(ackno, seqno + tcplen, &(iphdrdest), &(iphdrsrc),
00658                 tcphdr->dest, tcphdr->src);
00659       }
00660     } else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) {
00661       /* Looks like another copy of the SYN - retransmit our SYN-ACK */
00662       tcp_rexmit(pcb);
00663     }
00664     break;
00665   case CLOSE_WAIT:
00666     /* FALLTHROUGH */
00667   case ESTABLISHED:
00668     accepted_inseq = tcp_receive(pcb);
00669     if ((flags & TCP_FIN) && accepted_inseq) { /* passive close */
00670       tcp_ack_now(pcb);
00671       pcb->state = CLOSE_WAIT;
00672     }
00673     break;
00674   case FIN_WAIT_1:
00675     tcp_receive(pcb);
00676     if (flags & TCP_FIN) {
00677       if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
00678         LWIP_DEBUGF(TCP_DEBUG,
00679           ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
00680         tcp_ack_now(pcb);
00681         tcp_pcb_purge(pcb);
00682         TCP_RMV(&tcp_active_pcbs, pcb);
00683         pcb->state = TIME_WAIT;
00684         TCP_REG(&tcp_tw_pcbs, pcb);
00685       } else {
00686         tcp_ack_now(pcb);
00687         pcb->state = CLOSING;
00688       }
00689     } else if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
00690       pcb->state = FIN_WAIT_2;
00691     }
00692     break;
00693   case FIN_WAIT_2:
00694     tcp_receive(pcb);
00695     if (flags & TCP_FIN) {
00696       LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
00697       tcp_ack_now(pcb);
00698       tcp_pcb_purge(pcb);
00699       TCP_RMV(&tcp_active_pcbs, pcb);
00700       pcb->state = TIME_WAIT;
00701       TCP_REG(&tcp_tw_pcbs, pcb);
00702     }
00703     break;
00704   case CLOSING:
00705     tcp_receive(pcb);
00706     if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
00707       LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
00708       tcp_ack_now(pcb);
00709       tcp_pcb_purge(pcb);
00710       TCP_RMV(&tcp_active_pcbs, pcb);
00711       pcb->state = TIME_WAIT;
00712       TCP_REG(&tcp_tw_pcbs, pcb);
00713     }
00714     break;
00715   case LAST_ACK:
00716     tcp_receive(pcb);
00717     if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
00718       LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
00719       /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */
00720       recv_flags = TF_CLOSED;
00721     }
00722     break;
00723   default:
00724     break;
00725   }
00726   return ERR_OK;
00727 }
00728 
00729 /**
00730  * Called by tcp_process. Checks if the given segment is an ACK for outstanding
00731  * data, and if so frees the memory of the buffered data. Next, is places the
00732  * segment on any of the receive queues (pcb->recved or pcb->ooseq). If the segment
00733  * is buffered, the pbuf is referenced by pbuf_ref so that it will not be freed until
00734  * i it has been removed from the buffer.
00735  *
00736  * If the incoming segment constitutes an ACK for a segment that was used for RTT
00737  * estimation, the RTT is estimated here as well.
00738  *
00739  * Called from tcp_process().
00740  *
00741  * @return 1 if the incoming segment is the next in sequence, 0 if not
00742  */
00743 static u8_t
00744 tcp_receive(struct tcp_pcb *pcb)
00745 {
00746   struct tcp_seg *next;
00747 #if TCP_QUEUE_OOSEQ
00748   struct tcp_seg *prev, *cseg;
00749 #endif
00750   struct pbuf *p;
00751   s32_t off;
00752   s16_t m;
00753   u32_t right_wnd_edge;
00754   u16_t new_tot_len;
00755   u8_t accepted_inseq = 0;
00756 
00757   if (flags & TCP_ACK) {
00758     right_wnd_edge = pcb->snd_wnd + pcb->snd_wl1;
00759 
00760     /* Update window. */
00761     if (TCP_SEQ_LT(pcb->snd_wl1, seqno) ||
00762        (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) ||
00763        (pcb->snd_wl2 == ackno && tcphdr->wnd > pcb->snd_wnd)) {
00764       pcb->snd_wnd = tcphdr->wnd;
00765       pcb->snd_wl1 = seqno;
00766       pcb->snd_wl2 = ackno;
00767       if (pcb->snd_wnd > 0 && pcb->persist_backoff > 0) {
00768           pcb->persist_backoff = 0;
00769       }
00770       LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"U16_F"\n", pcb->snd_wnd));
00771 #if TCP_WND_DEBUG
00772     } else {
00773       if (pcb->snd_wnd != tcphdr->wnd) {
00774         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",
00775                                pcb->lastack, pcb->snd_max, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2));
00776       }
00777 #endif /* TCP_WND_DEBUG */
00778     }
00779 
00780     if (pcb->lastack == ackno) {
00781       pcb->acked = 0;
00782 
00783       if (pcb->snd_wl1 + pcb->snd_wnd == right_wnd_edge){
00784         ++pcb->dupacks;
00785         if (pcb->dupacks >= 3 && pcb->unacked != NULL) {
00786           if (!(pcb->flags & TF_INFR)) {
00787             /* This is fast retransmit. Retransmit the first unacked segment. */
00788             LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupacks %"U16_F" (%"U32_F"), fast retransmit %"U32_F"\n",
00789                                        (u16_t)pcb->dupacks, pcb->lastack,
00790                                        ntohl(pcb->unacked->tcphdr->seqno)));
00791             tcp_rexmit(pcb);
00792             /* Set ssthresh to max (FlightSize / 2, 2*SMSS) */
00793             /*pcb->ssthresh = LWIP_MAX((pcb->snd_max -
00794                                       pcb->lastack) / 2,
00795                                       2 * pcb->mss);*/
00796             /* Set ssthresh to half of the minimum of the current cwnd and the advertised window */
00797             if (pcb->cwnd > pcb->snd_wnd)
00798               pcb->ssthresh = pcb->snd_wnd / 2;
00799             else
00800               pcb->ssthresh = pcb->cwnd / 2;
00801 
00802             /* The minimum value for ssthresh should be 2 MSS */
00803             if (pcb->ssthresh < 2*pcb->mss) {
00804               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));
00805               pcb->ssthresh = 2*pcb->mss;
00806             }
00807 
00808             pcb->cwnd = pcb->ssthresh + 3 * pcb->mss;
00809             pcb->flags |= TF_INFR;
00810           } else {
00811             /* Inflate the congestion window, but not if it means that
00812                the value overflows. */
00813             if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
00814               pcb->cwnd += pcb->mss;
00815             }
00816           }
00817         }
00818       } else {
00819         LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupack averted %"U32_F" %"U32_F"\n",
00820                                    pcb->snd_wl1 + pcb->snd_wnd, right_wnd_edge));
00821       }
00822     } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_max)){
00823       /* We come here when the ACK acknowledges new data. */
00824       
00825       /* Reset the "IN Fast Retransmit" flag, since we are no longer
00826          in fast retransmit. Also reset the congestion window to the
00827          slow start threshold. */
00828       if (pcb->flags & TF_INFR) {
00829         pcb->flags &= ~TF_INFR;
00830         pcb->cwnd = pcb->ssthresh;
00831       }
00832 
00833       /* Reset the number of retransmissions. */
00834       pcb->nrtx = 0;
00835 
00836       /* Reset the retransmission time-out. */
00837       pcb->rto = (pcb->sa >> 3) + pcb->sv;
00838 
00839       /* Update the send buffer space. Diff between the two can never exceed 64K? */
00840       pcb->acked = (u16_t)(ackno - pcb->lastack);
00841 
00842       pcb->snd_buf += pcb->acked;
00843 
00844       /* Reset the fast retransmit variables. */
00845       pcb->dupacks = 0;
00846       pcb->lastack = ackno;
00847 
00848       /* Update the congestion control variables (cwnd and
00849          ssthresh). */
00850       if (pcb->state >= ESTABLISHED) {
00851         if (pcb->cwnd < pcb->ssthresh) {
00852           if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
00853             pcb->cwnd += pcb->mss;
00854           }
00855           LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"U16_F"\n", pcb->cwnd));
00856         } else {
00857           u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd);
00858           if (new_cwnd > pcb->cwnd) {
00859             pcb->cwnd = new_cwnd;
00860           }
00861           LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"U16_F"\n", pcb->cwnd));
00862         }
00863       }
00864       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n",
00865                                     ackno,
00866                                     pcb->unacked != NULL?
00867                                     ntohl(pcb->unacked->tcphdr->seqno): 0,
00868                                     pcb->unacked != NULL?
00869                                     ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0));
00870 
00871       /* Remove segment from the unacknowledged list if the incoming
00872          ACK acknowlegdes them. */
00873       while (pcb->unacked != NULL &&
00874              TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) +
00875                          TCP_TCPLEN(pcb->unacked), ackno)) {
00876         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unacked\n",
00877                                       ntohl(pcb->unacked->tcphdr->seqno),
00878                                       ntohl(pcb->unacked->tcphdr->seqno) +
00879                                       TCP_TCPLEN(pcb->unacked)));
00880 
00881         next = pcb->unacked;
00882         pcb->unacked = pcb->unacked->next;
00883 
00884         LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen));
00885         LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
00886         pcb->snd_queuelen -= pbuf_clen(next->p);
00887         tcp_seg_free(next);
00888 
00889         LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unacked)\n", (u16_t)pcb->snd_queuelen));
00890         if (pcb->snd_queuelen != 0) {
00891           LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL ||
00892                       pcb->unsent != NULL);
00893         }
00894       }
00895 
00896       /* If there's nothing left to acknowledge, stop the retransmit
00897          timer, otherwise reset it to start again */
00898       if(pcb->unacked == NULL)
00899         pcb->rtime = -1;
00900       else
00901         pcb->rtime = 0;
00902 
00903       pcb->polltmr = 0;
00904     } else {
00905       /* Fix bug bug #21582: out of sequence ACK, didn't really ack anything */
00906       pcb->acked = 0;
00907     }
00908 
00909     /* We go through the ->unsent list to see if any of the segments
00910        on the list are acknowledged by the ACK. This may seem
00911        strange since an "unsent" segment shouldn't be acked. The
00912        rationale is that lwIP puts all outstanding segments on the
00913        ->unsent list after a retransmission, so these segments may
00914        in fact have been sent once. */
00915     while (pcb->unsent != NULL &&
00916            /*TCP_SEQ_LEQ(ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent), ackno) &&
00917              TCP_SEQ_LEQ(ackno, pcb->snd_max)*/
00918            TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent), pcb->snd_max)
00919            ) {
00920       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n",
00921                                     ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) +
00922                                     TCP_TCPLEN(pcb->unsent)));
00923 
00924       next = pcb->unsent;
00925       pcb->unsent = pcb->unsent->next;
00926       LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen));
00927       LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
00928       pcb->snd_queuelen -= pbuf_clen(next->p);
00929       tcp_seg_free(next);
00930       LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unsent)\n", (u16_t)pcb->snd_queuelen));
00931       if (pcb->snd_queuelen != 0) {
00932         LWIP_ASSERT("tcp_receive: valid queue length",
00933           pcb->unacked != NULL || pcb->unsent != NULL);
00934       }
00935 
00936       if (pcb->unsent != NULL) {
00937         pcb->snd_nxt = htonl(pcb->unsent->tcphdr->seqno);
00938       }
00939     }
00940     /* End of ACK for new data processing. */
00941 
00942     LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %"U32_F" rtseq %"U32_F" ackno %"U32_F"\n",
00943                                 pcb->rttest, pcb->rtseq, ackno));
00944 
00945     /* RTT estimation calculations. This is done by checking if the
00946        incoming segment acknowledges the segment we use to take a
00947        round-trip time measurement. */
00948     if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) {
00949       /* diff between this shouldn't exceed 32K since this are tcp timer ticks
00950          and a round-trip shouldn't be that long... */
00951       m = (s16_t)(tcp_ticks - pcb->rttest);
00952 
00953       LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %"U16_F" ticks (%"U16_F" msec).\n",
00954                                   m, m * TCP_SLOW_INTERVAL));
00955 
00956       /* This is taken directly from VJs original code in his paper */
00957       m = m - (pcb->sa >> 3);
00958       pcb->sa += m;
00959       if (m < 0) {
00960         m = -m;
00961       }
00962       m = m - (pcb->sv >> 2);
00963       pcb->sv += m;
00964       pcb->rto = (pcb->sa >> 3) + pcb->sv;
00965 
00966       LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %"U16_F" (%"U16_F" milliseconds)\n",
00967                                   pcb->rto, pcb->rto * TCP_SLOW_INTERVAL));
00968 
00969       pcb->rttest = 0;
00970     }
00971   }
00972 
00973   /* If the incoming segment contains data, we must process it
00974      further. */
00975   if (tcplen > 0) {
00976     /* This code basically does three things:
00977 
00978     +) If the incoming segment contains data that is the next
00979     in-sequence data, this data is passed to the application. This
00980     might involve trimming the first edge of the data. The rcv_nxt
00981     variable and the advertised window are adjusted.
00982 
00983     +) If the incoming segment has data that is above the next
00984     sequence number expected (->rcv_nxt), the segment is placed on
00985     the ->ooseq queue. This is done by finding the appropriate
00986     place in the ->ooseq queue (which is ordered by sequence
00987     number) and trim the segment in both ends if needed. An
00988     immediate ACK is sent to indicate that we received an
00989     out-of-sequence segment.
00990 
00991     +) Finally, we check if the first segment on the ->ooseq queue
00992     now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If
00993     rcv_nxt > ooseq->seqno, we must trim the first edge of the
00994     segment on ->ooseq before we adjust rcv_nxt. The data in the
00995     segments that are now on sequence are chained onto the
00996     incoming segment so that we only need to call the application
00997     once.
00998     */
00999 
01000     /* First, we check if we must trim the first edge. We have to do
01001        this if the sequence number of the incoming segment is less
01002        than rcv_nxt, and the sequence number plus the length of the
01003        segment is larger than rcv_nxt. */
01004     /*    if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){
01005           if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/
01006     if (TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno + 1, seqno + tcplen - 1)){
01007       /* Trimming the first edge is done by pushing the payload
01008          pointer in the pbuf downwards. This is somewhat tricky since
01009          we do not want to discard the full contents of the pbuf up to
01010          the new starting point of the data since we have to keep the
01011          TCP header which is present in the first pbuf in the chain.
01012 
01013          What is done is really quite a nasty hack: the first pbuf in
01014          the pbuf chain is pointed to by inseg.p. Since we need to be
01015          able to deallocate the whole pbuf, we cannot change this
01016          inseg.p pointer to point to any of the later pbufs in the
01017          chain. Instead, we point the ->payload pointer in the first
01018          pbuf to data in one of the later pbufs. We also set the
01019          inseg.data pointer to point to the right place. This way, the
01020          ->p pointer will still point to the first pbuf, but the
01021          ->p->payload pointer will point to data in another pbuf.
01022 
01023          After we are done with adjusting the pbuf pointers we must
01024          adjust the ->data pointer in the seg and the segment
01025          length.*/
01026 
01027       off = pcb->rcv_nxt - seqno;
01028       p = inseg.p;
01029       LWIP_ASSERT("inseg.p != NULL", inseg.p);
01030       LWIP_ASSERT("insane offset!", (off < 0x7fff));
01031       if (inseg.p->len < off) {
01032         LWIP_ASSERT("pbuf too short!", (((s32_t)inseg.p->tot_len) >= off));
01033         new_tot_len = (u16_t)(inseg.p->tot_len - off);
01034         while (p->len < off) {
01035           off -= p->len;
01036           /* KJM following line changed (with addition of new_tot_len var)
01037              to fix bug #9076
01038              inseg.p->tot_len -= p->len; */
01039           p->tot_len = new_tot_len;
01040           p->len = 0;
01041           p = p->next;
01042         }
01043         if(pbuf_header(p, (s16_t)-off)) {
01044           /* Do we need to cope with this failing?  Assert for now */
01045           LWIP_ASSERT("pbuf_header failed", 0);
01046         }
01047       } else {
01048         if(pbuf_header(inseg.p, (s16_t)-off)) {
01049           /* Do we need to cope with this failing?  Assert for now */
01050           LWIP_ASSERT("pbuf_header failed", 0);
01051         }
01052       }
01053       /* KJM following line changed to use p->payload rather than inseg->p->payload
01054          to fix bug #9076 */
01055       inseg.dataptr = p->payload;
01056       inseg.len -= (u16_t)(pcb->rcv_nxt - seqno);
01057       inseg.tcphdr->seqno = seqno = pcb->rcv_nxt;
01058     }
01059     else {
01060       if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){
01061         /* the whole segment is < rcv_nxt */
01062         /* must be a duplicate of a packet that has already been correctly handled */
01063 
01064         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno));
01065         tcp_ack_now(pcb);
01066       }
01067     }
01068 
01069     /* The sequence number must be within the window (above rcv_nxt
01070        and below rcv_nxt + rcv_wnd) in order to be further
01071        processed. */
01072     if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, 
01073                         pcb->rcv_nxt + pcb->rcv_wnd - 1)){
01074       if (pcb->rcv_nxt == seqno) {
01075         accepted_inseq = 1; 
01076         /* The incoming segment is the next in sequence. We check if
01077            we have to trim the end of the segment and update rcv_nxt
01078            and pass the data to the application. */
01079 #if TCP_QUEUE_OOSEQ
01080         if (pcb->ooseq != NULL &&
01081                 TCP_SEQ_LEQ(pcb->ooseq->tcphdr->seqno, seqno + inseg.len)) {
01082           if (pcb->ooseq->len > 0) {
01083             /* We have to trim the second edge of the incoming
01084                segment. */
01085             inseg.len = (u16_t)(pcb->ooseq->tcphdr->seqno - seqno);
01086             pbuf_realloc(inseg.p, inseg.len);
01087           } else {
01088             /* does the ooseq segment contain only flags that are in inseg also? */
01089             if ((TCPH_FLAGS(inseg.tcphdr) & (TCP_FIN|TCP_SYN)) ==
01090                 (TCPH_FLAGS(pcb->ooseq->tcphdr) & (TCP_FIN|TCP_SYN))) {
01091               struct tcp_seg *old_ooseq = pcb->ooseq;
01092               pcb->ooseq = pcb->ooseq->next;
01093               memp_free(MEMP_TCP_SEG, old_ooseq);
01094             }
01095           }
01096         }
01097 #endif /* TCP_QUEUE_OOSEQ */
01098 
01099         tcplen = TCP_TCPLEN(&inseg);
01100 
01101         /* First received FIN will be ACKed +1, on any successive (duplicate)
01102          * FINs we are already in CLOSE_WAIT and have already done +1.
01103          */
01104         if (pcb->state != CLOSE_WAIT) {
01105           pcb->rcv_nxt += tcplen;
01106         }
01107 
01108         /* Update the receiver's (our) window. */
01109         if (pcb->rcv_wnd < tcplen) {
01110           pcb->rcv_wnd = 0;
01111         } else {
01112           pcb->rcv_wnd -= tcplen;
01113         }
01114 
01115         tcp_update_rcv_ann_wnd(pcb);
01116 
01117         /* If there is data in the segment, we make preparations to
01118            pass this up to the application. The ->recv_data variable
01119            is used for holding the pbuf that goes to the
01120            application. The code for reassembling out-of-sequence data
01121            chains its data on this pbuf as well.
01122 
01123            If the segment was a FIN, we set the TF_GOT_FIN flag that will
01124            be used to indicate to the application that the remote side has
01125            closed its end of the connection. */
01126         if (inseg.p->tot_len > 0) {
01127           recv_data = inseg.p;
01128           /* Since this pbuf now is the responsibility of the
01129              application, we delete our reference to it so that we won't
01130              (mistakingly) deallocate it. */
01131           inseg.p = NULL;
01132         }
01133         if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
01134           LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n"));
01135           recv_flags = TF_GOT_FIN;
01136         }
01137 
01138 #if TCP_QUEUE_OOSEQ
01139         /* We now check if we have segments on the ->ooseq queue that
01140            is now in sequence. */
01141         while (pcb->ooseq != NULL &&
01142                pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) {
01143 
01144           cseg = pcb->ooseq;
01145           seqno = pcb->ooseq->tcphdr->seqno;
01146 
01147           pcb->rcv_nxt += TCP_TCPLEN(cseg);
01148           if (pcb->rcv_wnd < TCP_TCPLEN(cseg)) {
01149             pcb->rcv_wnd = 0;
01150           } else {
01151             pcb->rcv_wnd -= TCP_TCPLEN(cseg);
01152           }
01153 
01154           tcp_update_rcv_ann_wnd(pcb);
01155 
01156           if (cseg->p->tot_len > 0) {
01157             /* Chain this pbuf onto the pbuf that we will pass to
01158                the application. */
01159             if (recv_data) {
01160               pbuf_cat(recv_data, cseg->p);
01161             } else {
01162               recv_data = cseg->p;
01163             }
01164             cseg->p = NULL;
01165           }
01166           if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
01167             LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n"));
01168             recv_flags = TF_GOT_FIN;
01169             if (pcb->state == ESTABLISHED) { /* force passive close or we can move to active close */
01170               pcb->state = CLOSE_WAIT;
01171             } 
01172           }
01173 
01174 
01175           pcb->ooseq = cseg->next;
01176           tcp_seg_free(cseg);
01177         }
01178 #endif /* TCP_QUEUE_OOSEQ */
01179 
01180 
01181         /* Acknowledge the segment(s). */
01182         tcp_ack(pcb);
01183 
01184       } else {
01185         /* We get here if the incoming segment is out-of-sequence. */
01186         tcp_ack_now(pcb);
01187 #if TCP_QUEUE_OOSEQ
01188         /* We queue the segment on the ->ooseq queue. */
01189         if (pcb->ooseq == NULL) {
01190           pcb->ooseq = tcp_seg_copy(&inseg);
01191         } else {
01192           /* If the queue is not empty, we walk through the queue and
01193              try to find a place where the sequence number of the
01194              incoming segment is between the sequence numbers of the
01195              previous and the next segment on the ->ooseq queue. That is
01196              the place where we put the incoming segment. If needed, we
01197              trim the second edges of the previous and the incoming
01198              segment so that it will fit into the sequence.
01199 
01200              If the incoming segment has the same sequence number as a
01201              segment on the ->ooseq queue, we discard the segment that
01202              contains less data. */
01203 
01204           prev = NULL;
01205           for(next = pcb->ooseq; next != NULL; next = next->next) {
01206             if (seqno == next->tcphdr->seqno) {
01207               /* The sequence number of the incoming segment is the
01208                  same as the sequence number of the segment on
01209                  ->ooseq. We check the lengths to see which one to
01210                  discard. */
01211               if (inseg.len > next->len) {
01212                 /* The incoming segment is larger than the old
01213                    segment. We replace the old segment with the new
01214                    one. */
01215                 cseg = tcp_seg_copy(&inseg);
01216                 if (cseg != NULL) {
01217                   cseg->next = next->next;
01218                   if (prev != NULL) {
01219                     prev->next = cseg;
01220                   } else {
01221                     pcb->ooseq = cseg;
01222                   }
01223                   tcp_seg_free(next);
01224                   if (cseg->next != NULL) {
01225                     next = cseg->next;
01226                     if (TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) {
01227                       /* We need to trim the incoming segment. */
01228                       cseg->len = (u16_t)(next->tcphdr->seqno - seqno);
01229                       pbuf_realloc(cseg->p, cseg->len);
01230                     }
01231                   }
01232                 }
01233                 break;
01234               } else {
01235                 /* Either the lenghts are the same or the incoming
01236                    segment was smaller than the old one; in either
01237                    case, we ditch the incoming segment. */
01238                 break;
01239               }
01240             } else {
01241               if (prev == NULL) {
01242                 if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {
01243                   /* The sequence number of the incoming segment is lower
01244                      than the sequence number of the first segment on the
01245                      queue. We put the incoming segment first on the
01246                      queue. */
01247 
01248                   if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) {
01249                     /* We need to trim the incoming segment. */
01250                     inseg.len = (u16_t)(next->tcphdr->seqno - seqno);
01251                     pbuf_realloc(inseg.p, inseg.len);
01252                   }
01253                   cseg = tcp_seg_copy(&inseg);
01254                   if (cseg != NULL) {
01255                     cseg->next = next;
01256                     pcb->ooseq = cseg;
01257                   }
01258                   break;
01259                 }
01260               } else 
01261                 /*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) &&
01262                   TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/
01263                 if(TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)){
01264                 /* The sequence number of the incoming segment is in
01265                    between the sequence numbers of the previous and
01266                    the next segment on ->ooseq. We trim and insert the
01267                    incoming segment and trim the previous segment, if
01268                    needed. */
01269                 if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) {
01270                   /* We need to trim the incoming segment. */
01271                   inseg.len = (u16_t)(next->tcphdr->seqno - seqno);
01272                   pbuf_realloc(inseg.p, inseg.len);
01273                 }
01274 
01275                 cseg = tcp_seg_copy(&inseg);
01276                 if (cseg != NULL) {
01277                   cseg->next = next;
01278                   prev->next = cseg;
01279                   if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) {
01280                     /* We need to trim the prev segment. */
01281                     prev->len = (u16_t)(seqno - prev->tcphdr->seqno);
01282                     pbuf_realloc(prev->p, prev->len);
01283                   }
01284                 }
01285                 break;
01286               }
01287               /* If the "next" segment is the last segment on the
01288                  ooseq queue, we add the incoming segment to the end
01289                  of the list. */
01290               if (next->next == NULL &&
01291                   TCP_SEQ_GT(seqno, next->tcphdr->seqno)) {
01292                 next->next = tcp_seg_copy(&inseg);
01293                 if (next->next != NULL) {
01294                   if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) {
01295                     /* We need to trim the last segment. */
01296                     next->len = (u16_t)(seqno - next->tcphdr->seqno);
01297                     pbuf_realloc(next->p, next->len);
01298                   }
01299                 }
01300                 break;
01301               }
01302             }
01303             prev = next;
01304           }
01305         }
01306 #endif /* TCP_QUEUE_OOSEQ */
01307 
01308       }
01309     } else {
01310       tcp_ack_now(pcb);
01311     }
01312   } else {
01313     /* Segments with length 0 is taken care of here. Segments that
01314        fall out of the window are ACKed. */
01315     /*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) ||
01316       TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/
01317     if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){
01318       tcp_ack_now(pcb);
01319     }
01320   }
01321   return accepted_inseq;
01322 }
01323 
01324 /**
01325  * Parses the options contained in the incoming segment. 
01326  *
01327  * Called from tcp_listen_input() and tcp_process().
01328  * Currently, only the MSS option is supported!
01329  *
01330  * @param pcb the tcp_pcb for which a segment arrived
01331  */
01332 static void
01333 tcp_parseopt(struct tcp_pcb *pcb)
01334 {
01335   u16_t c, max_c;
01336   u16_t mss;
01337   u8_t *opts, opt;
01338 #if LWIP_TCP_TIMESTAMPS
01339   u32_t tsval;
01340 #endif
01341 
01342   opts = (u8_t *)tcphdr + TCP_HLEN;
01343 
01344   /* Parse the TCP MSS option, if present. */
01345   if(TCPH_HDRLEN(tcphdr) > 0x5) {
01346     max_c = (TCPH_HDRLEN(tcphdr) - 5) << 2;
01347     for (c = 0; c < max_c; ) {
01348       opt = opts[c];
01349       switch (opt) {
01350       case 0x00:
01351         /* End of options. */
01352         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: EOL\n"));
01353         return;
01354       case 0x01:
01355         /* NOP option. */
01356         ++c;
01357         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: NOP\n"));
01358         break;
01359       case 0x02:
01360         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: MSS\n"));
01361         if (opts[c + 1] != 0x04 || c + 0x04 > max_c) {
01362           /* Bad length */
01363           LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
01364           return;
01365         }
01366         /* An MSS option with the right option length. */
01367         mss = (opts[c + 2] << 8) | opts[c + 3];
01368         /* Limit the mss to the configured TCP_MSS and prevent division by zero */
01369         pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss;
01370         /* Advance to next option */
01371         c += 0x04;
01372         break;
01373 #if LWIP_TCP_TIMESTAMPS
01374       case 0x08:
01375         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: TS\n"));
01376         if (opts[c + 1] != 0x0A || c + 0x0A > max_c) {
01377           /* Bad length */
01378           LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
01379           return;
01380         }
01381         /* TCP timestamp option with valid length */
01382         tsval = (opts[c+2]) | (opts[c+3] << 8) | 
01383           (opts[c+4] << 16) | (opts[c+5] << 24);
01384         if (flags & TCP_SYN) {
01385           pcb->ts_recent = ntohl(tsval);
01386           pcb->flags |= TF_TIMESTAMP;
01387         } else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno+tcplen)) {
01388           pcb->ts_recent = ntohl(tsval);
01389         }
01390         /* Advance to next option */
01391         c += 0x0A;
01392         break;
01393 #endif
01394       default:
01395         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: other\n"));
01396         if (opts[c + 1] == 0) {
01397           LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
01398           /* If the length field is zero, the options are malformed
01399              and we don't process them further. */
01400           return;
01401         }
01402         /* All other options have a length field, so that we easily
01403            can skip past them. */
01404         c += opts[c + 1];
01405       }
01406     }
01407   }
01408 }
01409 
01410 #endif /* LWIP_TCP */