Warning, cross-references for /kernel/lwip/core/tcp_in.c need to be fixed.
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044 #include "lwip/opt.h"
0045
0046 #if LWIP_TCP
0047
0048 #include "lwip/tcp.h"
0049 #include "lwip/def.h"
0050 #include "lwip/ip_addr.h"
0051 #include "lwip/netif.h"
0052 #include "lwip/mem.h"
0053 #include "lwip/memp.h"
0054 #include "lwip/inet.h"
0055 #include "lwip/inet_chksum.h"
0056 #include "lwip/stats.h"
0057 #include "lwip/snmp.h"
0058 #include "arch/perf.h"
0059
0060
0061
0062
0063 static struct tcp_seg inseg;
0064 static struct tcp_hdr *tcphdr;
0065 static struct ip_hdr *iphdr;
0066 static u32_t seqno, ackno;
0067 static u8_t flags;
0068 static u16_t tcplen;
0069
0070 static u8_t recv_flags;
0071 static struct pbuf *recv_data;
0072
0073 struct tcp_pcb *tcp_input_pcb;
0074
0075
0076 static err_t tcp_process(struct tcp_pcb *pcb);
0077 static void tcp_receive(struct tcp_pcb *pcb);
0078 static void tcp_parseopt(struct tcp_pcb *pcb);
0079
0080 static err_t tcp_listen_input(struct tcp_pcb_listen *pcb);
0081 static err_t tcp_timewait_input(struct tcp_pcb *pcb);
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092 void
0093 tcp_input(struct pbuf *p, struct netif *inp)
0094 {
0095 struct tcp_pcb *pcb, *prev;
0096 struct tcp_pcb_listen *lpcb;
0097 u8_t hdrlen;
0098 err_t err;
0099
0100 PERF_START;
0101
0102 TCP_STATS_INC(tcp.recv);
0103 snmp_inc_tcpinsegs();
0104
0105 iphdr = p->payload;
0106 tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4);
0107
0108 #if TCP_INPUT_DEBUG
0109 tcp_debug_print(tcphdr);
0110 #endif
0111
0112
0113 if (pbuf_header(p, -((s16_t)(IPH_HL(iphdr) * 4))) || (p->tot_len < sizeof(struct tcp_hdr))) {
0114
0115 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len));
0116 TCP_STATS_INC(tcp.lenerr);
0117 TCP_STATS_INC(tcp.drop);
0118 snmp_inc_tcpinerrs();
0119 pbuf_free(p);
0120 return;
0121 }
0122
0123
0124 if (ip_addr_isbroadcast(&(iphdr->dest), inp) ||
0125 ip_addr_ismulticast(&(iphdr->dest))) {
0126 TCP_STATS_INC(tcp.proterr);
0127 TCP_STATS_INC(tcp.drop);
0128 snmp_inc_tcpinerrs();
0129 pbuf_free(p);
0130 return;
0131 }
0132
0133 #if CHECKSUM_CHECK_TCP
0134
0135 if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
0136 (struct ip_addr *)&(iphdr->dest),
0137 IP_PROTO_TCP, p->tot_len) != 0) {
0138 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n",
0139 inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src), (struct ip_addr *)&(iphdr->dest),
0140 IP_PROTO_TCP, p->tot_len)));
0141 #if TCP_DEBUG
0142 tcp_debug_print(tcphdr);
0143 #endif
0144 TCP_STATS_INC(tcp.chkerr);
0145 TCP_STATS_INC(tcp.drop);
0146 snmp_inc_tcpinerrs();
0147 pbuf_free(p);
0148 return;
0149 }
0150 #endif
0151
0152
0153
0154 hdrlen = TCPH_HDRLEN(tcphdr);
0155 if(pbuf_header(p, -(hdrlen * 4))){
0156
0157 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet\n"));
0158 TCP_STATS_INC(tcp.lenerr);
0159 TCP_STATS_INC(tcp.drop);
0160 snmp_inc_tcpinerrs();
0161 pbuf_free(p);
0162 return;
0163 }
0164
0165
0166 tcphdr->src = ntohs(tcphdr->src);
0167 tcphdr->dest = ntohs(tcphdr->dest);
0168 seqno = tcphdr->seqno = ntohl(tcphdr->seqno);
0169 ackno = tcphdr->ackno = ntohl(tcphdr->ackno);
0170 tcphdr->wnd = ntohs(tcphdr->wnd);
0171
0172 flags = TCPH_FLAGS(tcphdr);
0173 tcplen = p->tot_len + ((flags & (TCP_FIN | TCP_SYN)) ? 1 : 0);
0174
0175
0176
0177 prev = NULL;
0178
0179
0180 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
0181 LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED);
0182 LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
0183 LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
0184 if (pcb->remote_port == tcphdr->src &&
0185 pcb->local_port == tcphdr->dest &&
0186 ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
0187 ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
0188
0189
0190
0191
0192 LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb);
0193 if (prev != NULL) {
0194 prev->next = pcb->next;
0195 pcb->next = tcp_active_pcbs;
0196 tcp_active_pcbs = pcb;
0197 }
0198 LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb);
0199 break;
0200 }
0201 prev = pcb;
0202 }
0203
0204 if (pcb == NULL) {
0205
0206
0207 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
0208 LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
0209 if (pcb->remote_port == tcphdr->src &&
0210 pcb->local_port == tcphdr->dest &&
0211 ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
0212 ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
0213
0214
0215
0216 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n"));
0217 tcp_timewait_input(pcb);
0218 pbuf_free(p);
0219 return;
0220 }
0221 }
0222
0223
0224
0225 prev = NULL;
0226 for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
0227 if ((ip_addr_isany(&(lpcb->local_ip)) ||
0228 ip_addr_cmp(&(lpcb->local_ip), &(iphdr->dest))) &&
0229 lpcb->local_port == tcphdr->dest) {
0230
0231
0232
0233 if (prev != NULL) {
0234 ((struct tcp_pcb_listen *)prev)->next = lpcb->next;
0235
0236 lpcb->next = tcp_listen_pcbs.listen_pcbs;
0237
0238 tcp_listen_pcbs.listen_pcbs = lpcb;
0239 }
0240
0241 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n"));
0242 tcp_listen_input(lpcb);
0243 pbuf_free(p);
0244 return;
0245 }
0246 prev = (struct tcp_pcb *)lpcb;
0247 }
0248 }
0249
0250 #if TCP_INPUT_DEBUG
0251 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags "));
0252 tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
0253 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n"));
0254 #endif
0255
0256
0257 if (pcb != NULL) {
0258
0259 #if TCP_INPUT_DEBUG
0260 #if TCP_DEBUG
0261 tcp_debug_print_state(pcb->state);
0262 #endif
0263 #endif
0264
0265
0266 inseg.next = NULL;
0267 inseg.len = p->tot_len;
0268 inseg.dataptr = p->payload;
0269 inseg.p = p;
0270 inseg.tcphdr = tcphdr;
0271
0272 recv_data = NULL;
0273 recv_flags = 0;
0274
0275
0276 if (pcb->refused_data != NULL) {
0277
0278 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: notify kept packet\n"));
0279 TCP_EVENT_RECV(pcb, pcb->refused_data, ERR_OK, err);
0280 if (err == ERR_OK) {
0281 pcb->refused_data = NULL;
0282 } else {
0283
0284 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n"));
0285 TCP_STATS_INC(tcp.drop);
0286 snmp_inc_tcpinerrs();
0287 pbuf_free(p);
0288 return;
0289 }
0290 }
0291 tcp_input_pcb = pcb;
0292 err = tcp_process(pcb);
0293
0294
0295 if (err != ERR_ABRT) {
0296 if (recv_flags & TF_RESET) {
0297
0298
0299
0300
0301 TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST);
0302 tcp_pcb_remove(&tcp_active_pcbs, pcb);
0303 memp_free(MEMP_TCP_PCB, pcb);
0304 } else if (recv_flags & TF_CLOSED) {
0305
0306
0307 tcp_pcb_remove(&tcp_active_pcbs, pcb);
0308 memp_free(MEMP_TCP_PCB, pcb);
0309 } else {
0310 err = ERR_OK;
0311
0312
0313
0314 if (pcb->acked > 0) {
0315 TCP_EVENT_SENT(pcb, pcb->acked, err);
0316 }
0317
0318 if (recv_data != NULL) {
0319 if(flags & TCP_PSH) {
0320 recv_data->flags |= PBUF_FLAG_PUSH;
0321 }
0322
0323
0324 TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err);
0325
0326
0327 if (err != ERR_OK) {
0328 pcb->refused_data = recv_data;
0329 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: keep incoming packet, because pcb is \"full\"\n"));
0330 }
0331 }
0332
0333
0334
0335 if (recv_flags & TF_GOT_FIN) {
0336 TCP_EVENT_RECV(pcb, NULL, ERR_OK, err);
0337 }
0338
0339 tcp_input_pcb = NULL;
0340
0341 tcp_output(pcb);
0342 #if TCP_INPUT_DEBUG
0343 #if TCP_DEBUG
0344 tcp_debug_print_state(pcb->state);
0345 #endif
0346 #endif
0347 }
0348 }
0349 tcp_input_pcb = NULL;
0350
0351
0352
0353 if (inseg.p != NULL)
0354 {
0355 pbuf_free(inseg.p);
0356 inseg.p = NULL;
0357 }
0358 } else {
0359
0360
0361
0362 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n"));
0363 if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) {
0364 TCP_STATS_INC(tcp.proterr);
0365 TCP_STATS_INC(tcp.drop);
0366 tcp_rst(ackno, seqno + tcplen,
0367 &(iphdr->dest), &(iphdr->src),
0368 tcphdr->dest, tcphdr->src);
0369 }
0370 pbuf_free(p);
0371 }
0372
0373 LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());
0374 PERF_STOP("tcp_input");
0375 }
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388
0389 static err_t
0390 tcp_listen_input(struct tcp_pcb_listen *pcb)
0391 {
0392 struct tcp_pcb *npcb;
0393 err_t rc;
0394
0395
0396
0397 if (flags & TCP_ACK) {
0398
0399
0400 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n"));
0401 tcp_rst(ackno + 1, seqno + tcplen,
0402 &(iphdr->dest), &(iphdr->src),
0403 tcphdr->dest, tcphdr->src);
0404 } else if (flags & TCP_SYN) {
0405 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest));
0406 #if TCP_LISTEN_BACKLOG
0407 if (pcb->accepts_pending >= pcb->backlog) {
0408 LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: listen backlog exceeded for port %"U16_F"\n", tcphdr->dest));
0409 return ERR_ABRT;
0410 }
0411 #endif
0412 npcb = tcp_alloc(pcb->prio);
0413
0414
0415
0416 if (npcb == NULL) {
0417 LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n"));
0418 TCP_STATS_INC(tcp.memerr);
0419 return ERR_MEM;
0420 }
0421 #if TCP_LISTEN_BACKLOG
0422 pcb->accepts_pending++;
0423 #endif
0424
0425 ip_addr_set(&(npcb->local_ip), &(iphdr->dest));
0426 npcb->local_port = pcb->local_port;
0427 ip_addr_set(&(npcb->remote_ip), &(iphdr->src));
0428 npcb->remote_port = tcphdr->src;
0429 npcb->state = SYN_RCVD;
0430 npcb->rcv_nxt = seqno + 1;
0431 npcb->rcv_ann_right_edge = npcb->rcv_nxt;
0432 npcb->snd_wnd = tcphdr->wnd;
0433 npcb->ssthresh = npcb->snd_wnd;
0434 npcb->snd_wl1 = seqno - 1;
0435 npcb->callback_arg = pcb->callback_arg;
0436 #if LWIP_CALLBACK_API
0437 npcb->accept = pcb->accept;
0438 #endif
0439
0440 npcb->so_options = pcb->so_options & (SOF_DEBUG|SOF_DONTROUTE|SOF_KEEPALIVE|SOF_OOBINLINE|SOF_LINGER);
0441
0442
0443 TCP_REG(&tcp_active_pcbs, npcb);
0444
0445
0446 tcp_parseopt(npcb);
0447 #if TCP_CALCULATE_EFF_SEND_MSS
0448 npcb->mss = tcp_eff_send_mss(npcb->mss, &(npcb->remote_ip));
0449 #endif
0450
0451 snmp_inc_tcppassiveopens();
0452
0453
0454 rc = tcp_enqueue(npcb, NULL, 0, TCP_SYN | TCP_ACK, 0, TF_SEG_OPTS_MSS
0455 #if LWIP_TCP_TIMESTAMPS
0456
0457 | (npcb->flags & TF_TIMESTAMP ? TF_SEG_OPTS_TS : 0)
0458 #endif
0459 );
0460 if (rc != ERR_OK) {
0461 tcp_abandon(npcb, 0);
0462 return rc;
0463 }
0464 return tcp_output(npcb);
0465 }
0466 return ERR_OK;
0467 }
0468
0469
0470
0471
0472
0473
0474
0475
0476
0477
0478 static err_t
0479 tcp_timewait_input(struct tcp_pcb *pcb)
0480 {
0481
0482
0483
0484
0485
0486 if (flags & TCP_RST) {
0487 return ERR_OK;
0488 }
0489
0490 if (flags & TCP_SYN) {
0491
0492
0493 if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) {
0494
0495 tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src),
0496 tcphdr->dest, tcphdr->src);
0497 return ERR_OK;
0498 }
0499 } else if (flags & TCP_FIN) {
0500
0501
0502 pcb->tmr = tcp_ticks;
0503 }
0504
0505 if ((tcplen > 0)) {
0506
0507 pcb->flags |= TF_ACK_NOW;
0508 return tcp_output(pcb);
0509 }
0510 return ERR_OK;
0511 }
0512
0513
0514
0515
0516
0517
0518
0519
0520
0521
0522
0523
0524 static err_t
0525 tcp_process(struct tcp_pcb *pcb)
0526 {
0527 struct tcp_seg *rseg;
0528 u8_t acceptable = 0;
0529 err_t err;
0530
0531 err = ERR_OK;
0532
0533
0534 if (flags & TCP_RST) {
0535
0536 if (pcb->state == SYN_SENT) {
0537 if (ackno == pcb->snd_nxt) {
0538 acceptable = 1;
0539 }
0540 } else {
0541 if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
0542 pcb->rcv_nxt+pcb->rcv_wnd)) {
0543 acceptable = 1;
0544 }
0545 }
0546
0547 if (acceptable) {
0548 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n"));
0549 LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED);
0550 recv_flags |= TF_RESET;
0551 pcb->flags &= ~TF_ACK_DELAY;
0552 return ERR_RST;
0553 } else {
0554 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n",
0555 seqno, pcb->rcv_nxt));
0556 LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n",
0557 seqno, pcb->rcv_nxt));
0558 return ERR_OK;
0559 }
0560 }
0561
0562 if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) {
0563
0564 tcp_ack_now(pcb);
0565 return ERR_OK;
0566 }
0567
0568
0569 pcb->tmr = tcp_ticks;
0570 pcb->keep_cnt_sent = 0;
0571
0572 tcp_parseopt(pcb);
0573
0574
0575 switch (pcb->state) {
0576 case SYN_SENT:
0577 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno,
0578 pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno)));
0579
0580 if ((flags & TCP_ACK) && (flags & TCP_SYN)
0581 && ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) {
0582 pcb->snd_buf++;
0583 pcb->rcv_nxt = seqno + 1;
0584 pcb->rcv_ann_right_edge = pcb->rcv_nxt;
0585 pcb->lastack = ackno;
0586 pcb->snd_wnd = tcphdr->wnd;
0587 pcb->snd_wl1 = seqno - 1;
0588 pcb->state = ESTABLISHED;
0589
0590 #if TCP_CALCULATE_EFF_SEND_MSS
0591 pcb->mss = tcp_eff_send_mss(pcb->mss, &(pcb->remote_ip));
0592 #endif
0593
0594
0595
0596 pcb->ssthresh = pcb->mss * 10;
0597
0598 pcb->cwnd = ((pcb->cwnd == 1) ? (pcb->mss * 2) : pcb->mss);
0599 LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0));
0600 --pcb->snd_queuelen;
0601 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"U16_F"\n", (u16_t)pcb->snd_queuelen));
0602 rseg = pcb->unacked;
0603 pcb->unacked = rseg->next;
0604
0605
0606
0607 if(pcb->unacked == NULL)
0608 pcb->rtime = -1;
0609 else {
0610 pcb->rtime = 0;
0611 pcb->nrtx = 0;
0612 }
0613
0614 tcp_seg_free(rseg);
0615
0616
0617
0618 TCP_EVENT_CONNECTED(pcb, ERR_OK, err);
0619 tcp_ack_now(pcb);
0620 }
0621
0622 else if (flags & TCP_ACK) {
0623
0624 tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src),
0625 tcphdr->dest, tcphdr->src);
0626 }
0627 break;
0628 case SYN_RCVD:
0629 if (flags & TCP_ACK) {
0630
0631 if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) {
0632 u16_t old_cwnd;
0633 pcb->state = ESTABLISHED;
0634 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
0635 #if LWIP_CALLBACK_API
0636 LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL);
0637 #endif
0638
0639 TCP_EVENT_ACCEPT(pcb, ERR_OK, err);
0640 if (err != ERR_OK) {
0641
0642
0643 tcp_abort(pcb);
0644 return ERR_ABRT;
0645 }
0646 old_cwnd = pcb->cwnd;
0647
0648
0649 tcp_receive(pcb);
0650
0651
0652 if (pcb->acked != 0) {
0653 pcb->acked--;
0654 }
0655
0656 pcb->cwnd = ((old_cwnd == 1) ? (pcb->mss * 2) : pcb->mss);
0657
0658 if (recv_flags & TF_GOT_FIN) {
0659 tcp_ack_now(pcb);
0660 pcb->state = CLOSE_WAIT;
0661 }
0662 }
0663
0664 else {
0665
0666 tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src),
0667 tcphdr->dest, tcphdr->src);
0668 }
0669 } else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) {
0670
0671 tcp_rexmit(pcb);
0672 }
0673 break;
0674 case CLOSE_WAIT:
0675
0676 case ESTABLISHED:
0677 tcp_receive(pcb);
0678 if (recv_flags & TF_GOT_FIN) {
0679 tcp_ack_now(pcb);
0680 pcb->state = CLOSE_WAIT;
0681 }
0682 break;
0683 case FIN_WAIT_1:
0684 tcp_receive(pcb);
0685 if (recv_flags & TF_GOT_FIN) {
0686 if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) {
0687 LWIP_DEBUGF(TCP_DEBUG,
0688 ("TCP connection closed: FIN_WAIT_1 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
0689 tcp_ack_now(pcb);
0690 tcp_pcb_purge(pcb);
0691 TCP_RMV(&tcp_active_pcbs, pcb);
0692 pcb->state = TIME_WAIT;
0693 TCP_REG(&tcp_tw_pcbs, pcb);
0694 } else {
0695 tcp_ack_now(pcb);
0696 pcb->state = CLOSING;
0697 }
0698 } else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) {
0699 pcb->state = FIN_WAIT_2;
0700 }
0701 break;
0702 case FIN_WAIT_2:
0703 tcp_receive(pcb);
0704 if (recv_flags & TF_GOT_FIN) {
0705 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: FIN_WAIT_2 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
0706 tcp_ack_now(pcb);
0707 tcp_pcb_purge(pcb);
0708 TCP_RMV(&tcp_active_pcbs, pcb);
0709 pcb->state = TIME_WAIT;
0710 TCP_REG(&tcp_tw_pcbs, pcb);
0711 }
0712 break;
0713 case CLOSING:
0714 tcp_receive(pcb);
0715 if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
0716 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
0717 tcp_pcb_purge(pcb);
0718 TCP_RMV(&tcp_active_pcbs, pcb);
0719 pcb->state = TIME_WAIT;
0720 TCP_REG(&tcp_tw_pcbs, pcb);
0721 }
0722 break;
0723 case LAST_ACK:
0724 tcp_receive(pcb);
0725 if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
0726 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: LAST_ACK %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
0727
0728 recv_flags |= TF_CLOSED;
0729 }
0730 break;
0731 default:
0732 break;
0733 }
0734 return ERR_OK;
0735 }
0736
0737 #if TCP_QUEUE_OOSEQ
0738
0739
0740
0741
0742
0743 static void
0744 tcp_oos_insert_segment(struct tcp_seg *cseg, struct tcp_seg *next)
0745 {
0746 struct tcp_seg *old_seg;
0747
0748 if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
0749
0750 tcp_segs_free(next);
0751 next = NULL;
0752 }
0753 else {
0754
0755
0756 while (next &&
0757 TCP_SEQ_GEQ((seqno + cseg->len),
0758 (next->tcphdr->seqno + next->len))) {
0759
0760 if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) {
0761 TCPH_FLAGS_SET(cseg->tcphdr, TCPH_FLAGS(cseg->tcphdr) | TCP_FIN);
0762 }
0763 old_seg = next;
0764 next = next->next;
0765 tcp_seg_free(old_seg);
0766 }
0767 if (next &&
0768 TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) {
0769
0770 cseg->len = (u16_t)(next->tcphdr->seqno - seqno);
0771 pbuf_realloc(cseg->p, cseg->len);
0772 }
0773 }
0774 cseg->next = next;
0775 }
0776 #endif
0777
0778
0779
0780
0781
0782
0783
0784
0785
0786
0787
0788
0789
0790 static void
0791 tcp_receive(struct tcp_pcb *pcb)
0792 {
0793 struct tcp_seg *next;
0794 #if TCP_QUEUE_OOSEQ
0795 struct tcp_seg *prev, *cseg;
0796 #endif
0797 struct pbuf *p;
0798 s32_t off;
0799 s16_t m;
0800 u32_t right_wnd_edge;
0801 u16_t new_tot_len;
0802 int found_dupack = 0;
0803
0804 if (flags & TCP_ACK) {
0805 right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2;
0806
0807
0808 if (TCP_SEQ_LT(pcb->snd_wl1, seqno) ||
0809 (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) ||
0810 (pcb->snd_wl2 == ackno && tcphdr->wnd > pcb->snd_wnd)) {
0811 pcb->snd_wnd = tcphdr->wnd;
0812 pcb->snd_wl1 = seqno;
0813 pcb->snd_wl2 = ackno;
0814 if (pcb->snd_wnd > 0 && pcb->persist_backoff > 0) {
0815 pcb->persist_backoff = 0;
0816 }
0817 LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"U16_F"\n", pcb->snd_wnd));
0818 #if TCP_WND_DEBUG
0819 } else {
0820 if (pcb->snd_wnd != tcphdr->wnd) {
0821 LWIP_DEBUGF(TCP_WND_DEBUG,
0822 ("tcp_receive: no window update lastack %"U32_F" ackno %"
0823 U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n",
0824 pcb->lastack, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2));
0825 }
0826 #endif
0827 }
0828
0829
0830
0831
0832
0833
0834
0835
0836
0837
0838
0839
0840
0841
0842
0843
0844
0845
0846
0847
0848
0849
0850 if (TCP_SEQ_LEQ(ackno, pcb->lastack)) {
0851 pcb->acked = 0;
0852
0853 if (tcplen == 0) {
0854
0855 if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge){
0856
0857 if (pcb->rtime >= 0) {
0858
0859 if (pcb->lastack == ackno) {
0860 found_dupack = 1;
0861 if (pcb->dupacks + 1 > pcb->dupacks)
0862 ++pcb->dupacks;
0863 if (pcb->dupacks > 3) {
0864
0865
0866 if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
0867 pcb->cwnd += pcb->mss;
0868 }
0869 } else if (pcb->dupacks == 3) {
0870
0871 tcp_rexmit_fast(pcb);
0872 }
0873 }
0874 }
0875 }
0876 }
0877
0878
0879 if (!found_dupack) {
0880 pcb->dupacks = 0;
0881 }
0882 } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)){
0883
0884
0885
0886
0887
0888 if (pcb->flags & TF_INFR) {
0889 pcb->flags &= ~TF_INFR;
0890 pcb->cwnd = pcb->ssthresh;
0891 }
0892
0893
0894 pcb->nrtx = 0;
0895
0896
0897 pcb->rto = (pcb->sa >> 3) + pcb->sv;
0898
0899
0900 pcb->acked = (u16_t)(ackno - pcb->lastack);
0901
0902 pcb->snd_buf += pcb->acked;
0903
0904
0905 pcb->dupacks = 0;
0906 pcb->lastack = ackno;
0907
0908
0909
0910 if (pcb->state >= ESTABLISHED) {
0911 if (pcb->cwnd < pcb->ssthresh) {
0912 if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
0913 pcb->cwnd += pcb->mss;
0914 }
0915 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"U16_F"\n", pcb->cwnd));
0916 } else {
0917 u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd);
0918 if (new_cwnd > pcb->cwnd) {
0919 pcb->cwnd = new_cwnd;
0920 }
0921 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"U16_F"\n", pcb->cwnd));
0922 }
0923 }
0924 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n",
0925 ackno,
0926 pcb->unacked != NULL?
0927 ntohl(pcb->unacked->tcphdr->seqno): 0,
0928 pcb->unacked != NULL?
0929 ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0));
0930
0931
0932
0933 while (pcb->unacked != NULL &&
0934 TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) +
0935 TCP_TCPLEN(pcb->unacked), ackno)) {
0936 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unacked\n",
0937 ntohl(pcb->unacked->tcphdr->seqno),
0938 ntohl(pcb->unacked->tcphdr->seqno) +
0939 TCP_TCPLEN(pcb->unacked)));
0940
0941 next = pcb->unacked;
0942 pcb->unacked = pcb->unacked->next;
0943
0944 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen));
0945 LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
0946
0947 if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) {
0948 pcb->acked--;
0949 }
0950
0951 pcb->snd_queuelen -= pbuf_clen(next->p);
0952 tcp_seg_free(next);
0953
0954 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unacked)\n", (u16_t)pcb->snd_queuelen));
0955 if (pcb->snd_queuelen != 0) {
0956 LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL ||
0957 pcb->unsent != NULL);
0958 }
0959 }
0960
0961
0962
0963 if(pcb->unacked == NULL)
0964 pcb->rtime = -1;
0965 else
0966 pcb->rtime = 0;
0967
0968 pcb->polltmr = 0;
0969 } else {
0970
0971 pcb->acked = 0;
0972 }
0973
0974
0975
0976
0977
0978
0979
0980 while (pcb->unsent != NULL &&
0981 TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) +
0982 TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) {
0983 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n",
0984 ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) +
0985 TCP_TCPLEN(pcb->unsent)));
0986
0987 next = pcb->unsent;
0988 pcb->unsent = pcb->unsent->next;
0989 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen));
0990 LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
0991
0992 if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) {
0993 pcb->acked--;
0994 }
0995 pcb->snd_queuelen -= pbuf_clen(next->p);
0996 tcp_seg_free(next);
0997 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unsent)\n", (u16_t)pcb->snd_queuelen));
0998 if (pcb->snd_queuelen != 0) {
0999 LWIP_ASSERT("tcp_receive: valid queue length",
1000 pcb->unacked != NULL || pcb->unsent != NULL);
1001 }
1002 }
1003
1004
1005 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %"U32_F" rtseq %"U32_F" ackno %"U32_F"\n",
1006 pcb->rttest, pcb->rtseq, ackno));
1007
1008
1009
1010
1011 if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) {
1012
1013
1014 m = (s16_t)(tcp_ticks - pcb->rttest);
1015
1016 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %"U16_F" ticks (%"U16_F" msec).\n",
1017 m, m * TCP_SLOW_INTERVAL));
1018
1019
1020 m = m - (pcb->sa >> 3);
1021 pcb->sa += m;
1022 if (m < 0) {
1023 m = -m;
1024 }
1025 m = m - (pcb->sv >> 2);
1026 pcb->sv += m;
1027 pcb->rto = (pcb->sa >> 3) + pcb->sv;
1028
1029 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %"U16_F" (%"U16_F" milliseconds)\n",
1030 pcb->rto, pcb->rto * TCP_SLOW_INTERVAL));
1031
1032 pcb->rttest = 0;
1033 }
1034 }
1035
1036
1037
1038 if (tcplen > 0) {
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069 if (TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno + 1, seqno + tcplen - 1)){
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090 off = pcb->rcv_nxt - seqno;
1091 p = inseg.p;
1092 LWIP_ASSERT("inseg.p != NULL", inseg.p);
1093 LWIP_ASSERT("insane offset!", (off < 0x7fff));
1094 if (inseg.p->len < off) {
1095 LWIP_ASSERT("pbuf too short!", (((s32_t)inseg.p->tot_len) >= off));
1096 new_tot_len = (u16_t)(inseg.p->tot_len - off);
1097 while (p->len < off) {
1098 off -= p->len;
1099
1100
1101
1102 p->tot_len = new_tot_len;
1103 p->len = 0;
1104 p = p->next;
1105 }
1106 if(pbuf_header(p, (s16_t)-off)) {
1107
1108 LWIP_ASSERT("pbuf_header failed", 0);
1109 }
1110 } else {
1111 if(pbuf_header(inseg.p, (s16_t)-off)) {
1112
1113 LWIP_ASSERT("pbuf_header failed", 0);
1114 }
1115 }
1116
1117
1118 inseg.dataptr = p->payload;
1119 inseg.len -= (u16_t)(pcb->rcv_nxt - seqno);
1120 inseg.tcphdr->seqno = seqno = pcb->rcv_nxt;
1121 }
1122 else {
1123 if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){
1124
1125
1126
1127 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno));
1128 tcp_ack_now(pcb);
1129 }
1130 }
1131
1132
1133
1134
1135 if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt,
1136 pcb->rcv_nxt + pcb->rcv_wnd - 1)){
1137 if (pcb->rcv_nxt == seqno) {
1138
1139
1140
1141 tcplen = TCP_TCPLEN(&inseg);
1142
1143 if (tcplen > pcb->rcv_wnd) {
1144 LWIP_DEBUGF(TCP_INPUT_DEBUG,
1145 ("tcp_receive: other end overran receive window"
1146 "seqno %"U32_F" len %"U32_F" right edge %"U32_F"\n",
1147 seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd));
1148 if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
1149
1150
1151 TCPH_FLAGS_SET(inseg.tcphdr, TCPH_FLAGS(inseg.tcphdr) &~ TCP_FIN);
1152 }
1153
1154 inseg.len = pcb->rcv_wnd;
1155 if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
1156 inseg.len -= 1;
1157 }
1158 pbuf_realloc(inseg.p, inseg.len);
1159 tcplen = TCP_TCPLEN(&inseg);
1160 LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n",
1161 (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd));
1162 }
1163 #if TCP_QUEUE_OOSEQ
1164 if (pcb->ooseq != NULL) {
1165 if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
1166 LWIP_DEBUGF(TCP_INPUT_DEBUG,
1167 ("tcp_receive: received in-order FIN, binning ooseq queue\n"));
1168
1169
1170
1171
1172
1173
1174
1175 while (pcb->ooseq != NULL) {
1176 struct tcp_seg *old_ooseq = pcb->ooseq;
1177 pcb->ooseq = pcb->ooseq->next;
1178 tcp_seg_free(old_ooseq);
1179 }
1180 }
1181 else {
1182 struct tcp_seg* next = pcb->ooseq;
1183 struct tcp_seg *old_seg;
1184
1185
1186
1187
1188 while (next &&
1189 TCP_SEQ_GEQ(seqno + tcplen,
1190 next->tcphdr->seqno + next->len)) {
1191
1192 if (TCPH_FLAGS(next->tcphdr) & TCP_FIN &&
1193 (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) {
1194 TCPH_FLAGS_SET(inseg.tcphdr,
1195 TCPH_FLAGS(inseg.tcphdr) | TCP_FIN);
1196 tcplen = TCP_TCPLEN(&inseg);
1197 }
1198 old_seg = next;
1199 next = next->next;
1200 tcp_seg_free(old_seg);
1201 }
1202
1203
1204
1205
1206 if (next &&
1207 TCP_SEQ_GT(seqno + tcplen,
1208 next->tcphdr->seqno)) {
1209
1210 inseg.len = (u16_t)(pcb->ooseq->tcphdr->seqno - seqno);
1211 if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
1212 inseg.len -= 1;
1213 }
1214 pbuf_realloc(inseg.p, inseg.len);
1215 tcplen = TCP_TCPLEN(&inseg);
1216 LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n",
1217 (seqno + tcplen) == pcb->ooseq->tcphdr->seqno);
1218 }
1219 pcb->ooseq = next;
1220 }
1221 }
1222 #endif
1223
1224 pcb->rcv_nxt = seqno + tcplen;
1225
1226
1227 LWIP_ASSERT("tcp_receive: tcplen > rcv_wnd\n", pcb->rcv_wnd >= tcplen);
1228 pcb->rcv_wnd -= tcplen;
1229
1230 tcp_update_rcv_ann_wnd(pcb);
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241 if (inseg.p->tot_len > 0) {
1242 recv_data = inseg.p;
1243
1244
1245
1246 inseg.p = NULL;
1247 }
1248 if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
1249 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n"));
1250 recv_flags |= TF_GOT_FIN;
1251 }
1252
1253 #if TCP_QUEUE_OOSEQ
1254
1255
1256 while (pcb->ooseq != NULL &&
1257 pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) {
1258
1259 cseg = pcb->ooseq;
1260 seqno = pcb->ooseq->tcphdr->seqno;
1261
1262 pcb->rcv_nxt += TCP_TCPLEN(cseg);
1263 LWIP_ASSERT("tcp_receive: ooseq tcplen > rcv_wnd\n",
1264 pcb->rcv_wnd >= TCP_TCPLEN(cseg));
1265 pcb->rcv_wnd -= TCP_TCPLEN(cseg);
1266
1267 tcp_update_rcv_ann_wnd(pcb);
1268
1269 if (cseg->p->tot_len > 0) {
1270
1271
1272 if (recv_data) {
1273 pbuf_cat(recv_data, cseg->p);
1274 } else {
1275 recv_data = cseg->p;
1276 }
1277 cseg->p = NULL;
1278 }
1279 if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
1280 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n"));
1281 recv_flags |= TF_GOT_FIN;
1282 if (pcb->state == ESTABLISHED) {
1283 pcb->state = CLOSE_WAIT;
1284 }
1285 }
1286
1287 pcb->ooseq = cseg->next;
1288 tcp_seg_free(cseg);
1289 }
1290 #endif
1291
1292
1293
1294 tcp_ack(pcb);
1295
1296 } else {
1297
1298 tcp_send_empty_ack(pcb);
1299 #if TCP_QUEUE_OOSEQ
1300
1301 if (pcb->ooseq == NULL) {
1302 pcb->ooseq = tcp_seg_copy(&inseg);
1303 } else {
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316 prev = NULL;
1317 for(next = pcb->ooseq; next != NULL; next = next->next) {
1318 if (seqno == next->tcphdr->seqno) {
1319
1320
1321
1322
1323 if (inseg.len > next->len) {
1324
1325
1326
1327 cseg = tcp_seg_copy(&inseg);
1328 if (cseg != NULL) {
1329 if (prev != NULL) {
1330 prev->next = cseg;
1331 } else {
1332 pcb->ooseq = cseg;
1333 }
1334 tcp_oos_insert_segment(cseg, next);
1335 }
1336 break;
1337 } else {
1338
1339
1340
1341 break;
1342 }
1343 } else {
1344 if (prev == NULL) {
1345 if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {
1346
1347
1348
1349
1350 cseg = tcp_seg_copy(&inseg);
1351 if (cseg != NULL) {
1352 pcb->ooseq = cseg;
1353 tcp_oos_insert_segment(cseg, next);
1354 }
1355 break;
1356 }
1357 } else {
1358
1359
1360 if (TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)) {
1361
1362
1363
1364
1365
1366 cseg = tcp_seg_copy(&inseg);
1367 if (cseg != NULL) {
1368 if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) {
1369
1370 prev->len = (u16_t)(seqno - prev->tcphdr->seqno);
1371 pbuf_realloc(prev->p, prev->len);
1372 }
1373 prev->next = cseg;
1374 tcp_oos_insert_segment(cseg, next);
1375 }
1376 break;
1377 }
1378 }
1379
1380
1381
1382 if (next->next == NULL &&
1383 TCP_SEQ_GT(seqno, next->tcphdr->seqno)) {
1384 if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) {
1385
1386 break;
1387 }
1388 next->next = tcp_seg_copy(&inseg);
1389 if (next->next != NULL) {
1390 if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) {
1391
1392 next->len = (u16_t)(seqno - next->tcphdr->seqno);
1393 pbuf_realloc(next->p, next->len);
1394 }
1395 }
1396 break;
1397 }
1398 }
1399 prev = next;
1400 }
1401 }
1402 #endif
1403
1404 }
1405 } else {
1406
1407 tcp_send_empty_ack(pcb);
1408 }
1409 } else {
1410
1411
1412
1413
1414 if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){
1415 tcp_ack_now(pcb);
1416 }
1417 }
1418 }
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428 static void
1429 tcp_parseopt(struct tcp_pcb *pcb)
1430 {
1431 u16_t c, max_c;
1432 u16_t mss;
1433 u8_t *opts, opt;
1434 #if LWIP_TCP_TIMESTAMPS
1435 u32_t tsval;
1436 #endif
1437
1438 opts = (u8_t *)tcphdr + TCP_HLEN;
1439
1440
1441 if(TCPH_HDRLEN(tcphdr) > 0x5) {
1442 max_c = (TCPH_HDRLEN(tcphdr) - 5) << 2;
1443 for (c = 0; c < max_c; ) {
1444 opt = opts[c];
1445 switch (opt) {
1446 case 0x00:
1447
1448 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: EOL\n"));
1449 return;
1450 case 0x01:
1451
1452 ++c;
1453 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: NOP\n"));
1454 break;
1455 case 0x02:
1456 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: MSS\n"));
1457 if (opts[c + 1] != 0x04 || c + 0x04 > max_c) {
1458
1459 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
1460 return;
1461 }
1462
1463 mss = (opts[c + 2] << 8) | opts[c + 3];
1464
1465 pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss;
1466
1467 c += 0x04;
1468 break;
1469 #if LWIP_TCP_TIMESTAMPS
1470 case 0x08:
1471 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: TS\n"));
1472 if (opts[c + 1] != 0x0A || c + 0x0A > max_c) {
1473
1474 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
1475 return;
1476 }
1477
1478 tsval = (opts[c+2]) | (opts[c+3] << 8) |
1479 (opts[c+4] << 16) | (opts[c+5] << 24);
1480 if (flags & TCP_SYN) {
1481 pcb->ts_recent = ntohl(tsval);
1482 pcb->flags |= TF_TIMESTAMP;
1483 } else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno+tcplen)) {
1484 pcb->ts_recent = ntohl(tsval);
1485 }
1486
1487 c += 0x0A;
1488 break;
1489 #endif
1490 default:
1491 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: other\n"));
1492 if (opts[c + 1] == 0) {
1493 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
1494
1495
1496 return;
1497 }
1498
1499
1500 c += opts[c + 1];
1501 }
1502 }
1503 }
1504 }
1505
1506 #endif