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

Subversion Repositories openrisc

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

Go to most recent revision | 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 u8_t 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) & 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
 */
392
static err_t
393
tcp_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
 */
472
static err_t
473
tcp_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
 */
495
static err_t
496
tcp_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
 */
711
static u8_t
712
tcp_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
 */
1311
static void
1312
tcp_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 */

powered by: WebSVN 2.1.0

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