OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [Common/] [ethernet/] [lwIP_132/] [src/] [core/] [tcp_in.c] - Blame information for rev 606

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 606 jeremybenn
/**
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. */
63
static struct tcp_seg inseg;
64
static struct tcp_hdr *tcphdr;
65
static struct ip_hdr *iphdr;
66
static u32_t seqno, ackno;
67
static u8_t flags;
68
static u16_t tcplen;
69
 
70
static u8_t recv_flags;
71
static struct pbuf *recv_data;
72
 
73
struct tcp_pcb *tcp_input_pcb;
74
 
75
/* Forward declarations. */
76
static err_t tcp_process(struct tcp_pcb *pcb);
77
static void tcp_receive(struct tcp_pcb *pcb);
78
static void tcp_parseopt(struct tcp_pcb *pcb);
79
 
80
static err_t tcp_listen_input(struct tcp_pcb_listen *pcb);
81
static 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
 */
92
void
93
tcp_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);
173
  tcplen = p->tot_len + ((flags & (TCP_FIN | 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
    tcp_input_pcb = pcb;
292
    err = tcp_process(pcb);
293
    /* A return value of ERR_ABRT means that tcp_abort() was called
294
       and that the pcb has been freed. If so, we don't do anything. */
295
    if (err != ERR_ABRT) {
296
      if (recv_flags & TF_RESET) {
297
        /* TF_RESET means that the connection was reset by the other
298
           end. We then call the error callback to inform the
299
           application that the connection is dead before we
300
           deallocate the PCB. */
301
        TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST);
302
        tcp_pcb_remove(&tcp_active_pcbs, pcb);
303
        memp_free(MEMP_TCP_PCB, pcb);
304
      } else if (recv_flags & TF_CLOSED) {
305
        /* The connection has been closed and we will deallocate the
306
           PCB. */
307
        tcp_pcb_remove(&tcp_active_pcbs, pcb);
308
        memp_free(MEMP_TCP_PCB, pcb);
309
      } else {
310
        err = ERR_OK;
311
        /* If the application has registered a "sent" function to be
312
           called when new send buffer space is available, we call it
313
           now. */
314
        if (pcb->acked > 0) {
315
          TCP_EVENT_SENT(pcb, pcb->acked, err);
316
        }
317
 
318
        if (recv_data != NULL) {
319
          if(flags & TCP_PSH) {
320
            recv_data->flags |= PBUF_FLAG_PUSH;
321
          }
322
 
323
          /* Notify application that data has been received. */
324
          TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err);
325
 
326
          /* If the upper layer can't receive this data, store it */
327
          if (err != ERR_OK) {
328
            pcb->refused_data = recv_data;
329
            LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: keep incoming packet, because pcb is \"full\"\n"));
330
          }
331
        }
332
 
333
        /* If a FIN segment was received, we call the callback
334
           function with a NULL buffer to indicate EOF. */
335
        if (recv_flags & TF_GOT_FIN) {
336
          TCP_EVENT_RECV(pcb, NULL, ERR_OK, err);
337
        }
338
 
339
        tcp_input_pcb = NULL;
340
        /* Try to send something out. */
341
        tcp_output(pcb);
342
#if TCP_INPUT_DEBUG
343
#if TCP_DEBUG
344
        tcp_debug_print_state(pcb->state);
345
#endif /* TCP_DEBUG */
346
#endif /* TCP_INPUT_DEBUG */
347
      }
348
    }
349
    tcp_input_pcb = NULL;
350
 
351
 
352
    /* give up our reference to inseg.p */
353
    if (inseg.p != NULL)
354
    {
355
      pbuf_free(inseg.p);
356
      inseg.p = NULL;
357
    }
358
  } else {
359
 
360
    /* If no matching PCB was found, send a TCP RST (reset) to the
361
       sender. */
362
    LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n"));
363
    if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) {
364
      TCP_STATS_INC(tcp.proterr);
365
      TCP_STATS_INC(tcp.drop);
366
      tcp_rst(ackno, seqno + tcplen,
367
        &(iphdr->dest), &(iphdr->src),
368
        tcphdr->dest, tcphdr->src);
369
    }
370
    pbuf_free(p);
371
  }
372
 
373
  LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());
374
  PERF_STOP("tcp_input");
375
}
376
 
377
/**
378
 * Called by tcp_input() when a segment arrives for a listening
379
 * connection (from tcp_input()).
380
 *
381
 * @param pcb the tcp_pcb_listen for which a segment arrived
382
 * @return ERR_OK if the segment was processed
383
 *         another err_t on error
384
 *
385
 * @note the return value is not (yet?) used in tcp_input()
386
 * @note the segment which arrived is saved in global variables, therefore only the pcb
387
 *       involved is passed as a parameter to this function
388
 */
389
static err_t
390
tcp_listen_input(struct tcp_pcb_listen *pcb)
391
{
392
  struct tcp_pcb *npcb;
393
  err_t rc;
394
 
395
  /* In the LISTEN state, we check for incoming SYN segments,
396
     creates a new PCB, and responds with a SYN|ACK. */
397
  if (flags & TCP_ACK) {
398
    /* For incoming segments with the ACK flag set, respond with a
399
       RST. */
400
    LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n"));
401
    tcp_rst(ackno + 1, seqno + tcplen,
402
      &(iphdr->dest), &(iphdr->src),
403
      tcphdr->dest, tcphdr->src);
404
  } else if (flags & TCP_SYN) {
405
    LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest));
406
#if TCP_LISTEN_BACKLOG
407
    if (pcb->accepts_pending >= pcb->backlog) {
408
      LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: listen backlog exceeded for port %"U16_F"\n", tcphdr->dest));
409
      return ERR_ABRT;
410
    }
411
#endif /* TCP_LISTEN_BACKLOG */
412
    npcb = tcp_alloc(pcb->prio);
413
    /* If a new PCB could not be created (probably due to lack of memory),
414
       we don't do anything, but rely on the sender will retransmit the
415
       SYN at a time when we have more memory available. */
416
    if (npcb == NULL) {
417
      LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n"));
418
      TCP_STATS_INC(tcp.memerr);
419
      return ERR_MEM;
420
    }
421
#if TCP_LISTEN_BACKLOG
422
    pcb->accepts_pending++;
