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