A version of LWIP, provided for backwards compatibility.

Dependents:   AA_DemoBoard DemoBoard HelloServerDemo DemoBoard_RangeIndicator ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers tcp.c Source File

tcp.c

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