Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

tcp_in.c

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

Generated on Wed Jan 14 12:58:57 2004 for RTL-lwIP-0.4 by doxygen 1.3.4