423
#endif /* TCP_LISTEN_BACKLOG */
424
    /* Set up the new PCB. */
425
    ip_addr_set(&(npcb->local_ip), &(iphdr->dest));
426
    npcb->local_port = pcb->local_port;
427
    ip_addr_set(&(npcb->remote_ip), &(iphdr->src));
428
    npcb->remote_port = tcphdr->src;
429
    npcb->state = SYN_RCVD;
430
    npcb->rcv_nxt = seqno + 1;
431
    npcb->rcv_ann_right_edge = npcb->rcv_nxt;
432
    npcb->snd_wnd = tcphdr->wnd;
433
    npcb->ssthresh = npcb->snd_wnd;
434
    npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */
435
    npcb->callback_arg = pcb->callback_arg;
436
#if LWIP_CALLBACK_API
437
    npcb->accept = pcb->accept;
438
#endif /* LWIP_CALLBACK_API */
439
    /* inherit socket options */
440
    npcb->so_options = pcb->so_options & (SOF_DEBUG|SOF_DONTROUTE|SOF_KEEPALIVE|SOF_OOBINLINE|SOF_LINGER);
441
    /* Register the new PCB so that we can begin receiving segments
442
       for it. */
443
    TCP_REG(&tcp_active_pcbs, npcb);
444
 
445
    /* Parse any options in the SYN. */
446
    tcp_parseopt(npcb);
447
#if TCP_CALCULATE_EFF_SEND_MSS
448
    npcb->mss = tcp_eff_send_mss(npcb->mss, &(npcb->remote_ip));
449
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
450
 
451
    snmp_inc_tcppassiveopens();
452
 
453
    /* Send a SYN|ACK together with the MSS option. */
454
    rc = tcp_enqueue(npcb, NULL, 0, TCP_SYN | TCP_ACK, 0, TF_SEG_OPTS_MSS
455
#if LWIP_TCP_TIMESTAMPS
456
      /* and maybe include the TIMESTAMP option */
457
     | (npcb->flags & TF_TIMESTAMP ? TF_SEG_OPTS_TS : 0)
458
#endif
459
      );
460
    if (rc != ERR_OK) {
461
      tcp_abandon(npcb, 0);
462
      return rc;
463
    }
464
    return tcp_output(npcb);
465
  }
466
  return ERR_OK;
467
}
468
 
469
/**
470
 * Called by tcp_input() when a segment arrives for a connection in
471
 * TIME_WAIT.
472
 *
473
 * @param pcb the tcp_pcb for which a segment arrived
474
 *
475
 * @note the segment which arrived is saved in global variables, therefore only the pcb
476
 *       involved is passed as a parameter to this function
477
 */
478
static err_t
479
tcp_timewait_input(struct tcp_pcb *pcb)
480
{
481
  /* RFC 1337: in TIME_WAIT, ignore RST and ACK FINs + any 'acceptable' segments */
482
  /* RFC 793 3.9 Event Processing - Segment Arrives:
483
   * - first check sequence number - we skip that one in TIME_WAIT (always
484
   *   acceptable since we only send ACKs)
485
   * - second check the RST bit (... return) */
486
  if (flags & TCP_RST)  {
487
    return ERR_OK;
488
  }
489
  /* - fourth, check the SYN bit, */
490
  if (flags & TCP_SYN) {
491
    /* If an incoming segment is not acceptable, an acknowledgment
492
       should be sent in reply */
493
    if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) {
494
      /* If the SYN is in the window it is an error, send a reset */
495
      tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src),
496
        tcphdr->dest, tcphdr->src);
497
      return ERR_OK;
498
    }
499
  } else if (flags & TCP_FIN) {
500
    /* - eighth, check the FIN bit: Remain in the TIME-WAIT state.
501
         Restart the 2 MSL time-wait timeout.*/
502
    pcb->tmr = tcp_ticks;
503
  }
504
 
505
  if ((tcplen > 0))  {
506
    /* Acknowledge data, FIN or out-of-window SYN */
507
    pcb->flags |= TF_ACK_NOW;
508
    return tcp_output(pcb);
509
  }
510
  return ERR_OK;
511
}
512
 
513
/**
514
 * Implements the TCP state machine. Called by tcp_input. In some
515
 * states tcp_receive() is called to receive data. The tcp_seg
516
 * argument will be freed by the caller (tcp_input()) unless the
517
 * recv_data pointer in the pcb is set.
518
 *
519
 * @param pcb the tcp_pcb for which a segment arrived
520
 *
521
 * @note the segment which arrived is saved in global variables, therefore only the pcb
522
 *       involved is passed as a parameter to this function
523
 */
524
static err_t
525
tcp_process(struct tcp_pcb *pcb)
526
{
527
  struct tcp_seg *rseg;
528
  u8_t acceptable = 0;
529
  err_t err;
530
 
531
  err = ERR_OK;
532
 
533
  /* Process incoming RST segments. */
534
  if (flags & TCP_RST) {
535
    /* First, determine if the reset is acceptable. */
536
    if (pcb->state == SYN_SENT) {
537
      if (ackno == pcb->snd_nxt) {
538
        acceptable = 1;
539
      }
540
    } else {
541
      if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
542
                          pcb->rcv_nxt+pcb->rcv_wnd)) {
543
        acceptable = 1;
544
      }
545
    }
546
 
547
    if (acceptable) {
548
      LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n"));
549
      LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED);
550
      recv_flags |= TF_RESET;
551
      pcb->flags &= ~TF_ACK_DELAY;
552
      return ERR_RST;
553
    } else {
554
      LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n",
555
       seqno, pcb->rcv_nxt));
556
      LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n",
557
       seqno, pcb->rcv_nxt));
558
      return ERR_OK;
559
    }
560
  }
561
 
562
  if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) {
563
    /* Cope with new connection attempt after remote end crashed */
564
    tcp_ack_now(pcb);
565
    return ERR_OK;
566
  }
567
 
568
  /* Update the PCB (in)activity timer. */
569
  pcb->tmr = tcp_ticks;
570
  pcb->keep_cnt_sent = 0;
571
 
572
  tcp_parseopt(pcb);
573
 
574
  /* Do different things depending on the TCP state. */
575
  switch (pcb->state) {
576
  case SYN_SENT:
577
    LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno,
578
     pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno)));
