Official mbed lwIP library (version 1.4.0)

Dependents:   LwIPNetworking NetServicesMin EthernetInterface EthernetInterface_RSF ... more

Legacy Networking Libraries

This is an mbed 2 networking library. For mbed OS 5, lwip has been integrated with built-in networking interfaces. The networking libraries have been revised to better support additional network stacks and thread safety here.

This library is based on the code of lwIP v1.4.0

Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
All rights reserved. 

Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
   derived from this software without specific prior written permission. 

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
OF SUCH DAMAGE.
Committer:
mbed_official
Date:
Fri Jun 22 09:25:39 2012 +0000
Revision:
0:51ac1d130fd4
Initial import from lwip-1.4.0: http://download.savannah.gnu.org/releases/lwip/lwip-1.4.0.zip

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 0:51ac1d130fd4 1 /**
mbed_official 0:51ac1d130fd4 2 * @file
mbed_official 0:51ac1d130fd4 3 * Transmission Control Protocol for IP
mbed_official 0:51ac1d130fd4 4 *
mbed_official 0:51ac1d130fd4 5 * This file contains common functions for the TCP implementation, such as functinos
mbed_official 0:51ac1d130fd4 6 * for manipulating the data structures and the TCP timer functions. TCP functions
mbed_official 0:51ac1d130fd4 7 * related to input and output is found in tcp_in.c and tcp_out.c respectively.
mbed_official 0:51ac1d130fd4 8 *
mbed_official 0:51ac1d130fd4 9 */
mbed_official 0:51ac1d130fd4 10
mbed_official 0:51ac1d130fd4 11 /*
mbed_official 0:51ac1d130fd4 12 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
mbed_official 0:51ac1d130fd4 13 * All rights reserved.
mbed_official 0:51ac1d130fd4 14 *
mbed_official 0:51ac1d130fd4 15 * Redistribution and use in source and binary forms, with or without modification,
mbed_official 0:51ac1d130fd4 16 * are permitted provided that the following conditions are met:
mbed_official 0:51ac1d130fd4 17 *
mbed_official 0:51ac1d130fd4 18 * 1. Redistributions of source code must retain the above copyright notice,
mbed_official 0:51ac1d130fd4 19 * this list of conditions and the following disclaimer.
mbed_official 0:51ac1d130fd4 20 * 2. Redistributions in binary form must reproduce the above copyright notice,
mbed_official 0:51ac1d130fd4 21 * this list of conditions and the following disclaimer in the documentation
mbed_official 0:51ac1d130fd4 22 * and/or other materials provided with the distribution.
mbed_official 0:51ac1d130fd4 23 * 3. The name of the author may not be used to endorse or promote products
mbed_official 0:51ac1d130fd4 24 * derived from this software without specific prior written permission.
mbed_official 0:51ac1d130fd4 25 *
mbed_official 0:51ac1d130fd4 26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
mbed_official 0:51ac1d130fd4 27 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
mbed_official 0:51ac1d130fd4 28 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
mbed_official 0:51ac1d130fd4 29 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
mbed_official 0:51ac1d130fd4 30 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
mbed_official 0:51ac1d130fd4 31 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
mbed_official 0:51ac1d130fd4 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
mbed_official 0:51ac1d130fd4 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
mbed_official 0:51ac1d130fd4 34 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
mbed_official 0:51ac1d130fd4 35 * OF SUCH DAMAGE.
mbed_official 0:51ac1d130fd4 36 *
mbed_official 0:51ac1d130fd4 37 * This file is part of the lwIP TCP/IP stack.
mbed_official 0:51ac1d130fd4 38 *
mbed_official 0:51ac1d130fd4 39 * Author: Adam Dunkels <adam@sics.se>
mbed_official 0:51ac1d130fd4 40 *
mbed_official 0:51ac1d130fd4 41 */
mbed_official 0:51ac1d130fd4 42
mbed_official 0:51ac1d130fd4 43 #include "lwip/opt.h"
mbed_official 0:51ac1d130fd4 44
mbed_official 0:51ac1d130fd4 45 #if LWIP_TCP /* don't build if not configured for use in lwipopts.h */
mbed_official 0:51ac1d130fd4 46
mbed_official 0:51ac1d130fd4 47 #include "lwip/def.h"
mbed_official 0:51ac1d130fd4 48 #include "lwip/mem.h"
mbed_official 0:51ac1d130fd4 49 #include "lwip/memp.h"
mbed_official 0:51ac1d130fd4 50 #include "lwip/snmp.h"
mbed_official 0:51ac1d130fd4 51 #include "lwip/tcp.h"
mbed_official 0:51ac1d130fd4 52 #include "lwip/tcp_impl.h"
mbed_official 0:51ac1d130fd4 53 #include "lwip/debug.h"
mbed_official 0:51ac1d130fd4 54 #include "lwip/stats.h"
mbed_official 0:51ac1d130fd4 55
mbed_official 0:51ac1d130fd4 56 #include <string.h>
mbed_official 0:51ac1d130fd4 57
mbed_official 0:51ac1d130fd4 58 const char * const tcp_state_str[] = {
mbed_official 0:51ac1d130fd4 59 "CLOSED",
mbed_official 0:51ac1d130fd4 60 "LISTEN",
mbed_official 0:51ac1d130fd4 61 "SYN_SENT",
mbed_official 0:51ac1d130fd4 62 "SYN_RCVD",
mbed_official 0:51ac1d130fd4 63 "ESTABLISHED",
mbed_official 0:51ac1d130fd4 64 "FIN_WAIT_1",
mbed_official 0:51ac1d130fd4 65 "FIN_WAIT_2",
mbed_official 0:51ac1d130fd4 66 "CLOSE_WAIT",
mbed_official 0:51ac1d130fd4 67 "CLOSING",
mbed_official 0:51ac1d130fd4 68 "LAST_ACK",
mbed_official 0:51ac1d130fd4 69 "TIME_WAIT"
mbed_official 0:51ac1d130fd4 70 };
mbed_official 0:51ac1d130fd4 71
mbed_official 0:51ac1d130fd4 72 /* Incremented every coarse grained timer shot (typically every 500 ms). */
mbed_official 0:51ac1d130fd4 73 u32_t tcp_ticks;
mbed_official 0:51ac1d130fd4 74 const u8_t tcp_backoff[13] =
mbed_official 0:51ac1d130fd4 75 { 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7};
mbed_official 0:51ac1d130fd4 76 /* Times per slowtmr hits */
mbed_official 0:51ac1d130fd4 77 const u8_t tcp_persist_backoff[7] = { 3, 6, 12, 24, 48, 96, 120 };
mbed_official 0:51ac1d130fd4 78
mbed_official 0:51ac1d130fd4 79 /* The TCP PCB lists. */
mbed_official 0:51ac1d130fd4 80
mbed_official 0:51ac1d130fd4 81 /** List of all TCP PCBs bound but not yet (connected || listening) */
mbed_official 0:51ac1d130fd4 82 struct tcp_pcb *tcp_bound_pcbs;
mbed_official 0:51ac1d130fd4 83 /** List of all TCP PCBs in LISTEN state */
mbed_official 0:51ac1d130fd4 84 union tcp_listen_pcbs_t tcp_listen_pcbs;
mbed_official 0:51ac1d130fd4 85 /** List of all TCP PCBs that are in a state in which
mbed_official 0:51ac1d130fd4 86 * they accept or send data. */
mbed_official 0:51ac1d130fd4 87 struct tcp_pcb *tcp_active_pcbs;
mbed_official 0:51ac1d130fd4 88 /** List of all TCP PCBs in TIME-WAIT state */
mbed_official 0:51ac1d130fd4 89 struct tcp_pcb *tcp_tw_pcbs;
mbed_official 0:51ac1d130fd4 90
mbed_official 0:51ac1d130fd4 91 #define NUM_TCP_PCB_LISTS 4
mbed_official 0:51ac1d130fd4 92 #define NUM_TCP_PCB_LISTS_NO_TIME_WAIT 3
mbed_official 0:51ac1d130fd4 93 /** An array with all (non-temporary) PCB lists, mainly used for smaller code size */
mbed_official 0:51ac1d130fd4 94 struct tcp_pcb ** const tcp_pcb_lists[] = {&tcp_listen_pcbs.pcbs, &tcp_bound_pcbs,
mbed_official 0:51ac1d130fd4 95 &tcp_active_pcbs, &tcp_tw_pcbs};
mbed_official 0:51ac1d130fd4 96
mbed_official 0:51ac1d130fd4 97 /** Only used for temporary storage. */
mbed_official 0:51ac1d130fd4 98 struct tcp_pcb *tcp_tmp_pcb;
mbed_official 0:51ac1d130fd4 99
mbed_official 0:51ac1d130fd4 100 /** Timer counter to handle calling slow-timer from tcp_tmr() */
mbed_official 0:51ac1d130fd4 101 static u8_t tcp_timer;
mbed_official 0:51ac1d130fd4 102 static u16_t tcp_new_port(void);
mbed_official 0:51ac1d130fd4 103
mbed_official 0:51ac1d130fd4 104 /**
mbed_official 0:51ac1d130fd4 105 * Called periodically to dispatch TCP timers.
mbed_official 0:51ac1d130fd4 106 *
mbed_official 0:51ac1d130fd4 107 */
mbed_official 0:51ac1d130fd4 108 void
mbed_official 0:51ac1d130fd4 109 tcp_tmr(void)
mbed_official 0:51ac1d130fd4 110 {
mbed_official 0:51ac1d130fd4 111 /* Call tcp_fasttmr() every 250 ms */
mbed_official 0:51ac1d130fd4 112 tcp_fasttmr();
mbed_official 0:51ac1d130fd4 113
mbed_official 0:51ac1d130fd4 114 if (++tcp_timer & 1) {
mbed_official 0:51ac1d130fd4 115 /* Call tcp_tmr() every 500 ms, i.e., every other timer
mbed_official 0:51ac1d130fd4 116 tcp_tmr() is called. */
mbed_official 0:51ac1d130fd4 117 tcp_slowtmr();
mbed_official 0:51ac1d130fd4 118 }
mbed_official 0:51ac1d130fd4 119 }
mbed_official 0:51ac1d130fd4 120
mbed_official 0:51ac1d130fd4 121 /**
mbed_official 0:51ac1d130fd4 122 * Closes the TX side of a connection held by the PCB.
mbed_official 0:51ac1d130fd4 123 * For tcp_close(), a RST is sent if the application didn't receive all data
mbed_official 0:51ac1d130fd4 124 * (tcp_recved() not called for all data passed to recv callback).
mbed_official 0:51ac1d130fd4 125 *
mbed_official 0:51ac1d130fd4 126 * Listening pcbs are freed and may not be referenced any more.
mbed_official 0:51ac1d130fd4 127 * Connection pcbs are freed if not yet connected and may not be referenced
mbed_official 0:51ac1d130fd4 128 * any more. If a connection is established (at least SYN received or in
mbed_official 0:51ac1d130fd4 129 * a closing state), the connection is closed, and put in a closing state.
mbed_official 0:51ac1d130fd4 130 * The pcb is then automatically freed in tcp_slowtmr(). It is therefore
mbed_official 0:51ac1d130fd4 131 * unsafe to reference it.
mbed_official 0:51ac1d130fd4 132 *
mbed_official 0:51ac1d130fd4 133 * @param pcb the tcp_pcb to close
mbed_official 0:51ac1d130fd4 134 * @return ERR_OK if connection has been closed
mbed_official 0:51ac1d130fd4 135 * another err_t if closing failed and pcb is not freed
mbed_official 0:51ac1d130fd4 136 */
mbed_official 0:51ac1d130fd4 137 static err_t
mbed_official 0:51ac1d130fd4 138 tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data)
mbed_official 0:51ac1d130fd4 139 {
mbed_official 0:51ac1d130fd4 140 err_t err;
mbed_official 0:51ac1d130fd4 141
mbed_official 0:51ac1d130fd4 142 if (rst_on_unacked_data && (pcb->state != LISTEN)) {
mbed_official 0:51ac1d130fd4 143 if ((pcb->refused_data != NULL) || (pcb->rcv_wnd != TCP_WND)) {
mbed_official 0:51ac1d130fd4 144 /* Not all data received by application, send RST to tell the remote
mbed_official 0:51ac1d130fd4 145 side about this. */
mbed_official 0:51ac1d130fd4 146 LWIP_ASSERT("pcb->flags & TF_RXCLOSED", pcb->flags & TF_RXCLOSED);
mbed_official 0:51ac1d130fd4 147
mbed_official 0:51ac1d130fd4 148 /* don't call tcp_abort here: we must not deallocate the pcb since
mbed_official 0:51ac1d130fd4 149 that might not be expected when calling tcp_close */
mbed_official 0:51ac1d130fd4 150 tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip,
mbed_official 0:51ac1d130fd4 151 pcb->local_port, pcb->remote_port);
mbed_official 0:51ac1d130fd4 152
mbed_official 0:51ac1d130fd4 153 tcp_pcb_purge(pcb);
mbed_official 0:51ac1d130fd4 154
mbed_official 0:51ac1d130fd4 155 /* TODO: to which state do we move now? */
mbed_official 0:51ac1d130fd4 156
mbed_official 0:51ac1d130fd4 157 /* move to TIME_WAIT since we close actively */
mbed_official 0:51ac1d130fd4 158 TCP_RMV(&tcp_active_pcbs, pcb);
mbed_official 0:51ac1d130fd4 159 pcb->state = TIME_WAIT;
mbed_official 0:51ac1d130fd4 160 TCP_REG(&tcp_tw_pcbs, pcb);
mbed_official 0:51ac1d130fd4 161
mbed_official 0:51ac1d130fd4 162 return ERR_OK;
mbed_official 0:51ac1d130fd4 163 }
mbed_official 0:51ac1d130fd4 164 }
mbed_official 0:51ac1d130fd4 165
mbed_official 0:51ac1d130fd4 166 switch (pcb->state) {
mbed_official 0:51ac1d130fd4 167 case CLOSED:
mbed_official 0:51ac1d130fd4 168 /* Closing a pcb in the CLOSED state might seem erroneous,
mbed_official 0:51ac1d130fd4 169 * however, it is in this state once allocated and as yet unused
mbed_official 0:51ac1d130fd4 170 * and the user needs some way to free it should the need arise.
mbed_official 0:51ac1d130fd4 171 * Calling tcp_close() with a pcb that has already been closed, (i.e. twice)
mbed_official 0:51ac1d130fd4 172 * or for a pcb that has been used and then entered the CLOSED state
mbed_official 0:51ac1d130fd4 173 * is erroneous, but this should never happen as the pcb has in those cases
mbed_official 0:51ac1d130fd4 174 * been freed, and so any remaining handles are bogus. */
mbed_official 0:51ac1d130fd4 175 err = ERR_OK;
mbed_official 0:51ac1d130fd4 176 if (pcb->local_port != 0) {
mbed_official 0:51ac1d130fd4 177 TCP_RMV(&tcp_bound_pcbs, pcb);
mbed_official 0:51ac1d130fd4 178 }
mbed_official 0:51ac1d130fd4 179 memp_free(MEMP_TCP_PCB, pcb);
mbed_official 0:51ac1d130fd4 180 pcb = NULL;
mbed_official 0:51ac1d130fd4 181 break;
mbed_official 0:51ac1d130fd4 182 case LISTEN:
mbed_official 0:51ac1d130fd4 183 err = ERR_OK;
mbed_official 0:51ac1d130fd4 184 tcp_pcb_remove(&tcp_listen_pcbs.pcbs, pcb);
mbed_official 0:51ac1d130fd4 185 memp_free(MEMP_TCP_PCB_LISTEN, pcb);
mbed_official 0:51ac1d130fd4 186 pcb = NULL;
mbed_official 0:51ac1d130fd4 187 break;
mbed_official 0:51ac1d130fd4 188 case SYN_SENT:
mbed_official 0:51ac1d130fd4 189 err = ERR_OK;
mbed_official 0:51ac1d130fd4 190 tcp_pcb_remove(&tcp_active_pcbs, pcb);
mbed_official 0:51ac1d130fd4 191 memp_free(MEMP_TCP_PCB, pcb);
mbed_official 0:51ac1d130fd4 192 pcb = NULL;
mbed_official 0:51ac1d130fd4 193 snmp_inc_tcpattemptfails();
mbed_official 0:51ac1d130fd4 194 break;
mbed_official 0:51ac1d130fd4 195 case SYN_RCVD:
mbed_official 0:51ac1d130fd4 196 err = tcp_send_fin(pcb);
mbed_official 0:51ac1d130fd4 197 if (err == ERR_OK) {
mbed_official 0:51ac1d130fd4 198 snmp_inc_tcpattemptfails();
mbed_official 0:51ac1d130fd4 199 pcb->state = FIN_WAIT_1;
mbed_official 0:51ac1d130fd4 200 }
mbed_official 0:51ac1d130fd4 201 break;
mbed_official 0:51ac1d130fd4 202 case ESTABLISHED:
mbed_official 0:51ac1d130fd4 203 err = tcp_send_fin(pcb);
mbed_official 0:51ac1d130fd4 204 if (err == ERR_OK) {
mbed_official 0:51ac1d130fd4 205 snmp_inc_tcpestabresets();
mbed_official 0:51ac1d130fd4 206 pcb->state = FIN_WAIT_1;
mbed_official 0:51ac1d130fd4 207 }
mbed_official 0:51ac1d130fd4 208 break;
mbed_official 0:51ac1d130fd4 209 case CLOSE_WAIT:
mbed_official 0:51ac1d130fd4 210 err = tcp_send_fin(pcb);
mbed_official 0:51ac1d130fd4 211 if (err == ERR_OK) {
mbed_official 0:51ac1d130fd4 212 snmp_inc_tcpestabresets();
mbed_official 0:51ac1d130fd4 213 pcb->state = LAST_ACK;
mbed_official 0:51ac1d130fd4 214 }
mbed_official 0:51ac1d130fd4 215 break;
mbed_official 0:51ac1d130fd4 216 default:
mbed_official 0:51ac1d130fd4 217 /* Has already been closed, do nothing. */
mbed_official 0:51ac1d130fd4 218 err = ERR_OK;
mbed_official 0:51ac1d130fd4 219 pcb = NULL;
mbed_official 0:51ac1d130fd4 220 break;
mbed_official 0:51ac1d130fd4 221 }
mbed_official 0:51ac1d130fd4 222
mbed_official 0:51ac1d130fd4 223 if (pcb != NULL && err == ERR_OK) {
mbed_official 0:51ac1d130fd4 224 /* To ensure all data has been sent when tcp_close returns, we have
mbed_official 0:51ac1d130fd4 225 to make sure tcp_output doesn't fail.
mbed_official 0:51ac1d130fd4 226 Since we don't really have to ensure all data has been sent when tcp_close
mbed_official 0:51ac1d130fd4 227 returns (unsent data is sent from tcp timer functions, also), we don't care
mbed_official 0:51ac1d130fd4 228 for the return value of tcp_output for now. */
mbed_official 0:51ac1d130fd4 229 /* @todo: When implementing SO_LINGER, this must be changed somehow:
mbed_official 0:51ac1d130fd4 230 If SOF_LINGER is set, the data should be sent and acked before close returns.
mbed_official 0:51ac1d130fd4 231 This can only be valid for sequential APIs, not for the raw API. */
mbed_official 0:51ac1d130fd4 232 tcp_output(pcb);
mbed_official 0:51ac1d130fd4 233 }
mbed_official 0:51ac1d130fd4 234 return err;
mbed_official 0:51ac1d130fd4 235 }
mbed_official 0:51ac1d130fd4 236
mbed_official 0:51ac1d130fd4 237 /**
mbed_official 0:51ac1d130fd4 238 * Closes the connection held by the PCB.
mbed_official 0:51ac1d130fd4 239 *
mbed_official 0:51ac1d130fd4 240 * Listening pcbs are freed and may not be referenced any more.
mbed_official 0:51ac1d130fd4 241 * Connection pcbs are freed if not yet connected and may not be referenced
mbed_official 0:51ac1d130fd4 242 * any more. If a connection is established (at least SYN received or in
mbed_official 0:51ac1d130fd4 243 * a closing state), the connection is closed, and put in a closing state.
mbed_official 0:51ac1d130fd4 244 * The pcb is then automatically freed in tcp_slowtmr(). It is therefore
mbed_official 0:51ac1d130fd4 245 * unsafe to reference it (unless an error is returned).
mbed_official 0:51ac1d130fd4 246 *
mbed_official 0:51ac1d130fd4 247 * @param pcb the tcp_pcb to close
mbed_official 0:51ac1d130fd4 248 * @return ERR_OK if connection has been closed
mbed_official 0:51ac1d130fd4 249 * another err_t if closing failed and pcb is not freed
mbed_official 0:51ac1d130fd4 250 */
mbed_official 0:51ac1d130fd4 251 err_t
mbed_official 0:51ac1d130fd4 252 tcp_close(struct tcp_pcb *pcb)
mbed_official 0:51ac1d130fd4 253 {
mbed_official 0:51ac1d130fd4 254 #if TCP_DEBUG
mbed_official 0:51ac1d130fd4 255 LWIP_DEBUGF(TCP_DEBUG, ("tcp_close: closing in "));
mbed_official 0:51ac1d130fd4 256 tcp_debug_print_state(pcb->state);
mbed_official 0:51ac1d130fd4 257 #endif /* TCP_DEBUG */
mbed_official 0:51ac1d130fd4 258
mbed_official 0:51ac1d130fd4 259 if (pcb->state != LISTEN) {
mbed_official 0:51ac1d130fd4 260 /* Set a flag not to receive any more data... */
mbed_official 0:51ac1d130fd4 261 pcb->flags |= TF_RXCLOSED;
mbed_official 0:51ac1d130fd4 262 }
mbed_official 0:51ac1d130fd4 263 /* ... and close */
mbed_official 0:51ac1d130fd4 264 return tcp_close_shutdown(pcb, 1);
mbed_official 0:51ac1d130fd4 265 }
mbed_official 0:51ac1d130fd4 266
mbed_official 0:51ac1d130fd4 267 /**
mbed_official 0:51ac1d130fd4 268 * Causes all or part of a full-duplex connection of this PCB to be shut down.
mbed_official 0:51ac1d130fd4 269 * This doesn't deallocate the PCB!
mbed_official 0:51ac1d130fd4 270 *
mbed_official 0:51ac1d130fd4 271 * @param pcb PCB to shutdown
mbed_official 0:51ac1d130fd4 272 * @param shut_rx shut down receive side if this is != 0
mbed_official 0:51ac1d130fd4 273 * @param shut_tx shut down send side if this is != 0
mbed_official 0:51ac1d130fd4 274 * @return ERR_OK if shutdown succeeded (or the PCB has already been shut down)
mbed_official 0:51ac1d130fd4 275 * another err_t on error.
mbed_official 0:51ac1d130fd4 276 */
mbed_official 0:51ac1d130fd4 277 err_t
mbed_official 0:51ac1d130fd4 278 tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx)
mbed_official 0:51ac1d130fd4 279 {
mbed_official 0:51ac1d130fd4 280 if (pcb->state == LISTEN) {
mbed_official 0:51ac1d130fd4 281 return ERR_CONN;
mbed_official 0:51ac1d130fd4 282 }
mbed_official 0:51ac1d130fd4 283 if (shut_rx) {
mbed_official 0:51ac1d130fd4 284 /* shut down the receive side: free buffered data... */
mbed_official 0:51ac1d130fd4 285 if (pcb->refused_data != NULL) {
mbed_official 0:51ac1d130fd4 286 pbuf_free(pcb->refused_data);
mbed_official 0:51ac1d130fd4 287 pcb->refused_data = NULL;
mbed_official 0:51ac1d130fd4 288 }
mbed_official 0:51ac1d130fd4 289 /* ... and set a flag not to receive any more data */
mbed_official 0:51ac1d130fd4 290 pcb->flags |= TF_RXCLOSED;
mbed_official 0:51ac1d130fd4 291 }
mbed_official 0:51ac1d130fd4 292 if (shut_tx) {
mbed_official 0:51ac1d130fd4 293 /* This can't happen twice since if it succeeds, the pcb's state is changed.
mbed_official 0:51ac1d130fd4 294 Only close in these states as the others directly deallocate the PCB */
mbed_official 0:51ac1d130fd4 295 switch (pcb->state) {
mbed_official 0:51ac1d130fd4 296 case SYN_RCVD:
mbed_official 0:51ac1d130fd4 297 case ESTABLISHED:
mbed_official 0:51ac1d130fd4 298 case CLOSE_WAIT:
mbed_official 0:51ac1d130fd4 299 return tcp_close_shutdown(pcb, 0);
mbed_official 0:51ac1d130fd4 300 default:
mbed_official 0:51ac1d130fd4 301 /* don't shut down other states */
mbed_official 0:51ac1d130fd4 302 break;
mbed_official 0:51ac1d130fd4 303 }
mbed_official 0:51ac1d130fd4 304 }
mbed_official 0:51ac1d130fd4 305 /* @todo: return another err_t if not in correct state or already shut? */
mbed_official 0:51ac1d130fd4 306 return ERR_OK;
mbed_official 0:51ac1d130fd4 307 }
mbed_official 0:51ac1d130fd4 308
mbed_official 0:51ac1d130fd4 309 /**
mbed_official 0:51ac1d130fd4 310 * Abandons a connection and optionally sends a RST to the remote
mbed_official 0:51ac1d130fd4 311 * host. Deletes the local protocol control block. This is done when
mbed_official 0:51ac1d130fd4 312 * a connection is killed because of shortage of memory.
mbed_official 0:51ac1d130fd4 313 *
mbed_official 0:51ac1d130fd4 314 * @param pcb the tcp_pcb to abort
mbed_official 0:51ac1d130fd4 315 * @param reset boolean to indicate whether a reset should be sent
mbed_official 0:51ac1d130fd4 316 */
mbed_official 0:51ac1d130fd4 317 void
mbed_official 0:51ac1d130fd4 318 tcp_abandon(struct tcp_pcb *pcb, int reset)
mbed_official 0:51ac1d130fd4 319 {
mbed_official 0:51ac1d130fd4 320 u32_t seqno, ackno;
mbed_official 0:51ac1d130fd4 321 u16_t remote_port, local_port;
mbed_official 0:51ac1d130fd4 322 ip_addr_t remote_ip, local_ip;
mbed_official 0:51ac1d130fd4 323 #if LWIP_CALLBACK_API
mbed_official 0:51ac1d130fd4 324 tcp_err_fn errf;
mbed_official 0:51ac1d130fd4 325 #endif /* LWIP_CALLBACK_API */
mbed_official 0:51ac1d130fd4 326 void *errf_arg;
mbed_official 0:51ac1d130fd4 327
mbed_official 0:51ac1d130fd4 328 /* pcb->state LISTEN not allowed here */
mbed_official 0:51ac1d130fd4 329 LWIP_ASSERT("don't call tcp_abort/tcp_abandon for listen-pcbs",
mbed_official 0:51ac1d130fd4 330 pcb->state != LISTEN);
mbed_official 0:51ac1d130fd4 331 /* Figure out on which TCP PCB list we are, and remove us. If we
mbed_official 0:51ac1d130fd4 332 are in an active state, call the receive function associated with
mbed_official 0:51ac1d130fd4 333 the PCB with a NULL argument, and send an RST to the remote end. */
mbed_official 0:51ac1d130fd4 334 if (pcb->state == TIME_WAIT) {
mbed_official 0:51ac1d130fd4 335 tcp_pcb_remove(&tcp_tw_pcbs, pcb);
mbed_official 0:51ac1d130fd4 336 memp_free(MEMP_TCP_PCB, pcb);
mbed_official 0:51ac1d130fd4 337 } else {
mbed_official 0:51ac1d130fd4 338 seqno = pcb->snd_nxt;
mbed_official 0:51ac1d130fd4 339 ackno = pcb->rcv_nxt;
mbed_official 0:51ac1d130fd4 340 ip_addr_copy(local_ip, pcb->local_ip);
mbed_official 0:51ac1d130fd4 341 ip_addr_copy(remote_ip, pcb->remote_ip);
mbed_official 0:51ac1d130fd4 342 local_port = pcb->local_port;
mbed_official 0:51ac1d130fd4 343 remote_port = pcb->remote_port;
mbed_official 0:51ac1d130fd4 344 #if LWIP_CALLBACK_API
mbed_official 0:51ac1d130fd4 345 errf = pcb->errf;
mbed_official 0:51ac1d130fd4 346 #endif /* LWIP_CALLBACK_API */
mbed_official 0:51ac1d130fd4 347 errf_arg = pcb->callback_arg;
mbed_official 0:51ac1d130fd4 348 tcp_pcb_remove(&tcp_active_pcbs, pcb);
mbed_official 0:51ac1d130fd4 349 if (pcb->unacked != NULL) {
mbed_official 0:51ac1d130fd4 350 tcp_segs_free(pcb->unacked);
mbed_official 0:51ac1d130fd4 351 }
mbed_official 0:51ac1d130fd4 352 if (pcb->unsent != NULL) {
mbed_official 0:51ac1d130fd4 353 tcp_segs_free(pcb->unsent);
mbed_official 0:51ac1d130fd4 354 }
mbed_official 0:51ac1d130fd4 355 #if TCP_QUEUE_OOSEQ
mbed_official 0:51ac1d130fd4 356 if (pcb->ooseq != NULL) {
mbed_official 0:51ac1d130fd4 357 tcp_segs_free(pcb->ooseq);
mbed_official 0:51ac1d130fd4 358 }
mbed_official 0:51ac1d130fd4 359 #endif /* TCP_QUEUE_OOSEQ */
mbed_official 0:51ac1d130fd4 360 memp_free(MEMP_TCP_PCB, pcb);
mbed_official 0:51ac1d130fd4 361 TCP_EVENT_ERR(errf, errf_arg, ERR_ABRT);
mbed_official 0:51ac1d130fd4 362 if (reset) {
mbed_official 0:51ac1d130fd4 363 LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n"));
mbed_official 0:51ac1d130fd4 364 tcp_rst(seqno, ackno, &local_ip, &remote_ip, local_port, remote_port);
mbed_official 0:51ac1d130fd4 365 }
mbed_official 0:51ac1d130fd4 366 }
mbed_official 0:51ac1d130fd4 367 }
mbed_official 0:51ac1d130fd4 368
mbed_official 0:51ac1d130fd4 369 /**
mbed_official 0:51ac1d130fd4 370 * Aborts the connection by sending a RST (reset) segment to the remote
mbed_official 0:51ac1d130fd4 371 * host. The pcb is deallocated. This function never fails.
mbed_official 0:51ac1d130fd4 372 *
mbed_official 0:51ac1d130fd4 373 * ATTENTION: When calling this from one of the TCP callbacks, make
mbed_official 0:51ac1d130fd4 374 * sure you always return ERR_ABRT (and never return ERR_ABRT otherwise
mbed_official 0:51ac1d130fd4 375 * or you will risk accessing deallocated memory or memory leaks!
mbed_official 0:51ac1d130fd4 376 *
mbed_official 0:51ac1d130fd4 377 * @param pcb the tcp pcb to abort
mbed_official 0:51ac1d130fd4 378 */
mbed_official 0:51ac1d130fd4 379 void
mbed_official 0:51ac1d130fd4 380 tcp_abort(struct tcp_pcb *pcb)
mbed_official 0:51ac1d130fd4 381 {
mbed_official 0:51ac1d130fd4 382 tcp_abandon(pcb, 1);
mbed_official 0:51ac1d130fd4 383 }
mbed_official 0:51ac1d130fd4 384
mbed_official 0:51ac1d130fd4 385 /**
mbed_official 0:51ac1d130fd4 386 * Binds the connection to a local portnumber and IP address. If the
mbed_official 0:51ac1d130fd4 387 * IP address is not given (i.e., ipaddr == NULL), the IP address of
mbed_official 0:51ac1d130fd4 388 * the outgoing network interface is used instead.
mbed_official 0:51ac1d130fd4 389 *
mbed_official 0:51ac1d130fd4 390 * @param pcb the tcp_pcb to bind (no check is done whether this pcb is
mbed_official 0:51ac1d130fd4 391 * already bound!)
mbed_official 0:51ac1d130fd4 392 * @param ipaddr the local ip address to bind to (use IP_ADDR_ANY to bind
mbed_official 0:51ac1d130fd4 393 * to any local address
mbed_official 0:51ac1d130fd4 394 * @param port the local port to bind to
mbed_official 0:51ac1d130fd4 395 * @return ERR_USE if the port is already in use
mbed_official 0:51ac1d130fd4 396 * ERR_VAL if bind failed because the PCB is not in a valid state
mbed_official 0:51ac1d130fd4 397 * ERR_OK if bound
mbed_official 0:51ac1d130fd4 398 */
mbed_official 0:51ac1d130fd4 399 err_t
mbed_official 0:51ac1d130fd4 400 tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
mbed_official 0:51ac1d130fd4 401 {
mbed_official 0:51ac1d130fd4 402 int i;
mbed_official 0:51ac1d130fd4 403 int max_pcb_list = NUM_TCP_PCB_LISTS;
mbed_official 0:51ac1d130fd4 404 struct tcp_pcb *cpcb;
mbed_official 0:51ac1d130fd4 405
mbed_official 0:51ac1d130fd4 406 LWIP_ERROR("tcp_bind: can only bind in state CLOSED", pcb->state == CLOSED, return ERR_VAL);
mbed_official 0:51ac1d130fd4 407
mbed_official 0:51ac1d130fd4 408 #if SO_REUSE
mbed_official 0:51ac1d130fd4 409 /* Unless the REUSEADDR flag is set,
mbed_official 0:51ac1d130fd4 410 we have to check the pcbs in TIME-WAIT state, also.
mbed_official 0:51ac1d130fd4 411 We do not dump TIME_WAIT pcb's; they can still be matched by incoming
mbed_official 0:51ac1d130fd4 412 packets using both local and remote IP addresses and ports to distinguish.
mbed_official 0:51ac1d130fd4 413 */
mbed_official 0:51ac1d130fd4 414 if ((pcb->so_options & SOF_REUSEADDR) != 0) {
mbed_official 0:51ac1d130fd4 415 max_pcb_list = NUM_TCP_PCB_LISTS_NO_TIME_WAIT;
mbed_official 0:51ac1d130fd4 416 }
mbed_official 0:51ac1d130fd4 417 #endif /* SO_REUSE */
mbed_official 0:51ac1d130fd4 418
mbed_official 0:51ac1d130fd4 419 if (port == 0) {
mbed_official 0:51ac1d130fd4 420 port = tcp_new_port();
mbed_official 0:51ac1d130fd4 421 }
mbed_official 0:51ac1d130fd4 422
mbed_official 0:51ac1d130fd4 423 /* Check if the address already is in use (on all lists) */
mbed_official 0:51ac1d130fd4 424 for (i = 0; i < max_pcb_list; i++) {
mbed_official 0:51ac1d130fd4 425 for(cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) {
mbed_official 0:51ac1d130fd4 426 if (cpcb->local_port == port) {
mbed_official 0:51ac1d130fd4 427 #if SO_REUSE
mbed_official 0:51ac1d130fd4 428 /* Omit checking for the same port if both pcbs have REUSEADDR set.
mbed_official 0:51ac1d130fd4 429 For SO_REUSEADDR, the duplicate-check for a 5-tuple is done in
mbed_official 0:51ac1d130fd4 430 tcp_connect. */
mbed_official 0:51ac1d130fd4 431 if (((pcb->so_options & SOF_REUSEADDR) == 0) ||
mbed_official 0:51ac1d130fd4 432 ((cpcb->so_options & SOF_REUSEADDR) == 0))
mbed_official 0:51ac1d130fd4 433 #endif /* SO_REUSE */
mbed_official 0:51ac1d130fd4 434 {
mbed_official 0:51ac1d130fd4 435 if (ip_addr_isany(&(cpcb->local_ip)) ||
mbed_official 0:51ac1d130fd4 436 ip_addr_isany(ipaddr) ||
mbed_official 0:51ac1d130fd4 437 ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
mbed_official 0:51ac1d130fd4 438 return ERR_USE;
mbed_official 0:51ac1d130fd4 439 }
mbed_official 0:51ac1d130fd4 440 }
mbed_official 0:51ac1d130fd4 441 }
mbed_official 0:51ac1d130fd4 442 }
mbed_official 0:51ac1d130fd4 443 }
mbed_official 0:51ac1d130fd4 444
mbed_official 0:51ac1d130fd4 445 if (!ip_addr_isany(ipaddr)) {
mbed_official 0:51ac1d130fd4 446 pcb->local_ip = *ipaddr;
mbed_official 0:51ac1d130fd4 447 }
mbed_official 0:51ac1d130fd4 448 pcb->local_port = port;
mbed_official 0:51ac1d130fd4 449 TCP_REG(&tcp_bound_pcbs, pcb);
mbed_official 0:51ac1d130fd4 450 LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %"U16_F"\n", port));
mbed_official 0:51ac1d130fd4 451 return ERR_OK;
mbed_official 0:51ac1d130fd4 452 }
mbed_official 0:51ac1d130fd4 453 #if LWIP_CALLBACK_API
mbed_official 0:51ac1d130fd4 454 /**
mbed_official 0:51ac1d130fd4 455 * Default accept callback if no accept callback is specified by the user.
mbed_official 0:51ac1d130fd4 456 */
mbed_official 0:51ac1d130fd4 457 static err_t
mbed_official 0:51ac1d130fd4 458 tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err)
mbed_official 0:51ac1d130fd4 459 {
mbed_official 0:51ac1d130fd4 460 LWIP_UNUSED_ARG(arg);
mbed_official 0:51ac1d130fd4 461 LWIP_UNUSED_ARG(pcb);
mbed_official 0:51ac1d130fd4 462 LWIP_UNUSED_ARG(err);
mbed_official 0:51ac1d130fd4 463
mbed_official 0:51ac1d130fd4 464 return ERR_ABRT;
mbed_official 0:51ac1d130fd4 465 }
mbed_official 0:51ac1d130fd4 466 #endif /* LWIP_CALLBACK_API */
mbed_official 0:51ac1d130fd4 467
mbed_official 0:51ac1d130fd4 468 /**
mbed_official 0:51ac1d130fd4 469 * Set the state of the connection to be LISTEN, which means that it
mbed_official 0:51ac1d130fd4 470 * is able to accept incoming connections. The protocol control block
mbed_official 0:51ac1d130fd4 471 * is reallocated in order to consume less memory. Setting the
mbed_official 0:51ac1d130fd4 472 * connection to LISTEN is an irreversible process.
mbed_official 0:51ac1d130fd4 473 *
mbed_official 0:51ac1d130fd4 474 * @param pcb the original tcp_pcb
mbed_official 0:51ac1d130fd4 475 * @param backlog the incoming connections queue limit
mbed_official 0:51ac1d130fd4 476 * @return tcp_pcb used for listening, consumes less memory.
mbed_official 0:51ac1d130fd4 477 *
mbed_official 0:51ac1d130fd4 478 * @note The original tcp_pcb is freed. This function therefore has to be
mbed_official 0:51ac1d130fd4 479 * called like this:
mbed_official 0:51ac1d130fd4 480 * tpcb = tcp_listen(tpcb);
mbed_official 0:51ac1d130fd4 481 */
mbed_official 0:51ac1d130fd4 482 struct tcp_pcb *
mbed_official 0:51ac1d130fd4 483 tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
mbed_official 0:51ac1d130fd4 484 {
mbed_official 0:51ac1d130fd4 485 struct tcp_pcb_listen *lpcb;
mbed_official 0:51ac1d130fd4 486
mbed_official 0:51ac1d130fd4 487 LWIP_UNUSED_ARG(backlog);
mbed_official 0:51ac1d130fd4 488 LWIP_ERROR("tcp_listen: pcb already connected", pcb->state == CLOSED, return NULL);
mbed_official 0:51ac1d130fd4 489
mbed_official 0:51ac1d130fd4 490 /* already listening? */
mbed_official 0:51ac1d130fd4 491 if (pcb->state == LISTEN) {
mbed_official 0:51ac1d130fd4 492 return pcb;
mbed_official 0:51ac1d130fd4 493 }
mbed_official 0:51ac1d130fd4 494 #if SO_REUSE
mbed_official 0:51ac1d130fd4 495 if ((pcb->so_options & SOF_REUSEADDR) != 0) {
mbed_official 0:51ac1d130fd4 496 /* Since SOF_REUSEADDR allows reusing a local address before the pcb's usage
mbed_official 0:51ac1d130fd4 497 is declared (listen-/connection-pcb), we have to make sure now that
mbed_official 0:51ac1d130fd4 498 this port is only used once for every local IP. */
mbed_official 0:51ac1d130fd4 499 for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
mbed_official 0:51ac1d130fd4 500 if (lpcb->local_port == pcb->local_port) {
mbed_official 0:51ac1d130fd4 501 if (ip_addr_cmp(&lpcb->local_ip, &pcb->local_ip)) {
mbed_official 0:51ac1d130fd4 502 /* this address/port is already used */
mbed_official 0:51ac1d130fd4 503 return NULL;
mbed_official 0:51ac1d130fd4 504 }
mbed_official 0:51ac1d130fd4 505 }
mbed_official 0:51ac1d130fd4 506 }
mbed_official 0:51ac1d130fd4 507 }
mbed_official 0:51ac1d130fd4 508 #endif /* SO_REUSE */
mbed_official 0:51ac1d130fd4 509 lpcb = (struct tcp_pcb_listen *)memp_malloc(MEMP_TCP_PCB_LISTEN);
mbed_official 0:51ac1d130fd4 510 if (lpcb == NULL) {
mbed_official 0:51ac1d130fd4 511 return NULL;
mbed_official 0:51ac1d130fd4 512 }
mbed_official 0:51ac1d130fd4 513 lpcb->callback_arg = pcb->callback_arg;
mbed_official 0:51ac1d130fd4 514 lpcb->local_port = pcb->local_port;
mbed_official 0:51ac1d130fd4 515 lpcb->state = LISTEN;
mbed_official 0:51ac1d130fd4 516 lpcb->prio = pcb->prio;
mbed_official 0:51ac1d130fd4 517 lpcb->so_options = pcb->so_options;
mbed_official 0:51ac1d130fd4 518 lpcb->so_options |= SOF_ACCEPTCONN;
mbed_official 0:51ac1d130fd4 519 lpcb->ttl = pcb->ttl;
mbed_official 0:51ac1d130fd4 520 lpcb->tos = pcb->tos;
mbed_official 0:51ac1d130fd4 521 ip_addr_copy(lpcb->local_ip, pcb->local_ip);
mbed_official 0:51ac1d130fd4 522 if (pcb->local_port != 0) {
mbed_official 0:51ac1d130fd4 523 TCP_RMV(&tcp_bound_pcbs, pcb);
mbed_official 0:51ac1d130fd4 524 }
mbed_official 0:51ac1d130fd4 525 memp_free(MEMP_TCP_PCB, pcb);
mbed_official 0:51ac1d130fd4 526 #if LWIP_CALLBACK_API
mbed_official 0:51ac1d130fd4 527 lpcb->accept = tcp_accept_null;
mbed_official 0:51ac1d130fd4 528 #endif /* LWIP_CALLBACK_API */
mbed_official 0:51ac1d130fd4 529 #if TCP_LISTEN_BACKLOG
mbed_official 0:51ac1d130fd4 530 lpcb->accepts_pending = 0;
mbed_official 0:51ac1d130fd4 531 lpcb->backlog = (backlog ? backlog : 1);
mbed_official 0:51ac1d130fd4 532 #endif /* TCP_LISTEN_BACKLOG */
mbed_official 0:51ac1d130fd4 533 TCP_REG(&tcp_listen_pcbs.pcbs, (struct tcp_pcb *)lpcb);
mbed_official 0:51ac1d130fd4 534 return (struct tcp_pcb *)lpcb;
mbed_official 0:51ac1d130fd4 535 }
mbed_official 0:51ac1d130fd4 536
mbed_official 0:51ac1d130fd4 537 /**
mbed_official 0:51ac1d130fd4 538 * Update the state that tracks the available window space to advertise.
mbed_official 0:51ac1d130fd4 539 *
mbed_official 0:51ac1d130fd4 540 * Returns how much extra window would be advertised if we sent an
mbed_official 0:51ac1d130fd4 541 * update now.
mbed_official 0:51ac1d130fd4 542 */
mbed_official 0:51ac1d130fd4 543 u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb)
mbed_official 0:51ac1d130fd4 544 {
mbed_official 0:51ac1d130fd4 545 u32_t new_right_edge = pcb->rcv_nxt + pcb->rcv_wnd;
mbed_official 0:51ac1d130fd4 546
mbed_official 0:51ac1d130fd4 547 if (TCP_SEQ_GEQ(new_right_edge, pcb->rcv_ann_right_edge + LWIP_MIN((TCP_WND / 2), pcb->mss))) {
mbed_official 0:51ac1d130fd4 548 /* we can advertise more window */
mbed_official 0:51ac1d130fd4 549 pcb->rcv_ann_wnd = pcb->rcv_wnd;
mbed_official 0:51ac1d130fd4 550 return new_right_edge - pcb->rcv_ann_right_edge;
mbed_official 0:51ac1d130fd4 551 } else {
mbed_official 0:51ac1d130fd4 552 if (TCP_SEQ_GT(pcb->rcv_nxt, pcb->rcv_ann_right_edge)) {
mbed_official 0:51ac1d130fd4 553 /* Can happen due to other end sending out of advertised window,
mbed_official 0:51ac1d130fd4 554 * but within actual available (but not yet advertised) window */
mbed_official 0:51ac1d130fd4 555 pcb->rcv_ann_wnd = 0;
mbed_official 0:51ac1d130fd4 556 } else {
mbed_official 0:51ac1d130fd4 557 /* keep the right edge of window constant */
mbed_official 0:51ac1d130fd4 558 u32_t new_rcv_ann_wnd = pcb->rcv_ann_right_edge - pcb->rcv_nxt;
mbed_official 0:51ac1d130fd4 559 LWIP_ASSERT("new_rcv_ann_wnd <= 0xffff", new_rcv_ann_wnd <= 0xffff);
mbed_official 0:51ac1d130fd4 560 pcb->rcv_ann_wnd = (u16_t)new_rcv_ann_wnd;
mbed_official 0:51ac1d130fd4 561 }
mbed_official 0:51ac1d130fd4 562 return 0;
mbed_official 0:51ac1d130fd4 563 }
mbed_official 0:51ac1d130fd4 564 }
mbed_official 0:51ac1d130fd4 565
mbed_official 0:51ac1d130fd4 566 /**
mbed_official 0:51ac1d130fd4 567 * This function should be called by the application when it has
mbed_official 0:51ac1d130fd4 568 * processed the data. The purpose is to advertise a larger window
mbed_official 0:51ac1d130fd4 569 * when the data has been processed.
mbed_official 0:51ac1d130fd4 570 *
mbed_official 0:51ac1d130fd4 571 * @param pcb the tcp_pcb for which data is read
mbed_official 0:51ac1d130fd4 572 * @param len the amount of bytes that have been read by the application
mbed_official 0:51ac1d130fd4 573 */
mbed_official 0:51ac1d130fd4 574 void
mbed_official 0:51ac1d130fd4 575 tcp_recved(struct tcp_pcb *pcb, u16_t len)
mbed_official 0:51ac1d130fd4 576 {
mbed_official 0:51ac1d130fd4 577 int wnd_inflation;
mbed_official 0:51ac1d130fd4 578
mbed_official 0:51ac1d130fd4 579 LWIP_ASSERT("tcp_recved: len would wrap rcv_wnd\n",
mbed_official 0:51ac1d130fd4 580 len <= 0xffff - pcb->rcv_wnd );
mbed_official 0:51ac1d130fd4 581
mbed_official 0:51ac1d130fd4 582 pcb->rcv_wnd += len;
mbed_official 0:51ac1d130fd4 583 if (pcb->rcv_wnd > TCP_WND) {
mbed_official 0:51ac1d130fd4 584 pcb->rcv_wnd = TCP_WND;
mbed_official 0:51ac1d130fd4 585 }
mbed_official 0:51ac1d130fd4 586
mbed_official 0:51ac1d130fd4 587 wnd_inflation = tcp_update_rcv_ann_wnd(pcb);
mbed_official 0:51ac1d130fd4 588
mbed_official 0:51ac1d130fd4 589 /* If the change in the right edge of window is significant (default
mbed_official 0:51ac1d130fd4 590 * watermark is TCP_WND/4), then send an explicit update now.
mbed_official 0:51ac1d130fd4 591 * Otherwise wait for a packet to be sent in the normal course of
mbed_official 0:51ac1d130fd4 592 * events (or more window to be available later) */
mbed_official 0:51ac1d130fd4 593 if (wnd_inflation >= TCP_WND_UPDATE_THRESHOLD) {
mbed_official 0:51ac1d130fd4 594 tcp_ack_now(pcb);
mbed_official 0:51ac1d130fd4 595 tcp_output(pcb);
mbed_official 0:51ac1d130fd4 596 }
mbed_official 0:51ac1d130fd4 597
mbed_official 0:51ac1d130fd4 598 LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %"U16_F" bytes, wnd %"U16_F" (%"U16_F").\n",
mbed_official 0:51ac1d130fd4 599 len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd));
mbed_official 0:51ac1d130fd4 600 }
mbed_official 0:51ac1d130fd4 601
mbed_official 0:51ac1d130fd4 602 /**
mbed_official 0:51ac1d130fd4 603 * A nastly hack featuring 'goto' statements that allocates a
mbed_official 0:51ac1d130fd4 604 * new TCP local port.
mbed_official 0:51ac1d130fd4 605 *
mbed_official 0:51ac1d130fd4 606 * @return a new (free) local TCP port number
mbed_official 0:51ac1d130fd4 607 */
mbed_official 0:51ac1d130fd4 608 static u16_t
mbed_official 0:51ac1d130fd4 609 tcp_new_port(void)
mbed_official 0:51ac1d130fd4 610 {
mbed_official 0:51ac1d130fd4 611 int i;
mbed_official 0:51ac1d130fd4 612 struct tcp_pcb *pcb;
mbed_official 0:51ac1d130fd4 613 #ifndef TCP_LOCAL_PORT_RANGE_START
mbed_official 0:51ac1d130fd4 614 /* From http://www.iana.org/assignments/port-numbers:
mbed_official 0:51ac1d130fd4 615 "The Dynamic and/or Private Ports are those from 49152 through 65535" */
mbed_official 0:51ac1d130fd4 616 #define TCP_LOCAL_PORT_RANGE_START 0xc000
mbed_official 0:51ac1d130fd4 617 #define TCP_LOCAL_PORT_RANGE_END 0xffff
mbed_official 0:51ac1d130fd4 618 #endif
mbed_official 0:51ac1d130fd4 619 static u16_t port = TCP_LOCAL_PORT_RANGE_START;
mbed_official 0:51ac1d130fd4 620
mbed_official 0:51ac1d130fd4 621 again:
mbed_official 0:51ac1d130fd4 622 if (port++ >= TCP_LOCAL_PORT_RANGE_END) {
mbed_official 0:51ac1d130fd4 623 port = TCP_LOCAL_PORT_RANGE_START;
mbed_official 0:51ac1d130fd4 624 }
mbed_official 0:51ac1d130fd4 625 /* Check all PCB lists. */
mbed_official 0:51ac1d130fd4 626 for (i = 0; i < NUM_TCP_PCB_LISTS; i++) {
mbed_official 0:51ac1d130fd4 627 for(pcb = *tcp_pcb_lists[i]; pcb != NULL; pcb = pcb->next) {
mbed_official 0:51ac1d130fd4 628 if (pcb->local_port == port) {
mbed_official 0:51ac1d130fd4 629 goto again;
mbed_official 0:51ac1d130fd4 630 }
mbed_official 0:51ac1d130fd4 631 }
mbed_official 0:51ac1d130fd4 632 }
mbed_official 0:51ac1d130fd4 633 return port;
mbed_official 0:51ac1d130fd4 634 }
mbed_official 0:51ac1d130fd4 635
mbed_official 0:51ac1d130fd4 636 /**
mbed_official 0:51ac1d130fd4 637 * Connects to another host. The function given as the "connected"
mbed_official 0:51ac1d130fd4 638 * argument will be called when the connection has been established.
mbed_official 0:51ac1d130fd4 639 *
mbed_official 0:51ac1d130fd4 640 * @param pcb the tcp_pcb used to establish the connection
mbed_official 0:51ac1d130fd4 641 * @param ipaddr the remote ip address to connect to
mbed_official 0:51ac1d130fd4 642 * @param port the remote tcp port to connect to
mbed_official 0:51ac1d130fd4 643 * @param connected callback function to call when connected (or on error)
mbed_official 0:51ac1d130fd4 644 * @return ERR_VAL if invalid arguments are given
mbed_official 0:51ac1d130fd4 645 * ERR_OK if connect request has been sent
mbed_official 0:51ac1d130fd4 646 * other err_t values if connect request couldn't be sent
mbed_official 0:51ac1d130fd4 647 */
mbed_official 0:51ac1d130fd4 648 err_t
mbed_official 0:51ac1d130fd4 649 tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port,
mbed_official 0:51ac1d130fd4 650 tcp_connected_fn connected)
mbed_official 0:51ac1d130fd4 651 {
mbed_official 0:51ac1d130fd4 652 err_t ret;
mbed_official 0:51ac1d130fd4 653 u32_t iss;
mbed_official 0:51ac1d130fd4 654 u16_t old_local_port;
mbed_official 0:51ac1d130fd4 655
mbed_official 0:51ac1d130fd4 656 LWIP_ERROR("tcp_connect: can only connect from state CLOSED", pcb->state == CLOSED, return ERR_ISCONN);
mbed_official 0:51ac1d130fd4 657
mbed_official 0:51ac1d130fd4 658 LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port));
mbed_official 0:51ac1d130fd4 659 if (ipaddr != NULL) {
mbed_official 0:51ac1d130fd4 660 pcb->remote_ip = *ipaddr;
mbed_official 0:51ac1d130fd4 661 } else {
mbed_official 0:51ac1d130fd4 662 return ERR_VAL;
mbed_official 0:51ac1d130fd4 663 }
mbed_official 0:51ac1d130fd4 664 pcb->remote_port = port;
mbed_official 0:51ac1d130fd4 665
mbed_official 0:51ac1d130fd4 666 /* check if we have a route to the remote host */
mbed_official 0:51ac1d130fd4 667 if (ip_addr_isany(&(pcb->local_ip))) {
mbed_official 0:51ac1d130fd4 668 /* no local IP address set, yet. */
mbed_official 0:51ac1d130fd4 669 struct netif *netif = ip_route(&(pcb->remote_ip));
mbed_official 0:51ac1d130fd4 670 if (netif == NULL) {
mbed_official 0:51ac1d130fd4 671 /* Don't even try to send a SYN packet if we have no route
mbed_official 0:51ac1d130fd4 672 since that will fail. */
mbed_official 0:51ac1d130fd4 673 return ERR_RTE;
mbed_official 0:51ac1d130fd4 674 }
mbed_official 0:51ac1d130fd4 675 /* Use the netif's IP address as local address. */
mbed_official 0:51ac1d130fd4 676 ip_addr_copy(pcb->local_ip, netif->ip_addr);
mbed_official 0:51ac1d130fd4 677 }
mbed_official 0:51ac1d130fd4 678
mbed_official 0:51ac1d130fd4 679 old_local_port = pcb->local_port;
mbed_official 0:51ac1d130fd4 680 if (pcb->local_port == 0) {
mbed_official 0:51ac1d130fd4 681 pcb->local_port = tcp_new_port();
mbed_official 0:51ac1d130fd4 682 }
mbed_official 0:51ac1d130fd4 683 #if SO_REUSE
mbed_official 0:51ac1d130fd4 684 if ((pcb->so_options & SOF_REUSEADDR) != 0) {
mbed_official 0:51ac1d130fd4 685 /* Since SOF_REUSEADDR allows reusing a local address, we have to make sure
mbed_official 0:51ac1d130fd4 686 now that the 5-tuple is unique. */
mbed_official 0:51ac1d130fd4 687 struct tcp_pcb *cpcb;
mbed_official 0:51ac1d130fd4 688 int i;
mbed_official 0:51ac1d130fd4 689 /* Don't check listen- and bound-PCBs, check active- and TIME-WAIT PCBs. */
mbed_official 0:51ac1d130fd4 690 for (i = 2; i < NUM_TCP_PCB_LISTS; i++) {
mbed_official 0:51ac1d130fd4 691 for(cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) {
mbed_official 0:51ac1d130fd4 692 if ((cpcb->local_port == pcb->local_port) &&
mbed_official 0:51ac1d130fd4 693 (cpcb->remote_port == port) &&
mbed_official 0:51ac1d130fd4 694 ip_addr_cmp(&cpcb->local_ip, &pcb->local_ip) &&
mbed_official 0:51ac1d130fd4 695 ip_addr_cmp(&cpcb->remote_ip, ipaddr)) {
mbed_official 0:51ac1d130fd4 696 /* linux returns EISCONN here, but ERR_USE should be OK for us */
mbed_official 0:51ac1d130fd4 697 return ERR_USE;
mbed_official 0:51ac1d130fd4 698 }
mbed_official 0:51ac1d130fd4 699 }
mbed_official 0:51ac1d130fd4 700 }
mbed_official 0:51ac1d130fd4 701 }
mbed_official 0:51ac1d130fd4 702 #endif /* SO_REUSE */
mbed_official 0:51ac1d130fd4 703 iss = tcp_next_iss();
mbed_official 0:51ac1d130fd4 704 pcb->rcv_nxt = 0;
mbed_official 0:51ac1d130fd4 705 pcb->snd_nxt = iss;
mbed_official 0:51ac1d130fd4 706 pcb->lastack = iss - 1;
mbed_official 0:51ac1d130fd4 707 pcb->snd_lbb = iss - 1;
mbed_official 0:51ac1d130fd4 708 pcb->rcv_wnd = TCP_WND;
mbed_official 0:51ac1d130fd4 709 pcb->rcv_ann_wnd = TCP_WND;
mbed_official 0:51ac1d130fd4 710 pcb->rcv_ann_right_edge = pcb->rcv_nxt;
mbed_official 0:51ac1d130fd4 711 pcb->snd_wnd = TCP_WND;
mbed_official 0:51ac1d130fd4 712 /* As initial send MSS, we use TCP_MSS but limit it to 536.
mbed_official 0:51ac1d130fd4 713 The send MSS is updated when an MSS option is received. */
mbed_official 0:51ac1d130fd4 714 pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS;
mbed_official 0:51ac1d130fd4 715 #if TCP_CALCULATE_EFF_SEND_MSS
mbed_official 0:51ac1d130fd4 716 pcb->mss = tcp_eff_send_mss(pcb->mss, ipaddr);
mbed_official 0:51ac1d130fd4 717 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
mbed_official 0:51ac1d130fd4 718 pcb->cwnd = 1;
mbed_official 0:51ac1d130fd4 719 pcb->ssthresh = pcb->mss * 10;
mbed_official 0:51ac1d130fd4 720 #if LWIP_CALLBACK_API
mbed_official 0:51ac1d130fd4 721 pcb->connected = connected;
mbed_official 0:51ac1d130fd4 722 #else /* LWIP_CALLBACK_API */
mbed_official 0:51ac1d130fd4 723 LWIP_UNUSED_ARG(connected);
mbed_official 0:51ac1d130fd4 724 #endif /* LWIP_CALLBACK_API */
mbed_official 0:51ac1d130fd4 725
mbed_official 0:51ac1d130fd4 726 /* Send a SYN together with the MSS option. */
mbed_official 0:51ac1d130fd4 727 ret = tcp_enqueue_flags(pcb, TCP_SYN);
mbed_official 0:51ac1d130fd4 728 if (ret == ERR_OK) {
mbed_official 0:51ac1d130fd4 729 /* SYN segment was enqueued, changed the pcbs state now */
mbed_official 0:51ac1d130fd4 730 pcb->state = SYN_SENT;
mbed_official 0:51ac1d130fd4 731 if (old_local_port != 0) {
mbed_official 0:51ac1d130fd4 732 TCP_RMV(&tcp_bound_pcbs, pcb);
mbed_official 0:51ac1d130fd4 733 }
mbed_official 0:51ac1d130fd4 734 TCP_REG(&tcp_active_pcbs, pcb);
mbed_official 0:51ac1d130fd4 735 snmp_inc_tcpactiveopens();
mbed_official 0:51ac1d130fd4 736
mbed_official 0:51ac1d130fd4 737 tcp_output(pcb);
mbed_official 0:51ac1d130fd4 738 }
mbed_official 0:51ac1d130fd4 739 return ret;
mbed_official 0:51ac1d130fd4 740 }
mbed_official 0:51ac1d130fd4 741
mbed_official 0:51ac1d130fd4 742 /**
mbed_official 0:51ac1d130fd4 743 * Called every 500 ms and implements the retransmission timer and the timer that
mbed_official 0:51ac1d130fd4 744 * removes PCBs that have been in TIME-WAIT for enough time. It also increments
mbed_official 0:51ac1d130fd4 745 * various timers such as the inactivity timer in each PCB.
mbed_official 0:51ac1d130fd4 746 *
mbed_official 0:51ac1d130fd4 747 * Automatically called from tcp_tmr().
mbed_official 0:51ac1d130fd4 748 */
mbed_official 0:51ac1d130fd4 749 void
mbed_official 0:51ac1d130fd4 750 tcp_slowtmr(void)
mbed_official 0:51ac1d130fd4 751 {
mbed_official 0:51ac1d130fd4 752 struct tcp_pcb *pcb, *prev;
mbed_official 0:51ac1d130fd4 753 u16_t eff_wnd;
mbed_official 0:51ac1d130fd4 754 u8_t pcb_remove; /* flag if a PCB should be removed */
mbed_official 0:51ac1d130fd4 755 u8_t pcb_reset; /* flag if a RST should be sent when removing */
mbed_official 0:51ac1d130fd4 756 err_t err;
mbed_official 0:51ac1d130fd4 757
mbed_official 0:51ac1d130fd4 758 err = ERR_OK;
mbed_official 0:51ac1d130fd4 759
mbed_official 0:51ac1d130fd4 760 ++tcp_ticks;
mbed_official 0:51ac1d130fd4 761
mbed_official 0:51ac1d130fd4 762 /* Steps through all of the active PCBs. */
mbed_official 0:51ac1d130fd4 763 prev = NULL;
mbed_official 0:51ac1d130fd4 764 pcb = tcp_active_pcbs;
mbed_official 0:51ac1d130fd4 765 if (pcb == NULL) {
mbed_official 0:51ac1d130fd4 766 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n"));
mbed_official 0:51ac1d130fd4 767 }
mbed_official 0:51ac1d130fd4 768 while (pcb != NULL) {
mbed_official 0:51ac1d130fd4 769 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb\n"));
mbed_official 0:51ac1d130fd4 770 LWIP_ASSERT("tcp_slowtmr: active pcb->state != CLOSED\n", pcb->state != CLOSED);
mbed_official 0:51ac1d130fd4 771 LWIP_ASSERT("tcp_slowtmr: active pcb->state != LISTEN\n", pcb->state != LISTEN);
mbed_official 0:51ac1d130fd4 772 LWIP_ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT\n", pcb->state != TIME_WAIT);
mbed_official 0:51ac1d130fd4 773
mbed_official 0:51ac1d130fd4 774 pcb_remove = 0;
mbed_official 0:51ac1d130fd4 775 pcb_reset = 0;
mbed_official 0:51ac1d130fd4 776
mbed_official 0:51ac1d130fd4 777 if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) {
mbed_official 0:51ac1d130fd4 778 ++pcb_remove;
mbed_official 0:51ac1d130fd4 779 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max SYN retries reached\n"));
mbed_official 0:51ac1d130fd4 780 }
mbed_official 0:51ac1d130fd4 781 else if (pcb->nrtx == TCP_MAXRTX) {
mbed_official 0:51ac1d130fd4 782 ++pcb_remove;
mbed_official 0:51ac1d130fd4 783 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n"));
mbed_official 0:51ac1d130fd4 784 } else {
mbed_official 0:51ac1d130fd4 785 if (pcb->persist_backoff > 0) {
mbed_official 0:51ac1d130fd4 786 /* If snd_wnd is zero, use persist timer to send 1 byte probes
mbed_official 0:51ac1d130fd4 787 * instead of using the standard retransmission mechanism. */
mbed_official 0:51ac1d130fd4 788 pcb->persist_cnt++;
mbed_official 0:51ac1d130fd4 789 if (pcb->persist_cnt >= tcp_persist_backoff[pcb->persist_backoff-1]) {
mbed_official 0:51ac1d130fd4 790 pcb->persist_cnt = 0;
mbed_official 0:51ac1d130fd4 791 if (pcb->persist_backoff < sizeof(tcp_persist_backoff)) {
mbed_official 0:51ac1d130fd4 792 pcb->persist_backoff++;
mbed_official 0:51ac1d130fd4 793 }
mbed_official 0:51ac1d130fd4 794 tcp_zero_window_probe(pcb);
mbed_official 0:51ac1d130fd4 795 }
mbed_official 0:51ac1d130fd4 796 } else {
mbed_official 0:51ac1d130fd4 797 /* Increase the retransmission timer if it is running */
mbed_official 0:51ac1d130fd4 798 if(pcb->rtime >= 0)
mbed_official 0:51ac1d130fd4 799 ++pcb->rtime;
mbed_official 0:51ac1d130fd4 800
mbed_official 0:51ac1d130fd4 801 if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) {
mbed_official 0:51ac1d130fd4 802 /* Time for a retransmission. */
mbed_official 0:51ac1d130fd4 803 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"S16_F
mbed_official 0:51ac1d130fd4 804 " pcb->rto %"S16_F"\n",
mbed_official 0:51ac1d130fd4 805 pcb->rtime, pcb->rto));
mbed_official 0:51ac1d130fd4 806
mbed_official 0:51ac1d130fd4 807 /* Double retransmission time-out unless we are trying to
mbed_official 0:51ac1d130fd4 808 * connect to somebody (i.e., we are in SYN_SENT). */
mbed_official 0:51ac1d130fd4 809 if (pcb->state != SYN_SENT) {
mbed_official 0:51ac1d130fd4 810 pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx];
mbed_official 0:51ac1d130fd4 811 }
mbed_official 0:51ac1d130fd4 812
mbed_official 0:51ac1d130fd4 813 /* Reset the retransmission timer. */
mbed_official 0:51ac1d130fd4 814 pcb->rtime = 0;
mbed_official 0:51ac1d130fd4 815
mbed_official 0:51ac1d130fd4 816 /* Reduce congestion window and ssthresh. */
mbed_official 0:51ac1d130fd4 817 eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd);
mbed_official 0:51ac1d130fd4 818 pcb->ssthresh = eff_wnd >> 1;
mbed_official 0:51ac1d130fd4 819 if (pcb->ssthresh < (pcb->mss << 1)) {
mbed_official 0:51ac1d130fd4 820 pcb->ssthresh = (pcb->mss << 1);
mbed_official 0:51ac1d130fd4 821 }
mbed_official 0:51ac1d130fd4 822 pcb->cwnd = pcb->mss;
mbed_official 0:51ac1d130fd4 823 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"U16_F
mbed_official 0:51ac1d130fd4 824 " ssthresh %"U16_F"\n",
mbed_official 0:51ac1d130fd4 825 pcb->cwnd, pcb->ssthresh));
mbed_official 0:51ac1d130fd4 826
mbed_official 0:51ac1d130fd4 827 /* The following needs to be called AFTER cwnd is set to one
mbed_official 0:51ac1d130fd4 828 mss - STJ */
mbed_official 0:51ac1d130fd4 829 tcp_rexmit_rto(pcb);
mbed_official 0:51ac1d130fd4 830 }
mbed_official 0:51ac1d130fd4 831 }
mbed_official 0:51ac1d130fd4 832 }
mbed_official 0:51ac1d130fd4 833 /* Check if this PCB has stayed too long in FIN-WAIT-2 */
mbed_official 0:51ac1d130fd4 834 if (pcb->state == FIN_WAIT_2) {
mbed_official 0:51ac1d130fd4 835 if ((u32_t)(tcp_ticks - pcb->tmr) >
mbed_official 0:51ac1d130fd4 836 TCP_FIN_WAIT_TIMEOUT / TCP_SLOW_INTERVAL) {
mbed_official 0:51ac1d130fd4 837 ++pcb_remove;
mbed_official 0:51ac1d130fd4 838 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in FIN-WAIT-2\n"));
mbed_official 0:51ac1d130fd4 839 }
mbed_official 0:51ac1d130fd4 840 }
mbed_official 0:51ac1d130fd4 841
mbed_official 0:51ac1d130fd4 842 /* Check if KEEPALIVE should be sent */
mbed_official 0:51ac1d130fd4 843 if((pcb->so_options & SOF_KEEPALIVE) &&
mbed_official 0:51ac1d130fd4 844 ((pcb->state == ESTABLISHED) ||
mbed_official 0:51ac1d130fd4 845 (pcb->state == CLOSE_WAIT))) {
mbed_official 0:51ac1d130fd4 846 #if LWIP_TCP_KEEPALIVE
mbed_official 0:51ac1d130fd4 847 if((u32_t)(tcp_ticks - pcb->tmr) >
mbed_official 0:51ac1d130fd4 848 (pcb->keep_idle + (pcb->keep_cnt*pcb->keep_intvl))
mbed_official 0:51ac1d130fd4 849 / TCP_SLOW_INTERVAL)
mbed_official 0:51ac1d130fd4 850 #else
mbed_official 0:51ac1d130fd4 851 if((u32_t)(tcp_ticks - pcb->tmr) >
mbed_official 0:51ac1d130fd4 852 (pcb->keep_idle + TCP_MAXIDLE) / TCP_SLOW_INTERVAL)
mbed_official 0:51ac1d130fd4 853 #endif /* LWIP_TCP_KEEPALIVE */
mbed_official 0:51ac1d130fd4 854 {
mbed_official 0:51ac1d130fd4 855 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %"U16_F".%"U16_F".%"U16_F".%"U16_F".\n",
mbed_official 0:51ac1d130fd4 856 ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip),
mbed_official 0:51ac1d130fd4 857 ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip)));
mbed_official 0:51ac1d130fd4 858
mbed_official 0:51ac1d130fd4 859 ++pcb_remove;
mbed_official 0:51ac1d130fd4 860 ++pcb_reset;
mbed_official 0:51ac1d130fd4 861 }
mbed_official 0:51ac1d130fd4 862 #if LWIP_TCP_KEEPALIVE
mbed_official 0:51ac1d130fd4 863 else if((u32_t)(tcp_ticks - pcb->tmr) >
mbed_official 0:51ac1d130fd4 864 (pcb->keep_idle + pcb->keep_cnt_sent * pcb->keep_intvl)
mbed_official 0:51ac1d130fd4 865 / TCP_SLOW_INTERVAL)
mbed_official 0:51ac1d130fd4 866 #else
mbed_official 0:51ac1d130fd4 867 else if((u32_t)(tcp_ticks - pcb->tmr) >
mbed_official 0:51ac1d130fd4 868 (pcb->keep_idle + pcb->keep_cnt_sent * TCP_KEEPINTVL_DEFAULT)
mbed_official 0:51ac1d130fd4 869 / TCP_SLOW_INTERVAL)
mbed_official 0:51ac1d130fd4 870 #endif /* LWIP_TCP_KEEPALIVE */
mbed_official 0:51ac1d130fd4 871 {
mbed_official 0:51ac1d130fd4 872 tcp_keepalive(pcb);
mbed_official 0:51ac1d130fd4 873 pcb->keep_cnt_sent++;
mbed_official 0:51ac1d130fd4 874 }
mbed_official 0:51ac1d130fd4 875 }
mbed_official 0:51ac1d130fd4 876
mbed_official 0:51ac1d130fd4 877 /* If this PCB has queued out of sequence data, but has been
mbed_official 0:51ac1d130fd4 878 inactive for too long, will drop the data (it will eventually
mbed_official 0:51ac1d130fd4 879 be retransmitted). */
mbed_official 0:51ac1d130fd4 880 #if TCP_QUEUE_OOSEQ
mbed_official 0:51ac1d130fd4 881 if (pcb->ooseq != NULL &&
mbed_official 0:51ac1d130fd4 882 (u32_t)tcp_ticks - pcb->tmr >= pcb->rto * TCP_OOSEQ_TIMEOUT) {
mbed_official 0:51ac1d130fd4 883 tcp_segs_free(pcb->ooseq);
mbed_official 0:51ac1d130fd4 884 pcb->ooseq = NULL;
mbed_official 0:51ac1d130fd4 885 LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: dropping OOSEQ queued data\n"));
mbed_official 0:51ac1d130fd4 886 }
mbed_official 0:51ac1d130fd4 887 #endif /* TCP_QUEUE_OOSEQ */
mbed_official 0:51ac1d130fd4 888
mbed_official 0:51ac1d130fd4 889 /* Check if this PCB has stayed too long in SYN-RCVD */
mbed_official 0:51ac1d130fd4 890 if (pcb->state == SYN_RCVD) {
mbed_official 0:51ac1d130fd4 891 if ((u32_t)(tcp_ticks - pcb->tmr) >
mbed_official 0:51ac1d130fd4 892 TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) {
mbed_official 0:51ac1d130fd4 893 ++pcb_remove;
mbed_official 0:51ac1d130fd4 894 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in SYN-RCVD\n"));
mbed_official 0:51ac1d130fd4 895 }
mbed_official 0:51ac1d130fd4 896 }
mbed_official 0:51ac1d130fd4 897
mbed_official 0:51ac1d130fd4 898 /* Check if this PCB has stayed too long in LAST-ACK */
mbed_official 0:51ac1d130fd4 899 if (pcb->state == LAST_ACK) {
mbed_official 0:51ac1d130fd4 900 if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) {
mbed_official 0:51ac1d130fd4 901 ++pcb_remove;
mbed_official 0:51ac1d130fd4 902 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in LAST-ACK\n"));
mbed_official 0:51ac1d130fd4 903 }
mbed_official 0:51ac1d130fd4 904 }
mbed_official 0:51ac1d130fd4 905
mbed_official 0:51ac1d130fd4 906 /* If the PCB should be removed, do it. */
mbed_official 0:51ac1d130fd4 907 if (pcb_remove) {
mbed_official 0:51ac1d130fd4 908 struct tcp_pcb *pcb2;
mbed_official 0:51ac1d130fd4 909 tcp_pcb_purge(pcb);
mbed_official 0:51ac1d130fd4 910 /* Remove PCB from tcp_active_pcbs list. */
mbed_official 0:51ac1d130fd4 911 if (prev != NULL) {
mbed_official 0:51ac1d130fd4 912 LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_active_pcbs", pcb != tcp_active_pcbs);
mbed_official 0:51ac1d130fd4 913 prev->next = pcb->next;
mbed_official 0:51ac1d130fd4 914 } else {
mbed_official 0:51ac1d130fd4 915 /* This PCB was the first. */
mbed_official 0:51ac1d130fd4 916 LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_active_pcbs", tcp_active_pcbs == pcb);
mbed_official 0:51ac1d130fd4 917 tcp_active_pcbs = pcb->next;
mbed_official 0:51ac1d130fd4 918 }
mbed_official 0:51ac1d130fd4 919
mbed_official 0:51ac1d130fd4 920 TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_ABRT);
mbed_official 0:51ac1d130fd4 921 if (pcb_reset) {
mbed_official 0:51ac1d130fd4 922 tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip,
mbed_official 0:51ac1d130fd4 923 pcb->local_port, pcb->remote_port);
mbed_official 0:51ac1d130fd4 924 }
mbed_official 0:51ac1d130fd4 925
mbed_official 0:51ac1d130fd4 926 pcb2 = pcb;
mbed_official 0:51ac1d130fd4 927 pcb = pcb->next;
mbed_official 0:51ac1d130fd4 928 memp_free(MEMP_TCP_PCB, pcb2);
mbed_official 0:51ac1d130fd4 929 } else {
mbed_official 0:51ac1d130fd4 930 /* get the 'next' element now and work with 'prev' below (in case of abort) */
mbed_official 0:51ac1d130fd4 931 prev = pcb;
mbed_official 0:51ac1d130fd4 932 pcb = pcb->next;
mbed_official 0:51ac1d130fd4 933
mbed_official 0:51ac1d130fd4 934 /* We check if we should poll the connection. */
mbed_official 0:51ac1d130fd4 935 ++prev->polltmr;
mbed_official 0:51ac1d130fd4 936 if (prev->polltmr >= prev->pollinterval) {
mbed_official 0:51ac1d130fd4 937 prev->polltmr = 0;
mbed_official 0:51ac1d130fd4 938 LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: polling application\n"));
mbed_official 0:51ac1d130fd4 939 TCP_EVENT_POLL(prev, err);
mbed_official 0:51ac1d130fd4 940 /* if err == ERR_ABRT, 'prev' is already deallocated */
mbed_official 0:51ac1d130fd4 941 if (err == ERR_OK) {
mbed_official 0:51ac1d130fd4 942 tcp_output(prev);
mbed_official 0:51ac1d130fd4 943 }
mbed_official 0:51ac1d130fd4 944 }
mbed_official 0:51ac1d130fd4 945 }
mbed_official 0:51ac1d130fd4 946 }
mbed_official 0:51ac1d130fd4 947
mbed_official 0:51ac1d130fd4 948
mbed_official 0:51ac1d130fd4 949 /* Steps through all of the TIME-WAIT PCBs. */
mbed_official 0:51ac1d130fd4 950 prev = NULL;
mbed_official 0:51ac1d130fd4 951 pcb = tcp_tw_pcbs;
mbed_official 0:51ac1d130fd4 952 while (pcb != NULL) {
mbed_official 0:51ac1d130fd4 953 LWIP_ASSERT("tcp_slowtmr: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
mbed_official 0:51ac1d130fd4 954 pcb_remove = 0;
mbed_official 0:51ac1d130fd4 955
mbed_official 0:51ac1d130fd4 956 /* Check if this PCB has stayed long enough in TIME-WAIT */
mbed_official 0:51ac1d130fd4 957 if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) {
mbed_official 0:51ac1d130fd4 958 ++pcb_remove;
mbed_official 0:51ac1d130fd4 959 }
mbed_official 0:51ac1d130fd4 960
mbed_official 0:51ac1d130fd4 961
mbed_official 0:51ac1d130fd4 962
mbed_official 0:51ac1d130fd4 963 /* If the PCB should be removed, do it. */
mbed_official 0:51ac1d130fd4 964 if (pcb_remove) {
mbed_official 0:51ac1d130fd4 965 struct tcp_pcb *pcb2;
mbed_official 0:51ac1d130fd4 966 tcp_pcb_purge(pcb);
mbed_official 0:51ac1d130fd4 967 /* Remove PCB from tcp_tw_pcbs list. */
mbed_official 0:51ac1d130fd4 968 if (prev != NULL) {
mbed_official 0:51ac1d130fd4 969 LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_tw_pcbs", pcb != tcp_tw_pcbs);
mbed_official 0:51ac1d130fd4 970 prev->next = pcb->next;
mbed_official 0:51ac1d130fd4 971 } else {
mbed_official 0:51ac1d130fd4 972 /* This PCB was the first. */
mbed_official 0:51ac1d130fd4 973 LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_tw_pcbs", tcp_tw_pcbs == pcb);
mbed_official 0:51ac1d130fd4 974 tcp_tw_pcbs = pcb->next;
mbed_official 0:51ac1d130fd4 975 }
mbed_official 0:51ac1d130fd4 976 pcb2 = pcb;
mbed_official 0:51ac1d130fd4 977 pcb = pcb->next;
mbed_official 0:51ac1d130fd4 978 memp_free(MEMP_TCP_PCB, pcb2);
mbed_official 0:51ac1d130fd4 979 } else {
mbed_official 0:51ac1d130fd4 980 prev = pcb;
mbed_official 0:51ac1d130fd4 981 pcb = pcb->next;
mbed_official 0:51ac1d130fd4 982 }
mbed_official 0:51ac1d130fd4 983 }
mbed_official 0:51ac1d130fd4 984 }
mbed_official 0:51ac1d130fd4 985
mbed_official 0:51ac1d130fd4 986 /**
mbed_official 0:51ac1d130fd4 987 * Is called every TCP_FAST_INTERVAL (250 ms) and process data previously
mbed_official 0:51ac1d130fd4 988 * "refused" by upper layer (application) and sends delayed ACKs.
mbed_official 0:51ac1d130fd4 989 *
mbed_official 0:51ac1d130fd4 990 * Automatically called from tcp_tmr().
mbed_official 0:51ac1d130fd4 991 */
mbed_official 0:51ac1d130fd4 992 void
mbed_official 0:51ac1d130fd4 993 tcp_fasttmr(void)
mbed_official 0:51ac1d130fd4 994 {
mbed_official 0:51ac1d130fd4 995 struct tcp_pcb *pcb = tcp_active_pcbs;
mbed_official 0:51ac1d130fd4 996
mbed_official 0:51ac1d130fd4 997 while(pcb != NULL) {
mbed_official 0:51ac1d130fd4 998 struct tcp_pcb *next = pcb->next;
mbed_official 0:51ac1d130fd4 999 /* If there is data which was previously "refused" by upper layer */
mbed_official 0:51ac1d130fd4 1000 if (pcb->refused_data != NULL) {
mbed_official 0:51ac1d130fd4 1001 /* Notify again application with data previously received. */
mbed_official 0:51ac1d130fd4 1002 err_t err;
mbed_official 0:51ac1d130fd4 1003 LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_fasttmr: notify kept packet\n"));
mbed_official 0:51ac1d130fd4 1004 TCP_EVENT_RECV(pcb, pcb->refused_data, ERR_OK, err);
mbed_official 0:51ac1d130fd4 1005 if (err == ERR_OK) {
mbed_official 0:51ac1d130fd4 1006 pcb->refused_data = NULL;
mbed_official 0:51ac1d130fd4 1007 } else if (err == ERR_ABRT) {
mbed_official 0:51ac1d130fd4 1008 /* if err == ERR_ABRT, 'pcb' is already deallocated */
mbed_official 0:51ac1d130fd4 1009 pcb = NULL;
mbed_official 0:51ac1d130fd4 1010 }
mbed_official 0:51ac1d130fd4 1011 }
mbed_official 0:51ac1d130fd4 1012
mbed_official 0:51ac1d130fd4 1013 /* send delayed ACKs */
mbed_official 0:51ac1d130fd4 1014 if (pcb && (pcb->flags & TF_ACK_DELAY)) {
mbed_official 0:51ac1d130fd4 1015 LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: delayed ACK\n"));
mbed_official 0:51ac1d130fd4 1016 tcp_ack_now(pcb);
mbed_official 0:51ac1d130fd4 1017 tcp_output(pcb);
mbed_official 0:51ac1d130fd4 1018 pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
mbed_official 0:51ac1d130fd4 1019 }
mbed_official 0:51ac1d130fd4 1020
mbed_official 0:51ac1d130fd4 1021 pcb = next;
mbed_official 0:51ac1d130fd4 1022 }
mbed_official 0:51ac1d130fd4 1023 }
mbed_official 0:51ac1d130fd4 1024
mbed_official 0:51ac1d130fd4 1025 /**
mbed_official 0:51ac1d130fd4 1026 * Deallocates a list of TCP segments (tcp_seg structures).
mbed_official 0:51ac1d130fd4 1027 *
mbed_official 0:51ac1d130fd4 1028 * @param seg tcp_seg list of TCP segments to free
mbed_official 0:51ac1d130fd4 1029 */
mbed_official 0:51ac1d130fd4 1030 void
mbed_official 0:51ac1d130fd4 1031 tcp_segs_free(struct tcp_seg *seg)
mbed_official 0:51ac1d130fd4 1032 {
mbed_official 0:51ac1d130fd4 1033 while (seg != NULL) {
mbed_official 0:51ac1d130fd4 1034 struct tcp_seg *next = seg->next;
mbed_official 0:51ac1d130fd4 1035 tcp_seg_free(seg);
mbed_official 0:51ac1d130fd4 1036 seg = next;
mbed_official 0:51ac1d130fd4 1037 }
mbed_official 0:51ac1d130fd4 1038 }
mbed_official 0:51ac1d130fd4 1039
mbed_official 0:51ac1d130fd4 1040 /**
mbed_official 0:51ac1d130fd4 1041 * Frees a TCP segment (tcp_seg structure).
mbed_official 0:51ac1d130fd4 1042 *
mbed_official 0:51ac1d130fd4 1043 * @param seg single tcp_seg to free
mbed_official 0:51ac1d130fd4 1044 */
mbed_official 0:51ac1d130fd4 1045 void
mbed_official 0:51ac1d130fd4 1046 tcp_seg_free(struct tcp_seg *seg)
mbed_official 0:51ac1d130fd4 1047 {
mbed_official 0:51ac1d130fd4 1048 if (seg != NULL) {
mbed_official 0:51ac1d130fd4 1049 if (seg->p != NULL) {
mbed_official 0:51ac1d130fd4 1050 pbuf_free(seg->p);
mbed_official 0:51ac1d130fd4 1051 #if TCP_DEBUG
mbed_official 0:51ac1d130fd4 1052 seg->p = NULL;
mbed_official 0:51ac1d130fd4 1053 #endif /* TCP_DEBUG */
mbed_official 0:51ac1d130fd4 1054 }
mbed_official 0:51ac1d130fd4 1055 memp_free(MEMP_TCP_SEG, seg);
mbed_official 0:51ac1d130fd4 1056 }
mbed_official 0:51ac1d130fd4 1057 }
mbed_official 0:51ac1d130fd4 1058
mbed_official 0:51ac1d130fd4 1059 /**
mbed_official 0:51ac1d130fd4 1060 * Sets the priority of a connection.
mbed_official 0:51ac1d130fd4 1061 *
mbed_official 0:51ac1d130fd4 1062 * @param pcb the tcp_pcb to manipulate
mbed_official 0:51ac1d130fd4 1063 * @param prio new priority
mbed_official 0:51ac1d130fd4 1064 */
mbed_official 0:51ac1d130fd4 1065 void
mbed_official 0:51ac1d130fd4 1066 tcp_setprio(struct tcp_pcb *pcb, u8_t prio)
mbed_official 0:51ac1d130fd4 1067 {
mbed_official 0:51ac1d130fd4 1068 pcb->prio = prio;
mbed_official 0:51ac1d130fd4 1069 }
mbed_official 0:51ac1d130fd4 1070
mbed_official 0:51ac1d130fd4 1071 #if TCP_QUEUE_OOSEQ
mbed_official 0:51ac1d130fd4 1072 /**
mbed_official 0:51ac1d130fd4 1073 * Returns a copy of the given TCP segment.
mbed_official 0:51ac1d130fd4 1074 * The pbuf and data are not copied, only the pointers
mbed_official 0:51ac1d130fd4 1075 *
mbed_official 0:51ac1d130fd4 1076 * @param seg the old tcp_seg
mbed_official 0:51ac1d130fd4 1077 * @return a copy of seg
mbed_official 0:51ac1d130fd4 1078 */
mbed_official 0:51ac1d130fd4 1079 struct tcp_seg *
mbed_official 0:51ac1d130fd4 1080 tcp_seg_copy(struct tcp_seg *seg)
mbed_official 0:51ac1d130fd4 1081 {
mbed_official 0:51ac1d130fd4 1082 struct tcp_seg *cseg;
mbed_official 0:51ac1d130fd4 1083
mbed_official 0:51ac1d130fd4 1084 cseg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG);
mbed_official 0:51ac1d130fd4 1085 if (cseg == NULL) {
mbed_official 0:51ac1d130fd4 1086 return NULL;
mbed_official 0:51ac1d130fd4 1087 }
mbed_official 0:51ac1d130fd4 1088 SMEMCPY((u8_t *)cseg, (const u8_t *)seg, sizeof(struct tcp_seg));
mbed_official 0:51ac1d130fd4 1089 pbuf_ref(cseg->p);
mbed_official 0:51ac1d130fd4 1090 return cseg;
mbed_official 0:51ac1d130fd4 1091 }
mbed_official 0:51ac1d130fd4 1092 #endif /* TCP_QUEUE_OOSEQ */
mbed_official 0:51ac1d130fd4 1093
mbed_official 0:51ac1d130fd4 1094 #if LWIP_CALLBACK_API
mbed_official 0:51ac1d130fd4 1095 /**
mbed_official 0:51ac1d130fd4 1096 * Default receive callback that is called if the user didn't register
mbed_official 0:51ac1d130fd4 1097 * a recv callback for the pcb.
mbed_official 0:51ac1d130fd4 1098 */
mbed_official 0:51ac1d130fd4 1099 err_t
mbed_official 0:51ac1d130fd4 1100 tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
mbed_official 0:51ac1d130fd4 1101 {
mbed_official 0:51ac1d130fd4 1102 LWIP_UNUSED_ARG(arg);
mbed_official 0:51ac1d130fd4 1103 if (p != NULL) {
mbed_official 0:51ac1d130fd4 1104 tcp_recved(pcb, p->tot_len);
mbed_official 0:51ac1d130fd4 1105 pbuf_free(p);
mbed_official 0:51ac1d130fd4 1106 } else if (err == ERR_OK) {
mbed_official 0:51ac1d130fd4 1107 return tcp_close(pcb);
mbed_official 0:51ac1d130fd4 1108 }
mbed_official 0:51ac1d130fd4 1109 return ERR_OK;
mbed_official 0:51ac1d130fd4 1110 }
mbed_official 0:51ac1d130fd4 1111 #endif /* LWIP_CALLBACK_API */
mbed_official 0:51ac1d130fd4 1112
mbed_official 0:51ac1d130fd4 1113 /**
mbed_official 0:51ac1d130fd4 1114 * Kills the oldest active connection that has lower priority than prio.
mbed_official 0:51ac1d130fd4 1115 *
mbed_official 0:51ac1d130fd4 1116 * @param prio minimum priority
mbed_official 0:51ac1d130fd4 1117 */
mbed_official 0:51ac1d130fd4 1118 static void
mbed_official 0:51ac1d130fd4 1119 tcp_kill_prio(u8_t prio)
mbed_official 0:51ac1d130fd4 1120 {
mbed_official 0:51ac1d130fd4 1121 struct tcp_pcb *pcb, *inactive;
mbed_official 0:51ac1d130fd4 1122 u32_t inactivity;
mbed_official 0:51ac1d130fd4 1123 u8_t mprio;
mbed_official 0:51ac1d130fd4 1124
mbed_official 0:51ac1d130fd4 1125
mbed_official 0:51ac1d130fd4 1126 mprio = TCP_PRIO_MAX;
mbed_official 0:51ac1d130fd4 1127
mbed_official 0:51ac1d130fd4 1128 /* We kill the oldest active connection that has lower priority than prio. */
mbed_official 0:51ac1d130fd4 1129 inactivity = 0;
mbed_official 0:51ac1d130fd4 1130 inactive = NULL;
mbed_official 0:51ac1d130fd4 1131 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
mbed_official 0:51ac1d130fd4 1132 if (pcb->prio <= prio &&
mbed_official 0:51ac1d130fd4 1133 pcb->prio <= mprio &&
mbed_official 0:51ac1d130fd4 1134 (u32_t)(tcp_ticks - pcb->tmr) >= inactivity) {
mbed_official 0:51ac1d130fd4 1135 inactivity = tcp_ticks - pcb->tmr;
mbed_official 0:51ac1d130fd4 1136 inactive = pcb;
mbed_official 0:51ac1d130fd4 1137 mprio = pcb->prio;
mbed_official 0:51ac1d130fd4 1138 }
mbed_official 0:51ac1d130fd4 1139 }
mbed_official 0:51ac1d130fd4 1140 if (inactive != NULL) {
mbed_official 0:51ac1d130fd4 1141 LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%"S32_F")\n",
mbed_official 0:51ac1d130fd4 1142 (void *)inactive, inactivity));
mbed_official 0:51ac1d130fd4 1143 tcp_abort(inactive);
mbed_official 0:51ac1d130fd4 1144 }
mbed_official 0:51ac1d130fd4 1145 }
mbed_official 0:51ac1d130fd4 1146
mbed_official 0:51ac1d130fd4 1147 /**
mbed_official 0:51ac1d130fd4 1148 * Kills the oldest connection that is in TIME_WAIT state.
mbed_official 0:51ac1d130fd4 1149 * Called from tcp_alloc() if no more connections are available.
mbed_official 0:51ac1d130fd4 1150 */
mbed_official 0:51ac1d130fd4 1151 static void
mbed_official 0:51ac1d130fd4 1152 tcp_kill_timewait(void)
mbed_official 0:51ac1d130fd4 1153 {
mbed_official 0:51ac1d130fd4 1154 struct tcp_pcb *pcb, *inactive;
mbed_official 0:51ac1d130fd4 1155 u32_t inactivity;
mbed_official 0:51ac1d130fd4 1156
mbed_official 0:51ac1d130fd4 1157 inactivity = 0;
mbed_official 0:51ac1d130fd4 1158 inactive = NULL;
mbed_official 0:51ac1d130fd4 1159 /* Go through the list of TIME_WAIT pcbs and get the oldest pcb. */
mbed_official 0:51ac1d130fd4 1160 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
mbed_official 0:51ac1d130fd4 1161 if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) {
mbed_official 0:51ac1d130fd4 1162 inactivity = tcp_ticks - pcb->tmr;
mbed_official 0:51ac1d130fd4 1163 inactive = pcb;
mbed_official 0:51ac1d130fd4 1164 }
mbed_official 0:51ac1d130fd4 1165 }
mbed_official 0:51ac1d130fd4 1166 if (inactive != NULL) {
mbed_official 0:51ac1d130fd4 1167 LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%"S32_F")\n",
mbed_official 0:51ac1d130fd4 1168 (void *)inactive, inactivity));
mbed_official 0:51ac1d130fd4 1169 tcp_abort(inactive);
mbed_official 0:51ac1d130fd4 1170 }
mbed_official 0:51ac1d130fd4 1171 }
mbed_official 0:51ac1d130fd4 1172
mbed_official 0:51ac1d130fd4 1173 /**
mbed_official 0:51ac1d130fd4 1174 * Allocate a new tcp_pcb structure.
mbed_official 0:51ac1d130fd4 1175 *
mbed_official 0:51ac1d130fd4 1176 * @param prio priority for the new pcb
mbed_official 0:51ac1d130fd4 1177 * @return a new tcp_pcb that initially is in state CLOSED
mbed_official 0:51ac1d130fd4 1178 */
mbed_official 0:51ac1d130fd4 1179 struct tcp_pcb *
mbed_official 0:51ac1d130fd4 1180 tcp_alloc(u8_t prio)
mbed_official 0:51ac1d130fd4 1181 {
mbed_official 0:51ac1d130fd4 1182 struct tcp_pcb *pcb;
mbed_official 0:51ac1d130fd4 1183 u32_t iss;
mbed_official 0:51ac1d130fd4 1184
mbed_official 0:51ac1d130fd4 1185 pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB);
mbed_official 0:51ac1d130fd4 1186 if (pcb == NULL) {
mbed_official 0:51ac1d130fd4 1187 /* Try killing oldest connection in TIME-WAIT. */
mbed_official 0:51ac1d130fd4 1188 LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest TIME-WAIT connection\n"));
mbed_official 0:51ac1d130fd4 1189 tcp_kill_timewait();
mbed_official 0:51ac1d130fd4 1190 /* Try to allocate a tcp_pcb again. */
mbed_official 0:51ac1d130fd4 1191 pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB);
mbed_official 0:51ac1d130fd4 1192 if (pcb == NULL) {
mbed_official 0:51ac1d130fd4 1193 /* Try killing active connections with lower priority than the new one. */
mbed_official 0:51ac1d130fd4 1194 LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing connection with prio lower than %d\n", prio));
mbed_official 0:51ac1d130fd4 1195 tcp_kill_prio(prio);
mbed_official 0:51ac1d130fd4 1196 /* Try to allocate a tcp_pcb again. */
mbed_official 0:51ac1d130fd4 1197 pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB);
mbed_official 0:51ac1d130fd4 1198 if (pcb != NULL) {
mbed_official 0:51ac1d130fd4 1199 /* adjust err stats: memp_malloc failed twice before */
mbed_official 0:51ac1d130fd4 1200 MEMP_STATS_DEC(err, MEMP_TCP_PCB);
mbed_official 0:51ac1d130fd4 1201 }
mbed_official 0:51ac1d130fd4 1202 }
mbed_official 0:51ac1d130fd4 1203 if (pcb != NULL) {
mbed_official 0:51ac1d130fd4 1204 /* adjust err stats: timewait PCB was freed above */
mbed_official 0:51ac1d130fd4 1205 MEMP_STATS_DEC(err, MEMP_TCP_PCB);
mbed_official 0:51ac1d130fd4 1206 }
mbed_official 0:51ac1d130fd4 1207 }
mbed_official 0:51ac1d130fd4 1208 if (pcb != NULL) {
mbed_official 0:51ac1d130fd4 1209 memset(pcb, 0, sizeof(struct tcp_pcb));
mbed_official 0:51ac1d130fd4 1210 pcb->prio = prio;
mbed_official 0:51ac1d130fd4 1211 pcb->snd_buf = TCP_SND_BUF;
mbed_official 0:51ac1d130fd4 1212 pcb->snd_queuelen = 0;
mbed_official 0:51ac1d130fd4 1213 pcb->rcv_wnd = TCP_WND;
mbed_official 0:51ac1d130fd4 1214 pcb->rcv_ann_wnd = TCP_WND;
mbed_official 0:51ac1d130fd4 1215 pcb->tos = 0;
mbed_official 0:51ac1d130fd4 1216 pcb->ttl = TCP_TTL;
mbed_official 0:51ac1d130fd4 1217 /* As initial send MSS, we use TCP_MSS but limit it to 536.
mbed_official 0:51ac1d130fd4 1218 The send MSS is updated when an MSS option is received. */
mbed_official 0:51ac1d130fd4 1219 pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS;
mbed_official 0:51ac1d130fd4 1220 pcb->rto = 3000 / TCP_SLOW_INTERVAL;
mbed_official 0:51ac1d130fd4 1221 pcb->sa = 0;
mbed_official 0:51ac1d130fd4 1222 pcb->sv = 3000 / TCP_SLOW_INTERVAL;
mbed_official 0:51ac1d130fd4 1223 pcb->rtime = -1;
mbed_official 0:51ac1d130fd4 1224 pcb->cwnd = 1;
mbed_official 0:51ac1d130fd4 1225 iss = tcp_next_iss();
mbed_official 0:51ac1d130fd4 1226 pcb->snd_wl2 = iss;
mbed_official 0:51ac1d130fd4 1227 pcb->snd_nxt = iss;
mbed_official 0:51ac1d130fd4 1228 pcb->lastack = iss;
mbed_official 0:51ac1d130fd4 1229 pcb->snd_lbb = iss;
mbed_official 0:51ac1d130fd4 1230 pcb->tmr = tcp_ticks;
mbed_official 0:51ac1d130fd4 1231
mbed_official 0:51ac1d130fd4 1232 pcb->polltmr = 0;
mbed_official 0:51ac1d130fd4 1233
mbed_official 0:51ac1d130fd4 1234 #if LWIP_CALLBACK_API
mbed_official 0:51ac1d130fd4 1235 pcb->recv = tcp_recv_null;
mbed_official 0:51ac1d130fd4 1236 #endif /* LWIP_CALLBACK_API */
mbed_official 0:51ac1d130fd4 1237
mbed_official 0:51ac1d130fd4 1238 /* Init KEEPALIVE timer */
mbed_official 0:51ac1d130fd4 1239 pcb->keep_idle = TCP_KEEPIDLE_DEFAULT;
mbed_official 0:51ac1d130fd4 1240
mbed_official 0:51ac1d130fd4 1241 #if LWIP_TCP_KEEPALIVE
mbed_official 0:51ac1d130fd4 1242 pcb->keep_intvl = TCP_KEEPINTVL_DEFAULT;
mbed_official 0:51ac1d130fd4 1243 pcb->keep_cnt = TCP_KEEPCNT_DEFAULT;
mbed_official 0:51ac1d130fd4 1244 #endif /* LWIP_TCP_KEEPALIVE */
mbed_official 0:51ac1d130fd4 1245
mbed_official 0:51ac1d130fd4 1246 pcb->keep_cnt_sent = 0;
mbed_official 0:51ac1d130fd4 1247 }
mbed_official 0:51ac1d130fd4 1248 return pcb;
mbed_official 0:51ac1d130fd4 1249 }
mbed_official 0:51ac1d130fd4 1250
mbed_official 0:51ac1d130fd4 1251 /**
mbed_official 0:51ac1d130fd4 1252 * Creates a new TCP protocol control block but doesn't place it on
mbed_official 0:51ac1d130fd4 1253 * any of the TCP PCB lists.
mbed_official 0:51ac1d130fd4 1254 * The pcb is not put on any list until binding using tcp_bind().
mbed_official 0:51ac1d130fd4 1255 *
mbed_official 0:51ac1d130fd4 1256 * @internal: Maybe there should be a idle TCP PCB list where these
mbed_official 0:51ac1d130fd4 1257 * PCBs are put on. Port reservation using tcp_bind() is implemented but
mbed_official 0:51ac1d130fd4 1258 * allocated pcbs that are not bound can't be killed automatically if wanting
mbed_official 0:51ac1d130fd4 1259 * to allocate a pcb with higher prio (@see tcp_kill_prio())
mbed_official 0:51ac1d130fd4 1260 *
mbed_official 0:51ac1d130fd4 1261 * @return a new tcp_pcb that initially is in state CLOSED
mbed_official 0:51ac1d130fd4 1262 */
mbed_official 0:51ac1d130fd4 1263 struct tcp_pcb *
mbed_official 0:51ac1d130fd4 1264 tcp_new(void)
mbed_official 0:51ac1d130fd4 1265 {
mbed_official 0:51ac1d130fd4 1266 return tcp_alloc(TCP_PRIO_NORMAL);
mbed_official 0:51ac1d130fd4 1267 }
mbed_official 0:51ac1d130fd4 1268
mbed_official 0:51ac1d130fd4 1269 /**
mbed_official 0:51ac1d130fd4 1270 * Used to specify the argument that should be passed callback
mbed_official 0:51ac1d130fd4 1271 * functions.
mbed_official 0:51ac1d130fd4 1272 *
mbed_official 0:51ac1d130fd4 1273 * @param pcb tcp_pcb to set the callback argument
mbed_official 0:51ac1d130fd4 1274 * @param arg void pointer argument to pass to callback functions
mbed_official 0:51ac1d130fd4 1275 */
mbed_official 0:51ac1d130fd4 1276 void
mbed_official 0:51ac1d130fd4 1277 tcp_arg(struct tcp_pcb *pcb, void *arg)
mbed_official 0:51ac1d130fd4 1278 {
mbed_official 0:51ac1d130fd4 1279 pcb->callback_arg = arg;
mbed_official 0:51ac1d130fd4 1280 }
mbed_official 0:51ac1d130fd4 1281 #if LWIP_CALLBACK_API
mbed_official 0:51ac1d130fd4 1282
mbed_official 0:51ac1d130fd4 1283 /**
mbed_official 0:51ac1d130fd4 1284 * Used to specify the function that should be called when a TCP
mbed_official 0:51ac1d130fd4 1285 * connection receives data.
mbed_official 0:51ac1d130fd4 1286 *
mbed_official 0:51ac1d130fd4 1287 * @param pcb tcp_pcb to set the recv callback
mbed_official 0:51ac1d130fd4 1288 * @param recv callback function to call for this pcb when data is received
mbed_official 0:51ac1d130fd4 1289 */
mbed_official 0:51ac1d130fd4 1290 void
mbed_official 0:51ac1d130fd4 1291 tcp_recv(struct tcp_pcb *pcb, tcp_recv_fn recv)
mbed_official 0:51ac1d130fd4 1292 {
mbed_official 0:51ac1d130fd4 1293 pcb->recv = recv;
mbed_official 0:51ac1d130fd4 1294 }
mbed_official 0:51ac1d130fd4 1295
mbed_official 0:51ac1d130fd4 1296 /**
mbed_official 0:51ac1d130fd4 1297 * Used to specify the function that should be called when TCP data
mbed_official 0:51ac1d130fd4 1298 * has been successfully delivered to the remote host.
mbed_official 0:51ac1d130fd4 1299 *
mbed_official 0:51ac1d130fd4 1300 * @param pcb tcp_pcb to set the sent callback
mbed_official 0:51ac1d130fd4 1301 * @param sent callback function to call for this pcb when data is successfully sent
mbed_official 0:51ac1d130fd4 1302 */
mbed_official 0:51ac1d130fd4 1303 void
mbed_official 0:51ac1d130fd4 1304 tcp_sent(struct tcp_pcb *pcb, tcp_sent_fn sent)
mbed_official 0:51ac1d130fd4 1305 {
mbed_official 0:51ac1d130fd4 1306 pcb->sent = sent;
mbed_official 0:51ac1d130fd4 1307 }
mbed_official 0:51ac1d130fd4 1308
mbed_official 0:51ac1d130fd4 1309 /**
mbed_official 0:51ac1d130fd4 1310 * Used to specify the function that should be called when a fatal error
mbed_official 0:51ac1d130fd4 1311 * has occured on the connection.
mbed_official 0:51ac1d130fd4 1312 *
mbed_official 0:51ac1d130fd4 1313 * @param pcb tcp_pcb to set the err callback
mbed_official 0:51ac1d130fd4 1314 * @param err callback function to call for this pcb when a fatal error
mbed_official 0:51ac1d130fd4 1315 * has occured on the connection
mbed_official 0:51ac1d130fd4 1316 */
mbed_official 0:51ac1d130fd4 1317 void
mbed_official 0:51ac1d130fd4 1318 tcp_err(struct tcp_pcb *pcb, tcp_err_fn err)
mbed_official 0:51ac1d130fd4 1319 {
mbed_official 0:51ac1d130fd4 1320 pcb->errf = err;
mbed_official 0:51ac1d130fd4 1321 }
mbed_official 0:51ac1d130fd4 1322
mbed_official 0:51ac1d130fd4 1323 /**
mbed_official 0:51ac1d130fd4 1324 * Used for specifying the function that should be called when a
mbed_official 0:51ac1d130fd4 1325 * LISTENing connection has been connected to another host.
mbed_official 0:51ac1d130fd4 1326 *
mbed_official 0:51ac1d130fd4 1327 * @param pcb tcp_pcb to set the accept callback
mbed_official 0:51ac1d130fd4 1328 * @param accept callback function to call for this pcb when LISTENing
mbed_official 0:51ac1d130fd4 1329 * connection has been connected to another host
mbed_official 0:51ac1d130fd4 1330 */
mbed_official 0:51ac1d130fd4 1331 void
mbed_official 0:51ac1d130fd4 1332 tcp_accept(struct tcp_pcb *pcb, tcp_accept_fn accept)
mbed_official 0:51ac1d130fd4 1333 {
mbed_official 0:51ac1d130fd4 1334 pcb->accept = accept;
mbed_official 0:51ac1d130fd4 1335 }
mbed_official 0:51ac1d130fd4 1336 #endif /* LWIP_CALLBACK_API */
mbed_official 0:51ac1d130fd4 1337
mbed_official 0:51ac1d130fd4 1338
mbed_official 0:51ac1d130fd4 1339 /**
mbed_official 0:51ac1d130fd4 1340 * Used to specify the function that should be called periodically
mbed_official 0:51ac1d130fd4 1341 * from TCP. The interval is specified in terms of the TCP coarse
mbed_official 0:51ac1d130fd4 1342 * timer interval, which is called twice a second.
mbed_official 0:51ac1d130fd4 1343 *
mbed_official 0:51ac1d130fd4 1344 */
mbed_official 0:51ac1d130fd4 1345 void
mbed_official 0:51ac1d130fd4 1346 tcp_poll(struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval)
mbed_official 0:51ac1d130fd4 1347 {
mbed_official 0:51ac1d130fd4 1348 #if LWIP_CALLBACK_API
mbed_official 0:51ac1d130fd4 1349 pcb->poll = poll;
mbed_official 0:51ac1d130fd4 1350 #else /* LWIP_CALLBACK_API */
mbed_official 0:51ac1d130fd4 1351 LWIP_UNUSED_ARG(poll);
mbed_official 0:51ac1d130fd4 1352 #endif /* LWIP_CALLBACK_API */
mbed_official 0:51ac1d130fd4 1353 pcb->pollinterval = interval;
mbed_official 0:51ac1d130fd4 1354 }
mbed_official 0:51ac1d130fd4 1355
mbed_official 0:51ac1d130fd4 1356 /**
mbed_official 0:51ac1d130fd4 1357 * Purges a TCP PCB. Removes any buffered data and frees the buffer memory
mbed_official 0:51ac1d130fd4 1358 * (pcb->ooseq, pcb->unsent and pcb->unacked are freed).
mbed_official 0:51ac1d130fd4 1359 *
mbed_official 0:51ac1d130fd4 1360 * @param pcb tcp_pcb to purge. The pcb itself is not deallocated!
mbed_official 0:51ac1d130fd4 1361 */
mbed_official 0:51ac1d130fd4 1362 void
mbed_official 0:51ac1d130fd4 1363 tcp_pcb_purge(struct tcp_pcb *pcb)
mbed_official 0:51ac1d130fd4 1364 {
mbed_official 0:51ac1d130fd4 1365 if (pcb->state != CLOSED &&
mbed_official 0:51ac1d130fd4 1366 pcb->state != TIME_WAIT &&
mbed_official 0:51ac1d130fd4 1367 pcb->state != LISTEN) {
mbed_official 0:51ac1d130fd4 1368
mbed_official 0:51ac1d130fd4 1369 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n"));
mbed_official 0:51ac1d130fd4 1370
mbed_official 0:51ac1d130fd4 1371 #if TCP_LISTEN_BACKLOG
mbed_official 0:51ac1d130fd4 1372 if (pcb->state == SYN_RCVD) {
mbed_official 0:51ac1d130fd4 1373 /* Need to find the corresponding listen_pcb and decrease its accepts_pending */
mbed_official 0:51ac1d130fd4 1374 struct tcp_pcb_listen *lpcb;
mbed_official 0:51ac1d130fd4 1375 LWIP_ASSERT("tcp_pcb_purge: pcb->state == SYN_RCVD but tcp_listen_pcbs is NULL",
mbed_official 0:51ac1d130fd4 1376 tcp_listen_pcbs.listen_pcbs != NULL);
mbed_official 0:51ac1d130fd4 1377 for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
mbed_official 0:51ac1d130fd4 1378 if ((lpcb->local_port == pcb->local_port) &&
mbed_official 0:51ac1d130fd4 1379 (ip_addr_isany(&lpcb->local_ip) ||
mbed_official 0:51ac1d130fd4 1380 ip_addr_cmp(&pcb->local_ip, &lpcb->local_ip))) {
mbed_official 0:51ac1d130fd4 1381 /* port and address of the listen pcb match the timed-out pcb */
mbed_official 0:51ac1d130fd4 1382 LWIP_ASSERT("tcp_pcb_purge: listen pcb does not have accepts pending",
mbed_official 0:51ac1d130fd4 1383 lpcb->accepts_pending > 0);
mbed_official 0:51ac1d130fd4 1384 lpcb->accepts_pending--;
mbed_official 0:51ac1d130fd4 1385 break;
mbed_official 0:51ac1d130fd4 1386 }
mbed_official 0:51ac1d130fd4 1387 }
mbed_official 0:51ac1d130fd4 1388 }
mbed_official 0:51ac1d130fd4 1389 #endif /* TCP_LISTEN_BACKLOG */
mbed_official 0:51ac1d130fd4 1390
mbed_official 0:51ac1d130fd4 1391
mbed_official 0:51ac1d130fd4 1392 if (pcb->refused_data != NULL) {
mbed_official 0:51ac1d130fd4 1393 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->refused_data\n"));
mbed_official 0:51ac1d130fd4 1394 pbuf_free(pcb->refused_data);
mbed_official 0:51ac1d130fd4 1395 pcb->refused_data = NULL;
mbed_official 0:51ac1d130fd4 1396 }
mbed_official 0:51ac1d130fd4 1397 if (pcb->unsent != NULL) {
mbed_official 0:51ac1d130fd4 1398 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: not all data sent\n"));
mbed_official 0:51ac1d130fd4 1399 }
mbed_official 0:51ac1d130fd4 1400 if (pcb->unacked != NULL) {
mbed_official 0:51ac1d130fd4 1401 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->unacked\n"));
mbed_official 0:51ac1d130fd4 1402 }
mbed_official 0:51ac1d130fd4 1403 #if TCP_QUEUE_OOSEQ
mbed_official 0:51ac1d130fd4 1404 if (pcb->ooseq != NULL) {
mbed_official 0:51ac1d130fd4 1405 LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->ooseq\n"));
mbed_official 0:51ac1d130fd4 1406 }
mbed_official 0:51ac1d130fd4 1407 tcp_segs_free(pcb->ooseq);
mbed_official 0:51ac1d130fd4 1408 pcb->ooseq = NULL;
mbed_official 0:51ac1d130fd4 1409 #endif /* TCP_QUEUE_OOSEQ */
mbed_official 0:51ac1d130fd4 1410
mbed_official 0:51ac1d130fd4 1411 /* Stop the retransmission timer as it will expect data on unacked
mbed_official 0:51ac1d130fd4 1412 queue if it fires */
mbed_official 0:51ac1d130fd4 1413 pcb->rtime = -1;
mbed_official 0:51ac1d130fd4 1414
mbed_official 0:51ac1d130fd4 1415 tcp_segs_free(pcb->unsent);
mbed_official 0:51ac1d130fd4 1416 tcp_segs_free(pcb->unacked);
mbed_official 0:51ac1d130fd4 1417 pcb->unacked = pcb->unsent = NULL;
mbed_official 0:51ac1d130fd4 1418 #if TCP_OVERSIZE
mbed_official 0:51ac1d130fd4 1419 pcb->unsent_oversize = 0;
mbed_official 0:51ac1d130fd4 1420 #endif /* TCP_OVERSIZE */
mbed_official 0:51ac1d130fd4 1421 }
mbed_official 0:51ac1d130fd4 1422 }
mbed_official 0:51ac1d130fd4 1423
mbed_official 0:51ac1d130fd4 1424 /**
mbed_official 0:51ac1d130fd4 1425 * Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first.
mbed_official 0:51ac1d130fd4 1426 *
mbed_official 0:51ac1d130fd4 1427 * @param pcblist PCB list to purge.
mbed_official 0:51ac1d130fd4 1428 * @param pcb tcp_pcb to purge. The pcb itself is NOT deallocated!
mbed_official 0:51ac1d130fd4 1429 */
mbed_official 0:51ac1d130fd4 1430 void
mbed_official 0:51ac1d130fd4 1431 tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb)
mbed_official 0:51ac1d130fd4 1432 {
mbed_official 0:51ac1d130fd4 1433 TCP_RMV(pcblist, pcb);
mbed_official 0:51ac1d130fd4 1434
mbed_official 0:51ac1d130fd4 1435 tcp_pcb_purge(pcb);
mbed_official 0:51ac1d130fd4 1436
mbed_official 0:51ac1d130fd4 1437 /* if there is an outstanding delayed ACKs, send it */
mbed_official 0:51ac1d130fd4 1438 if (pcb->state != TIME_WAIT &&
mbed_official 0:51ac1d130fd4 1439 pcb->state != LISTEN &&
mbed_official 0:51ac1d130fd4 1440 pcb->flags & TF_ACK_DELAY) {
mbed_official 0:51ac1d130fd4 1441 pcb->flags |= TF_ACK_NOW;
mbed_official 0:51ac1d130fd4 1442 tcp_output(pcb);
mbed_official 0:51ac1d130fd4 1443 }
mbed_official 0:51ac1d130fd4 1444
mbed_official 0:51ac1d130fd4 1445 if (pcb->state != LISTEN) {
mbed_official 0:51ac1d130fd4 1446 LWIP_ASSERT("unsent segments leaking", pcb->unsent == NULL);
mbed_official 0:51ac1d130fd4 1447 LWIP_ASSERT("unacked segments leaking", pcb->unacked == NULL);
mbed_official 0:51ac1d130fd4 1448 #if TCP_QUEUE_OOSEQ
mbed_official 0:51ac1d130fd4 1449 LWIP_ASSERT("ooseq segments leaking", pcb->ooseq == NULL);
mbed_official 0:51ac1d130fd4 1450 #endif /* TCP_QUEUE_OOSEQ */
mbed_official 0:51ac1d130fd4 1451 }
mbed_official 0:51ac1d130fd4 1452
mbed_official 0:51ac1d130fd4 1453 pcb->state = CLOSED;
mbed_official 0:51ac1d130fd4 1454
mbed_official 0:51ac1d130fd4 1455 LWIP_ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane());
mbed_official 0:51ac1d130fd4 1456 }
mbed_official 0:51ac1d130fd4 1457
mbed_official 0:51ac1d130fd4 1458 /**
mbed_official 0:51ac1d130fd4 1459 * Calculates a new initial sequence number for new connections.
mbed_official 0:51ac1d130fd4 1460 *
mbed_official 0:51ac1d130fd4 1461 * @return u32_t pseudo random sequence number
mbed_official 0:51ac1d130fd4 1462 */
mbed_official 0:51ac1d130fd4 1463 u32_t
mbed_official 0:51ac1d130fd4 1464 tcp_next_iss(void)
mbed_official 0:51ac1d130fd4 1465 {
mbed_official 0:51ac1d130fd4 1466 static u32_t iss = 6510;
mbed_official 0:51ac1d130fd4 1467
mbed_official 0:51ac1d130fd4 1468 iss += tcp_ticks; /* XXX */
mbed_official 0:51ac1d130fd4 1469 return iss;
mbed_official 0:51ac1d130fd4 1470 }
mbed_official 0:51ac1d130fd4 1471
mbed_official 0:51ac1d130fd4 1472 #if TCP_CALCULATE_EFF_SEND_MSS
mbed_official 0:51ac1d130fd4 1473 /**
mbed_official 0:51ac1d130fd4 1474 * Calcluates the effective send mss that can be used for a specific IP address
mbed_official 0:51ac1d130fd4 1475 * by using ip_route to determin the netif used to send to the address and
mbed_official 0:51ac1d130fd4 1476 * calculating the minimum of TCP_MSS and that netif's mtu (if set).
mbed_official 0:51ac1d130fd4 1477 */
mbed_official 0:51ac1d130fd4 1478 u16_t
mbed_official 0:51ac1d130fd4 1479 tcp_eff_send_mss(u16_t sendmss, ip_addr_t *addr)
mbed_official 0:51ac1d130fd4 1480 {
mbed_official 0:51ac1d130fd4 1481 u16_t mss_s;
mbed_official 0:51ac1d130fd4 1482 struct netif *outif;
mbed_official 0:51ac1d130fd4 1483
mbed_official 0:51ac1d130fd4 1484 outif = ip_route(addr);
mbed_official 0:51ac1d130fd4 1485 if ((outif != NULL) && (outif->mtu != 0)) {
mbed_official 0:51ac1d130fd4 1486 mss_s = outif->mtu - IP_HLEN - TCP_HLEN;
mbed_official 0:51ac1d130fd4 1487 /* RFC 1122, chap 4.2.2.6:
mbed_official 0:51ac1d130fd4 1488 * Eff.snd.MSS = min(SendMSS+20, MMS_S) - TCPhdrsize - IPoptionsize
mbed_official 0:51ac1d130fd4 1489 * We correct for TCP options in tcp_write(), and don't support IP options.
mbed_official 0:51ac1d130fd4 1490 */
mbed_official 0:51ac1d130fd4 1491 sendmss = LWIP_MIN(sendmss, mss_s);
mbed_official 0:51ac1d130fd4 1492 }
mbed_official 0:51ac1d130fd4 1493 return sendmss;
mbed_official 0:51ac1d130fd4 1494 }
mbed_official 0:51ac1d130fd4 1495 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
mbed_official 0:51ac1d130fd4 1496
mbed_official 0:51ac1d130fd4 1497 const char*
mbed_official 0:51ac1d130fd4 1498 tcp_debug_state_str(enum tcp_state s)
mbed_official 0:51ac1d130fd4 1499 {
mbed_official 0:51ac1d130fd4 1500 return tcp_state_str[s];
mbed_official 0:51ac1d130fd4 1501 }
mbed_official 0:51ac1d130fd4 1502
mbed_official 0:51ac1d130fd4 1503 #if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
mbed_official 0:51ac1d130fd4 1504 /**
mbed_official 0:51ac1d130fd4 1505 * Print a tcp header for debugging purposes.
mbed_official 0:51ac1d130fd4 1506 *
mbed_official 0:51ac1d130fd4 1507 * @param tcphdr pointer to a struct tcp_hdr
mbed_official 0:51ac1d130fd4 1508 */
mbed_official 0:51ac1d130fd4 1509 void
mbed_official 0:51ac1d130fd4 1510 tcp_debug_print(struct tcp_hdr *tcphdr)
mbed_official 0:51ac1d130fd4 1511 {
mbed_official 0:51ac1d130fd4 1512 LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n"));
mbed_official 0:51ac1d130fd4 1513 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
mbed_official 0:51ac1d130fd4 1514 LWIP_DEBUGF(TCP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n",
mbed_official 0:51ac1d130fd4 1515 ntohs(tcphdr->src), ntohs(tcphdr->dest)));
mbed_official 0:51ac1d130fd4 1516 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
mbed_official 0:51ac1d130fd4 1517 LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (seq no)\n",
mbed_official 0:51ac1d130fd4 1518 ntohl(tcphdr->seqno)));
mbed_official 0:51ac1d130fd4 1519 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
mbed_official 0:51ac1d130fd4 1520 LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (ack no)\n",
mbed_official 0:51ac1d130fd4 1521 ntohl(tcphdr->ackno)));
mbed_official 0:51ac1d130fd4 1522 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
mbed_official 0:51ac1d130fd4 1523 LWIP_DEBUGF(TCP_DEBUG, ("| %2"U16_F" | |%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"| %5"U16_F" | (hdrlen, flags (",
mbed_official 0:51ac1d130fd4 1524 TCPH_HDRLEN(tcphdr),
mbed_official 0:51ac1d130fd4 1525 TCPH_FLAGS(tcphdr) >> 5 & 1,
mbed_official 0:51ac1d130fd4 1526 TCPH_FLAGS(tcphdr) >> 4 & 1,
mbed_official 0:51ac1d130fd4 1527 TCPH_FLAGS(tcphdr) >> 3 & 1,
mbed_official 0:51ac1d130fd4 1528 TCPH_FLAGS(tcphdr) >> 2 & 1,
mbed_official 0:51ac1d130fd4 1529 TCPH_FLAGS(tcphdr) >> 1 & 1,
mbed_official 0:51ac1d130fd4 1530 TCPH_FLAGS(tcphdr) & 1,
mbed_official 0:51ac1d130fd4 1531 ntohs(tcphdr->wnd)));
mbed_official 0:51ac1d130fd4 1532 tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
mbed_official 0:51ac1d130fd4 1533 LWIP_DEBUGF(TCP_DEBUG, ("), win)\n"));
mbed_official 0:51ac1d130fd4 1534 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
mbed_official 0:51ac1d130fd4 1535 LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04"X16_F" | %5"U16_F" | (chksum, urgp)\n",
mbed_official 0:51ac1d130fd4 1536 ntohs(tcphdr->chksum), ntohs(tcphdr->urgp)));
mbed_official 0:51ac1d130fd4 1537 LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
mbed_official 0:51ac1d130fd4 1538 }
mbed_official 0:51ac1d130fd4 1539
mbed_official 0:51ac1d130fd4 1540 /**
mbed_official 0:51ac1d130fd4 1541 * Print a tcp state for debugging purposes.
mbed_official 0:51ac1d130fd4 1542 *
mbed_official 0:51ac1d130fd4 1543 * @param s enum tcp_state to print
mbed_official 0:51ac1d130fd4 1544 */
mbed_official 0:51ac1d130fd4 1545 void
mbed_official 0:51ac1d130fd4 1546 tcp_debug_print_state(enum tcp_state s)
mbed_official 0:51ac1d130fd4 1547 {
mbed_official 0:51ac1d130fd4 1548 LWIP_DEBUGF(TCP_DEBUG, ("State: %s\n", tcp_state_str[s]));
mbed_official 0:51ac1d130fd4 1549 }
mbed_official 0:51ac1d130fd4 1550
mbed_official 0:51ac1d130fd4 1551 /**
mbed_official 0:51ac1d130fd4 1552 * Print tcp flags for debugging purposes.
mbed_official 0:51ac1d130fd4 1553 *
mbed_official 0:51ac1d130fd4 1554 * @param flags tcp flags, all active flags are printed
mbed_official 0:51ac1d130fd4 1555 */
mbed_official 0:51ac1d130fd4 1556 void
mbed_official 0:51ac1d130fd4 1557 tcp_debug_print_flags(u8_t flags)
mbed_official 0:51ac1d130fd4 1558 {
mbed_official 0:51ac1d130fd4 1559 if (flags & TCP_FIN) {
mbed_official 0:51ac1d130fd4 1560 LWIP_DEBUGF(TCP_DEBUG, ("FIN "));
mbed_official 0:51ac1d130fd4 1561 }
mbed_official 0:51ac1d130fd4 1562 if (flags & TCP_SYN) {
mbed_official 0:51ac1d130fd4 1563 LWIP_DEBUGF(TCP_DEBUG, ("SYN "));
mbed_official 0:51ac1d130fd4 1564 }
mbed_official 0:51ac1d130fd4 1565 if (flags & TCP_RST) {
mbed_official 0:51ac1d130fd4 1566 LWIP_DEBUGF(TCP_DEBUG, ("RST "));
mbed_official 0:51ac1d130fd4 1567 }
mbed_official 0:51ac1d130fd4 1568 if (flags & TCP_PSH) {
mbed_official 0:51ac1d130fd4 1569 LWIP_DEBUGF(TCP_DEBUG, ("PSH "));
mbed_official 0:51ac1d130fd4 1570 }
mbed_official 0:51ac1d130fd4 1571 if (flags & TCP_ACK) {
mbed_official 0:51ac1d130fd4 1572 LWIP_DEBUGF(TCP_DEBUG, ("ACK "));
mbed_official 0:51ac1d130fd4 1573 }
mbed_official 0:51ac1d130fd4 1574 if (flags & TCP_URG) {
mbed_official 0:51ac1d130fd4 1575 LWIP_DEBUGF(TCP_DEBUG, ("URG "));
mbed_official 0:51ac1d130fd4 1576 }
mbed_official 0:51ac1d130fd4 1577 if (flags & TCP_ECE) {
mbed_official 0:51ac1d130fd4 1578 LWIP_DEBUGF(TCP_DEBUG, ("ECE "));
mbed_official 0:51ac1d130fd4 1579 }
mbed_official 0:51ac1d130fd4 1580 if (flags & TCP_CWR) {
mbed_official 0:51ac1d130fd4 1581 LWIP_DEBUGF(TCP_DEBUG, ("CWR "));
mbed_official 0:51ac1d130fd4 1582 }
mbed_official 0:51ac1d130fd4 1583 LWIP_DEBUGF(TCP_DEBUG, ("\n"));
mbed_official 0:51ac1d130fd4 1584 }
mbed_official 0:51ac1d130fd4 1585
mbed_official 0:51ac1d130fd4 1586 /**
mbed_official 0:51ac1d130fd4 1587 * Print all tcp_pcbs in every list for debugging purposes.
mbed_official 0:51ac1d130fd4 1588 */
mbed_official 0:51ac1d130fd4 1589 void
mbed_official 0:51ac1d130fd4 1590 tcp_debug_print_pcbs(void)
mbed_official 0:51ac1d130fd4 1591 {
mbed_official 0:51ac1d130fd4 1592 struct tcp_pcb *pcb;
mbed_official 0:51ac1d130fd4 1593 LWIP_DEBUGF(TCP_DEBUG, ("Active PCB states:\n"));
mbed_official 0:51ac1d130fd4 1594 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
mbed_official 0:51ac1d130fd4 1595 LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ",
mbed_official 0:51ac1d130fd4 1596 pcb->local_port, pcb->remote_port,
mbed_official 0:51ac1d130fd4 1597 pcb->snd_nxt, pcb->rcv_nxt));
mbed_official 0:51ac1d130fd4 1598 tcp_debug_print_state(pcb->state);
mbed_official 0:51ac1d130fd4 1599 }
mbed_official 0:51ac1d130fd4 1600 LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n"));
mbed_official 0:51ac1d130fd4 1601 for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) {
mbed_official 0:51ac1d130fd4 1602 LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ",
mbed_official 0:51ac1d130fd4 1603 pcb->local_port, pcb->remote_port,
mbed_official 0:51ac1d130fd4 1604 pcb->snd_nxt, pcb->rcv_nxt));
mbed_official 0:51ac1d130fd4 1605 tcp_debug_print_state(pcb->state);
mbed_official 0:51ac1d130fd4 1606 }
mbed_official 0:51ac1d130fd4 1607 LWIP_DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n"));
mbed_official 0:51ac1d130fd4 1608 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
mbed_official 0:51ac1d130fd4 1609 LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ",
mbed_official 0:51ac1d130fd4 1610 pcb->local_port, pcb->remote_port,
mbed_official 0:51ac1d130fd4 1611 pcb->snd_nxt, pcb->rcv_nxt));
mbed_official 0:51ac1d130fd4 1612 tcp_debug_print_state(pcb->state);
mbed_official 0:51ac1d130fd4 1613 }
mbed_official 0:51ac1d130fd4 1614 }
mbed_official 0:51ac1d130fd4 1615
mbed_official 0:51ac1d130fd4 1616 /**
mbed_official 0:51ac1d130fd4 1617 * Check state consistency of the tcp_pcb lists.
mbed_official 0:51ac1d130fd4 1618 */
mbed_official 0:51ac1d130fd4 1619 s16_t
mbed_official 0:51ac1d130fd4 1620 tcp_pcbs_sane(void)
mbed_official 0:51ac1d130fd4 1621 {
mbed_official 0:51ac1d130fd4 1622 struct tcp_pcb *pcb;
mbed_official 0:51ac1d130fd4 1623 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
mbed_official 0:51ac1d130fd4 1624 LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != CLOSED", pcb->state != CLOSED);
mbed_official 0:51ac1d130fd4 1625 LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != LISTEN", pcb->state != LISTEN);
mbed_official 0:51ac1d130fd4 1626 LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
mbed_official 0:51ac1d130fd4 1627 }
mbed_official 0:51ac1d130fd4 1628 for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
mbed_official 0:51ac1d130fd4 1629 LWIP_ASSERT("tcp_pcbs_sane: tw pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
mbed_official 0:51ac1d130fd4 1630 }
mbed_official 0:51ac1d130fd4 1631 return 1;
mbed_official 0:51ac1d130fd4 1632 }
mbed_official 0:51ac1d130fd4 1633 #endif /* TCP_DEBUG */
mbed_official 0:51ac1d130fd4 1634
mbed_official 0:51ac1d130fd4 1635 #endif /* LWIP_TCP */