My fork of the HTTPServer (working)
Embed:
(wiki syntax)
Show/hide line numbers
tcp_in.c
Go to the documentation of this file.
00001 /** 00002 * @file 00003 * Transmission Control Protocol, incoming traffic 00004 * 00005 * The input processing functions of the TCP layer. 00006 * 00007 * These functions are generally called in the order (ip_input() ->) 00008 * tcp_input() -> * tcp_process() -> tcp_receive() (-> application). 00009 * 00010 */ 00011 00012 /* 00013 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 00014 * All rights reserved. 00015 * 00016 * Redistribution and use in source and binary forms, with or without modification, 00017 * are permitted provided that the following conditions are met: 00018 * 00019 * 1. Redistributions of source code must retain the above copyright notice, 00020 * this list of conditions and the following disclaimer. 00021 * 2. Redistributions in binary form must reproduce the above copyright notice, 00022 * this list of conditions and the following disclaimer in the documentation 00023 * and/or other materials provided with the distribution. 00024 * 3. The name of the author may not be used to endorse or promote products 00025 * derived from this software without specific prior written permission. 00026 * 00027 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00028 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00029 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00030 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00031 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00032 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00033 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00034 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00035 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00036 * OF SUCH DAMAGE. 00037 * 00038 * This file is part of the lwIP TCP/IP stack. 00039 * 00040 * Author: Adam Dunkels <adam@sics.se> 00041 * 00042 */ 00043 00044 #include "lwip/opt.h" 00045 00046 #if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ 00047 00048 #include "lwip/tcp.h" 00049 #include "lwip/def.h" 00050 #include "lwip/ip_addr.h" 00051 #include "lwip/netif.h" 00052 #include "lwip/mem.h" 00053 #include "lwip/memp.h" 00054 #include "lwip/inet.h" 00055 #include "lwip/inet_chksum.h" 00056 #include "lwip/stats.h" 00057 #include "lwip/snmp.h" 00058 #include "arch/perf.h" 00059 00060 /* These variables are global to all functions involved in the input 00061 processing of TCP segments. They are set by the tcp_input() 00062 function. */ 00063 static struct tcp_seg inseg; 00064 static struct tcp_hdr *tcphdr; 00065 static struct ip_hdr *iphdr; 00066 static u32_t seqno, ackno; 00067 static u8_t flags; 00068 static u16_t tcplen; 00069 00070 static u8_t recv_flags; 00071 static struct pbuf *recv_data; 00072 00073 struct tcp_pcb *tcp_input_pcb; 00074 00075 /* Forward declarations. */ 00076 static err_t tcp_process(struct tcp_pcb *pcb); 00077 static u8_t tcp_receive(struct tcp_pcb *pcb); 00078 static void tcp_parseopt(struct tcp_pcb *pcb); 00079 00080 static err_t tcp_listen_input(struct tcp_pcb_listen *pcb); 00081 static err_t tcp_timewait_input(struct tcp_pcb *pcb); 00082 00083 /** 00084 * The initial input processing of TCP. It verifies the TCP header, demultiplexes 00085 * the segment between the PCBs and passes it on to tcp_process(), which implements 00086 * the TCP finite state machine. This function is called by the IP layer (in 00087 * ip_input()). 00088 * 00089 * @param p received TCP segment to process (p->payload pointing to the IP header) 00090 * @param inp network interface on which this segment was received 00091 */ 00092 void 00093 tcp_input(struct pbuf *p, struct netif *inp) 00094 { 00095 struct tcp_pcb *pcb, *prev; 00096 struct tcp_pcb_listen *lpcb; 00097 u8_t hdrlen; 00098 err_t err; 00099 00100 PERF_START; 00101 00102 TCP_STATS_INC(tcp.recv); 00103 snmp_inc_tcpinsegs(); 00104 00105 iphdr = (struct ip_hdr *)(p->payload); 00106 tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4); 00107 00108 #if TCP_INPUT_DEBUG 00109 tcp_debug_print(tcphdr); 00110 #endif 00111 00112 /* remove header from payload */ 00113 if (pbuf_header(p, -((s16_t)(IPH_HL(iphdr) * 4))) || (p->tot_len < sizeof(struct tcp_hdr))) { 00114 /* drop short packets */ 00115 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len)); 00116 TCP_STATS_INC(tcp.lenerr); 00117 TCP_STATS_INC(tcp.drop); 00118 snmp_inc_tcpinerrs(); 00119 pbuf_free(p); 00120 return; 00121 } 00122 00123 /* Don't even process incoming broadcasts/multicasts. */ 00124 if (ip_addr_isbroadcast(&(iphdr->dest), inp) || 00125 ip_addr_ismulticast(&(iphdr->dest))) { 00126 TCP_STATS_INC(tcp.proterr); 00127 TCP_STATS_INC(tcp.drop); 00128 snmp_inc_tcpinerrs(); 00129 pbuf_free(p); 00130 return; 00131 } 00132 00133 #if CHECKSUM_CHECK_TCP 00134 /* Verify TCP checksum. */ 00135 if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src), 00136 (struct ip_addr *)&(iphdr->dest), 00137 IP_PROTO_TCP, p->tot_len) != 0) { 00138 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n", 00139 inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src), (struct ip_addr *)&(iphdr->dest), 00140 IP_PROTO_TCP, p->tot_len))); 00141 #if TCP_DEBUG 00142 tcp_debug_print(tcphdr); 00143 #endif /* TCP_DEBUG */ 00144 TCP_STATS_INC(tcp.chkerr); 00145 TCP_STATS_INC(tcp.drop); 00146 snmp_inc_tcpinerrs(); 00147 pbuf_free(p); 00148 return; 00149 } 00150 #endif 00151 00152 /* Move the payload pointer in the pbuf so that it points to the 00153 TCP data instead of the TCP header. */ 00154 hdrlen = TCPH_HDRLEN(tcphdr); 00155 if(pbuf_header(p, -(hdrlen * 4))){ 00156 /* drop short packets */ 00157 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet\n")); 00158 TCP_STATS_INC(tcp.lenerr); 00159 TCP_STATS_INC(tcp.drop); 00160 snmp_inc_tcpinerrs(); 00161 pbuf_free(p); 00162 return; 00163 } 00164 00165 /* Convert fields in TCP header to host byte order. */ 00166 tcphdr->src = ntohs(tcphdr->src); 00167 tcphdr->dest = ntohs(tcphdr->dest); 00168 seqno = tcphdr->seqno = ntohl(tcphdr->seqno); 00169 ackno = tcphdr->ackno = ntohl(tcphdr->ackno); 00170 tcphdr->wnd = ntohs(tcphdr->wnd); 00171 00172 flags = TCPH_FLAGS(tcphdr) & TCP_FLAGS; 00173 tcplen = p->tot_len + ((flags & TCP_FIN || flags & TCP_SYN)? 1: 0); 00174 00175 /* Demultiplex an incoming segment. First, we check if it is destined 00176 for an active connection. */ 00177 prev = (struct tcp_pcb *)(NULL); 00178 00179 00180 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { 00181 LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED); 00182 LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); 00183 LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN); 00184 if (pcb->remote_port == tcphdr->src && 00185 pcb->local_port == tcphdr->dest && 00186 ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) && 00187 ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) { 00188 00189 /* Move this PCB to the front of the list so that subsequent 00190 lookups will be faster (we exploit locality in TCP segment 00191 arrivals). */ 00192 LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb); 00193 if (prev != NULL) { 00194 prev->next = pcb->next; 00195 pcb->next = tcp_active_pcbs; 00196 tcp_active_pcbs = pcb; 00197 } 00198 LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb); 00199 break; 00200 } 00201 prev = pcb; 00202 } 00203 00204 if (pcb == NULL) { 00205 /* If it did not go to an active connection, we check the connections 00206 in the TIME-WAIT state. */ 00207 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { 00208 LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); 00209 if (pcb->remote_port == tcphdr->src && 00210 pcb->local_port == tcphdr->dest && 00211 ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) && 00212 ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) { 00213 /* We don't really care enough to move this PCB to the front 00214 of the list since we are not very likely to receive that 00215 many segments for connections in TIME-WAIT. */ 00216 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n")); 00217 tcp_timewait_input(pcb); 00218 pbuf_free(p); 00219 return; 00220 } 00221 } 00222 00223 /* Finally, if we still did not get a match, we check all PCBs that 00224 are LISTENing for incoming connections. */ 00225 prev = (struct tcp_pcb *)(NULL); 00226 for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { 00227 if ((ip_addr_isany(&(lpcb->local_ip)) || 00228 ip_addr_cmp(&(lpcb->local_ip), &(iphdr->dest))) && 00229 lpcb->local_port == tcphdr->dest) { 00230 /* Move this PCB to the front of the list so that subsequent 00231 lookups will be faster (we exploit locality in TCP segment 00232 arrivals). */ 00233 if (prev != NULL) { 00234 ((struct tcp_pcb_listen *)prev)->next = lpcb->next; 00235 /* our successor is the remainder of the listening list */ 00236 lpcb->next = tcp_listen_pcbs.listen_pcbs; 00237 /* put this listening pcb at the head of the listening list */ 00238 tcp_listen_pcbs.listen_pcbs = lpcb; 00239 } 00240 00241 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n")); 00242 tcp_listen_input(lpcb); 00243 pbuf_free(p); 00244 return; 00245 } 00246 prev = (struct tcp_pcb *)lpcb; 00247 } 00248 } 00249 00250 #if TCP_INPUT_DEBUG 00251 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags ")); 00252 tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); 00253 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n")); 00254 #endif /* TCP_INPUT_DEBUG */ 00255 00256 00257 if (pcb != NULL) { 00258 /* The incoming segment belongs to a connection. */ 00259 #if TCP_INPUT_DEBUG 00260 #if TCP_DEBUG 00261 tcp_debug_print_state(pcb->state); 00262 #endif /* TCP_DEBUG */ 00263 #endif /* TCP_INPUT_DEBUG */ 00264 00265 /* Set up a tcp_seg structure. */ 00266 inseg.next = (struct tcp_seg *)(NULL); 00267 inseg.len = p->tot_len; 00268 inseg.dataptr = p->payload; 00269 inseg.p = p; 00270 inseg.tcphdr = tcphdr; 00271 00272 recv_data = (struct pbuf *)(NULL); 00273 recv_flags = 0; 00274 00275 /* If there is data which was previously "refused" by upper layer */ 00276 if (pcb->refused_data != NULL) { 00277 /* Notify again application with data previously received. */ 00278 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: notify kept packet\n")); 00279 TCP_EVENT_RECV(pcb, pcb->refused_data, ERR_OK, err); 00280 if (err == ERR_OK) { 00281 pcb->refused_data = (struct pbuf *)(NULL); 00282 } else { 00283 /* drop incoming packets, because pcb is "full" */ 00284 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n")); 00285 TCP_STATS_INC(tcp.drop); 00286 snmp_inc_tcpinerrs(); 00287 pbuf_free(p); 00288 return; 00289 } 00290 } 00291 00292 tcp_input_pcb = pcb; 00293 err = tcp_process(pcb); 00294 tcp_input_pcb = (struct tcp_pcb *)(NULL); 00295 /* A return value of ERR_ABRT means that tcp_abort() was called 00296 and that the pcb has been freed. If so, we don't do anything. */ 00297 if (err != ERR_ABRT) { 00298 if (recv_flags & TF_RESET) { 00299 /* TF_RESET means that the connection was reset by the other 00300 end. We then call the error callback to inform the 00301 application that the connection is dead before we 00302 deallocate the PCB. */ 00303 TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST); 00304 tcp_pcb_remove(&tcp_active_pcbs, pcb); 00305 memp_free(MEMP_TCP_PCB, pcb); 00306 } else if (recv_flags & TF_CLOSED) { 00307 /* The connection has been closed and we will deallocate the 00308 PCB. */ 00309 tcp_pcb_remove(&tcp_active_pcbs, pcb); 00310 memp_free(MEMP_TCP_PCB, pcb); 00311 } else { 00312 err = ERR_OK; 00313 /* If the application has registered a "sent" function to be 00314 called when new send buffer space is available, we call it 00315 now. */ 00316 if (pcb->acked > 0) { 00317 TCP_EVENT_SENT(pcb, pcb->acked, err); 00318 } 00319 00320 if (recv_data != NULL) { 00321 if(flags & TCP_PSH) { 00322 recv_data->flags |= PBUF_FLAG_PUSH; 00323 } 00324 00325 /* Notify application that data has been received. */ 00326 TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err); 00327 00328 /* If the upper layer can't receive this data, store it */ 00329 if (err != ERR_OK) { 00330 pcb->refused_data = recv_data; 00331 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: keep incoming packet, because pcb is \"full\"\n")); 00332 } 00333 } 00334 00335 /* If a FIN segment was received, we call the callback 00336 function with a NULL buffer to indicate EOF. */ 00337 if (recv_flags & TF_GOT_FIN) { 00338 TCP_EVENT_RECV(pcb, (NULL), ERR_OK, err); 00339 } 00340 00341 /* If there were no errors, we try to send something out. */ 00342 if (err == ERR_OK) { 00343 tcp_output(pcb); 00344 } 00345 } 00346 } 00347 00348 00349 /* give up our reference to inseg.p */ 00350 if (inseg.p != NULL) 00351 { 00352 pbuf_free(inseg.p); 00353 inseg.p = (struct pbuf *)(NULL); 00354 } 00355 #if TCP_INPUT_DEBUG 00356 #if TCP_DEBUG 00357 tcp_debug_print_state(pcb->state); 00358 #endif /* TCP_DEBUG */ 00359 #endif /* TCP_INPUT_DEBUG */ 00360 00361 } else { 00362 00363 /* If no matching PCB was found, send a TCP RST (reset) to the 00364 sender. */ 00365 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n")); 00366 if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) { 00367 TCP_STATS_INC(tcp.proterr); 00368 TCP_STATS_INC(tcp.drop); 00369 struct ip_addr iphdrdest; 00370 iphdrdest.addr = iphdr->dest.addr; 00371 struct ip_addr iphdrsrc; 00372 iphdrsrc.addr = iphdr->src.addr; 00373 tcp_rst(ackno, seqno + tcplen, 00374 &(iphdrdest), &(iphdrsrc), 00375 tcphdr->dest, tcphdr->src); 00376 } 00377 pbuf_free(p); 00378 } 00379 00380 LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane()); 00381 PERF_STOP("tcp_input"); 00382 } 00383 00384 /** 00385 * Called by tcp_input() when a segment arrives for a listening 00386 * connection (from tcp_input()). 00387 * 00388 * @param pcb the tcp_pcb_listen for which a segment arrived 00389 * @return ERR_OK if the segment was processed 00390 * another err_t on error 00391 * 00392 * @note the return value is not (yet?) used in tcp_input() 00393 * @note the segment which arrived is saved in global variables, therefore only the pcb 00394 * involved is passed as a parameter to this function 00395 */ 00396 static err_t 00397 tcp_listen_input(struct tcp_pcb_listen *pcb) 00398 { 00399 struct tcp_pcb *npcb; 00400 err_t rc; 00401 00402 /* In the LISTEN state, we check for incoming SYN segments, 00403 creates a new PCB, and responds with a SYN|ACK. */ 00404 if (flags & TCP_ACK) { 00405 /* For incoming segments with the ACK flag set, respond with a 00406 RST. */ 00407 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n")); 00408 struct ip_addr iphdrdest; 00409 iphdrdest.addr = iphdr->dest.addr; 00410 struct ip_addr iphdrsrc; 00411 iphdrsrc.addr = iphdr->src.addr; 00412 tcp_rst(ackno + 1, seqno + tcplen, 00413 &(iphdrdest), &(iphdrsrc), 00414 tcphdr->dest, tcphdr->src); 00415 } else if (flags & TCP_SYN) { 00416 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest)); 00417 #if TCP_LISTEN_BACKLOG 00418 if (pcb->accepts_pending >= pcb->backlog) { 00419 return ERR_ABRT; 00420 } 00421 #endif /* TCP_LISTEN_BACKLOG */ 00422 npcb = tcp_alloc(pcb->prio); 00423 /* If a new PCB could not be created (probably due to lack of memory), 00424 we don't do anything, but rely on the sender will retransmit the 00425 SYN at a time when we have more memory available. */ 00426 if (npcb == NULL) { 00427 LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n")); 00428 TCP_STATS_INC(tcp.memerr); 00429 return ERR_MEM; 00430 } 00431 #if TCP_LISTEN_BACKLOG 00432 pcb->accepts_pending++; 00433 #endif /* TCP_LISTEN_BACKLOG */ 00434 /* Set up the new PCB. */ 00435 ip_addr_set(&(npcb->local_ip), &(iphdr->dest)); 00436 npcb->local_port = pcb->local_port; 00437 ip_addr_set(&(npcb->remote_ip), &(iphdr->src)); 00438 npcb->remote_port = tcphdr->src; 00439 npcb->state = SYN_RCVD; 00440 npcb->rcv_nxt = seqno + 1; 00441 npcb->rcv_ann_right_edge = npcb->rcv_nxt; 00442 npcb->snd_wnd = tcphdr->wnd; 00443 npcb->ssthresh = npcb->snd_wnd; 00444 npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */ 00445 npcb->callback_arg = pcb->callback_arg; 00446 #if LWIP_CALLBACK_API 00447 npcb->accept = pcb->accept; 00448 #endif /* LWIP_CALLBACK_API */ 00449 /* inherit socket options */ 00450 npcb->so_options = pcb->so_options & (SOF_DEBUG|SOF_DONTROUTE|SOF_KEEPALIVE|SOF_OOBINLINE|SOF_LINGER); 00451 /* Register the new PCB so that we can begin receiving segments 00452 for it. */ 00453 TCP_REG(&tcp_active_pcbs, npcb); 00454 00455 /* Parse any options in the SYN. */ 00456 tcp_parseopt(npcb); 00457 #if TCP_CALCULATE_EFF_SEND_MSS 00458 npcb->mss = tcp_eff_send_mss(npcb->mss, &(npcb->remote_ip)); 00459 #endif /* TCP_CALCULATE_EFF_SEND_MSS */ 00460 00461 snmp_inc_tcppassiveopens(); 00462 00463 /* Send a SYN|ACK together with the MSS option. */ 00464 rc = tcp_enqueue(npcb, NULL, 0, TCP_SYN | TCP_ACK, 0, TF_SEG_OPTS_MSS 00465 #if LWIP_TCP_TIMESTAMPS 00466 /* and maybe include the TIMESTAMP option */ 00467 | (npcb->flags & TF_TIMESTAMP ? TF_SEG_OPTS_TS : 0) 00468 #endif 00469 ); 00470 if (rc != ERR_OK) { 00471 tcp_abandon(npcb, 0); 00472 return rc; 00473 } 00474 return tcp_output(npcb); 00475 } 00476 return ERR_OK; 00477 } 00478 00479 /** 00480 * Called by tcp_input() when a segment arrives for a connection in 00481 * TIME_WAIT. 00482 * 00483 * @param pcb the tcp_pcb for which a segment arrived 00484 * 00485 * @note the segment which arrived is saved in global variables, therefore only the pcb 00486 * involved is passed as a parameter to this function 00487 */ 00488 static err_t 00489 tcp_timewait_input(struct tcp_pcb *pcb) 00490 { 00491 if (TCP_SEQ_GT(seqno + tcplen, pcb->rcv_nxt)) { 00492 pcb->rcv_nxt = seqno + tcplen; 00493 } 00494 if (tcplen > 0) { 00495 tcp_ack_now(pcb); 00496 } 00497 return tcp_output(pcb); 00498 } 00499 00500 /** 00501 * Implements the TCP state machine. Called by tcp_input. In some 00502 * states tcp_receive() is called to receive data. The tcp_seg 00503 * argument will be freed by the caller (tcp_input()) unless the 00504 * recv_data pointer in the pcb is set. 00505 * 00506 * @param pcb the tcp_pcb for which a segment arrived 00507 * 00508 * @note the segment which arrived is saved in global variables, therefore only the pcb 00509 * involved is passed as a parameter to this function 00510 */ 00511 static err_t 00512 tcp_process(struct tcp_pcb *pcb) 00513 { 00514 struct tcp_seg *rseg; 00515 u8_t acceptable = 0; 00516 err_t err; 00517 u8_t accepted_inseq; 00518 00519 err = ERR_OK; 00520 00521 /* Process incoming RST segments. */ 00522 if (flags & TCP_RST) { 00523 /* First, determine if the reset is acceptable. */ 00524 if (pcb->state == SYN_SENT) { 00525 if (ackno == pcb->snd_nxt) { 00526 acceptable = 1; 00527 } 00528 } else { 00529 if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, 00530 pcb->rcv_nxt+pcb->rcv_wnd)) { 00531 acceptable = 1; 00532 } 00533 } 00534 00535 if (acceptable) { 00536 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n")); 00537 LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED); 00538 recv_flags = TF_RESET; 00539 pcb->flags &= ~TF_ACK_DELAY; 00540 return ERR_RST; 00541 } else { 00542 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", 00543 seqno, pcb->rcv_nxt)); 00544 LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", 00545 seqno, pcb->rcv_nxt)); 00546 return ERR_OK; 00547 } 00548 } 00549 00550 if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) { 00551 /* Cope with new connection attempt after remote end crashed */ 00552 tcp_ack_now(pcb); 00553 return ERR_OK; 00554 } 00555 00556 /* Update the PCB (in)activity timer. */ 00557 pcb->tmr = tcp_ticks; 00558 pcb->keep_cnt_sent = 0; 00559 00560 tcp_parseopt(pcb); 00561 00562 /* Do different things depending on the TCP state. */ 00563 switch (pcb->state) { 00564 case SYN_SENT: 00565 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno, 00566 pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno))); 00567 /* received SYN ACK with expected sequence number? */ 00568 if ((flags & TCP_ACK) && (flags & TCP_SYN) 00569 && ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) { 00570 pcb->snd_buf++; 00571 pcb->rcv_nxt = seqno + 1; 00572 pcb->rcv_ann_right_edge = pcb->rcv_nxt; 00573 pcb->lastack = ackno; 00574 pcb->snd_wnd = tcphdr->wnd; 00575 pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */ 00576 pcb->state = ESTABLISHED; 00577 00578 #if TCP_CALCULATE_EFF_SEND_MSS 00579 pcb->mss = tcp_eff_send_mss(pcb->mss, &(pcb->remote_ip)); 00580 #endif /* TCP_CALCULATE_EFF_SEND_MSS */ 00581 00582 /* Set ssthresh again after changing pcb->mss (already set in tcp_connect 00583 * but for the default value of pcb->mss) */ 00584 pcb->ssthresh = pcb->mss * 10; 00585 00586 pcb->cwnd = ((pcb->cwnd == 1) ? (pcb->mss * 2) : pcb->mss); 00587 LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0)); 00588 --pcb->snd_queuelen; 00589 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"U16_F"\n", (u16_t)pcb->snd_queuelen)); 00590 rseg = pcb->unacked; 00591 pcb->unacked = rseg->next; 00592 00593 /* If there's nothing left to acknowledge, stop the retransmit 00594 timer, otherwise reset it to start again */ 00595 if(pcb->unacked == NULL) 00596 pcb->rtime = -1; 00597 else { 00598 pcb->rtime = 0; 00599 pcb->nrtx = 0; 00600 } 00601 00602 tcp_seg_free(rseg); 00603 00604 /* Call the user specified function to call when sucessfully 00605 * connected. */ 00606 TCP_EVENT_CONNECTED(pcb, ERR_OK, err); 00607 tcp_ack_now(pcb); 00608 } 00609 /* received ACK? possibly a half-open connection */ 00610 else if (flags & TCP_ACK) { 00611 /* send a RST to bring the other side in a non-synchronized state. */ 00612 struct ip_addr iphdrdest; 00613 iphdrdest.addr = iphdr->dest.addr; 00614 struct ip_addr iphdrsrc; 00615 iphdrsrc.addr = iphdr->src.addr; 00616 tcp_rst(ackno, seqno + tcplen, &(iphdrdest), &(iphdrsrc), 00617 tcphdr->dest, tcphdr->src); 00618 } 00619 break; 00620 case SYN_RCVD: 00621 if (flags & TCP_ACK) { 00622 /* expected ACK number? */ 00623 if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) { 00624 u16_t old_cwnd; 00625 pcb->state = ESTABLISHED; 00626 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); 00627 #if LWIP_CALLBACK_API 00628 LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL); 00629 #endif 00630 /* Call the accept function. */ 00631 TCP_EVENT_ACCEPT(pcb, ERR_OK, err); 00632 if (err != ERR_OK) { 00633 /* If the accept function returns with an error, we abort 00634 * the connection. */ 00635 tcp_abort(pcb); 00636 return ERR_ABRT; 00637 } 00638 old_cwnd = pcb->cwnd; 00639 /* If there was any data contained within this ACK, 00640 * we'd better pass it on to the application as well. */ 00641 accepted_inseq = tcp_receive(pcb); 00642 00643 pcb->cwnd = ((old_cwnd == 1) ? (pcb->mss * 2) : pcb->mss); 00644 00645 if ((flags & TCP_FIN) && accepted_inseq) { 00646 tcp_ack_now(pcb); 00647 pcb->state = CLOSE_WAIT; 00648 } 00649 } 00650 /* incorrect ACK number */ 00651 else { 00652 /* send RST */ 00653 struct ip_addr iphdrdest; 00654 iphdrdest.addr = iphdr->dest.addr; 00655 struct ip_addr iphdrsrc; 00656 iphdrsrc.addr = iphdr->src.addr; 00657 tcp_rst(ackno, seqno + tcplen, &(iphdrdest), &(iphdrsrc), 00658 tcphdr->dest, tcphdr->src); 00659 } 00660 } else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) { 00661 /* Looks like another copy of the SYN - retransmit our SYN-ACK */ 00662 tcp_rexmit(pcb); 00663 } 00664 break; 00665 case CLOSE_WAIT: 00666 /* FALLTHROUGH */ 00667 case ESTABLISHED: 00668 accepted_inseq = tcp_receive(pcb); 00669 if ((flags & TCP_FIN) && accepted_inseq) { /* passive close */ 00670 tcp_ack_now(pcb); 00671 pcb->state = CLOSE_WAIT; 00672 } 00673 break; 00674 case FIN_WAIT_1: 00675 tcp_receive(pcb); 00676 if (flags & TCP_FIN) { 00677 if (flags & TCP_ACK && ackno == pcb->snd_nxt) { 00678 LWIP_DEBUGF(TCP_DEBUG, 00679 ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); 00680 tcp_ack_now(pcb); 00681 tcp_pcb_purge(pcb); 00682 TCP_RMV(&tcp_active_pcbs, pcb); 00683 pcb->state = TIME_WAIT; 00684 TCP_REG(&tcp_tw_pcbs, pcb); 00685 } else { 00686 tcp_ack_now(pcb); 00687 pcb->state = CLOSING; 00688 } 00689 } else if (flags & TCP_ACK && ackno == pcb->snd_nxt) { 00690 pcb->state = FIN_WAIT_2; 00691 } 00692 break; 00693 case FIN_WAIT_2: 00694 tcp_receive(pcb); 00695 if (flags & TCP_FIN) { 00696 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); 00697 tcp_ack_now(pcb); 00698 tcp_pcb_purge(pcb); 00699 TCP_RMV(&tcp_active_pcbs, pcb); 00700 pcb->state = TIME_WAIT; 00701 TCP_REG(&tcp_tw_pcbs, pcb); 00702 } 00703 break; 00704 case CLOSING: 00705 tcp_receive(pcb); 00706 if (flags & TCP_ACK && ackno == pcb->snd_nxt) { 00707 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); 00708 tcp_ack_now(pcb); 00709 tcp_pcb_purge(pcb); 00710 TCP_RMV(&tcp_active_pcbs, pcb); 00711 pcb->state = TIME_WAIT; 00712 TCP_REG(&tcp_tw_pcbs, pcb); 00713 } 00714 break; 00715 case LAST_ACK: 00716 tcp_receive(pcb); 00717 if (flags & TCP_ACK && ackno == pcb->snd_nxt) { 00718 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); 00719 /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */ 00720 recv_flags = TF_CLOSED; 00721 } 00722 break; 00723 default: 00724 break; 00725 } 00726 return ERR_OK; 00727 } 00728 00729 /** 00730 * Called by tcp_process. Checks if the given segment is an ACK for outstanding 00731 * data, and if so frees the memory of the buffered data. Next, is places the 00732 * segment on any of the receive queues (pcb->recved or pcb->ooseq). If the segment 00733 * is buffered, the pbuf is referenced by pbuf_ref so that it will not be freed until 00734 * i it has been removed from the buffer. 00735 * 00736 * If the incoming segment constitutes an ACK for a segment that was used for RTT 00737 * estimation, the RTT is estimated here as well. 00738 * 00739 * Called from tcp_process(). 00740 * 00741 * @return 1 if the incoming segment is the next in sequence, 0 if not 00742 */ 00743 static u8_t 00744 tcp_receive(struct tcp_pcb *pcb) 00745 { 00746 struct tcp_seg *next; 00747 #if TCP_QUEUE_OOSEQ 00748 struct tcp_seg *prev, *cseg; 00749 #endif 00750 struct pbuf *p; 00751 s32_t off; 00752 s16_t m; 00753 u32_t right_wnd_edge; 00754 u16_t new_tot_len; 00755 u8_t accepted_inseq = 0; 00756 00757 if (flags & TCP_ACK) { 00758 right_wnd_edge = pcb->snd_wnd + pcb->snd_wl1; 00759 00760 /* Update window. */ 00761 if (TCP_SEQ_LT(pcb->snd_wl1, seqno) || 00762 (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) || 00763 (pcb->snd_wl2 == ackno && tcphdr->wnd > pcb->snd_wnd)) { 00764 pcb->snd_wnd = tcphdr->wnd; 00765 pcb->snd_wl1 = seqno; 00766 pcb->snd_wl2 = ackno; 00767 if (pcb->snd_wnd > 0 && pcb->persist_backoff > 0) { 00768 pcb->persist_backoff = 0; 00769 } 00770 LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"U16_F"\n", pcb->snd_wnd)); 00771 #if TCP_WND_DEBUG 00772 } else { 00773 if (pcb->snd_wnd != tcphdr->wnd) { 00774 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", 00775 pcb->lastack, pcb->snd_max, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2)); 00776 } 00777 #endif /* TCP_WND_DEBUG */ 00778 } 00779 00780 if (pcb->lastack == ackno) { 00781 pcb->acked = 0; 00782 00783 if (pcb->snd_wl1 + pcb->snd_wnd == right_wnd_edge){ 00784 ++pcb->dupacks; 00785 if (pcb->dupacks >= 3 && pcb->unacked != NULL) { 00786 if (!(pcb->flags & TF_INFR)) { 00787 /* This is fast retransmit. Retransmit the first unacked segment. */ 00788 LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupacks %"U16_F" (%"U32_F"), fast retransmit %"U32_F"\n", 00789 (u16_t)pcb->dupacks, pcb->lastack, 00790 ntohl(pcb->unacked->tcphdr->seqno))); 00791 tcp_rexmit(pcb); 00792 /* Set ssthresh to max (FlightSize / 2, 2*SMSS) */ 00793 /*pcb->ssthresh = LWIP_MAX((pcb->snd_max - 00794 pcb->lastack) / 2, 00795 2 * pcb->mss);*/ 00796 /* Set ssthresh to half of the minimum of the current cwnd and the advertised window */ 00797 if (pcb->cwnd > pcb->snd_wnd) 00798 pcb->ssthresh = pcb->snd_wnd / 2; 00799 else 00800 pcb->ssthresh = pcb->cwnd / 2; 00801 00802 /* The minimum value for ssthresh should be 2 MSS */ 00803 if (pcb->ssthresh < 2*pcb->mss) { 00804 LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: The minimum value for ssthresh %"U16_F" should be min 2 mss %"U16_F"...\n", pcb->ssthresh, 2*pcb->mss)); 00805 pcb->ssthresh = 2*pcb->mss; 00806 } 00807 00808 pcb->cwnd = pcb->ssthresh + 3 * pcb->mss; 00809 pcb->flags |= TF_INFR; 00810 } else { 00811 /* Inflate the congestion window, but not if it means that 00812 the value overflows. */ 00813 if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { 00814 pcb->cwnd += pcb->mss; 00815 } 00816 } 00817 } 00818 } else { 00819 LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupack averted %"U32_F" %"U32_F"\n", 00820 pcb->snd_wl1 + pcb->snd_wnd, right_wnd_edge)); 00821 } 00822 } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_max)){ 00823 /* We come here when the ACK acknowledges new data. */ 00824 00825 /* Reset the "IN Fast Retransmit" flag, since we are no longer 00826 in fast retransmit. Also reset the congestion window to the 00827 slow start threshold. */ 00828 if (pcb->flags & TF_INFR) { 00829 pcb->flags &= ~TF_INFR; 00830 pcb->cwnd = pcb->ssthresh; 00831 } 00832 00833 /* Reset the number of retransmissions. */ 00834 pcb->nrtx = 0; 00835 00836 /* Reset the retransmission time-out. */ 00837 pcb->rto = (pcb->sa >> 3) + pcb->sv; 00838 00839 /* Update the send buffer space. Diff between the two can never exceed 64K? */ 00840 pcb->acked = (u16_t)(ackno - pcb->lastack); 00841 00842 pcb->snd_buf += pcb->acked; 00843 00844 /* Reset the fast retransmit variables. */ 00845 pcb->dupacks = 0; 00846 pcb->lastack = ackno; 00847 00848 /* Update the congestion control variables (cwnd and 00849 ssthresh). */ 00850 if (pcb->state >= ESTABLISHED) { 00851 if (pcb->cwnd < pcb->ssthresh) { 00852 if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { 00853 pcb->cwnd += pcb->mss; 00854 } 00855 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"U16_F"\n", pcb->cwnd)); 00856 } else { 00857 u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd); 00858 if (new_cwnd > pcb->cwnd) { 00859 pcb->cwnd = new_cwnd; 00860 } 00861 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"U16_F"\n", pcb->cwnd)); 00862 } 00863 } 00864 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n", 00865 ackno, 00866 pcb->unacked != NULL? 00867 ntohl(pcb->unacked->tcphdr->seqno): 0, 00868 pcb->unacked != NULL? 00869 ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0)); 00870 00871 /* Remove segment from the unacknowledged list if the incoming 00872 ACK acknowlegdes them. */ 00873 while (pcb->unacked != NULL && 00874 TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) + 00875 TCP_TCPLEN(pcb->unacked), ackno)) { 00876 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unacked\n", 00877 ntohl(pcb->unacked->tcphdr->seqno), 00878 ntohl(pcb->unacked->tcphdr->seqno) + 00879 TCP_TCPLEN(pcb->unacked))); 00880 00881 next = pcb->unacked; 00882 pcb->unacked = pcb->unacked->next; 00883 00884 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen)); 00885 LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); 00886 pcb->snd_queuelen -= pbuf_clen(next->p); 00887 tcp_seg_free(next); 00888 00889 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unacked)\n", (u16_t)pcb->snd_queuelen)); 00890 if (pcb->snd_queuelen != 0) { 00891 LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL || 00892 pcb->unsent != NULL); 00893 } 00894 } 00895 00896 /* If there's nothing left to acknowledge, stop the retransmit 00897 timer, otherwise reset it to start again */ 00898 if(pcb->unacked == NULL) 00899 pcb->rtime = -1; 00900 else 00901 pcb->rtime = 0; 00902 00903 pcb->polltmr = 0; 00904 } else { 00905 /* Fix bug bug #21582: out of sequence ACK, didn't really ack anything */ 00906 pcb->acked = 0; 00907 } 00908 00909 /* We go through the ->unsent list to see if any of the segments 00910 on the list are acknowledged by the ACK. This may seem 00911 strange since an "unsent" segment shouldn't be acked. The 00912 rationale is that lwIP puts all outstanding segments on the 00913 ->unsent list after a retransmission, so these segments may 00914 in fact have been sent once. */ 00915 while (pcb->unsent != NULL && 00916 /*TCP_SEQ_LEQ(ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent), ackno) && 00917 TCP_SEQ_LEQ(ackno, pcb->snd_max)*/ 00918 TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent), pcb->snd_max) 00919 ) { 00920 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n", 00921 ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) + 00922 TCP_TCPLEN(pcb->unsent))); 00923 00924 next = pcb->unsent; 00925 pcb->unsent = pcb->unsent->next; 00926 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen)); 00927 LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); 00928 pcb->snd_queuelen -= pbuf_clen(next->p); 00929 tcp_seg_free(next); 00930 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unsent)\n", (u16_t)pcb->snd_queuelen)); 00931 if (pcb->snd_queuelen != 0) { 00932 LWIP_ASSERT("tcp_receive: valid queue length", 00933 pcb->unacked != NULL || pcb->unsent != NULL); 00934 } 00935 00936 if (pcb->unsent != NULL) { 00937 pcb->snd_nxt = htonl(pcb->unsent->tcphdr->seqno); 00938 } 00939 } 00940 /* End of ACK for new data processing. */ 00941 00942 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %"U32_F" rtseq %"U32_F" ackno %"U32_F"\n", 00943 pcb->rttest, pcb->rtseq, ackno)); 00944 00945 /* RTT estimation calculations. This is done by checking if the 00946 incoming segment acknowledges the segment we use to take a 00947 round-trip time measurement. */ 00948 if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) { 00949 /* diff between this shouldn't exceed 32K since this are tcp timer ticks 00950 and a round-trip shouldn't be that long... */ 00951 m = (s16_t)(tcp_ticks - pcb->rttest); 00952 00953 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %"U16_F" ticks (%"U16_F" msec).\n", 00954 m, m * TCP_SLOW_INTERVAL)); 00955 00956 /* This is taken directly from VJs original code in his paper */ 00957 m = m - (pcb->sa >> 3); 00958 pcb->sa += m; 00959 if (m < 0) { 00960 m = -m; 00961 } 00962 m = m - (pcb->sv >> 2); 00963 pcb->sv += m; 00964 pcb->rto = (pcb->sa >> 3) + pcb->sv; 00965 00966 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %"U16_F" (%"U16_F" milliseconds)\n", 00967 pcb->rto, pcb->rto * TCP_SLOW_INTERVAL)); 00968 00969 pcb->rttest = 0; 00970 } 00971 } 00972 00973 /* If the incoming segment contains data, we must process it 00974 further. */ 00975 if (tcplen > 0) { 00976 /* This code basically does three things: 00977 00978 +) If the incoming segment contains data that is the next 00979 in-sequence data, this data is passed to the application. This 00980 might involve trimming the first edge of the data. The rcv_nxt 00981 variable and the advertised window are adjusted. 00982 00983 +) If the incoming segment has data that is above the next 00984 sequence number expected (->rcv_nxt), the segment is placed on 00985 the ->ooseq queue. This is done by finding the appropriate 00986 place in the ->ooseq queue (which is ordered by sequence 00987 number) and trim the segment in both ends if needed. An 00988 immediate ACK is sent to indicate that we received an 00989 out-of-sequence segment. 00990 00991 +) Finally, we check if the first segment on the ->ooseq queue 00992 now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If 00993 rcv_nxt > ooseq->seqno, we must trim the first edge of the 00994 segment on ->ooseq before we adjust rcv_nxt. The data in the 00995 segments that are now on sequence are chained onto the 00996 incoming segment so that we only need to call the application 00997 once. 00998 */ 00999 01000 /* First, we check if we must trim the first edge. We have to do 01001 this if the sequence number of the incoming segment is less 01002 than rcv_nxt, and the sequence number plus the length of the 01003 segment is larger than rcv_nxt. */ 01004 /* if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){ 01005 if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/ 01006 if (TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno + 1, seqno + tcplen - 1)){ 01007 /* Trimming the first edge is done by pushing the payload 01008 pointer in the pbuf downwards. This is somewhat tricky since 01009 we do not want to discard the full contents of the pbuf up to 01010 the new starting point of the data since we have to keep the 01011 TCP header which is present in the first pbuf in the chain. 01012 01013 What is done is really quite a nasty hack: the first pbuf in 01014 the pbuf chain is pointed to by inseg.p. Since we need to be 01015 able to deallocate the whole pbuf, we cannot change this 01016 inseg.p pointer to point to any of the later pbufs in the 01017 chain. Instead, we point the ->payload pointer in the first 01018 pbuf to data in one of the later pbufs. We also set the 01019 inseg.data pointer to point to the right place. This way, the 01020 ->p pointer will still point to the first pbuf, but the 01021 ->p->payload pointer will point to data in another pbuf. 01022 01023 After we are done with adjusting the pbuf pointers we must 01024 adjust the ->data pointer in the seg and the segment 01025 length.*/ 01026 01027 off = pcb->rcv_nxt - seqno; 01028 p = inseg.p; 01029 LWIP_ASSERT("inseg.p != NULL", inseg.p); 01030 LWIP_ASSERT("insane offset!", (off < 0x7fff)); 01031 if (inseg.p->len < off) { 01032 LWIP_ASSERT("pbuf too short!", (((s32_t)inseg.p->tot_len) >= off)); 01033 new_tot_len = (u16_t)(inseg.p->tot_len - off); 01034 while (p->len < off) { 01035 off -= p->len; 01036 /* KJM following line changed (with addition of new_tot_len var) 01037 to fix bug #9076 01038 inseg.p->tot_len -= p->len; */ 01039 p->tot_len = new_tot_len; 01040 p->len = 0; 01041 p = p->next; 01042 } 01043 if(pbuf_header(p, (s16_t)-off)) { 01044 /* Do we need to cope with this failing? Assert for now */ 01045 LWIP_ASSERT("pbuf_header failed", 0); 01046 } 01047 } else { 01048 if(pbuf_header(inseg.p, (s16_t)-off)) { 01049 /* Do we need to cope with this failing? Assert for now */ 01050 LWIP_ASSERT("pbuf_header failed", 0); 01051 } 01052 } 01053 /* KJM following line changed to use p->payload rather than inseg->p->payload 01054 to fix bug #9076 */ 01055 inseg.dataptr = p->payload; 01056 inseg.len -= (u16_t)(pcb->rcv_nxt - seqno); 01057 inseg.tcphdr->seqno = seqno = pcb->rcv_nxt; 01058 } 01059 else { 01060 if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){ 01061 /* the whole segment is < rcv_nxt */ 01062 /* must be a duplicate of a packet that has already been correctly handled */ 01063 01064 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno)); 01065 tcp_ack_now(pcb); 01066 } 01067 } 01068 01069 /* The sequence number must be within the window (above rcv_nxt 01070 and below rcv_nxt + rcv_wnd) in order to be further 01071 processed. */ 01072 if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, 01073 pcb->rcv_nxt + pcb->rcv_wnd - 1)){ 01074 if (pcb->rcv_nxt == seqno) { 01075 accepted_inseq = 1; 01076 /* The incoming segment is the next in sequence. We check if 01077 we have to trim the end of the segment and update rcv_nxt 01078 and pass the data to the application. */ 01079 #if TCP_QUEUE_OOSEQ 01080 if (pcb->ooseq != NULL && 01081 TCP_SEQ_LEQ(pcb->ooseq->tcphdr->seqno, seqno + inseg.len)) { 01082 if (pcb->ooseq->len > 0) { 01083 /* We have to trim the second edge of the incoming 01084 segment. */ 01085 inseg.len = (u16_t)(pcb->ooseq->tcphdr->seqno - seqno); 01086 pbuf_realloc(inseg.p, inseg.len); 01087 } else { 01088 /* does the ooseq segment contain only flags that are in inseg also? */ 01089 if ((TCPH_FLAGS(inseg.tcphdr) & (TCP_FIN|TCP_SYN)) == 01090 (TCPH_FLAGS(pcb->ooseq->tcphdr) & (TCP_FIN|TCP_SYN))) { 01091 struct tcp_seg *old_ooseq = pcb->ooseq; 01092 pcb->ooseq = pcb->ooseq->next; 01093 memp_free(MEMP_TCP_SEG, old_ooseq); 01094 } 01095 } 01096 } 01097 #endif /* TCP_QUEUE_OOSEQ */ 01098 01099 tcplen = TCP_TCPLEN(&inseg); 01100 01101 /* First received FIN will be ACKed +1, on any successive (duplicate) 01102 * FINs we are already in CLOSE_WAIT and have already done +1. 01103 */ 01104 if (pcb->state != CLOSE_WAIT) { 01105 pcb->rcv_nxt += tcplen; 01106 } 01107 01108 /* Update the receiver's (our) window. */ 01109 if (pcb->rcv_wnd < tcplen) { 01110 pcb->rcv_wnd = 0; 01111 } else { 01112 pcb->rcv_wnd -= tcplen; 01113 } 01114 01115 tcp_update_rcv_ann_wnd(pcb); 01116 01117 /* If there is data in the segment, we make preparations to 01118 pass this up to the application. The ->recv_data variable 01119 is used for holding the pbuf that goes to the 01120 application. The code for reassembling out-of-sequence data 01121 chains its data on this pbuf as well. 01122 01123 If the segment was a FIN, we set the TF_GOT_FIN flag that will 01124 be used to indicate to the application that the remote side has 01125 closed its end of the connection. */ 01126 if (inseg.p->tot_len > 0) { 01127 recv_data = inseg.p; 01128 /* Since this pbuf now is the responsibility of the 01129 application, we delete our reference to it so that we won't 01130 (mistakingly) deallocate it. */ 01131 inseg.p = NULL; 01132 } 01133 if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { 01134 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n")); 01135 recv_flags = TF_GOT_FIN; 01136 } 01137 01138 #if TCP_QUEUE_OOSEQ 01139 /* We now check if we have segments on the ->ooseq queue that 01140 is now in sequence. */ 01141 while (pcb->ooseq != NULL && 01142 pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) { 01143 01144 cseg = pcb->ooseq; 01145 seqno = pcb->ooseq->tcphdr->seqno; 01146 01147 pcb->rcv_nxt += TCP_TCPLEN(cseg); 01148 if (pcb->rcv_wnd < TCP_TCPLEN(cseg)) { 01149 pcb->rcv_wnd = 0; 01150 } else { 01151 pcb->rcv_wnd -= TCP_TCPLEN(cseg); 01152 } 01153 01154 tcp_update_rcv_ann_wnd(pcb); 01155 01156 if (cseg->p->tot_len > 0) { 01157 /* Chain this pbuf onto the pbuf that we will pass to 01158 the application. */ 01159 if (recv_data) { 01160 pbuf_cat(recv_data, cseg->p); 01161 } else { 01162 recv_data = cseg->p; 01163 } 01164 cseg->p = NULL; 01165 } 01166 if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) { 01167 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n")); 01168 recv_flags = TF_GOT_FIN; 01169 if (pcb->state == ESTABLISHED) { /* force passive close or we can move to active close */ 01170 pcb->state = CLOSE_WAIT; 01171 } 01172 } 01173 01174 01175 pcb->ooseq = cseg->next; 01176 tcp_seg_free(cseg); 01177 } 01178 #endif /* TCP_QUEUE_OOSEQ */ 01179 01180 01181 /* Acknowledge the segment(s). */ 01182 tcp_ack(pcb); 01183 01184 } else { 01185 /* We get here if the incoming segment is out-of-sequence. */ 01186 tcp_ack_now(pcb); 01187 #if TCP_QUEUE_OOSEQ 01188 /* We queue the segment on the ->ooseq queue. */ 01189 if (pcb->ooseq == NULL) { 01190 pcb->ooseq = tcp_seg_copy(&inseg); 01191 } else { 01192 /* If the queue is not empty, we walk through the queue and 01193 try to find a place where the sequence number of the 01194 incoming segment is between the sequence numbers of the 01195 previous and the next segment on the ->ooseq queue. That is 01196 the place where we put the incoming segment. If needed, we 01197 trim the second edges of the previous and the incoming 01198 segment so that it will fit into the sequence. 01199 01200 If the incoming segment has the same sequence number as a 01201 segment on the ->ooseq queue, we discard the segment that 01202 contains less data. */ 01203 01204 prev = NULL; 01205 for(next = pcb->ooseq; next != NULL; next = next->next) { 01206 if (seqno == next->tcphdr->seqno) { 01207 /* The sequence number of the incoming segment is the 01208 same as the sequence number of the segment on 01209 ->ooseq. We check the lengths to see which one to 01210 discard. */ 01211 if (inseg.len > next->len) { 01212 /* The incoming segment is larger than the old 01213 segment. We replace the old segment with the new 01214 one. */ 01215 cseg = tcp_seg_copy(&inseg); 01216 if (cseg != NULL) { 01217 cseg->next = next->next; 01218 if (prev != NULL) { 01219 prev->next = cseg; 01220 } else { 01221 pcb->ooseq = cseg; 01222 } 01223 tcp_seg_free(next); 01224 if (cseg->next != NULL) { 01225 next = cseg->next; 01226 if (TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) { 01227 /* We need to trim the incoming segment. */ 01228 cseg->len = (u16_t)(next->tcphdr->seqno - seqno); 01229 pbuf_realloc(cseg->p, cseg->len); 01230 } 01231 } 01232 } 01233 break; 01234 } else { 01235 /* Either the lenghts are the same or the incoming 01236 segment was smaller than the old one; in either 01237 case, we ditch the incoming segment. */ 01238 break; 01239 } 01240 } else { 01241 if (prev == NULL) { 01242 if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) { 01243 /* The sequence number of the incoming segment is lower 01244 than the sequence number of the first segment on the 01245 queue. We put the incoming segment first on the 01246 queue. */ 01247 01248 if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) { 01249 /* We need to trim the incoming segment. */ 01250 inseg.len = (u16_t)(next->tcphdr->seqno - seqno); 01251 pbuf_realloc(inseg.p, inseg.len); 01252 } 01253 cseg = tcp_seg_copy(&inseg); 01254 if (cseg != NULL) { 01255 cseg->next = next; 01256 pcb->ooseq = cseg; 01257 } 01258 break; 01259 } 01260 } else 01261 /*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) && 01262 TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/ 01263 if(TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)){ 01264 /* The sequence number of the incoming segment is in 01265 between the sequence numbers of the previous and 01266 the next segment on ->ooseq. We trim and insert the 01267 incoming segment and trim the previous segment, if 01268 needed. */ 01269 if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) { 01270 /* We need to trim the incoming segment. */ 01271 inseg.len = (u16_t)(next->tcphdr->seqno - seqno); 01272 pbuf_realloc(inseg.p, inseg.len); 01273 } 01274 01275 cseg = tcp_seg_copy(&inseg); 01276 if (cseg != NULL) { 01277 cseg->next = next; 01278 prev->next = cseg; 01279 if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) { 01280 /* We need to trim the prev segment. */ 01281 prev->len = (u16_t)(seqno - prev->tcphdr->seqno); 01282 pbuf_realloc(prev->p, prev->len); 01283 } 01284 } 01285 break; 01286 } 01287 /* If the "next" segment is the last segment on the 01288 ooseq queue, we add the incoming segment to the end 01289 of the list. */ 01290 if (next->next == NULL && 01291 TCP_SEQ_GT(seqno, next->tcphdr->seqno)) { 01292 next->next = tcp_seg_copy(&inseg); 01293 if (next->next != NULL) { 01294 if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) { 01295 /* We need to trim the last segment. */ 01296 next->len = (u16_t)(seqno - next->tcphdr->seqno); 01297 pbuf_realloc(next->p, next->len); 01298 } 01299 } 01300 break; 01301 } 01302 } 01303 prev = next; 01304 } 01305 } 01306 #endif /* TCP_QUEUE_OOSEQ */ 01307 01308 } 01309 } else { 01310 tcp_ack_now(pcb); 01311 } 01312 } else { 01313 /* Segments with length 0 is taken care of here. Segments that 01314 fall out of the window are ACKed. */ 01315 /*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) || 01316 TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/ 01317 if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){ 01318 tcp_ack_now(pcb); 01319 } 01320 } 01321 return accepted_inseq; 01322 } 01323 01324 /** 01325 * Parses the options contained in the incoming segment. 01326 * 01327 * Called from tcp_listen_input() and tcp_process(). 01328 * Currently, only the MSS option is supported! 01329 * 01330 * @param pcb the tcp_pcb for which a segment arrived 01331 */ 01332 static void 01333 tcp_parseopt(struct tcp_pcb *pcb) 01334 { 01335 u16_t c, max_c; 01336 u16_t mss; 01337 u8_t *opts, opt; 01338 #if LWIP_TCP_TIMESTAMPS 01339 u32_t tsval; 01340 #endif 01341 01342 opts = (u8_t *)tcphdr + TCP_HLEN; 01343 01344 /* Parse the TCP MSS option, if present. */ 01345 if(TCPH_HDRLEN(tcphdr) > 0x5) { 01346 max_c = (TCPH_HDRLEN(tcphdr) - 5) << 2; 01347 for (c = 0; c < max_c; ) { 01348 opt = opts[c]; 01349 switch (opt) { 01350 case 0x00: 01351 /* End of options. */ 01352 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: EOL\n")); 01353 return; 01354 case 0x01: 01355 /* NOP option. */ 01356 ++c; 01357 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: NOP\n")); 01358 break; 01359 case 0x02: 01360 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: MSS\n")); 01361 if (opts[c + 1] != 0x04 || c + 0x04 > max_c) { 01362 /* Bad length */ 01363 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); 01364 return; 01365 } 01366 /* An MSS option with the right option length. */ 01367 mss = (opts[c + 2] << 8) | opts[c + 3]; 01368 /* Limit the mss to the configured TCP_MSS and prevent division by zero */ 01369 pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss; 01370 /* Advance to next option */ 01371 c += 0x04; 01372 break; 01373 #if LWIP_TCP_TIMESTAMPS 01374 case 0x08: 01375 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: TS\n")); 01376 if (opts[c + 1] != 0x0A || c + 0x0A > max_c) { 01377 /* Bad length */ 01378 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); 01379 return; 01380 } 01381 /* TCP timestamp option with valid length */ 01382 tsval = (opts[c+2]) | (opts[c+3] << 8) | 01383 (opts[c+4] << 16) | (opts[c+5] << 24); 01384 if (flags & TCP_SYN) { 01385 pcb->ts_recent = ntohl(tsval); 01386 pcb->flags |= TF_TIMESTAMP; 01387 } else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno+tcplen)) { 01388 pcb->ts_recent = ntohl(tsval); 01389 } 01390 /* Advance to next option */ 01391 c += 0x0A; 01392 break; 01393 #endif 01394 default: 01395 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: other\n")); 01396 if (opts[c + 1] == 0) { 01397 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); 01398 /* If the length field is zero, the options are malformed 01399 and we don't process them further. */ 01400 return; 01401 } 01402 /* All other options have a length field, so that we easily 01403 can skip past them. */ 01404 c += opts[c + 1]; 01405 } 01406 } 01407 } 01408 } 01409 01410 #endif /* LWIP_TCP */
Generated on Tue Jul 12 2022 19:24:06 by
![doxygen](doxygen.png)