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