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

Subversion Repositories openrisc

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

powered by: WebSVN 2.1.0

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