Some quick code to use UDP-only (no TCP) with mBed. Echos received packets and sends packets when a button is pressed
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 = (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); 00173 tcplen = p->tot_len + ((flags & (TCP_FIN | TCP_SYN)) ? 1 : 0); 00174 00175 /* Demultiplex an incoming segment. First, we check if it is destined 00176 for an active connection. */ 00177 prev = 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 = 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 = NULL; 00267 inseg.len = p->tot_len; 00268 inseg.dataptr = p->payload; 00269 inseg.p = p; 00270 inseg.tcphdr = tcphdr; 00271 00272 recv_data = 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 = 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 tcp_input_pcb = pcb; 00292 err = tcp_process(pcb); 00293 tcp_input_pcb = NULL; 00294 /* A return value of ERR_ABRT means that tcp_abort() was called 00295 and that the pcb has been freed. If so, we don't do anything. */ 00296 if (err != ERR_ABRT) { 00297 if (recv_flags & TF_RESET) { 00298 /* TF_RESET means that the connection was reset by the other 00299 end. We then call the error callback to inform the 00300 application that the connection is dead before we 00301 deallocate the PCB. */ 00302 TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST); 00303 tcp_pcb_remove(&tcp_active_pcbs, pcb); 00304 memp_free(MEMP_TCP_PCB, pcb); 00305 } else if (recv_flags & TF_CLOSED) { 00306 /* The connection has been closed and we will deallocate the 00307 PCB. */ 00308 tcp_pcb_remove(&tcp_active_pcbs, pcb); 00309 memp_free(MEMP_TCP_PCB, pcb); 00310 } else { 00311 err = ERR_OK; 00312 /* If the application has registered a "sent" function to be 00313 called when new send buffer space is available, we call it 00314 now. */ 00315 if (pcb->acked > 0) { 00316 TCP_EVENT_SENT(pcb, pcb->acked, err); 00317 } 00318 00319 if (recv_data != NULL) { 00320 if(flags & TCP_PSH) { 00321 recv_data->flags |= PBUF_FLAG_PUSH; 00322 } 00323 00324 /* Notify application that data has been received. */ 00325 TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err); 00326 00327 /* If the upper layer can't receive this data, store it */ 00328 if (err != ERR_OK) { 00329 pcb->refused_data = recv_data; 00330 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: keep incoming packet, because pcb is \"full\"\n")); 00331 } 00332 } 00333 00334 /* If a FIN segment was received, we call the callback 00335 function with a NULL buffer to indicate EOF. */ 00336 if (recv_flags & TF_GOT_FIN) { 00337 TCP_EVENT_RECV(pcb, NULL, ERR_OK, err); 00338 } 00339 00340 /* If there were no errors, we try to send something out. */ 00341 if (err == ERR_OK) { 00342 tcp_output(pcb); 00343 } 00344 } 00345 } 00346 00347 00348 /* give up our reference to inseg.p */ 00349 if (inseg.p != NULL) 00350 { 00351 pbuf_free(inseg.p); 00352 inseg.p = NULL; 00353 } 00354 #if TCP_INPUT_DEBUG 00355 #if TCP_DEBUG 00356 tcp_debug_print_state(pcb->state); 00357 #endif /* TCP_DEBUG */ 00358 #endif /* TCP_INPUT_DEBUG */ 00359 00360 } else { 00361 00362 /* If no matching PCB was found, send a TCP RST (reset) to the 00363 sender. */ 00364 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n")); 00365 if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) { 00366 TCP_STATS_INC(tcp.proterr); 00367 TCP_STATS_INC(tcp.drop); 00368 tcp_rst(ackno, seqno + tcplen, 00369 &(iphdr->dest), &(iphdr->src), 00370 tcphdr->dest, tcphdr->src); 00371 } 00372 pbuf_free(p); 00373 } 00374 00375 LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane()); 00376 PERF_STOP("tcp_input"); 00377 } 00378 00379 /** 00380 * Called by tcp_input() when a segment arrives for a listening 00381 * connection (from tcp_input()). 00382 * 00383 * @param pcb the tcp_pcb_listen for which a segment arrived 00384 * @return ERR_OK if the segment was processed 00385 * another err_t on error 00386 * 00387 * @note the return value is not (yet?) used in tcp_input() 00388 * @note the segment which arrived is saved in global variables, therefore only the pcb 00389 * involved is passed as a parameter to this function 00390 */ 00391 static err_t 00392 tcp_listen_input(struct tcp_pcb_listen *pcb) 00393 { 00394 struct tcp_pcb *npcb; 00395 err_t rc; 00396 00397 /* In the LISTEN state, we check for incoming SYN segments, 00398 creates a new PCB, and responds with a SYN|ACK. */ 00399 if (flags & TCP_ACK) { 00400 /* For incoming segments with the ACK flag set, respond with a 00401 RST. */ 00402 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n")); 00403 tcp_rst(ackno + 1, seqno + tcplen, 00404 &(iphdr->dest), &(iphdr->src), 00405 tcphdr->dest, tcphdr->src); 00406 } else if (flags & TCP_SYN) { 00407 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest)); 00408 #if TCP_LISTEN_BACKLOG 00409 if (pcb->accepts_pending >= pcb->backlog) { 00410 LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: listen backlog exceeded for port %"U16_F"\n", tcphdr->dest)); 00411 return ERR_ABRT; 00412 } 00413 #endif /* TCP_LISTEN_BACKLOG */ 00414 npcb = tcp_alloc(pcb->prio); 00415 /* If a new PCB could not be created (probably due to lack of memory), 00416 we don't do anything, but rely on the sender will retransmit the 00417 SYN at a time when we have more memory available. */ 00418 if (npcb == NULL) { 00419 LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n")); 00420 TCP_STATS_INC(tcp.memerr); 00421 return ERR_MEM; 00422 } 00423 #if TCP_LISTEN_BACKLOG 00424 pcb->accepts_pending++; 00425 #endif /* TCP_LISTEN_BACKLOG */ 00426 /* Set up the new PCB. */ 00427 ip_addr_set(&(npcb->local_ip), &(iphdr->dest)); 00428 npcb->local_port = pcb->local_port; 00429 ip_addr_set(&(npcb->remote_ip), &(iphdr->src)); 00430 npcb->remote_port = tcphdr->src; 00431 npcb->state = SYN_RCVD; 00432 npcb->rcv_nxt = seqno + 1; 00433 npcb->rcv_ann_right_edge = npcb->rcv_nxt; 00434 npcb->snd_wnd = tcphdr->wnd; 00435 npcb->ssthresh = npcb->snd_wnd; 00436 npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */ 00437 npcb->callback_arg = pcb->callback_arg; 00438 #if LWIP_CALLBACK_API 00439 npcb->accept = pcb->accept; 00440 #endif /* LWIP_CALLBACK_API */ 00441 /* inherit socket options */ 00442 npcb->so_options = pcb->so_options & (SOF_DEBUG|SOF_DONTROUTE|SOF_KEEPALIVE|SOF_OOBINLINE|SOF_LINGER); 00443 /* Register the new PCB so that we can begin receiving segments 00444 for it. */ 00445 TCP_REG(&tcp_active_pcbs, npcb); 00446 00447 /* Parse any options in the SYN. */ 00448 tcp_parseopt(npcb); 00449 #if TCP_CALCULATE_EFF_SEND_MSS 00450 npcb->mss = tcp_eff_send_mss(npcb->mss, &(npcb->remote_ip)); 00451 #endif /* TCP_CALCULATE_EFF_SEND_MSS */ 00452 00453 snmp_inc_tcppassiveopens(); 00454 00455 /* Send a SYN|ACK together with the MSS option. */ 00456 rc = tcp_enqueue(npcb, NULL, 0, TCP_SYN | TCP_ACK, 0, TF_SEG_OPTS_MSS 00457 #if LWIP_TCP_TIMESTAMPS 00458 /* and maybe include the TIMESTAMP option */ 00459 | (npcb->flags & TF_TIMESTAMP ? TF_SEG_OPTS_TS : 0) 00460 #endif 00461 ); 00462 if (rc != ERR_OK) { 00463 tcp_abandon(npcb, 0); 00464 return rc; 00465 } 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 /* RFC 1337: in TIME_WAIT, ignore RST and ACK FINs + any 'acceptable' segments */ 00484 /* RFC 793 3.9 Event Processing - Segment Arrives: 00485 * - first check sequence number - we skip that one in TIME_WAIT (always 00486 * acceptable since we only send ACKs) 00487 * - second check the RST bit (... return) */ 00488 if (flags & TCP_RST) { 00489 return ERR_OK; 00490 } 00491 /* - fourth, check the SYN bit, */ 00492 if (flags & TCP_SYN) { 00493 /* If an incoming segment is not acceptable, an acknowledgment 00494 should be sent in reply */ 00495 if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) { 00496 /* If the SYN is in the window it is an error, send a reset */ 00497 tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src), 00498 tcphdr->dest, tcphdr->src); 00499 return ERR_OK; 00500 } 00501 } else if (flags & TCP_FIN) { 00502 /* - eighth, check the FIN bit: Remain in the TIME-WAIT state. 00503 Restart the 2 MSL time-wait timeout.*/ 00504 pcb->tmr = tcp_ticks; 00505 } 00506 00507 if ((tcplen > 0)) { 00508 /* Acknowledge data, FIN or out-of-window SYN */ 00509 pcb->flags |= TF_ACK_NOW; 00510 return tcp_output(pcb); 00511 } 00512 return ERR_OK; 00513 } 00514 00515 /** 00516 * Implements the TCP state machine. Called by tcp_input. In some 00517 * states tcp_receive() is called to receive data. The tcp_seg 00518 * argument will be freed by the caller (tcp_input()) unless the 00519 * recv_data pointer in the pcb is set. 00520 * 00521 * @param pcb the tcp_pcb for which a segment arrived 00522 * 00523 * @note the segment which arrived is saved in global variables, therefore only the pcb 00524 * involved is passed as a parameter to this function 00525 */ 00526 static err_t 00527 tcp_process(struct tcp_pcb *pcb) 00528 { 00529 struct tcp_seg *rseg; 00530 u8_t acceptable = 0; 00531 err_t err; 00532 00533 err = ERR_OK; 00534 00535 /* Process incoming RST segments. */ 00536 if (flags & TCP_RST) { 00537 /* First, determine if the reset is acceptable. */ 00538 if (pcb->state == SYN_SENT) { 00539 if (ackno == pcb->snd_nxt) { 00540 acceptable = 1; 00541 } 00542 } else { 00543 if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, 00544 pcb->rcv_nxt+pcb->rcv_wnd)) { 00545 acceptable = 1; 00546 } 00547 } 00548 00549 if (acceptable) { 00550 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n")); 00551 LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED); 00552 recv_flags |= TF_RESET; 00553 pcb->flags &= ~TF_ACK_DELAY; 00554 return ERR_RST; 00555 } else { 00556 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", 00557 seqno, pcb->rcv_nxt)); 00558 LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", 00559 seqno, pcb->rcv_nxt)); 00560 return ERR_OK; 00561 } 00562 } 00563 00564 if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) { 00565 /* Cope with new connection attempt after remote end crashed */ 00566 tcp_ack_now(pcb); 00567 return ERR_OK; 00568 } 00569 00570 /* Update the PCB (in)activity timer. */ 00571 pcb->tmr = tcp_ticks; 00572 pcb->keep_cnt_sent = 0; 00573 00574 tcp_parseopt(pcb); 00575 00576 /* Do different things depending on the TCP state. */ 00577 switch (pcb->state) { 00578 case SYN_SENT: 00579 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno, 00580 pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno))); 00581 /* received SYN ACK with expected sequence number? */ 00582 if ((flags & TCP_ACK) && (flags & TCP_SYN) 00583 && ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) { 00584 pcb->snd_buf++; 00585 pcb->rcv_nxt = seqno + 1; 00586 pcb->rcv_ann_right_edge = pcb->rcv_nxt; 00587 pcb->lastack = ackno; 00588 pcb->snd_wnd = tcphdr->wnd; 00589 pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */ 00590 pcb->state = ESTABLISHED; 00591 00592 #if TCP_CALCULATE_EFF_SEND_MSS 00593 pcb->mss = tcp_eff_send_mss(pcb->mss, &(pcb->remote_ip)); 00594 #endif /* TCP_CALCULATE_EFF_SEND_MSS */ 00595 00596 /* Set ssthresh again after changing pcb->mss (already set in tcp_connect 00597 * but for the default value of pcb->mss) */ 00598 pcb->ssthresh = pcb->mss * 10; 00599 00600 pcb->cwnd = ((pcb->cwnd == 1) ? (pcb->mss * 2) : pcb->mss); 00601 LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0)); 00602 --pcb->snd_queuelen; 00603 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"U16_F"\n", (u16_t)pcb->snd_queuelen)); 00604 rseg = pcb->unacked; 00605 pcb->unacked = rseg->next; 00606 00607 /* If there's nothing left to acknowledge, stop the retransmit 00608 timer, otherwise reset it to start again */ 00609 if(pcb->unacked == NULL) 00610 pcb->rtime = -1; 00611 else { 00612 pcb->rtime = 0; 00613 pcb->nrtx = 0; 00614 } 00615 00616 tcp_seg_free(rseg); 00617 00618 /* Call the user specified function to call when sucessfully 00619 * connected. */ 00620 TCP_EVENT_CONNECTED(pcb, ERR_OK, err); 00621 tcp_ack_now(pcb); 00622 } 00623 /* received ACK? possibly a half-open connection */ 00624 else if (flags & TCP_ACK) { 00625 /* send a RST to bring the other side in a non-synchronized state. */ 00626 tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src), 00627 tcphdr->dest, tcphdr->src); 00628 } 00629 break; 00630 case SYN_RCVD: 00631 if (flags & TCP_ACK) { 00632 /* expected ACK number? */ 00633 if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) { 00634 u16_t old_cwnd; 00635 pcb->state = ESTABLISHED; 00636 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); 00637 #if LWIP_CALLBACK_API 00638 LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL); 00639 #endif 00640 /* Call the accept function. */ 00641 TCP_EVENT_ACCEPT(pcb, ERR_OK, err); 00642 if (err != ERR_OK) { 00643 /* If the accept function returns with an error, we abort 00644 * the connection. */ 00645 tcp_abort(pcb); 00646 return ERR_ABRT; 00647 } 00648 old_cwnd = pcb->cwnd; 00649 /* If there was any data contained within this ACK, 00650 * we'd better pass it on to the application as well. */ 00651 tcp_receive(pcb); 00652 00653 /* Prevent ACK for SYN to generate a sent event */ 00654 if (pcb->acked != 0) { 00655 pcb->acked--; 00656 } 00657 00658 pcb->cwnd = ((old_cwnd == 1) ? (pcb->mss * 2) : pcb->mss); 00659 00660 if (recv_flags & TF_GOT_FIN) { 00661 tcp_ack_now(pcb); 00662 pcb->state = CLOSE_WAIT; 00663 } 00664 } 00665 /* incorrect ACK number */ 00666 else { 00667 /* send RST */ 00668 tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src), 00669 tcphdr->dest, tcphdr->src); 00670 } 00671 } else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) { 00672 /* Looks like another copy of the SYN - retransmit our SYN-ACK */ 00673 tcp_rexmit(pcb); 00674 } 00675 break; 00676 case CLOSE_WAIT: 00677 /* FALLTHROUGH */ 00678 case ESTABLISHED: 00679 tcp_receive(pcb); 00680 if (recv_flags & TF_GOT_FIN) { /* passive close */ 00681 tcp_ack_now(pcb); 00682 pcb->state = CLOSE_WAIT; 00683 } 00684 break; 00685 case FIN_WAIT_1: 00686 tcp_receive(pcb); 00687 if (recv_flags & TF_GOT_FIN) { 00688 if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) { 00689 LWIP_DEBUGF(TCP_DEBUG, 00690 ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); 00691 tcp_ack_now(pcb); 00692 tcp_pcb_purge(pcb); 00693 TCP_RMV(&tcp_active_pcbs, pcb); 00694 pcb->state = TIME_WAIT; 00695 TCP_REG(&tcp_tw_pcbs, pcb); 00696 } else { 00697 tcp_ack_now(pcb); 00698 pcb->state = CLOSING; 00699 } 00700 } else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) { 00701 pcb->state = FIN_WAIT_2; 00702 } 00703 break; 00704 case FIN_WAIT_2: 00705 tcp_receive(pcb); 00706 if (recv_flags & TF_GOT_FIN) { 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 CLOSING: 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 tcp_pcb_purge(pcb); 00720 TCP_RMV(&tcp_active_pcbs, pcb); 00721 pcb->state = TIME_WAIT; 00722 TCP_REG(&tcp_tw_pcbs, pcb); 00723 } 00724 break; 00725 case LAST_ACK: 00726 tcp_receive(pcb); 00727 if (flags & TCP_ACK && ackno == pcb->snd_nxt) { 00728 LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); 00729 /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */ 00730 recv_flags |= TF_CLOSED; 00731 } 00732 break; 00733 default: 00734 break; 00735 } 00736 return ERR_OK; 00737 } 00738 00739 /** 00740 * Called by tcp_process. Checks if the given segment is an ACK for outstanding 00741 * data, and if so frees the memory of the buffered data. Next, is places the 00742 * segment on any of the receive queues (pcb->recved or pcb->ooseq). If the segment 00743 * is buffered, the pbuf is referenced by pbuf_ref so that it will not be freed until 00744 * i it has been removed from the buffer. 00745 * 00746 * If the incoming segment constitutes an ACK for a segment that was used for RTT 00747 * estimation, the RTT is estimated here as well. 00748 * 00749 * Called from tcp_process(). 00750 * 00751 * @return 1 if the incoming segment is the next in sequence, 0 if not 00752 */ 00753 static u8_t 00754 tcp_receive(struct tcp_pcb *pcb) 00755 { 00756 struct tcp_seg *next; 00757 #if TCP_QUEUE_OOSEQ 00758 struct tcp_seg *prev, *cseg; 00759 #endif 00760 struct pbuf *p; 00761 s32_t off; 00762 s16_t m; 00763 u32_t right_wnd_edge; 00764 u16_t new_tot_len; 00765 u8_t accepted_inseq = 0; 00766 int found_dupack = 0; 00767 00768 if (flags & TCP_ACK) { 00769 right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2; 00770 00771 /* Update window. */ 00772 if (TCP_SEQ_LT(pcb->snd_wl1, seqno) || 00773 (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) || 00774 (pcb->snd_wl2 == ackno && tcphdr->wnd > pcb->snd_wnd)) { 00775 pcb->snd_wnd = tcphdr->wnd; 00776 pcb->snd_wl1 = seqno; 00777 pcb->snd_wl2 = ackno; 00778 if (pcb->snd_wnd > 0 && pcb->persist_backoff > 0) { 00779 pcb->persist_backoff = 0; 00780 } 00781 LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"U16_F"\n", pcb->snd_wnd)); 00782 #if TCP_WND_DEBUG 00783 } else { 00784 if (pcb->snd_wnd != tcphdr->wnd) { 00785 LWIP_DEBUGF(TCP_WND_DEBUG, 00786 ("tcp_receive: no window update lastack %"U32_F" ackno %" 00787 U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n", 00788 pcb->lastack, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2)); 00789 } 00790 #endif /* TCP_WND_DEBUG */ 00791 } 00792 00793 /* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a 00794 * duplicate ack if: 00795 * 1) It doesn't ACK new data 00796 * 2) length of received packet is zero (i.e. no payload) 00797 * 3) the advertised window hasn't changed 00798 * 4) There is outstanding unacknowledged data (retransmission timer running) 00799 * 5) The ACK is == biggest ACK sequence number so far seen (snd_una) 00800 * 00801 * If it passes all five, should process as a dupack: 00802 * a) dupacks < 3: do nothing 00803 * b) dupacks == 3: fast retransmit 00804 * c) dupacks > 3: increase cwnd 00805 * 00806 * If it only passes 1-3, should reset dupack counter (and add to 00807 * stats, which we don't do in lwIP) 00808 * 00809 * If it only passes 1, should reset dupack counter 00810 * 00811 */ 00812 00813 /* Clause 1 */ 00814 if (TCP_SEQ_LEQ(ackno, pcb->lastack)) { 00815 pcb->acked = 0; 00816 /* Clause 2 */ 00817 if (tcplen == 0) { 00818 /* Clause 3 */ 00819 if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge){ 00820 /* Clause 4 */ 00821 if (pcb->rtime >= 0) { 00822 /* Clause 5 */ 00823 if (pcb->lastack == ackno) { 00824 found_dupack = 1; 00825 if (pcb->dupacks + 1 > pcb->dupacks) 00826 ++pcb->dupacks; 00827 if (pcb->dupacks > 3) { 00828 /* Inflate the congestion window, but not if it means that 00829 the value overflows. */ 00830 if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { 00831 pcb->cwnd += pcb->mss; 00832 } 00833 } else if (pcb->dupacks == 3) { 00834 /* Do fast retransmit */ 00835 tcp_rexmit_fast(pcb); 00836 } 00837 } 00838 } 00839 } 00840 } 00841 /* If Clause (1) or more is true, but not a duplicate ack, reset 00842 * count of consecutive duplicate acks */ 00843 if (!found_dupack) { 00844 pcb->dupacks = 0; 00845 } 00846 } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)){ 00847 /* We come here when the ACK acknowledges new data. */ 00848 00849 /* Reset the "IN Fast Retransmit" flag, since we are no longer 00850 in fast retransmit. Also reset the congestion window to the 00851 slow start threshold. */ 00852 if (pcb->flags & TF_INFR) { 00853 pcb->flags &= ~TF_INFR; 00854 pcb->cwnd = pcb->ssthresh; 00855 } 00856 00857 /* Reset the number of retransmissions. */ 00858 pcb->nrtx = 0; 00859 00860 /* Reset the retransmission time-out. */ 00861 pcb->rto = (pcb->sa >> 3) + pcb->sv; 00862 00863 /* Update the send buffer space. Diff between the two can never exceed 64K? */ 00864 pcb->acked = (u16_t)(ackno - pcb->lastack); 00865 00866 pcb->snd_buf += pcb->acked; 00867 00868 /* Reset the fast retransmit variables. */ 00869 pcb->dupacks = 0; 00870 pcb->lastack = ackno; 00871 00872 /* Update the congestion control variables (cwnd and 00873 ssthresh). */ 00874 if (pcb->state >= ESTABLISHED) { 00875 if (pcb->cwnd < pcb->ssthresh) { 00876 if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { 00877 pcb->cwnd += pcb->mss; 00878 } 00879 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"U16_F"\n", pcb->cwnd)); 00880 } else { 00881 u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd); 00882 if (new_cwnd > pcb->cwnd) { 00883 pcb->cwnd = new_cwnd; 00884 } 00885 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"U16_F"\n", pcb->cwnd)); 00886 } 00887 } 00888 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n", 00889 ackno, 00890 pcb->unacked != NULL? 00891 ntohl(pcb->unacked->tcphdr->seqno): 0, 00892 pcb->unacked != NULL? 00893 ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0)); 00894 00895 /* Remove segment from the unacknowledged list if the incoming 00896 ACK acknowlegdes them. */ 00897 while (pcb->unacked != NULL && 00898 TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) + 00899 TCP_TCPLEN(pcb->unacked), ackno)) { 00900 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unacked\n", 00901 ntohl(pcb->unacked->tcphdr->seqno), 00902 ntohl(pcb->unacked->tcphdr->seqno) + 00903 TCP_TCPLEN(pcb->unacked))); 00904 00905 next = pcb->unacked; 00906 pcb->unacked = pcb->unacked->next; 00907 00908 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen)); 00909 LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); 00910 /* Prevent ACK for FIN to generate a sent event */ 00911 if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) { 00912 pcb->acked--; 00913 } 00914 00915 pcb->snd_queuelen -= pbuf_clen(next->p); 00916 tcp_seg_free(next); 00917 00918 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unacked)\n", (u16_t)pcb->snd_queuelen)); 00919 if (pcb->snd_queuelen != 0) { 00920 LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL || 00921 pcb->unsent != NULL); 00922 } 00923 } 00924 00925 /* If there's nothing left to acknowledge, stop the retransmit 00926 timer, otherwise reset it to start again */ 00927 if(pcb->unacked == NULL) 00928 pcb->rtime = -1; 00929 else 00930 pcb->rtime = 0; 00931 00932 pcb->polltmr = 0; 00933 } else { 00934 /* Fix bug bug #21582: out of sequence ACK, didn't really ack anything */ 00935 pcb->acked = 0; 00936 } 00937 00938 /* We go through the ->unsent list to see if any of the segments 00939 on the list are acknowledged by the ACK. This may seem 00940 strange since an "unsent" segment shouldn't be acked. The 00941 rationale is that lwIP puts all outstanding segments on the 00942 ->unsent list after a retransmission, so these segments may 00943 in fact have been sent once. */ 00944 while (pcb->unsent != NULL && 00945 TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) + 00946 TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) { 00947 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n", 00948 ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) + 00949 TCP_TCPLEN(pcb->unsent))); 00950 00951 next = pcb->unsent; 00952 pcb->unsent = pcb->unsent->next; 00953 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen)); 00954 LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); 00955 /* Prevent ACK for FIN to generate a sent event */ 00956 if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) { 00957 pcb->acked--; 00958 } 00959 pcb->snd_queuelen -= pbuf_clen(next->p); 00960 tcp_seg_free(next); 00961 LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unsent)\n", (u16_t)pcb->snd_queuelen)); 00962 if (pcb->snd_queuelen != 0) { 00963 LWIP_ASSERT("tcp_receive: valid queue length", 00964 pcb->unacked != NULL || pcb->unsent != NULL); 00965 } 00966 } 00967 /* End of ACK for new data processing. */ 00968 00969 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %"U32_F" rtseq %"U32_F" ackno %"U32_F"\n", 00970 pcb->rttest, pcb->rtseq, ackno)); 00971 00972 /* RTT estimation calculations. This is done by checking if the 00973 incoming segment acknowledges the segment we use to take a 00974 round-trip time measurement. */ 00975 if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) { 00976 /* diff between this shouldn't exceed 32K since this are tcp timer ticks 00977 and a round-trip shouldn't be that long... */ 00978 m = (s16_t)(tcp_ticks - pcb->rttest); 00979 00980 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %"U16_F" ticks (%"U16_F" msec).\n", 00981 m, m * TCP_SLOW_INTERVAL)); 00982 00983 /* This is taken directly from VJs original code in his paper */ 00984 m = m - (pcb->sa >> 3); 00985 pcb->sa += m; 00986 if (m < 0) { 00987 m = -m; 00988 } 00989 m = m - (pcb->sv >> 2); 00990 pcb->sv += m; 00991 pcb->rto = (pcb->sa >> 3) + pcb->sv; 00992 00993 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %"U16_F" (%"U16_F" milliseconds)\n", 00994 pcb->rto, pcb->rto * TCP_SLOW_INTERVAL)); 00995 00996 pcb->rttest = 0; 00997 } 00998 } 00999 01000 /* If the incoming segment contains data, we must process it 01001 further. */ 01002 if (tcplen > 0) { 01003 /* This code basically does three things: 01004 01005 +) If the incoming segment contains data that is the next 01006 in-sequence data, this data is passed to the application. This 01007 might involve trimming the first edge of the data. The rcv_nxt 01008 variable and the advertised window are adjusted. 01009 01010 +) If the incoming segment has data that is above the next 01011 sequence number expected (->rcv_nxt), the segment is placed on 01012 the ->ooseq queue. This is done by finding the appropriate 01013 place in the ->ooseq queue (which is ordered by sequence 01014 number) and trim the segment in both ends if needed. An 01015 immediate ACK is sent to indicate that we received an 01016 out-of-sequence segment. 01017 01018 +) Finally, we check if the first segment on the ->ooseq queue 01019 now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If 01020 rcv_nxt > ooseq->seqno, we must trim the first edge of the 01021 segment on ->ooseq before we adjust rcv_nxt. The data in the 01022 segments that are now on sequence are chained onto the 01023 incoming segment so that we only need to call the application 01024 once. 01025 */ 01026 01027 /* First, we check if we must trim the first edge. We have to do 01028 this if the sequence number of the incoming segment is less 01029 than rcv_nxt, and the sequence number plus the length of the 01030 segment is larger than rcv_nxt. */ 01031 /* if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){ 01032 if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/ 01033 if (TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno + 1, seqno + tcplen - 1)){ 01034 /* Trimming the first edge is done by pushing the payload 01035 pointer in the pbuf downwards. This is somewhat tricky since 01036 we do not want to discard the full contents of the pbuf up to 01037 the new starting point of the data since we have to keep the 01038 TCP header which is present in the first pbuf in the chain. 01039 01040 What is done is really quite a nasty hack: the first pbuf in 01041 the pbuf chain is pointed to by inseg.p. Since we need to be 01042 able to deallocate the whole pbuf, we cannot change this 01043 inseg.p pointer to point to any of the later pbufs in the 01044 chain. Instead, we point the ->payload pointer in the first 01045 pbuf to data in one of the later pbufs. We also set the 01046 inseg.data pointer to point to the right place. This way, the 01047 ->p pointer will still point to the first pbuf, but the 01048 ->p->payload pointer will point to data in another pbuf. 01049 01050 After we are done with adjusting the pbuf pointers we must 01051 adjust the ->data pointer in the seg and the segment 01052 length.*/ 01053 01054 off = pcb->rcv_nxt - seqno; 01055 p = inseg.p; 01056 LWIP_ASSERT("inseg.p != NULL", inseg.p); 01057 LWIP_ASSERT("insane offset!", (off < 0x7fff)); 01058 if (inseg.p->len < off) { 01059 LWIP_ASSERT("pbuf too short!", (((s32_t)inseg.p->tot_len) >= off)); 01060 new_tot_len = (u16_t)(inseg.p->tot_len - off); 01061 while (p->len < off) { 01062 off -= p->len; 01063 /* KJM following line changed (with addition of new_tot_len var) 01064 to fix bug #9076 01065 inseg.p->tot_len -= p->len; */ 01066 p->tot_len = new_tot_len; 01067 p->len = 0; 01068 p = p->next; 01069 } 01070 if(pbuf_header(p, (s16_t)-off)) { 01071 /* Do we need to cope with this failing? Assert for now */ 01072 LWIP_ASSERT("pbuf_header failed", 0); 01073 } 01074 } else { 01075 if(pbuf_header(inseg.p, (s16_t)-off)) { 01076 /* Do we need to cope with this failing? Assert for now */ 01077 LWIP_ASSERT("pbuf_header failed", 0); 01078 } 01079 } 01080 /* KJM following line changed to use p->payload rather than inseg->p->payload 01081 to fix bug #9076 */ 01082 inseg.dataptr = p->payload; 01083 inseg.len -= (u16_t)(pcb->rcv_nxt - seqno); 01084 inseg.tcphdr->seqno = seqno = pcb->rcv_nxt; 01085 } 01086 else { 01087 if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){ 01088 /* the whole segment is < rcv_nxt */ 01089 /* must be a duplicate of a packet that has already been correctly handled */ 01090 01091 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno)); 01092 tcp_ack_now(pcb); 01093 } 01094 } 01095 01096 /* The sequence number must be within the window (above rcv_nxt 01097 and below rcv_nxt + rcv_wnd) in order to be further 01098 processed. */ 01099 if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, 01100 pcb->rcv_nxt + pcb->rcv_wnd - 1)){ 01101 if (pcb->rcv_nxt == seqno) { 01102 accepted_inseq = 1; 01103 /* The incoming segment is the next in sequence. We check if 01104 we have to trim the end of the segment and update rcv_nxt 01105 and pass the data to the application. */ 01106 tcplen = TCP_TCPLEN(&inseg); 01107 01108 if (tcplen > pcb->rcv_wnd) { 01109 LWIP_DEBUGF(TCP_INPUT_DEBUG, 01110 ("tcp_receive: other end overran receive window" 01111 "seqno %"U32_F" len %"U32_F" right edge %"U32_F"\n", 01112 seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd)); 01113 if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { 01114 /* Must remove the FIN from the header as we're trimming 01115 * that byte of sequence-space from the packet */ 01116 TCPH_FLAGS_SET(inseg.tcphdr, TCPH_FLAGS(inseg.tcphdr) &~ TCP_FIN); 01117 } 01118 /* Adjust length of segment to fit in the window. */ 01119 inseg.len = pcb->rcv_wnd; 01120 if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) { 01121 inseg.len -= 1; 01122 } 01123 pbuf_realloc(inseg.p, inseg.len); 01124 tcplen = TCP_TCPLEN(&inseg); 01125 LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n", 01126 (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd)); 01127 } 01128 #if TCP_QUEUE_OOSEQ 01129 if (pcb->ooseq != NULL) { 01130 if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { 01131 LWIP_DEBUGF(TCP_INPUT_DEBUG, 01132 ("tcp_receive: received in-order FIN, binning ooseq queue\n")); 01133 /* Received in-order FIN means anything that was received 01134 * out of order must now have been received in-order, so 01135 * bin the ooseq queue */ 01136 while (pcb->ooseq != NULL) { 01137 struct tcp_seg *old_ooseq = pcb->ooseq; 01138 pcb->ooseq = pcb->ooseq->next; 01139 memp_free(MEMP_TCP_SEG, old_ooseq); 01140 } 01141 } else if (TCP_SEQ_LEQ(pcb->ooseq->tcphdr->seqno, seqno + tcplen)) { 01142 if (pcb->ooseq->len > 0) { 01143 /* We have to trim the second edge of the incoming segment. */ 01144 LWIP_ASSERT("tcp_receive: trimmed segment would have zero length\n", 01145 TCP_SEQ_GT(pcb->ooseq->tcphdr->seqno, seqno)); 01146 /* FIN in inseg already handled by dropping whole ooseq queue */ 01147 inseg.len = (u16_t)(pcb->ooseq->tcphdr->seqno - seqno); 01148 if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) { 01149 inseg.len -= 1; 01150 } 01151 pbuf_realloc(inseg.p, inseg.len); 01152 tcplen = TCP_TCPLEN(&inseg); 01153 LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n", 01154 (seqno + tcplen) == pcb->ooseq->tcphdr->seqno); 01155 } else { 01156 /* does the ooseq segment contain only flags that are in inseg also? */ 01157 if ((TCPH_FLAGS(inseg.tcphdr) & (TCP_FIN|TCP_SYN)) == 01158 (TCPH_FLAGS(pcb->ooseq->tcphdr) & (TCP_FIN|TCP_SYN))) { 01159 struct tcp_seg *old_ooseq = pcb->ooseq; 01160 pcb->ooseq = pcb->ooseq->next; 01161 memp_free(MEMP_TCP_SEG, old_ooseq); 01162 } 01163 } 01164 } 01165 } 01166 #endif /* TCP_QUEUE_OOSEQ */ 01167 01168 pcb->rcv_nxt = seqno + tcplen; 01169 01170 /* Update the receiver's (our) window. */ 01171 LWIP_ASSERT("tcp_receive: tcplen > rcv_wnd\n", pcb->rcv_wnd >= tcplen); 01172 pcb->rcv_wnd -= tcplen; 01173 01174 tcp_update_rcv_ann_wnd(pcb); 01175 01176 /* If there is data in the segment, we make preparations to 01177 pass this up to the application. The ->recv_data variable 01178 is used for holding the pbuf that goes to the 01179 application. The code for reassembling out-of-sequence data 01180 chains its data on this pbuf as well. 01181 01182 If the segment was a FIN, we set the TF_GOT_FIN flag that will 01183 be used to indicate to the application that the remote side has 01184 closed its end of the connection. */ 01185 if (inseg.p->tot_len > 0) { 01186 recv_data = inseg.p; 01187 /* Since this pbuf now is the responsibility of the 01188 application, we delete our reference to it so that we won't 01189 (mistakingly) deallocate it. */ 01190 inseg.p = NULL; 01191 } 01192 if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { 01193 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n")); 01194 recv_flags |= TF_GOT_FIN; 01195 } 01196 01197 #if TCP_QUEUE_OOSEQ 01198 /* We now check if we have segments on the ->ooseq queue that 01199 is now in sequence. */ 01200 while (pcb->ooseq != NULL && 01201 pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) { 01202 01203 cseg = pcb->ooseq; 01204 seqno = pcb->ooseq->tcphdr->seqno; 01205 01206 pcb->rcv_nxt += TCP_TCPLEN(cseg); 01207 LWIP_ASSERT("tcp_receive: ooseq tcplen > rcv_wnd\n", 01208 pcb->rcv_wnd >= TCP_TCPLEN(cseg)); 01209 pcb->rcv_wnd -= TCP_TCPLEN(cseg); 01210 01211 tcp_update_rcv_ann_wnd(pcb); 01212 01213 if (cseg->p->tot_len > 0) { 01214 /* Chain this pbuf onto the pbuf that we will pass to 01215 the application. */ 01216 if (recv_data) { 01217 pbuf_cat(recv_data, cseg->p); 01218 } else { 01219 recv_data = cseg->p; 01220 } 01221 cseg->p = NULL; 01222 } 01223 if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) { 01224 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n")); 01225 recv_flags |= TF_GOT_FIN; 01226 if (pcb->state == ESTABLISHED) { /* force passive close or we can move to active close */ 01227 pcb->state = CLOSE_WAIT; 01228 } 01229 } 01230 01231 01232 pcb->ooseq = cseg->next; 01233 tcp_seg_free(cseg); 01234 } 01235 #endif /* TCP_QUEUE_OOSEQ */ 01236 01237 01238 /* Acknowledge the segment(s). */ 01239 tcp_ack(pcb); 01240 01241 } else { 01242 /* We get here if the incoming segment is out-of-sequence. */ 01243 tcp_ack_now(pcb); 01244 #if TCP_QUEUE_OOSEQ 01245 /* We queue the segment on the ->ooseq queue. */ 01246 if (pcb->ooseq == NULL) { 01247 pcb->ooseq = tcp_seg_copy(&inseg); 01248 } else { 01249 /* If the queue is not empty, we walk through the queue and 01250 try to find a place where the sequence number of the 01251 incoming segment is between the sequence numbers of the 01252 previous and the next segment on the ->ooseq queue. That is 01253 the place where we put the incoming segment. If needed, we 01254 trim the second edges of the previous and the incoming 01255 segment so that it will fit into the sequence. 01256 01257 If the incoming segment has the same sequence number as a 01258 segment on the ->ooseq queue, we discard the segment that 01259 contains less data. */ 01260 01261 prev = NULL; 01262 for(next = pcb->ooseq; next != NULL; next = next->next) { 01263 if (seqno == next->tcphdr->seqno) { 01264 /* The sequence number of the incoming segment is the 01265 same as the sequence number of the segment on 01266 ->ooseq. We check the lengths to see which one to 01267 discard. */ 01268 if (inseg.len > next->len) { 01269 /* The incoming segment is larger than the old 01270 segment. We replace the old segment with the new 01271 one. */ 01272 cseg = tcp_seg_copy(&inseg); 01273 if (cseg != NULL) { 01274 cseg->next = next->next; 01275 if (prev != NULL) { 01276 prev->next = cseg; 01277 } else { 01278 pcb->ooseq = cseg; 01279 } 01280 tcp_seg_free(next); 01281 if (cseg->next != NULL) { 01282 next = cseg->next; 01283 if (TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) { 01284 /* We need to trim the incoming segment. */ 01285 cseg->len = (u16_t)(next->tcphdr->seqno - seqno); 01286 pbuf_realloc(cseg->p, cseg->len); 01287 } 01288 } 01289 } 01290 break; 01291 } else { 01292 /* Either the lenghts are the same or the incoming 01293 segment was smaller than the old one; in either 01294 case, we ditch the incoming segment. */ 01295 break; 01296 } 01297 } else { 01298 if (prev == NULL) { 01299 if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) { 01300 /* The sequence number of the incoming segment is lower 01301 than the sequence number of the first segment on the 01302 queue. We put the incoming segment first on the 01303 queue. */ 01304 01305 if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) { 01306 /* We need to trim the incoming segment. */ 01307 inseg.len = (u16_t)(next->tcphdr->seqno - seqno); 01308 pbuf_realloc(inseg.p, inseg.len); 01309 } 01310 cseg = tcp_seg_copy(&inseg); 01311 if (cseg != NULL) { 01312 cseg->next = next; 01313 pcb->ooseq = cseg; 01314 } 01315 break; 01316 } 01317 } else 01318 /*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) && 01319 TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/ 01320 if(TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)){ 01321 /* The sequence number of the incoming segment is in 01322 between the sequence numbers of the previous and 01323 the next segment on ->ooseq. We trim and insert the 01324 incoming segment and trim the previous segment, if 01325 needed. */ 01326 if (TCP_SEQ_GT(seqno + inseg.len, next->tcphdr->seqno)) { 01327 /* We need to trim the incoming segment. */ 01328 inseg.len = (u16_t)(next->tcphdr->seqno - seqno); 01329 pbuf_realloc(inseg.p, inseg.len); 01330 } 01331 01332 cseg = tcp_seg_copy(&inseg); 01333 if (cseg != NULL) { 01334 cseg->next = next; 01335 prev->next = cseg; 01336 if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) { 01337 /* We need to trim the prev segment. */ 01338 prev->len = (u16_t)(seqno - prev->tcphdr->seqno); 01339 pbuf_realloc(prev->p, prev->len); 01340 } 01341 } 01342 break; 01343 } 01344 /* If the "next" segment is the last segment on the 01345 ooseq queue, we add the incoming segment to the end 01346 of the list. */ 01347 if (next->next == NULL && 01348 TCP_SEQ_GT(seqno, next->tcphdr->seqno)) { 01349 next->next = tcp_seg_copy(&inseg); 01350 if (next->next != NULL) { 01351 if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) { 01352 /* We need to trim the last segment. */ 01353 next->len = (u16_t)(seqno - next->tcphdr->seqno); 01354 pbuf_realloc(next->p, next->len); 01355 } 01356 } 01357 break; 01358 } 01359 } 01360 prev = next; 01361 } 01362 } 01363 #endif /* TCP_QUEUE_OOSEQ */ 01364 01365 } 01366 } else { 01367 tcp_ack_now(pcb); 01368 } 01369 } else { 01370 /* Segments with length 0 is taken care of here. Segments that 01371 fall out of the window are ACKed. */ 01372 /*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) || 01373 TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/ 01374 if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){ 01375 tcp_ack_now(pcb); 01376 } 01377 } 01378 return accepted_inseq; 01379 } 01380 01381 /** 01382 * Parses the options contained in the incoming segment. 01383 * 01384 * Called from tcp_listen_input() and tcp_process(). 01385 * Currently, only the MSS option is supported! 01386 * 01387 * @param pcb the tcp_pcb for which a segment arrived 01388 */ 01389 static void 01390 tcp_parseopt(struct tcp_pcb *pcb) 01391 { 01392 u16_t c, max_c; 01393 u16_t mss; 01394 u8_t *opts, opt; 01395 #if LWIP_TCP_TIMESTAMPS 01396 u32_t tsval; 01397 #endif 01398 01399 opts = (u8_t *)tcphdr + TCP_HLEN; 01400 01401 /* Parse the TCP MSS option, if present. */ 01402 if(TCPH_HDRLEN(tcphdr) > 0x5) { 01403 max_c = (TCPH_HDRLEN(tcphdr) - 5) << 2; 01404 for (c = 0; c < max_c; ) { 01405 opt = opts[c]; 01406 switch (opt) { 01407 case 0x00: 01408 /* End of options. */ 01409 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: EOL\n")); 01410 return; 01411 case 0x01: 01412 /* NOP option. */ 01413 ++c; 01414 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: NOP\n")); 01415 break; 01416 case 0x02: 01417 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: MSS\n")); 01418 if (opts[c + 1] != 0x04 || c + 0x04 > max_c) { 01419 /* Bad length */ 01420 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); 01421 return; 01422 } 01423 /* An MSS option with the right option length. */ 01424 mss = (opts[c + 2] << 8) | opts[c + 3]; 01425 /* Limit the mss to the configured TCP_MSS and prevent division by zero */ 01426 pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss; 01427 /* Advance to next option */ 01428 c += 0x04; 01429 break; 01430 #if LWIP_TCP_TIMESTAMPS 01431 case 0x08: 01432 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: TS\n")); 01433 if (opts[c + 1] != 0x0A || c + 0x0A > max_c) { 01434 /* Bad length */ 01435 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); 01436 return; 01437 } 01438 /* TCP timestamp option with valid length */ 01439 tsval = (opts[c+2]) | (opts[c+3] << 8) | 01440 (opts[c+4] << 16) | (opts[c+5] << 24); 01441 if (flags & TCP_SYN) { 01442 pcb->ts_recent = ntohl(tsval); 01443 pcb->flags |= TF_TIMESTAMP; 01444 } else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno+tcplen)) { 01445 pcb->ts_recent = ntohl(tsval); 01446 } 01447 /* Advance to next option */ 01448 c += 0x0A; 01449 break; 01450 #endif 01451 default: 01452 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: other\n")); 01453 if (opts[c + 1] == 0) { 01454 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); 01455 /* If the length field is zero, the options are malformed 01456 and we don't process them further. */ 01457 return; 01458 } 01459 /* All other options have a length field, so that we easily 01460 can skip past them. */ 01461 c += opts[c + 1]; 01462 } 01463 } 01464 } 01465 } 01466 01467 #endif /* LWIP_TCP */
Generated on Tue Jul 12 2022 19:17:24 by 1.7.2