579
    /* received SYN ACK with expected sequence number? */
580
    if ((flags & TCP_ACK) && (flags & TCP_SYN)
581
        && ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) {
582
      pcb->snd_buf++;
583
      pcb->rcv_nxt = seqno + 1;
584
      pcb->rcv_ann_right_edge = pcb->rcv_nxt;
585
      pcb->lastack = ackno;
586
      pcb->snd_wnd = tcphdr->wnd;
587
      pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */
588
      pcb->state = ESTABLISHED;
589
 
590
#if TCP_CALCULATE_EFF_SEND_MSS
591
      pcb->mss = tcp_eff_send_mss(pcb->mss, &(pcb->remote_ip));
592
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
593
 
594
      /* Set ssthresh again after changing pcb->mss (already set in tcp_connect
595
       * but for the default value of pcb->mss) */
596
      pcb->ssthresh = pcb->mss * 10;
597
 
598
      pcb->cwnd = ((pcb->cwnd == 1) ? (pcb->mss * 2) : pcb->mss);
599
      LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0));
600
      --pcb->snd_queuelen;
601
      LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"U16_F"\n", (u16_t)pcb->snd_queuelen));
602
      rseg = pcb->unacked;
603
      pcb->unacked = rseg->next;
604
 
605
      /* If there's nothing left to acknowledge, stop the retransmit
606
         timer, otherwise reset it to start again */
607
      if(pcb->unacked == NULL)
608
        pcb->rtime = -1;
609
      else {
610
        pcb->rtime = 0;
611
        pcb->nrtx = 0;
612
      }
613
 
614
      tcp_seg_free(rseg);
615
 
616
      /* Call the user specified function to call when sucessfully
617
       * connected. */
618
      TCP_EVENT_CONNECTED(pcb, ERR_OK, err);
619
      tcp_ack_now(pcb);
620
    }
621
    /* received ACK? possibly a half-open connection */
622
    else if (flags & TCP_ACK) {
623
      /* send a RST to bring the other side in a non-synchronized state. */
624
      tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src),
625
        tcphdr->dest, tcphdr->src);
626
    }
627
    break;
628
  case SYN_RCVD:
629
    if (flags & TCP_ACK) {
630
      /* expected ACK number? */
631
      if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) {
632
        u16_t old_cwnd;
633
        pcb->state = ESTABLISHED;
634
        LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
635
#if LWIP_CALLBACK_API
636
        LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL);
637
#endif
638
        /* Call the accept function. */
639
        TCP_EVENT_ACCEPT(pcb, ERR_OK, err);
640
        if (err != ERR_OK) {
641
          /* If the accept function returns with an error, we abort
642
           * the connection. */
643
          tcp_abort(pcb);
644
          return ERR_ABRT;
645
        }
646
        old_cwnd = pcb->cwnd;
647
        /* If there was any data contained within this ACK,
648
         * we'd better pass it on to the application as well. */
649
        tcp_receive(pcb);
650
 
651
        /* Prevent ACK for SYN to generate a sent event */
652
        if (pcb->acked != 0) {
653
          pcb->acked--;
654
        }
655
 
656
        pcb->cwnd = ((old_cwnd == 1) ? (pcb->mss * 2) : pcb->mss);
657
 
658
        if (recv_flags & TF_GOT_FIN) {
659
          tcp_ack_now(pcb);
660
          pcb->state = CLOSE_WAIT;
661
        }
662
      }
663
      /* incorrect ACK number */
664
      else {
665
        /* send RST */
666
        tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src),
667
                tcphdr->dest, tcphdr->src);
668
      }
669
    } else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) {
670
      /* Looks like another copy of the SYN - retransmit our SYN-ACK */
671
      tcp_rexmit(pcb);
672
    }
673
    break;
674
  case CLOSE_WAIT:
675
    /* FALLTHROUGH */
676
  case ESTABLISHED:
677
    tcp_receive(pcb);
678
    if (recv_flags & TF_GOT_FIN) { /* passive close */
679
      tcp_ack_now(pcb);
680
      pcb->state = CLOSE_WAIT;
681
    }
682
    break;
683
  case FIN_WAIT_1:
684
    tcp_receive(pcb);
685
    if (recv_flags & TF_GOT_FIN) {
686
      if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) {
687
        LWIP_DEBUGF(TCP_DEBUG,
688
          ("TCP connection closed: FIN_WAIT_1 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
689
        tcp_ack_now(pcb);
690
        tcp_pcb_purge(pcb);
691
        TCP_RMV(&tcp_active_pcbs, pcb);
692
        pcb->state = TIME_WAIT;
693
        TCP_REG(&tcp_tw_pcbs, pcb);
694
      } else {
695
        tcp_ack_now(pcb);
696
        pcb->state = CLOSING;
697
      }
698
    } else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) {
699
      pcb->state = FIN_WAIT_2;
700
    }
701
    break;
702
  case FIN_WAIT_2:
703
    tcp_receive(pcb);
704
    if (recv_flags & TF_GOT_FIN) {
705
      LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: FIN_WAIT_2 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
706
      tcp_ack_now(pcb);
707
      tcp_pcb_purge(pcb);
708
      TCP_RMV(&tcp_active_pcbs, pcb);
709
      pcb->state = TIME_WAIT;
710
      TCP_REG(&tcp_tw_pcbs, pcb);
711
    }
712
    break;
713
  case CLOSING:
714
    tcp_receive(pcb);
715
    if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
716
      LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
717
      tcp_pcb_purge(pcb);
718
      TCP_RMV(&tcp_active_pcbs, pcb);
719
      pcb->state = TIME_WAIT;
720
      TCP_REG(&tcp_tw_pcbs, pcb);
721
    }
722
    break;
723
  case LAST_ACK:
724
    tcp_receive(pcb);
725
    if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
726
      LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: LAST_ACK %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
727
      /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */
728
      recv_flags |= TF_CLOSED;
729
    }
730
    break;
731
  default:
732
    break;
733
  }
734
  return ERR_OK;
735
}
736
 
737
#if TCP_QUEUE_OOSEQ
738
/**
739
 * Insert segment into the list (segments covered with new one will be deleted)
740
 *
741
 * Called from tcp_receive()
742
 */
