Ethernet for Nucleo and Disco board STM32F746 works with gcc and arm. IAC is untested
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 Tue Jul 12 2022 21:19:02 by 1.7.2