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 /* These variables are global to all functions involved in the input
60 processing of TCP segments. They are set by the tcp_input()
62 static struct tcp_seg inseg
;
63 static struct tcp_hdr
*tcphdr
;
64 static struct ip_hdr
*iphdr
;
65 static u32_t seqno
, ackno
;
69 static u8_t recv_flags
;
70 static struct pbuf
*recv_data
;
72 struct tcp_pcb
*tcp_input_pcb
;
74 /* Forward declarations. */
75 static err_t
tcp_process(struct tcp_pcb
*pcb
);
76 static void tcp_receive(struct tcp_pcb
*pcb
);
77 static void tcp_parseopt(struct tcp_pcb
*pcb
);
79 static err_t
tcp_listen_input(struct tcp_pcb_listen
*pcb
);
80 static err_t
tcp_timewait_input(struct tcp_pcb
*pcb
);
82 static const char * const tcp_state_str
[] = {
97 * The initial input processing of TCP. It verifies the TCP header, demultiplexes
98 * the segment between the PCBs and passes it on to tcp_process(), which implements
99 * the TCP finite state machine. This function is called by the IP layer (in
102 * @param p received TCP segment to process (p->payload pointing to the IP header)
103 * @param inp network interface on which this segment was received
106 tcp_input(struct pbuf
*p
, struct netif
*inp
)
108 struct tcp_pcb
*pcb
, *prev
;
109 struct tcp_pcb_listen
*lpcb
;
111 struct tcp_pcb
*lpcb_prev
= NULL
;
112 struct tcp_pcb_listen
*lpcb_any
= NULL
;
113 #endif /* SO_REUSE */
119 TCP_STATS_INC(tcp
.recv
);
120 snmp_inc_tcpinsegs();
122 iphdr
= (struct ip_hdr
*)p
->payload
;
123 tcphdr
= (struct tcp_hdr
*)((u8_t
*)p
->payload
+ IPH_HL(iphdr
) * 4);
126 tcp_debug_print(tcphdr
);
129 /* remove header from payload */
130 if (pbuf_header(p
, -((s16_t
)(IPH_HL(iphdr
) * 4))) || (p
->tot_len
< sizeof(struct tcp_hdr
))) {
131 /* drop short packets */
132 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_input: short packet (%"U16_F
" bytes) discarded\n", p
->tot_len
));
133 TCP_STATS_INC(tcp
.lenerr
);
134 TCP_STATS_INC(tcp
.drop
);
135 snmp_inc_tcpinerrs();
140 /* Don't even process incoming broadcasts/multicasts. */
141 if (ip_addr_isbroadcast(¤t_iphdr_dest
, inp
) ||
142 ip_addr_ismulticast(¤t_iphdr_dest
)) {
143 TCP_STATS_INC(tcp
.proterr
);
144 TCP_STATS_INC(tcp
.drop
);
145 snmp_inc_tcpinerrs();
150 #if CHECKSUM_CHECK_TCP
151 /* Verify TCP checksum. */
152 if (inet_chksum_pseudo(p
, ip_current_src_addr(), ip_current_dest_addr(),
153 IP_PROTO_TCP
, p
->tot_len
) != 0) {
154 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F
"\n",
155 inet_chksum_pseudo(p
, ip_current_src_addr(), ip_current_dest_addr(),
156 IP_PROTO_TCP
, p
->tot_len
)));
158 tcp_debug_print(tcphdr
);
159 #endif /* TCP_DEBUG */
160 TCP_STATS_INC(tcp
.chkerr
);
161 TCP_STATS_INC(tcp
.drop
);
162 snmp_inc_tcpinerrs();
168 /* Move the payload pointer in the pbuf so that it points to the
169 TCP data instead of the TCP header. */
170 hdrlen
= TCPH_HDRLEN(tcphdr
);
171 if(pbuf_header(p
, -(hdrlen
* 4))){
172 /* drop short packets */
173 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_input: short packet\n"));
174 TCP_STATS_INC(tcp
.lenerr
);
175 TCP_STATS_INC(tcp
.drop
);
176 snmp_inc_tcpinerrs();
181 /* Convert fields in TCP header to host byte order. */
182 tcphdr
->src
= ntohs(tcphdr
->src
);
183 tcphdr
->dest
= ntohs(tcphdr
->dest
);
184 seqno
= tcphdr
->seqno
= ntohl(tcphdr
->seqno
);
185 ackno
= tcphdr
->ackno
= ntohl(tcphdr
->ackno
);
186 tcphdr
->wnd
= ntohs(tcphdr
->wnd
);
188 flags
= TCPH_FLAGS(tcphdr
);
189 tcplen
= p
->tot_len
+ ((flags
& (TCP_FIN
| TCP_SYN
)) ? 1 : 0);
191 /* Demultiplex an incoming segment. First, we check if it is destined
192 for an active connection. */
196 for(pcb
= tcp_active_pcbs
; pcb
!= NULL
; pcb
= pcb
->next
) {
197 LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb
->state
!= CLOSED
);
198 LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb
->state
!= TIME_WAIT
);
199 LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb
->state
!= LISTEN
);
200 if (pcb
->remote_port
== tcphdr
->src
&&
201 pcb
->local_port
== tcphdr
->dest
&&
202 ip_addr_cmp(&(pcb
->remote_ip
), ¤t_iphdr_src
) &&
203 ip_addr_cmp(&(pcb
->local_ip
), ¤t_iphdr_dest
)) {
205 /* Move this PCB to the front of the list so that subsequent
206 lookups will be faster (we exploit locality in TCP segment
208 LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb
->next
!= pcb
);
210 prev
->next
= pcb
->next
;
211 pcb
->next
= tcp_active_pcbs
;
212 tcp_active_pcbs
= pcb
;
214 LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb
->next
!= pcb
);
221 /* If it did not go to an active connection, we check the connections
222 in the TIME-WAIT state. */
223 for(pcb
= tcp_tw_pcbs
; pcb
!= NULL
; pcb
= pcb
->next
) {
224 LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb
->state
== TIME_WAIT
);
225 if (pcb
->remote_port
== tcphdr
->src
&&
226 pcb
->local_port
== tcphdr
->dest
&&
227 ip_addr_cmp(&(pcb
->remote_ip
), ¤t_iphdr_src
) &&
228 ip_addr_cmp(&(pcb
->local_ip
), ¤t_iphdr_dest
)) {
229 /* We don't really care enough to move this PCB to the front
230 of the list since we are not very likely to receive that
231 many segments for connections in TIME-WAIT. */
232 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_input: packed for TIME_WAITing connection.\n"));
233 tcp_timewait_input(pcb
);
239 /* Finally, if we still did not get a match, we check all PCBs that
240 are LISTENing for incoming connections. */
242 for(lpcb
= tcp_listen_pcbs
.listen_pcbs
; lpcb
!= NULL
; lpcb
= lpcb
->next
) {
243 if (lpcb
->local_port
== tcphdr
->dest
) {
245 if (ip_addr_cmp(&(lpcb
->local_ip
), ¤t_iphdr_dest
)) {
246 /* found an exact match */
248 } else if(ip_addr_isany(&(lpcb
->local_ip
))) {
249 /* found an ANY-match */
254 if (ip_addr_cmp(&(lpcb
->local_ip
), ¤t_iphdr_dest
) ||
255 ip_addr_isany(&(lpcb
->local_ip
))) {
259 #endif /* SO_REUSE */
261 prev
= (struct tcp_pcb
*)lpcb
;
264 /* first try specific local IP */
266 /* only pass to ANY if no specific local IP has been found */
270 #endif /* SO_REUSE */
272 /* Move this PCB to the front of the list so that subsequent
273 lookups will be faster (we exploit locality in TCP segment
276 ((struct tcp_pcb_listen
*)prev
)->next
= lpcb
->next
;
277 /* our successor is the remainder of the listening list */
278 lpcb
->next
= tcp_listen_pcbs
.listen_pcbs
;
279 /* put this listening pcb at the head of the listening list */
280 tcp_listen_pcbs
.listen_pcbs
= lpcb
;
283 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_input: packed for LISTENing connection.\n"));
284 tcp_listen_input(lpcb
);
291 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags "));
292 tcp_debug_print_flags(TCPH_FLAGS(tcphdr
));
293 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n"));
294 #endif /* TCP_INPUT_DEBUG */
298 /* The incoming segment belongs to a connection. */
301 tcp_debug_print_state(pcb
->state
);
302 #endif /* TCP_DEBUG */
303 #endif /* TCP_INPUT_DEBUG */
305 /* Set up a tcp_seg structure. */
307 inseg
.len
= p
->tot_len
;
309 inseg
.tcphdr
= tcphdr
;
314 /* If there is data which was previously "refused" by upper layer */
315 if (pcb
->refused_data
!= NULL
) {
316 /* Notify again application with data previously received. */
317 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_input: notify kept packet\n"));
318 TCP_EVENT_RECV(pcb
, pcb
->refused_data
, ERR_OK
, err
);
320 pcb
->refused_data
= NULL
;
321 } else if ((err
== ERR_ABRT
) || (tcplen
> 0)) {
322 /* if err == ERR_ABRT, 'pcb' is already deallocated */
323 /* Drop incoming packets because pcb is "full" (only if the incoming
324 segment contains data). */
325 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_input: drop incoming packets, because pcb is \"full\"\n"));
326 TCP_STATS_INC(tcp
.drop
);
327 snmp_inc_tcpinerrs();
333 err
= tcp_process(pcb
);
334 /* A return value of ERR_ABRT means that tcp_abort() was called
335 and that the pcb has been freed. If so, we don't do anything. */
336 if (err
!= ERR_ABRT
) {
337 if (recv_flags
& TF_RESET
) {
338 /* TF_RESET means that the connection was reset by the other
339 end. We then call the error callback to inform the
340 application that the connection is dead before we
341 deallocate the PCB. */
342 TCP_EVENT_ERR(pcb
->errf
, pcb
->callback_arg
, ERR_RST
);
343 tcp_pcb_remove(&tcp_active_pcbs
, pcb
);
344 memp_free(MEMP_TCP_PCB
, pcb
);
345 } else if (recv_flags
& TF_CLOSED
) {
346 /* The connection has been closed and we will deallocate the
348 TCP_EVENT_CLOSED(pcb
, err
);
349 if (err
== ERR_ABRT
) {
352 tcp_pcb_remove(&tcp_active_pcbs
, pcb
);
353 memp_free(MEMP_TCP_PCB
, pcb
);
356 /* If the application has registered a "sent" function to be
357 called when new send buffer space is available, we call it
359 if (pcb
->acked
> 0) {
360 TCP_EVENT_SENT(pcb
, pcb
->acked
, err
);
361 if (err
== ERR_ABRT
) {
366 if (recv_data
!= NULL
) {
367 LWIP_ASSERT("pcb->refused_data == NULL", pcb
->refused_data
== NULL
);
368 if (pcb
->flags
& TF_RXCLOSED
) {
369 /* received data although already closed -> abort (send RST) to
370 notify the remote host that not all data has been processed */
371 pbuf_free(recv_data
);
375 if (flags
& TCP_PSH
) {
376 recv_data
->flags
|= PBUF_FLAG_PUSH
;
379 /* Notify application that data has been received. */
380 TCP_EVENT_RECV(pcb
, recv_data
, ERR_OK
, err
);
381 if (err
== ERR_ABRT
) {
385 /* If the upper layer can't receive this data, store it */
387 pcb
->refused_data
= recv_data
;
388 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_input: keep incoming packet, because pcb is \"full\"\n"));
392 /* If a FIN segment was received, we call the callback
393 function with a NULL buffer to indicate EOF. */
394 if (recv_flags
& TF_GOT_FIN
) {
395 /* correct rcv_wnd as the application won't call tcp_recved()
396 for the FIN's seqno */
397 if (pcb
->rcv_wnd
!= TCP_WND
) {
400 TCP_EVENT_CLOSED(pcb
, err
);
401 if (err
== ERR_ABRT
) {
406 tcp_input_pcb
= NULL
;
407 /* Try to send something out. */
411 tcp_debug_print_state(pcb
->state
);
412 #endif /* TCP_DEBUG */
413 #endif /* TCP_INPUT_DEBUG */
416 /* Jump target if pcb has been aborted in a callback (by calling tcp_abort()).
417 Below this line, 'pcb' may not be dereferenced! */
419 tcp_input_pcb
= NULL
;
422 /* give up our reference to inseg.p */
430 /* If no matching PCB was found, send a TCP RST (reset) to the
432 LWIP_DEBUGF(TCP_RST_DEBUG
, ("tcp_input: no PCB match found, resetting.\n"));
433 if (!(TCPH_FLAGS(tcphdr
) & TCP_RST
)) {
434 TCP_STATS_INC(tcp
.proterr
);
435 TCP_STATS_INC(tcp
.drop
);
436 tcp_rst(ackno
, seqno
+ tcplen
,
437 ip_current_dest_addr(), ip_current_src_addr(),
438 tcphdr
->dest
, tcphdr
->src
);
443 LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());
444 PERF_STOP("tcp_input");
448 * Called by tcp_input() when a segment arrives for a listening
449 * connection (from tcp_input()).
451 * @param pcb the tcp_pcb_listen for which a segment arrived
452 * @return ERR_OK if the segment was processed
453 * another err_t on error
455 * @note the return value is not (yet?) used in tcp_input()
456 * @note the segment which arrived is saved in global variables, therefore only the pcb
457 * involved is passed as a parameter to this function
460 tcp_listen_input(struct tcp_pcb_listen
*pcb
)
462 struct tcp_pcb
*npcb
;
465 /* In the LISTEN state, we check for incoming SYN segments,
466 creates a new PCB, and responds with a SYN|ACK. */
467 if (flags
& TCP_ACK
) {
468 /* For incoming segments with the ACK flag set, respond with a
470 LWIP_DEBUGF(TCP_RST_DEBUG
, ("tcp_listen_input: ACK in LISTEN, sending reset\n"));
471 tcp_rst(ackno
+ 1, seqno
+ tcplen
,
472 ip_current_dest_addr(), ip_current_src_addr(),
473 tcphdr
->dest
, tcphdr
->src
);
474 } else if (flags
& TCP_SYN
) {
475 LWIP_DEBUGF(TCP_DEBUG
, ("TCP connection request %"U16_F
" -> %"U16_F
".\n", tcphdr
->src
, tcphdr
->dest
));
476 #if TCP_LISTEN_BACKLOG
477 if (pcb
->accepts_pending
>= pcb
->backlog
) {
478 LWIP_DEBUGF(TCP_DEBUG
, ("tcp_listen_input: listen backlog exceeded for port %"U16_F
"\n", tcphdr
->dest
));
481 #endif /* TCP_LISTEN_BACKLOG */
482 npcb
= tcp_alloc(pcb
->prio
);
483 /* If a new PCB could not be created (probably due to lack of memory),
484 we don't do anything, but rely on the sender will retransmit the
485 SYN at a time when we have more memory available. */
487 LWIP_DEBUGF(TCP_DEBUG
, ("tcp_listen_input: could not allocate PCB\n"));
488 TCP_STATS_INC(tcp
.memerr
);
491 #if TCP_LISTEN_BACKLOG
492 pcb
->accepts_pending
++;
493 #endif /* TCP_LISTEN_BACKLOG */
494 /* Set up the new PCB. */
495 ip_addr_copy(npcb
->local_ip
, current_iphdr_dest
);
496 npcb
->local_port
= pcb
->local_port
;
497 ip_addr_copy(npcb
->remote_ip
, current_iphdr_src
);
498 npcb
->remote_port
= tcphdr
->src
;
499 npcb
->state
= SYN_RCVD
;
500 npcb
->rcv_nxt
= seqno
+ 1;
501 npcb
->rcv_ann_right_edge
= npcb
->rcv_nxt
;
502 npcb
->snd_wnd
= tcphdr
->wnd
;
503 npcb
->ssthresh
= npcb
->snd_wnd
;
504 npcb
->snd_wl1
= seqno
- 1;/* initialise to seqno-1 to force window update */
505 npcb
->callback_arg
= pcb
->callback_arg
;
506 #if LWIP_CALLBACK_API
507 npcb
->accept
= pcb
->accept
;
508 #endif /* LWIP_CALLBACK_API */
509 /* inherit socket options */
510 npcb
->so_options
= pcb
->so_options
& SOF_INHERITED
;
511 /* Register the new PCB so that we can begin receiving segments
513 TCP_REG(&tcp_active_pcbs
, npcb
);
515 /* Parse any options in the SYN. */
517 #if TCP_CALCULATE_EFF_SEND_MSS
518 npcb
->mss
= tcp_eff_send_mss(npcb
->mss
, &(npcb
->remote_ip
));
519 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
521 snmp_inc_tcppassiveopens();
523 /* Send a SYN|ACK together with the MSS option. */
524 rc
= tcp_enqueue_flags(npcb
, TCP_SYN
| TCP_ACK
);
526 tcp_abandon(npcb
, 0);
529 return tcp_output(npcb
);
535 * Called by tcp_input() when a segment arrives for a connection in
538 * @param pcb the tcp_pcb for which a segment arrived
540 * @note the segment which arrived is saved in global variables, therefore only the pcb
541 * involved is passed as a parameter to this function
544 tcp_timewait_input(struct tcp_pcb
*pcb
)
546 /* RFC 1337: in TIME_WAIT, ignore RST and ACK FINs + any 'acceptable' segments */
547 /* RFC 793 3.9 Event Processing - Segment Arrives:
548 * - first check sequence number - we skip that one in TIME_WAIT (always
549 * acceptable since we only send ACKs)
550 * - second check the RST bit (... return) */
551 if (flags
& TCP_RST
) {
554 /* - fourth, check the SYN bit, */
555 if (flags
& TCP_SYN
) {
556 /* If an incoming segment is not acceptable, an acknowledgment
557 should be sent in reply */
558 if (TCP_SEQ_BETWEEN(seqno
, pcb
->rcv_nxt
, pcb
->rcv_nxt
+pcb
->rcv_wnd
)) {
559 /* If the SYN is in the window it is an error, send a reset */
560 tcp_rst(ackno
, seqno
+ tcplen
, ip_current_dest_addr(), ip_current_src_addr(),
561 tcphdr
->dest
, tcphdr
->src
);
564 } else if (flags
& TCP_FIN
) {
565 /* - eighth, check the FIN bit: Remain in the TIME-WAIT state.
566 Restart the 2 MSL time-wait timeout.*/
567 pcb
->tmr
= tcp_ticks
;
571 /* Acknowledge data, FIN or out-of-window SYN */
572 pcb
->flags
|= TF_ACK_NOW
;
573 return tcp_output(pcb
);
579 * Implements the TCP state machine. Called by tcp_input. In some
580 * states tcp_receive() is called to receive data. The tcp_seg
581 * argument will be freed by the caller (tcp_input()) unless the
582 * recv_data pointer in the pcb is set.
584 * @param pcb the tcp_pcb for which a segment arrived
586 * @note the segment which arrived is saved in global variables, therefore only the pcb
587 * involved is passed as a parameter to this function
590 tcp_process(struct tcp_pcb
*pcb
)
592 struct tcp_seg
*rseg
;
598 /* Process incoming RST segments. */
599 if (flags
& TCP_RST
) {
600 /* First, determine if the reset is acceptable. */
601 if (pcb
->state
== SYN_SENT
) {
602 if (ackno
== pcb
->snd_nxt
) {
606 if (TCP_SEQ_BETWEEN(seqno
, pcb
->rcv_nxt
,
607 pcb
->rcv_nxt
+pcb
->rcv_wnd
)) {
613 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_process: Connection RESET\n"));
614 LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb
->state
!= CLOSED
);
615 recv_flags
|= TF_RESET
;
616 pcb
->flags
&= ~TF_ACK_DELAY
;
619 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_process: unacceptable reset seqno %"U32_F
" rcv_nxt %"U32_F
"\n",
620 seqno
, pcb
->rcv_nxt
));
621 LWIP_DEBUGF(TCP_DEBUG
, ("tcp_process: unacceptable reset seqno %"U32_F
" rcv_nxt %"U32_F
"\n",
622 seqno
, pcb
->rcv_nxt
));
627 if ((flags
& TCP_SYN
) && (pcb
->state
!= SYN_SENT
&& pcb
->state
!= SYN_RCVD
)) {
628 /* Cope with new connection attempt after remote end crashed */
633 if ((pcb
->flags
& TF_RXCLOSED
) == 0) {
634 /* Update the PCB (in)activity timer unless rx is closed (see tcp_shutdown) */
635 pcb
->tmr
= tcp_ticks
;
637 pcb
->keep_cnt_sent
= 0;
641 /* Do different things depending on the TCP state. */
642 switch (pcb
->state
) {
644 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("SYN-SENT: ackno %"U32_F
" pcb->snd_nxt %"U32_F
" unacked %"U32_F
"\n", ackno
,
645 pcb
->snd_nxt
, ntohl(pcb
->unacked
->tcphdr
->seqno
)));
646 /* received SYN ACK with expected sequence number? */
647 if ((flags
& TCP_ACK
) && (flags
& TCP_SYN
)
648 && ackno
== ntohl(pcb
->unacked
->tcphdr
->seqno
) + 1) {
650 pcb
->rcv_nxt
= seqno
+ 1;
651 pcb
->rcv_ann_right_edge
= pcb
->rcv_nxt
;
652 pcb
->lastack
= ackno
;
653 pcb
->snd_wnd
= tcphdr
->wnd
;
654 pcb
->snd_wl1
= seqno
- 1; /* initialise to seqno - 1 to force window update */
655 pcb
->state
= ESTABLISHED
;
657 #if TCP_CALCULATE_EFF_SEND_MSS
658 pcb
->mss
= tcp_eff_send_mss(pcb
->mss
, &(pcb
->remote_ip
));
659 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
661 /* Set ssthresh again after changing pcb->mss (already set in tcp_connect
662 * but for the default value of pcb->mss) */
663 pcb
->ssthresh
= pcb
->mss
* 10;
665 pcb
->cwnd
= ((pcb
->cwnd
== 1) ? (pcb
->mss
* 2) : pcb
->mss
);
666 LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb
->snd_queuelen
> 0));
668 LWIP_DEBUGF(TCP_QLEN_DEBUG
, ("tcp_process: SYN-SENT --queuelen %"U16_F
"\n", (u16_t
)pcb
->snd_queuelen
));
670 pcb
->unacked
= rseg
->next
;
672 /* If there's nothing left to acknowledge, stop the retransmit
673 timer, otherwise reset it to start again */
674 if(pcb
->unacked
== NULL
)
683 /* Call the user specified function to call when sucessfully
685 TCP_EVENT_CONNECTED(pcb
, ERR_OK
, err
);
686 if (err
== ERR_ABRT
) {
691 /* received ACK? possibly a half-open connection */
692 else if (flags
& TCP_ACK
) {
693 /* send a RST to bring the other side in a non-synchronized state. */
694 tcp_rst(ackno
, seqno
+ tcplen
, ip_current_dest_addr(), ip_current_src_addr(),
695 tcphdr
->dest
, tcphdr
->src
);
699 if (flags
& TCP_ACK
) {
700 /* expected ACK number? */
701 if (TCP_SEQ_BETWEEN(ackno
, pcb
->lastack
+1, pcb
->snd_nxt
)) {
703 pcb
->state
= ESTABLISHED
;
704 LWIP_DEBUGF(TCP_DEBUG
, ("TCP connection established %"U16_F
" -> %"U16_F
".\n", inseg
.tcphdr
->src
, inseg
.tcphdr
->dest
));
705 #if LWIP_CALLBACK_API
706 LWIP_ASSERT("pcb->accept != NULL", pcb
->accept
!= NULL
);
708 /* Call the accept function. */
709 TCP_EVENT_ACCEPT(pcb
, ERR_OK
, err
);
711 /* If the accept function returns with an error, we abort
713 /* Already aborted? */
714 if (err
!= ERR_ABRT
) {
719 old_cwnd
= pcb
->cwnd
;
720 /* If there was any data contained within this ACK,
721 * we'd better pass it on to the application as well. */
724 /* Prevent ACK for SYN to generate a sent event */
725 if (pcb
->acked
!= 0) {
729 pcb
->cwnd
= ((old_cwnd
== 1) ? (pcb
->mss
* 2) : pcb
->mss
);
731 if (recv_flags
& TF_GOT_FIN
) {
733 pcb
->state
= CLOSE_WAIT
;
736 /* incorrect ACK number, send RST */
737 tcp_rst(ackno
, seqno
+ tcplen
, ip_current_dest_addr(), ip_current_src_addr(),
738 tcphdr
->dest
, tcphdr
->src
);
740 } else if ((flags
& TCP_SYN
) && (seqno
== pcb
->rcv_nxt
- 1)) {
741 /* Looks like another copy of the SYN - retransmit our SYN-ACK */
749 if (recv_flags
& TF_GOT_FIN
) { /* passive close */
751 pcb
->state
= CLOSE_WAIT
;
756 if (recv_flags
& TF_GOT_FIN
) {
757 if ((flags
& TCP_ACK
) && (ackno
== pcb
->snd_nxt
)) {
758 LWIP_DEBUGF(TCP_DEBUG
,
759 ("TCP connection closed: FIN_WAIT_1 %"U16_F
" -> %"U16_F
".\n", inseg
.tcphdr
->src
, inseg
.tcphdr
->dest
));
762 TCP_RMV(&tcp_active_pcbs
, pcb
);
763 pcb
->state
= TIME_WAIT
;
764 TCP_REG(&tcp_tw_pcbs
, pcb
);
767 pcb
->state
= CLOSING
;
769 } else if ((flags
& TCP_ACK
) && (ackno
== pcb
->snd_nxt
)) {
770 pcb
->state
= FIN_WAIT_2
;
775 if (recv_flags
& TF_GOT_FIN
) {
776 LWIP_DEBUGF(TCP_DEBUG
, ("TCP connection closed: FIN_WAIT_2 %"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: CLOSING %"U16_F
" -> %"U16_F
".\n", inseg
.tcphdr
->src
, inseg
.tcphdr
->dest
));
789 TCP_RMV(&tcp_active_pcbs
, pcb
);
790 pcb
->state
= TIME_WAIT
;
791 TCP_REG(&tcp_tw_pcbs
, pcb
);
796 if (flags
& TCP_ACK
&& ackno
== pcb
->snd_nxt
) {
797 LWIP_DEBUGF(TCP_DEBUG
, ("TCP connection closed: LAST_ACK %"U16_F
" -> %"U16_F
".\n", inseg
.tcphdr
->src
, inseg
.tcphdr
->dest
));
798 /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */
799 recv_flags
|= TF_CLOSED
;
810 * Insert segment into the list (segments covered with new one will be deleted)
812 * Called from tcp_receive()
815 tcp_oos_insert_segment(struct tcp_seg
*cseg
, struct tcp_seg
*next
)
817 struct tcp_seg
*old_seg
;
819 if (TCPH_FLAGS(cseg
->tcphdr
) & TCP_FIN
) {
820 /* received segment overlaps all following segments */
825 /* delete some following segments
826 oos queue may have segments with FIN flag */
828 TCP_SEQ_GEQ((seqno
+ cseg
->len
),
829 (next
->tcphdr
->seqno
+ next
->len
))) {
830 /* cseg with FIN already processed */
831 if (TCPH_FLAGS(next
->tcphdr
) & TCP_FIN
) {
832 TCPH_SET_FLAG(cseg
->tcphdr
, TCP_FIN
);
836 tcp_seg_free(old_seg
);
839 TCP_SEQ_GT(seqno
+ cseg
->len
, next
->tcphdr
->seqno
)) {
840 /* We need to trim the incoming segment. */
841 cseg
->len
= (u16_t
)(next
->tcphdr
->seqno
- seqno
);
842 pbuf_realloc(cseg
->p
, cseg
->len
);
847 #endif /* TCP_QUEUE_OOSEQ */
850 * Called by tcp_process. Checks if the given segment is an ACK for outstanding
851 * data, and if so frees the memory of the buffered data. Next, is places the
852 * segment on any of the receive queues (pcb->recved or pcb->ooseq). If the segment
853 * is buffered, the pbuf is referenced by pbuf_ref so that it will not be freed until
854 * i it has been removed from the buffer.
856 * If the incoming segment constitutes an ACK for a segment that was used for RTT
857 * estimation, the RTT is estimated here as well.
859 * Called from tcp_process().
862 tcp_receive(struct tcp_pcb
*pcb
)
864 struct tcp_seg
*next
;
866 struct tcp_seg
*prev
, *cseg
;
867 #endif /* TCP_QUEUE_OOSEQ */
871 u32_t right_wnd_edge
;
873 int found_dupack
= 0;
875 if (flags
& TCP_ACK
) {
876 right_wnd_edge
= pcb
->snd_wnd
+ pcb
->snd_wl2
;
879 if (TCP_SEQ_LT(pcb
->snd_wl1
, seqno
) ||
880 (pcb
->snd_wl1
== seqno
&& TCP_SEQ_LT(pcb
->snd_wl2
, ackno
)) ||
881 (pcb
->snd_wl2
== ackno
&& tcphdr
->wnd
> pcb
->snd_wnd
)) {
882 pcb
->snd_wnd
= tcphdr
->wnd
;
883 pcb
->snd_wl1
= seqno
;
884 pcb
->snd_wl2
= ackno
;
885 if (pcb
->snd_wnd
> 0 && pcb
->persist_backoff
> 0) {
886 pcb
->persist_backoff
= 0;
888 LWIP_DEBUGF(TCP_WND_DEBUG
, ("tcp_receive: window update %"U16_F
"\n", pcb
->snd_wnd
));
891 if (pcb
->snd_wnd
!= tcphdr
->wnd
) {
892 LWIP_DEBUGF(TCP_WND_DEBUG
,
893 ("tcp_receive: no window update lastack %"U32_F
" ackno %"
894 U32_F
" wl1 %"U32_F
" seqno %"U32_F
" wl2 %"U32_F
"\n",
895 pcb
->lastack
, ackno
, pcb
->snd_wl1
, seqno
, pcb
->snd_wl2
));
897 #endif /* TCP_WND_DEBUG */
900 /* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a
902 * 1) It doesn't ACK new data
903 * 2) length of received packet is zero (i.e. no payload)
904 * 3) the advertised window hasn't changed
905 * 4) There is outstanding unacknowledged data (retransmission timer running)
906 * 5) The ACK is == biggest ACK sequence number so far seen (snd_una)
908 * If it passes all five, should process as a dupack:
909 * a) dupacks < 3: do nothing
910 * b) dupacks == 3: fast retransmit
911 * c) dupacks > 3: increase cwnd
913 * If it only passes 1-3, should reset dupack counter (and add to
914 * stats, which we don't do in lwIP)
916 * If it only passes 1, should reset dupack counter
921 if (TCP_SEQ_LEQ(ackno
, pcb
->lastack
)) {
926 if (pcb
->snd_wl2
+ pcb
->snd_wnd
== right_wnd_edge
){
928 if (pcb
->rtime
>= 0) {
930 if (pcb
->lastack
== ackno
) {
932 if (pcb
->dupacks
+ 1 > pcb
->dupacks
)
934 if (pcb
->dupacks
> 3) {
935 /* Inflate the congestion window, but not if it means that
936 the value overflows. */
937 if ((u16_t
)(pcb
->cwnd
+ pcb
->mss
) > pcb
->cwnd
) {
938 pcb
->cwnd
+= pcb
->mss
;
940 } else if (pcb
->dupacks
== 3) {
941 /* Do fast retransmit */
942 tcp_rexmit_fast(pcb
);
948 /* If Clause (1) or more is true, but not a duplicate ack, reset
949 * count of consecutive duplicate acks */
953 } else if (TCP_SEQ_BETWEEN(ackno
, pcb
->lastack
+1, pcb
->snd_nxt
)){
954 /* We come here when the ACK acknowledges new data. */
956 /* Reset the "IN Fast Retransmit" flag, since we are no longer
957 in fast retransmit. Also reset the congestion window to the
958 slow start threshold. */
959 if (pcb
->flags
& TF_INFR
) {
960 pcb
->flags
&= ~TF_INFR
;
961 pcb
->cwnd
= pcb
->ssthresh
;
964 /* Reset the number of retransmissions. */
967 /* Reset the retransmission time-out. */
968 pcb
->rto
= (pcb
->sa
>> 3) + pcb
->sv
;
970 /* Update the send buffer space. Diff between the two can never exceed 64K? */
971 pcb
->acked
= (u16_t
)(ackno
- pcb
->lastack
);
973 pcb
->snd_buf
+= pcb
->acked
;
975 /* Reset the fast retransmit variables. */
977 pcb
->lastack
= ackno
;
979 /* Update the congestion control variables (cwnd and
981 if (pcb
->state
>= ESTABLISHED
) {
982 if (pcb
->cwnd
< pcb
->ssthresh
) {
983 if ((u16_t
)(pcb
->cwnd
+ pcb
->mss
) > pcb
->cwnd
) {
984 pcb
->cwnd
+= pcb
->mss
;
986 LWIP_DEBUGF(TCP_CWND_DEBUG
, ("tcp_receive: slow start cwnd %"U16_F
"\n", pcb
->cwnd
));
988 u16_t new_cwnd
= (pcb
->cwnd
+ pcb
->mss
* pcb
->mss
/ pcb
->cwnd
);
989 if (new_cwnd
> pcb
->cwnd
) {
990 pcb
->cwnd
= new_cwnd
;
992 LWIP_DEBUGF(TCP_CWND_DEBUG
, ("tcp_receive: congestion avoidance cwnd %"U16_F
"\n", pcb
->cwnd
));
995 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_receive: ACK for %"U32_F
", unacked->seqno %"U32_F
":%"U32_F
"\n",
997 pcb
->unacked
!= NULL
?
998 ntohl(pcb
->unacked
->tcphdr
->seqno
): 0,
999 pcb
->unacked
!= NULL
?
1000 ntohl(pcb
->unacked
->tcphdr
->seqno
) + TCP_TCPLEN(pcb
->unacked
): 0));
1002 /* Remove segment from the unacknowledged list if the incoming
1003 ACK acknowlegdes them. */
1004 while (pcb
->unacked
!= NULL
&&
1005 TCP_SEQ_LEQ(ntohl(pcb
->unacked
->tcphdr
->seqno
) +
1006 TCP_TCPLEN(pcb
->unacked
), ackno
)) {
1007 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_receive: removing %"U32_F
":%"U32_F
" from pcb->unacked\n",
1008 ntohl(pcb
->unacked
->tcphdr
->seqno
),
1009 ntohl(pcb
->unacked
->tcphdr
->seqno
) +
1010 TCP_TCPLEN(pcb
->unacked
)));
1012 next
= pcb
->unacked
;
1013 pcb
->unacked
= pcb
->unacked
->next
;
1015 LWIP_DEBUGF(TCP_QLEN_DEBUG
, ("tcp_receive: queuelen %"U16_F
" ... ", (u16_t
)pcb
->snd_queuelen
));
1016 LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb
->snd_queuelen
>= pbuf_clen(next
->p
)));
1017 /* Prevent ACK for FIN to generate a sent event */
1018 if ((pcb
->acked
!= 0) && ((TCPH_FLAGS(next
->tcphdr
) & TCP_FIN
) != 0)) {
1022 pcb
->snd_queuelen
-= pbuf_clen(next
->p
);
1025 LWIP_DEBUGF(TCP_QLEN_DEBUG
, ("%"U16_F
" (after freeing unacked)\n", (u16_t
)pcb
->snd_queuelen
));
1026 if (pcb
->snd_queuelen
!= 0) {
1027 LWIP_ASSERT("tcp_receive: valid queue length", pcb
->unacked
!= NULL
||
1028 pcb
->unsent
!= NULL
);
1032 /* If there's nothing left to acknowledge, stop the retransmit
1033 timer, otherwise reset it to start again */
1034 if(pcb
->unacked
== NULL
)
1041 /* Fix bug bug #21582: out of sequence ACK, didn't really ack anything */
1045 /* We go through the ->unsent list to see if any of the segments
1046 on the list are acknowledged by the ACK. This may seem
1047 strange since an "unsent" segment shouldn't be acked. The
1048 rationale is that lwIP puts all outstanding segments on the
1049 ->unsent list after a retransmission, so these segments may
1050 in fact have been sent once. */
1051 while (pcb
->unsent
!= NULL
&&
1052 TCP_SEQ_BETWEEN(ackno
, ntohl(pcb
->unsent
->tcphdr
->seqno
) +
1053 TCP_TCPLEN(pcb
->unsent
), pcb
->snd_nxt
)) {
1054 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_receive: removing %"U32_F
":%"U32_F
" from pcb->unsent\n",
1055 ntohl(pcb
->unsent
->tcphdr
->seqno
), ntohl(pcb
->unsent
->tcphdr
->seqno
) +
1056 TCP_TCPLEN(pcb
->unsent
)));
1059 pcb
->unsent
= pcb
->unsent
->next
;
1060 LWIP_DEBUGF(TCP_QLEN_DEBUG
, ("tcp_receive: queuelen %"U16_F
" ... ", (u16_t
)pcb
->snd_queuelen
));
1061 LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb
->snd_queuelen
>= pbuf_clen(next
->p
)));
1062 /* Prevent ACK for FIN to generate a sent event */
1063 if ((pcb
->acked
!= 0) && ((TCPH_FLAGS(next
->tcphdr
) & TCP_FIN
) != 0)) {
1066 pcb
->snd_queuelen
-= pbuf_clen(next
->p
);
1068 LWIP_DEBUGF(TCP_QLEN_DEBUG
, ("%"U16_F
" (after freeing unsent)\n", (u16_t
)pcb
->snd_queuelen
));
1069 if (pcb
->snd_queuelen
!= 0) {
1070 LWIP_ASSERT("tcp_receive: valid queue length",
1071 pcb
->unacked
!= NULL
|| pcb
->unsent
!= NULL
);
1074 /* End of ACK for new data processing. */
1076 LWIP_DEBUGF(TCP_RTO_DEBUG
, ("tcp_receive: pcb->rttest %"U32_F
" rtseq %"U32_F
" ackno %"U32_F
"\n",
1077 pcb
->rttest
, pcb
->rtseq
, ackno
));
1079 /* RTT estimation calculations. This is done by checking if the
1080 incoming segment acknowledges the segment we use to take a
1081 round-trip time measurement. */
1082 if (pcb
->rttest
&& TCP_SEQ_LT(pcb
->rtseq
, ackno
)) {
1083 /* diff between this shouldn't exceed 32K since this are tcp timer ticks
1084 and a round-trip shouldn't be that long... */
1085 m
= (s16_t
)(tcp_ticks
- pcb
->rttest
);
1087 LWIP_DEBUGF(TCP_RTO_DEBUG
, ("tcp_receive: experienced rtt %"U16_F
" ticks (%"U16_F
" msec).\n",
1088 m
, m
* TCP_SLOW_INTERVAL
));
1090 /* This is taken directly from VJs original code in his paper */
1091 m
= m
- (pcb
->sa
>> 3);
1096 m
= m
- (pcb
->sv
>> 2);
1098 pcb
->rto
= (pcb
->sa
>> 3) + pcb
->sv
;
1100 LWIP_DEBUGF(TCP_RTO_DEBUG
, ("tcp_receive: RTO %"U16_F
" (%"U16_F
" milliseconds)\n",
1101 pcb
->rto
, pcb
->rto
* TCP_SLOW_INTERVAL
));
1107 /* If the incoming segment contains data, we must process it
1110 /* This code basically does three things:
1112 +) If the incoming segment contains data that is the next
1113 in-sequence data, this data is passed to the application. This
1114 might involve trimming the first edge of the data. The rcv_nxt
1115 variable and the advertised window are adjusted.
1117 +) If the incoming segment has data that is above the next
1118 sequence number expected (->rcv_nxt), the segment is placed on
1119 the ->ooseq queue. This is done by finding the appropriate
1120 place in the ->ooseq queue (which is ordered by sequence
1121 number) and trim the segment in both ends if needed. An
1122 immediate ACK is sent to indicate that we received an
1123 out-of-sequence segment.
1125 +) Finally, we check if the first segment on the ->ooseq queue
1126 now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If
1127 rcv_nxt > ooseq->seqno, we must trim the first edge of the
1128 segment on ->ooseq before we adjust rcv_nxt. The data in the
1129 segments that are now on sequence are chained onto the
1130 incoming segment so that we only need to call the application
1134 /* First, we check if we must trim the first edge. We have to do
1135 this if the sequence number of the incoming segment is less
1136 than rcv_nxt, and the sequence number plus the length of the
1137 segment is larger than rcv_nxt. */
1138 /* if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){
1139 if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/
1140 if (TCP_SEQ_BETWEEN(pcb
->rcv_nxt
, seqno
+ 1, seqno
+ tcplen
- 1)){
1141 /* Trimming the first edge is done by pushing the payload
1142 pointer in the pbuf downwards. This is somewhat tricky since
1143 we do not want to discard the full contents of the pbuf up to
1144 the new starting point of the data since we have to keep the
1145 TCP header which is present in the first pbuf in the chain.
1147 What is done is really quite a nasty hack: the first pbuf in
1148 the pbuf chain is pointed to by inseg.p. Since we need to be
1149 able to deallocate the whole pbuf, we cannot change this
1150 inseg.p pointer to point to any of the later pbufs in the
1151 chain. Instead, we point the ->payload pointer in the first
1152 pbuf to data in one of the later pbufs. We also set the
1153 inseg.data pointer to point to the right place. This way, the
1154 ->p pointer will still point to the first pbuf, but the
1155 ->p->payload pointer will point to data in another pbuf.
1157 After we are done with adjusting the pbuf pointers we must
1158 adjust the ->data pointer in the seg and the segment
1161 off
= pcb
->rcv_nxt
- seqno
;
1163 LWIP_ASSERT("inseg.p != NULL", inseg
.p
);
1164 LWIP_ASSERT("insane offset!", (off
< 0x7fff));
1165 if (inseg
.p
->len
< off
) {
1166 LWIP_ASSERT("pbuf too short!", (((s32_t
)inseg
.p
->tot_len
) >= off
));
1167 new_tot_len
= (u16_t
)(inseg
.p
->tot_len
- off
);
1168 while (p
->len
< off
) {
1170 /* KJM following line changed (with addition of new_tot_len var)
1172 inseg.p->tot_len -= p->len; */
1173 p
->tot_len
= new_tot_len
;
1177 if(pbuf_header(p
, (s16_t
)-off
)) {
1178 /* Do we need to cope with this failing? Assert for now */
1179 LWIP_ASSERT("pbuf_header failed", 0);
1182 if(pbuf_header(inseg
.p
, (s16_t
)-off
)) {
1183 /* Do we need to cope with this failing? Assert for now */
1184 LWIP_ASSERT("pbuf_header failed", 0);
1187 inseg
.len
-= (u16_t
)(pcb
->rcv_nxt
- seqno
);
1188 inseg
.tcphdr
->seqno
= seqno
= pcb
->rcv_nxt
;
1191 if (TCP_SEQ_LT(seqno
, pcb
->rcv_nxt
)){
1192 /* the whole segment is < rcv_nxt */
1193 /* must be a duplicate of a packet that has already been correctly handled */
1195 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_receive: duplicate seqno %"U32_F
"\n", seqno
));
1200 /* The sequence number must be within the window (above rcv_nxt
1201 and below rcv_nxt + rcv_wnd) in order to be further
1203 if (TCP_SEQ_BETWEEN(seqno
, pcb
->rcv_nxt
,
1204 pcb
->rcv_nxt
+ pcb
->rcv_wnd
- 1)){
1205 if (pcb
->rcv_nxt
== seqno
) {
1206 /* The incoming segment is the next in sequence. We check if
1207 we have to trim the end of the segment and update rcv_nxt
1208 and pass the data to the application. */
1209 tcplen
= TCP_TCPLEN(&inseg
);
1211 if (tcplen
> pcb
->rcv_wnd
) {
1212 LWIP_DEBUGF(TCP_INPUT_DEBUG
,
1213 ("tcp_receive: other end overran receive window"
1214 "seqno %"U32_F
" len %"U16_F
" right edge %"U32_F
"\n",
1215 seqno
, tcplen
, pcb
->rcv_nxt
+ pcb
->rcv_wnd
));
1216 if (TCPH_FLAGS(inseg
.tcphdr
) & TCP_FIN
) {
1217 /* Must remove the FIN from the header as we're trimming
1218 * that byte of sequence-space from the packet */
1219 TCPH_FLAGS_SET(inseg
.tcphdr
, TCPH_FLAGS(inseg
.tcphdr
) &~ TCP_FIN
);
1221 /* Adjust length of segment to fit in the window. */
1222 inseg
.len
= pcb
->rcv_wnd
;
1223 if (TCPH_FLAGS(inseg
.tcphdr
) & TCP_SYN
) {
1226 pbuf_realloc(inseg
.p
, inseg
.len
);
1227 tcplen
= TCP_TCPLEN(&inseg
);
1228 LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n",
1229 (seqno
+ tcplen
) == (pcb
->rcv_nxt
+ pcb
->rcv_wnd
));
1232 /* Received in-sequence data, adjust ooseq data if:
1233 - FIN has been received or
1234 - inseq overlaps with ooseq */
1235 if (pcb
->ooseq
!= NULL
) {
1236 if (TCPH_FLAGS(inseg
.tcphdr
) & TCP_FIN
) {
1237 LWIP_DEBUGF(TCP_INPUT_DEBUG
,
1238 ("tcp_receive: received in-order FIN, binning ooseq queue\n"));
1239 /* Received in-order FIN means anything that was received
1240 * out of order must now have been received in-order, so
1241 * bin the ooseq queue */
1242 while (pcb
->ooseq
!= NULL
) {
1243 struct tcp_seg
*old_ooseq
= pcb
->ooseq
;
1244 pcb
->ooseq
= pcb
->ooseq
->next
;
1245 tcp_seg_free(old_ooseq
);
1250 /* Remove all segments on ooseq that are covered by inseg already.
1251 * FIN is copied from ooseq to inseg if present. */
1253 TCP_SEQ_GEQ(seqno
+ tcplen
,
1254 next
->tcphdr
->seqno
+ next
->len
)) {
1255 /* inseg cannot have FIN here (already processed above) */
1256 if (TCPH_FLAGS(next
->tcphdr
) & TCP_FIN
&&
1257 (TCPH_FLAGS(inseg
.tcphdr
) & TCP_SYN
) == 0) {
1258 TCPH_SET_FLAG(inseg
.tcphdr
, TCP_FIN
);
1259 tcplen
= TCP_TCPLEN(&inseg
);
1265 /* Now trim right side of inseg if it overlaps with the first
1266 * segment on ooseq */
1268 TCP_SEQ_GT(seqno
+ tcplen
,
1269 next
->tcphdr
->seqno
)) {
1270 /* inseg cannot have FIN here (already processed above) */
1271 inseg
.len
= (u16_t
)(next
->tcphdr
->seqno
- seqno
);
1272 if (TCPH_FLAGS(inseg
.tcphdr
) & TCP_SYN
) {
1275 pbuf_realloc(inseg
.p
, inseg
.len
);
1276 tcplen
= TCP_TCPLEN(&inseg
);
1277 LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n",
1278 (seqno
+ tcplen
) == next
->tcphdr
->seqno
);
1283 #endif /* TCP_QUEUE_OOSEQ */
1285 pcb
->rcv_nxt
= seqno
+ tcplen
;
1287 /* Update the receiver's (our) window. */
1288 LWIP_ASSERT("tcp_receive: tcplen > rcv_wnd\n", pcb
->rcv_wnd
>= tcplen
);
1289 pcb
->rcv_wnd
-= tcplen
;
1291 tcp_update_rcv_ann_wnd(pcb
);
1293 /* If there is data in the segment, we make preparations to
1294 pass this up to the application. The ->recv_data variable
1295 is used for holding the pbuf that goes to the
1296 application. The code for reassembling out-of-sequence data
1297 chains its data on this pbuf as well.
1299 If the segment was a FIN, we set the TF_GOT_FIN flag that will
1300 be used to indicate to the application that the remote side has
1301 closed its end of the connection. */
1302 if (inseg
.p
->tot_len
> 0) {
1303 recv_data
= inseg
.p
;
1304 /* Since this pbuf now is the responsibility of the
1305 application, we delete our reference to it so that we won't
1306 (mistakingly) deallocate it. */
1309 if (TCPH_FLAGS(inseg
.tcphdr
) & TCP_FIN
) {
1310 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_receive: received FIN.\n"));
1311 recv_flags
|= TF_GOT_FIN
;
1315 /* We now check if we have segments on the ->ooseq queue that
1316 are now in sequence. */
1317 while (pcb
->ooseq
!= NULL
&&
1318 pcb
->ooseq
->tcphdr
->seqno
== pcb
->rcv_nxt
) {
1321 seqno
= pcb
->ooseq
->tcphdr
->seqno
;
1323 pcb
->rcv_nxt
+= TCP_TCPLEN(cseg
);
1324 LWIP_ASSERT("tcp_receive: ooseq tcplen > rcv_wnd\n",
1325 pcb
->rcv_wnd
>= TCP_TCPLEN(cseg
));
1326 pcb
->rcv_wnd
-= TCP_TCPLEN(cseg
);
1328 tcp_update_rcv_ann_wnd(pcb
);
1330 if (cseg
->p
->tot_len
> 0) {
1331 /* Chain this pbuf onto the pbuf that we will pass to
1334 pbuf_cat(recv_data
, cseg
->p
);
1336 recv_data
= cseg
->p
;
1340 if (TCPH_FLAGS(cseg
->tcphdr
) & TCP_FIN
) {
1341 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_receive: dequeued FIN.\n"));
1342 recv_flags
|= TF_GOT_FIN
;
1343 if (pcb
->state
== ESTABLISHED
) { /* force passive close or we can move to active close */
1344 pcb
->state
= CLOSE_WAIT
;
1348 pcb
->ooseq
= cseg
->next
;
1351 #endif /* TCP_QUEUE_OOSEQ */
1354 /* Acknowledge the segment(s). */
1358 /* We get here if the incoming segment is out-of-sequence. */
1359 tcp_send_empty_ack(pcb
);
1361 /* We queue the segment on the ->ooseq queue. */
1362 if (pcb
->ooseq
== NULL
) {
1363 pcb
->ooseq
= tcp_seg_copy(&inseg
);
1365 /* If the queue is not empty, we walk through the queue and
1366 try to find a place where the sequence number of the
1367 incoming segment is between the sequence numbers of the
1368 previous and the next segment on the ->ooseq queue. That is
1369 the place where we put the incoming segment. If needed, we
1370 trim the second edges of the previous and the incoming
1371 segment so that it will fit into the sequence.
1373 If the incoming segment has the same sequence number as a
1374 segment on the ->ooseq queue, we discard the segment that
1375 contains less data. */
1378 for(next
= pcb
->ooseq
; next
!= NULL
; next
= next
->next
) {
1379 if (seqno
== next
->tcphdr
->seqno
) {
1380 /* The sequence number of the incoming segment is the
1381 same as the sequence number of the segment on
1382 ->ooseq. We check the lengths to see which one to
1384 if (inseg
.len
> next
->len
) {
1385 /* The incoming segment is larger than the old
1386 segment. We replace some segments with the new
1388 cseg
= tcp_seg_copy(&inseg
);
1395 tcp_oos_insert_segment(cseg
, next
);
1399 /* Either the lenghts are the same or the incoming
1400 segment was smaller than the old one; in either
1401 case, we ditch the incoming segment. */
1406 if (TCP_SEQ_LT(seqno
, next
->tcphdr
->seqno
)) {
1407 /* The sequence number of the incoming segment is lower
1408 than the sequence number of the first segment on the
1409 queue. We put the incoming segment first on the
1411 cseg
= tcp_seg_copy(&inseg
);
1414 tcp_oos_insert_segment(cseg
, next
);
1419 /*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) &&
1420 TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/
1421 if (TCP_SEQ_BETWEEN(seqno
, prev
->tcphdr
->seqno
+1, next
->tcphdr
->seqno
-1)) {
1422 /* The sequence number of the incoming segment is in
1423 between the sequence numbers of the previous and
1424 the next segment on ->ooseq. We trim trim the previous
1425 segment, delete next segments that included in received segment
1426 and trim received, if needed. */
1427 cseg
= tcp_seg_copy(&inseg
);
1429 if (TCP_SEQ_GT(prev
->tcphdr
->seqno
+ prev
->len
, seqno
)) {
1430 /* We need to trim the prev segment. */
1431 prev
->len
= (u16_t
)(seqno
- prev
->tcphdr
->seqno
);
1432 pbuf_realloc(prev
->p
, prev
->len
);
1435 tcp_oos_insert_segment(cseg
, next
);
1440 /* If the "next" segment is the last segment on the
1441 ooseq queue, we add the incoming segment to the end
1443 if (next
->next
== NULL
&&
1444 TCP_SEQ_GT(seqno
, next
->tcphdr
->seqno
)) {
1445 if (TCPH_FLAGS(next
->tcphdr
) & TCP_FIN
) {
1446 /* segment "next" already contains all data */
1449 next
->next
= tcp_seg_copy(&inseg
);
1450 if (next
->next
!= NULL
) {
1451 if (TCP_SEQ_GT(next
->tcphdr
->seqno
+ next
->len
, seqno
)) {
1452 /* We need to trim the last segment. */
1453 next
->len
= (u16_t
)(seqno
- next
->tcphdr
->seqno
);
1454 pbuf_realloc(next
->p
, next
->len
);
1456 /* check if the remote side overruns our receive window */
1457 if ((u32_t
)tcplen
+ seqno
> pcb
->rcv_nxt
+ (u32_t
)pcb
->rcv_wnd
) {
1458 LWIP_DEBUGF(TCP_INPUT_DEBUG
,
1459 ("tcp_receive: other end overran receive window"
1460 "seqno %"U32_F
" len %"U16_F
" right edge %"U32_F
"\n",
1461 seqno
, tcplen
, pcb
->rcv_nxt
+ pcb
->rcv_wnd
));
1462 if (TCPH_FLAGS(next
->next
->tcphdr
) & TCP_FIN
) {
1463 /* Must remove the FIN from the header as we're trimming
1464 * that byte of sequence-space from the packet */
1465 TCPH_FLAGS_SET(next
->next
->tcphdr
, TCPH_FLAGS(next
->next
->tcphdr
) &~ TCP_FIN
);
1467 /* Adjust length of segment to fit in the window. */
1468 next
->next
->len
= pcb
->rcv_nxt
+ pcb
->rcv_wnd
- seqno
;
1469 pbuf_realloc(next
->next
->p
, next
->next
->len
);
1470 tcplen
= TCP_TCPLEN(next
->next
);
1471 LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n",
1472 (seqno
+ tcplen
) == (pcb
->rcv_nxt
+ pcb
->rcv_wnd
));
1481 #endif /* TCP_QUEUE_OOSEQ */
1485 /* The incoming segment is not withing the window. */
1486 tcp_send_empty_ack(pcb
);
1489 /* Segments with length 0 is taken care of here. Segments that
1490 fall out of the window are ACKed. */
1491 /*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) ||
1492 TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/
1493 if(!TCP_SEQ_BETWEEN(seqno
, pcb
->rcv_nxt
, pcb
->rcv_nxt
+ pcb
->rcv_wnd
-1)){
1500 * Parses the options contained in the incoming segment.
1502 * Called from tcp_listen_input() and tcp_process().
1503 * Currently, only the MSS option is supported!
1505 * @param pcb the tcp_pcb for which a segment arrived
1508 tcp_parseopt(struct tcp_pcb
*pcb
)
1513 #if LWIP_TCP_TIMESTAMPS
1517 opts
= (u8_t
*)tcphdr
+ TCP_HLEN
;
1519 /* Parse the TCP MSS option, if present. */
1520 if(TCPH_HDRLEN(tcphdr
) > 0x5) {
1521 max_c
= (TCPH_HDRLEN(tcphdr
) - 5) << 2;
1522 for (c
= 0; c
< max_c
; ) {
1526 /* End of options. */
1527 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_parseopt: EOL\n"));
1532 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_parseopt: NOP\n"));
1535 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_parseopt: MSS\n"));
1536 if (opts
[c
+ 1] != 0x04 || c
+ 0x04 > max_c
) {
1538 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_parseopt: bad length\n"));
1541 /* An MSS option with the right option length. */
1542 mss
= (opts
[c
+ 2] << 8) | opts
[c
+ 3];
1543 /* Limit the mss to the configured TCP_MSS and prevent division by zero */
1544 pcb
->mss
= ((mss
> TCP_MSS
) || (mss
== 0)) ? TCP_MSS
: mss
;
1545 /* Advance to next option */
1548 #if LWIP_TCP_TIMESTAMPS
1550 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_parseopt: TS\n"));
1551 if (opts
[c
+ 1] != 0x0A || c
+ 0x0A > max_c
) {
1553 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_parseopt: bad length\n"));
1556 /* TCP timestamp option with valid length */
1557 tsval
= (opts
[c
+2]) | (opts
[c
+3] << 8) |
1558 (opts
[c
+4] << 16) | (opts
[c
+5] << 24);
1559 if (flags
& TCP_SYN
) {
1560 pcb
->ts_recent
= ntohl(tsval
);
1561 pcb
->flags
|= TF_TIMESTAMP
;
1562 } else if (TCP_SEQ_BETWEEN(pcb
->ts_lastacksent
, seqno
, seqno
+tcplen
)) {
1563 pcb
->ts_recent
= ntohl(tsval
);
1565 /* Advance to next option */
1570 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_parseopt: other\n"));
1571 if (opts
[c
+ 1] == 0) {
1572 LWIP_DEBUGF(TCP_INPUT_DEBUG
, ("tcp_parseopt: bad length\n"));
1573 /* If the length field is zero, the options are malformed
1574 and we don't process them further. */
1577 /* All other options have a length field, so that we easily
1578 can skip past them. */
1585 #endif /* LWIP_TCP */