743
static void
744
tcp_oos_insert_segment(struct tcp_seg *cseg, struct tcp_seg *next)
745
{
746
  struct tcp_seg *old_seg;
747
 
748
  if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
749
    /* received segment overlaps all following segments */
750
    tcp_segs_free(next);
751
    next = NULL;
752
  }
753
  else {
754
    /* delete some following segments
755
       oos queue may have segments with FIN flag */
756
    while (next &&
757
           TCP_SEQ_GEQ((seqno + cseg->len),
758
                      (next->tcphdr->seqno + next->len))) {
759
      /* cseg with FIN already processed */
760
      if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) {
761
        TCPH_FLAGS_SET(cseg->tcphdr, TCPH_FLAGS(cseg->tcphdr) | TCP_FIN);
762
      }
763
      old_seg = next;
764
      next = next->next;
765
      tcp_seg_free(old_seg);
766
    }
767
    if (next &&
768
        TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) {
769
      /* We need to trim the incoming segment. */
770
      cseg->len = (u16_t)(next->tcphdr->seqno - seqno);
771
      pbuf_realloc(cseg->p, cseg->len);
772
    }
773
  }
774
  cseg->next = next;
775
}
776
#endif
777
 
778
/**
779
 * Called by tcp_process. Checks if the given segment is an ACK for outstanding
780
 * data, and if so frees the memory of the buffered data. Next, is places the
781
 * segment on any of the receive queues (pcb->recved or pcb->ooseq). If the segment
782
 * is buffered, the pbuf is referenced by pbuf_ref so that it will not be freed until
783
 * i it has been removed from the buffer.
784
 *
785
 * If the incoming segment constitutes an ACK for a segment that was used for RTT
786
 * estimation, the RTT is estimated here as well.
787
 *
788
 * Called from tcp_process().
789
 */
790
static void
791
tcp_receive(struct tcp_pcb *pcb)
792
{
793
  struct tcp_seg *next;
794
#if TCP_QUEUE_OOSEQ
795
  struct tcp_seg *prev, *cseg;
796
#endif
797
  struct pbuf *p;
798
  s32_t off;
799
  s16_t m;
800
  u32_t right_wnd_edge;
801
  u16_t new_tot_len;
802
  int found_dupack = 0;
803
 
804
  if (flags & TCP_ACK) {
805
    right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2;
806
 
807
    /* Update window. */
808
    if (TCP_SEQ_LT(pcb->snd_wl1, seqno) ||
809
       (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) ||
810
       (pcb->snd_wl2 == ackno && tcphdr->wnd > pcb->snd_wnd)) {
811
      pcb->snd_wnd = tcphdr->wnd;
812
      pcb->snd_wl1 = seqno;
813
      pcb->snd_wl2 = ackno;
814
      if (pcb->snd_wnd > 0 && pcb->persist_backoff > 0) {
815
          pcb->persist_backoff = 0;
816
      }
817
      LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"U16_F"\n", pcb->snd_wnd));
818
#if TCP_WND_DEBUG
819
    } else {
820
      if (pcb->snd_wnd != tcphdr->wnd) {
821
        LWIP_DEBUGF(TCP_WND_DEBUG,
822
                    ("tcp_receive: no window update lastack %"U32_F" ackno %"
823
                     U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n",
824
                     pcb->lastack, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2));
825
      }
826
#endif /* TCP_WND_DEBUG */
827
    }
828
 
829
    /* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a
830
     * duplicate ack if:
831
     * 1) It doesn't ACK new data
832
     * 2) length of received packet is zero (i.e. no payload)
833
     * 3) the advertised window hasn't changed
834
     * 4) There is outstanding unacknowledged data (retransmission timer running)
835
     * 5) The ACK is == biggest ACK sequence number so far seen (snd_una)
836
     *
837
     * If it passes all five, should process as a dupack:
838
     * a) dupacks < 3: do nothing
839
     * b) dupacks == 3: fast retransmit
840
     * c) dupacks > 3: increase cwnd
841
     *
842
     * If it only passes 1-3, should reset dupack counter (and add to
843
     * stats, which we don't do in lwIP)
844
     *
845
     * If it only passes 1, should reset dupack counter
846
     *
847
     */
848
 
849
    /* Clause 1 */
850
    if (TCP_SEQ_LEQ(ackno, pcb->lastack)) {
851
      pcb->acked = 0;
852
      /* Clause 2 */
853
      if (tcplen == 0) {
854
        /* Clause 3 */
855
        if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge){
856
          /* Clause 4 */
857
          if (pcb->rtime >= 0) {
858
            /* Clause 5 */
859
            if (pcb->lastack == ackno) {
860
              found_dupack = 1;
861
              if (pcb->dupacks + 1 > pcb->dupacks)
862
                ++pcb->dupacks;
863
              if (pcb->dupacks > 3) {
864
                /* Inflate the congestion window, but not if it means that
865
                   the value overflows. */
866
                if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
867
                  pcb->cwnd += pcb->mss;
868
                }
869
              } else if (pcb->dupacks == 3) {
870
                /* Do fast retransmit */
871
                tcp_rexmit_fast(pcb);
872
              }
873
            }
874
          }
875
        }
876
      }
877
      /* If Clause (1) or more is true, but not a duplicate ack, reset
878
       * count of consecutive duplicate acks */
879
      if (!found_dupack) {
880
        pcb->dupacks = 0;
881
      }
882
    } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)){
883
      /* We come here when the ACK acknowledges new data. */
884
 
885
      /* Reset the "IN Fast Retransmit" flag, since we are no longer
886
         in fast retransmit. Also reset the congestion window to the
887
         slow start threshold. */
888
      if (pcb->flags & TF_INFR) {
889
        pcb->flags &= ~TF_INFR;
890
        pcb->cwnd = pcb->ssthresh;
891
      }
892
 
893
      /* Reset the number of retransmissions. */
894
      pcb->nrtx = 0;
895
 
896
      /* Reset the retransmission time-out. */
897
      pcb->rto = (pcb->sa >> 3) + pcb->sv;
898
 
899
      /* Update the send buffer space. Diff between the two can never exceed 64K? */
900
      pcb->acked = (u16_t)(ackno - pcb->lastack);
901
 
902
      pcb->snd_buf += pcb->acked;
903
 
904
      /* Reset the fast retransmit variables. */
905
      pcb->dupacks = 0;
906
      pcb->lastack = ackno;
907
 
908
      /* Update the congestion control variables (cwnd and
909
         ssthresh). */
910
      if (pcb->state >= ESTABLISHED) {
911
        if (pcb->cwnd < pcb->ssthresh) {
912
          if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
913
            pcb->cwnd += pcb->mss;
914
          }
915
          LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"U16_F"\n", pcb->cwnd));
916
        } else {
917
          u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd);
918
          if (new_cwnd > pcb->cwnd) {
919
            pcb->cwnd = new_cwnd;
920
          }
921
          LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"U16_F"\n", pcb->cwnd));
922
        }
