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).
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
38 * This file is part of the lwIP TCP/IP stack.
40 * Author: Adam Dunkels <adam@sics.se>
46 #if LWIP_TCP /* don't build if not configured for use in lwipopts.h */
48 #include "lwip/tcp_impl.h"
50 #include "lwip/ip_addr.h"
51 #include "lwip/netif.h"
53 #include "lwip/memp.h"
54 #include "lwip/inet_chksum.h"
55 #include "lwip/stats.h"
56 #include "lwip/snmp.h"
57 #include "arch/perf.h"
59 #include "lwip/ip6_addr.h"
60 #include "lwip/inet_chksum.h"
61 #if LWIP_ND6_TCP_REACHABILITY_HINTS
63 #endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */
65 /* These variables are global to all functions involved in the input
66 processing of TCP segments. They are set by the tcp_input()
68 static struct tcp_seg inseg;
69 static struct tcp_hdr *tcphdr;
70 static u32_t seqno, ackno;
74 static u8_t recv_flags;
75 static struct pbuf *recv_data;
77 struct tcp_pcb *tcp_input_pcb;
79 /* Forward declarations. */
80 static err_t tcp_process(struct tcp_pcb *pcb);
81 static void tcp_receive(struct tcp_pcb *pcb);
82 static void tcp_parseopt(struct tcp_pcb *pcb);
84 static err_t tcp_listen_input(struct tcp_pcb_listen *pcb);
85 static err_t tcp_timewait_input(struct tcp_pcb *pcb);
88 * The initial input processing of TCP. It verifies the TCP header, demultiplexes
89 * the segment between the PCBs and passes it on to tcp_process(), which implements
90 * the TCP finite state machine. This function is called by the IP layer (in
93 * @param p received TCP segment to process (p->payload pointing to the TCP header)
94 * @param inp network interface on which this segment was received
97 tcp_input(struct pbuf *p, struct netif *inp)
99 struct tcp_pcb *pcb, *prev;
100 struct tcp_pcb_listen *lpcb;
102 struct tcp_pcb *lpcb_prev = NULL;
103 struct tcp_pcb_listen *lpcb_any = NULL;
104 #endif /* SO_REUSE */
107 #if CHECKSUM_CHECK_TCP
109 #endif /* CHECKSUM_CHECK_TCP */
113 TCP_STATS_INC(tcp.recv);
114 snmp_inc_tcpinsegs();
116 tcphdr = (struct tcp_hdr *)p->payload;
119 tcp_debug_print(tcphdr);
122 /* Check that TCP header fits in payload */
123 if (p->len < sizeof(struct tcp_hdr)) {
124 /* drop short packets */
125 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len));
126 TCP_STATS_INC(tcp.lenerr);
130 /* Don't even process incoming broadcasts/multicasts. */
131 if ((!ip_current_is_v6() && ip_addr_isbroadcast(ip_current_dest_addr(), inp)) ||
132 ipX_addr_ismulticast(ip_current_is_v6(), ipX_current_dest_addr())) {
133 TCP_STATS_INC(tcp.proterr);
137 #if CHECKSUM_CHECK_TCP
138 /* Verify TCP checksum. */
139 chksum = ipX_chksum_pseudo(ip_current_is_v6(), p, IP_PROTO_TCP, p->tot_len,
140 ipX_current_src_addr(), ipX_current_dest_addr());
142 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n",
144 tcp_debug_print(tcphdr);
145 TCP_STATS_INC(tcp.chkerr);
148 #endif /* CHECKSUM_CHECK_TCP */
150 /* Move the payload pointer in the pbuf so that it points to the
151 TCP data instead of the TCP header. */
152 hdrlen = TCPH_HDRLEN(tcphdr);
153 if(pbuf_header(p, -(hdrlen * 4))){
154 /* drop short packets */
155 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet\n"));
156 TCP_STATS_INC(tcp.lenerr);
160 /* Convert fields in TCP header to host byte order. */
161 tcphdr->src = ntohs(tcphdr->src);
162 tcphdr->dest = ntohs(tcphdr->dest);
163 seqno = tcphdr->seqno = ntohl(tcphdr->seqno);
164 ackno = tcphdr->ackno = ntohl(tcphdr->ackno);
165 tcphdr->wnd = ntohs(tcphdr->wnd);
167 flags = TCPH_FLAGS(tcphdr);
168 tcplen = p->tot_len + ((flags & (TCP_FIN | TCP_SYN)) ? 1 : 0);
170 /* Demultiplex an incoming segment. First, we check if it is destined
171 for an active connection. */
175 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
176 LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED);
177 LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
178 LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
179 if (pcb->remote_port == tcphdr->src &&
180 pcb->local_port == tcphdr->dest &&
181 IP_PCB_IPVER_INPUT_MATCH(pcb) &&
182 ipX_addr_cmp(ip_current_is_v6(), &pcb->remote_ip, ipX_current_src_addr()) &&
183 ipX_addr_cmp(ip_current_is_v6(),&pcb->local_ip, ipX_current_dest_addr())) {
184 /* Move this PCB to the front of the list so that subsequent
185 lookups will be faster (we exploit locality in TCP segment
187 LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb);
189 prev->next = pcb->next;
190 pcb->next = tcp_active_pcbs;
191 tcp_active_pcbs = pcb;
193 LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb);
200 /* If it did not go to an active connection, we check the connections
201 in the TIME-WAIT state. */
202 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
203 LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
204 if (pcb->remote_port == tcphdr->src &&
205 pcb->local_port == tcphdr->dest &&
206 IP_PCB_IPVER_INPUT_MATCH(pcb) &&
207 ipX_addr_cmp(ip_current_is_v6(), &pcb->remote_ip, ipX_current_src_addr()) &&
208 ipX_addr_cmp(ip_current_is_v6(),&pcb->local_ip, ipX_current_dest_addr())) {
209 /* We don't really care enough to move this PCB to the front
210 of the list since we are not very likely to receive that
211 many segments for connections in TIME-WAIT. */
212 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n"));
213 tcp_timewait_input(pcb);
219 /* Finally, if we still did not get a match, we check all PCBs that
220 are LISTENing for incoming connections. */
222 for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
223 if (lpcb->local_port == tcphdr->dest) {
225 if (lpcb->accept_any_ip_version) {
226 /* found an ANY-match */
232 #endif /* SO_REUSE */
234 #endif /* LWIP_IPV6 */
235 if (IP_PCB_IPVER_INPUT_MATCH(lpcb)) {
236 if (ipX_addr_cmp(ip_current_is_v6(), &lpcb->local_ip, ipX_current_dest_addr())) {
237 /* found an exact match */
239 } else if (ipX_addr_isany(ip_current_is_v6(), &lpcb->local_ip)) {
240 /* found an ANY-match */
246 #endif /* SO_REUSE */
250 prev = (struct tcp_pcb *)lpcb;
253 /* first try specific local IP */
255 /* only pass to ANY if no specific local IP has been found */
259 #endif /* SO_REUSE */
261 /* Move this PCB to the front of the list so that subsequent
262 lookups will be faster (we exploit locality in TCP segment
265 ((struct tcp_pcb_listen *)prev)->next = lpcb->next;
266 /* our successor is the remainder of the listening list */
267 lpcb->next = tcp_listen_pcbs.listen_pcbs;
268 /* put this listening pcb at the head of the listening list */
269 tcp_listen_pcbs.listen_pcbs = lpcb;
272 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n"));
273 tcp_listen_input(lpcb);
280 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags "));
281 tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
282 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n"));
283 #endif /* TCP_INPUT_DEBUG */
287 /* The incoming segment belongs to a connection. */
290 tcp_debug_print_state(pcb->state);
291 #endif /* TCP_DEBUG */
292 #endif /* TCP_INPUT_DEBUG */
294 /* Set up a tcp_seg structure. */
296 inseg.len = p->tot_len;
298 inseg.tcphdr = tcphdr;
303 /* If there is data which was previously "refused" by upper layer */
304 if (pcb->refused_data != NULL) {
305 /* Notify again application with data previously received. */
306 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: notify kept packet\n"));
307 TCP_EVENT_RECV(pcb, pcb->refused_data, ERR_OK, err);
309 pcb->refused_data = NULL;
310 } else if ((err == ERR_ABRT) || (tcplen > 0)) {
311 /* if err == ERR_ABRT, 'pcb' is already deallocated */
312 /* Drop incoming packets because pcb is "full" (only if the incoming
313 segment contains data). */
314 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n"));
319 err = tcp_process(pcb);
320 /* A return value of ERR_ABRT means that tcp_abort() was called
321 and that the pcb has been freed. If so, we don't do anything. */
322 if (err != ERR_ABRT) {
323 if (recv_flags & TF_RESET) {
324 /* TF_RESET means that the connection was reset by the other
325 end. We then call the error callback to inform the
326 application that the connection is dead before we
327 deallocate the PCB. */
328 TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST);
329 tcp_pcb_remove(&tcp_active_pcbs, pcb);
330 memp_free(MEMP_TCP_PCB, pcb);
331 } else if (recv_flags & TF_CLOSED) {
332 /* The connection has been closed and we will deallocate the
334 tcp_pcb_remove(&tcp_active_pcbs, pcb);
335 memp_free(MEMP_TCP_PCB, pcb);
338 /* If the application has registered a "sent" function to be
339 called when new send buffer space is available, we call it
341 if (pcb->acked > 0) {
342 TCP_EVENT_SENT(pcb, pcb->acked, err);
343 if (err == ERR_ABRT) {
348 if (recv_data != NULL) {
349 LWIP_ASSERT("pcb->refused_data == NULL", pcb->refused_data == NULL);
350 if (pcb->flags & TF_RXCLOSED) {
351 /* received data although already closed -> abort (send RST) to
352 notify the remote host that not all data has been processed */
353 pbuf_free(recv_data);
357 if (flags & TCP_PSH) {
358 recv_data->flags |= PBUF_FLAG_PUSH;
361 /* Notify application that data has been received. */
362 TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err);
363 if (err == ERR_ABRT) {
367 /* If the upper layer can't receive this data, store it */
369 pcb->refused_data = recv_data;
370 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: keep incoming packet, because pcb is \"full\"\n"));
374 /* If a FIN segment was received, we call the callback
375 function with a NULL buffer to indicate EOF. */
376 if (recv_flags & TF_GOT_FIN) {
377 /* correct rcv_wnd as the application won't call tcp_recved()
378 for the FIN's seqno */
379 if (pcb->rcv_wnd != TCP_WND) {
382 TCP_EVENT_CLOSED(pcb, err);
383 if (err == ERR_ABRT) {
388 tcp_input_pcb = NULL;
389 /* Try to send something out. */
393 tcp_debug_print_state(pcb->state);
394 #endif /* TCP_DEBUG */
395 #endif /* TCP_INPUT_DEBUG */
398 /* Jump target if pcb has been aborted in a callback (by calling tcp_abort()).
399 Below this line, 'pcb' may not be dereferenced! */
401 tcp_input_pcb = NULL;
404 /* give up our reference to inseg.p */
412 /* If no matching PCB was found, send a TCP RST (reset) to the
414 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n"));
415 if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) {
416 TCP_STATS_INC(tcp.proterr);
417 TCP_STATS_INC(tcp.drop);
418 tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(),
419 ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6());
424 LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());
425 PERF_STOP("tcp_input");
428 TCP_STATS_INC(tcp.drop);
429 snmp_inc_tcpinerrs();
434 * Called by tcp_input() when a segment arrives for a listening
435 * connection (from tcp_input()).
437 * @param pcb the tcp_pcb_listen for which a segment arrived
438 * @return ERR_OK if the segment was processed
439 * another err_t on error
441 * @note the return value is not (yet?) used in tcp_input()
442 * @note the segment which arrived is saved in global variables, therefore only the pcb
443 * involved is passed as a parameter to this function
446 tcp_listen_input(struct tcp_pcb_listen *pcb)
448 struct tcp_pcb *npcb;
451 /* In the LISTEN state, we check for incoming SYN segments,
452 creates a new PCB, and responds with a SYN|ACK. */
453 if (flags & TCP_ACK) {
454 /* For incoming segments with the ACK flag set, respond with a
456 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n"));
457 tcp_rst(ackno + 1, seqno + tcplen, ipX_current_dest_addr(),
458 ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6());
459 } else if (flags & TCP_SYN) {
460 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest));
461 #if TCP_LISTEN_BACKLOG
462 if (pcb->accepts_pending >= pcb->backlog) {
463 LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: listen backlog exceeded for port %"U16_F"\n", tcphdr->dest));
466 #endif /* TCP_LISTEN_BACKLOG */
467 npcb = tcp_alloc(pcb->prio);
468 /* If a new PCB could not be created (probably due to lack of memory),
469 we don't do anything, but rely on the sender will retransmit the
470 SYN at a time when we have more memory available. */
472 LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n"));
473 TCP_STATS_INC(tcp.memerr);
476 #if TCP_LISTEN_BACKLOG
477 pcb->accepts_pending++;
478 #endif /* TCP_LISTEN_BACKLOG */
479 /* Set up the new PCB. */
481 PCB_ISIPV6(npcb) = ip_current_is_v6();
482 #endif /* LWIP_IPV6 */
483 ipX_addr_copy(ip_current_is_v6(), npcb->local_ip, *ipX_current_dest_addr());
484 ipX_addr_copy(ip_current_is_v6(), npcb->remote_ip, *ipX_current_src_addr());
485 npcb->local_port = pcb->local_port;
486 npcb->remote_port = tcphdr->src;
487 npcb->state = SYN_RCVD;
488 npcb->rcv_nxt = seqno + 1;
489 npcb->rcv_ann_right_edge = npcb->rcv_nxt;
490 npcb->snd_wnd = tcphdr->wnd;
491 npcb->ssthresh = npcb->snd_wnd;
492 npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */
493 npcb->callback_arg = pcb->callback_arg;
494 #if LWIP_CALLBACK_API
495 npcb->accept = pcb->accept;
496 #endif /* LWIP_CALLBACK_API */
497 /* inherit socket options */
498 npcb->so_options = pcb->so_options & SOF_INHERITED;
499 /* Register the new PCB so that we can begin receiving segments
501 TCP_REG(&tcp_active_pcbs, npcb);
503 /* Parse any options in the SYN. */
505 #if TCP_CALCULATE_EFF_SEND_MSS
506 npcb->mss = tcp_eff_send_mss(npcb->mss, &npcb->local_ip,
507 &npcb->remote_ip, PCB_ISIPV6(npcb));
508 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
510 snmp_inc_tcppassiveopens();
512 /* Send a SYN|ACK together with the MSS option. */
513 rc = tcp_enqueue_flags(npcb, TCP_SYN | TCP_ACK);
515 tcp_abandon(npcb, 0);
518 return tcp_output(npcb);
524 * Called by tcp_input() when a segment arrives for a connection in
527 * @param pcb the tcp_pcb for which a segment arrived
529 * @note the segment which arrived is saved in global variables, therefore only the pcb
530 * involved is passed as a parameter to this function
533 tcp_timewait_input(struct tcp_pcb *pcb)
535 /* RFC 1337: in TIME_WAIT, ignore RST and ACK FINs + any 'acceptable' segments */
536 /* RFC 793 3.9 Event Processing - Segment Arrives:
537 * - first check sequence number - we skip that one in TIME_WAIT (always
538 * acceptable since we only send ACKs)
539 * - second check the RST bit (... return) */
540 if (flags & TCP_RST) {
543 /* - fourth, check the SYN bit, */
544 if (flags & TCP_SYN) {
545 /* If an incoming segment is not acceptable, an acknowledgment
546 should be sent in reply */
547 if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) {
548 /* If the SYN is in the window it is an error, send a reset */
549 tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(),
550 ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6());
553 } else if (flags & TCP_FIN) {
554 /* - eighth, check the FIN bit: Remain in the TIME-WAIT state.
555 Restart the 2 MSL time-wait timeout.*/
556 pcb->tmr = tcp_ticks;
560 /* Acknowledge data, FIN or out-of-window SYN */
561 pcb->flags |= TF_ACK_NOW;
562 return tcp_output(pcb);
568 * Implements the TCP state machine. Called by tcp_input. In some
569 * states tcp_receive() is called to receive data. The tcp_seg
570 * argument will be freed by the caller (tcp_input()) unless the
571 * recv_data pointer in the pcb is set.
573 * @param pcb the tcp_pcb for which a segment arrived
575 * @note the segment which arrived is saved in global variables, therefore only the pcb
576 * involved is passed as a parameter to this function
579 tcp_process(struct tcp_pcb *pcb)
581 struct tcp_seg *rseg;
587 /* Process incoming RST segments. */
588 if (flags & TCP_RST) {
589 /* First, determine if the reset is acceptable. */
590 if (pcb->state == SYN_SENT) {
591 if (ackno == pcb->snd_nxt) {
595 if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
596 pcb->rcv_nxt+pcb->rcv_wnd)) {
602 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n"));
603 LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED);
604 recv_flags |= TF_RESET;
605 pcb->flags &= ~TF_ACK_DELAY;
608 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n",
609 seqno, pcb->rcv_nxt));
610 LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n",
611 seqno, pcb->rcv_nxt));
616 if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) {
617 /* Cope with new connection attempt after remote end crashed */
622 if ((pcb->flags & TF_RXCLOSED) == 0) {
623 /* Update the PCB (in)activity timer unless rx is closed (see tcp_shutdown) */
624 pcb->tmr = tcp_ticks;
626 pcb->keep_cnt_sent = 0;
630 /* Do different things depending on the TCP state. */
631 switch (pcb->state) {
633 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno,
634 pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno)));
635 /* received SYN ACK with expected sequence number? */
636 if ((flags & TCP_ACK) && (flags & TCP_SYN)
637 && ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) {
639 pcb->rcv_nxt = seqno + 1;
640 pcb->rcv_ann_right_edge = pcb->rcv_nxt;
641 pcb->lastack = ackno;
642 pcb->snd_wnd = tcphdr->wnd;
643 pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */
644 pcb->state = ESTABLISHED;
646 #if TCP_CALCULATE_EFF_SEND_MSS
647 pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip,
649 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
651 /* Set ssthresh again after changing pcb->mss (already set in tcp_connect
652 * but for the default value of pcb->mss) */
653 pcb->ssthresh = pcb->mss * 10;
655 pcb->cwnd = ((pcb->cwnd == 1) ? (pcb->mss * 2) : pcb->mss);
656 LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0));
658 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"U16_F"\n", (u16_t)pcb->snd_queuelen));
660 pcb->unacked = rseg->next;
662 /* If there's nothing left to acknowledge, stop the retransmit
663 timer, otherwise reset it to start again */
664 if(pcb->unacked == NULL)
673 /* Call the user specified function to call when sucessfully
675 TCP_EVENT_CONNECTED(pcb, ERR_OK, err);
676 if (err == ERR_ABRT) {
681 /* received ACK? possibly a half-open connection */
682 else if (flags & TCP_ACK) {
683 /* send a RST to bring the other side in a non-synchronized state. */
684 tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(),
685 ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6());
689 if (flags & TCP_ACK) {
690 /* expected ACK number? */
691 if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) {
693 pcb->state = ESTABLISHED;
694 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
695 #if LWIP_CALLBACK_API
696 LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL);
698 /* Call the accept function. */
699 TCP_EVENT_ACCEPT(pcb, ERR_OK, err);
701 /* If the accept function returns with an error, we abort
703 /* Already aborted? */
704 if (err != ERR_ABRT) {
709 old_cwnd = pcb->cwnd;
710 /* If there was any data contained within this ACK,
711 * we'd better pass it on to the application as well. */
714 /* Prevent ACK for SYN to generate a sent event */
715 if (pcb->acked != 0) {
719 pcb->cwnd = ((old_cwnd == 1) ? (pcb->mss * 2) : pcb->mss);
721 if (recv_flags & TF_GOT_FIN) {
723 pcb->state = CLOSE_WAIT;
726 /* incorrect ACK number, send RST */
727 tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(),
728 ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6());
730 } else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) {
731 /* Looks like another copy of the SYN - retransmit our SYN-ACK */
739 if (recv_flags & TF_GOT_FIN) { /* passive close */
741 pcb->state = CLOSE_WAIT;
746 if (recv_flags & TF_GOT_FIN) {
747 if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) {
748 LWIP_DEBUGF(TCP_DEBUG,
749 ("TCP connection closed: FIN_WAIT_1 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
752 TCP_RMV(&tcp_active_pcbs, pcb);
753 pcb->state = TIME_WAIT;
754 TCP_REG(&tcp_tw_pcbs, pcb);
757 pcb->state = CLOSING;
759 } else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) {
760 pcb->state = FIN_WAIT_2;
765 if (recv_flags & TF_GOT_FIN) {
766 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: FIN_WAIT_2 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
769 TCP_RMV(&tcp_active_pcbs, pcb);
770 pcb->state = TIME_WAIT;
771 TCP_REG(&tcp_tw_pcbs, pcb);
776 if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
777 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
779 TCP_RMV(&tcp_active_pcbs, pcb);
780 pcb->state = TIME_WAIT;
781 TCP_REG(&tcp_tw_pcbs, pcb);
786 if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
787 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: LAST_ACK %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
788 /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */
789 recv_flags |= TF_CLOSED;
800 * Insert segment into the list (segments covered with new one will be deleted)
802 * Called from tcp_receive()
805 tcp_oos_insert_segment(struct tcp_seg *cseg, struct tcp_seg *next)
807 struct tcp_seg *old_seg;
809 if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
810 /* received segment overlaps all following segments */
815 /* delete some following segments
816 oos queue may have segments with FIN flag */
818 TCP_SEQ_GEQ((seqno + cseg->len),
819 (next->tcphdr->seqno + next->len))) {
820 /* cseg with FIN already processed */
821 if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) {
822 TCPH_SET_FLAG(cseg->tcphdr, TCP_FIN);
826 tcp_seg_free(old_seg);
829 TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) {
830 /* We need to trim the incoming segment. */
831 cseg->len = (u16_t)(next->tcphdr->seqno - seqno);
832 pbuf_realloc(cseg->p, cseg->len);
837 #endif /* TCP_QUEUE_OOSEQ */
840 * Called by tcp_process. Checks if the given segment is an ACK for outstanding
841 * data, and if so frees the memory of the buffered data. Next, is places the
842 * segment on any of the receive queues (pcb->recved or pcb->ooseq). If the segment
843 * is buffered, the pbuf is referenced by pbuf_ref so that it will not be freed until
844 * i it has been removed from the buffer.
846 * If the incoming segment constitutes an ACK for a segment that was used for RTT
847 * estimation, the RTT is estimated here as well.
849 * Called from tcp_process().
852 tcp_receive(struct tcp_pcb *pcb)
854 struct tcp_seg *next;
856 struct tcp_seg *prev, *cseg;
857 #endif /* TCP_QUEUE_OOSEQ */
861 u32_t right_wnd_edge;
863 int found_dupack = 0;
865 if (flags & TCP_ACK) {
866 right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2;
869 if (TCP_SEQ_LT(pcb->snd_wl1, seqno) ||
870 (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) ||
871 (pcb->snd_wl2 == ackno && tcphdr->wnd > pcb->snd_wnd)) {
872 pcb->snd_wnd = tcphdr->wnd;
873 pcb->snd_wl1 = seqno;
874 pcb->snd_wl2 = ackno;
875 if (pcb->snd_wnd > 0 && pcb->persist_backoff > 0) {
876 pcb->persist_backoff = 0;
878 LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"U16_F"\n", pcb->snd_wnd));
881 if (pcb->snd_wnd != tcphdr->wnd) {
882 LWIP_DEBUGF(TCP_WND_DEBUG,
883 ("tcp_receive: no window update lastack %"U32_F" ackno %"
884 U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n",
885 pcb->lastack, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2));
887 #endif /* TCP_WND_DEBUG */
890 /* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a
892 * 1) It doesn't ACK new data
893 * 2) length of received packet is zero (i.e. no payload)
894 * 3) the advertised window hasn't changed
895 * 4) There is outstanding unacknowledged data (retransmission timer running)
896 * 5) The ACK is == biggest ACK sequence number so far seen (snd_una)
898 * If it passes all five, should process as a dupack:
899 * a) dupacks < 3: do nothing
900 * b) dupacks == 3: fast retransmit
901 * c) dupacks > 3: increase cwnd
903 * If it only passes 1-3, should reset dupack counter (and add to
904 * stats, which we don't do in lwIP)
906 * If it only passes 1, should reset dupack counter
911 if (TCP_SEQ_LEQ(ackno, pcb->lastack)) {
916 if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge){
918 if (pcb->rtime >= 0) {
920 if (pcb->lastack == ackno) {
922 if (pcb->dupacks + 1 > pcb->dupacks)
924 if (pcb->dupacks > 3) {
925 /* Inflate the congestion window, but not if it means that
926 the value overflows. */
927 if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
928 pcb->cwnd += pcb->mss;
930 } else if (pcb->dupacks == 3) {
931 /* Do fast retransmit */
932 tcp_rexmit_fast(pcb);
938 /* If Clause (1) or more is true, but not a duplicate ack, reset
939 * count of consecutive duplicate acks */
943 } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)){
944 /* We come here when the ACK acknowledges new data. */
946 /* Reset the "IN Fast Retransmit" flag, since we are no longer
947 in fast retransmit. Also reset the congestion window to the
948 slow start threshold. */
949 if (pcb->flags & TF_INFR) {
950 pcb->flags &= ~TF_INFR;
951 pcb->cwnd = pcb->ssthresh;
954 /* Reset the number of retransmissions. */
957 /* Reset the retransmission time-out. */
958 pcb->rto = (pcb->sa >> 3) + pcb->sv;
960 /* Update the send buffer space. Diff between the two can never exceed 64K? */
961 pcb->acked = (u16_t)(ackno - pcb->lastack);
963 pcb->snd_buf += pcb->acked;
965 /* Reset the fast retransmit variables. */
967 pcb->lastack = ackno;
969 /* Update the congestion control variables (cwnd and
971 if (pcb->state >= ESTABLISHED) {
972 if (pcb->cwnd < pcb->ssthresh) {
973 if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
974 pcb->cwnd += pcb->mss;
976 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"U16_F"\n", pcb->cwnd));
978 u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd);
979 if (new_cwnd > pcb->cwnd) {
980 pcb->cwnd = new_cwnd;
982 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"U16_F"\n", pcb->cwnd));
985 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n",
987 pcb->unacked != NULL?
988 ntohl(pcb->unacked->tcphdr->seqno): 0,
989 pcb->unacked != NULL?
990 ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0));
992 /* Remove segment from the unacknowledged list if the incoming
993 ACK acknowlegdes them. */
994 while (pcb->unacked != NULL &&
995 TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) +
996 TCP_TCPLEN(pcb->unacked), ackno)) {
997 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unacked\n",
998 ntohl(pcb->unacked->tcphdr->seqno),
999 ntohl(pcb->unacked->tcphdr->seqno) +
1000 TCP_TCPLEN(pcb->unacked)));
1002 next = pcb->unacked;
1003 pcb->unacked = pcb->unacked->next;
1005 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen));
1006 LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
1007 /* Prevent ACK for FIN to generate a sent event */
1008 if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) {
1012 pcb->snd_queuelen -= pbuf_clen(next->p);
1015 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unacked)\n", (u16_t)pcb->snd_queuelen));
1016 if (pcb->snd_queuelen != 0) {
1017 LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL ||
1018 pcb->unsent != NULL);
1022 /* If there's nothing left to acknowledge, stop the retransmit
1023 timer, otherwise reset it to start again */
1024 if(pcb->unacked == NULL)
1031 #if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS
1032 if (PCB_ISIPV6(pcb)) {
1033 /* Inform neighbor reachability of forward progress. */
1034 nd6_reachability_hint(ip6_current_src_addr());
1036 #endif /* LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS*/
1038 /* Fix bug bug #21582: out of sequence ACK, didn't really ack anything */
1042 /* We go through the ->unsent list to see if any of the segments
1043 on the list are acknowledged by the ACK. This may seem
1044 strange since an "unsent" segment shouldn't be acked. The
1045 rationale is that lwIP puts all outstanding segments on the
1046 ->unsent list after a retransmission, so these segments may
1047 in fact have been sent once. */
1048 while (pcb->unsent != NULL &&
1049 TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) +
1050 TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) {
1051 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n",
1052 ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) +
1053 TCP_TCPLEN(pcb->unsent)));
1056 pcb->unsent = pcb->unsent->next;
1057 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen));
1058 LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
1059 /* Prevent ACK for FIN to generate a sent event */
1060 if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) {
1063 pcb->snd_queuelen -= pbuf_clen(next->p);
1065 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unsent)\n", (u16_t)pcb->snd_queuelen));
1066 if (pcb->snd_queuelen != 0) {
1067 LWIP_ASSERT("tcp_receive: valid queue length",
1068 pcb->unacked != NULL || pcb->unsent != NULL);
1071 /* End of ACK for new data processing. */
1073 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %"U32_F" rtseq %"U32_F" ackno %"U32_F"\n",
1074 pcb->rttest, pcb->rtseq, ackno));
1076 /* RTT estimation calculations. This is done by checking if the
1077 incoming segment acknowledges the segment we use to take a
1078 round-trip time measurement. */
1079 if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) {
1080 /* diff between this shouldn't exceed 32K since this are tcp timer ticks
1081 and a round-trip shouldn't be that long... */
1082 m = (s16_t)(tcp_ticks - pcb->rttest);
1084 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %"U16_F" ticks (%"U16_F" msec).\n",
1085 m, m * TCP_SLOW_INTERVAL));
1087 /* This is taken directly from VJs original code in his paper */
1088 m = m - (pcb->sa >> 3);
1093 m = m - (pcb->sv >> 2);
1095 pcb->rto = (pcb->sa >> 3) + pcb->sv;
1097 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %"U16_F" (%"U16_F" milliseconds)\n",
1098 pcb->rto, pcb->rto * TCP_SLOW_INTERVAL));
1104 /* If the incoming segment contains data, we must process it
1107 /* This code basically does three things:
1109 +) If the incoming segment contains data that is the next
1110 in-sequence data, this data is passed to the application. This
1111 might involve trimming the first edge of the data. The rcv_nxt
1112 variable and the advertised window are adjusted.
1114 +) If the incoming segment has data that is above the next
1115 sequence number expected (->rcv_nxt), the segment is placed on
1116 the ->ooseq queue. This is done by finding the appropriate
1117 place in the ->ooseq queue (which is ordered by sequence
1118 number) and trim the segment in both ends if needed. An
1119 immediate ACK is sent to indicate that we received an
1120 out-of-sequence segment.
1122 +) Finally, we check if the first segment on the ->ooseq queue
1123 now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If
1124 rcv_nxt > ooseq->seqno, we must trim the first edge of the
1125 segment on ->ooseq before we adjust rcv_nxt. The data in the
1126 segments that are now on sequence are chained onto the
1127 incoming segment so that we only need to call the application
1131 /* First, we check if we must trim the first edge. We have to do
1132 this if the sequence number of the incoming segment is less
1133 than rcv_nxt, and the sequence number plus the length of the
1134 segment is larger than rcv_nxt. */
1135 /* if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){
1136 if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/
1137 if (TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno + 1, seqno + tcplen - 1)){
1138 /* Trimming the first edge is done by pushing the payload
1139 pointer in the pbuf downwards. This is somewhat tricky since
1140 we do not want to discard the full contents of the pbuf up to
1141 the new starting point of the data since we have to keep the
1142 TCP header which is present in the first pbuf in the chain.
1144 What is done is really quite a nasty hack: the first pbuf in
1145 the pbuf chain is pointed to by inseg.p. Since we need to be
1146 able to deallocate the whole pbuf, we cannot change this
1147 inseg.p pointer to point to any of the later pbufs in the
1148 chain. Instead, we point the ->payload pointer in the first
1149 pbuf to data in one of the later pbufs. We also set the
1150 inseg.data pointer to point to the right place. This way, the
1151 ->p pointer will still point to the first pbuf, but the
1152 ->p->payload pointer will point to data in another pbuf.
1154 After we are done with adjusting the pbuf pointers we must
1155 adjust the ->data pointer in the seg and the segment
1158 off = pcb->rcv_nxt - seqno;
1160 LWIP_ASSERT("inseg.p != NULL", inseg.p);
1161 LWIP_ASSERT("insane offset!", (off < 0x7fff));
1162 if (inseg.p->len < off) {
1163 LWIP_ASSERT("pbuf too short!", (((s32_t)inseg.p->tot_len) >= off));
1164 new_tot_len = (u16_t)(inseg.p->tot_len - off);
1165 while (p->len < off) {
1167 /* KJM following line changed (with addition of new_tot_len var)
1169 inseg.p->tot_len -= p->len; */
1170 p->tot_len = new_tot_len;
1174 if(pbuf_header(p, (s16_t)-off)) {
1175 /* Do we need to cope with this failing? Assert for now */
1176 LWIP_ASSERT("pbuf_header failed", 0);
1179 if(pbuf_header(inseg.p, (s16_t)-off)) {
1180 /* Do we need to cope with this failing? Assert for now */
1181 LWIP_ASSERT("pbuf_header failed", 0);
1184 inseg.len -= (u16_t)(pcb->rcv_nxt - seqno);
1185 inseg.tcphdr->seqno = seqno = pcb->rcv_nxt;
1188 if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){
1189 /* the whole segment is < rcv_nxt */
1190 /* must be a duplicate of a packet that has already been correctly handled */
1192 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno));
1197 /* The sequence number must be within the window (above rcv_nxt
1198 and below rcv_nxt + rcv_wnd) in order to be further
1200 if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
1201 pcb->rcv_nxt + pcb->rcv_wnd - 1)){
1202 if (pcb->rcv_nxt == seqno) {
1203 /* The incoming segment is the next in sequence. We check if
1204 we have to trim the end of the segment and update rcv_nxt
1205 and pass the data to the application. */
1206 tcplen = TCP_TCPLEN(&inseg);
1208 if (tcplen > pcb->rcv_wnd) {
1209 LWIP_DEBUGF(TCP_INPUT_DEBUG,
1210 ("tcp_receive: other end overran receive window"
1211 "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n",
1212 seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd));
1213 if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
1214 /* Must remove the FIN from the header as we're trimming
1215 * that byte of sequence-space from the packet */
1216 TCPH_FLAGS_SET(inseg.tcphdr, TCPH_FLAGS(inseg.tcphdr) &~ TCP_FIN);
1218 /* Adjust length of segment to fit in the window. */
1219 inseg.len = pcb->rcv_wnd;
1220 if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
1223 pbuf_realloc(inseg.p, inseg.len);
1224 tcplen = TCP_TCPLEN(&inseg);
1225 LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n",
1226 (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd));
1229 /* Received in-sequence data, adjust ooseq data if:
1230 - FIN has been received or
1231 - inseq overlaps with ooseq */
1232 if (pcb->ooseq != NULL) {
1233 if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
1234 LWIP_DEBUGF(TCP_INPUT_DEBUG,
1235 ("tcp_receive: received in-order FIN, binning ooseq queue\n"));
1236 /* Received in-order FIN means anything that was received
1237 * out of order must now have been received in-order, so
1238 * bin the ooseq queue */
1239 while (pcb->ooseq != NULL) {
1240 struct tcp_seg *old_ooseq = pcb->ooseq;
1241 pcb->ooseq = pcb->ooseq->next;
1242 tcp_seg_free(old_ooseq);
1247 /* Remove all segments on ooseq that are covered by inseg already.
1248 * FIN is copied from ooseq to inseg if present. */
1250 TCP_SEQ_GEQ(seqno + tcplen,
1251 next->tcphdr->seqno + next->len)) {
1252 /* inseg cannot have FIN here (already processed above) */
1253 if (TCPH_FLAGS(next->tcphdr) & TCP_FIN &&
1254 (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) {
1255 TCPH_SET_FLAG(inseg.tcphdr, TCP_FIN);
1256 tcplen = TCP_TCPLEN(&inseg);
1262 /* Now trim right side of inseg if it overlaps with the first
1263 * segment on ooseq */
1265 TCP_SEQ_GT(seqno + tcplen,
1266 next->tcphdr->seqno)) {
1267 /* inseg cannot have FIN here (already processed above) */
1268 inseg.len = (u16_t)(next->tcphdr->seqno - seqno);
1269 if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
1272 pbuf_realloc(inseg.p, inseg.len);
1273 tcplen = TCP_TCPLEN(&inseg);
1274 LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n",
1275 (seqno + tcplen) == next->tcphdr->seqno);
1280 #endif /* TCP_QUEUE_OOSEQ */
1282 pcb->rcv_nxt = seqno + tcplen;
1284 /* Update the receiver's (our) window. */
1285 LWIP_ASSERT("tcp_receive: tcplen > rcv_wnd\n", pcb->rcv_wnd >= tcplen);
1286 pcb->rcv_wnd -= tcplen;
1288 tcp_update_rcv_ann_wnd(pcb);
1290 /* If there is data in the segment, we make preparations to
1291 pass this up to the application. The ->recv_data variable
1292 is used for holding the pbuf that goes to the
1293 application. The code for reassembling out-of-sequence data
1294 chains its data on this pbuf as well.
1296 If the segment was a FIN, we set the TF_GOT_FIN flag that will
1297 be used to indicate to the application that the remote side has
1298 closed its end of the connection. */
1299 if (inseg.p->tot_len > 0) {
1300 recv_data = inseg.p;
1301 /* Since this pbuf now is the responsibility of the
1302 application, we delete our reference to it so that we won't
1303 (mistakingly) deallocate it. */
1306 if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
1307 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n"));
1308 recv_flags |= TF_GOT_FIN;
1312 /* We now check if we have segments on the ->ooseq queue that
1313 are now in sequence. */
1314 while (pcb->ooseq != NULL &&
1315 pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) {
1318 seqno = pcb->ooseq->tcphdr->seqno;
1320 pcb->rcv_nxt += TCP_TCPLEN(cseg);
1321 LWIP_ASSERT("tcp_receive: ooseq tcplen > rcv_wnd\n",
1322 pcb->rcv_wnd >= TCP_TCPLEN(cseg));
1323 pcb->rcv_wnd -= TCP_TCPLEN(cseg);
1325 tcp_update_rcv_ann_wnd(pcb);
1327 if (cseg->p->tot_len > 0) {
1328 /* Chain this pbuf onto the pbuf that we will pass to
1331 pbuf_cat(recv_data, cseg->p);
1333 recv_data = cseg->p;
1337 if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
1338 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n"));
1339 recv_flags |= TF_GOT_FIN;
1340 if (pcb->state == ESTABLISHED) { /* force passive close or we can move to active close */
1341 pcb->state = CLOSE_WAIT;
1345 pcb->ooseq = cseg->next;
1348 #endif /* TCP_QUEUE_OOSEQ */
1351 /* Acknowledge the segment(s). */
1354 #if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS
1355 if (PCB_ISIPV6(pcb)) {
1356 /* Inform neighbor reachability of forward progress. */
1357 nd6_reachability_hint(ip6_current_src_addr());
1359 #endif /* LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS*/
1362 /* We get here if the incoming segment is out-of-sequence. */
1363 tcp_send_empty_ack(pcb);
1365 /* We queue the segment on the ->ooseq queue. */
1366 if (pcb->ooseq == NULL) {
1367 pcb->ooseq = tcp_seg_copy(&inseg);
1369 /* If the queue is not empty, we walk through the queue and
1370 try to find a place where the sequence number of the
1371 incoming segment is between the sequence numbers of the
1372 previous and the next segment on the ->ooseq queue. That is
1373 the place where we put the incoming segment. If needed, we
1374 trim the second edges of the previous and the incoming
1375 segment so that it will fit into the sequence.
1377 If the incoming segment has the same sequence number as a
1378 segment on the ->ooseq queue, we discard the segment that
1379 contains less data. */
1382 for(next = pcb->ooseq; next != NULL; next = next->next) {
1383 if (seqno == next->tcphdr->seqno) {
1384 /* The sequence number of the incoming segment is the
1385 same as the sequence number of the segment on
1386 ->ooseq. We check the lengths to see which one to
1388 if (inseg.len > next->len) {
1389 /* The incoming segment is larger than the old
1390 segment. We replace some segments with the new
1392 cseg = tcp_seg_copy(&inseg);
1399 tcp_oos_insert_segment(cseg, next);
1403 /* Either the lenghts are the same or the incoming
1404 segment was smaller than the old one; in either
1405 case, we ditch the incoming segment. */
1410 if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {
1411 /* The sequence number of the incoming segment is lower
1412 than the sequence number of the first segment on the
1413 queue. We put the incoming segment first on the
1415 cseg = tcp_seg_copy(&inseg);
1418 tcp_oos_insert_segment(cseg, next);
1423 /*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) &&
1424 TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/
1425 if (TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)) {
1426 /* The sequence number of the incoming segment is in
1427 between the sequence numbers of the previous and
1428 the next segment on ->ooseq. We trim trim the previous
1429 segment, delete next segments that included in received segment
1430 and trim received, if needed. */
1431 cseg = tcp_seg_copy(&inseg);
1433 if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) {
1434 /* We need to trim the prev segment. */
1435 prev->len = (u16_t)(seqno - prev->tcphdr->seqno);
1436 pbuf_realloc(prev->p, prev->len);
1439 tcp_oos_insert_segment(cseg, next);
1444 /* If the "next" segment is the last segment on the
1445 ooseq queue, we add the incoming segment to the end
1447 if (next->next == NULL &&
1448 TCP_SEQ_GT(seqno, next->tcphdr->seqno)) {
1449 if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) {
1450 /* segment "next" already contains all data */
1453 next->next = tcp_seg_copy(&inseg);
1454 if (next->next != NULL) {
1455 if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) {
1456 /* We need to trim the last segment. */
1457 next->len = (u16_t)(seqno - next->tcphdr->seqno);
1458 pbuf_realloc(next->p, next->len);
1460 /* check if the remote side overruns our receive window */
1461 if ((u32_t)tcplen + seqno > pcb->rcv_nxt + (u32_t)pcb->rcv_wnd) {
1462 LWIP_DEBUGF(TCP_INPUT_DEBUG,
1463 ("tcp_receive: other end overran receive window"
1464 "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n",
1465 seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd));
1466 if (TCPH_FLAGS(next->next->tcphdr) & TCP_FIN) {
1467 /* Must remove the FIN from the header as we're trimming
1468 * that byte of sequence-space from the packet */
1469 TCPH_FLAGS_SET(next->next->tcphdr, TCPH_FLAGS(next->next->tcphdr) &~ TCP_FIN);
1471 /* Adjust length of segment to fit in the window. */
1472 next->next->len = pcb->rcv_nxt + pcb->rcv_wnd - seqno;
1473 pbuf_realloc(next->next->p, next->next->len);
1474 tcplen = TCP_TCPLEN(next->next);
1475 LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n",
1476 (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd));
1485 #endif /* TCP_QUEUE_OOSEQ */
1489 /* The incoming segment is not withing the window. */
1490 tcp_send_empty_ack(pcb);
1493 /* Segments with length 0 is taken care of here. Segments that
1494 fall out of the window are ACKed. */
1495 /*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) ||
1496 TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/
1497 if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){
1504 * Parses the options contained in the incoming segment.
1506 * Called from tcp_listen_input() and tcp_process().
1507 * Currently, only the MSS option is supported!
1509 * @param pcb the tcp_pcb for which a segment arrived
1512 tcp_parseopt(struct tcp_pcb *pcb)
1517 #if LWIP_TCP_TIMESTAMPS
1521 opts = (u8_t *)tcphdr + TCP_HLEN;
1523 /* Parse the TCP MSS option, if present. */
1524 if(TCPH_HDRLEN(tcphdr) > 0x5) {
1525 max_c = (TCPH_HDRLEN(tcphdr) - 5) << 2;
1526 for (c = 0; c < max_c; ) {
1530 /* End of options. */
1531 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: EOL\n"));
1536 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: NOP\n"));
1539 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: MSS\n"));
1540 if (opts[c + 1] != 0x04 || c + 0x04 > max_c) {
1542 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
1545 /* An MSS option with the right option length. */
1546 mss = (opts[c + 2] << 8) | opts[c + 3];
1547 /* Limit the mss to the configured TCP_MSS and prevent division by zero */
1548 pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss;
1549 /* Advance to next option */
1552 #if LWIP_TCP_TIMESTAMPS
1554 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: TS\n"));
1555 if (opts[c + 1] != 0x0A || c + 0x0A > max_c) {
1557 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
1560 /* TCP timestamp option with valid length */
1561 tsval = (opts[c+2]) | (opts[c+3] << 8) |
1562 (opts[c+4] << 16) | (opts[c+5] << 24);
1563 if (flags & TCP_SYN) {
1564 pcb->ts_recent = ntohl(tsval);
1565 pcb->flags |= TF_TIMESTAMP;
1566 } else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno+tcplen)) {
1567 pcb->ts_recent = ntohl(tsval);
1569 /* Advance to next option */
1574 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: other\n"));
1575 if (opts[c + 1] == 0) {
1576 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
1577 /* If the length field is zero, the options are malformed
1578 and we don't process them further. */
1581 /* All other options have a length field, so that we easily
1582 can skip past them. */
1589 #endif /* LWIP_TCP */