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