923
      }
924
      LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n",
925
                                    ackno,
926
                                    pcb->unacked != NULL?
927
                                    ntohl(pcb->unacked->tcphdr->seqno): 0,
928
                                    pcb->unacked != NULL?
929
                                    ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0));
930
 
931
      /* Remove segment from the unacknowledged list if the incoming
932
         ACK acknowlegdes them. */
933
      while (pcb->unacked != NULL &&
934
             TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) +
935
                         TCP_TCPLEN(pcb->unacked), ackno)) {
936
        LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unacked\n",
937
                                      ntohl(pcb->unacked->tcphdr->seqno),
938
                                      ntohl(pcb->unacked->tcphdr->seqno) +
939
                                      TCP_TCPLEN(pcb->unacked)));
940
 
941
        next = pcb->unacked;
942
        pcb->unacked = pcb->unacked->next;
943
 
944
        LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen));
945
        LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
946
        /* Prevent ACK for FIN to generate a sent event */
947
        if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) {
948
          pcb->acked--;
949
        }
950
 
951
        pcb->snd_queuelen -= pbuf_clen(next->p);
952
        tcp_seg_free(next);
953
 
954
        LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unacked)\n", (u16_t)pcb->snd_queuelen));
955
        if (pcb->snd_queuelen != 0) {
956
          LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL ||
957
                      pcb->unsent != NULL);
958
        }
959
      }
960
 
961
      /* If there's nothing left to acknowledge, stop the retransmit
962
         timer, otherwise reset it to start again */
963
      if(pcb->unacked == NULL)
964
        pcb->rtime = -1;
965
      else
966
        pcb->rtime = 0;
967
 
968
      pcb->polltmr = 0;
969
    } else {
970
      /* Fix bug bug #21582: out of sequence ACK, didn't really ack anything */
971
      pcb->acked = 0;
972
    }
973
 
974
    /* We go through the ->unsent list to see if any of the segments
975
       on the list are acknowledged by the ACK. This may seem
976
       strange since an "unsent" segment shouldn't be acked. The
977
       rationale is that lwIP puts all outstanding segments on the
978
       ->unsent list after a retransmission, so these segments may
979
       in fact have been sent once. */
980
    while (pcb->unsent != NULL &&
981
           TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) +
982
                           TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) {
983
      LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n",
984
                                    ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) +
985
                                    TCP_TCPLEN(pcb->unsent)));
986
 
987
      next = pcb->unsent;
988
      pcb->unsent = pcb->unsent->next;
989
      LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen));
990
      LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
991
      /* Prevent ACK for FIN to generate a sent event */
992
      if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) {
993
        pcb->acked--;
994
      }
995
      pcb->snd_queuelen -= pbuf_clen(next->p);
996
      tcp_seg_free(next);
997
      LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unsent)\n", (u16_t)pcb->snd_queuelen));
998
      if (pcb->snd_queuelen != 0) {
999
        LWIP_ASSERT("tcp_receive: valid queue length",
1000
          pcb->unacked != NULL || pcb->unsent != NULL);
1001
      }
1002
    }
1003
    /* End of ACK for new data processing. */
1004
 
1005
    LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %"U32_F" rtseq %"U32_F" ackno %"U32_F"\n",
1006
                                pcb->rttest, pcb->rtseq, ackno));
1007
 
1008
    /* RTT estimation calculations. This is done by checking if the
1009
       incoming segment acknowledges the segment we use to take a
1010
       round-trip time measurement. */
1011
    if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) {
1012
      /* diff between this shouldn't exceed 32K since this are tcp timer ticks
1013
         and a round-trip shouldn't be that long... */
1014
      m = (s16_t)(tcp_ticks - pcb->rttest);
1015
 
1016
      LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %"U16_F" ticks (%"U16_F" msec).\n",
1017
                                  m, m * TCP_SLOW_INTERVAL));
1018
 
1019
      /* This is taken directly from VJs original code in his paper */
1020
      m = m - (pcb->sa >> 3);
1021
      pcb->sa += m;
1022
      if (m < 0) {
1023
        m = -m;
1024
      }
1025
      m = m - (pcb->sv >> 2);
1026
      pcb->sv += m;
1027
      pcb->rto = (pcb->sa >> 3) + pcb->sv;
1028
 
1029
      LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %"U16_F" (%"U16_F" milliseconds)\n",
1030
                                  pcb->rto, pcb->rto * TCP_SLOW_INTERVAL));
1031
 
1032
      pcb->rttest = 0;
1033
    }
1034
  }
1035
 
1036
  /* If the incoming segment contains data, we must process it
1037
     further. */
