]> git.sur5r.net Git - freertos/blob - Demo/lwIP_Demo_Rowley_ARM7/lwip-1.1.0/src/core/tcp_in.c
First version under SVN is V4.0.1
[freertos] / Demo / lwIP_Demo_Rowley_ARM7 / lwip-1.1.0 / src / core / tcp_in.c
1 /**
2  * @file
3  *
4  * Transmission Control Protocol, incoming traffic
5  *
6  * The input processing functions of TCP.
7  *
8  * These functions are generally called in the order (ip_input() ->) tcp_input() ->
9  * tcp_process() -> tcp_receive() (-> application).
10  * 
11  */
12
13 /*
14  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
15  * All rights reserved.
16  *
17  * Redistribution and use in source and binary forms, with or without modification,
18  * are permitted provided that the following conditions are met:
19  *
20  * 1. Redistributions of source code must retain the above copyright notice,
21  *    this list of conditions and the following disclaimer.
22  * 2. Redistributions in binary form must reproduce the above copyright notice,
23  *    this list of conditions and the following disclaimer in the documentation
24  *    and/or other materials provided with the distribution.
25  * 3. The name of the author may not be used to endorse or promote products
26  *    derived from this software without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
29  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
31  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
33  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
36  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
37  * OF SUCH DAMAGE.
38  *
39  * This file is part of the lwIP TCP/IP stack.
40  *
41  * Author: Adam Dunkels <adam@sics.se>
42  *
43  */
44
45 #include "lwip/def.h"
46 #include "lwip/opt.h"
47
48 #include "lwip/ip_addr.h"
49 #include "lwip/netif.h"
50 #include "lwip/mem.h"
51 #include "lwip/memp.h"
52
53 #include "lwip/inet.h"
54 #include "lwip/tcp.h"
55
56 #include "lwip/stats.h"
57
58 #include "arch/perf.h"
59 #if LWIP_TCP
60 /* These variables are global to all functions involved in the input
61    processing of TCP segments. They are set by the tcp_input()
62    function. */
63 static struct tcp_seg inseg;
64 static struct tcp_hdr *tcphdr;
65 static struct ip_hdr *iphdr;
66 static u32_t seqno, ackno;
67 static u8_t flags;
68 static u16_t tcplen;
69
70 static u8_t recv_flags;
71 static struct pbuf *recv_data;
72
73 struct tcp_pcb *tcp_input_pcb;
74
75 /* Forward declarations. */
76 static err_t tcp_process(struct tcp_pcb *pcb);
77 static void tcp_receive(struct tcp_pcb *pcb);
78 static void tcp_parseopt(struct tcp_pcb *pcb);
79
80 static err_t tcp_listen_input(struct tcp_pcb_listen *pcb);
81 static err_t tcp_timewait_input(struct tcp_pcb *pcb);
82
83
84 /* tcp_input:
85  *
86  * The initial input processing of TCP. It verifies the TCP header, demultiplexes
87  * the segment between the PCBs and passes it on to tcp_process(), which implements
88  * the TCP finite state machine. This function is called by the IP layer (in
89  * ip_input()).
90  */
91
92 void
93 tcp_input(struct pbuf *p, struct netif *inp)
94 {
95   struct tcp_pcb *pcb, *prev;
96   struct tcp_pcb_listen *lpcb;
97   u8_t hdrlen;
98   err_t err;
99
100 #if SO_REUSE
101   struct tcp_pcb *pcb_temp;
102   int reuse = 0;
103   int reuse_port = 0;
104 #endif /* SO_REUSE */
105
106   PERF_START;
107
108   TCP_STATS_INC(tcp.recv);
109
110   iphdr = p->payload;
111   tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4);
112
113 #if TCP_INPUT_DEBUG
114   tcp_debug_print(tcphdr);
115 #endif
116
117   /* remove header from payload */
118   if (pbuf_header(p, -((s16_t)(IPH_HL(iphdr) * 4))) || (p->tot_len < sizeof(struct tcp_hdr))) {
119     /* drop short packets */
120     LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%u bytes) discarded\n", p->tot_len));
121     TCP_STATS_INC(tcp.lenerr);
122     TCP_STATS_INC(tcp.drop);
123     pbuf_free(p);
124     return;
125   }
126
127   /* Don't even process incoming broadcasts/multicasts. */
128   if (ip_addr_isbroadcast(&(iphdr->dest), inp) ||
129       ip_addr_ismulticast(&(iphdr->dest))) {
130     pbuf_free(p);
131     return;
132   }
133
134 #if CHECKSUM_CHECK_TCP
135   /* Verify TCP checksum. */
136   if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
137       (struct ip_addr *)&(iphdr->dest),
138       IP_PROTO_TCP, p->tot_len) != 0) {
139       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04x\n",
140         inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src), (struct ip_addr *)&(iphdr->dest),
141       IP_PROTO_TCP, p->tot_len)));
142 #if TCP_DEBUG
143     tcp_debug_print(tcphdr);
144 #endif /* TCP_DEBUG */
145     TCP_STATS_INC(tcp.chkerr);
146     TCP_STATS_INC(tcp.drop);
147
148     pbuf_free(p);
149     return;
150   }
151 #endif
152
153   /* Move the payload pointer in the pbuf so that it points to the
154      TCP data instead of the TCP header. */
155   hdrlen = TCPH_HDRLEN(tcphdr);
156   pbuf_header(p, -(hdrlen * 4));
157
158   /* Convert fields in TCP header to host byte order. */
159   tcphdr->src = ntohs(tcphdr->src);
160   tcphdr->dest = ntohs(tcphdr->dest);
161   seqno = tcphdr->seqno = ntohl(tcphdr->seqno);
162   ackno = tcphdr->ackno = ntohl(tcphdr->ackno);
163   tcphdr->wnd = ntohs(tcphdr->wnd);
164
165   flags = TCPH_FLAGS(tcphdr) & TCP_FLAGS;
166   tcplen = p->tot_len + ((flags & TCP_FIN || flags & TCP_SYN)? 1: 0);
167
168   /* Demultiplex an incoming segment. First, we check if it is destined
169      for an active connection. */
170   prev = NULL;
171
172 #if SO_REUSE
173   pcb_temp = tcp_active_pcbs;
174   
175  again_1:
176   
177   /* Iterate through the TCP pcb list for a fully matching pcb */
178   for(pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
179 #else  /* SO_REUSE */
180   for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
181 #endif  /* SO_REUSE */
182     LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED);
183     LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
184     LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
185     if (pcb->remote_port == tcphdr->src &&
186        pcb->local_port == tcphdr->dest &&
187        ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
188        ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
189
190 #if SO_REUSE
191       if(pcb->so_options & SOF_REUSEPORT) {
192         if(reuse) {
193           /* We processed one PCB already */
194           LWIP_DEBUGF(TCP_INPUT_DEBUG,("tcp_input: second or later PCB and SOF_REUSEPORT set.\n"));
195         } else {
196           /* First PCB with this address */
197           LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: first PCB and SOF_REUSEPORT set.\n"));
198           reuse = 1;
199         }
200         
201         reuse_port = 1; 
202         p->ref++;
203         
204         /* We want to search on next socket after receiving */
205         pcb_temp = pcb->next;
206         
207         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: reference counter on PBUF set to %i\n", p->ref));
208       } else  {
209         if(reuse) {
210           /* We processed one PCB already */
211           LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
212         }
213       }
214 #endif /* SO_REUSE */
215
216       /* Move this PCB to the front of the list so that subsequent
217    lookups will be faster (we exploit locality in TCP segment
218    arrivals). */
219       LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb);
220       if (prev != NULL) {
221   prev->next = pcb->next;
222   pcb->next = tcp_active_pcbs;
223   tcp_active_pcbs = pcb;
224       }
225       LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb);
226       break;
227     }
228     prev = pcb;
229   }
230
231   if (pcb == NULL) {
232     /* If it did not go to an active connection, we check the connections
233        in the TIME-WAIT state. */
234
235     for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
236       LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
237       if (pcb->remote_port == tcphdr->src &&
238    pcb->local_port == tcphdr->dest &&
239    ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
240          ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
241   /* We don't really care enough to move this PCB to the front
242      of the list since we are not very likely to receive that
243      many segments for connections in TIME-WAIT. */
244   LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n"));
245   tcp_timewait_input(pcb);
246   pbuf_free(p);
247   return;
248       }
249     }
250
251   /* Finally, if we still did not get a match, we check all PCBs that
252      are LISTENing for incoming connections. */
253     prev = NULL;
254     for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
255       if ((ip_addr_isany(&(lpcb->local_ip)) ||
256     ip_addr_cmp(&(lpcb->local_ip), &(iphdr->dest))) &&
257    lpcb->local_port == tcphdr->dest) {
258   /* Move this PCB to the front of the list so that subsequent
259      lookups will be faster (we exploit locality in TCP segment
260      arrivals). */
261   if (prev != NULL) {
262     ((struct tcp_pcb_listen *)prev)->next = lpcb->next;
263           /* our successor is the remainder of the listening list */
264     lpcb->next = tcp_listen_pcbs.listen_pcbs;
265           /* put this listening pcb at the head of the listening list */
266     tcp_listen_pcbs.listen_pcbs = lpcb;
267   }
268
269   LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n"));
270   tcp_listen_input(lpcb);
271   pbuf_free(p);
272   return;
273       }
274       prev = (struct tcp_pcb *)lpcb;
275     }
276   }
277
278 #if TCP_INPUT_DEBUG
279   LWIP_DEBUGF(TCP_INPUT_DEBUG, ("+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags "));
280   tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
281   LWIP_DEBUGF(TCP_INPUT_DEBUG, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n"));
282 #endif /* TCP_INPUT_DEBUG */
283
284
285   if (pcb != NULL) {
286     /* The incoming segment belongs to a connection. */
287 #if TCP_INPUT_DEBUG
288 #if TCP_DEBUG
289     tcp_debug_print_state(pcb->state);
290 #endif /* TCP_DEBUG */
291 #endif /* TCP_INPUT_DEBUG */
292
293     /* Set up a tcp_seg structure. */
294     inseg.next = NULL;
295     inseg.len = p->tot_len;
296     inseg.dataptr = p->payload;
297     inseg.p = p;
298     inseg.tcphdr = tcphdr;
299
300     recv_data = NULL;
301     recv_flags = 0;
302
303     tcp_input_pcb = pcb;
304     err = tcp_process(pcb);
305     tcp_input_pcb = NULL;
306     /* A return value of ERR_ABRT means that tcp_abort() was called
307        and that the pcb has been freed. If so, we don't do anything. */
308     if (err != ERR_ABRT) {
309       if (recv_flags & TF_RESET) {
310   /* TF_RESET means that the connection was reset by the other
311      end. We then call the error callback to inform the
312      application that the connection is dead before we
313      deallocate the PCB. */
314   TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST);
315   tcp_pcb_remove(&tcp_active_pcbs, pcb);
316   memp_free(MEMP_TCP_PCB, pcb);
317       } else if (recv_flags & TF_CLOSED) {
318   /* The connection has been closed and we will deallocate the
319      PCB. */
320   tcp_pcb_remove(&tcp_active_pcbs, pcb);
321   memp_free(MEMP_TCP_PCB, pcb);
322       } else {
323   err = ERR_OK;
324   /* If the application has registered a "sent" function to be
325      called when new send buffer space is available, we call it
326      now. */
327   if (pcb->acked > 0) {
328     TCP_EVENT_SENT(pcb, pcb->acked, err);
329   }
330
331   if (recv_data != NULL) {
332     /* Notify application that data has been received. */
333     TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err);
334   }
335
336   /* If a FIN segment was received, we call the callback
337      function with a NULL buffer to indicate EOF. */
338   if (recv_flags & TF_GOT_FIN) {
339     TCP_EVENT_RECV(pcb, NULL, ERR_OK, err);
340   }
341   /* If there were no errors, we try to send something out. */
342   if (err == ERR_OK) {
343     tcp_output(pcb);
344   }
345       }
346     }
347
348
349     /* We deallocate the incoming pbuf. If it was buffered by the
350        application, the application should have called pbuf_ref() to
351        increase the reference counter in the pbuf. If so, the buffer
352        isn't actually deallocated by the call to pbuf_free(), only the
353        reference count is decreased. */
354     if (inseg.p != NULL) pbuf_free(inseg.p);
355 #if TCP_INPUT_DEBUG
356 #if TCP_DEBUG
357     tcp_debug_print_state(pcb->state);
358 #endif /* TCP_DEBUG */
359 #endif /* TCP_INPUT_DEBUG */
360 #if SO_REUSE
361     /* First socket should receive now */
362     if(reuse_port) {
363       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: searching next PCB.\n"));
364       reuse_port = 0;
365       
366       /* We are searching connected sockets */
367       goto again_1;
368     }
369 #endif /* SO_REUSE */
370
371   } else {
372 #if SO_REUSE
373     if(reuse) {
374       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: freeing PBUF with reference counter set to %i\n", p->ref));
375       pbuf_free(p);
376       goto end;
377     }
378 #endif /* SO_REUSE */
379     /* If no matching PCB was found, send a TCP RST (reset) to the
380        sender. */
381     LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n"));
382     if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) {
383       TCP_STATS_INC(tcp.proterr);
384       TCP_STATS_INC(tcp.drop);
385       tcp_rst(ackno, seqno + tcplen,
386         &(iphdr->dest), &(iphdr->src),
387         tcphdr->dest, tcphdr->src);
388     }
389     pbuf_free(p);
390   }
391 #if SO_REUSE
392  end:
393 #endif /* SO_REUSE */
394   LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());
395   PERF_STOP("tcp_input");
396 }
397
398 /* tcp_listen_input():
399  *
400  * Called by tcp_input() when a segment arrives for a listening
401  * connection.
402  */
403
404 static err_t
405 tcp_listen_input(struct tcp_pcb_listen *pcb)
406 {
407   struct tcp_pcb *npcb;
408   u32_t optdata;
409
410   /* In the LISTEN state, we check for incoming SYN segments,
411      creates a new PCB, and responds with a SYN|ACK. */
412   if (flags & TCP_ACK) {
413     /* For incoming segments with the ACK flag set, respond with a
414        RST. */
415     LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n"));
416     tcp_rst(ackno + 1, seqno + tcplen,
417       &(iphdr->dest), &(iphdr->src),
418       tcphdr->dest, tcphdr->src);
419   } else if (flags & TCP_SYN) {
420     LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %u -> %u.\n", tcphdr->src, tcphdr->dest));
421     npcb = tcp_alloc(pcb->prio);
422     /* If a new PCB could not be created (probably due to lack of memory),
423        we don't do anything, but rely on the sender will retransmit the
424        SYN at a time when we have more memory available. */
425     if (npcb == NULL) {
426       LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n"));
427       TCP_STATS_INC(tcp.memerr);
428       return ERR_MEM;
429     }
430     /* Set up the new PCB. */
431     ip_addr_set(&(npcb->local_ip), &(iphdr->dest));
432     npcb->local_port = pcb->local_port;
433     ip_addr_set(&(npcb->remote_ip), &(iphdr->src));
434     npcb->remote_port = tcphdr->src;
435     npcb->state = SYN_RCVD;
436     npcb->rcv_nxt = seqno + 1;
437     npcb->snd_wnd = tcphdr->wnd;
438     npcb->ssthresh = npcb->snd_wnd;
439     npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */
440     npcb->callback_arg = pcb->callback_arg;
441 #if LWIP_CALLBACK_API
442     npcb->accept = pcb->accept;
443 #endif /* LWIP_CALLBACK_API */
444     /* inherit socket options */
445     npcb->so_options = pcb->so_options & (SOF_DEBUG|SOF_DONTROUTE|SOF_KEEPALIVE|SOF_OOBINLINE|SOF_LINGER);
446     /* Register the new PCB so that we can begin receiving segments
447        for it. */
448     TCP_REG(&tcp_active_pcbs, npcb);
449
450     /* Parse any options in the SYN. */
451     tcp_parseopt(npcb);
452
453     /* Build an MSS option. */
454     optdata = htonl(((u32_t)2 << 24) |
455         ((u32_t)4 << 16) |
456         (((u32_t)npcb->mss / 256) << 8) |
457         (npcb->mss & 255));
458     /* Send a SYN|ACK together with the MSS option. */
459     tcp_enqueue(npcb, NULL, 0, TCP_SYN | TCP_ACK, 0, (u8_t *)&optdata, 4);
460     return tcp_output(npcb);
461   }
462   return ERR_OK;
463 }
464
465 /* tcp_timewait_input():
466  *
467  * Called by tcp_input() when a segment arrives for a connection in
468  * TIME_WAIT.
469  */
470
471 static err_t
472 tcp_timewait_input(struct tcp_pcb *pcb)
473 {
474   if (TCP_SEQ_GT(seqno + tcplen, pcb->rcv_nxt)) {
475     pcb->rcv_nxt = seqno + tcplen;
476   }
477   if (tcplen > 0) {
478     tcp_ack_now(pcb);
479   }
480   return tcp_output(pcb);
481 }
482
483 /* tcp_process
484  *
485  * Implements the TCP state machine. Called by tcp_input. In some
486  * states tcp_receive() is called to receive data. The tcp_seg
487  * argument will be freed by the caller (tcp_input()) unless the
488  * recv_data pointer in the pcb is set.
489  */
490
491 static err_t
492 tcp_process(struct tcp_pcb *pcb)
493 {
494   struct tcp_seg *rseg;
495   u8_t acceptable = 0;
496   err_t err;
497
498
499   err = ERR_OK;
500
501   /* Process incoming RST segments. */
502   if (flags & TCP_RST) {
503     /* First, determine if the reset is acceptable. */
504     if (pcb->state == SYN_SENT) {
505       if (ackno == pcb->snd_nxt) {
506         acceptable = 1;
507       }
508     } else {
509       /*if (TCP_SEQ_GEQ(seqno, pcb->rcv_nxt) &&
510           TCP_SEQ_LEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {
511       */
512       if(TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)){
513         acceptable = 1;
514       }
515     }
516
517     if (acceptable) {
518       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n"));
519       LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED);
520       recv_flags = TF_RESET;
521       pcb->flags &= ~TF_ACK_DELAY;
522       return ERR_RST;
523     } else {
524       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %lu rcv_nxt %lu\n",
525        seqno, pcb->rcv_nxt));
526       LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %lu rcv_nxt %lu\n",
527        seqno, pcb->rcv_nxt));
528       return ERR_OK;
529     }
530   }
531
532   /* Update the PCB (in)activity timer. */
533   pcb->tmr = tcp_ticks;
534   pcb->keep_cnt = 0;
535
536   /* Do different things depending on the TCP state. */
537   switch (pcb->state) {
538   case SYN_SENT:
539     LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %lu pcb->snd_nxt %lu unacked %lu\n", ackno,
540      pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno)));
541     if ((flags & TCP_ACK) && (flags & TCP_SYN)
542         && ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) {
543       pcb->snd_buf ++;
544       pcb->rcv_nxt = seqno + 1;
545       pcb->lastack = ackno;
546       pcb->snd_wnd = tcphdr->wnd;
547       pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */
548       pcb->state = ESTABLISHED;
549       pcb->cwnd = pcb->mss;
550       --pcb->snd_queuelen;
551       LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %u\n", (unsigned int)pcb->snd_queuelen));
552       rseg = pcb->unacked;
553       pcb->unacked = rseg->next;
554       tcp_seg_free(rseg);
555
556       /* Parse any options in the SYNACK. */
557       tcp_parseopt(pcb);
558
559       /* Call the user specified function to call when sucessfully
560        * connected. */
561       TCP_EVENT_CONNECTED(pcb, ERR_OK, err);
562       tcp_ack(pcb);
563     }
564     break;
565   case SYN_RCVD:
566     if (flags & TCP_ACK &&
567        !(flags & TCP_RST)) {
568       /*if (TCP_SEQ_LT(pcb->lastack, ackno) &&
569         TCP_SEQ_LEQ(ackno, pcb->snd_nxt)) { */
570       if(TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)){
571         pcb->state = ESTABLISHED;
572         LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %u -> %u.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
573 #if LWIP_CALLBACK_API
574         LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL);
575 #endif
576         /* Call the accept function. */
577         TCP_EVENT_ACCEPT(pcb, ERR_OK, err);
578         if (err != ERR_OK) {
579           /* If the accept function returns with an error, we abort
580            * the connection. */
581           tcp_abort(pcb);
582           return ERR_ABRT;
583         }
584         /* If there was any data contained within this ACK,
585          * we'd better pass it on to the application as well. */
586         tcp_receive(pcb);
587         pcb->cwnd = pcb->mss;
588       }
589     }
590     break;
591   case CLOSE_WAIT:
592     /* FALLTHROUGH */
593   case ESTABLISHED:
594     tcp_receive(pcb);
595     if (flags & TCP_FIN) {
596       tcp_ack_now(pcb);
597       pcb->state = CLOSE_WAIT;
598     }
599     break;
600   case FIN_WAIT_1:
601     tcp_receive(pcb);
602     if (flags & TCP_FIN) {
603       if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
604         LWIP_DEBUGF(TCP_DEBUG,
605          ("TCP connection closed %d -> %d.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
606   tcp_ack_now(pcb);
607   tcp_pcb_purge(pcb);
608   TCP_RMV(&tcp_active_pcbs, pcb);
609   pcb->state = TIME_WAIT;
610   TCP_REG(&tcp_tw_pcbs, pcb);
611       } else {
612   tcp_ack_now(pcb);
613   pcb->state = CLOSING;
614       }
615     } else if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
616       pcb->state = FIN_WAIT_2;
617     }
618     break;
619   case FIN_WAIT_2:
620     tcp_receive(pcb);
621     if (flags & TCP_FIN) {
622       LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %u -> %u.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
623       tcp_ack_now(pcb);
624       tcp_pcb_purge(pcb);
625       TCP_RMV(&tcp_active_pcbs, pcb);
626       pcb->state = TIME_WAIT;
627       TCP_REG(&tcp_tw_pcbs, pcb);
628     }
629     break;
630   case CLOSING:
631     tcp_receive(pcb);
632     if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
633       LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %u -> %u.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
634       tcp_ack_now(pcb);
635       tcp_pcb_purge(pcb);
636       TCP_RMV(&tcp_active_pcbs, pcb);
637       pcb->state = TIME_WAIT;
638       TCP_REG(&tcp_tw_pcbs, pcb);
639     }
640     break;
641   case LAST_ACK:
642     tcp_receive(pcb);
643     if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
644       LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %u -> %u.\n", inseg.tcphdr->src, inseg.tcphdr->dest));
645       pcb->state = CLOSED;
646       recv_flags = TF_CLOSED;
647     }
648     break;
649   default:
650     break;
651   }
652
653   return ERR_OK;
654 }
655
656 /* tcp_receive:
657  *
658  * Called by tcp_process. Checks if the given segment is an ACK for outstanding
659  * data, and if so frees the memory of the buffered data. Next, is places the
660  * segment on any of the receive queues (pcb->recved or pcb->ooseq). If the segment
661  * is buffered, the pbuf is referenced by pbuf_ref so that it will not be freed until
662  * i it has been removed from the buffer.
663  *
664  * If the incoming segment constitutes an ACK for a segment that was used for RTT
665  * estimation, the RTT is estimated here as well.
666  */
667
668 static void
669 tcp_receive(struct tcp_pcb *pcb)
670 {
671   struct tcp_seg *next;
672 #if TCP_QUEUE_OOSEQ
673   struct tcp_seg *prev, *cseg;
674 #endif
675   struct pbuf *p;
676   s32_t off;
677   int m;
678   u32_t right_wnd_edge;
679   u16_t new_tot_len;
680
681
682   if (flags & TCP_ACK) {
683     right_wnd_edge = pcb->snd_wnd + pcb->snd_wl1;
684
685     /* Update window. */
686     if (TCP_SEQ_LT(pcb->snd_wl1, seqno) ||
687        (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) ||
688        (pcb->snd_wl2 == ackno && tcphdr->wnd > pcb->snd_wnd)) {
689       pcb->snd_wnd = tcphdr->wnd;
690       pcb->snd_wl1 = seqno;
691       pcb->snd_wl2 = ackno;
692       LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %lu\n", pcb->snd_wnd));
693 #if TCP_WND_DEBUG
694     } else {
695       if (pcb->snd_wnd != tcphdr->wnd) {
696         LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: no window update lastack %lu snd_max %lu ackno %lu wl1 %lu seqno %lu wl2 %lu\n",
697                                pcb->lastack, pcb->snd_max, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2));
698       }
699 #endif /* TCP_WND_DEBUG */
700     }
701
702
703     if (pcb->lastack == ackno) {
704       pcb->acked = 0;
705
706       if (pcb->snd_wl1 + pcb->snd_wnd == right_wnd_edge){
707         ++pcb->dupacks;
708         if (pcb->dupacks >= 3 && pcb->unacked != NULL) {
709           if (!(pcb->flags & TF_INFR)) {
710             /* This is fast retransmit. Retransmit the first unacked segment. */
711             LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupacks %u (%lu), fast retransmit %lu\n",
712                                        (unsigned int)pcb->dupacks, pcb->lastack,
713                                        ntohl(pcb->unacked->tcphdr->seqno)));
714             tcp_rexmit(pcb);
715             /* Set ssthresh to max (FlightSize / 2, 2*SMSS) */
716             /*pcb->ssthresh = LWIP_MAX((pcb->snd_max -
717                                       pcb->lastack) / 2,
718                                       2 * pcb->mss);*/
719             /* Set ssthresh to half of the minimum of the currenct cwnd and the advertised window */
720             if(pcb->cwnd > pcb->snd_wnd)
721               pcb->ssthresh = pcb->snd_wnd / 2;
722             else
723               pcb->ssthresh = pcb->cwnd / 2;
724
725             pcb->cwnd = pcb->ssthresh + 3 * pcb->mss;
726             pcb->flags |= TF_INFR;
727           } else {
728             /* Inflate the congestion window, but not if it means that
729                the value overflows. */
730             if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
731               pcb->cwnd += pcb->mss;
732             }
733           }
734         }
735       } else {
736         LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupack averted %lu %lu\n",
737                                    pcb->snd_wl1 + pcb->snd_wnd, right_wnd_edge));
738       }
739     } else
740       /*if (TCP_SEQ_LT(pcb->lastack, ackno) &&
741         TCP_SEQ_LEQ(ackno, pcb->snd_max)) { */
742       if(TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_max)){
743       /* We come here when the ACK acknowledges new data. */
744       
745       /* Reset the "IN Fast Retransmit" flag, since we are no longer
746          in fast retransmit. Also reset the congestion window to the
747          slow start threshold. */
748       if (pcb->flags & TF_INFR) {
749         pcb->flags &= ~TF_INFR;
750         pcb->cwnd = pcb->ssthresh;
751       }
752
753       /* Reset the number of retransmissions. */
754       pcb->nrtx = 0;
755
756       /* Reset the retransmission time-out. */
757       pcb->rto = (pcb->sa >> 3) + pcb->sv;
758
759       /* Update the send buffer space. */
760       pcb->acked = ackno - pcb->lastack;
761       pcb->snd_buf += pcb->acked;
762
763       /* Reset the fast retransmit variables. */
764       pcb->dupacks = 0;
765       pcb->lastack = ackno;
766
767       /* Update the congestion control variables (cwnd and
768          ssthresh). */
769       if (pcb->state >= ESTABLISHED) {
770         if (pcb->cwnd < pcb->ssthresh) {
771           if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
772             pcb->cwnd += pcb->mss;
773           }
774           LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %u\n", pcb->cwnd));
775         } else {
776           u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd);
777           if (new_cwnd > pcb->cwnd) {
778             pcb->cwnd = new_cwnd;
779           }
780           LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %u\n", pcb->cwnd));
781         }
782       }
783       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %lu, unacked->seqno %lu:%lu\n",
784                                     ackno,
785                                     pcb->unacked != NULL?
786                                     ntohl(pcb->unacked->tcphdr->seqno): 0,
787                                     pcb->unacked != NULL?
788                                     ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0));
789
790       /* Remove segment from the unacknowledged list if the incoming
791          ACK acknowlegdes them. */
792       while (pcb->unacked != NULL &&
793              TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) +
794                          TCP_TCPLEN(pcb->unacked), ackno)) {
795         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %lu:%lu from pcb->unacked\n",
796                                       ntohl(pcb->unacked->tcphdr->seqno),
797                                       ntohl(pcb->unacked->tcphdr->seqno) +
798                                       TCP_TCPLEN(pcb->unacked)));
799
800         next = pcb->unacked;
801         pcb->unacked = pcb->unacked->next;
802
803         LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %u ... ", (unsigned int)pcb->snd_queuelen));
804         pcb->snd_queuelen -= pbuf_clen(next->p);
805         tcp_seg_free(next);
806
807         LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%u (after freeing unacked)\n", (unsigned int)pcb->snd_queuelen));
808         if (pcb->snd_queuelen != 0) {
809           LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL ||
810                       pcb->unsent != NULL);
811         }
812       }
813       pcb->polltmr = 0;
814     }
815
816     /* We go through the ->unsent list to see if any of the segments
817        on the list are acknowledged by the ACK. This may seem
818        strange since an "unsent" segment shouldn't be acked. The
819        rationale is that lwIP puts all outstanding segments on the
820        ->unsent list after a retransmission, so these segments may
821        in fact have been sent once. */
822     while (pcb->unsent != NULL &&
823            /*TCP_SEQ_LEQ(ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent), ackno) &&
824              TCP_SEQ_LEQ(ackno, pcb->snd_max)*/
825            TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent), pcb->snd_max)
826            ) {
827       LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %lu:%lu from pcb->unsent\n",
828                                     ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) +
829                                     TCP_TCPLEN(pcb->unsent)));
830
831       next = pcb->unsent;
832       pcb->unsent = pcb->unsent->next;
833       LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %u ... ", (unsigned int)pcb->snd_queuelen));
834       pcb->snd_queuelen -= pbuf_clen(next->p);
835       tcp_seg_free(next);
836       LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%u (after freeing unsent)\n", (unsigned int)pcb->snd_queuelen));
837       if (pcb->snd_queuelen != 0) {
838         LWIP_ASSERT("tcp_receive: valid queue length",
839           pcb->unacked != NULL || pcb->unsent != NULL);
840       }
841
842       if (pcb->unsent != NULL) {
843         pcb->snd_nxt = htonl(pcb->unsent->tcphdr->seqno);
844       }
845     }
846     /* End of ACK for new data processing. */
847
848     LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %u rtseq %lu ackno %lu\n",
849                                 pcb->rttest, pcb->rtseq, ackno));
850
851     /* RTT estimation calculations. This is done by checking if the
852        incoming segment acknowledges the segment we use to take a
853        round-trip time measurement. */
854     if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) {
855       m = tcp_ticks - pcb->rttest;
856
857       LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %u ticks (%u msec).\n",
858                                   m, m * TCP_SLOW_INTERVAL));
859
860       /* This is taken directly from VJs original code in his paper */
861       m = m - (pcb->sa >> 3);
862       pcb->sa += m;
863       if (m < 0) {
864         m = -m;
865       }
866       m = m - (pcb->sv >> 2);
867       pcb->sv += m;
868       pcb->rto = (pcb->sa >> 3) + pcb->sv;
869
870       LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %u (%u miliseconds)\n",
871                                   pcb->rto, pcb->rto * TCP_SLOW_INTERVAL));
872
873       pcb->rttest = 0;
874     }
875   }
876
877   /* If the incoming segment contains data, we must process it
878      further. */
879   if (tcplen > 0) {
880     /* This code basically does three things:
881
882     +) If the incoming segment contains data that is the next
883     in-sequence data, this data is passed to the application. This
884     might involve trimming the first edge of the data. The rcv_nxt
885     variable and the advertised window are adjusted.
886
887     +) If the incoming segment has data that is above the next
888     sequence number expected (->rcv_nxt), the segment is placed on
889     the ->ooseq queue. This is done by finding the appropriate
890     place in the ->ooseq queue (which is ordered by sequence
891     number) and trim the segment in both ends if needed. An
892     immediate ACK is sent to indicate that we received an
893     out-of-sequence segment.
894
895     +) Finally, we check if the first segment on the ->ooseq queue
896     now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If
897     rcv_nxt > ooseq->seqno, we must trim the first edge of the
898     segment on ->ooseq before we adjust rcv_nxt. The data in the
899     segments that are now on sequence are chained onto the
900     incoming segment so that we only need to call the application
901     once.
902     */
903
904     /* First, we check if we must trim the first edge. We have to do
905        this if the sequence number of the incoming segment is less
906        than rcv_nxt, and the sequence number plus the length of the
907        segment is larger than rcv_nxt. */
908     /*    if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){
909           if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/
910     if(TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno+1, seqno+tcplen-1)){
911       /* Trimming the first edge is done by pushing the payload
912          pointer in the pbuf downwards. This is somewhat tricky since
913          we do not want to discard the full contents of the pbuf up to
914          the new starting point of the data since we have to keep the
915          TCP header which is present in the first pbuf in the chain.
916          
917          What is done is really quite a nasty hack: the first pbuf in
918          the pbuf chain is pointed to by inseg.p. Since we need to be
919          able to deallocate the whole pbuf, we cannot change this
920          inseg.p pointer to point to any of the later pbufs in the
921          chain. Instead, we point the ->payload pointer in the first
922          pbuf to data in one of the later pbufs. We also set the
923          inseg.data pointer to point to the right place. This way, the
924          ->p pointer will still point to the first pbuf, but the
925          ->p->payload pointer will point to data in another pbuf.
926          
927          After we are done with adjusting the pbuf pointers we must
928          adjust the ->data pointer in the seg and the segment
929          length.*/
930       
931       off = pcb->rcv_nxt - seqno;
932       p = inseg.p;
933       if (inseg.p->len < off) {
934         new_tot_len = inseg.p->tot_len - off;
935         while (p->len < off) {
936           off -= p->len;
937           /* KJM following line changed (with addition of new_tot_len var)
938              to fix bug #9076
939              inseg.p->tot_len -= p->len; */
940           p->tot_len = new_tot_len;
941           p->len = 0;
942           p = p->next;
943         }
944         pbuf_header(p, -off);
945       } else {
946         pbuf_header(inseg.p, -off);
947       }
948       /* KJM following line changed to use p->payload rather than inseg->p->payload
949          to fix bug #9076 */
950       inseg.dataptr = p->payload;
951       inseg.len -= pcb->rcv_nxt - seqno;
952       inseg.tcphdr->seqno = seqno = pcb->rcv_nxt;
953     }
954     else{
955       if(TCP_SEQ_LT(seqno, pcb->rcv_nxt)){
956         /* the whole segment is < rcv_nxt */
957         /* must be a duplicate of a packet that has already been correctly handled */
958         
959         LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %lu\n", seqno));
960         tcp_ack_now(pcb);
961       }
962     }
963
964     /* The sequence number must be within the window (above rcv_nxt
965        and below rcv_nxt + rcv_wnd) in order to be further
966        processed. */
967     /*if (TCP_SEQ_GEQ(seqno, pcb->rcv_nxt) &&
968       TCP_SEQ_LT(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/
969     if(TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd - 1)){
970       if (pcb->rcv_nxt == seqno) {
971         /* The incoming segment is the next in sequence. We check if
972            we have to trim the end of the segment and update rcv_nxt
973            and pass the data to the application. */
974 #if TCP_QUEUE_OOSEQ
975         if (pcb->ooseq != NULL &&
976             TCP_SEQ_LEQ(pcb->ooseq->tcphdr->seqno, seqno + inseg.len)) {
977           /* We have to trim the second edge of the incoming
978              segment. */
979           inseg.len = pcb->ooseq->tcphdr->seqno - seqno;
980           pbuf_realloc(inseg.p, inseg.len);
981         }
982 #endif /* TCP_QUEUE_OOSEQ */
983
984         tcplen = TCP_TCPLEN(&inseg);
985
986         pcb->rcv_nxt += tcplen;
987
988         /* Update the receiver's (our) window. */
989         if (pcb->rcv_wnd < tcplen) {
990           pcb->rcv_wnd = 0;
991         } else {
992           pcb->rcv_wnd -= tcplen;
993         }
994
995         /* If there is data in the segment, we make preparations to
996            pass this up to the application. The ->recv_data variable
997            is used for holding the pbuf that goes to the
998            application. The code for reassembling out-of-sequence data
999            chains its data on this pbuf as well.
1000
1001            If the segment was a FIN, we set the TF_GOT_FIN flag that will
1002            be used to indicate to the application that the remote side has
1003            closed its end of the connection. */
1004         if (inseg.p->tot_len > 0) {
1005           recv_data = inseg.p;
1006           /* Since this pbuf now is the responsibility of the
1007              application, we delete our reference to it so that we won't
1008              (mistakingly) deallocate it. */
1009           inseg.p = NULL;
1010         }
1011         if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
1012           LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n"));
1013           recv_flags = TF_GOT_FIN;
1014         }
1015
1016 #if TCP_QUEUE_OOSEQ
1017         /* We now check if we have segments on the ->ooseq queue that
1018            is now in sequence. */
1019         while (pcb->ooseq != NULL &&
1020                pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) {
1021
1022           cseg = pcb->ooseq;
1023           seqno = pcb->ooseq->tcphdr->seqno;
1024
1025           pcb->rcv_nxt += TCP_TCPLEN(cseg);
1026           if (pcb->rcv_wnd < TCP_TCPLEN(cseg)) {
1027             pcb->rcv_wnd = 0;
1028           } else {
1029             pcb->rcv_wnd -= TCP_TCPLEN(cseg);
1030           }
1031           if (cseg->p->tot_len > 0) {
1032             /* Chain this pbuf onto the pbuf that we will pass to
1033                the application. */
1034             if (recv_data) {
1035               pbuf_cat(recv_data, cseg->p);
1036             } else {
1037               recv_data = cseg->p;
1038             }
1039             cseg->p = NULL;
1040           }
1041           if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
1042             LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n"));
1043             recv_flags = TF_GOT_FIN;
1044           }
1045
1046
1047           pcb->ooseq = cseg->next;
1048           tcp_seg_free(cseg);
1049         }
1050 #endif /* TCP_QUEUE_OOSEQ */
1051
1052
1053         /* Acknowledge the segment(s). */
1054         tcp_ack(pcb);
1055
1056       } else {
1057         /* We get here if the incoming segment is out-of-sequence. */
1058         tcp_ack_now(pcb);
1059 #if TCP_QUEUE_OOSEQ
1060         /* We queue the segment on the ->ooseq queue. */
1061         if (pcb->ooseq == NULL) {
1062           pcb->ooseq = tcp_seg_copy(&inseg);
1063         } else {
1064           /* If the queue is not empty, we walk through the queue and
1065              try to find a place where the sequence number of the
1066              incoming segment is between the sequence numbers of the
1067              previous and the next segment on the ->ooseq queue. That is
1068              the place where we put the incoming segment. If needed, we
1069              trim the second edges of the previous and the incoming
1070              segment so that it will fit into the sequence.
1071
1072              If the incoming segment has the same sequence number as a
1073              segment on the ->ooseq queue, we discard the segment that
1074              contains less data. */
1075
1076           prev = NULL;
1077           for(next = pcb->ooseq; next != NULL; next = next->next) {
1078             if (seqno == next->tcphdr->seqno) {
1079               /* The sequence number of the incoming segment is the
1080                  same as the sequence number of the segment on
1081                  ->ooseq. We check the lengths to see which one to
1082                  discard. */
1083               if (inseg.len > next->len) {
1084                 /* The incoming segment is larger than the old
1085                    segment. We replace the old segment with the new
1086                    one. */
1087                 cseg = tcp_seg_copy(&inseg);
1088                 if (cseg != NULL) {
1089                   cseg->next = next->next;
1090                   if (prev != NULL) {
1091                     prev->next = cseg;
1092                   } else {
1093                     pcb->ooseq = cseg;
1094                   }
1095                 }
1096                 break;
1097               } else {
1098                 /* Either the lenghts are the same or the incoming
1099                    segment was smaller than the old one; in either
1100                    case, we ditch the incoming segment. */
1101                 break;
1102               }
1103             } else {
1104               if (prev == NULL) {
1105                 if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {
1106                   /* The sequence number of the incoming segment is lower
1107                      than the sequence number of the first segment on the
1108                      queue. We put the incoming segment first on the
1109                      queue. */
1110
1111                   if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) {
1112                     /* We need to trim the incoming segment. */
1113                     inseg.len = next->tcphdr->seqno - seqno;
1114                     pbuf_realloc(inseg.p, inseg.len);
1115                   }
1116                   cseg = tcp_seg_copy(&inseg);
1117                   if (cseg != NULL) {
1118                     cseg->next = next;
1119                     pcb->ooseq = cseg;
1120                   }
1121                   break;
1122                 }
1123               } else 
1124                 /*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) &&
1125                   TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/
1126                 if(TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)){
1127                 /* The sequence number of the incoming segment is in
1128                    between the sequence numbers of the previous and
1129                    the next segment on ->ooseq. We trim and insert the
1130                    incoming segment and trim the previous segment, if
1131                    needed. */
1132                 if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) {
1133                   /* We need to trim the incoming segment. */
1134                   inseg.len = next->tcphdr->seqno - seqno;
1135                   pbuf_realloc(inseg.p, inseg.len);
1136                 }
1137
1138                 cseg = tcp_seg_copy(&inseg);
1139                 if (cseg != NULL) {
1140                   cseg->next = next;
1141                   prev->next = cseg;
1142                   if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) {
1143                     /* We need to trim the prev segment. */
1144                     prev->len = seqno - prev->tcphdr->seqno;
1145                     pbuf_realloc(prev->p, prev->len);
1146                   }
1147                 }
1148                 break;
1149               }
1150               /* If the "next" segment is the last segment on the
1151                  ooseq queue, we add the incoming segment to the end
1152                  of the list. */
1153               if (next->next == NULL &&
1154                   TCP_SEQ_GT(seqno, next->tcphdr->seqno)) {
1155                 next->next = tcp_seg_copy(&inseg);
1156                 if (next->next != NULL) {
1157                   if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) {
1158                     /* We need to trim the last segment. */
1159                     next->len = seqno - next->tcphdr->seqno;
1160                     pbuf_realloc(next->p, next->len);
1161                   }
1162                 }
1163                 break;
1164               }
1165             }
1166             prev = next;
1167           }
1168         }
1169 #endif /* TCP_QUEUE_OOSEQ */
1170
1171       }
1172     } else {
1173       /*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) ||
1174         TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/
1175       if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){
1176         tcp_ack_now(pcb);
1177       }
1178     }
1179   } else {
1180     /* Segments with length 0 is taken care of here. Segments that
1181        fall out of the window are ACKed. */
1182     /*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) ||
1183       TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/
1184     if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){
1185       tcp_ack_now(pcb);
1186     }
1187   }
1188 }
1189
1190 /*
1191  * tcp_parseopt:
1192  *
1193  * Parses the options contained in the incoming segment. (Code taken
1194  * from uIP with only small changes.)
1195  *
1196  */
1197
1198 static void
1199 tcp_parseopt(struct tcp_pcb *pcb)
1200 {
1201   u8_t c;
1202   u8_t *opts, opt;
1203   u16_t mss;
1204
1205   opts = (u8_t *)tcphdr + TCP_HLEN;
1206
1207   /* Parse the TCP MSS option, if present. */
1208   if(TCPH_HDRLEN(tcphdr) > 0x5) {
1209     for(c = 0; c < (TCPH_HDRLEN(tcphdr) - 5) << 2 ;) {
1210       opt = opts[c];
1211       if (opt == 0x00) {
1212         /* End of options. */
1213   break;
1214       } else if (opt == 0x01) {
1215         ++c;
1216         /* NOP option. */
1217       } else if (opt == 0x02 &&
1218         opts[c + 1] == 0x04) {
1219         /* An MSS option with the right option length. */
1220         mss = (opts[c + 2] << 8) | opts[c + 3];
1221         pcb->mss = mss > TCP_MSS? TCP_MSS: mss;
1222
1223         /* And we are done processing options. */
1224         break;
1225       } else {
1226   if (opts[c + 1] == 0) {
1227           /* If the length field is zero, the options are malformed
1228              and we don't process them further. */
1229           break;
1230         }
1231         /* All other options have a length field, so that we easily
1232            can skip past them. */
1233         c += opts[c + 1];
1234       }
1235     }
1236   }
1237 }
1238 #endif /* LWIP_TCP */
1239
1240