Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
tcp.c
00001 /** 00002 * @file 00003 * Transmission Control Protocol for IP 00004 * 00005 * This file contains common functions for the TCP implementation, such as functinos 00006 * for manipulating the data structures and the TCP timer functions. TCP functions 00007 * related to input and output is found in tcp_in.c and tcp_out.c respectively. 00008 * 00009 */ 00010 00011 /* 00012 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 00013 * All rights reserved. 00014 * 00015 * Redistribution and use in source and binary forms, with or without modification, 00016 * are permitted provided that the following conditions are met: 00017 * 00018 * 1. Redistributions of source code must retain the above copyright notice, 00019 * this list of conditions and the following disclaimer. 00020 * 2. Redistributions in binary form must reproduce the above copyright notice, 00021 * this list of conditions and the following disclaimer in the documentation 00022 * and/or other materials provided with the distribution. 00023 * 3. The name of the author may not be used to endorse or promote products 00024 * derived from this software without specific prior written permission. 00025 * 00026 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00027 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00028 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00029 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00030 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00031 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00032 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00033 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00034 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00035 * OF SUCH DAMAGE. 00036 * 00037 * This file is part of the lwIP TCP/IP stack. 00038 * 00039 * Author: Adam Dunkels <adam@sics.se> 00040 * 00041 */ 00042 00043 #include "lwip/opt.h" 00044 00045 #if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ 00046 00047 #include "lwip/def.h" 00048 #include "lwip/mem.h" 00049 #include "lwip/memp.h" 00050 #include "lwip/snmp.h" 00051 #include "lwip/tcp.h" 00052 00053 #include <string.h> 00054 00055 /* Incremented every coarse grained timer shot (typically every 500 ms). */ 00056 u32_t tcp_ticks; 00057 const u8_t tcp_backoff[13] = 00058 { 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7}; 00059 /* Times per slowtmr hits */ 00060 const u8_t tcp_persist_backoff[7] = { 3, 6, 12, 24, 48, 96, 120 }; 00061 00062 /* The TCP PCB lists. */ 00063 00064 /** List of all TCP PCBs bound but not yet (connected || listening) */ 00065 struct tcp_pcb *tcp_bound_pcbs; 00066 /** List of all TCP PCBs in LISTEN state */ 00067 union tcp_listen_pcbs_t tcp_listen_pcbs; 00068 /** List of all TCP PCBs that are in a state in which 00069 * they accept or send data. */ 00070 struct tcp_pcb *tcp_active_pcbs; 00071 /** List of all TCP PCBs in TIME-WAIT state */ 00072 struct tcp_pcb *tcp_tw_pcbs; 00073 00074 struct tcp_pcb *tcp_tmp_pcb; 00075 00076 static u8_t tcp_timer; 00077 static u16_t tcp_new_port(void); 00078 00079 /** 00080 * Called periodically to dispatch TCP timers. 00081 * 00082 */ 00083 void 00084 tcp_tmr(void) 00085 { 00086 /* Call tcp_fasttmr() every 250 ms */ 00087 tcp_fasttmr(); 00088 00089 if (++tcp_timer & 1) { 00090 /* Call tcp_tmr() every 500 ms, i.e., every other timer 00091 tcp_tmr() is called. */ 00092 tcp_slowtmr(); 00093 } 00094 } 00095 00096 /** 00097 * Closes the connection held by the PCB. 00098 * 00099 * Listening pcbs are freed and may not be referenced any more. 00100 * Connection pcbs are freed if not yet connected and may not be referenced 00101 * any more. If a connection is established (at least SYN received or in 00102 * a closing state), the connection is closed, and put in a closing state. 00103 * The pcb is then automatically freed in tcp_slowtmr(). It is therefore 00104 * unsafe to reference it. 00105 * 00106 * @param pcb the tcp_pcb to close 00107 * @return ERR_OK if connection has been closed 00108 * another err_t if closing failed and pcb is not freed 00109 */ 00110 err_t 00111 tcp_close(struct tcp_pcb *pcb) 00112 { 00113 err_t err; 00114 00115 #if TCP_DEBUG 00116 LWIP_DEBUGF(TCP_DEBUG, ("tcp_close: closing in ")); 00117 tcp_debug_print_state(pcb->state); 00118 #endif /* TCP_DEBUG */ 00119 00120 switch (pcb->state) { 00121 case CLOSED: 00122 /* Closing a pcb in the CLOSED state might seem erroneous, 00123 * however, it is in this state once allocated and as yet unused 00124 * and the user needs some way to free it should the need arise. 00125 * Calling tcp_close() with a pcb that has already been closed, (i.e. twice) 00126 * or for a pcb that has been used and then entered the CLOSED state 00127 * is erroneous, but this should never happen as the pcb has in those cases 00128 * been freed, and so any remaining handles are bogus. */ 00129 err = ERR_OK; 00130 TCP_RMV(&tcp_bound_pcbs, pcb); 00131 memp_free(MEMP_TCP_PCB, pcb); 00132 pcb = NULL; 00133 break; 00134 case LISTEN: 00135 err = ERR_OK; 00136 tcp_pcb_remove((struct tcp_pcb **)&tcp_listen_pcbs.pcbs, pcb); 00137 memp_free(MEMP_TCP_PCB_LISTEN, pcb); 00138 pcb = NULL; 00139 break; 00140 case SYN_SENT: 00141 err = ERR_OK; 00142 tcp_pcb_remove(&tcp_active_pcbs, pcb); 00143 memp_free(MEMP_TCP_PCB, pcb); 00144 pcb = NULL; 00145 snmp_inc_tcpattemptfails(); 00146 break; 00147 case SYN_RCVD: 00148 err = tcp_send_ctrl(pcb, TCP_FIN); 00149 if (err == ERR_OK) { 00150 snmp_inc_tcpattemptfails(); 00151 pcb->state = FIN_WAIT_1; 00152 } 00153 break; 00154 case ESTABLISHED: 00155 err = tcp_send_ctrl(pcb, TCP_FIN); 00156 if (err == ERR_OK) { 00157 snmp_inc_tcpestabresets(); 00158 pcb->state = FIN_WAIT_1; 00159 } 00160 break; 00161 case CLOSE_WAIT: 00162 err = tcp_send_ctrl(pcb, TCP_FIN); 00163 if (err == ERR_OK) { 00164 snmp_inc_tcpestabresets(); 00165 pcb->state = LAST_ACK; 00166 } 00167 break; 00168 default: 00169 /* Has already been closed, do nothing. */ 00170 err = ERR_OK; 00171 pcb = NULL; 00172 break; 00173 } 00174 00175 if (pcb != NULL && err == ERR_OK) { 00176 /* To ensure all data has been sent when tcp_close returns, we have 00177 to make sure tcp_output doesn't fail. 00178 Since we don't really have to ensure all data has been sent when tcp_close 00179 returns (unsent data is sent from tcp timer functions, also), we don't care 00180 for the return value of tcp_output for now. */ 00181 /* @todo: When implementing SO_LINGER, this must be changed somehow: 00182 If SOF_LINGER is set, the data should be sent when tcp_close returns. */ 00183 tcp_output(pcb); 00184 } 00185 return err; 00186 } 00187 00188 /** 00189 * Abandons a connection and optionally sends a RST to the remote 00190 * host. Deletes the local protocol control block. This is done when 00191 * a connection is killed because of shortage of memory. 00192 * 00193 * @param pcb the tcp_pcb to abort 00194 * @param reset boolean to indicate whether a reset should be sent 00195 */ 00196 void 00197 tcp_abandon(struct tcp_pcb *pcb, int reset) 00198 { 00199 u32_t seqno, ackno; 00200 u16_t remote_port, local_port; 00201 struct ip_addr remote_ip, local_ip; 00202 #if LWIP_CALLBACK_API 00203 void (* errf)(void *arg, err_t err); 00204 #endif /* LWIP_CALLBACK_API */ 00205 void *errf_arg; 00206 00207 00208 /* Figure out on which TCP PCB list we are, and remove us. If we 00209 are in an active state, call the receive function associated with 00210 the PCB with a NULL argument, and send an RST to the remote end. */ 00211 if (pcb->state == TIME_WAIT) { 00212 tcp_pcb_remove(&tcp_tw_pcbs, pcb); 00213 memp_free(MEMP_TCP_PCB, pcb); 00214 } else { 00215 seqno = pcb->snd_nxt; 00216 ackno = pcb->rcv_nxt; 00217 ip_addr_set(&local_ip, &(pcb->local_ip)); 00218 ip_addr_set(&remote_ip, &(pcb->remote_ip)); 00219 local_port = pcb->local_port; 00220 remote_port = pcb->remote_port; 00221 #if LWIP_CALLBACK_API 00222 errf = pcb->errf; 00223 #endif /* LWIP_CALLBACK_API */ 00224 errf_arg = pcb->callback_arg; 00225 tcp_pcb_remove(&tcp_active_pcbs, pcb); 00226 if (pcb->unacked != NULL) { 00227 tcp_segs_free(pcb->unacked); 00228 } 00229 if (pcb->unsent != NULL) { 00230 tcp_segs_free(pcb->unsent); 00231 } 00232 #if TCP_QUEUE_OOSEQ 00233 if (pcb->ooseq != NULL) { 00234 tcp_segs_free(pcb->ooseq); 00235 } 00236 #endif /* TCP_QUEUE_OOSEQ */ 00237 memp_free(MEMP_TCP_PCB, pcb); 00238 TCP_EVENT_ERR(errf, errf_arg, ERR_ABRT); 00239 if (reset) { 00240 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n")); 00241 tcp_rst(seqno, ackno, &local_ip, &remote_ip, local_port, remote_port); 00242 } 00243 } 00244 } 00245 00246 /** 00247 * Binds the connection to a local portnumber and IP address. If the 00248 * IP address is not given (i.e., ipaddr == NULL), the IP address of 00249 * the outgoing network interface is used instead. 00250 * 00251 * @param pcb the tcp_pcb to bind (no check is done whether this pcb is 00252 * already bound!) 00253 * @param ipaddr the local ip address to bind to (use IP_ADDR_ANY to bind 00254 * to any local address 00255 * @param port the local port to bind to 00256 * @return ERR_USE if the port is already in use 00257 * ERR_OK if bound 00258 */ 00259 err_t 00260 tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port) 00261 { 00262 struct tcp_pcb *cpcb; 00263 00264 LWIP_ERROR("tcp_bind: can only bind in state CLOSED", pcb->state == CLOSED, return ERR_ISCONN); 00265 00266 if (port == 0) { 00267 port = tcp_new_port(); 00268 } 00269 /* Check if the address already is in use. */ 00270 /* Check the listen pcbs. */ 00271 for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; 00272 cpcb != NULL; cpcb = cpcb->next) { 00273 if (cpcb->local_port == port) { 00274 if (ip_addr_isany(&(cpcb->local_ip)) || 00275 ip_addr_isany(ipaddr) || 00276 ip_addr_cmp(&(cpcb->local_ip), ipaddr)) { 00277 return ERR_USE; 00278 } 00279 } 00280 } 00281 /* Check the connected pcbs. */ 00282 for(cpcb = tcp_active_pcbs; 00283 cpcb != NULL; cpcb = cpcb->next) { 00284 if (cpcb->local_port == port) { 00285 if (ip_addr_isany(&(cpcb->local_ip)) || 00286 ip_addr_isany(ipaddr) || 00287 ip_addr_cmp(&(cpcb->local_ip), ipaddr)) { 00288 return ERR_USE; 00289 } 00290 } 00291 } 00292 /* Check the bound, not yet connected pcbs. */ 00293 for(cpcb = tcp_bound_pcbs; cpcb != NULL; cpcb = cpcb->next) { 00294 if (cpcb->local_port == port) { 00295 if (ip_addr_isany(&(cpcb->local_ip)) || 00296 ip_addr_isany(ipaddr) || 00297 ip_addr_cmp(&(cpcb->local_ip), ipaddr)) { 00298 return ERR_USE; 00299 } 00300 } 00301 } 00302 /* @todo: until SO_REUSEADDR is implemented (see task #6995 on savannah), 00303 * we have to check the pcbs in TIME-WAIT state, also: */ 00304 for(cpcb = tcp_tw_pcbs; cpcb != NULL; cpcb = cpcb->next) { 00305 if (cpcb->local_port == port) { 00306 if (ip_addr_cmp(&(cpcb->local_ip), ipaddr)) { 00307 return ERR_USE; 00308 } 00309 } 00310 } 00311 00312 if (!ip_addr_isany(ipaddr)) { 00313 pcb->local_ip = *ipaddr; 00314 } 00315 pcb->local_port = port; 00316 TCP_REG(&tcp_bound_pcbs, pcb); 00317 LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %"U16_F"\n", port)); 00318 return ERR_OK; 00319 } 00320 #if LWIP_CALLBACK_API 00321 /** 00322 * Default accept callback if no accept callback is specified by the user. 00323 */ 00324 static err_t 00325 tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err) 00326 { 00327 LWIP_UNUSED_ARG(arg); 00328 LWIP_UNUSED_ARG(pcb); 00329 LWIP_UNUSED_ARG(err); 00330 00331 return ERR_ABRT; 00332 } 00333 #endif /* LWIP_CALLBACK_API */ 00334 00335 /** 00336 * Set the state of the connection to be LISTEN, which means that it 00337 * is able to accept incoming connections. The protocol control block 00338 * is reallocated in order to consume less memory. Setting the 00339 * connection to LISTEN is an irreversible process. 00340 * 00341 * @param pcb the original tcp_pcb 00342 * @param backlog the incoming connections queue limit 00343 * @return tcp_pcb used for listening, consumes less memory. 00344 * 00345 * @note The original tcp_pcb is freed. This function therefore has to be 00346 * called like this: 00347 * tpcb = tcp_listen(tpcb); 00348 */ 00349 struct tcp_pcb * 00350 tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) 00351 { 00352 struct tcp_pcb_listen *lpcb; 00353 00354 LWIP_UNUSED_ARG(backlog); 00355 LWIP_ERROR("tcp_listen: pcb already connected", pcb->state == CLOSED, return NULL); 00356 00357 /* already listening? */ 00358 if (pcb->state == LISTEN) { 00359 return pcb; 00360 } 00361 lpcb = (struct tcp_pcb_listen *)(memp_malloc(MEMP_TCP_PCB_LISTEN)); // static_cast<struct tcp_pcb_listen *>(x) 00362 if (lpcb == NULL) { 00363 return NULL; 00364 } 00365 lpcb->callback_arg = pcb->callback_arg; 00366 lpcb->local_port = pcb->local_port; 00367 lpcb->state = LISTEN; 00368 lpcb->so_options = pcb->so_options; 00369 lpcb->so_options |= SOF_ACCEPTCONN; 00370 lpcb->ttl = pcb->ttl; 00371 lpcb->tos = pcb->tos; 00372 ip_addr_set(&lpcb->local_ip, &pcb->local_ip); 00373 TCP_RMV(&tcp_bound_pcbs, pcb); 00374 memp_free(MEMP_TCP_PCB, pcb); 00375 #if LWIP_CALLBACK_API 00376 lpcb->accept = tcp_accept_null; 00377 #endif /* LWIP_CALLBACK_API */ 00378 #if TCP_LISTEN_BACKLOG 00379 lpcb->accepts_pending = 0; 00380 lpcb->backlog = (backlog ? backlog : 1); 00381 #endif /* TCP_LISTEN_BACKLOG */ 00382 TCP_REG(&tcp_listen_pcbs.listen_pcbs, lpcb); 00383 return (struct tcp_pcb *)lpcb; 00384 } 00385 00386 /** 00387 * Update the state that tracks the available window space to advertise. 00388 * 00389 * Returns how much extra window would be advertised if we sent an 00390 * update now. 00391 */ 00392 u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb) 00393 { 00394 u32_t new_right_edge = pcb->rcv_nxt + pcb->rcv_wnd; 00395 00396 if (TCP_SEQ_GEQ(new_right_edge, pcb->rcv_ann_right_edge + pcb->mss)) { 00397 /* we can advertise more window */ 00398 pcb->rcv_ann_wnd = pcb->rcv_wnd; 00399 return new_right_edge - pcb->rcv_ann_right_edge; 00400 } else { 00401 if (TCP_SEQ_GT(pcb->rcv_nxt, pcb->rcv_ann_right_edge)) { 00402 /* Can happen due to other end sending out of advertised window, 00403 * but within actual available (but not yet advertised) window */ 00404 pcb->rcv_ann_wnd = 0; 00405 } else { 00406 /* keep the right edge of window constant */ 00407 pcb->rcv_ann_wnd = pcb->rcv_ann_right_edge - pcb->rcv_nxt; 00408 } 00409 return 0; 00410 } 00411 } 00412 00413 /** 00414 * This function should be called by the application when it has 00415 * processed the data. The purpose is to advertise a larger window 00416 * when the data has been processed. 00417 * 00418 * @param pcb the tcp_pcb for which data is read 00419 * @param len the amount of bytes that have been read by the application 00420 */ 00421 void 00422 tcp_recved(struct tcp_pcb *pcb, u16_t len) 00423 { 00424 int wnd_inflation; 00425 00426 pcb->rcv_wnd += len; 00427 if (pcb->rcv_wnd > TCP_WND) 00428 pcb->rcv_wnd = TCP_WND; 00429 00430 wnd_inflation = tcp_update_rcv_ann_wnd(pcb); 00431 00432 /* If the change in the right edge of window is significant (default 00433 * watermark is TCP_WND/2), then send an explicit update now. 00434 * Otherwise wait for a packet to be sent in the normal course of 00435 * events (or more window to be available later) */ 00436 if (wnd_inflation >= TCP_WND_UPDATE_THRESHOLD) 00437 tcp_ack_now(pcb); 00438 00439 LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %"U16_F" bytes, wnd %"U16_F" (%"U16_F").\n", 00440 len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd)); 00441 } 00442 00443 /** 00444 * A nastly hack featuring 'goto' statements that allocates a 00445 * new TCP local port. 00446 * 00447 * @return a new (free) local TCP port number 00448 */ 00449 static u16_t 00450 tcp_new_port(void) 00451 { 00452 struct tcp_pcb *pcb; 00453 #ifndef TCP_LOCAL_PORT_RANGE_START 00454 #define TCP_LOCAL_PORT_RANGE_START 4096 00455 #define TCP_LOCAL_PORT_RANGE_END 0x7fff 00456 #endif 00457 static u16_t port = TCP_LOCAL_PORT_RANGE_START; 00458 00459 again: 00460 if (++port > TCP_LOCAL_PORT_RANGE_END) { 00461 port = TCP_LOCAL_PORT_RANGE_START; 00462 } 00463 00464 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { 00465 if (pcb->local_port == port) { 00466 goto again; 00467 } 00468 } 00469 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { 00470 if (pcb->local_port == port) { 00471 goto again; 00472 } 00473 } 00474 for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) { 00475 if (pcb->local_port == port) { 00476 goto again; 00477 } 00478 } 00479 return port; 00480 } 00481 00482 /** 00483 * Connects to another host. The function given as the "connected" 00484 * argument will be called when the connection has been established. 00485 * 00486 * @param pcb the tcp_pcb used to establish the connection 00487 * @param ipaddr the remote ip address to connect to 00488 * @param port the remote tcp port to connect to 00489 * @param connected callback function to call when connected (or on error) 00490 * @return ERR_VAL if invalid arguments are given 00491 * ERR_OK if connect request has been sent 00492 * other err_t values if connect request couldn't be sent 00493 */ 00494 err_t 00495 tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port, 00496 err_t (* connected)(void *arg, struct tcp_pcb *tpcb, err_t err)) 00497 { 00498 err_t ret; 00499 u32_t iss; 00500 00501 LWIP_ERROR("tcp_connect: can only connected from state CLOSED", pcb->state == CLOSED, return ERR_ISCONN); 00502 00503 LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port)); 00504 if (ipaddr != NULL) { 00505 pcb->remote_ip = *ipaddr; 00506 } else { 00507 return ERR_VAL; 00508 } 00509 pcb->remote_port = port; 00510 if (pcb->local_port == 0) { 00511 pcb->local_port = tcp_new_port(); 00512 } 00513 iss = tcp_next_iss(); 00514 pcb->rcv_nxt = 0; 00515 pcb->snd_nxt = iss; 00516 pcb->lastack = iss - 1; 00517 pcb->snd_lbb = iss - 1; 00518 pcb->rcv_wnd = TCP_WND; 00519 pcb->rcv_ann_wnd = TCP_WND; 00520 pcb->rcv_ann_right_edge = pcb->rcv_nxt; 00521 pcb->snd_wnd = TCP_WND; 00522 /* As initial send MSS, we use TCP_MSS but limit it to 536. 00523 The send MSS is updated when an MSS option is received. */ 00524 pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS; 00525 #if TCP_CALCULATE_EFF_SEND_MSS 00526 pcb->mss = tcp_eff_send_mss(pcb->mss, ipaddr); 00527 #endif /* TCP_CALCULATE_EFF_SEND_MSS */ 00528 pcb->cwnd = 1; 00529 pcb->ssthresh = pcb->mss * 10; 00530 pcb->state = SYN_SENT; 00531 #if LWIP_CALLBACK_API 00532 pcb->connected = connected; 00533 #endif /* LWIP_CALLBACK_API */ 00534 TCP_RMV(&tcp_bound_pcbs, pcb); 00535 TCP_REG(&tcp_active_pcbs, pcb); 00536 00537 snmp_inc_tcpactiveopens(); 00538 00539 ret = tcp_enqueue(pcb, NULL, 0, TCP_SYN, 0, TF_SEG_OPTS_MSS 00540 #if LWIP_TCP_TIMESTAMPS 00541 | TF_SEG_OPTS_TS 00542 #endif 00543 ); 00544 if (ret == ERR_OK) { 00545 tcp_output(pcb); 00546 } 00547 return ret; 00548 } 00549 00550 /** 00551 * Called every 500 ms and implements the retransmission timer and the timer that 00552 * removes PCBs that have been in TIME-WAIT for enough time. It also increments 00553 * various timers such as the inactivity timer in each PCB. 00554 * 00555 * Automatically called from tcp_tmr(). 00556 */ 00557 void 00558 tcp_slowtmr(void) 00559 { 00560 struct tcp_pcb *pcb, *pcb2, *prev; 00561 u16_t eff_wnd; 00562 u8_t pcb_remove; /* flag if a PCB should be removed */ 00563 err_t err; 00564 00565 err = ERR_OK; 00566 00567 ++tcp_ticks; 00568 00569 /* Steps through all of the active PCBs. */ 00570 prev = NULL; 00571 pcb = tcp_active_pcbs; 00572 if (pcb == NULL) { 00573 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n")); 00574 } 00575 while (pcb != NULL) { 00576 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb\n")); 00577 LWIP_ASSERT("tcp_slowtmr: active pcb->state != CLOSED\n", pcb->state != CLOSED); 00578 LWIP_ASSERT("tcp_slowtmr: active pcb->state != LISTEN\n", pcb->state != LISTEN); 00579 LWIP_ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT\n", pcb->state != TIME_WAIT); 00580 00581 pcb_remove = 0; 00582 00583 if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) { 00584 ++pcb_remove; 00585 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max SYN retries reached\n")); 00586 } 00587 else if (pcb->nrtx == TCP_MAXRTX) { 00588 ++pcb_remove; 00589 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n")); 00590 } else { 00591 if (pcb->persist_backoff > 0) { 00592 /* If snd_wnd is zero, use persist timer to send 1 byte probes 00593 * instead of using the standard retransmission mechanism. */ 00594 pcb->persist_cnt++; 00595 if (pcb->persist_cnt >= tcp_persist_backoff[pcb->persist_backoff-1]) { 00596 pcb->persist_cnt = 0; 00597 if (pcb->persist_backoff < sizeof(tcp_persist_backoff)) { 00598 pcb->persist_backoff++; 00599 } 00600 tcp_zero_window_probe(pcb); 00601 } 00602 } else { 00603 /* Increase the retransmission timer if it is running */ 00604 if(pcb->rtime >= 0) 00605 ++pcb->rtime; 00606 00607 if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) { 00608 /* Time for a retransmission. */ 00609 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"S16_F 00610 " pcb->rto %"S16_F"\n", 00611 pcb->rtime, pcb->rto)); 00612 00613 /* Double retransmission time-out unless we are trying to 00614 * connect to somebody (i.e., we are in SYN_SENT). */ 00615 if (pcb->state != SYN_SENT) { 00616 pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx]; 00617 } 00618 00619 /* Reset the retransmission timer. */ 00620 pcb->rtime = 0; 00621 00622 /* Reduce congestion window and ssthresh. */ 00623 eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd); 00624 pcb->ssthresh = eff_wnd >> 1; 00625 if (pcb->ssthresh < pcb->mss) { 00626 pcb->ssthresh = pcb->mss * 2; 00627 } 00628 pcb->cwnd = pcb->mss; 00629 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"U16_F 00630 " ssthresh %"U16_F"\n", 00631 pcb->cwnd, pcb->ssthresh)); 00632 00633 /* The following needs to be called AFTER cwnd is set to one 00634 mss - STJ */ 00635 tcp_rexmit_rto(pcb); 00636 } 00637 } 00638 } 00639 /* Check if this PCB has stayed too long in FIN-WAIT-2 */ 00640 if (pcb->state == FIN_WAIT_2) { 00641 if ((u32_t)(tcp_ticks - pcb->tmr) > 00642 TCP_FIN_WAIT_TIMEOUT / TCP_SLOW_INTERVAL) { 00643 ++pcb_remove; 00644 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in FIN-WAIT-2\n")); 00645 } 00646 } 00647 00648 /* Check if KEEPALIVE should be sent */ 00649 if((pcb->so_options & SOF_KEEPALIVE) && 00650 ((pcb->state == ESTABLISHED) || 00651 (pcb->state == CLOSE_WAIT))) { 00652 #if LWIP_TCP_KEEPALIVE 00653 if((u32_t)(tcp_ticks - pcb->tmr) > 00654 (pcb->keep_idle + (pcb->keep_cnt*pcb->keep_intvl)) 00655 / TCP_SLOW_INTERVAL) 00656 #else 00657 if((u32_t)(tcp_ticks - pcb->tmr) > 00658 (pcb->keep_idle + TCP_MAXIDLE) / TCP_SLOW_INTERVAL) 00659 #endif /* LWIP_TCP_KEEPALIVE */ 00660 { 00661 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %"U16_F".%"U16_F".%"U16_F".%"U16_F".\n", 00662 ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip), 00663 ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip))); 00664 00665 tcp_abort(pcb); 00666 } 00667 #if LWIP_TCP_KEEPALIVE 00668 else if((u32_t)(tcp_ticks - pcb->tmr) > 00669 (pcb->keep_idle + pcb->keep_cnt_sent * pcb->keep_intvl) 00670 / TCP_SLOW_INTERVAL) 00671 #else 00672 else if((u32_t)(tcp_ticks - pcb->tmr) > 00673 (pcb->keep_idle + pcb->keep_cnt_sent * TCP_KEEPINTVL_DEFAULT) 00674 / TCP_SLOW_INTERVAL) 00675 #endif /* LWIP_TCP_KEEPALIVE */ 00676 { 00677 tcp_keepalive(pcb); 00678 pcb->keep_cnt_sent++; 00679 } 00680 } 00681 00682 /* If this PCB has queued out of sequence data, but has been 00683 inactive for too long, will drop the data (it will eventually 00684 be retransmitted). */ 00685 #if TCP_QUEUE_OOSEQ 00686 if (pcb->ooseq != NULL && 00687 (u32_t)tcp_ticks - pcb->tmr >= pcb->rto * TCP_OOSEQ_TIMEOUT) { 00688 tcp_segs_free(pcb->ooseq); 00689 pcb->ooseq = NULL; 00690 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: dropping OOSEQ queued data\n")); 00691 } 00692 #endif /* TCP_QUEUE_OOSEQ */ 00693 00694 /* Check if this PCB has stayed too long in SYN-RCVD */ 00695 if (pcb->state == SYN_RCVD) { 00696 if ((u32_t)(tcp_ticks - pcb->tmr) > 00697 TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) { 00698 ++pcb_remove; 00699 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in SYN-RCVD\n")); 00700 } 00701 } 00702 00703 /* Check if this PCB has stayed too long in LAST-ACK */ 00704 if (pcb->state == LAST_ACK) { 00705 if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) { 00706 ++pcb_remove; 00707 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in LAST-ACK\n")); 00708 } 00709 } 00710 00711 /* If the PCB should be removed, do it. */ 00712 if (pcb_remove) { 00713 tcp_pcb_purge(pcb); 00714 /* Remove PCB from tcp_active_pcbs list. */ 00715 if (prev != NULL) { 00716 LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_active_pcbs", pcb != tcp_active_pcbs); 00717 prev->next = pcb->next; 00718 } else { 00719 /* This PCB was the first. */ 00720 LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_active_pcbs", tcp_active_pcbs == pcb); 00721 tcp_active_pcbs = pcb->next; 00722 } 00723 00724 TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_ABRT); 00725 00726 pcb2 = pcb->next; 00727 memp_free(MEMP_TCP_PCB, pcb); 00728 pcb = pcb2; 00729 } else { 00730 00731 /* We check if we should poll the connection. */ 00732 ++pcb->polltmr; 00733 if (pcb->polltmr >= pcb->pollinterval) { 00734 pcb->polltmr = 0; 00735 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: polling application\n")); 00736 TCP_EVENT_POLL(pcb, err); 00737 if (err == ERR_OK) { 00738 tcp_output(pcb); 00739 } 00740 } 00741 00742 prev = pcb; 00743 pcb = pcb->next; 00744 } 00745 } 00746 00747 00748 /* Steps through all of the TIME-WAIT PCBs. */ 00749 prev = NULL; 00750 pcb = tcp_tw_pcbs; 00751 while (pcb != NULL) { 00752 LWIP_ASSERT("tcp_slowtmr: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); 00753 pcb_remove = 0; 00754 00755 /* Check if this PCB has stayed long enough in TIME-WAIT */ 00756 if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) { 00757 ++pcb_remove; 00758 } 00759 00760 00761 00762 /* If the PCB should be removed, do it. */ 00763 if (pcb_remove) { 00764 tcp_pcb_purge(pcb); 00765 /* Remove PCB from tcp_tw_pcbs list. */ 00766 if (prev != NULL) { 00767 LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_tw_pcbs", pcb != tcp_tw_pcbs); 00768 prev->next = pcb->next; 00769 } else { 00770 /* This PCB was the first. */ 00771 LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_tw_pcbs", tcp_tw_pcbs == pcb); 00772 tcp_tw_pcbs = pcb->next; 00773 } 00774 pcb2 = pcb->next; 00775 memp_free(MEMP_TCP_PCB, pcb); 00776 pcb = pcb2; 00777 } else { 00778 prev = pcb; 00779 pcb = pcb->next; 00780 } 00781 } 00782 } 00783 00784 /** 00785 * Is called every TCP_FAST_INTERVAL (250 ms) and process data previously 00786 * "refused" by upper layer (application) and sends delayed ACKs. 00787 * 00788 * Automatically called from tcp_tmr(). 00789 */ 00790 void 00791 tcp_fasttmr(void) 00792 { 00793 struct tcp_pcb *pcb; 00794 00795 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { 00796 /* If there is data which was previously "refused" by upper layer */ 00797 if (pcb->refused_data != NULL) { 00798 /* Notify again application with data previously received. */ 00799 err_t err; 00800 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_fasttmr: notify kept packet\n")); 00801 TCP_EVENT_RECV(pcb, pcb->refused_data, ERR_OK, err); 00802 if (err == ERR_OK) { 00803 pcb->refused_data = NULL; 00804 } 00805 } 00806 00807 /* send delayed ACKs */ 00808 if (pcb->flags & TF_ACK_DELAY) { 00809 LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: delayed ACK\n")); 00810 tcp_ack_now(pcb); 00811 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); 00812 } 00813 } 00814 } 00815 00816 /** 00817 * Deallocates a list of TCP segments (tcp_seg structures). 00818 * 00819 * @param seg tcp_seg list of TCP segments to free 00820 * @return the number of pbufs that were deallocated 00821 */ 00822 u8_t 00823 tcp_segs_free(struct tcp_seg *seg) 00824 { 00825 u8_t count = 0; 00826 struct tcp_seg *next; 00827 while (seg != NULL) { 00828 next = seg->next; 00829 count += tcp_seg_free(seg); 00830 seg = next; 00831 } 00832 return count; 00833 } 00834 00835 /** 00836 * Frees a TCP segment (tcp_seg structure). 00837 * 00838 * @param seg single tcp_seg to free 00839 * @return the number of pbufs that were deallocated 00840 */ 00841 u8_t 00842 tcp_seg_free(struct tcp_seg *seg) 00843 { 00844 u8_t count = 0; 00845 00846 if (seg != NULL) { 00847 if (seg->p != NULL) { 00848 count = pbuf_free(seg->p); 00849 #if TCP_DEBUG 00850 seg->p = NULL; 00851 #endif /* TCP_DEBUG */ 00852 } 00853 memp_free(MEMP_TCP_SEG, seg); 00854 } 00855 return count; 00856 } 00857 00858 /** 00859 * Sets the priority of a connection. 00860 * 00861 * @param pcb the tcp_pcb to manipulate 00862 * @param prio new priority 00863 */ 00864 void 00865 tcp_setprio(struct tcp_pcb *pcb, u8_t prio) 00866 { 00867 pcb->prio = prio; 00868 } 00869 #if TCP_QUEUE_OOSEQ 00870 00871 /** 00872 * Returns a copy of the given TCP segment. 00873 * The pbuf and data are not copied, only the pointers 00874 * 00875 * @param seg the old tcp_seg 00876 * @return a copy of seg 00877 */ 00878 struct tcp_seg * 00879 tcp_seg_copy(struct tcp_seg *seg) 00880 { 00881 struct tcp_seg *cseg; 00882 00883 cseg = (struct tcp_seg *)(memp_malloc(MEMP_TCP_SEG)); // static_cast<struct tcp_seg *>(x) 00884 if (cseg == NULL) { 00885 return NULL; 00886 } 00887 SMEMCPY((u8_t *)cseg, (const u8_t *)seg, sizeof(struct tcp_seg)); 00888 pbuf_ref(cseg->p); 00889 return cseg; 00890 } 00891 #endif 00892 00893 #if LWIP_CALLBACK_API 00894 /** 00895 * Default receive callback that is called if the user didn't register 00896 * a recv callback for the pcb. 00897 */ 00898 static err_t 00899 tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) 00900 { 00901 arg = arg; 00902 if (p != NULL) { 00903 pbuf_free(p); 00904 } else if (err == ERR_OK) { 00905 return tcp_close(pcb); 00906 } 00907 return ERR_OK; 00908 } 00909 #endif /* LWIP_CALLBACK_API */ 00910 00911 /** 00912 * Kills the oldest active connection that has lower priority than prio. 00913 * 00914 * @param prio minimum priority 00915 */ 00916 static void 00917 tcp_kill_prio(u8_t prio) 00918 { 00919 struct tcp_pcb *pcb, *inactive; 00920 u32_t inactivity; 00921 u8_t mprio; 00922 00923 00924 mprio = TCP_PRIO_MAX; 00925 00926 /* We kill the oldest active connection that has lower priority than prio. */ 00927 inactivity = 0; 00928 inactive = NULL; 00929 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { 00930 if (pcb->prio <= prio && 00931 pcb->prio <= mprio && 00932 (u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { 00933 inactivity = tcp_ticks - pcb->tmr; 00934 inactive = pcb; 00935 mprio = pcb->prio; 00936 } 00937 } 00938 if (inactive != NULL) { 00939 LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%"S32_F")\n", 00940 (void *)inactive, inactivity)); 00941 tcp_abort(inactive); 00942 } 00943 } 00944 00945 /** 00946 * Kills the oldest connection that is in TIME_WAIT state. 00947 * Called from tcp_alloc() if no more connections are available. 00948 */ 00949 static void 00950 tcp_kill_timewait(void) 00951 { 00952 struct tcp_pcb *pcb, *inactive; 00953 u32_t inactivity; 00954 00955 inactivity = 0; 00956 inactive = NULL; 00957 /* Go through the list of TIME_WAIT pcbs and get the oldest pcb. */ 00958 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { 00959 if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { 00960 inactivity = tcp_ticks - pcb->tmr; 00961 inactive = pcb; 00962 } 00963 } 00964 if (inactive != NULL) { 00965 LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%"S32_F")\n", 00966 (void *)inactive, inactivity)); 00967 tcp_abort(inactive); 00968 } 00969 } 00970 00971 /** 00972 * Allocate a new tcp_pcb structure. 00973 * 00974 * @param prio priority for the new pcb 00975 * @return a new tcp_pcb that initially is in state CLOSED 00976 */ 00977 struct tcp_pcb * 00978 tcp_alloc(u8_t prio) 00979 { 00980 struct tcp_pcb *pcb; 00981 u32_t iss; 00982 00983 pcb = (struct tcp_pcb *)(memp_malloc(MEMP_TCP_PCB)); // static_cast<struct tcp_pcb *>(x) 00984 if (pcb == NULL) { 00985 /* Try killing oldest connection in TIME-WAIT. */ 00986 LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest TIME-WAIT connection\n")); 00987 tcp_kill_timewait(); 00988 /* Try to allocate a tcp_pcb again. */ 00989 pcb = (struct tcp_pcb *)(memp_malloc(MEMP_TCP_PCB)); // static_cast<struct tcp_pcb *>(x) 00990 if (pcb == NULL) { 00991 /* Try killing active connections with lower priority than the new one. */ 00992 tcp_kill_prio(prio); 00993 /* Try to allocate a tcp_pcb again. */ 00994 pcb = (struct tcp_pcb *)(memp_malloc(MEMP_TCP_PCB)); // static_cast<struct tcp_pcb *>(x) 00995 } 00996 } 00997 if (pcb != NULL) { 00998 memset(pcb, 0, sizeof(struct tcp_pcb)); 00999 pcb->prio = TCP_PRIO_NORMAL; 01000 pcb->snd_buf = TCP_SND_BUF; 01001 pcb->snd_queuelen = 0; 01002 pcb->rcv_wnd = TCP_WND; 01003 pcb->rcv_ann_wnd = TCP_WND; 01004 pcb->tos = 0; 01005 pcb->ttl = TCP_TTL; 01006 /* As initial send MSS, we use TCP_MSS but limit it to 536. 01007 The send MSS is updated when an MSS option is received. */ 01008 pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS; 01009 pcb->rto = 3000 / TCP_SLOW_INTERVAL; 01010 pcb->sa = 0; 01011 pcb->sv = 3000 / TCP_SLOW_INTERVAL; 01012 pcb->rtime = -1; 01013 pcb->cwnd = 1; 01014 iss = tcp_next_iss(); 01015 pcb->snd_wl2 = iss; 01016 pcb->snd_nxt = iss; 01017 pcb->snd_max = iss; 01018 pcb->lastack = iss; 01019 pcb->snd_lbb = iss; 01020 pcb->tmr = tcp_ticks; 01021 01022 pcb->polltmr = 0; 01023 01024 #if LWIP_CALLBACK_API 01025 pcb->recv = tcp_recv_null; 01026 #endif /* LWIP_CALLBACK_API */ 01027 01028 /* Init KEEPALIVE timer */ 01029 pcb->keep_idle = TCP_KEEPIDLE_DEFAULT; 01030 01031 #if LWIP_TCP_KEEPALIVE 01032 pcb->keep_intvl = TCP_KEEPINTVL_DEFAULT; 01033 pcb->keep_cnt = TCP_KEEPCNT_DEFAULT; 01034 #endif /* LWIP_TCP_KEEPALIVE */ 01035 01036 pcb->keep_cnt_sent = 0; 01037 } 01038 return pcb; 01039 } 01040 01041 /** 01042 * Creates a new TCP protocol control block but doesn't place it on 01043 * any of the TCP PCB lists. 01044 * The pcb is not put on any list until binding using tcp_bind(). 01045 * 01046 * @internal: Maybe there should be a idle TCP PCB list where these 01047 * PCBs are put on. Port reservation using tcp_bind() is implemented but 01048 * allocated pcbs that are not bound can't be killed automatically if wanting 01049 * to allocate a pcb with higher prio (@see tcp_kill_prio()) 01050 * 01051 * @return a new tcp_pcb that initially is in state CLOSED 01052 */ 01053 struct tcp_pcb * 01054 tcp_new(void) 01055 { 01056 return tcp_alloc(TCP_PRIO_NORMAL); 01057 } 01058 01059 /** 01060 * Used to specify the argument that should be passed callback 01061 * functions. 01062 * 01063 * @param pcb tcp_pcb to set the callback argument 01064 * @param arg void pointer argument to pass to callback functions 01065 */ 01066 void 01067 tcp_arg(struct tcp_pcb *pcb, void *arg) 01068 { 01069 pcb->callback_arg = arg; 01070 } 01071 #if LWIP_CALLBACK_API 01072 01073 /** 01074 * Used to specify the function that should be called when a TCP 01075 * connection receives data. 01076 * 01077 * @param pcb tcp_pcb to set the recv callback 01078 * @param recv callback function to call for this pcb when data is received 01079 */ 01080 void 01081 tcp_recv(struct tcp_pcb *pcb, 01082 err_t (* recv)(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)) 01083 { 01084 pcb->recv = recv; 01085 } 01086 01087 /** 01088 * Used to specify the function that should be called when TCP data 01089 * has been successfully delivered to the remote host. 01090 * 01091 * @param pcb tcp_pcb to set the sent callback 01092 * @param sent callback function to call for this pcb when data is successfully sent 01093 */ 01094 void 01095 tcp_sent(struct tcp_pcb *pcb, 01096 err_t (* sent)(void *arg, struct tcp_pcb *tpcb, u16_t len)) 01097 { 01098 pcb->sent = sent; 01099 } 01100 01101 /** 01102 * Used to specify the function that should be called when a fatal error 01103 * has occured on the connection. 01104 * 01105 * @param pcb tcp_pcb to set the err callback 01106 * @param errf callback function to call for this pcb when a fatal error 01107 * has occured on the connection 01108 */ 01109 void 01110 tcp_err(struct tcp_pcb *pcb, 01111 void (* errf)(void *arg, err_t err)) 01112 { 01113 pcb->errf = errf; 01114 } 01115 01116 /** 01117 * Used for specifying the function that should be called when a 01118 * LISTENing connection has been connected to another host. 01119 * 01120 * @param pcb tcp_pcb to set the accept callback 01121 * @param accept callback function to call for this pcb when LISTENing 01122 * connection has been connected to another host 01123 */ 01124 void 01125 tcp_accept(struct tcp_pcb *pcb, 01126 err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err)) 01127 { 01128 pcb->accept = accept; 01129 } 01130 #endif /* LWIP_CALLBACK_API */ 01131 01132 01133 /** 01134 * Used to specify the function that should be called periodically 01135 * from TCP. The interval is specified in terms of the TCP coarse 01136 * timer interval, which is called twice a second. 01137 * 01138 */ 01139 void 01140 tcp_poll(struct tcp_pcb *pcb, 01141 err_t (* poll)(void *arg, struct tcp_pcb *tpcb), u8_t interval) 01142 { 01143 #if LWIP_CALLBACK_API 01144 pcb->poll = poll; 01145 #endif /* LWIP_CALLBACK_API */ 01146 pcb->pollinterval = interval; 01147 } 01148 01149 /** 01150 * Purges a TCP PCB. Removes any buffered data and frees the buffer memory 01151 * (pcb->ooseq, pcb->unsent and pcb->unacked are freed). 01152 * 01153 * @param pcb tcp_pcb to purge. The pcb itself is not deallocated! 01154 */ 01155 void 01156 tcp_pcb_purge(struct tcp_pcb *pcb) 01157 { 01158 if (pcb->state != CLOSED && 01159 pcb->state != TIME_WAIT && 01160 pcb->state != LISTEN) { 01161 01162 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n")); 01163 01164 #if TCP_LISTEN_BACKLOG 01165 if (pcb->state == SYN_RCVD) { 01166 /* Need to find the corresponding listen_pcb and decrease its accepts_pending */ 01167 struct tcp_pcb_listen *lpcb; 01168 LWIP_ASSERT("tcp_pcb_purge: pcb->state == SYN_RCVD but tcp_listen_pcbs is NULL", 01169 tcp_listen_pcbs.listen_pcbs != NULL); 01170 for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { 01171 if ((lpcb->local_port == pcb->local_port) && 01172 (ip_addr_isany(&lpcb->local_ip) || 01173 ip_addr_cmp(&pcb->local_ip, &lpcb->local_ip))) { 01174 /* port and address of the listen pcb match the timed-out pcb */ 01175 LWIP_ASSERT("tcp_pcb_purge: listen pcb does not have accepts pending", 01176 lpcb->accepts_pending > 0); 01177 lpcb->accepts_pending--; 01178 break; 01179 } 01180 } 01181 } 01182 #endif /* TCP_LISTEN_BACKLOG */ 01183 01184 01185 if (pcb->refused_data != NULL) { 01186 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->refused_data\n")); 01187 pbuf_free(pcb->refused_data); 01188 pcb->refused_data = NULL; 01189 } 01190 if (pcb->unsent != NULL) { 01191 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: not all data sent\n")); 01192 } 01193 if (pcb->unacked != NULL) { 01194 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->unacked\n")); 01195 } 01196 #if TCP_QUEUE_OOSEQ /* LW */ 01197 if (pcb->ooseq != NULL) { 01198 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->ooseq\n")); 01199 } 01200 01201 /* Stop the retransmission timer as it will expect data on unacked 01202 queue if it fires */ 01203 pcb->rtime = -1; 01204 01205 tcp_segs_free(pcb->ooseq); 01206 pcb->ooseq = NULL; 01207 #endif /* TCP_QUEUE_OOSEQ */ 01208 tcp_segs_free(pcb->unsent); 01209 tcp_segs_free(pcb->unacked); 01210 pcb->unacked = pcb->unsent = NULL; 01211 } 01212 } 01213 01214 /** 01215 * Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first. 01216 * 01217 * @param pcblist PCB list to purge. 01218 * @param pcb tcp_pcb to purge. The pcb itself is also deallocated! 01219 */ 01220 void 01221 tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb) 01222 { 01223 TCP_RMV(pcblist, pcb); 01224 01225 tcp_pcb_purge(pcb); 01226 01227 /* if there is an outstanding delayed ACKs, send it */ 01228 if (pcb->state != TIME_WAIT && 01229 pcb->state != LISTEN && 01230 pcb->flags & TF_ACK_DELAY) { 01231 pcb->flags |= TF_ACK_NOW; 01232 tcp_output(pcb); 01233 } 01234 01235 if (pcb->state != LISTEN) { 01236 LWIP_ASSERT("unsent segments leaking", pcb->unsent == NULL); 01237 LWIP_ASSERT("unacked segments leaking", pcb->unacked == NULL); 01238 #if TCP_QUEUE_OOSEQ 01239 LWIP_ASSERT("ooseq segments leaking", pcb->ooseq == NULL); 01240 #endif /* TCP_QUEUE_OOSEQ */ 01241 } 01242 01243 pcb->state = CLOSED; 01244 01245 LWIP_ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane()); 01246 } 01247 01248 /** 01249 * Calculates a new initial sequence number for new connections. 01250 * 01251 * @return u32_t pseudo random sequence number 01252 */ 01253 u32_t 01254 tcp_next_iss(void) 01255 { 01256 static u32_t iss = 6510; 01257 01258 iss += tcp_ticks; /* XXX */ 01259 return iss; 01260 } 01261 01262 #if TCP_CALCULATE_EFF_SEND_MSS 01263 /** 01264 * Calcluates the effective send mss that can be used for a specific IP address 01265 * by using ip_route to determin the netif used to send to the address and 01266 * calculating the minimum of TCP_MSS and that netif's mtu (if set). 01267 */ 01268 u16_t 01269 tcp_eff_send_mss(u16_t sendmss, struct ip_addr *addr) 01270 { 01271 u16_t mss_s; 01272 struct netif *outif; 01273 01274 outif = ip_route(addr); 01275 if ((outif != NULL) && (outif->mtu != 0)) { 01276 mss_s = outif->mtu - IP_HLEN - TCP_HLEN; 01277 /* RFC 1122, chap 4.2.2.6: 01278 * Eff.snd.MSS = min(SendMSS+20, MMS_S) - TCPhdrsize - IPoptionsize 01279 * We correct for TCP options in tcp_enqueue(), and don't support 01280 * IP options 01281 */ 01282 sendmss = LWIP_MIN(sendmss, mss_s); 01283 } 01284 return sendmss; 01285 } 01286 #endif /* TCP_CALCULATE_EFF_SEND_MSS */ 01287 01288 #if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG 01289 /** 01290 * Print a tcp header for debugging purposes. 01291 * 01292 * @param tcphdr pointer to a struct tcp_hdr 01293 */ 01294 void 01295 tcp_debug_print(struct tcp_hdr *tcphdr) 01296 { 01297 LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n")); 01298 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); 01299 LWIP_DEBUGF(TCP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", 01300 ntohs(tcphdr->src), ntohs(tcphdr->dest))); 01301 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); 01302 LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (seq no)\n", 01303 ntohl(tcphdr->seqno))); 01304 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); 01305 LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (ack no)\n", 01306 ntohl(tcphdr->ackno))); 01307 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); 01308 LWIP_DEBUGF(TCP_DEBUG, ("| %2"U16_F" | |%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"| %5"U16_F" | (hdrlen, flags (", 01309 TCPH_HDRLEN(tcphdr), 01310 TCPH_FLAGS(tcphdr) >> 5 & 1, 01311 TCPH_FLAGS(tcphdr) >> 4 & 1, 01312 TCPH_FLAGS(tcphdr) >> 3 & 1, 01313 TCPH_FLAGS(tcphdr) >> 2 & 1, 01314 TCPH_FLAGS(tcphdr) >> 1 & 1, 01315 TCPH_FLAGS(tcphdr) & 1, 01316 ntohs(tcphdr->wnd))); 01317 tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); 01318 LWIP_DEBUGF(TCP_DEBUG, ("), win)\n")); 01319 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); 01320 LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04"X16_F" | %5"U16_F" | (chksum, urgp)\n", 01321 ntohs(tcphdr->chksum), ntohs(tcphdr->urgp))); 01322 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); 01323 } 01324 01325 /** 01326 * Print a tcp state for debugging purposes. 01327 * 01328 * @param s enum tcp_state to print 01329 */ 01330 void 01331 tcp_debug_print_state(enum tcp_state s) 01332 { 01333 LWIP_DEBUGF(TCP_DEBUG, ("State: ")); 01334 switch (s) { 01335 case CLOSED: 01336 LWIP_DEBUGF(TCP_DEBUG, ("CLOSED\n")); 01337 break; 01338 case LISTEN: 01339 LWIP_DEBUGF(TCP_DEBUG, ("LISTEN\n")); 01340 break; 01341 case SYN_SENT: 01342 LWIP_DEBUGF(TCP_DEBUG, ("SYN_SENT\n")); 01343 break; 01344 case SYN_RCVD: 01345 LWIP_DEBUGF(TCP_DEBUG, ("SYN_RCVD\n")); 01346 break; 01347 case ESTABLISHED: 01348 LWIP_DEBUGF(TCP_DEBUG, ("ESTABLISHED\n")); 01349 break; 01350 case FIN_WAIT_1: 01351 LWIP_DEBUGF(TCP_DEBUG, ("FIN_WAIT_1\n")); 01352 break; 01353 case FIN_WAIT_2: 01354 LWIP_DEBUGF(TCP_DEBUG, ("FIN_WAIT_2\n")); 01355 break; 01356 case CLOSE_WAIT: 01357 LWIP_DEBUGF(TCP_DEBUG, ("CLOSE_WAIT\n")); 01358 break; 01359 case CLOSING: 01360 LWIP_DEBUGF(TCP_DEBUG, ("CLOSING\n")); 01361 break; 01362 case LAST_ACK: 01363 LWIP_DEBUGF(TCP_DEBUG, ("LAST_ACK\n")); 01364 break; 01365 case TIME_WAIT: 01366 LWIP_DEBUGF(TCP_DEBUG, ("TIME_WAIT\n")); 01367 break; 01368 } 01369 } 01370 01371 /** 01372 * Print tcp flags for debugging purposes. 01373 * 01374 * @param flags tcp flags, all active flags are printed 01375 */ 01376 void 01377 tcp_debug_print_flags(u8_t flags) 01378 { 01379 if (flags & TCP_FIN) { 01380 LWIP_DEBUGF(TCP_DEBUG, ("FIN ")); 01381 } 01382 if (flags & TCP_SYN) { 01383 LWIP_DEBUGF(TCP_DEBUG, ("SYN ")); 01384 } 01385 if (flags & TCP_RST) { 01386 LWIP_DEBUGF(TCP_DEBUG, ("RST ")); 01387 } 01388 if (flags & TCP_PSH) { 01389 LWIP_DEBUGF(TCP_DEBUG, ("PSH ")); 01390 } 01391 if (flags & TCP_ACK) { 01392 LWIP_DEBUGF(TCP_DEBUG, ("ACK ")); 01393 } 01394 if (flags & TCP_URG) { 01395 LWIP_DEBUGF(TCP_DEBUG, ("URG ")); 01396 } 01397 if (flags & TCP_ECE) { 01398 LWIP_DEBUGF(TCP_DEBUG, ("ECE ")); 01399 } 01400 if (flags & TCP_CWR) { 01401 LWIP_DEBUGF(TCP_DEBUG, ("CWR ")); 01402 } 01403 } 01404 01405 /** 01406 * Print all tcp_pcbs in every list for debugging purposes. 01407 */ 01408 void 01409 tcp_debug_print_pcbs(void) 01410 { 01411 struct tcp_pcb *pcb; 01412 LWIP_DEBUGF(TCP_DEBUG, ("Active PCB states:\n")); 01413 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { 01414 LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", 01415 pcb->local_port, pcb->remote_port, 01416 pcb->snd_nxt, pcb->rcv_nxt)); 01417 tcp_debug_print_state(pcb->state); 01418 } 01419 LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n")); 01420 for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) { 01421 LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", 01422 pcb->local_port, pcb->remote_port, 01423 pcb->snd_nxt, pcb->rcv_nxt)); 01424 tcp_debug_print_state(pcb->state); 01425 } 01426 LWIP_DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n")); 01427 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { 01428 LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", 01429 pcb->local_port, pcb->remote_port, 01430 pcb->snd_nxt, pcb->rcv_nxt)); 01431 tcp_debug_print_state(pcb->state); 01432 } 01433 } 01434 01435 /** 01436 * Check state consistency of the tcp_pcb lists. 01437 */ 01438 s16_t 01439 tcp_pcbs_sane(void) 01440 { 01441 struct tcp_pcb *pcb; 01442 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { 01443 LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != CLOSED", pcb->state != CLOSED); 01444 LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != LISTEN", pcb->state != LISTEN); 01445 LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); 01446 } 01447 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { 01448 LWIP_ASSERT("tcp_pcbs_sane: tw pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); 01449 } 01450 return 1; 01451 } 01452 #endif /* TCP_DEBUG */ 01453 01454 #endif /* LWIP_TCP */
Generated on Tue Jul 12 2022 19:24:06 by
1.7.2