1038
  if (tcplen > 0) {
1039
    /* This code basically does three things:
1040
 
1041
    +) If the incoming segment contains data that is the next
1042
    in-sequence data, this data is passed to the application. This
1043
    might involve trimming the first edge of the data. The rcv_nxt
1044
    variable and the advertised window are adjusted.
1045
 
1046
    +) If the incoming segment has data that is above the next
1047
    sequence number expected (->rcv_nxt), the segment is placed on
1048
    the ->ooseq queue. This is done by finding the appropriate
1049
    place in the ->ooseq queue (which is ordered by sequence
1050
    number) and trim the segment in both ends if needed. An
1051
    immediate ACK is sent to indicate that we received an
1052
    out-of-sequence segment.
1053
 
1054
    +) Finally, we check if the first segment on the ->ooseq queue
1055
    now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If
1056
    rcv_nxt > ooseq->seqno, we must trim the first edge of the
1057
    segment on ->ooseq before we adjust rcv_nxt. The data in the
1058
    segments that are now on sequence are chained onto the
1059
    incoming segment so that we only need to call the application
1060
    once.
1061
    */
1062
 
1063
    /* First, we check if we must trim the first edge. We have to do
1064
       this if the sequence number of the incoming segment is less
1065
       than rcv_nxt, and the sequence number plus the length of the
1066
       segment is larger than rcv_nxt. */
1067
    /*    if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){
1068
          if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/
1069
    if (TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno + 1, seqno + tcplen - 1)){
1070
      /* Trimming the first edge is done by pushing the payload
1071
         pointer in the pbuf downwards. This is somewhat tricky since
1072
         we do not want to discard the full contents of the pbuf up to
1073
         the new starting point of the data since we have to keep the
1074
         TCP header which is present in the first pbuf in the chain.
1075
 
1076
         What is done is really quite a nasty hack: the first pbuf in
1077
         the pbuf chain is pointed to by inseg.p. Since we need to be
1078
         able to deallocate the whole pbuf, we cannot change this
1079
         inseg.p pointer to point to any of the later pbufs in the
1080
         chain. Instead, we point the ->payload pointer in the first
1081
         pbuf to data in one of the later pbufs. We also set the
1082
         inseg.data pointer to point to the right place. This way, the
1083
         ->p pointer will still point to the first pbuf, but the
1084
         ->p->payload pointer will point to data in another pbuf.
1085
 
1086
         After we are done with adjusting the pbuf pointers we must
1087
         adjust the ->data pointer in the seg and the segment
1088
         length.*/
1089
 
1090
      off = pcb->rcv_nxt - seqno;
1091
      p = inseg.p;
1092
      LWIP_ASSERT("inseg.p != NULL", inseg.p);
1093
      LWIP_ASSERT("insane offset!", (off < 0x7fff));
1094
      if (inseg.p->len < off) {
1095
        LWIP_ASSERT("pbuf too short!", (((s32_t)inseg.p->tot_len) >= off));
1096
        new_tot_len = (u16_t)(inseg.p->tot_len - off);
1097
        while (p->len < off) {
1098
          off -= p->len;
1099
          /* KJM following line changed (with addition of new_tot_len var)
1100
             to fix bug #9076
1101
             inseg.p->tot_len -= p->len; */
1102
          p->tot_len = new_tot_len;
1103
          p->len = 0;
1104
          p = p->next;
1105
        }
1106
        if(pbuf_header(p, (s16_t)-off)) {
1107
          /* Do we need to cope with this failing?  Assert for now */
1108
          LWIP_ASSERT("pbuf_header failed", 0);
1109
        }
1110
      } else {
1111
        if(pbuf_header(inseg.p, (s16_t)-off)) {
1112
          /* Do we need to cope with this failing?  Assert for now */
1113
          LWIP_ASSERT("pbuf_header failed", 0);
1114
        }
1115
      }
1116
      /* KJM following line changed to use p->payload rather than inseg->p->payload
1117
         to fix bug #9076 */
1118
      inseg.dataptr = p->payload;
1119
      inseg.len -= (u16_t)(pcb->rcv_nxt - seqno);
1120
      inseg.tcphdr->seqno = seqno = pcb->rcv_nxt;
1121
    }
1122
    else {
1123
      if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){
1124
        /* the whole segment is < rcv_nxt */
1125
        /* must be a duplicate of a packet that has already been correctly handled */
1126
 
1127
        LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno));
1128
        tcp_ack_now(pcb);
1129
      }
1130
    }
1131
 
1132
    /* The sequence number must be within the window (above rcv_nxt
1133
       and below rcv_nxt + rcv_wnd) in order to be further
1134
       processed. */
1135
    if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
1136
                        pcb->rcv_nxt + pcb->rcv_wnd - 1)){
1137
      if (pcb->rcv_nxt == seqno) {
1138
        /* The incoming segment is the next in sequence. We check if
1139
           we have to trim the end of the segment and update rcv_nxt
1140
           and pass the data to the application. */
1141
        tcplen = TCP_TCPLEN(&inseg);
1142
 
1143
        if (tcplen > pcb->rcv_wnd) {
1144
          LWIP_DEBUGF(TCP_INPUT_DEBUG,
1145
                      ("tcp_receive: other end overran receive window"
1146
                       "seqno %"U32_F" len %"U32_F" right edge %"U32_F"\n",
1147
                       seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd));
1148
          if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
1149
            /* Must remove the FIN from the header as we're trimming
1150
             * that byte of sequence-space from the packet */
1151
            TCPH_FLAGS_SET(inseg.tcphdr, TCPH_FLAGS(inseg.tcphdr) &~ TCP_FIN);
1152
          }
1153
          /* Adjust length of segment to fit in the window. */
1154
          inseg.len = pcb->rcv_wnd;
1155
          if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
1156
            inseg.len -= 1;
1157
          }
1158
          pbuf_realloc(inseg.p, inseg.len);
1159
          tcplen = TCP_TCPLEN(&inseg);
1160
          LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n",
1161
                      (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd));
1162
        }
1163
#if TCP_QUEUE_OOSEQ
1164
        if (pcb->ooseq != NULL) {
1165
          if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
1166
            LWIP_DEBUGF(TCP_INPUT_DEBUG,
1167
                        ("tcp_receive: received in-order FIN, binning ooseq queue\n"));
1168
            /* Received in-order FIN means anything that was received
1169
             * out of order must now have been received in-order, so
1170
             * bin the ooseq queue
1171
             * rcv_nxt
1172
             * .    |--ooseq--|
1173
             * .==seg============|FIN
1174
             */
1175
            while (pcb->ooseq != NULL) {
1176
              struct tcp_seg *old_ooseq = pcb->ooseq;
1177
              pcb->ooseq = pcb->ooseq->next;
1178
              tcp_seg_free(old_ooseq);
1179
            }
1180
          }
