SAMV71 Xplained Ultra Software Package 1.5

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