FreeRTOS
[armadillo_firmware.git] / FreeRTOS / Common / ethernet / lwIP_132 / src / core / tcp_in.c
blob51e8775901059eb0323d39088fa9cbf5302ec992
1 /**
2 * @file
3 * Transmission Control Protocol, incoming traffic
5 * The input processing functions of the TCP layer.
7 * These functions are generally called in the order (ip_input() ->)
8 * tcp_input() -> * tcp_process() -> tcp_receive() (-> application).
9 *
13 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
14 * All rights reserved.
16 * Redistribution and use in source and binary forms, with or without modification,
17 * are permitted provided that the following conditions are met:
19 * 1. Redistributions of source code must retain the above copyright notice,
20 * this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright notice,
22 * this list of conditions and the following disclaimer in the documentation
23 * and/or other materials provided with the distribution.
24 * 3. The name of the author may not be used to endorse or promote products
25 * derived from this software without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
28 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
29 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
30 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
32 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
35 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
36 * OF SUCH DAMAGE.
38 * This file is part of the lwIP TCP/IP stack.
40 * Author: Adam Dunkels <adam@sics.se>
44 #include "lwip/opt.h"
46 #if LWIP_TCP /* don't build if not configured for use in lwipopts.h */
48 #include "lwip/tcp.h"
49 #include "lwip/def.h"
50 #include "lwip/ip_addr.h"
51 #include "lwip/netif.h"
52 #include "lwip/mem.h"
53 #include "lwip/memp.h"
54 #include "lwip/inet.h"
55 #include "lwip/inet_chksum.h"
56 #include "lwip/stats.h"
57 #include "lwip/snmp.h"
58 #include "arch/perf.h"
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;
70 static u8_t recv_flags;
71 static struct pbuf *recv_data;
73 struct tcp_pcb *tcp_input_pcb;
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);
80 static err_t tcp_listen_input(struct tcp_pcb_listen *pcb);
81 static err_t tcp_timewait_input(struct tcp_pcb *pcb);
83 /**
84 * The initial input processing of TCP. It verifies the TCP header, demultiplexes
85 * the segment between the PCBs and passes it on to tcp_process(), which implements
86 * the TCP finite state machine. This function is called by the IP layer (in
87 * ip_input()).
89 * @param p received TCP segment to process (p->payload pointing to the IP header)
90 * @param inp network interface on which this segment was received
92 void
93 tcp_input(struct pbuf *p, struct netif *inp)
95 struct tcp_pcb *pcb, *prev;
96 struct tcp_pcb_listen *lpcb;
97 u8_t hdrlen;
98 err_t err;
100 PERF_START;
102 TCP_STATS_INC(tcp.recv);
103 snmp_inc_tcpinsegs();
105 iphdr = p->payload;
106 tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4);
108 #if TCP_INPUT_DEBUG
109 tcp_debug_print(tcphdr);
110 #endif
112 /* remove header from payload */
113 if (pbuf_header(p, -((s16_t)(IPH_HL(iphdr) * 4))) || (p->tot_len < sizeof(struct tcp_hdr))) {
114 /* drop short packets */
115 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len));
116 TCP_STATS_INC(tcp.lenerr);
117 TCP_STATS_INC(tcp.drop);
118 snmp_inc_tcpinerrs();
119 pbuf_free(p);
120 return;
123 /* Don't even process incoming broadcasts/multicasts. */
124 if (ip_addr_isbroadcast(&(iphdr->dest), inp) ||
125 ip_addr_ismulticast(&(iphdr->dest))) {
126 TCP_STATS_INC(tcp.proterr);
127 TCP_STATS_INC(tcp.drop);
128 snmp_inc_tcpinerrs();
129 pbuf_free(p);
130 return;
133 #if CHECKSUM_CHECK_TCP
134 /* Verify TCP checksum. */
135 if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
136 (struct ip_addr *)&(iphdr->dest),
137 IP_PROTO_TCP, p->tot_len) != 0) {
138 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n",
139 inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src), (struct ip_addr *)&(iphdr->dest),
140 IP_PROTO_TCP, p->tot_len)));
141 #if TCP_DEBUG
142 tcp_debug_print(tcphdr);
143 #endif /* TCP_DEBUG */
144 TCP_STATS_INC(tcp.chkerr);
145 TCP_STATS_INC(tcp.drop);
146 snmp_inc_tcpinerrs();
147 pbuf_free(p);
148 return;
150 #endif
152 /* Move the payload pointer in the pbuf so that it points to the
153 TCP data instead of the TCP header. */
154 hdrlen = TCPH_HDRLEN(tcphdr);
155 if(pbuf_header(p, -(hdrlen * 4))){
156 /* drop short packets */
157 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet\n"));
158 TCP_STATS_INC(tcp.lenerr);
159 TCP_STATS_INC(tcp.drop);
160 snmp_inc_tcpinerrs();
161 pbuf_free(p);
162 return;
165 /* Convert fields in TCP header to host byte order. */
166 tcphdr->src = ntohs(tcphdr->src);
167 tcphdr->dest = ntohs(tcphdr->dest);
168 seqno = tcphdr->seqno = ntohl(tcphdr->seqno);
169 ackno = tcphdr->ackno = ntohl(tcphdr->ackno);
170 tcphdr->wnd = ntohs(tcphdr->wnd);
172 flags = TCPH_FLAGS(tcphdr);
173 tcplen = p->tot_len + ((flags & (TCP_FIN | TCP_SYN)) ? 1 : 0);
175 /* Demultiplex an incoming segment. First, we check if it is destined
176 for an active connection. */
177 prev = NULL;
180 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
181 LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED);
182 LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
183 LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
184 if (pcb->remote_port == tcphdr->src &&
185 pcb->local_port == tcphdr->dest &&
186 ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
187 ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
189 /* Move this PCB to the front of the list so that subsequent
190 lookups will be faster (we exploit locality in TCP segment
191 arrivals). */
192 LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb);
193 if (prev != NULL) {
194 prev->next = pcb->next;
195 pcb->next = tcp_active_pcbs;
196 tcp_active_pcbs = pcb;
198 LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb);
199 break;
201 prev = pcb;
204 if (pcb == NULL) {
205 /* If it did not go to an active connection, we check the connections
206 in the TIME-WAIT state. */
207 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
208 LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
209 if (pcb->remote_port == tcphdr->src &&
210 pcb->local_port == tcphdr->dest &&
211 ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
212 ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
213 /* We don't really care enough to move this PCB to the front
214 of the list since we are not very likely to receive that
215 many segments for connections in TIME-WAIT. */
216 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n"));
217 tcp_timewait_input(pcb);
218 pbuf_free(p);
219 return;
223 /* Finally, if we still did not get a match, we check all PCBs that
224 are LISTENing for incoming connections. */
225 prev = NULL;
226 for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
227 if ((ip_addr_isany(&(lpcb->local_ip)) ||
228 ip_addr_cmp(&(lpcb->local_ip), &(iphdr->dest))) &&
229 lpcb->local_port == tcphdr->dest) {
230 /* Move this PCB to the front of the list so that subsequent
231 lookups will be faster (we exploit locality in TCP segment
232 arrivals). */
233 if (prev != NULL) {
234 ((struct tcp_pcb_listen *)prev)->next = lpcb->next;
235 /* our successor is the remainder of the listening list */
236 lpcb->next = tcp_listen_pcbs.listen_pcbs;
237 /* put this listening pcb at the head of the listening list */
238 tcp_listen_pcbs.listen_pcbs = lpcb;
241 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n"));
242 tcp_listen_input(lpcb);
243 pbuf_free(p);
244 return;
246 prev = (struct tcp_pcb *)lpcb;
250 #if TCP_INPUT_DEBUG
251 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags "));
252 tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
253 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n"));
254 #endif /* TCP_INPUT_DEBUG */
257 if (pcb != NULL) {
258 /* The incoming segment belongs to a connection. */
259 #if TCP_INPUT_DEBUG
260 #if TCP_DEBUG
261 tcp_debug_print_state(pcb->state);
262 #endif /* TCP_DEBUG */
263 #endif /* TCP_INPUT_DEBUG */
265 /* Set up a tcp_seg structure. */
266 inseg.next = NULL;
267 inseg.len = p->tot_len;
268 inseg.dataptr = p->payload;
269 inseg.p = p;
270 inseg.tcphdr = tcphdr;
272 recv_data = NULL;
273 recv_flags = 0;
275 /* If there is data which was previously "refused" by upper layer */
276 if (pcb->refused_data != NULL) {
277 /* Notify again application with data previously received. */
278 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: notify kept packet\n"));
279 TCP_EVENT_RECV(pcb, pcb->refused_data, ERR_OK, err);
280 if (err == ERR_OK) {
281 pcb->refused_data = NULL;
282 } else {
283 /* drop incoming packets, because pcb is "full" */
284 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n"));
285 TCP_STATS_INC(tcp.drop);
286 snmp_inc_tcpinerrs();
287 pbuf_free(p);
288 return;
291 tcp_input_pcb = pcb;
292 err = tcp_process(pcb);
293 /* A return value of ERR_ABRT means that tcp_abort() was called
294 and that the pcb has been freed. If so, we don't do anything. */
295 if (err != ERR_ABRT) {
296 if (recv_flags & TF_RESET) {
297 /* TF_RESET means that the connection was reset by the other
298 end. We then call the error callback to inform the
299 application that the connection is dead before we
300 deallocate the PCB. */
301 TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST);
302 tcp_pcb_remove(&tcp_active_pcbs, pcb);
303 memp_free(MEMP_TCP_PCB, pcb);
304 } else if (recv_flags & TF_CLOSED) {
305 /* The connection has been closed and we will deallocate the
306 PCB. */
307 tcp_pcb_remove(&tcp_active_pcbs, pcb);
308 memp_free(MEMP_TCP_PCB, pcb);
309 } else {
310 err = ERR_OK;
311 /* If the application has registered a "sent" function to be
312 called when new send buffer space is available, we call it
313 now. */
314 if (pcb->acked > 0) {
315 TCP_EVENT_SENT(pcb, pcb->acked, err);
318 if (recv_data != NULL) {
319 if(flags & TCP_PSH) {
320 recv_data->flags |= PBUF_FLAG_PUSH;
323 /* Notify application that data has been received. */
324 TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err);
326 /* If the upper layer can't receive this data, store it */
327 if (err != ERR_OK) {
328 pcb->refused_data = recv_data;
329 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: keep incoming packet, because pcb is \"full\"\n"));
333 /* If a FIN segment was received, we call the callback
334 function with a NULL buffer to indicate EOF. */
335 if (recv_flags & TF_GOT_FIN) {
336 TCP_EVENT_RECV(pcb, NULL, ERR_OK, err);
339 tcp_input_pcb = NULL;
340 /* Try to send something out. */
341 tcp_output(pcb);
342 #if TCP_INPUT_DEBUG
343 #if TCP_DEBUG
344 tcp_debug_print_state(pcb->state);
345 #endif /* TCP_DEBUG */
346 #endif /* TCP_INPUT_DEBUG */
349 tcp_input_pcb = NULL;
352 /* give up our reference to inseg.p */
353 if (inseg.p != NULL)
355 pbuf_free(inseg.p);
356 inseg.p = NULL;
358 } else {
360 /* If no matching PCB was found, send a TCP RST (reset) to the
361 sender. */
362 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n"));
363 if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) {
364 TCP_STATS_INC(tcp.proterr);
365 TCP_STATS_INC(tcp.drop);
366 tcp_rst(ackno, seqno + tcplen,
367 &(iphdr->dest), &(iphdr->src),
368 tcphdr->dest, tcphdr->src);
370 pbuf_free(p);
373 LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());
374 PERF_STOP("tcp_input");
378 * Called by tcp_input() when a segment arrives for a listening
379 * connection (from tcp_input()).
381 * @param pcb the tcp_pcb_listen for which a segment arrived
382 * @return ERR_OK if the segment was processed
383 * another err_t on error
385 * @note the return value is not (yet?) used in tcp_input()
386 * @note the segment which arrived is saved in global variables, therefore only the pcb
387 * involved is passed as a parameter to this function
389 static err_t
390 tcp_listen_input(struct tcp_pcb_listen *pcb)
392 struct tcp_pcb *npcb;
393 err_t rc;
395 /* In the LISTEN state, we check for incoming SYN segments,
396 creates a new PCB, and responds with a SYN|ACK. */
397 if (flags & TCP_ACK) {
398 /* For incoming segments with the ACK flag set, respond with a
399 RST. */
400 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n"));
401 tcp_rst(ackno + 1, seqno + tcplen,
402 &(iphdr->dest), &(iphdr->src),
403 tcphdr->dest, tcphdr->src);
404 } else if (flags & TCP_SYN) {
405 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest));
406 #if TCP_LISTEN_BACKLOG
407 if (pcb->accepts_pending >= pcb->backlog) {
408 LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: listen backlog exceeded for port %"U16_F"\n", tcphdr->dest));
409 return ERR_ABRT;
411 #endif /* TCP_LISTEN_BACKLOG */
412 npcb = tcp_alloc(pcb->prio);
413 /* If a new PCB could not be created (probably due to lack of memory),
414 we don't do anything, but rely on the sender will retransmit the
415 SYN at a time when we have more memory available. */
416 if (npcb == NULL) {
417 LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n"));
418 TCP_STATS_INC(tcp.memerr);
419 return ERR_MEM;
421 #if TCP_LISTEN_BACKLOG
422 pcb->accepts_pending++;
423 #endif /* TCP_LISTEN_BACKLOG */
424 /* Set up the new PCB. */
425 ip_addr_set(&(npcb->local_ip), &(iphdr->dest));
426 npcb->local_port = pcb->local_port;
427 ip_addr_set(&(npcb->remote_ip), &(iphdr->src));
428 npcb->remote_port = tcphdr->src;
429 npcb->state = SYN_RCVD;
430 npcb->rcv_nxt = seqno + 1;
431 npcb->rcv_ann_right_edge = npcb->rcv_nxt;
432 npcb->snd_wnd = tcphdr->wnd;
433 npcb->ssthresh = npcb->snd_wnd;
434 npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */
435 npcb->callback_arg = pcb->callback_arg;
436 #if LWIP_CALLBACK_API
437 npcb->accept = pcb->accept;
438 #endif /* LWIP_CALLBACK_API */
439 /* inherit socket options */
440 npcb->so_options = pcb->so_options & (SOF_DEBUG|SOF_DONTROUTE|SOF_KEEPALIVE|SOF_OOBINLINE|SOF_LINGER);
441 /* Register the new PCB so that we can begin receiving segments
442 for it. */
443 TCP_REG(&tcp_active_pcbs, npcb);
445 /* Parse any options in the SYN. */
446 tcp_parseopt(npcb);
447 #if TCP_CALCULATE_EFF_SEND_MSS
448 npcb->mss = tcp_eff_send_mss(npcb->mss, &(npcb->remote_ip));
449 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
451 snmp_inc_tcppassiveopens();
453 /* Send a SYN|ACK together with the MSS option. */
454 rc = tcp_enqueue(npcb, NULL, 0, TCP_SYN | TCP_ACK, 0, TF_SEG_OPTS_MSS
455 #if LWIP_TCP_TIMESTAMPS
456 /* and maybe include the TIMESTAMP option */
457 | (npcb->flags & TF_TIMESTAMP ? TF_SEG_OPTS_TS : 0)
458 #endif
460 if (rc != ERR_OK) {
461 tcp_abandon(npcb, 0);
462 return rc;
464 return tcp_output(npcb);
466 return ERR_OK;
470 * Called by tcp_input() when a segment arrives for a connection in
471 * TIME_WAIT.
473 * @param pcb the tcp_pcb for which a segment arrived
475 * @note the segment which arrived is saved in global variables, therefore only the pcb
476 * involved is passed as a parameter to this function
478 static err_t
479 tcp_timewait_input(struct tcp_pcb *pcb)
481 /* RFC 1337: in TIME_WAIT, ignore RST and ACK FINs + any 'acceptable' segments */
482 /* RFC 793 3.9 Event Processing - Segment Arrives:
483 * - first check sequence number - we skip that one in TIME_WAIT (always
484 * acceptable since we only send ACKs)
485 * - second check the RST bit (... return) */
486 if (flags & TCP_RST) {
487 return ERR_OK;
489 /* - fourth, check the SYN bit, */
490 if (flags & TCP_SYN) {
491 /* If an incoming segment is not acceptable, an acknowledgment
492 should be sent in reply */
493 if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) {
494 /* If the SYN is in the window it is an error, send a reset */
495 tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src),
496 tcphdr->dest, tcphdr->src);
497 return ERR_OK;
499 } else if (flags & TCP_FIN) {
500 /* - eighth, check the FIN bit: Remain in the TIME-WAIT state.
501 Restart the 2 MSL time-wait timeout.*/
502 pcb->tmr = tcp_ticks;
505 if ((tcplen > 0)) {
506 /* Acknowledge data, FIN or out-of-window SYN */
507 pcb->flags |= TF_ACK_NOW;
508 return tcp_output(pcb);
510 return ERR_OK;
514 * Implements the TCP state machine. Called by tcp_input. In some
515 * states tcp_receive() is called to receive data. The tcp_seg
516 * argument will be freed by the caller (tcp_input()) unless the
517 * recv_data pointer in the pcb is set.
519 * @param pcb the tcp_pcb for which a segment arrived
521 * @note the segment which arrived is saved in global variables, therefore only the pcb
522 * involved is passed as a parameter to this function
524 static err_t
525 tcp_process(struct tcp_pcb *pcb)
527 struct tcp_seg *rseg;
528 u8_t acceptable = 0;
529 err_t err;
531 err = ERR_OK;
533 /* Process incoming RST segments. */
534 if (flags & TCP_RST) {
535 /* First, determine if the reset is acceptable. */
536 if (pcb->state == SYN_SENT) {
537 if (ackno == pcb->snd_nxt) {
538 acceptable = 1;
540 } else {
541 if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
542 pcb->rcv_nxt+pcb->rcv_wnd)) {
543 acceptable = 1;
547 if (acceptable) {
548 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n"));
549 LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED);
550 recv_flags |= TF_RESET;
551 pcb->flags &= ~TF_ACK_DELAY;
552 return ERR_RST;
553 } else {
554 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n",
555 seqno, pcb->rcv_nxt));
556 LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n",
557 seqno, pcb->rcv_nxt));
558 return ERR_OK;
562 if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) {
563 /* Cope with new connection attempt after remote end crashed */
564 tcp_ack_now(pcb);
565 return ERR_OK;
568 /* Update the PCB (in)activity timer. */
569 pcb->tmr = tcp_ticks;
570 pcb->keep_cnt_sent = 0;
572 tcp_parseopt(pcb);
574 /* Do different things depending on the TCP state. */
575 switch (pcb->state) {
576 case SYN_SENT:
577 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno,
578 pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno)));
579 /* received SYN ACK with expected sequence number? */
580 if ((flags & TCP_ACK) && (flags & TCP_SYN)
581 && ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) {
582 pcb->snd_buf++;
583 pcb->rcv_nxt = seqno + 1;
584 pcb->rcv_ann_right_edge = pcb->rcv_nxt;
585 pcb->lastack = ackno;
586 pcb->snd_wnd = tcphdr->wnd;
587 pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */
588 pcb->state = ESTABLISHED;
590 #if TCP_CALCULATE_EFF_SEND_MSS
591 pcb->mss = tcp_eff_send_mss(pcb->mss, &(pcb->remote_ip));
592 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
594 /* Set ssthresh again after changing pcb->mss (already set in tcp_connect
595 * but for the default value of pcb->mss) */
596 pcb->ssthresh = pcb->mss * 10;
598 pcb->cwnd = ((pcb->cwnd == 1) ? (pcb->mss * 2) : pcb->mss);
599 LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0));
600 --pcb->snd_queuelen;
601 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"U16_F"\n", (u16_t)pcb->snd_queuelen));
602 rseg = pcb->unacked;
603 pcb->unacked = rseg->next;
605 /* If there's nothing left to acknowledge, stop the retransmit
606 timer, otherwise reset it to start again */
607 if(pcb->unacked == NULL)
608 pcb->rtime = -1;
609 else {
610 pcb->rtime = 0;
611 pcb->nrtx = 0;
614 tcp_seg_free(rseg);
616 /* Call the user specified function to call when sucessfully
617 * connected. */
618 TCP_EVENT_CONNECTED(pcb, ERR_OK, err);
619 tcp_ack_now(pcb);
621 /* received ACK? possibly a half-open connection */
622 else if (flags & TCP_ACK) {
623 /* send a RST to bring the other side in a non-synchronized state. */
624 tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src),
625 tcphdr->dest, tcphdr->src);
627 break;
628 case SYN_RCVD:
629 if (flags & TCP_ACK) {
630 /* expected ACK number? */
631 if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) {
632 u16_t old_cwnd;
633 pcb->state = ESTABLISHED;
634 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
635 #if LWIP_CALLBACK_API
636 LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL);
637 #endif
638 /* Call the accept function. */
639 TCP_EVENT_ACCEPT(pcb, ERR_OK, err);
640 if (err != ERR_OK) {
641 /* If the accept function returns with an error, we abort
642 * the connection. */
643 tcp_abort(pcb);
644 return ERR_ABRT;
646 old_cwnd = pcb->cwnd;
647 /* If there was any data contained within this ACK,
648 * we'd better pass it on to the application as well. */
649 tcp_receive(pcb);
651 /* Prevent ACK for SYN to generate a sent event */
652 if (pcb->acked != 0) {
653 pcb->acked--;
656 pcb->cwnd = ((old_cwnd == 1) ? (pcb->mss * 2) : pcb->mss);
658 if (recv_flags & TF_GOT_FIN) {
659 tcp_ack_now(pcb);
660 pcb->state = CLOSE_WAIT;
663 /* incorrect ACK number */
664 else {
665 /* send RST */
666 tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src),
667 tcphdr->dest, tcphdr->src);
669 } else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) {
670 /* Looks like another copy of the SYN - retransmit our SYN-ACK */
671 tcp_rexmit(pcb);
673 break;
674 case CLOSE_WAIT:
675 /* FALLTHROUGH */
676 case ESTABLISHED:
677 tcp_receive(pcb);
678 if (recv_flags & TF_GOT_FIN) { /* passive close */
679 tcp_ack_now(pcb);
680 pcb->state = CLOSE_WAIT;
682 break;
683 case FIN_WAIT_1:
684 tcp_receive(pcb);
685 if (recv_flags & TF_GOT_FIN) {
686 if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) {
687 LWIP_DEBUGF(TCP_DEBUG,
688 ("TCP connection closed: FIN_WAIT_1 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
689 tcp_ack_now(pcb);
690 tcp_pcb_purge(pcb);
691 TCP_RMV(&tcp_active_pcbs, pcb);
692 pcb->state = TIME_WAIT;
693 TCP_REG(&tcp_tw_pcbs, pcb);
694 } else {
695 tcp_ack_now(pcb);
696 pcb->state = CLOSING;
698 } else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) {
699 pcb->state = FIN_WAIT_2;
701 break;
702 case FIN_WAIT_2:
703 tcp_receive(pcb);
704 if (recv_flags & TF_GOT_FIN) {
705 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: FIN_WAIT_2 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
706 tcp_ack_now(pcb);
707 tcp_pcb_purge(pcb);
708 TCP_RMV(&tcp_active_pcbs, pcb);
709 pcb->state = TIME_WAIT;
710 TCP_REG(&tcp_tw_pcbs, pcb);
712 break;
713 case CLOSING:
714 tcp_receive(pcb);
715 if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
716 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
717 tcp_pcb_purge(pcb);
718 TCP_RMV(&tcp_active_pcbs, pcb);
719 pcb->state = TIME_WAIT;
720 TCP_REG(&tcp_tw_pcbs, pcb);
722 break;
723 case LAST_ACK:
724 tcp_receive(pcb);
725 if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
726 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: LAST_ACK %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
727 /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */
728 recv_flags |= TF_CLOSED;
730 break;
731 default:
732 break;
734 return ERR_OK;
737 #if TCP_QUEUE_OOSEQ
739 * Insert segment into the list (segments covered with new one will be deleted)
741 * Called from tcp_receive()
743 static void
744 tcp_oos_insert_segment(struct tcp_seg *cseg, struct tcp_seg *next)
746 struct tcp_seg *old_seg;
748 if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
749 /* received segment overlaps all following segments */
750 tcp_segs_free(next);
751 next = NULL;
753 else {
754 /* delete some following segments
755 oos queue may have segments with FIN flag */
756 while (next &&
757 TCP_SEQ_GEQ((seqno + cseg->len),
758 (next->tcphdr->seqno + next->len))) {
759 /* cseg with FIN already processed */
760 if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) {
761 TCPH_FLAGS_SET(cseg->tcphdr, TCPH_FLAGS(cseg->tcphdr) | TCP_FIN);
763 old_seg = next;
764 next = next->next;
765 tcp_seg_free(old_seg);
767 if (next &&
768 TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) {
769 /* We need to trim the incoming segment. */
770 cseg->len = (u16_t)(next->tcphdr->seqno - seqno);
771 pbuf_realloc(cseg->p, cseg->len);
774 cseg->next = next;
776 #endif
779 * Called by tcp_process. Checks if the given segment is an ACK for outstanding
780 * data, and if so frees the memory of the buffered data. Next, is places the
781 * segment on any of the receive queues (pcb->recved or pcb->ooseq). If the segment
782 * is buffered, the pbuf is referenced by pbuf_ref so that it will not be freed until
783 * i it has been removed from the buffer.
785 * If the incoming segment constitutes an ACK for a segment that was used for RTT
786 * estimation, the RTT is estimated here as well.
788 * Called from tcp_process().
790 static void
791 tcp_receive(struct tcp_pcb *pcb)
793 struct tcp_seg *next;
794 #if TCP_QUEUE_OOSEQ
795 struct tcp_seg *prev, *cseg;
796 #endif
797 struct pbuf *p;
798 s32_t off;
799 s16_t m;
800 u32_t right_wnd_edge;
801 u16_t new_tot_len;
802 int found_dupack = 0;
804 if (flags & TCP_ACK) {
805 right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2;
807 /* Update window. */
808 if (TCP_SEQ_LT(pcb->snd_wl1, seqno) ||
809 (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) ||
810 (pcb->snd_wl2 == ackno && tcphdr->wnd > pcb->snd_wnd)) {
811 pcb->snd_wnd = tcphdr->wnd;
812 pcb->snd_wl1 = seqno;
813 pcb->snd_wl2 = ackno;
814 if (pcb->snd_wnd > 0 && pcb->persist_backoff > 0) {
815 pcb->persist_backoff = 0;
817 LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"U16_F"\n", pcb->snd_wnd));
818 #if TCP_WND_DEBUG
819 } else {
820 if (pcb->snd_wnd != tcphdr->wnd) {
821 LWIP_DEBUGF(TCP_WND_DEBUG,
822 ("tcp_receive: no window update lastack %"U32_F" ackno %"
823 U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n",
824 pcb->lastack, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2));
826 #endif /* TCP_WND_DEBUG */
829 /* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a
830 * duplicate ack if:
831 * 1) It doesn't ACK new data
832 * 2) length of received packet is zero (i.e. no payload)
833 * 3) the advertised window hasn't changed
834 * 4) There is outstanding unacknowledged data (retransmission timer running)
835 * 5) The ACK is == biggest ACK sequence number so far seen (snd_una)
837 * If it passes all five, should process as a dupack:
838 * a) dupacks < 3: do nothing
839 * b) dupacks == 3: fast retransmit
840 * c) dupacks > 3: increase cwnd
842 * If it only passes 1-3, should reset dupack counter (and add to
843 * stats, which we don't do in lwIP)
845 * If it only passes 1, should reset dupack counter
849 /* Clause 1 */
850 if (TCP_SEQ_LEQ(ackno, pcb->lastack)) {
851 pcb->acked = 0;
852 /* Clause 2 */
853 if (tcplen == 0) {
854 /* Clause 3 */
855 if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge){
856 /* Clause 4 */
857 if (pcb->rtime >= 0) {
858 /* Clause 5 */
859 if (pcb->lastack == ackno) {
860 found_dupack = 1;
861 if (pcb->dupacks + 1 > pcb->dupacks)
862 ++pcb->dupacks;
863 if (pcb->dupacks > 3) {
864 /* Inflate the congestion window, but not if it means that
865 the value overflows. */
866 if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
867 pcb->cwnd += pcb->mss;
869 } else if (pcb->dupacks == 3) {
870 /* Do fast retransmit */
871 tcp_rexmit_fast(pcb);
877 /* If Clause (1) or more is true, but not a duplicate ack, reset
878 * count of consecutive duplicate acks */
879 if (!found_dupack) {
880 pcb->dupacks = 0;
882 } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)){
883 /* We come here when the ACK acknowledges new data. */
885 /* Reset the "IN Fast Retransmit" flag, since we are no longer
886 in fast retransmit. Also reset the congestion window to the
887 slow start threshold. */
888 if (pcb->flags & TF_INFR) {
889 pcb->flags &= ~TF_INFR;
890 pcb->cwnd = pcb->ssthresh;
893 /* Reset the number of retransmissions. */
894 pcb->nrtx = 0;
896 /* Reset the retransmission time-out. */
897 pcb->rto = (pcb->sa >> 3) + pcb->sv;
899 /* Update the send buffer space. Diff between the two can never exceed 64K? */
900 pcb->acked = (u16_t)(ackno - pcb->lastack);
902 pcb->snd_buf += pcb->acked;
904 /* Reset the fast retransmit variables. */
905 pcb->dupacks = 0;
906 pcb->lastack = ackno;
908 /* Update the congestion control variables (cwnd and
909 ssthresh). */
910 if (pcb->state >= ESTABLISHED) {
911 if (pcb->cwnd < pcb->ssthresh) {
912 if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
913 pcb->cwnd += pcb->mss;
915 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"U16_F"\n", pcb->cwnd));
916 } else {
917 u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd);
918 if (new_cwnd > pcb->cwnd) {
919 pcb->cwnd = new_cwnd;
921 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"U16_F"\n", pcb->cwnd));
924 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n",
925 ackno,
926 pcb->unacked != NULL?
927 ntohl(pcb->unacked->tcphdr->seqno): 0,
928 pcb->unacked != NULL?
929 ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0));
931 /* Remove segment from the unacknowledged list if the incoming
932 ACK acknowlegdes them. */
933 while (pcb->unacked != NULL &&
934 TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) +
935 TCP_TCPLEN(pcb->unacked), ackno)) {
936 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unacked\n",
937 ntohl(pcb->unacked->tcphdr->seqno),
938 ntohl(pcb->unacked->tcphdr->seqno) +
939 TCP_TCPLEN(pcb->unacked)));
941 next = pcb->unacked;
942 pcb->unacked = pcb->unacked->next;
944 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen));
945 LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
946 /* Prevent ACK for FIN to generate a sent event */
947 if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) {
948 pcb->acked--;
951 pcb->snd_queuelen -= pbuf_clen(next->p);
952 tcp_seg_free(next);
954 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unacked)\n", (u16_t)pcb->snd_queuelen));
955 if (pcb->snd_queuelen != 0) {
956 LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL ||
957 pcb->unsent != NULL);
961 /* If there's nothing left to acknowledge, stop the retransmit
962 timer, otherwise reset it to start again */
963 if(pcb->unacked == NULL)
964 pcb->rtime = -1;
965 else
966 pcb->rtime = 0;
968 pcb->polltmr = 0;
969 } else {
970 /* Fix bug bug #21582: out of sequence ACK, didn't really ack anything */
971 pcb->acked = 0;
974 /* We go through the ->unsent list to see if any of the segments
975 on the list are acknowledged by the ACK. This may seem
976 strange since an "unsent" segment shouldn't be acked. The
977 rationale is that lwIP puts all outstanding segments on the
978 ->unsent list after a retransmission, so these segments may
979 in fact have been sent once. */
980 while (pcb->unsent != NULL &&
981 TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) +
982 TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) {
983 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n",
984 ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) +
985 TCP_TCPLEN(pcb->unsent)));
987 next = pcb->unsent;
988 pcb->unsent = pcb->unsent->next;
989 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen));
990 LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
991 /* Prevent ACK for FIN to generate a sent event */
992 if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) {
993 pcb->acked--;
995 pcb->snd_queuelen -= pbuf_clen(next->p);
996 tcp_seg_free(next);
997 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unsent)\n", (u16_t)pcb->snd_queuelen));
998 if (pcb->snd_queuelen != 0) {
999 LWIP_ASSERT("tcp_receive: valid queue length",
1000 pcb->unacked != NULL || pcb->unsent != NULL);
1003 /* End of ACK for new data processing. */
1005 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %"U32_F" rtseq %"U32_F" ackno %"U32_F"\n",
1006 pcb->rttest, pcb->rtseq, ackno));
1008 /* RTT estimation calculations. This is done by checking if the
1009 incoming segment acknowledges the segment we use to take a
1010 round-trip time measurement. */
1011 if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) {
1012 /* diff between this shouldn't exceed 32K since this are tcp timer ticks
1013 and a round-trip shouldn't be that long... */
1014 m = (s16_t)(tcp_ticks - pcb->rttest);
1016 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %"U16_F" ticks (%"U16_F" msec).\n",
1017 m, m * TCP_SLOW_INTERVAL));
1019 /* This is taken directly from VJs original code in his paper */
1020 m = m - (pcb->sa >> 3);
1021 pcb->sa += m;
1022 if (m < 0) {
1023 m = -m;
1025 m = m - (pcb->sv >> 2);
1026 pcb->sv += m;
1027 pcb->rto = (pcb->sa >> 3) + pcb->sv;
1029 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %"U16_F" (%"U16_F" milliseconds)\n",
1030 pcb->rto, pcb->rto * TCP_SLOW_INTERVAL));
1032 pcb->rttest = 0;
1036 /* If the incoming segment contains data, we must process it
1037 further. */
1038 if (tcplen > 0) {
1039 /* This code basically does three things:
1041 +) If the incoming segment contains data that is the next
1042 in-sequence data, this data is passed to the application. This
1043 might involve trimming the first edge of the data. The rcv_nxt
1044 variable and the advertised window are adjusted.
1046 +) If the incoming segment has data that is above the next
1047 sequence number expected (->rcv_nxt), the segment is placed on
1048 the ->ooseq queue. This is done by finding the appropriate
1049 place in the ->ooseq queue (which is ordered by sequence
1050 number) and trim the segment in both ends if needed. An
1051 immediate ACK is sent to indicate that we received an
1052 out-of-sequence segment.
1054 +) Finally, we check if the first segment on the ->ooseq queue
1055 now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If
1056 rcv_nxt > ooseq->seqno, we must trim the first edge of the
1057 segment on ->ooseq before we adjust rcv_nxt. The data in the
1058 segments that are now on sequence are chained onto the
1059 incoming segment so that we only need to call the application
1060 once.
1063 /* First, we check if we must trim the first edge. We have to do
1064 this if the sequence number of the incoming segment is less
1065 than rcv_nxt, and the sequence number plus the length of the
1066 segment is larger than rcv_nxt. */
1067 /* if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){
1068 if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/
1069 if (TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno + 1, seqno + tcplen - 1)){
1070 /* Trimming the first edge is done by pushing the payload
1071 pointer in the pbuf downwards. This is somewhat tricky since
1072 we do not want to discard the full contents of the pbuf up to
1073 the new starting point of the data since we have to keep the
1074 TCP header which is present in the first pbuf in the chain.
1076 What is done is really quite a nasty hack: the first pbuf in
1077 the pbuf chain is pointed to by inseg.p. Since we need to be
1078 able to deallocate the whole pbuf, we cannot change this
1079 inseg.p pointer to point to any of the later pbufs in the
1080 chain. Instead, we point the ->payload pointer in the first
1081 pbuf to data in one of the later pbufs. We also set the
1082 inseg.data pointer to point to the right place. This way, the
1083 ->p pointer will still point to the first pbuf, but the
1084 ->p->payload pointer will point to data in another pbuf.
1086 After we are done with adjusting the pbuf pointers we must
1087 adjust the ->data pointer in the seg and the segment
1088 length.*/
1090 off = pcb->rcv_nxt - seqno;
1091 p = inseg.p;
1092 LWIP_ASSERT("inseg.p != NULL", inseg.p);
1093 LWIP_ASSERT("insane offset!", (off < 0x7fff));
1094 if (inseg.p->len < off) {
1095 LWIP_ASSERT("pbuf too short!", (((s32_t)inseg.p->tot_len) >= off));
1096 new_tot_len = (u16_t)(inseg.p->tot_len - off);
1097 while (p->len < off) {
1098 off -= p->len;
1099 /* KJM following line changed (with addition of new_tot_len var)
1100 to fix bug #9076
1101 inseg.p->tot_len -= p->len; */
1102 p->tot_len = new_tot_len;
1103 p->len = 0;
1104 p = p->next;
1106 if(pbuf_header(p, (s16_t)-off)) {
1107 /* Do we need to cope with this failing? Assert for now */
1108 LWIP_ASSERT("pbuf_header failed", 0);
1110 } else {
1111 if(pbuf_header(inseg.p, (s16_t)-off)) {
1112 /* Do we need to cope with this failing? Assert for now */
1113 LWIP_ASSERT("pbuf_header failed", 0);
1116 /* KJM following line changed to use p->payload rather than inseg->p->payload
1117 to fix bug #9076 */
1118 inseg.dataptr = p->payload;
1119 inseg.len -= (u16_t)(pcb->rcv_nxt - seqno);
1120 inseg.tcphdr->seqno = seqno = pcb->rcv_nxt;
1122 else {
1123 if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){
1124 /* the whole segment is < rcv_nxt */
1125 /* must be a duplicate of a packet that has already been correctly handled */
1127 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno));
1128 tcp_ack_now(pcb);
1132 /* The sequence number must be within the window (above rcv_nxt
1133 and below rcv_nxt + rcv_wnd) in order to be further
1134 processed. */
1135 if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
1136 pcb->rcv_nxt + pcb->rcv_wnd - 1)){
1137 if (pcb->rcv_nxt == seqno) {
1138 /* The incoming segment is the next in sequence. We check if
1139 we have to trim the end of the segment and update rcv_nxt
1140 and pass the data to the application. */
1141 tcplen = TCP_TCPLEN(&inseg);
1143 if (tcplen > pcb->rcv_wnd) {
1144 LWIP_DEBUGF(TCP_INPUT_DEBUG,
1145 ("tcp_receive: other end overran receive window"
1146 "seqno %"U32_F" len %"U32_F" right edge %"U32_F"\n",
1147 seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd));
1148 if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
1149 /* Must remove the FIN from the header as we're trimming
1150 * that byte of sequence-space from the packet */
1151 TCPH_FLAGS_SET(inseg.tcphdr, TCPH_FLAGS(inseg.tcphdr) &~ TCP_FIN);
1153 /* Adjust length of segment to fit in the window. */
1154 inseg.len = pcb->rcv_wnd;
1155 if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
1156 inseg.len -= 1;
1158 pbuf_realloc(inseg.p, inseg.len);
1159 tcplen = TCP_TCPLEN(&inseg);
1160 LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n",
1161 (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd));
1163 #if TCP_QUEUE_OOSEQ
1164 if (pcb->ooseq != NULL) {
1165 if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
1166 LWIP_DEBUGF(TCP_INPUT_DEBUG,
1167 ("tcp_receive: received in-order FIN, binning ooseq queue\n"));
1168 /* Received in-order FIN means anything that was received
1169 * out of order must now have been received in-order, so
1170 * bin the ooseq queue
1171 * rcv_nxt
1172 * . |--ooseq--|
1173 * .==seg============|FIN
1175 while (pcb->ooseq != NULL) {
1176 struct tcp_seg *old_ooseq = pcb->ooseq;
1177 pcb->ooseq = pcb->ooseq->next;
1178 tcp_seg_free(old_ooseq);
1181 else {
1182 struct tcp_seg* next = pcb->ooseq;
1183 struct tcp_seg *old_seg;
1184 /* rcv_nxt
1185 * . |--ooseq--|
1186 * .==seg============|
1188 while (next &&
1189 TCP_SEQ_GEQ(seqno + tcplen,
1190 next->tcphdr->seqno + next->len)) {
1191 /* inseg doesn't have FIN (already processed) */
1192 if (TCPH_FLAGS(next->tcphdr) & TCP_FIN &&
1193 (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) {
1194 TCPH_FLAGS_SET(inseg.tcphdr,
1195 TCPH_FLAGS(inseg.tcphdr) | TCP_FIN);
1196 tcplen = TCP_TCPLEN(&inseg);
1198 old_seg = next;
1199 next = next->next;
1200 tcp_seg_free(old_seg);
1202 /* rcv_nxt
1203 * . |--ooseq--|
1204 * .==seg============|
1206 if (next &&
1207 TCP_SEQ_GT(seqno + tcplen,
1208 next->tcphdr->seqno)) {
1209 /* FIN in inseg already handled by dropping whole ooseq queue */
1210 inseg.len = (u16_t)(pcb->ooseq->tcphdr->seqno - seqno);
1211 if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
1212 inseg.len -= 1;
1214 pbuf_realloc(inseg.p, inseg.len);
1215 tcplen = TCP_TCPLEN(&inseg);
1216 LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n",
1217 (seqno + tcplen) == pcb->ooseq->tcphdr->seqno);
1219 pcb->ooseq = next;
1222 #endif /* TCP_QUEUE_OOSEQ */
1224 pcb->rcv_nxt = seqno + tcplen;
1226 /* Update the receiver's (our) window. */
1227 LWIP_ASSERT("tcp_receive: tcplen > rcv_wnd\n", pcb->rcv_wnd >= tcplen);
1228 pcb->rcv_wnd -= tcplen;
1230 tcp_update_rcv_ann_wnd(pcb);
1232 /* If there is data in the segment, we make preparations to
1233 pass this up to the application. The ->recv_data variable
1234 is used for holding the pbuf that goes to the
1235 application. The code for reassembling out-of-sequence data
1236 chains its data on this pbuf as well.
1238 If the segment was a FIN, we set the TF_GOT_FIN flag that will
1239 be used to indicate to the application that the remote side has
1240 closed its end of the connection. */
1241 if (inseg.p->tot_len > 0) {
1242 recv_data = inseg.p;
1243 /* Since this pbuf now is the responsibility of the
1244 application, we delete our reference to it so that we won't
1245 (mistakingly) deallocate it. */
1246 inseg.p = NULL;
1248 if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
1249 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n"));
1250 recv_flags |= TF_GOT_FIN;
1253 #if TCP_QUEUE_OOSEQ
1254 /* We now check if we have segments on the ->ooseq queue that
1255 is now in sequence. */
1256 while (pcb->ooseq != NULL &&
1257 pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) {
1259 cseg = pcb->ooseq;
1260 seqno = pcb->ooseq->tcphdr->seqno;
1262 pcb->rcv_nxt += TCP_TCPLEN(cseg);
1263 LWIP_ASSERT("tcp_receive: ooseq tcplen > rcv_wnd\n",
1264 pcb->rcv_wnd >= TCP_TCPLEN(cseg));
1265 pcb->rcv_wnd -= TCP_TCPLEN(cseg);
1267 tcp_update_rcv_ann_wnd(pcb);
1269 if (cseg->p->tot_len > 0) {
1270 /* Chain this pbuf onto the pbuf that we will pass to
1271 the application. */
1272 if (recv_data) {
1273 pbuf_cat(recv_data, cseg->p);
1274 } else {
1275 recv_data = cseg->p;
1277 cseg->p = NULL;
1279 if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
1280 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n"));
1281 recv_flags |= TF_GOT_FIN;
1282 if (pcb->state == ESTABLISHED) { /* force passive close or we can move to active close */
1283 pcb->state = CLOSE_WAIT;
1287 pcb->ooseq = cseg->next;
1288 tcp_seg_free(cseg);
1290 #endif /* TCP_QUEUE_OOSEQ */
1293 /* Acknowledge the segment(s). */
1294 tcp_ack(pcb);
1296 } else {
1297 /* We get here if the incoming segment is out-of-sequence. */
1298 tcp_send_empty_ack(pcb);
1299 #if TCP_QUEUE_OOSEQ
1300 /* We queue the segment on the ->ooseq queue. */
1301 if (pcb->ooseq == NULL) {
1302 pcb->ooseq = tcp_seg_copy(&inseg);
1303 } else {
1304 /* If the queue is not empty, we walk through the queue and
1305 try to find a place where the sequence number of the
1306 incoming segment is between the sequence numbers of the
1307 previous and the next segment on the ->ooseq queue. That is
1308 the place where we put the incoming segment. If needed, we
1309 trim the second edges of the previous and the incoming
1310 segment so that it will fit into the sequence.
1312 If the incoming segment has the same sequence number as a
1313 segment on the ->ooseq queue, we discard the segment that
1314 contains less data. */
1316 prev = NULL;
1317 for(next = pcb->ooseq; next != NULL; next = next->next) {
1318 if (seqno == next->tcphdr->seqno) {
1319 /* The sequence number of the incoming segment is the
1320 same as the sequence number of the segment on
1321 ->ooseq. We check the lengths to see which one to
1322 discard. */
1323 if (inseg.len > next->len) {
1324 /* The incoming segment is larger than the old
1325 segment. We replace some segments with the new
1326 one. */
1327 cseg = tcp_seg_copy(&inseg);
1328 if (cseg != NULL) {
1329 if (prev != NULL) {
1330 prev->next = cseg;
1331 } else {
1332 pcb->ooseq = cseg;
1334 tcp_oos_insert_segment(cseg, next);
1336 break;
1337 } else {
1338 /* Either the lenghts are the same or the incoming
1339 segment was smaller than the old one; in either
1340 case, we ditch the incoming segment. */
1341 break;
1343 } else {
1344 if (prev == NULL) {
1345 if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {
1346 /* The sequence number of the incoming segment is lower
1347 than the sequence number of the first segment on the
1348 queue. We put the incoming segment first on the
1349 queue. */
1350 cseg = tcp_seg_copy(&inseg);
1351 if (cseg != NULL) {
1352 pcb->ooseq = cseg;
1353 tcp_oos_insert_segment(cseg, next);
1355 break;
1357 } else {
1358 /*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) &&
1359 TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/
1360 if (TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)) {
1361 /* The sequence number of the incoming segment is in
1362 between the sequence numbers of the previous and
1363 the next segment on ->ooseq. We trim trim the previous
1364 segment, delete next segments that included in received segment
1365 and trim received, if needed. */
1366 cseg = tcp_seg_copy(&inseg);
1367 if (cseg != NULL) {
1368 if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) {
1369 /* We need to trim the prev segment. */
1370 prev->len = (u16_t)(seqno - prev->tcphdr->seqno);
1371 pbuf_realloc(prev->p, prev->len);
1373 prev->next = cseg;
1374 tcp_oos_insert_segment(cseg, next);
1376 break;
1379 /* If the "next" segment is the last segment on the
1380 ooseq queue, we add the incoming segment to the end
1381 of the list. */
1382 if (next->next == NULL &&
1383 TCP_SEQ_GT(seqno, next->tcphdr->seqno)) {
1384 if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) {
1385 /* segment "next" already contains all data */
1386 break;
1388 next->next = tcp_seg_copy(&inseg);
1389 if (next->next != NULL) {
1390 if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) {
1391 /* We need to trim the last segment. */
1392 next->len = (u16_t)(seqno - next->tcphdr->seqno);
1393 pbuf_realloc(next->p, next->len);
1396 break;
1399 prev = next;
1402 #endif /* TCP_QUEUE_OOSEQ */
1405 } else {
1406 /* The incoming segment is not withing the window. */
1407 tcp_send_empty_ack(pcb);
1409 } else {
1410 /* Segments with length 0 is taken care of here. Segments that
1411 fall out of the window are ACKed. */
1412 /*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) ||
1413 TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/
1414 if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){
1415 tcp_ack_now(pcb);
1421 * Parses the options contained in the incoming segment.
1423 * Called from tcp_listen_input() and tcp_process().
1424 * Currently, only the MSS option is supported!
1426 * @param pcb the tcp_pcb for which a segment arrived
1428 static void
1429 tcp_parseopt(struct tcp_pcb *pcb)
1431 u16_t c, max_c;
1432 u16_t mss;
1433 u8_t *opts, opt;
1434 #if LWIP_TCP_TIMESTAMPS
1435 u32_t tsval;
1436 #endif
1438 opts = (u8_t *)tcphdr + TCP_HLEN;
1440 /* Parse the TCP MSS option, if present. */
1441 if(TCPH_HDRLEN(tcphdr) > 0x5) {
1442 max_c = (TCPH_HDRLEN(tcphdr) - 5) << 2;
1443 for (c = 0; c < max_c; ) {
1444 opt = opts[c];
1445 switch (opt) {
1446 case 0x00:
1447 /* End of options. */
1448 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: EOL\n"));
1449 return;
1450 case 0x01:
1451 /* NOP option. */
1452 ++c;
1453 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: NOP\n"));
1454 break;
1455 case 0x02:
1456 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: MSS\n"));
1457 if (opts[c + 1] != 0x04 || c + 0x04 > max_c) {
1458 /* Bad length */
1459 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
1460 return;
1462 /* An MSS option with the right option length. */
1463 mss = (opts[c + 2] << 8) | opts[c + 3];
1464 /* Limit the mss to the configured TCP_MSS and prevent division by zero */
1465 pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss;
1466 /* Advance to next option */
1467 c += 0x04;
1468 break;
1469 #if LWIP_TCP_TIMESTAMPS
1470 case 0x08:
1471 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: TS\n"));
1472 if (opts[c + 1] != 0x0A || c + 0x0A > max_c) {
1473 /* Bad length */
1474 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
1475 return;
1477 /* TCP timestamp option with valid length */
1478 tsval = (opts[c+2]) | (opts[c+3] << 8) |
1479 (opts[c+4] << 16) | (opts[c+5] << 24);
1480 if (flags & TCP_SYN) {
1481 pcb->ts_recent = ntohl(tsval);
1482 pcb->flags |= TF_TIMESTAMP;
1483 } else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno+tcplen)) {
1484 pcb->ts_recent = ntohl(tsval);
1486 /* Advance to next option */
1487 c += 0x0A;
1488 break;
1489 #endif
1490 default:
1491 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: other\n"));
1492 if (opts[c + 1] == 0) {
1493 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
1494 /* If the length field is zero, the options are malformed
1495 and we don't process them further. */
1496 return;
1498 /* All other options have a length field, so that we easily
1499 can skip past them. */
1500 c += opts[c + 1];
1506 #endif /* LWIP_TCP */