1181
          else {
1182
            struct tcp_seg* next = pcb->ooseq;
1183
            struct tcp_seg *old_seg;
1184
            /* rcv_nxt
1185
             * .    |--ooseq--|
1186
             * .==seg============|
1187
             */
1188
            while (next &&
1189
                   TCP_SEQ_GEQ(seqno + tcplen,
1190
                               next->tcphdr->seqno + next->len)) {
1191
              /* inseg doesn't have FIN (already processed) */
1192
              if (TCPH_FLAGS(next->tcphdr) & TCP_FIN &&
1193
                  (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) {
1194
                TCPH_FLAGS_SET(inseg.tcphdr,
1195
                               TCPH_FLAGS(inseg.tcphdr) | TCP_FIN);
1196
                tcplen = TCP_TCPLEN(&inseg);
1197
              }
1198
              old_seg = next;
1199
              next = next->next;
1200
              tcp_seg_free(old_seg);
1201
            }
1202
            /* rcv_nxt
1203
             * .             |--ooseq--|
1204
             * .==seg============|
1205
             */
1206
            if (next &&
1207
                TCP_SEQ_GT(seqno + tcplen,
1208
                           next->tcphdr->seqno)) {
1209
              /* FIN in inseg already handled by dropping whole ooseq queue */
1210
              inseg.len = (u16_t)(pcb->ooseq->tcphdr->seqno - seqno);
1211
              if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
1212
                inseg.len -= 1;
1213
              }
1214
              pbuf_realloc(inseg.p, inseg.len);
1215
              tcplen = TCP_TCPLEN(&inseg);
1216
              LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n",
1217
                          (seqno + tcplen) == pcb->ooseq->tcphdr->seqno);
1218
            }
1219
            pcb->ooseq = next;
1220
          }
1221
        }
1222
#endif /* TCP_QUEUE_OOSEQ */
1223
 
1224
        pcb->rcv_nxt = seqno + tcplen;
1225
 
1226
        /* Update the receiver's (our) window. */
1227
        LWIP_ASSERT("tcp_receive: tcplen > rcv_wnd\n", pcb->rcv_wnd >= tcplen);
1228
        pcb->rcv_wnd -= tcplen;
1229
 
1230
        tcp_update_rcv_ann_wnd(pcb);
1231
 
1232
        /* If there is data in the segment, we make preparations to
1233
           pass this up to the application. The ->recv_data variable
1234
           is used for holding the pbuf that goes to the
1235
           application. The code for reassembling out-of-sequence data
1236
           chains its data on this pbuf as well.
1237
 
1238
           If the segment was a FIN, we set the TF_GOT_FIN flag that will
1239
           be used to indicate to the application that the remote side has
1240
           closed its end of the connection. */
1241
        if (inseg.p->tot_len > 0) {
1242
          recv_data = inseg.p;
1243
          /* Since this pbuf now is the responsibility of the
1244
             application, we delete our reference to it so that we won't
1245
             (mistakingly) deallocate it. */
1246
          inseg.p = NULL;
1247
        }
1248
        if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
1249
          LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n"));
1250
          recv_flags |= TF_GOT_FIN;
1251
        }
1252
 
1253
#if TCP_QUEUE_OOSEQ
1254
        /* We now check if we have segments on the ->ooseq queue that
1255
           is now in sequence. */
1256
        while (pcb->ooseq != NULL &&
1257
               pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) {
1258
 
1259
          cseg = pcb->ooseq;
1260
          seqno = pcb->ooseq->tcphdr->seqno;
1261
 
1262
          pcb->rcv_nxt += TCP_TCPLEN(cseg);
1263
          LWIP_ASSERT("tcp_receive: ooseq tcplen > rcv_wnd\n",
1264
                      pcb->rcv_wnd >= TCP_TCPLEN(cseg));
1265
          pcb->rcv_wnd -= TCP_TCPLEN(cseg);
1266
 
1267
          tcp_update_rcv_ann_wnd(pcb);
1268
 
1269
          if (cseg->p->tot_len > 0) {
1270
            /* Chain this pbuf onto the pbuf that we will pass to
1271
               the application. */
1272
            if (recv_data) {
1273
              pbuf_cat(recv_data, cseg->p);
1274
            } else {
1275
              recv_data = cseg->p;
1276
            }
1277
            cseg->p = NULL;
1278
          }
1279
          if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
1280
            LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n"));
1281
            recv_flags |= TF_GOT_FIN;
1282
            if (pcb->state == ESTABLISHED) { /* force passive close or we can move to active close */
1283
              pcb->state = CLOSE_WAIT;
1284
            }
1285
          }
1286
 
1287
          pcb->ooseq = cseg->next;
1288
          tcp_seg_free(cseg);
1289
        }
1290
#endif /* TCP_QUEUE_OOSEQ */
1291
 
1292
 
1293
        /* Acknowledge the segment(s). */
1294
        tcp_ack(pcb);
1295
 
