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.
Fork of F7_Ethernet by
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 #include "lwip/tcp_impl.h" 00053 #include "lwip/debug.h" 00054 #include "lwip/stats.h" 00055 00056 #include <string.h> 00057 00058 #ifndef TCP_LOCAL_PORT_RANGE_START 00059 /* From http://www.iana.org/assignments/port-numbers: 00060 "The Dynamic and/or Private Ports are those from 49152 through 65535" */ 00061 #define TCP_LOCAL_PORT_RANGE_START 0xc000 00062 #define TCP_LOCAL_PORT_RANGE_END 0xffff 00063 #define TCP_ENSURE_LOCAL_PORT_RANGE(port) (((port) & ~TCP_LOCAL_PORT_RANGE_START) + TCP_LOCAL_PORT_RANGE_START) 00064 #endif 00065 00066 #if LWIP_TCP_KEEPALIVE 00067 #define TCP_KEEP_DUR(pcb) ((pcb)->keep_cnt * (pcb)->keep_intvl) 00068 #define TCP_KEEP_INTVL(pcb) ((pcb)->keep_intvl) 00069 #else /* LWIP_TCP_KEEPALIVE */ 00070 #define TCP_KEEP_DUR(pcb) TCP_MAXIDLE 00071 #define TCP_KEEP_INTVL(pcb) TCP_KEEPINTVL_DEFAULT 00072 #endif /* LWIP_TCP_KEEPALIVE */ 00073 00074 const char * const tcp_state_str[] = { 00075 "CLOSED", 00076 "LISTEN", 00077 "SYN_SENT", 00078 "SYN_RCVD", 00079 "ESTABLISHED", 00080 "FIN_WAIT_1", 00081 "FIN_WAIT_2", 00082 "CLOSE_WAIT", 00083 "CLOSING", 00084 "LAST_ACK", 00085 "TIME_WAIT" 00086 }; 00087 00088 /* last local TCP port */ 00089 static u16_t tcp_port = TCP_LOCAL_PORT_RANGE_START; 00090 static u16_t preloaded_tcp_port=0; 00091 00092 /* Incremented every coarse grained timer shot (typically every 500 ms). */ 00093 u32_t tcp_ticks; 00094 const u8_t tcp_backoff[13] = 00095 { 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7}; 00096 /* Times per slowtmr hits */ 00097 const u8_t tcp_persist_backoff[7] = { 3, 6, 12, 24, 48, 96, 120 }; 00098 00099 /* The TCP PCB lists. */ 00100 00101 /** List of all TCP PCBs bound but not yet (connected || listening) */ 00102 struct tcp_pcb *tcp_bound_pcbs; 00103 /** List of all TCP PCBs in LISTEN state */ 00104 union tcp_listen_pcbs_t tcp_listen_pcbs; 00105 /** List of all TCP PCBs that are in a state in which 00106 * they accept or send data. */ 00107 struct tcp_pcb *tcp_active_pcbs; 00108 /** List of all TCP PCBs in TIME-WAIT state */ 00109 struct tcp_pcb *tcp_tw_pcbs; 00110 00111 #define NUM_TCP_PCB_LISTS 4 00112 #define NUM_TCP_PCB_LISTS_NO_TIME_WAIT 3 00113 /** An array with all (non-temporary) PCB lists, mainly used for smaller code size */ 00114 struct tcp_pcb ** const tcp_pcb_lists[] = {&tcp_listen_pcbs.pcbs, &tcp_bound_pcbs, 00115 &tcp_active_pcbs, &tcp_tw_pcbs}; 00116 00117 /** Only used for temporary storage. */ 00118 struct tcp_pcb *tcp_tmp_pcb; 00119 00120 u8_t tcp_active_pcbs_changed; 00121 00122 /** Timer counter to handle calling slow-timer from tcp_tmr() */ 00123 static u8_t tcp_timer; 00124 static u8_t tcp_timer_ctr; 00125 static u16_t tcp_new_port(void); 00126 00127 /** 00128 * Initialize this module. 00129 */ 00130 void 00131 tcp_init(void) 00132 { 00133 #if LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) 00134 tcp_port = TCP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND()); 00135 #endif /* LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) */ 00136 } 00137 00138 /** 00139 * Called periodically to dispatch TCP timers. 00140 */ 00141 void 00142 tcp_tmr(void) 00143 { 00144 /* Call tcp_fasttmr() every 250 ms */ 00145 tcp_fasttmr(); 00146 00147 if (++tcp_timer & 1) { 00148 /* Call tcp_tmr() every 500 ms, i.e., every other timer 00149 tcp_tmr() is called. */ 00150 tcp_slowtmr(); 00151 } 00152 } 00153 00154 /** 00155 * Closes the TX side of a connection held by the PCB. 00156 * For tcp_close(), a RST is sent if the application didn't receive all data 00157 * (tcp_recved() not called for all data passed to recv callback). 00158 * 00159 * Listening pcbs are freed and may not be referenced any more. 00160 * Connection pcbs are freed if not yet connected and may not be referenced 00161 * any more. If a connection is established (at least SYN received or in 00162 * a closing state), the connection is closed, and put in a closing state. 00163 * The pcb is then automatically freed in tcp_slowtmr(). It is therefore 00164 * unsafe to reference it. 00165 * 00166 * @param pcb the tcp_pcb to close 00167 * @return ERR_OK if connection has been closed 00168 * another err_t if closing failed and pcb is not freed 00169 */ 00170 static err_t 00171 tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data) 00172 { 00173 err_t err; 00174 00175 if (rst_on_unacked_data && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) { 00176 if ((pcb->refused_data != NULL) || (pcb->rcv_wnd != TCP_WND)) { 00177 /* Not all data received by application, send RST to tell the remote 00178 side about this. */ 00179 LWIP_ASSERT("pcb->flags & TF_RXCLOSED", pcb->flags & TF_RXCLOSED); 00180 00181 /* don't call tcp_abort here: we must not deallocate the pcb since 00182 that might not be expected when calling tcp_close */ 00183 tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip, 00184 pcb->local_port, pcb->remote_port); 00185 00186 tcp_pcb_purge(pcb); 00187 TCP_RMV_ACTIVE(pcb); 00188 if (pcb->state == ESTABLISHED) { 00189 /* move to TIME_WAIT since we close actively */ 00190 pcb->state = TIME_WAIT; 00191 TCP_REG(&tcp_tw_pcbs, pcb); 00192 } else { 00193 /* CLOSE_WAIT: deallocate the pcb since we already sent a RST for it */ 00194 memp_free(MEMP_TCP_PCB, pcb); 00195 } 00196 return ERR_OK; 00197 } 00198 } 00199 00200 switch (pcb->state) { 00201 case CLOSED: 00202 /* Closing a pcb in the CLOSED state might seem erroneous, 00203 * however, it is in this state once allocated and as yet unused 00204 * and the user needs some way to free it should the need arise. 00205 * Calling tcp_close() with a pcb that has already been closed, (i.e. twice) 00206 * or for a pcb that has been used and then entered the CLOSED state 00207 * is erroneous, but this should never happen as the pcb has in those cases 00208 * been freed, and so any remaining handles are bogus. */ 00209 err = ERR_OK; 00210 if (pcb->local_port != 0) { 00211 TCP_RMV(&tcp_bound_pcbs, pcb); 00212 } 00213 memp_free(MEMP_TCP_PCB, pcb); 00214 pcb = NULL; 00215 break; 00216 case LISTEN: 00217 err = ERR_OK; 00218 tcp_pcb_remove(&tcp_listen_pcbs.pcbs, pcb); 00219 memp_free(MEMP_TCP_PCB_LISTEN, pcb); 00220 pcb = NULL; 00221 break; 00222 case SYN_SENT: 00223 err = ERR_OK; 00224 TCP_PCB_REMOVE_ACTIVE(pcb); 00225 memp_free(MEMP_TCP_PCB, pcb); 00226 pcb = NULL; 00227 snmp_inc_tcpattemptfails(); 00228 break; 00229 case SYN_RCVD: 00230 err = tcp_send_fin(pcb); 00231 if (err == ERR_OK) { 00232 snmp_inc_tcpattemptfails(); 00233 pcb->state = FIN_WAIT_1; 00234 } 00235 break; 00236 case ESTABLISHED: 00237 err = tcp_send_fin(pcb); 00238 if (err == ERR_OK) { 00239 snmp_inc_tcpestabresets(); 00240 pcb->state = FIN_WAIT_1; 00241 } 00242 break; 00243 case CLOSE_WAIT: 00244 err = tcp_send_fin(pcb); 00245 if (err == ERR_OK) { 00246 snmp_inc_tcpestabresets(); 00247 pcb->state = LAST_ACK; 00248 } 00249 break; 00250 default: 00251 /* Has already been closed, do nothing. */ 00252 err = ERR_OK; 00253 pcb = NULL; 00254 break; 00255 } 00256 00257 if (pcb != NULL && err == ERR_OK) { 00258 /* To ensure all data has been sent when tcp_close returns, we have 00259 to make sure tcp_output doesn't fail. 00260 Since we don't really have to ensure all data has been sent when tcp_close 00261 returns (unsent data is sent from tcp timer functions, also), we don't care 00262 for the return value of tcp_output for now. */ 00263 /* @todo: When implementing SO_LINGER, this must be changed somehow: 00264 If SOF_LINGER is set, the data should be sent and acked before close returns. 00265 This can only be valid for sequential APIs, not for the raw API. */ 00266 tcp_output(pcb); 00267 } 00268 return err; 00269 } 00270 00271 /** 00272 * Closes the connection held by the PCB. 00273 * 00274 * Listening pcbs are freed and may not be referenced any more. 00275 * Connection pcbs are freed if not yet connected and may not be referenced 00276 * any more. If a connection is established (at least SYN received or in 00277 * a closing state), the connection is closed, and put in a closing state. 00278 * The pcb is then automatically freed in tcp_slowtmr(). It is therefore 00279 * unsafe to reference it (unless an error is returned). 00280 * 00281 * @param pcb the tcp_pcb to close 00282 * @return ERR_OK if connection has been closed 00283 * another err_t if closing failed and pcb is not freed 00284 */ 00285 err_t 00286 tcp_close(struct tcp_pcb *pcb) 00287 { 00288 #if TCP_DEBUG 00289 LWIP_DEBUGF(TCP_DEBUG, ("tcp_close: closing in ")); 00290 tcp_debug_print_state(pcb->state); 00291 #endif /* TCP_DEBUG */ 00292 00293 if (pcb->state != LISTEN) { 00294 /* Set a flag not to receive any more data... */ 00295 pcb->flags |= TF_RXCLOSED; 00296 } 00297 /* ... and close */ 00298 return tcp_close_shutdown(pcb, 1); 00299 } 00300 00301 /** 00302 * Causes all or part of a full-duplex connection of this PCB to be shut down. 00303 * This doesn't deallocate the PCB unless shutting down both sides! 00304 * Shutting down both sides is the same as calling tcp_close, so if it succeds, 00305 * the PCB should not be referenced any more. 00306 * 00307 * @param pcb PCB to shutdown 00308 * @param shut_rx shut down receive side if this is != 0 00309 * @param shut_tx shut down send side if this is != 0 00310 * @return ERR_OK if shutdown succeeded (or the PCB has already been shut down) 00311 * another err_t on error. 00312 */ 00313 err_t 00314 tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx) 00315 { 00316 if (pcb->state == LISTEN) { 00317 return ERR_CONN; 00318 } 00319 if (shut_rx) { 00320 /* shut down the receive side: set a flag not to receive any more data... */ 00321 pcb->flags |= TF_RXCLOSED; 00322 if (shut_tx) { 00323 /* shutting down the tx AND rx side is the same as closing for the raw API */ 00324 return tcp_close_shutdown(pcb, 1); 00325 } 00326 /* ... and free buffered data */ 00327 if (pcb->refused_data != NULL) { 00328 pbuf_free(pcb->refused_data); 00329 pcb->refused_data = NULL; 00330 } 00331 } 00332 if (shut_tx) { 00333 /* This can't happen twice since if it succeeds, the pcb's state is changed. 00334 Only close in these states as the others directly deallocate the PCB */ 00335 switch (pcb->state) { 00336 case SYN_RCVD: 00337 case ESTABLISHED: 00338 case CLOSE_WAIT: 00339 return tcp_close_shutdown(pcb, shut_rx); 00340 default: 00341 /* Not (yet?) connected, cannot shutdown the TX side as that would bring us 00342 into CLOSED state, where the PCB is deallocated. */ 00343 return ERR_CONN; 00344 } 00345 } 00346 return ERR_OK; 00347 } 00348 00349 /** 00350 * Abandons a connection and optionally sends a RST to the remote 00351 * host. Deletes the local protocol control block. This is done when 00352 * a connection is killed because of shortage of memory. 00353 * 00354 * @param pcb the tcp_pcb to abort 00355 * @param reset boolean to indicate whether a reset should be sent 00356 */ 00357 void 00358 tcp_abandon(struct tcp_pcb *pcb, int reset) 00359 { 00360 u32_t seqno, ackno; 00361 #if LWIP_CALLBACK_API 00362 tcp_err_fn errf; 00363 #endif /* LWIP_CALLBACK_API */ 00364 void *errf_arg; 00365 00366 /* pcb->state LISTEN not allowed here */ 00367 LWIP_ASSERT("don't call tcp_abort/tcp_abandon for listen-pcbs", 00368 pcb->state != LISTEN); 00369 /* Figure out on which TCP PCB list we are, and remove us. If we 00370 are in an active state, call the receive function associated with 00371 the PCB with a NULL argument, and send an RST to the remote end. */ 00372 if (pcb->state == TIME_WAIT) { 00373 tcp_pcb_remove(&tcp_tw_pcbs, pcb); 00374 memp_free(MEMP_TCP_PCB, pcb); 00375 } else { 00376 seqno = pcb->snd_nxt; 00377 ackno = pcb->rcv_nxt; 00378 #if LWIP_CALLBACK_API 00379 errf = pcb->errf; 00380 #endif /* LWIP_CALLBACK_API */ 00381 errf_arg = pcb->callback_arg; 00382 TCP_PCB_REMOVE_ACTIVE(pcb); 00383 if (pcb->unacked != NULL) { 00384 tcp_segs_free(pcb->unacked); 00385 } 00386 if (pcb->unsent != NULL) { 00387 tcp_segs_free(pcb->unsent); 00388 } 00389 #if TCP_QUEUE_OOSEQ 00390 if (pcb->ooseq != NULL) { 00391 tcp_segs_free(pcb->ooseq); 00392 } 00393 #endif /* TCP_QUEUE_OOSEQ */ 00394 if (reset) { 00395 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n")); 00396 tcp_rst(seqno, ackno, &pcb->local_ip, &pcb->remote_ip, pcb->local_port, pcb->remote_port); 00397 } 00398 memp_free(MEMP_TCP_PCB, pcb); 00399 TCP_EVENT_ERR(errf, errf_arg, ERR_ABRT); 00400 } 00401 } 00402 00403 /** 00404 * Aborts the connection by sending a RST (reset) segment to the remote 00405 * host. The pcb is deallocated. This function never fails. 00406 * 00407 * ATTENTION: When calling this from one of the TCP callbacks, make 00408 * sure you always return ERR_ABRT (and never return ERR_ABRT otherwise 00409 * or you will risk accessing deallocated memory or memory leaks! 00410 * 00411 * @param pcb the tcp pcb to abort 00412 */ 00413 void 00414 tcp_abort(struct tcp_pcb *pcb) 00415 { 00416 tcp_abandon(pcb, 1); 00417 } 00418 00419 /** 00420 * Binds the connection to a local portnumber and IP address. If the 00421 * IP address is not given (i.e., ipaddr == NULL), the IP address of 00422 * the outgoing network interface is used instead. 00423 * 00424 * @param pcb the tcp_pcb to bind (no check is done whether this pcb is 00425 * already bound!) 00426 * @param ipaddr the local ip address to bind to (use IP_ADDR_ANY to bind 00427 * to any local address 00428 * @param port the local port to bind to 00429 * @return ERR_USE if the port is already in use 00430 * ERR_VAL if bind failed because the PCB is not in a valid state 00431 * ERR_OK if bound 00432 */ 00433 err_t 00434 tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) 00435 { 00436 int i; 00437 int max_pcb_list = NUM_TCP_PCB_LISTS; 00438 struct tcp_pcb *cpcb; 00439 00440 LWIP_ERROR("tcp_bind: can only bind in state CLOSED", pcb->state == CLOSED, return ERR_VAL); 00441 00442 #if SO_REUSE 00443 /* Unless the REUSEADDR flag is set, 00444 we have to check the pcbs in TIME-WAIT state, also. 00445 We do not dump TIME_WAIT pcb's; they can still be matched by incoming 00446 packets using both local and remote IP addresses and ports to distinguish. 00447 */ 00448 if (ip_get_option(pcb, SOF_REUSEADDR)) { 00449 max_pcb_list = NUM_TCP_PCB_LISTS_NO_TIME_WAIT; 00450 } 00451 #endif /* SO_REUSE */ 00452 00453 if (port == 0) { 00454 port = tcp_new_port(); 00455 if (port == 0) { 00456 return ERR_BUF; 00457 } 00458 } 00459 00460 /* Check if the address already is in use (on all lists) */ 00461 for (i = 0; i < max_pcb_list; i++) { 00462 for(cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) { 00463 if (cpcb->local_port == port) { 00464 #if SO_REUSE 00465 /* Omit checking for the same port if both pcbs have REUSEADDR set. 00466 For SO_REUSEADDR, the duplicate-check for a 5-tuple is done in 00467 tcp_connect. */ 00468 if (!ip_get_option(pcb, SOF_REUSEADDR) || 00469 !ip_get_option(cpcb, SOF_REUSEADDR)) 00470 #endif /* SO_REUSE */ 00471 { 00472 if (ip_addr_isany(&(cpcb->local_ip)) || 00473 ip_addr_isany(ipaddr) || 00474 ip_addr_cmp(&(cpcb->local_ip), ipaddr)) { 00475 return ERR_USE; 00476 } 00477 } 00478 } 00479 } 00480 } 00481 00482 if (!ip_addr_isany(ipaddr)) { 00483 pcb->local_ip = *ipaddr; 00484 } 00485 pcb->local_port = port; 00486 TCP_REG(&tcp_bound_pcbs, pcb); 00487 LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %"U16_F"\n", port)); 00488 return ERR_OK; 00489 } 00490 #if LWIP_CALLBACK_API 00491 /** 00492 * Default accept callback if no accept callback is specified by the user. 00493 */ 00494 static err_t 00495 tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err) 00496 { 00497 LWIP_UNUSED_ARG(arg); 00498 LWIP_UNUSED_ARG(pcb); 00499 LWIP_UNUSED_ARG(err); 00500 00501 return ERR_ABRT; 00502 } 00503 #endif /* LWIP_CALLBACK_API */ 00504 00505 /** 00506 * Set the state of the connection to be LISTEN, which means that it 00507 * is able to accept incoming connections. The protocol control block 00508 * is reallocated in order to consume less memory. Setting the 00509 * connection to LISTEN is an irreversible process. 00510 * 00511 * @param pcb the original tcp_pcb 00512 * @param backlog the incoming connections queue limit 00513 * @return tcp_pcb used for listening, consumes less memory. 00514 * 00515 * @note The original tcp_pcb is freed. This function therefore has to be 00516 * called like this: 00517 * tpcb = tcp_listen(tpcb); 00518 */ 00519 struct tcp_pcb * 00520 tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) 00521 { 00522 struct tcp_pcb_listen *lpcb; 00523 00524 LWIP_UNUSED_ARG(backlog); 00525 LWIP_ERROR("tcp_listen: pcb already connected", pcb->state == CLOSED, return NULL); 00526 00527 /* already listening? */ 00528 if (pcb->state == LISTEN) { 00529 return pcb; 00530 } 00531 #if SO_REUSE 00532 if (ip_get_option(pcb, SOF_REUSEADDR)) { 00533 /* Since SOF_REUSEADDR allows reusing a local address before the pcb's usage 00534 is declared (listen-/connection-pcb), we have to make sure now that 00535 this port is only used once for every local IP. */ 00536 for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { 00537 if (lpcb->local_port == pcb->local_port) { 00538 if (ip_addr_cmp(&lpcb->local_ip, &pcb->local_ip)) { 00539 /* this address/port is already used */ 00540 return NULL; 00541 } 00542 } 00543 } 00544 } 00545 #endif /* SO_REUSE */ 00546 lpcb = (struct tcp_pcb_listen *)memp_malloc(MEMP_TCP_PCB_LISTEN); 00547 if (lpcb == NULL) { 00548 return NULL; 00549 } 00550 lpcb->callback_arg = pcb->callback_arg; 00551 lpcb->local_port = pcb->local_port; 00552 lpcb->state = LISTEN; 00553 lpcb->prio = pcb->prio; 00554 lpcb->so_options = pcb->so_options; 00555 ip_set_option(lpcb, SOF_ACCEPTCONN); 00556 lpcb->ttl = pcb->ttl; 00557 lpcb->tos = pcb->tos; 00558 ip_addr_copy(lpcb->local_ip, pcb->local_ip); 00559 if (pcb->local_port != 0) { 00560 TCP_RMV(&tcp_bound_pcbs, pcb); 00561 } 00562 memp_free(MEMP_TCP_PCB, pcb); 00563 #if LWIP_CALLBACK_API 00564 lpcb->accept = tcp_accept_null; 00565 #endif /* LWIP_CALLBACK_API */ 00566 #if TCP_LISTEN_BACKLOG 00567 lpcb->accepts_pending = 0; 00568 lpcb->backlog = (backlog ? backlog : 1); 00569 #endif /* TCP_LISTEN_BACKLOG */ 00570 TCP_REG(&tcp_listen_pcbs.pcbs, (struct tcp_pcb *)lpcb); 00571 return (struct tcp_pcb *)lpcb; 00572 } 00573 00574 /** 00575 * Update the state that tracks the available window space to advertise. 00576 * 00577 * Returns how much extra window would be advertised if we sent an 00578 * update now. 00579 */ 00580 u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb) 00581 { 00582 u32_t new_right_edge = pcb->rcv_nxt + pcb->rcv_wnd; 00583 00584 if (TCP_SEQ_GEQ(new_right_edge, pcb->rcv_ann_right_edge + LWIP_MIN((TCP_WND / 2), pcb->mss))) { 00585 /* we can advertise more window */ 00586 pcb->rcv_ann_wnd = pcb->rcv_wnd; 00587 return new_right_edge - pcb->rcv_ann_right_edge; 00588 } else { 00589 if (TCP_SEQ_GT(pcb->rcv_nxt, pcb->rcv_ann_right_edge)) { 00590 /* Can happen due to other end sending out of advertised window, 00591 * but within actual available (but not yet advertised) window */ 00592 pcb->rcv_ann_wnd = 0; 00593 } else { 00594 /* keep the right edge of window constant */ 00595 u32_t new_rcv_ann_wnd = pcb->rcv_ann_right_edge - pcb->rcv_nxt; 00596 LWIP_ASSERT("new_rcv_ann_wnd <= 0xffff", new_rcv_ann_wnd <= 0xffff); 00597 pcb->rcv_ann_wnd = (u16_t)new_rcv_ann_wnd; 00598 } 00599 return 0; 00600 } 00601 } 00602 00603 /** 00604 * This function should be called by the application when it has 00605 * processed the data. The purpose is to advertise a larger window 00606 * when the data has been processed. 00607 * 00608 * @param pcb the tcp_pcb for which data is read 00609 * @param len the amount of bytes that have been read by the application 00610 */ 00611 void 00612 tcp_recved(struct tcp_pcb *pcb, u16_t len) 00613 { 00614 int wnd_inflation; 00615 00616 /* pcb->state LISTEN not allowed here */ 00617 LWIP_ASSERT("don't call tcp_recved for listen-pcbs", 00618 pcb->state != LISTEN); 00619 LWIP_ASSERT("tcp_recved: len would wrap rcv_wnd\n", 00620 len <= 0xffff - pcb->rcv_wnd ); 00621 00622 pcb->rcv_wnd += len; 00623 if (pcb->rcv_wnd > TCP_WND) { 00624 pcb->rcv_wnd = TCP_WND; 00625 } 00626 00627 wnd_inflation = tcp_update_rcv_ann_wnd(pcb); 00628 00629 /* If the change in the right edge of window is significant (default 00630 * watermark is TCP_WND/4), then send an explicit update now. 00631 * Otherwise wait for a packet to be sent in the normal course of 00632 * events (or more window to be available later) */ 00633 if (wnd_inflation >= TCP_WND_UPDATE_THRESHOLD) { 00634 tcp_ack_now(pcb); 00635 tcp_output(pcb); 00636 } 00637 00638 LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %"U16_F" bytes, wnd %"U16_F" (%"U16_F").\n", 00639 len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd)); 00640 } 00641 /** 00642 * Preselect a tcp_port for next use 00643 * e.g. as source port 00644 */ 00645 void tcp_preselect_port(u16_t port) 00646 { 00647 preloaded_tcp_port=port; 00648 return; 00649 } 00650 00651 00652 00653 /** 00654 * Allocate a new local TCP port. 00655 * 00656 * @return a new (free) local TCP port number 00657 */ 00658 static u16_t 00659 tcp_new_port(void) 00660 { 00661 u8_t i; 00662 u16_t n = 0; 00663 struct tcp_pcb *pcb; 00664 if (preloaded_tcp_port!=0) 00665 { 00666 n=preloaded_tcp_port; 00667 preloaded_tcp_port=0; 00668 return n; 00669 } 00670 again: 00671 if (tcp_port++ == TCP_LOCAL_PORT_RANGE_END) { 00672 tcp_port = TCP_LOCAL_PORT_RANGE_START; 00673 } 00674 /* Check all PCB lists. */ 00675 for (i = 0; i < NUM_TCP_PCB_LISTS; i++) { 00676 for(pcb = *tcp_pcb_lists[i]; pcb != NULL; pcb = pcb->next) { 00677 if (pcb->local_port == tcp_port) { 00678 if (++n > (TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START)) { 00679 return 0; 00680 } 00681 goto again; 00682 } 00683 } 00684 } 00685 return tcp_port; 00686 } 00687 00688 /** 00689 * Connects to another host. The function given as the "connected" 00690 * argument will be called when the connection has been established. 00691 * 00692 * @param pcb the tcp_pcb used to establish the connection 00693 * @param ipaddr the remote ip address to connect to 00694 * @param port the remote tcp port to connect to 00695 * @param connected callback function to call when connected (or on error) 00696 * @return ERR_VAL if invalid arguments are given 00697 * ERR_OK if connect request has been sent 00698 * other err_t values if connect request couldn't be sent 00699 */ 00700 err_t 00701 tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port, 00702 tcp_connected_fn connected) 00703 { 00704 err_t ret; 00705 u32_t iss; 00706 u16_t old_local_port; 00707 00708 LWIP_ERROR("tcp_connect: can only connect from state CLOSED", pcb->state == CLOSED, return ERR_ISCONN); 00709 00710 LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port)); 00711 if (ipaddr != NULL) { 00712 pcb->remote_ip = *ipaddr; 00713 } else { 00714 return ERR_VAL; 00715 } 00716 pcb->remote_port = port; 00717 00718 /* check if we have a route to the remote host */ 00719 if (ip_addr_isany(&(pcb->local_ip))) { 00720 /* no local IP address set, yet. */ 00721 struct netif *netif = ip_route(&(pcb->remote_ip)); 00722 if (netif == NULL) { 00723 /* Don't even try to send a SYN packet if we have no route 00724 since that will fail. */ 00725 return ERR_RTE; 00726 } 00727 /* Use the netif's IP address as local address. */ 00728 ip_addr_copy(pcb->local_ip, netif->ip_addr); 00729 } 00730 00731 old_local_port = pcb->local_port; 00732 if (pcb->local_port == 0) { 00733 pcb->local_port = tcp_new_port(); 00734 if (pcb->local_port == 0) { 00735 return ERR_BUF; 00736 } 00737 } 00738 #if SO_REUSE 00739 if (ip_get_option(pcb, SOF_REUSEADDR)) { 00740 /* Since SOF_REUSEADDR allows reusing a local address, we have to make sure 00741 now that the 5-tuple is unique. */ 00742 struct tcp_pcb *cpcb; 00743 int i; 00744 /* Don't check listen- and bound-PCBs, check active- and TIME-WAIT PCBs. */ 00745 for (i = 2; i < NUM_TCP_PCB_LISTS; i++) { 00746 for(cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) { 00747 if ((cpcb->local_port == pcb->local_port) && 00748 (cpcb->remote_port == port) && 00749 ip_addr_cmp(&cpcb->local_ip, &pcb->local_ip) && 00750 ip_addr_cmp(&cpcb->remote_ip, ipaddr)) { 00751 /* linux returns EISCONN here, but ERR_USE should be OK for us */ 00752 return ERR_USE; 00753 } 00754 } 00755 } 00756 } 00757 #endif /* SO_REUSE */ 00758 iss = tcp_next_iss(); 00759 pcb->rcv_nxt = 0; 00760 pcb->snd_nxt = iss; 00761 pcb->lastack = iss - 1; 00762 pcb->snd_lbb = iss - 1; 00763 pcb->rcv_wnd = TCP_WND; 00764 pcb->rcv_ann_wnd = TCP_WND; 00765 pcb->rcv_ann_right_edge = pcb->rcv_nxt; 00766 pcb->snd_wnd = TCP_WND; 00767 /* As initial send MSS, we use TCP_MSS but limit it to 536. 00768 The send MSS is updated when an MSS option is received. */ 00769 pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS; 00770 #if TCP_CALCULATE_EFF_SEND_MSS 00771 pcb->mss = tcp_eff_send_mss(pcb->mss, ipaddr); 00772 #endif /* TCP_CALCULATE_EFF_SEND_MSS */ 00773 pcb->cwnd = 1; 00774 pcb->ssthresh = pcb->mss * 10; 00775 #if LWIP_CALLBACK_API 00776 pcb->connected = connected; 00777 #else /* LWIP_CALLBACK_API */ 00778 LWIP_UNUSED_ARG(connected); 00779 #endif /* LWIP_CALLBACK_API */ 00780 00781 /* Send a SYN together with the MSS option. */ 00782 ret = tcp_enqueue_flags(pcb, TCP_SYN); 00783 if (ret == ERR_OK) { 00784 /* SYN segment was enqueued, changed the pcbs state now */ 00785 pcb->state = SYN_SENT; 00786 if (old_local_port != 0) { 00787 TCP_RMV(&tcp_bound_pcbs, pcb); 00788 } 00789 TCP_REG_ACTIVE(pcb); 00790 snmp_inc_tcpactiveopens(); 00791 00792 tcp_output(pcb); 00793 } 00794 return ret; 00795 } 00796 00797 /** 00798 * Called every 500 ms and implements the retransmission timer and the timer that 00799 * removes PCBs that have been in TIME-WAIT for enough time. It also increments 00800 * various timers such as the inactivity timer in each PCB. 00801 * 00802 * Automatically called from tcp_tmr(). 00803 */ 00804 void 00805 tcp_slowtmr(void) 00806 { 00807 struct tcp_pcb *pcb, *prev; 00808 u16_t eff_wnd; 00809 u8_t pcb_remove; /* flag if a PCB should be removed */ 00810 u8_t pcb_reset; /* flag if a RST should be sent when removing */ 00811 err_t err; 00812 00813 err = ERR_OK; 00814 00815 ++tcp_ticks; 00816 ++tcp_timer_ctr; 00817 00818 tcp_slowtmr_start: 00819 /* Steps through all of the active PCBs. */ 00820 prev = NULL; 00821 pcb = tcp_active_pcbs; 00822 if (pcb == NULL) { 00823 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n")); 00824 } 00825 while (pcb != NULL) { 00826 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb\n")); 00827 LWIP_ASSERT("tcp_slowtmr: active pcb->state != CLOSED\n", pcb->state != CLOSED); 00828 LWIP_ASSERT("tcp_slowtmr: active pcb->state != LISTEN\n", pcb->state != LISTEN); 00829 LWIP_ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT\n", pcb->state != TIME_WAIT); 00830 if (pcb->last_timer == tcp_timer_ctr) { 00831 /* skip this pcb, we have already processed it */ 00832 pcb = pcb->next; 00833 continue; 00834 } 00835 pcb->last_timer = tcp_timer_ctr; 00836 00837 pcb_remove = 0; 00838 pcb_reset = 0; 00839 00840 if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) { 00841 ++pcb_remove; 00842 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max SYN retries reached\n")); 00843 } 00844 else if (pcb->nrtx == TCP_MAXRTX) { 00845 ++pcb_remove; 00846 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n")); 00847 } else { 00848 if (pcb->persist_backoff > 0) { 00849 /* If snd_wnd is zero, use persist timer to send 1 byte probes 00850 * instead of using the standard retransmission mechanism. */ 00851 pcb->persist_cnt++; 00852 if (pcb->persist_cnt >= tcp_persist_backoff[pcb->persist_backoff-1]) { 00853 pcb->persist_cnt = 0; 00854 if (pcb->persist_backoff < sizeof(tcp_persist_backoff)) { 00855 pcb->persist_backoff++; 00856 } 00857 tcp_zero_window_probe(pcb); 00858 } 00859 } else { 00860 /* Increase the retransmission timer if it is running */ 00861 if(pcb->rtime >= 0) { 00862 ++pcb->rtime; 00863 } 00864 00865 if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) { 00866 /* Time for a retransmission. */ 00867 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"S16_F 00868 " pcb->rto %"S16_F"\n", 00869 pcb->rtime, pcb->rto)); 00870 00871 /* Double retransmission time-out unless we are trying to 00872 * connect to somebody (i.e., we are in SYN_SENT). */ 00873 if (pcb->state != SYN_SENT) { 00874 pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx]; 00875 } 00876 00877 /* Reset the retransmission timer. */ 00878 pcb->rtime = 0; 00879 00880 /* Reduce congestion window and ssthresh. */ 00881 eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd); 00882 pcb->ssthresh = eff_wnd >> 1; 00883 if (pcb->ssthresh < (pcb->mss << 1)) { 00884 pcb->ssthresh = (pcb->mss << 1); 00885 } 00886 pcb->cwnd = pcb->mss; 00887 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"U16_F 00888 " ssthresh %"U16_F"\n", 00889 pcb->cwnd, pcb->ssthresh)); 00890 00891 /* The following needs to be called AFTER cwnd is set to one 00892 mss - STJ */ 00893 tcp_rexmit_rto(pcb); 00894 } 00895 } 00896 } 00897 /* Check if this PCB has stayed too long in FIN-WAIT-2 */ 00898 if (pcb->state == FIN_WAIT_2) { 00899 /* If this PCB is in FIN_WAIT_2 because of SHUT_WR don't let it time out. */ 00900 if (pcb->flags & TF_RXCLOSED) { 00901 /* PCB was fully closed (either through close() or SHUT_RDWR): 00902 normal FIN-WAIT timeout handling. */ 00903 if ((u32_t)(tcp_ticks - pcb->tmr) > 00904 TCP_FIN_WAIT_TIMEOUT / TCP_SLOW_INTERVAL) { 00905 ++pcb_remove; 00906 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in FIN-WAIT-2\n")); 00907 } 00908 } 00909 } 00910 00911 /* Check if KEEPALIVE should be sent */ 00912 if(ip_get_option(pcb, SOF_KEEPALIVE) && 00913 ((pcb->state == ESTABLISHED) || 00914 (pcb->state == CLOSE_WAIT))) { 00915 if((u32_t)(tcp_ticks - pcb->tmr) > 00916 (pcb->keep_idle + TCP_KEEP_DUR(pcb)) / TCP_SLOW_INTERVAL) 00917 { 00918 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %"U16_F".%"U16_F".%"U16_F".%"U16_F".\n", 00919 ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip), 00920 ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip))); 00921 00922 ++pcb_remove; 00923 ++pcb_reset; 00924 } 00925 else if((u32_t)(tcp_ticks - pcb->tmr) > 00926 (pcb->keep_idle + pcb->keep_cnt_sent * TCP_KEEP_INTVL(pcb)) 00927 / TCP_SLOW_INTERVAL) 00928 { 00929 tcp_keepalive(pcb); 00930 pcb->keep_cnt_sent++; 00931 } 00932 } 00933 00934 /* If this PCB has queued out of sequence data, but has been 00935 inactive for too long, will drop the data (it will eventually 00936 be retransmitted). */ 00937 #if TCP_QUEUE_OOSEQ 00938 if (pcb->ooseq != NULL && 00939 (u32_t)tcp_ticks - pcb->tmr >= pcb->rto * TCP_OOSEQ_TIMEOUT) { 00940 tcp_segs_free(pcb->ooseq); 00941 pcb->ooseq = NULL; 00942 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: dropping OOSEQ queued data\n")); 00943 } 00944 #endif /* TCP_QUEUE_OOSEQ */ 00945 00946 /* Check if this PCB has stayed too long in SYN-RCVD */ 00947 if (pcb->state == SYN_RCVD) { 00948 if ((u32_t)(tcp_ticks - pcb->tmr) > 00949 TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) { 00950 ++pcb_remove; 00951 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in SYN-RCVD\n")); 00952 } 00953 } 00954 00955 /* Check if this PCB has stayed too long in LAST-ACK */ 00956 if (pcb->state == LAST_ACK) { 00957 if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) { 00958 ++pcb_remove; 00959 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in LAST-ACK\n")); 00960 } 00961 } 00962 00963 /* If the PCB should be removed, do it. */ 00964 if (pcb_remove) { 00965 struct tcp_pcb *pcb2; 00966 tcp_err_fn err_fn; 00967 void *err_arg; 00968 tcp_pcb_purge(pcb); 00969 /* Remove PCB from tcp_active_pcbs list. */ 00970 if (prev != NULL) { 00971 LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_active_pcbs", pcb != tcp_active_pcbs); 00972 prev->next = pcb->next; 00973 } else { 00974 /* This PCB was the first. */ 00975 LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_active_pcbs", tcp_active_pcbs == pcb); 00976 tcp_active_pcbs = pcb->next; 00977 } 00978 00979 if (pcb_reset) { 00980 tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip, 00981 pcb->local_port, pcb->remote_port); 00982 } 00983 00984 err_fn = pcb->errf; 00985 err_arg = pcb->callback_arg; 00986 pcb2 = pcb; 00987 pcb = pcb->next; 00988 memp_free(MEMP_TCP_PCB, pcb2); 00989 00990 tcp_active_pcbs_changed = 0; 00991 TCP_EVENT_ERR(err_fn, err_arg, ERR_ABRT); 00992 if (tcp_active_pcbs_changed) { 00993 goto tcp_slowtmr_start; 00994 } 00995 } else { 00996 /* get the 'next' element now and work with 'prev' below (in case of abort) */ 00997 prev = pcb; 00998 pcb = pcb->next; 00999 01000 /* We check if we should poll the connection. */ 01001 ++prev->polltmr; 01002 if (prev->polltmr >= prev->pollinterval) { 01003 prev->polltmr = 0; 01004 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: polling application\n")); 01005 tcp_active_pcbs_changed = 0; 01006 TCP_EVENT_POLL(prev, err); 01007 if (tcp_active_pcbs_changed) { 01008 goto tcp_slowtmr_start; 01009 } 01010 /* if err == ERR_ABRT, 'prev' is already deallocated */ 01011 if (err == ERR_OK) { 01012 tcp_output(prev); 01013 } 01014 } 01015 } 01016 } 01017 01018 01019 /* Steps through all of the TIME-WAIT PCBs. */ 01020 prev = NULL; 01021 pcb = tcp_tw_pcbs; 01022 while (pcb != NULL) { 01023 LWIP_ASSERT("tcp_slowtmr: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); 01024 pcb_remove = 0; 01025 01026 /* Check if this PCB has stayed long enough in TIME-WAIT */ 01027 if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) { 01028 ++pcb_remove; 01029 } 01030 01031 01032 01033 /* If the PCB should be removed, do it. */ 01034 if (pcb_remove) { 01035 struct tcp_pcb *pcb2; 01036 tcp_pcb_purge(pcb); 01037 /* Remove PCB from tcp_tw_pcbs list. */ 01038 if (prev != NULL) { 01039 LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_tw_pcbs", pcb != tcp_tw_pcbs); 01040 prev->next = pcb->next; 01041 } else { 01042 /* This PCB was the first. */ 01043 LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_tw_pcbs", tcp_tw_pcbs == pcb); 01044 tcp_tw_pcbs = pcb->next; 01045 } 01046 pcb2 = pcb; 01047 pcb = pcb->next; 01048 memp_free(MEMP_TCP_PCB, pcb2); 01049 } else { 01050 prev = pcb; 01051 pcb = pcb->next; 01052 } 01053 } 01054 } 01055 01056 /** 01057 * Is called every TCP_FAST_INTERVAL (250 ms) and process data previously 01058 * "refused" by upper layer (application) and sends delayed ACKs. 01059 * 01060 * Automatically called from tcp_tmr(). 01061 */ 01062 void 01063 tcp_fasttmr(void) 01064 { 01065 struct tcp_pcb *pcb; 01066 01067 ++tcp_timer_ctr; 01068 01069 tcp_fasttmr_start: 01070 pcb = tcp_active_pcbs; 01071 01072 while(pcb != NULL) { 01073 if (pcb->last_timer != tcp_timer_ctr) { 01074 struct tcp_pcb *next; 01075 pcb->last_timer = tcp_timer_ctr; 01076 /* send delayed ACKs */ 01077 if (pcb->flags & TF_ACK_DELAY) { 01078 LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: delayed ACK\n")); 01079 tcp_ack_now(pcb); 01080 tcp_output(pcb); 01081 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); 01082 } 01083 01084 next = pcb->next; 01085 01086 /* If there is data which was previously "refused" by upper layer */ 01087 if (pcb->refused_data != NULL) { 01088 tcp_active_pcbs_changed = 0; 01089 tcp_process_refused_data(pcb); 01090 if (tcp_active_pcbs_changed) { 01091 /* application callback has changed the pcb list: restart the loop */ 01092 goto tcp_fasttmr_start; 01093 } 01094 } 01095 pcb = next; 01096 } 01097 } 01098 } 01099 01100 /** Pass pcb->refused_data to the recv callback */ 01101 err_t 01102 tcp_process_refused_data(struct tcp_pcb *pcb) 01103 { 01104 err_t err; 01105 u8_t refused_flags = pcb->refused_data->flags; 01106 /* set pcb->refused_data to NULL in case the callback frees it and then 01107 closes the pcb */ 01108 struct pbuf *refused_data = pcb->refused_data; 01109 pcb->refused_data = NULL; 01110 /* Notify again application with data previously received. */ 01111 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: notify kept packet\n")); 01112 TCP_EVENT_RECV(pcb, refused_data, ERR_OK, err); 01113 if (err == ERR_OK) { 01114 /* did refused_data include a FIN? */ 01115 if (refused_flags & PBUF_FLAG_TCP_FIN) { 01116 /* correct rcv_wnd as the application won't call tcp_recved() 01117 for the FIN's seqno */ 01118 if (pcb->rcv_wnd != TCP_WND) { 01119 pcb->rcv_wnd++; 01120 } 01121 TCP_EVENT_CLOSED(pcb, err); 01122 if (err == ERR_ABRT) { 01123 return ERR_ABRT; 01124 } 01125 } 01126 } else if (err == ERR_ABRT) { 01127 /* if err == ERR_ABRT, 'pcb' is already deallocated */ 01128 /* Drop incoming packets because pcb is "full" (only if the incoming 01129 segment contains data). */ 01130 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n")); 01131 return ERR_ABRT; 01132 } else { 01133 /* data is still refused, pbuf is still valid (go on for ACK-only packets) */ 01134 pcb->refused_data = refused_data; 01135 } 01136 return ERR_OK; 01137 } 01138 01139 /** 01140 * Deallocates a list of TCP segments (tcp_seg structures). 01141 * 01142 * @param seg tcp_seg list of TCP segments to free 01143 */ 01144 void 01145 tcp_segs_free(struct tcp_seg *seg) 01146 { 01147 while (seg != NULL) { 01148 struct tcp_seg *next = seg->next; 01149 tcp_seg_free(seg); 01150 seg = next; 01151 } 01152 } 01153 01154 /** 01155 * Frees a TCP segment (tcp_seg structure). 01156 * 01157 * @param seg single tcp_seg to free 01158 */ 01159 void 01160 tcp_seg_free(struct tcp_seg *seg) 01161 { 01162 if (seg != NULL) { 01163 if (seg->p != NULL) { 01164 pbuf_free(seg->p); 01165 #if TCP_DEBUG 01166 seg->p = NULL; 01167 #endif /* TCP_DEBUG */ 01168 } 01169 memp_free(MEMP_TCP_SEG, seg); 01170 } 01171 } 01172 01173 /** 01174 * Sets the priority of a connection. 01175 * 01176 * @param pcb the tcp_pcb to manipulate 01177 * @param prio new priority 01178 */ 01179 void 01180 tcp_setprio(struct tcp_pcb *pcb, u8_t prio) 01181 { 01182 pcb->prio = prio; 01183 } 01184 01185 #if TCP_QUEUE_OOSEQ 01186 /** 01187 * Returns a copy of the given TCP segment. 01188 * The pbuf and data are not copied, only the pointers 01189 * 01190 * @param seg the old tcp_seg 01191 * @return a copy of seg 01192 */ 01193 struct tcp_seg * 01194 tcp_seg_copy(struct tcp_seg *seg) 01195 { 01196 struct tcp_seg *cseg; 01197 01198 cseg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG); 01199 if (cseg == NULL) { 01200 return NULL; 01201 } 01202 SMEMCPY((u8_t *)cseg, (const u8_t *)seg, sizeof(struct tcp_seg)); 01203 pbuf_ref(cseg->p); 01204 return cseg; 01205 } 01206 #endif /* TCP_QUEUE_OOSEQ */ 01207 01208 #if LWIP_CALLBACK_API 01209 /** 01210 * Default receive callback that is called if the user didn't register 01211 * a recv callback for the pcb. 01212 */ 01213 err_t 01214 tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) 01215 { 01216 LWIP_UNUSED_ARG(arg); 01217 if (p != NULL) { 01218 tcp_recved(pcb, p->tot_len); 01219 pbuf_free(p); 01220 } else if (err == ERR_OK) { 01221 return tcp_close(pcb); 01222 } 01223 return ERR_OK; 01224 } 01225 #endif /* LWIP_CALLBACK_API */ 01226 01227 /** 01228 * Kills the oldest active connection that has the same or lower priority than 01229 * 'prio'. 01230 * 01231 * @param prio minimum priority 01232 */ 01233 static void 01234 tcp_kill_prio(u8_t prio) 01235 { 01236 struct tcp_pcb *pcb, *inactive; 01237 u32_t inactivity; 01238 u8_t mprio; 01239 01240 01241 mprio = TCP_PRIO_MAX; 01242 01243 /* We kill the oldest active connection that has lower priority than prio. */ 01244 inactivity = 0; 01245 inactive = NULL; 01246 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { 01247 if (pcb->prio <= prio && 01248 pcb->prio <= mprio && 01249 (u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { 01250 inactivity = tcp_ticks - pcb->tmr; 01251 inactive = pcb; 01252 mprio = pcb->prio; 01253 } 01254 } 01255 if (inactive != NULL) { 01256 LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%"S32_F")\n", 01257 (void *)inactive, inactivity)); 01258 tcp_abort(inactive); 01259 } 01260 } 01261 01262 /** 01263 * Kills the oldest connection that is in TIME_WAIT state. 01264 * Called from tcp_alloc() if no more connections are available. 01265 */ 01266 static void 01267 tcp_kill_timewait(void) 01268 { 01269 struct tcp_pcb *pcb, *inactive; 01270 u32_t inactivity; 01271 01272 inactivity = 0; 01273 inactive = NULL; 01274 /* Go through the list of TIME_WAIT pcbs and get the oldest pcb. */ 01275 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { 01276 if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { 01277 inactivity = tcp_ticks - pcb->tmr; 01278 inactive = pcb; 01279 } 01280 } 01281 if (inactive != NULL) { 01282 LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%"S32_F")\n", 01283 (void *)inactive, inactivity)); 01284 tcp_abort(inactive); 01285 } 01286 } 01287 01288 /** 01289 * Allocate a new tcp_pcb structure. 01290 * 01291 * @param prio priority for the new pcb 01292 * @return a new tcp_pcb that initially is in state CLOSED 01293 */ 01294 struct tcp_pcb * 01295 tcp_alloc(u8_t prio) 01296 { 01297 struct tcp_pcb *pcb; 01298 u32_t iss; 01299 01300 pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); 01301 if (pcb == NULL) { 01302 /* Try killing oldest connection in TIME-WAIT. */ 01303 LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest TIME-WAIT connection\n")); 01304 tcp_kill_timewait(); 01305 /* Try to allocate a tcp_pcb again. */ 01306 pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); 01307 if (pcb == NULL) { 01308 /* Try killing active connections with lower priority than the new one. */ 01309 LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing connection with prio lower than %d\n", prio)); 01310 tcp_kill_prio(prio); 01311 /* Try to allocate a tcp_pcb again. */ 01312 pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); 01313 if (pcb != NULL) { 01314 /* adjust err stats: memp_malloc failed twice before */ 01315 MEMP_STATS_DEC(err, MEMP_TCP_PCB); 01316 } 01317 } 01318 if (pcb != NULL) { 01319 /* adjust err stats: timewait PCB was freed above */ 01320 MEMP_STATS_DEC(err, MEMP_TCP_PCB); 01321 } 01322 } 01323 if (pcb != NULL) { 01324 memset(pcb, 0, sizeof(struct tcp_pcb)); 01325 pcb->prio = prio; 01326 pcb->snd_buf = TCP_SND_BUF; 01327 pcb->snd_queuelen = 0; 01328 pcb->rcv_wnd = TCP_WND; 01329 pcb->rcv_ann_wnd = TCP_WND; 01330 pcb->tos = 0; 01331 pcb->ttl = TCP_TTL; 01332 /* As initial send MSS, we use TCP_MSS but limit it to 536. 01333 The send MSS is updated when an MSS option is received. */ 01334 pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS; 01335 pcb->rto = 3000 / TCP_SLOW_INTERVAL; 01336 pcb->sa = 0; 01337 pcb->sv = 3000 / TCP_SLOW_INTERVAL; 01338 pcb->rtime = -1; 01339 pcb->cwnd = 1; 01340 iss = tcp_next_iss(); 01341 pcb->snd_wl2 = iss; 01342 pcb->snd_nxt = iss; 01343 pcb->lastack = iss; 01344 pcb->snd_lbb = iss; 01345 pcb->tmr = tcp_ticks; 01346 pcb->last_timer = tcp_timer_ctr; 01347 01348 pcb->polltmr = 0; 01349 01350 #if LWIP_CALLBACK_API 01351 pcb->recv = tcp_recv_null; 01352 #endif /* LWIP_CALLBACK_API */ 01353 01354 /* Init KEEPALIVE timer */ 01355 pcb->keep_idle = TCP_KEEPIDLE_DEFAULT; 01356 01357 #if LWIP_TCP_KEEPALIVE 01358 pcb->keep_intvl = TCP_KEEPINTVL_DEFAULT; 01359 pcb->keep_cnt = TCP_KEEPCNT_DEFAULT; 01360 #endif /* LWIP_TCP_KEEPALIVE */ 01361 01362 pcb->keep_cnt_sent = 0; 01363 } 01364 return pcb; 01365 } 01366 01367 /** 01368 * Creates a new TCP protocol control block but doesn't place it on 01369 * any of the TCP PCB lists. 01370 * The pcb is not put on any list until binding using tcp_bind(). 01371 * 01372 * @internal: Maybe there should be a idle TCP PCB list where these 01373 * PCBs are put on. Port reservation using tcp_bind() is implemented but 01374 * allocated pcbs that are not bound can't be killed automatically if wanting 01375 * to allocate a pcb with higher prio (@see tcp_kill_prio()) 01376 * 01377 * @return a new tcp_pcb that initially is in state CLOSED 01378 */ 01379 struct tcp_pcb * 01380 tcp_new(void) 01381 { 01382 return tcp_alloc(TCP_PRIO_NORMAL); 01383 } 01384 01385 /** 01386 * Used to specify the argument that should be passed callback 01387 * functions. 01388 * 01389 * @param pcb tcp_pcb to set the callback argument 01390 * @param arg void pointer argument to pass to callback functions 01391 */ 01392 void 01393 tcp_arg(struct tcp_pcb *pcb, void *arg) 01394 { 01395 /* This function is allowed to be called for both listen pcbs and 01396 connection pcbs. */ 01397 pcb->callback_arg = arg; 01398 } 01399 #if LWIP_CALLBACK_API 01400 01401 /** 01402 * Used to specify the function that should be called when a TCP 01403 * connection receives data. 01404 * 01405 * @param pcb tcp_pcb to set the recv callback 01406 * @param recv callback function to call for this pcb when data is received 01407 */ 01408 void 01409 tcp_recv(struct tcp_pcb *pcb, tcp_recv_fn recv) 01410 { 01411 LWIP_ASSERT("invalid socket state for recv callback", pcb->state != LISTEN); 01412 pcb->recv = recv; 01413 } 01414 01415 /** 01416 * Used to specify the function that should be called when TCP data 01417 * has been successfully delivered to the remote host. 01418 * 01419 * @param pcb tcp_pcb to set the sent callback 01420 * @param sent callback function to call for this pcb when data is successfully sent 01421 */ 01422 void 01423 tcp_sent(struct tcp_pcb *pcb, tcp_sent_fn sent) 01424 { 01425 LWIP_ASSERT("invalid socket state for sent callback", pcb->state != LISTEN); 01426 pcb->sent = sent; 01427 } 01428 01429 /** 01430 * Used to specify the function that should be called when a fatal error 01431 * has occured on the connection. 01432 * 01433 * @param pcb tcp_pcb to set the err callback 01434 * @param err callback function to call for this pcb when a fatal error 01435 * has occured on the connection 01436 */ 01437 void 01438 tcp_err(struct tcp_pcb *pcb, tcp_err_fn err) 01439 { 01440 LWIP_ASSERT("invalid socket state for err callback", pcb->state != LISTEN); 01441 pcb->errf = err; 01442 } 01443 01444 /** 01445 * Used for specifying the function that should be called when a 01446 * LISTENing connection has been connected to another host. 01447 * 01448 * @param pcb tcp_pcb to set the accept callback 01449 * @param accept callback function to call for this pcb when LISTENing 01450 * connection has been connected to another host 01451 */ 01452 void 01453 tcp_accept(struct tcp_pcb *pcb, tcp_accept_fn accept) 01454 { 01455 /* This function is allowed to be called for both listen pcbs and 01456 connection pcbs. */ 01457 pcb->accept = accept; 01458 } 01459 #endif /* LWIP_CALLBACK_API */ 01460 01461 01462 /** 01463 * Used to specify the function that should be called periodically 01464 * from TCP. The interval is specified in terms of the TCP coarse 01465 * timer interval, which is called twice a second. 01466 * 01467 */ 01468 void 01469 tcp_poll(struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval) 01470 { 01471 LWIP_ASSERT("invalid socket state for poll", pcb->state != LISTEN); 01472 #if LWIP_CALLBACK_API 01473 pcb->poll = poll; 01474 #else /* LWIP_CALLBACK_API */ 01475 LWIP_UNUSED_ARG(poll); 01476 #endif /* LWIP_CALLBACK_API */ 01477 pcb->pollinterval = interval; 01478 } 01479 01480 /** 01481 * Purges a TCP PCB. Removes any buffered data and frees the buffer memory 01482 * (pcb->ooseq, pcb->unsent and pcb->unacked are freed). 01483 * 01484 * @param pcb tcp_pcb to purge. The pcb itself is not deallocated! 01485 */ 01486 void 01487 tcp_pcb_purge(struct tcp_pcb *pcb) 01488 { 01489 if (pcb->state != CLOSED && 01490 pcb->state != TIME_WAIT && 01491 pcb->state != LISTEN) { 01492 01493 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n")); 01494 01495 #if TCP_LISTEN_BACKLOG 01496 if (pcb->state == SYN_RCVD) { 01497 /* Need to find the corresponding listen_pcb and decrease its accepts_pending */ 01498 struct tcp_pcb_listen *lpcb; 01499 LWIP_ASSERT("tcp_pcb_purge: pcb->state == SYN_RCVD but tcp_listen_pcbs is NULL", 01500 tcp_listen_pcbs.listen_pcbs != NULL); 01501 for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { 01502 if ((lpcb->local_port == pcb->local_port) && 01503 (ip_addr_isany(&lpcb->local_ip) || 01504 ip_addr_cmp(&pcb->local_ip, &lpcb->local_ip))) { 01505 /* port and address of the listen pcb match the timed-out pcb */ 01506 LWIP_ASSERT("tcp_pcb_purge: listen pcb does not have accepts pending", 01507 lpcb->accepts_pending > 0); 01508 lpcb->accepts_pending--; 01509 break; 01510 } 01511 } 01512 } 01513 #endif /* TCP_LISTEN_BACKLOG */ 01514 01515 01516 if (pcb->refused_data != NULL) { 01517 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->refused_data\n")); 01518 pbuf_free(pcb->refused_data); 01519 pcb->refused_data = NULL; 01520 } 01521 if (pcb->unsent != NULL) { 01522 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: not all data sent\n")); 01523 } 01524 if (pcb->unacked != NULL) { 01525 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->unacked\n")); 01526 } 01527 #if TCP_QUEUE_OOSEQ 01528 if (pcb->ooseq != NULL) { 01529 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->ooseq\n")); 01530 } 01531 tcp_segs_free(pcb->ooseq); 01532 pcb->ooseq = NULL; 01533 #endif /* TCP_QUEUE_OOSEQ */ 01534 01535 /* Stop the retransmission timer as it will expect data on unacked 01536 queue if it fires */ 01537 pcb->rtime = -1; 01538 01539 tcp_segs_free(pcb->unsent); 01540 tcp_segs_free(pcb->unacked); 01541 pcb->unacked = pcb->unsent = NULL; 01542 #if TCP_OVERSIZE 01543 pcb->unsent_oversize = 0; 01544 #endif /* TCP_OVERSIZE */ 01545 } 01546 } 01547 01548 /** 01549 * Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first. 01550 * 01551 * @param pcblist PCB list to purge. 01552 * @param pcb tcp_pcb to purge. The pcb itself is NOT deallocated! 01553 */ 01554 void 01555 tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb) 01556 { 01557 TCP_RMV(pcblist, pcb); 01558 01559 tcp_pcb_purge(pcb); 01560 01561 /* if there is an outstanding delayed ACKs, send it */ 01562 if (pcb->state != TIME_WAIT && 01563 pcb->state != LISTEN && 01564 pcb->flags & TF_ACK_DELAY) { 01565 pcb->flags |= TF_ACK_NOW; 01566 tcp_output(pcb); 01567 } 01568 01569 if (pcb->state != LISTEN) { 01570 LWIP_ASSERT("unsent segments leaking", pcb->unsent == NULL); 01571 LWIP_ASSERT("unacked segments leaking", pcb->unacked == NULL); 01572 #if TCP_QUEUE_OOSEQ 01573 LWIP_ASSERT("ooseq segments leaking", pcb->ooseq == NULL); 01574 #endif /* TCP_QUEUE_OOSEQ */ 01575 } 01576 01577 pcb->state = CLOSED; 01578 01579 LWIP_ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane()); 01580 } 01581 01582 /** 01583 * Calculates a new initial sequence number for new connections. 01584 * 01585 * @return u32_t pseudo random sequence number 01586 */ 01587 u32_t 01588 tcp_next_iss(void) 01589 { 01590 static u32_t iss = 6510; 01591 01592 iss += tcp_ticks; /* XXX */ 01593 return iss; 01594 } 01595 01596 #if TCP_CALCULATE_EFF_SEND_MSS 01597 /** 01598 * Calcluates the effective send mss that can be used for a specific IP address 01599 * by using ip_route to determin the netif used to send to the address and 01600 * calculating the minimum of TCP_MSS and that netif's mtu (if set). 01601 */ 01602 u16_t 01603 tcp_eff_send_mss(u16_t sendmss, ip_addr_t *addr) 01604 { 01605 u16_t mss_s; 01606 struct netif *outif; 01607 01608 outif = ip_route(addr); 01609 if ((outif != NULL) && (outif->mtu != 0)) { 01610 mss_s = outif->mtu - IP_HLEN - TCP_HLEN; 01611 /* RFC 1122, chap 4.2.2.6: 01612 * Eff.snd.MSS = min(SendMSS+20, MMS_S) - TCPhdrsize - IPoptionsize 01613 * We correct for TCP options in tcp_write(), and don't support IP options. 01614 */ 01615 sendmss = LWIP_MIN(sendmss, mss_s); 01616 } 01617 return sendmss; 01618 } 01619 #endif /* TCP_CALCULATE_EFF_SEND_MSS */ 01620 01621 const char* 01622 tcp_debug_state_str(enum tcp_state s) 01623 { 01624 return tcp_state_str[s]; 01625 } 01626 01627 #if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG 01628 /** 01629 * Print a tcp header for debugging purposes. 01630 * 01631 * @param tcphdr pointer to a struct tcp_hdr 01632 */ 01633 void 01634 tcp_debug_print(struct tcp_hdr *tcphdr) 01635 { 01636 LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n")); 01637 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); 01638 LWIP_DEBUGF(TCP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", 01639 ntohs(tcphdr->src), ntohs(tcphdr->dest))); 01640 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); 01641 LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (seq no)\n", 01642 ntohl(tcphdr->seqno))); 01643 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); 01644 LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (ack no)\n", 01645 ntohl(tcphdr->ackno))); 01646 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); 01647 LWIP_DEBUGF(TCP_DEBUG, ("| %2"U16_F" | |%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"| %5"U16_F" | (hdrlen, flags (", 01648 TCPH_HDRLEN(tcphdr), 01649 TCPH_FLAGS(tcphdr) >> 5 & 1, 01650 TCPH_FLAGS(tcphdr) >> 4 & 1, 01651 TCPH_FLAGS(tcphdr) >> 3 & 1, 01652 TCPH_FLAGS(tcphdr) >> 2 & 1, 01653 TCPH_FLAGS(tcphdr) >> 1 & 1, 01654 TCPH_FLAGS(tcphdr) & 1, 01655 ntohs(tcphdr->wnd))); 01656 tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); 01657 LWIP_DEBUGF(TCP_DEBUG, ("), win)\n")); 01658 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); 01659 LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04"X16_F" | %5"U16_F" | (chksum, urgp)\n", 01660 ntohs(tcphdr->chksum), ntohs(tcphdr->urgp))); 01661 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); 01662 } 01663 01664 /** 01665 * Print a tcp state for debugging purposes. 01666 * 01667 * @param s enum tcp_state to print 01668 */ 01669 void 01670 tcp_debug_print_state(enum tcp_state s) 01671 { 01672 LWIP_DEBUGF(TCP_DEBUG, ("State: %s\n", tcp_state_str[s])); 01673 } 01674 01675 /** 01676 * Print tcp flags for debugging purposes. 01677 * 01678 * @param flags tcp flags, all active flags are printed 01679 */ 01680 void 01681 tcp_debug_print_flags(u8_t flags) 01682 { 01683 if (flags & TCP_FIN) { 01684 LWIP_DEBUGF(TCP_DEBUG, ("FIN ")); 01685 } 01686 if (flags & TCP_SYN) { 01687 LWIP_DEBUGF(TCP_DEBUG, ("SYN ")); 01688 } 01689 if (flags & TCP_RST) { 01690 LWIP_DEBUGF(TCP_DEBUG, ("RST ")); 01691 } 01692 if (flags & TCP_PSH) { 01693 LWIP_DEBUGF(TCP_DEBUG, ("PSH ")); 01694 } 01695 if (flags & TCP_ACK) { 01696 LWIP_DEBUGF(TCP_DEBUG, ("ACK ")); 01697 } 01698 if (flags & TCP_URG) { 01699 LWIP_DEBUGF(TCP_DEBUG, ("URG ")); 01700 } 01701 if (flags & TCP_ECE) { 01702 LWIP_DEBUGF(TCP_DEBUG, ("ECE ")); 01703 } 01704 if (flags & TCP_CWR) { 01705 LWIP_DEBUGF(TCP_DEBUG, ("CWR ")); 01706 } 01707 LWIP_DEBUGF(TCP_DEBUG, ("\n")); 01708 } 01709 01710 /** 01711 * Print all tcp_pcbs in every list for debugging purposes. 01712 */ 01713 void 01714 tcp_debug_print_pcbs(void) 01715 { 01716 struct tcp_pcb *pcb; 01717 LWIP_DEBUGF(TCP_DEBUG, ("Active PCB states:\n")); 01718 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { 01719 LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", 01720 pcb->local_port, pcb->remote_port, 01721 pcb->snd_nxt, pcb->rcv_nxt)); 01722 tcp_debug_print_state(pcb->state); 01723 } 01724 LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n")); 01725 for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) { 01726 LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", 01727 pcb->local_port, pcb->remote_port, 01728 pcb->snd_nxt, pcb->rcv_nxt)); 01729 tcp_debug_print_state(pcb->state); 01730 } 01731 LWIP_DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n")); 01732 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { 01733 LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", 01734 pcb->local_port, pcb->remote_port, 01735 pcb->snd_nxt, pcb->rcv_nxt)); 01736 tcp_debug_print_state(pcb->state); 01737 } 01738 } 01739 01740 /** 01741 * Check state consistency of the tcp_pcb lists. 01742 */ 01743 s16_t 01744 tcp_pcbs_sane(void) 01745 { 01746 struct tcp_pcb *pcb; 01747 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { 01748 LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != CLOSED", pcb->state != CLOSED); 01749 LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != LISTEN", pcb->state != LISTEN); 01750 LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); 01751 } 01752 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { 01753 LWIP_ASSERT("tcp_pcbs_sane: tw pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); 01754 } 01755 return 1; 01756 } 01757 #endif /* TCP_DEBUG */ 01758 01759 #endif /* LWIP_TCP */
Generated on Wed Jul 13 2022 02:45:41 by
1.7.2
