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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [lwIP_Demo_Rowley_ARM7/] [lwip-1.1.0/] [src/] [core/] [tcp_in.c] - Blame information for rev 583

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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