1296
      } else {
1297
        /* We get here if the incoming segment is out-of-sequence. */
1298
        tcp_send_empty_ack(pcb);
1299
#if TCP_QUEUE_OOSEQ
1300
        /* We queue the segment on the ->ooseq queue. */
1301
        if (pcb->ooseq == NULL) {
1302
          pcb->ooseq = tcp_seg_copy(&inseg);
1303
        } else {
1304
          /* If the queue is not empty, we walk through the queue and
1305
             try to find a place where the sequence number of the
1306
             incoming segment is between the sequence numbers of the
1307
             previous and the next segment on the ->ooseq queue. That is
1308
             the place where we put the incoming segment. If needed, we
1309
             trim the second edges of the previous and the incoming
1310
             segment so that it will fit into the sequence.
1311
 
1312
             If the incoming segment has the same sequence number as a
1313
             segment on the ->ooseq queue, we discard the segment that
1314
             contains less data. */
1315
 
1316
          prev = NULL;
1317
          for(next = pcb->ooseq; next != NULL; next = next->next) {
1318
            if (seqno == next->tcphdr->seqno) {
1319
              /* The sequence number of the incoming segment is the
1320
                 same as the sequence number of the segment on
1321
                 ->ooseq. We check the lengths to see which one to
1322
                 discard. */
1323
              if (inseg.len > next->len) {
1324
                /* The incoming segment is larger than the old
1325
                   segment. We replace some segments with the new
1326
                   one. */
1327
                cseg = tcp_seg_copy(&inseg);
1328
                if (cseg != NULL) {
1329
                  if (prev != NULL) {
1330
                    prev->next = cseg;
1331
                  } else {
1332
                    pcb->ooseq = cseg;
1333
                  }
1334
                  tcp_oos_insert_segment(cseg, next);
1335
                }
1336
                break;
1337
              } else {
1338
                /* Either the lenghts are the same or the incoming
1339
                   segment was smaller than the old one; in either
1340
                   case, we ditch the incoming segment. */
1341
                break;
1342
              }
1343
            } else {
1344
              if (prev == NULL) {
1345
                if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {
1346
                  /* The sequence number of the incoming segment is lower
1347
                     than the sequence number of the first segment on the
1348
                     queue. We put the incoming segment first on the
1349
                     queue. */
1350
                  cseg = tcp_seg_copy(&inseg);
1351
                  if (cseg != NULL) {
1352
                    pcb->ooseq = cseg;
1353
                    tcp_oos_insert_segment(cseg, next);
1354
                  }
1355
                  break;
1356
                }
1357
              } else {
1358
                /*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) &&
1359
                  TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/
1360
                if (TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)) {
1361
                  /* The sequence number of the incoming segment is in
1362
                     between the sequence numbers of the previous and
1363
                     the next segment on ->ooseq. We trim trim the previous
1364
                     segment, delete next segments that included in received segment
1365
                     and trim received, if needed. */
1366
                  cseg = tcp_seg_copy(&inseg);
1367
                  if (cseg != NULL) {
1368
                    if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) {
1369
                      /* We need to trim the prev segment. */
1370
                      prev->len = (u16_t)(seqno - prev->tcphdr->seqno);
1371
                      pbuf_realloc(prev->p, prev->len);
1372
                    }
1373
                    prev->next = cseg;
1374
                    tcp_oos_insert_segment(cseg, next);
1375
                  }
1376
                  break;
1377
                }
1378
              }
1379
              /* If the "next" segment is the last segment on the
1380
                 ooseq queue, we add the incoming segment to the end
1381
                 of the list. */
1382
              if (next->next == NULL &&
1383
                  TCP_SEQ_GT(seqno, next->tcphdr->seqno)) {
1384
                if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) {
1385
                  /* segment "next" already contains all data */
1386
                  break;
1387
                }
1388
                next->next = tcp_seg_copy(&inseg);
1389
                if (next->next != NULL) {
1390
                  if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) {
1391
                    /* We need to trim the last segment. */
1392
                    next->len = (u16_t)(seqno - next->tcphdr->seqno);
1393
                    pbuf_realloc(next->p, next->len);
1394
                  }
1395
                }
1396
                break;
1397
              }
1398
            }
1399
            prev = next;
1400
          }
1401
        }
1402
#endif /* TCP_QUEUE_OOSEQ */
1403
 
1404
      }
1405
    } else {
1406
      /* The incoming segment is not withing the window. */
1407
      tcp_send_empty_ack(pcb);
1408
    }
1409
  } else {
1410
    /* Segments with length 0 is taken care of here. Segments that
1411
       fall out of the window are ACKed. */
1412
    /*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) ||
1413
      TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/
1414
    if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){
1415
      tcp_ack_now(pcb);
1416
    }
1417
  }
1418
}
1419
 
1420
/**
1421
 * Parses the options contained in the incoming segment.
1422
 *
1423
 * Called from tcp_listen_input() and tcp_process().
1424
 * Currently, only the MSS option is supported!
1425
 *
1426
 * @param pcb the tcp_pcb for which a segment arrived
1427
 */
1428
static void
1429
tcp_parseopt(struct tcp_pcb *pcb)
1430
{
1431
  u16_t c, max_c;
1432
  u16_t mss;
1433
  u8_t *opts, opt;
1434
#if LWIP_TCP_TIMESTAMPS
1435
  u32_t tsval;
1436
#endif
1437
 
1438
  opts = (u8_t *)tcphdr + TCP_HLEN;
1439
 
1440
  /* Parse the TCP MSS option, if present. */
1441
  if(TCPH_HDRLEN(tcphdr) > 0x5) {
1442
    max_c = (TCPH_HDRLEN(tcphdr) - 5) << 2;
1443
    for (c = 0; c < max_c; ) {
1444
      opt = opts[c];
1445
      switch (opt) {
1446
      case 0x00:
1447
        /* End of options. */
1448
        LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: EOL\n"));
1449
        return;
1450
      case 0x01:
1451
        /* NOP option. */
1452
        ++c;
1453
        LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: NOP\n"));
1454
        break;
1455
      case 0x02:
1456
        LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: MSS\n"));
1457
        if (opts[c + 1] != 0x04 || c + 0x04 > max_c) {
1458
          /* Bad length */
1459
          LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
1460
          return;
1461
        }
1462
        /* An MSS option with the right option length. */
1463
        mss = (opts[c + 2] << 8) | opts[c + 3];
1464
        /* Limit the mss to the configured TCP_MSS and prevent division by zero */
1465
        pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss;
1466
        /* Advance to next option */
1467
        c += 0x04;
1468
        break;
1469
#if LWIP_TCP_TIMESTAMPS
1470
      case 0x08:
1471
        LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: TS\n"));
1472
        if (opts[c + 1] != 0x0A || c + 0x0A > max_c) {
1473
          /* Bad length */
1474
          LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
1475
          return;
1476
        }
1477
        /* TCP timestamp option with valid length */
1478
        tsval = (opts[c+2]) | (opts[c+3] << 8) |
1479
          (opts[c+4] << 16) | (opts[c+5] << 24);
1480
        if (flags & TCP_SYN) {
1481
          pcb->ts_recent = ntohl(tsval);
1482
          pcb->flags |= TF_TIMESTAMP;
1483
        } else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno+tcplen)) {
1484
          pcb->ts_recent = ntohl(tsval);
1485
        }
1486
        /* Advance to next option */
1487
        c += 0x0A;
1488
        break;
1489
#endif
1490
      default:
1491
        LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: other\n"));
1492
        if (opts[c + 1] == 0) {
1493
          LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
1494
          /* If the length field is zero, the options are malformed
1495
             and we don't process them further. */
1496
          return;
1497
        }
1498
        /* All other options have a length field, so that we easily
1499
           can skip past them. */
1500
        c += opts[c + 1];
1501
      }
1502
    }
1503
  }
1504
}
1505
 
1506
#endif /* LWIP_TCP */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.