A version of LWIP, provided for backwards compatibility.
Dependents: AA_DemoBoard DemoBoard HelloServerDemo DemoBoard_RangeIndicator ... more
tcp_in.c
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 = static_cast<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 = static_cast<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 = static_cast<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 = static_cast<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 = static_cast<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 = static_cast<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 = static_cast<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 = static_cast<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 u32_t optdata; 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->snd_wnd = tcphdr->wnd; 00442 npcb->ssthresh = npcb->snd_wnd; 00443 npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */ 00444 npcb->callback_arg = pcb->callback_arg; 00445 #if LWIP_CALLBACK_API 00446 npcb->accept = pcb->accept; 00447 #endif /* LWIP_CALLBACK_API */ 00448 /* inherit socket options */ 00449 npcb->so_options = pcb->so_options & (SOF_DEBUG|SOF_DONTROUTE|SOF_KEEPALIVE|SOF_OOBINLINE|SOF_LINGER); 00450 /* Register the new PCB so that we can begin receiving segments 00451 for it. */ 00452 TCP_REG(&tcp_active_pcbs, npcb); 00453 00454 /* Parse any options in the SYN. */ 00455 tcp_parseopt(npcb); 00456 #if TCP_CALCULATE_EFF_SEND_MSS 00457 npcb->mss = tcp_eff_send_mss(npcb->mss, &(npcb->remote_ip)); 00458 #endif /* TCP_CALCULATE_EFF_SEND_MSS */ 00459 00460 snmp_inc_tcppassiveopens(); 00461 00462 /* Build an MSS option. */ 00463 optdata = TCP_BUILD_MSS_OPTION(); 00464 /* Send a SYN|ACK together with the MSS option. */ 00465 tcp_enqueue(npcb, NULL, 0, TCP_SYN | TCP_ACK, 0, (u8_t *)&optdata, 4); 00466 return tcp_output(npcb); 00467 } 00468 return ERR_OK; 00469 } 00470 00471 /** 00472 * Called by tcp_input() when a segment arrives for a connection in 00473 * TIME_WAIT. 00474 * 00475 * @param pcb the tcp_pcb for which a segment arrived 00476 * 00477 * @note the segment which arrived is saved in global variables, therefore only the pcb 00478 * involved is passed as a parameter to this function 00479 */ 00480 static err_t 00481 tcp_timewait_input(struct tcp_pcb *pcb) 00482 { 00483 if (TCP_SEQ_GT(seqno + tcplen, pcb->rcv_nxt)) { 00484 pcb->rcv_nxt = seqno + tcplen; 00485 } 00486 if (tcplen > 0) { 00487 tcp_ack_now(pcb); 00488 } 00489 return tcp_output(pcb); 00490 } 00491 00492 /** 00493 * Implements the TCP state machine. Called by tcp_input. In some 00494 * states tcp_receive() is called to receive data. The tcp_seg 00495 * argument will be freed by the caller (tcp_input()) unless the 00496 * recv_data pointer in the pcb is set. 00497 * 00498 * @param pcb the tcp_pcb for which a segment arrived 00499 * 00500 * @note the segment which arrived is saved in global variables, therefore only the pcb 00501 * involved is passed as a parameter to this function 00502 */ 00503 static err_t 00504 tcp_process(struct tcp_pcb *pcb) 00505 { 00506 struct tcp_seg *rseg; 00507 u8_t acceptable = 0; 00508 err_t err; 00509 u8_t accepted_inseq; 00510 00511 err = ERR_OK; 00512 00513 /* Process incoming RST segments. */ 00514 if (flags & TCP_RST) { 00515 /* First, determine if the reset is acceptable. */ 00516 if (pcb->state == SYN_SENT) { 00517 if (ackno == pcb->snd_nxt) { 00518 acceptable = 1; 00519 } 00520 } else { 00521 if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, 00522 pcb->rcv_nxt+pcb->rcv_ann_wnd)) { 00523 acceptable = 1; 00524 } 00525 } 00526 00527 if (acceptable) { 00528 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n")); 00529 LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED); 00530 recv_flags = TF_RESET; 00531 pcb->flags &= ~TF_ACK_DELAY; 00532 return ERR_RST; 00533 } else { 00534 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", 00535 seqno, pcb->rcv_nxt)); 00536 LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", 00537 seqno, pcb->rcv_nxt)); 00538 return ERR_OK; 00539 } 00540 } 00541 00542 /* Update the PCB (in)activity timer. */ 00543 pcb->tmr = tcp_ticks; 00544 pcb->keep_cnt_sent = 0; 00545 00546 /* Do different things depending on the TCP state. */ 00547 switch (pcb->state) { 00548 case SYN_SENT: 00549 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno, 00550 pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno))); 00551 /* received SYN ACK with expected sequence number? */ 00552 if ((flags & TCP_ACK) && (flags & TCP_SYN) 00553 && ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) { 00554 pcb->snd_buf++; 00555 pcb->rcv_nxt = seqno + 1; 00556 pcb->lastack = ackno; 00557 pcb->snd_wnd = tcphdr->wnd; 00558 pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */ 00559 pcb->state = ESTABLISHED; 00560 00561 /* Parse any options in the SYNACK before using pcb->mss since that 00562 * can be changed by the received options! */ 00563 tcp_parseopt(pcb); 00564 #if TCP_CALCULATE_EFF_SEND_MSS 00565 pcb->mss = tcp_eff_send_mss(pcb->mss, &(pcb->remote_ip)); 00566 #endif /* TCP_CALCULATE_EFF_SEND_MSS */ 00567 00568 /* Set ssthresh again after changing pcb->mss (already set in tcp_connect 00569 * but for the default value of pcb->mss) */ 00570 pcb->ssthresh = pcb->mss * 10; 00571 00572 pcb->cwnd = ((pcb->cwnd == 1) ? (pcb->mss * 2) : pcb->mss); 00573 LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0)); 00574 --pcb->snd_queuelen; 00575 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"U16_F"\n", (u16_t)pcb->snd_queuelen)); 00576 rseg = pcb->unacked; 00577 pcb->unacked = rseg->next; 00578 00579 /* If there's nothing left to acknowledge, stop the retransmit 00580 timer, otherwise reset it to start again */ 00581 if(pcb->unacked == NULL) 00582 pcb->rtime = -1; 00583 else { 00584 pcb->rtime = 0; 00585 pcb->nrtx = 0; 00586 } 00587 00588 tcp_seg_free(rseg); 00589 00590 /* Call the user specified function to call when sucessfully 00591 * connected. */ 00592 TCP_EVENT_CONNECTED(pcb, ERR_OK, err); 00593 tcp_ack_now(pcb); 00594 } 00595 /* received ACK? possibly a half-open connection */ 00596 else if (flags & TCP_ACK) { 00597 /* send a RST to bring the other side in a non-synchronized state. */ 00598 struct ip_addr iphdrdest; 00599 iphdrdest.addr = iphdr->dest.addr; 00600 struct ip_addr iphdrsrc; 00601 iphdrsrc.addr = iphdr->src.addr; 00602 tcp_rst(ackno, seqno + tcplen, &(iphdrdest), &(iphdrsrc), 00603 tcphdr->dest, tcphdr->src); 00604 } 00605 break; 00606 case SYN_RCVD: 00607 if (flags & TCP_ACK && 00608 !(flags & TCP_RST)) { 00609 /* expected ACK number? */ 00610 if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) { 00611 u16_t old_cwnd; 00612 pcb->state = ESTABLISHED; 00613 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); 00614 #if LWIP_CALLBACK_API 00615 LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL); 00616 #endif 00617 /* Call the accept function. */ 00618 TCP_EVENT_ACCEPT(pcb, ERR_OK, err); 00619 if (err != ERR_OK) { 00620 /* If the accept function returns with an error, we abort 00621 * the connection. */ 00622 tcp_abort(pcb); 00623 return ERR_ABRT; 00624 } 00625 old_cwnd = pcb->cwnd; 00626 /* If there was any data contained within this ACK, 00627 * we'd better pass it on to the application as well. */ 00628 accepted_inseq = tcp_receive(pcb); 00629 00630 pcb->cwnd = ((old_cwnd == 1) ? (pcb->mss * 2) : pcb->mss); 00631 00632 if ((flags & TCP_FIN) && accepted_inseq) { 00633 tcp_ack_now(pcb); 00634 pcb->state = CLOSE_WAIT; 00635 } 00636 } 00637 /* incorrect ACK number */ 00638 else { 00639 /* send RST */ 00640 struct ip_addr iphdrdest; 00641 iphdrdest.addr = iphdr->dest.addr; 00642 struct ip_addr iphdrsrc; 00643 iphdrsrc.addr = iphdr->src.addr; 00644 tcp_rst(ackno, seqno + tcplen, &(iphdrdest), &(iphdrsrc), 00645 tcphdr->dest, tcphdr->src); 00646 } 00647 } 00648 break; 00649 case CLOSE_WAIT: 00650 /* FALLTHROUGH */ 00651 case ESTABLISHED: 00652 accepted_inseq = tcp_receive(pcb); 00653 if ((flags & TCP_FIN) && accepted_inseq) { /* passive close */ 00654 tcp_ack_now(pcb); 00655 pcb->state = CLOSE_WAIT; 00656 } 00657 break; 00658 case FIN_WAIT_1: 00659 tcp_receive(pcb); 00660 if (flags & TCP_FIN) { 00661 if (flags & TCP_ACK && ackno == pcb->snd_nxt) { 00662 LWIP_DEBUGF(TCP_DEBUG, 00663 ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); 00664 tcp_ack_now(pcb); 00665 tcp_pcb_purge(pcb); 00666 TCP_RMV(&tcp_active_pcbs, pcb); 00667 pcb->state = TIME_WAIT; 00668 TCP_REG(&tcp_tw_pcbs, pcb); 00669 } else { 00670 tcp_ack_now(pcb); 00671 pcb->state = CLOSING; 00672 } 00673 } else if (flags & TCP_ACK && ackno == pcb->snd_nxt) { 00674 pcb->state = FIN_WAIT_2; 00675 } 00676 break; 00677 case FIN_WAIT_2: 00678 tcp_receive(pcb); 00679 if (flags & TCP_FIN) { 00680 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); 00681 tcp_ack_now(pcb); 00682 tcp_pcb_purge(pcb); 00683 TCP_RMV(&tcp_active_pcbs, pcb); 00684 pcb->state = TIME_WAIT; 00685 TCP_REG(&tcp_tw_pcbs, pcb); 00686 } 00687 break; 00688 case CLOSING: 00689 tcp_receive(pcb); 00690 if (flags & TCP_ACK && ackno == pcb->snd_nxt) { 00691 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); 00692 tcp_ack_now(pcb); 00693 tcp_pcb_purge(pcb); 00694 TCP_RMV(&tcp_active_pcbs, pcb); 00695 pcb->state = TIME_WAIT; 00696 TCP_REG(&tcp_tw_pcbs, pcb); 00697 } 00698 break; 00699 case LAST_ACK: 00700 tcp_receive(pcb); 00701 if (flags & TCP_ACK && ackno == pcb->snd_nxt) { 00702 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); 00703 /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */ 00704 recv_flags = TF_CLOSED; 00705 } 00706 break; 00707 default: 00708 break; 00709 } 00710 return ERR_OK; 00711 } 00712 00713 /** 00714 * Called by tcp_process. Checks if the given segment is an ACK for outstanding 00715 * data, and if so frees the memory of the buffered data. Next, is places the 00716 * segment on any of the receive queues (pcb->recved or pcb->ooseq). If the segment 00717 * is buffered, the pbuf is referenced by pbuf_ref so that it will not be freed until 00718 * i it has been removed from the buffer. 00719 * 00720 * If the incoming segment constitutes an ACK for a segment that was used for RTT 00721 * estimation, the RTT is estimated here as well. 00722 * 00723 * Called from tcp_process(). 00724 * 00725 * @return 1 if the incoming segment is the next in sequence, 0 if not 00726 */ 00727 static u8_t 00728 tcp_receive(struct tcp_pcb *pcb) 00729 { 00730 struct tcp_seg *next; 00731 #if TCP_QUEUE_OOSEQ 00732 struct tcp_seg *prev, *cseg; 00733 #endif 00734 struct pbuf *p; 00735 s32_t off; 00736 s16_t m; 00737 u32_t right_wnd_edge; 00738 u16_t new_tot_len; 00739 u8_t accepted_inseq = 0; 00740 00741 if (flags & TCP_ACK) { 00742 right_wnd_edge = pcb->snd_wnd + pcb->snd_wl1; 00743 00744 /* Update window. */ 00745 if (TCP_SEQ_LT(pcb->snd_wl1, seqno) || 00746 (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) || 00747 (pcb->snd_wl2 == ackno && tcphdr->wnd > pcb->snd_wnd)) { 00748 pcb->snd_wnd = tcphdr->wnd; 00749 pcb->snd_wl1 = seqno; 00750 pcb->snd_wl2 = ackno; 00751 if (pcb->snd_wnd > 0 && pcb->persist_backoff > 0) { 00752 pcb->persist_backoff = 0; 00753 } 00754 LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"U16_F"\n", pcb->snd_wnd)); 00755 #if TCP_WND_DEBUG 00756 } else { 00757 if (pcb->snd_wnd != tcphdr->wnd) { 00758 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", 00759 pcb->lastack, pcb->snd_max, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2)); 00760 } 00761 #endif /* TCP_WND_DEBUG */ 00762 } 00763 00764 if (pcb->lastack == ackno) { 00765 pcb->acked = 0; 00766 00767 if (pcb->snd_wl1 + pcb->snd_wnd == right_wnd_edge){ 00768 ++pcb->dupacks; 00769 if (pcb->dupacks >= 3 && pcb->unacked != NULL) { 00770 if (!(pcb->flags & TF_INFR)) { 00771 /* This is fast retransmit. Retransmit the first unacked segment. */ 00772 LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupacks %"U16_F" (%"U32_F"), fast retransmit %"U32_F"\n", 00773 (u16_t)pcb->dupacks, pcb->lastack, 00774 ntohl(pcb->unacked->tcphdr->seqno))); 00775 tcp_rexmit(pcb); 00776 /* Set ssthresh to max (FlightSize / 2, 2*SMSS) */ 00777 /*pcb->ssthresh = LWIP_MAX((pcb->snd_max - 00778 pcb->lastack) / 2, 00779 2 * pcb->mss);*/ 00780 /* Set ssthresh to half of the minimum of the current cwnd and the advertised window */ 00781 if (pcb->cwnd > pcb->snd_wnd) 00782 pcb->ssthresh = pcb->snd_wnd / 2; 00783 else 00784 pcb->ssthresh = pcb->cwnd / 2; 00785 00786 /* The minimum value for ssthresh should be 2 MSS */ 00787 if (pcb->ssthresh < 2*pcb->mss) { 00788 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)); 00789 pcb->ssthresh = 2*pcb->mss; 00790 } 00791 00792 pcb->cwnd = pcb->ssthresh + 3 * pcb->mss; 00793 pcb->flags |= TF_INFR; 00794 } else { 00795 /* Inflate the congestion window, but not if it means that 00796 the value overflows. */ 00797 if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { 00798 pcb->cwnd += pcb->mss; 00799 } 00800 } 00801 } 00802 } else { 00803 LWIP_DEBUGF(TCP_FR_DEBUG, ("tcp_receive: dupack averted %"U32_F" %"U32_F"\n", 00804 pcb->snd_wl1 + pcb->snd_wnd, right_wnd_edge)); 00805 } 00806 } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_max)){ 00807 /* We come here when the ACK acknowledges new data. */ 00808 00809 /* Reset the "IN Fast Retransmit" flag, since we are no longer 00810 in fast retransmit. Also reset the congestion window to the 00811 slow start threshold. */ 00812 if (pcb->flags & TF_INFR) { 00813 pcb->flags &= ~TF_INFR; 00814 pcb->cwnd = pcb->ssthresh; 00815 } 00816 00817 /* Reset the number of retransmissions. */ 00818 pcb->nrtx = 0; 00819 00820 /* Reset the retransmission time-out. */ 00821 pcb->rto = (pcb->sa >> 3) + pcb->sv; 00822 00823 /* Update the send buffer space. Diff between the two can never exceed 64K? */ 00824 pcb->acked = (u16_t)(ackno - pcb->lastack); 00825 00826 pcb->snd_buf += pcb->acked; 00827 00828 /* Reset the fast retransmit variables. */ 00829 pcb->dupacks = 0; 00830 pcb->lastack = ackno; 00831 00832 /* Update the congestion control variables (cwnd and 00833 ssthresh). */ 00834 if (pcb->state >= ESTABLISHED) { 00835 if (pcb->cwnd < pcb->ssthresh) { 00836 if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { 00837 pcb->cwnd += pcb->mss; 00838 } 00839 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"U16_F"\n", pcb->cwnd)); 00840 } else { 00841 u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd); 00842 if (new_cwnd > pcb->cwnd) { 00843 pcb->cwnd = new_cwnd; 00844 } 00845 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"U16_F"\n", pcb->cwnd)); 00846 } 00847 } 00848 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n", 00849 ackno, 00850 pcb->unacked != NULL? 00851 ntohl(pcb->unacked->tcphdr->seqno): 0, 00852 pcb->unacked != NULL? 00853 ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0)); 00854 00855 /* Remove segment from the unacknowledged list if the incoming 00856 ACK acknowlegdes them. */ 00857 while (pcb->unacked != NULL && 00858 TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) + 00859 TCP_TCPLEN(pcb->unacked), ackno)) { 00860 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unacked\n", 00861 ntohl(pcb->unacked->tcphdr->seqno), 00862 ntohl(pcb->unacked->tcphdr->seqno) + 00863 TCP_TCPLEN(pcb->unacked))); 00864 00865 next = pcb->unacked; 00866 pcb->unacked = pcb->unacked->next; 00867 00868 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen)); 00869 LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); 00870 pcb->snd_queuelen -= pbuf_clen(next->p); 00871 tcp_seg_free(next); 00872 00873 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unacked)\n", (u16_t)pcb->snd_queuelen)); 00874 if (pcb->snd_queuelen != 0) { 00875 LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL || 00876 pcb->unsent != NULL); 00877 } 00878 } 00879 00880 /* If there's nothing left to acknowledge, stop the retransmit 00881 timer, otherwise reset it to start again */ 00882 if(pcb->unacked == NULL) 00883 pcb->rtime = -1; 00884 else 00885 pcb->rtime = 0; 00886 00887 pcb->polltmr = 0; 00888 } else { 00889 /* Fix bug bug #21582: out of sequence ACK, didn't really ack anything */ 00890 pcb->acked = 0; 00891 } 00892 00893 /* We go through the ->unsent list to see if any of the segments 00894 on the list are acknowledged by the ACK. This may seem 00895 strange since an "unsent" segment shouldn't be acked. The 00896 rationale is that lwIP puts all outstanding segments on the 00897 ->unsent list after a retransmission, so these segments may 00898 in fact have been sent once. */ 00899 while (pcb->unsent != NULL && 00900 /*TCP_SEQ_LEQ(ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent), ackno) && 00901 TCP_SEQ_LEQ(ackno, pcb->snd_max)*/ 00902 TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent), pcb->snd_max) 00903 ) { 00904 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n", 00905 ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) + 00906 TCP_TCPLEN(pcb->unsent))); 00907 00908 next = pcb->unsent; 00909 pcb->unsent = pcb->unsent->next; 00910 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen)); 00911 LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); 00912 pcb->snd_queuelen -= pbuf_clen(next->p); 00913 tcp_seg_free(next); 00914 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unsent)\n", (u16_t)pcb->snd_queuelen)); 00915 if (pcb->snd_queuelen != 0) { 00916 LWIP_ASSERT("tcp_receive: valid queue length", 00917 pcb->unacked != NULL || pcb->unsent != NULL); 00918 } 00919 00920 if (pcb->unsent != NULL) { 00921 pcb->snd_nxt = htonl(pcb->unsent->tcphdr->seqno); 00922 } 00923 } 00924 /* End of ACK for new data processing. */ 00925 00926 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %"U32_F" rtseq %"U32_F" ackno %"U32_F"\n", 00927 pcb->rttest, pcb->rtseq, ackno)); 00928 00929 /* RTT estimation calculations. This is done by checking if the 00930 incoming segment acknowledges the segment we use to take a 00931 round-trip time measurement. */ 00932 if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) { 00933 /* diff between this shouldn't exceed 32K since this are tcp timer ticks 00934 and a round-trip shouldn't be that long... */ 00935 m = (s16_t)(tcp_ticks - pcb->rttest); 00936 00937 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %"U16_F" ticks (%"U16_F" msec).\n", 00938 m, m * TCP_SLOW_INTERVAL)); 00939 00940 /* This is taken directly from VJs original code in his paper */ 00941 m = m - (pcb->sa >> 3); 00942 pcb->sa += m; 00943 if (m < 0) { 00944 m = -m; 00945 } 00946 m = m - (pcb->sv >> 2); 00947 pcb->sv += m; 00948 pcb->rto = (pcb->sa >> 3) + pcb->sv; 00949 00950 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %"U16_F" (%"U16_F" milliseconds)\n", 00951 pcb->rto, pcb->rto * TCP_SLOW_INTERVAL)); 00952 00953 pcb->rttest = 0; 00954 } 00955 } 00956 00957 /* If the incoming segment contains data, we must process it 00958 further. */ 00959 if (tcplen > 0) { 00960 /* This code basically does three things: 00961 00962 +) If the incoming segment contains data that is the next 00963 in-sequence data, this data is passed to the application. This 00964 might involve trimming the first edge of the data. The rcv_nxt 00965 variable and the advertised window are adjusted. 00966 00967 +) If the incoming segment has data that is above the next 00968 sequence number expected (->rcv_nxt), the segment is placed on 00969 the ->ooseq queue. This is done by finding the appropriate 00970 place in the ->ooseq queue (which is ordered by sequence 00971 number) and trim the segment in both ends if needed. An 00972 immediate ACK is sent to indicate that we received an 00973 out-of-sequence segment. 00974 00975 +) Finally, we check if the first segment on the ->ooseq queue 00976 now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If 00977 rcv_nxt > ooseq->seqno, we must trim the first edge of the 00978 segment on ->ooseq before we adjust rcv_nxt. The data in the 00979 segments that are now on sequence are chained onto the 00980 incoming segment so that we only need to call the application 00981 once. 00982 */ 00983 00984 /* First, we check if we must trim the first edge. We have to do 00985 this if the sequence number of the incoming segment is less 00986 than rcv_nxt, and the sequence number plus the length of the 00987 segment is larger than rcv_nxt. */ 00988 /* if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){ 00989 if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/ 00990 if (TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno + 1, seqno + tcplen - 1)){ 00991 /* Trimming the first edge is done by pushing the payload 00992 pointer in the pbuf downwards. This is somewhat tricky since 00993 we do not want to discard the full contents of the pbuf up to 00994 the new starting point of the data since we have to keep the 00995 TCP header which is present in the first pbuf in the chain. 00996 00997 What is done is really quite a nasty hack: the first pbuf in 00998 the pbuf chain is pointed to by inseg.p. Since we need to be 00999 able to deallocate the whole pbuf, we cannot change this 01000 inseg.p pointer to point to any of the later pbufs in the 01001 chain. Instead, we point the ->payload pointer in the first 01002 pbuf to data in one of the later pbufs. We also set the 01003 inseg.data pointer to point to the right place. This way, the 01004 ->p pointer will still point to the first pbuf, but the 01005 ->p->payload pointer will point to data in another pbuf. 01006 01007 After we are done with adjusting the pbuf pointers we must 01008 adjust the ->data pointer in the seg and the segment 01009 length.*/ 01010 01011 off = pcb->rcv_nxt - seqno; 01012 p = inseg.p; 01013 LWIP_ASSERT("inseg.p != NULL", inseg.p); 01014 LWIP_ASSERT("insane offset!", (off < 0x7fff)); 01015 if (inseg.p->len < off) { 01016 LWIP_ASSERT("pbuf too short!", (((s32_t)inseg.p->tot_len) >= off)); 01017 new_tot_len = (u16_t)(inseg.p->tot_len - off); 01018 while (p->len < off) { 01019 off -= p->len; 01020 /* KJM following line changed (with addition of new_tot_len var) 01021 to fix bug #9076 01022 inseg.p->tot_len -= p->len; */ 01023 p->tot_len = new_tot_len; 01024 p->len = 0; 01025 p = p->next; 01026 } 01027 if(pbuf_header(p, (s16_t)-off)) { 01028 /* Do we need to cope with this failing? Assert for now */ 01029 LWIP_ASSERT("pbuf_header failed", 0); 01030 } 01031 } else { 01032 if(pbuf_header(inseg.p, (s16_t)-off)) { 01033 /* Do we need to cope with this failing? Assert for now */ 01034 LWIP_ASSERT("pbuf_header failed", 0); 01035 } 01036 } 01037 /* KJM following line changed to use p->payload rather than inseg->p->payload 01038 to fix bug #9076 */ 01039 inseg.dataptr = p->payload; 01040 inseg.len -= (u16_t)(pcb->rcv_nxt - seqno); 01041 inseg.tcphdr->seqno = seqno = pcb->rcv_nxt; 01042 } 01043 else { 01044 if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){ 01045 /* the whole segment is < rcv_nxt */ 01046 /* must be a duplicate of a packet that has already been correctly handled */ 01047 01048 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno)); 01049 tcp_ack_now(pcb); 01050 } 01051 } 01052 01053 /* The sequence number must be within the window (above rcv_nxt 01054 and below rcv_nxt + rcv_wnd) in order to be further 01055 processed. */ 01056 if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, 01057 pcb->rcv_nxt + pcb->rcv_ann_wnd - 1)){ 01058 if (pcb->rcv_nxt == seqno) { 01059 accepted_inseq = 1; 01060 /* The incoming segment is the next in sequence. We check if 01061 we have to trim the end of the segment and update rcv_nxt 01062 and pass the data to the application. */ 01063 #if TCP_QUEUE_OOSEQ 01064 if (pcb->ooseq != NULL && 01065 TCP_SEQ_LEQ(pcb->ooseq->tcphdr->seqno, seqno + inseg.len)) { 01066 if (pcb->ooseq->len > 0) { 01067 /* We have to trim the second edge of the incoming 01068 segment. */ 01069 inseg.len = (u16_t)(pcb->ooseq->tcphdr->seqno - seqno); 01070 pbuf_realloc(inseg.p, inseg.len); 01071 } else { 01072 /* does the ooseq segment contain only flags that are in inseg also? */ 01073 if ((TCPH_FLAGS(inseg.tcphdr) & (TCP_FIN|TCP_SYN)) == 01074 (TCPH_FLAGS(pcb->ooseq->tcphdr) & (TCP_FIN|TCP_SYN))) { 01075 struct tcp_seg *old_ooseq = pcb->ooseq; 01076 pcb->ooseq = pcb->ooseq->next; 01077 memp_free(MEMP_TCP_SEG, old_ooseq); 01078 } 01079 } 01080 } 01081 #endif /* TCP_QUEUE_OOSEQ */ 01082 01083 tcplen = TCP_TCPLEN(&inseg); 01084 01085 /* First received FIN will be ACKed +1, on any successive (duplicate) 01086 * FINs we are already in CLOSE_WAIT and have already done +1. 01087 */ 01088 if (pcb->state != CLOSE_WAIT) { 01089 pcb->rcv_nxt += tcplen; 01090 } 01091 01092 /* Update the receiver's (our) window. */ 01093 if (pcb->rcv_wnd < tcplen) { 01094 pcb->rcv_wnd = 0; 01095 } else { 01096 pcb->rcv_wnd -= tcplen; 01097 } 01098 01099 if (pcb->rcv_ann_wnd < tcplen) { 01100 pcb->rcv_ann_wnd = 0; 01101 } else { 01102 pcb->rcv_ann_wnd -= tcplen; 01103 } 01104 01105 /* If there is data in the segment, we make preparations to 01106 pass this up to the application. The ->recv_data variable 01107 is used for holding the pbuf that goes to the 01108 application. The code for reassembling out-of-sequence data 01109 chains its data on this pbuf as well. 01110 01111 If the segment was a FIN, we set the TF_GOT_FIN flag that will 01112 be used to indicate to the application that the remote side has 01113 closed its end of the connection. */ 01114 if (inseg.p->tot_len > 0) { 01115 recv_data = inseg.p; 01116 /* Since this pbuf now is the responsibility of the 01117 application, we delete our reference to it so that we won't 01118 (mistakingly) deallocate it. */ 01119 inseg.p = NULL; 01120 } 01121 if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { 01122 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n")); 01123 recv_flags = TF_GOT_FIN; 01124 } 01125 01126 #if TCP_QUEUE_OOSEQ 01127 /* We now check if we have segments on the ->ooseq queue that 01128 is now in sequence. */ 01129 while (pcb->ooseq != NULL && 01130 pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) { 01131 01132 cseg = pcb->ooseq; 01133 seqno = pcb->ooseq->tcphdr->seqno; 01134 01135 pcb->rcv_nxt += TCP_TCPLEN(cseg); 01136 if (pcb->rcv_wnd < TCP_TCPLEN(cseg)) { 01137 pcb->rcv_wnd = 0; 01138 } else { 01139 pcb->rcv_wnd -= TCP_TCPLEN(cseg); 01140 } 01141 if (pcb->rcv_ann_wnd < TCP_TCPLEN(cseg)) { 01142 pcb->rcv_ann_wnd = 0; 01143 } else { 01144 pcb->rcv_ann_wnd -= TCP_TCPLEN(cseg); 01145 } 01146 01147 if (cseg->p->tot_len > 0) { 01148 /* Chain this pbuf onto the pbuf that we will pass to 01149 the application. */ 01150 if (recv_data) { 01151 pbuf_cat(recv_data, cseg->p); 01152 } else { 01153 recv_data = cseg->p; 01154 } 01155 cseg->p = NULL; 01156 } 01157 if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) { 01158 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n")); 01159 recv_flags = TF_GOT_FIN; 01160 if (pcb->state == ESTABLISHED) { /* force passive close or we can move to active close */ 01161 pcb->state = CLOSE_WAIT; 01162 } 01163 } 01164 01165 01166 pcb->ooseq = cseg->next; 01167 tcp_seg_free(cseg); 01168 } 01169 #endif /* TCP_QUEUE_OOSEQ */ 01170 01171 01172 /* Acknowledge the segment(s). */ 01173 tcp_ack(pcb); 01174 01175 } else { 01176 /* We get here if the incoming segment is out-of-sequence. */ 01177 tcp_ack_now(pcb); 01178 #if TCP_QUEUE_OOSEQ 01179 /* We queue the segment on the ->ooseq queue. */ 01180 if (pcb->ooseq == NULL) { 01181 pcb->ooseq = tcp_seg_copy(&inseg); 01182 } else { 01183 /* If the queue is not empty, we walk through the queue and 01184 try to find a place where the sequence number of the 01185 incoming segment is between the sequence numbers of the 01186 previous and the next segment on the ->ooseq queue. That is 01187 the place where we put the incoming segment. If needed, we 01188 trim the second edges of the previous and the incoming 01189 segment so that it will fit into the sequence. 01190 01191 If the incoming segment has the same sequence number as a 01192 segment on the ->ooseq queue, we discard the segment that 01193 contains less data. */ 01194 01195 prev = NULL; 01196 for(next = pcb->ooseq; next != NULL; next = next->next) { 01197 if (seqno == next->tcphdr->seqno) { 01198 /* The sequence number of the incoming segment is the 01199 same as the sequence number of the segment on 01200 ->ooseq. We check the lengths to see which one to 01201 discard. */ 01202 if (inseg.len > next->len) { 01203 /* The incoming segment is larger than the old 01204 segment. We replace the old segment with the new 01205 one. */ 01206 cseg = tcp_seg_copy(&inseg); 01207 if (cseg != NULL) { 01208 cseg->next = next->next; 01209 if (prev != NULL) { 01210 prev->next = cseg; 01211 } else { 01212 pcb->ooseq = cseg; 01213 } 01214 } 01215 tcp_seg_free(next); 01216 if (cseg->next != NULL) { 01217 next = cseg->next; 01218 if (TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) { 01219 /* We need to trim the incoming segment. */ 01220 cseg->len = (u16_t)(next->tcphdr->seqno - seqno); 01221 pbuf_realloc(cseg->p, cseg->len); 01222 } 01223 } 01224 break; 01225 } else { 01226 /* Either the lenghts are the same or the incoming 01227 segment was smaller than the old one; in either 01228 case, we ditch the incoming segment. */ 01229 break; 01230 } 01231 } else { 01232 if (prev == NULL) { 01233 if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) { 01234 /* The sequence number of the incoming segment is lower 01235 than the sequence number of the first segment on the 01236 queue. We put the incoming segment first on the 01237 queue. */ 01238 01239 if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) { 01240 /* We need to trim the incoming segment. */ 01241 inseg.len = (u16_t)(next->tcphdr->seqno - seqno); 01242 pbuf_realloc(inseg.p, inseg.len); 01243 } 01244 cseg = tcp_seg_copy(&inseg); 01245 if (cseg != NULL) { 01246 cseg->next = next; 01247 pcb->ooseq = cseg; 01248 } 01249 break; 01250 } 01251 } else 01252 /*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) && 01253 TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/ 01254 if(TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)){ 01255 /* The sequence number of the incoming segment is in 01256 between the sequence numbers of the previous and 01257 the next segment on ->ooseq. We trim and insert the 01258 incoming segment and trim the previous segment, if 01259 needed. */ 01260 if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) { 01261 /* We need to trim the incoming segment. */ 01262 inseg.len = (u16_t)(next->tcphdr->seqno - seqno); 01263 pbuf_realloc(inseg.p, inseg.len); 01264 } 01265 01266 cseg = tcp_seg_copy(&inseg); 01267 if (cseg != NULL) { 01268 cseg->next = next; 01269 prev->next = cseg; 01270 if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) { 01271 /* We need to trim the prev segment. */ 01272 prev->len = (u16_t)(seqno - prev->tcphdr->seqno); 01273 pbuf_realloc(prev->p, prev->len); 01274 } 01275 } 01276 break; 01277 } 01278 /* If the "next" segment is the last segment on the 01279 ooseq queue, we add the incoming segment to the end 01280 of the list. */ 01281 if (next->next == NULL && 01282 TCP_SEQ_GT(seqno, next->tcphdr->seqno)) { 01283 next->next = tcp_seg_copy(&inseg); 01284 if (next->next != NULL) { 01285 if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) { 01286 /* We need to trim the last segment. */ 01287 next->len = (u16_t)(seqno - next->tcphdr->seqno); 01288 pbuf_realloc(next->p, next->len); 01289 } 01290 } 01291 break; 01292 } 01293 } 01294 prev = next; 01295 } 01296 } 01297 #endif /* TCP_QUEUE_OOSEQ */ 01298 01299 } 01300 } else { 01301 if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, 01302 pcb->rcv_nxt + pcb->rcv_ann_wnd-1)){ 01303 tcp_ack_now(pcb); 01304 } 01305 } 01306 } else { 01307 /* Segments with length 0 is taken care of here. Segments that 01308 fall out of the window are ACKed. */ 01309 /*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) || 01310 TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/ 01311 if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){ 01312 tcp_ack_now(pcb); 01313 } 01314 } 01315 return accepted_inseq; 01316 } 01317 01318 /** 01319 * Parses the options contained in the incoming segment. (Code taken 01320 * from uIP with only small changes.) 01321 * 01322 * Called from tcp_listen_input() and tcp_process(). 01323 * Currently, only the MSS option is supported! 01324 * 01325 * @param pcb the tcp_pcb for which a segment arrived 01326 */ 01327 static void 01328 tcp_parseopt(struct tcp_pcb *pcb) 01329 { 01330 u8_t c; 01331 u8_t *opts, opt; 01332 u16_t mss; 01333 01334 opts = (u8_t *)tcphdr + TCP_HLEN; 01335 01336 /* Parse the TCP MSS option, if present. */ 01337 if(TCPH_HDRLEN(tcphdr) > 0x5) { 01338 for(c = 0; c < (TCPH_HDRLEN(tcphdr) - 5) << 2 ;) { 01339 opt = opts[c]; 01340 if (opt == 0x00) { 01341 /* End of options. */ 01342 break; 01343 } else if (opt == 0x01) { 01344 ++c; 01345 /* NOP option. */ 01346 } else if (opt == 0x02 && 01347 opts[c + 1] == 0x04) { 01348 /* An MSS option with the right option length. */ 01349 mss = (opts[c + 2] << 8) | opts[c + 3]; 01350 pcb->mss = mss > TCP_MSS? TCP_MSS: mss; 01351 01352 /* And we are done processing options. */ 01353 break; 01354 } else { 01355 if (opts[c + 1] == 0) { 01356 /* If the length field is zero, the options are malformed 01357 and we don't process them further. */ 01358 break; 01359 } 01360 /* All other options have a length field, so that we easily 01361 can skip past them. */ 01362 c += opts[c + 1]; 01363 } 01364 } 01365 } 01366 } 01367 01368 #endif /* LWIP_TCP */
Generated on Tue Jul 12 2022 16:06:25 by 1.7.2