1 /** 2 * @file 3 * TCP internal implementations (do not use in application code) 4 */ 5 6 /* 7 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without modification, 11 * are permitted provided that the following conditions are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright notice, 14 * this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright notice, 16 * this list of conditions and the following disclaimer in the documentation 17 * and/or other materials provided with the distribution. 18 * 3. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 24 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 26 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 29 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 30 * OF SUCH DAMAGE. 31 * 32 * This file is part of the lwIP TCP/IP stack. 33 * 34 * Author: Adam Dunkels <adam@sics.se> 35 * 36 */ 37 #ifndef LWIP_HDR_TCP_PRIV_H 38 #define LWIP_HDR_TCP_PRIV_H 39 40 #include "lwip/opt.h" 41 42 #if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ 43 44 #include "lwip/tcp.h" 45 #include "lwip/mem.h" 46 #include "lwip/pbuf.h" 47 #include "lwip/ip.h" 48 #include "lwip/icmp.h" 49 #include "lwip/err.h" 50 #include "lwip/ip6.h" 51 #include "lwip/ip6_addr.h" 52 #include "lwip/prot/tcp.h" 53 54 #if defined (__cplusplus) && __cplusplus 55 extern "C" { 56 #endif 57 58 /* Functions for interfacing with TCP: */ 59 60 /* Lower layer interface to TCP: */ 61 void tcp_init (void); /* Initialize this module. */ 62 void tcp_tmr (void); /* Must be called every 63 TCP_TMR_INTERVAL 64 ms. (Typically 250 ms). */ 65 /* It is also possible to call these two functions at the right 66 intervals (instead of calling tcp_tmr()). */ 67 void tcp_slowtmr (void); 68 void tcp_fasttmr (void); 69 70 #if LWIP_API_RICH 71 /* Call this from a netif driver (watch out for threading issues!) that has 72 returned a memory error on transmit and now has free buffers to send more. 73 This iterates all active pcbs that had an error and tries to call 74 tcp_output, so use this with care as it might slow down the system. */ 75 void tcp_txnow (void); 76 #endif /* LWIP_API_RICH */ 77 78 /* Only used by IP to pass a TCP segment to TCP: */ 79 void tcp_input (struct pbuf *p, struct netif *inp); 80 /* Used within the TCP code only: */ 81 struct tcp_pcb *tcp_alloc (u8_t prio); 82 void tcp_free (struct tcp_pcb *pcb); 83 void tcp_abandon (struct tcp_pcb *pcb, int reset); 84 void tcp_send_rst_abort (struct tcp_pcb *pcb, int reset); 85 err_t tcp_send_empty_ack(struct tcp_pcb *pcb); 86 err_t tcp_rexmit (struct tcp_pcb *pcb); 87 void tcp_rexmit_rto (struct tcp_pcb *pcb); 88 void tcp_rexmit_fast (struct tcp_pcb *pcb); 89 u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb); 90 err_t tcp_process_refused_data(struct tcp_pcb *pcb); 91 92 93 #define TCP_SEQ_LT(a, b) ((s32_t)((u32_t)(a) - (u32_t)(b)) < 0) 94 #define TCP_SEQ_LEQ(a, b) ((s32_t)((u32_t)(a) - (u32_t)(b)) <= 0) 95 #define TCP_SEQ_GT(a, b) ((s32_t)((u32_t)(a) - (u32_t)(b)) > 0) 96 #define TCP_SEQ_GEQ(a, b) ((s32_t)((u32_t)(a) - (u32_t)(b)) >= 0) 97 /* is b <= a <=c ? */ 98 /* see bug #10548 */ 99 #define TCP_SEQ_BETWEEN(a, b, c) (TCP_SEQ_GEQ(a, b) && TCP_SEQ_LEQ(a, c)) 100 101 /* Minshall's variant of the Nagle send check. */ 102 #define tcp_nagle_minshall_check(tpcb) (TCP_SEQ_GT(tpcb->snd_sml, tpcb->lastack) && TCP_SEQ_LEQ(tpcb->snd_sml, tpcb->snd_nxt)) 103 104 /** 105 * This is the Nagle algorithm: try to combine usrdata to send as few TCP 106 * segments as possible. Only send if 107 * - no previously transmitted data on the connection remains unacknowledged or 108 * - the TF_NODELAY flag is set (nagle algorithm turned off for this pcb) or 109 * - the only unsent segment is at least pcb->mss bytes long (or there is more 110 * than one unsent segment - with lwIP, this can happen although unsent->len < mss) 111 * - or if we are in fast-retransmit (TF_INFR) 112 * - With Minshall's variant: all sent small packets are ACKed. 113 */ 114 #define tcp_do_output_nagle(tpcb) ((((tpcb)->unacked == NULL) || \ 115 ((tpcb)->flags & (TF_NODELAY | TF_INFR)) || \ 116 (((tpcb)->unsent != NULL) && (((tpcb)->unsent->next != NULL) || \ 117 ((tpcb)->unsent->len >= (tpcb)->mss) || !tcp_nagle_minshall_check(tpcb))) \ 118 ) ? 1 : 0) 119 120 #define tcp_output_nagle(tpcb) (tcp_do_output_nagle(tpcb) ? tcp_output(tpcb) : ERR_OK) 121 122 /* 123 * 100 value looks awkward, 124 * A fast timer every 100 milliseconds (yet beats delay ack duration of 200msec of linux.) 125 * Slow timer every 200 milliseconds, 126 */ 127 #ifndef TCP_TMR_INTERVAL 128 #define TCP_TMR_INTERVAL 100 /* The TCP timer interval in milliseconds. */ 129 #endif /* TCP_TMR_INTERVAL */ 130 131 #ifndef TCP_FAST_INTERVAL 132 #define TCP_FAST_INTERVAL TCP_TMR_INTERVAL /* the fine grained timeout in milliseconds */ 133 #endif /* TCP_FAST_INTERVAL */ 134 135 #ifndef TCP_SLOW_INTERVAL 136 137 #ifndef TCP_SLOW_INTERVAL_PERIOD 138 #define TCP_SLOW_INTERVAL_PERIOD 2 /* the fine grained timeout in milliseconds */ 139 #endif /* TCP_SLOW_INTERVAL_PERIOD */ 140 141 /* the coarse grained timeout in milliseconds */ 142 #define TCP_SLOW_INTERVAL (TCP_SLOW_INTERVAL_PERIOD * TCP_TMR_INTERVAL) 143 #endif /* TCP_SLOW_INTERVAL */ 144 145 /** 146 * @cond liteos 147 * TCP_INITIAL_RTO_DURATION: Minimum RTO default duration has been reduced to 1 second from 3 seconds, RFC6298 148 */ 149 #ifndef TCP_INITIAL_RTO_DURATION 150 #define TCP_INITIAL_RTO_DURATION 1000 151 #endif 152 153 /* RTO druation of 400ms ensures that RTO expiry will be always between 200ms-400ms */ 154 #ifndef TCP_MIN_RTO_DURATION 155 #define TCP_MIN_RTO_DURATION 400 156 #endif 157 158 #ifndef TCP_RTO_DURATION_AFTER_SYN_RTX 159 #define TCP_RTO_DURATION_AFTER_SYN_RTX 3000 160 #endif 161 162 /** 163 * TCP_MAX_RTO_DURATION A maximum value MAY be placed on RTO provided it is at least 60 seconds. 164 */ 165 #ifndef TCP_MAX_RTO_DURATION 166 #define TCP_MAX_RTO_DURATION 60000 167 #endif 168 169 #ifndef TCP_MIN_RTO_TICKS 170 #define TCP_MIN_RTO_TICKS (TCP_MIN_RTO_DURATION / TCP_SLOW_INTERVAL) 171 #endif 172 173 #ifndef TCP_MAX_RTO_TICKS 174 #define TCP_MAX_RTO_TICKS (TCP_MAX_RTO_DURATION / TCP_SLOW_INTERVAL) 175 #endif 176 177 #ifndef TCP_RTO_TICKS_AFTER_SYN_RTX 178 #define TCP_RTO_TICKS_AFTER_SYN_RTX (TCP_RTO_DURATION_AFTER_SYN_RTX / TCP_SLOW_INTERVAL) 179 #endif 180 181 #if DRIVER_STATUS_CHECK 182 /* will round off to the higher value in case it is not multiples of TCP_SLOW_INTERVAL */ 183 #define DRIVER_WAKEUP_COUNT ((DRIVER_WAKEUP_INTERVAL + (TCP_SLOW_INTERVAL - 1)) / TCP_SLOW_INTERVAL) 184 #endif 185 186 #define TCP_FIN_WAIT_TIMEOUT 20000 /* milliseconds */ 187 #define TCP_SYN_RCVD_TIMEOUT 20000 /* milliseconds */ 188 189 #define TCP_OOSEQ_TIMEOUT 6 /* x RTO */ 190 191 #ifndef TCP_MSL 192 #define TCP_MSL 60000UL /* The maximum segment lifetime in milliseconds */ 193 #endif 194 195 /* Keepalive values, compliant with RFC 1122. Don't change this unless you know what you're doing */ 196 #ifndef TCP_KEEPIDLE_DEFAULT 197 #define TCP_KEEPIDLE_DEFAULT 7200000UL /* Default KEEPALIVE timer in milliseconds */ 198 #endif 199 200 #ifndef TCP_KEEPINTVL_DEFAULT 201 #define TCP_KEEPINTVL_DEFAULT 75000UL /* Default Time between KEEPALIVE probes in milliseconds */ 202 #endif 203 204 #ifndef TCP_KEEPCNT_DEFAULT 205 #define TCP_KEEPCNT_DEFAULT 9U /* Default Counter for KEEPALIVE probes */ 206 #endif 207 208 #define TCP_MAXIDLE TCP_KEEPCNT_DEFAULT * TCP_KEEPINTVL_DEFAULT /* Maximum KEEPALIVE probe time */ 209 210 #define TCP_TCPLEN(seg) ((seg)->len + (((TCPH_FLAGS((seg)->tcphdr) & (TCP_FIN | TCP_SYN)) != 0) ? 1U : 0U)) 211 212 /** Flags used on input processing, not on pcb->flags 213 */ 214 #define TF_RESET (u8_t)0x08U /* Connection was reset. */ 215 #define TF_CLOSED (u8_t)0x10U /* Connection was successfully closed. */ 216 #define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */ 217 218 219 #if LWIP_EVENT_API 220 221 #define TCP_EVENT_ACCEPT(lpcb, pcb, arg, err, ret) ret = lwip_tcp_event(arg, (pcb), \ 222 LWIP_EVENT_ACCEPT, NULL, 0, err) 223 #define TCP_EVENT_SENT(pcb, space, ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb), \ 224 LWIP_EVENT_SENT, NULL, space, ERR_OK) 225 #define TCP_EVENT_RECV(pcb, p, err, ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb), \ 226 LWIP_EVENT_RECV, (p), 0, (err)) 227 #define TCP_EVENT_CLOSED(pcb, ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb), \ 228 LWIP_EVENT_RECV, NULL, 0, ERR_OK) 229 #define TCP_EVENT_CONNECTED(pcb, err, ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb), \ 230 LWIP_EVENT_CONNECTED, NULL, 0, (err)) 231 #define TCP_EVENT_POLL(pcb, ret) \ 232 do { \ 233 if ((pcb)->state != SYN_RCVD) { \ 234 ret = lwip_tcp_event((pcb)->callback_arg, (pcb), LWIP_EVENT_POLL, NULL, 0, ERR_OK); \ 235 } else { \ 236 ret = ERR_ARG; \ 237 } \ 238 } while (0) 239 #define TCP_EVENT_ERR(last_state, errf, arg, err) do { if (last_state != SYN_RCVD) { \ 240 lwip_tcp_event((arg), NULL, LWIP_EVENT_ERR, NULL, 0, (err)); } } while (0) 241 242 #else /* LWIP_EVENT_API */ 243 244 #define TCP_EVENT_ACCEPT(lpcb, pcb, arg, err, ret) \ 245 do { \ 246 if ((lpcb)->accept != NULL) { \ 247 (ret) = (lpcb)->accept((arg), (pcb), (err)); \ 248 } else { \ 249 (ret) = ERR_ARG; \ 250 } \ 251 } while (0) 252 253 #define TCP_EVENT_SENT(pcb, space, ret) \ 254 do { \ 255 if ((pcb)->sent != NULL) { \ 256 (ret) = (pcb)->sent((pcb)->callback_arg, (pcb), (space)); \ 257 } else { \ 258 (ret) = ERR_OK; \ 259 } \ 260 } while (0) 261 262 #define TCP_EVENT_RECV(pcb, p, err, ret) \ 263 do { \ 264 if ((pcb)->recv != NULL) { \ 265 (ret) = (pcb)->recv((pcb)->callback_arg, (pcb), (p), (err)); \ 266 } else { \ 267 (ret) = tcp_recv_null(NULL, (pcb), (p), (err)); \ 268 } \ 269 } while (0) 270 271 #define TCP_EVENT_CLOSED(pcb, ret) \ 272 do { \ 273 if (((pcb)->recv != NULL)) { \ 274 (ret) = (pcb)->recv((pcb)->callback_arg, (pcb), NULL, ERR_OK); \ 275 } else { \ 276 (ret) = ERR_OK; \ 277 } \ 278 } while (0) 279 280 #define TCP_EVENT_CONNECTED(pcb, err, ret) \ 281 do { \ 282 if ((pcb)->connected != NULL) { \ 283 (ret) = (pcb)->connected((pcb)->callback_arg, (pcb), (err)); \ 284 } else { \ 285 (ret) = ERR_OK; \ 286 } \ 287 } while (0) 288 289 #define TCP_EVENT_POLL(pcb, ret) \ 290 do { \ 291 if ((pcb)->poll != NULL) { \ 292 (ret) = (pcb)->poll((pcb)->callback_arg, (pcb)); \ 293 } else { \ 294 (ret) = ERR_OK; \ 295 } \ 296 } while (0) 297 298 #define TCP_EVENT_ERR(last_state, errf, arg, err) \ 299 do { \ 300 LWIP_UNUSED_ARG(last_state); \ 301 if ((errf) != NULL) { \ 302 (errf)((arg), (err)); \ 303 } \ 304 } while (0) 305 306 #endif /* LWIP_EVENT_API */ 307 308 /** Enabled extra-check for TCP_OVERSIZE if LWIP_DEBUG is enabled */ 309 #if TCP_OVERSIZE && defined(LWIP_DEBUG) 310 #define TCP_OVERSIZE_DBGCHECK 1 311 #else 312 #define TCP_OVERSIZE_DBGCHECK 0 313 #endif 314 315 /** Don't generate checksum on copy if CHECKSUM_GEN_TCP is disabled */ 316 #define TCP_CHECKSUM_ON_COPY (LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_TCP) 317 318 /* This structure represents a TCP segment on the unsent, unacked and ooseq queues */ 319 struct tcp_seg { 320 struct tcp_seg *next; /* used when putting segments on a queue */ 321 struct pbuf *p; /* buffer containing data + TCP header */ 322 u16_t len; /* the TCP length of this segment */ 323 #if TCP_OVERSIZE_DBGCHECK 324 u16_t oversize_left; /* Extra bytes available at the end of the last 325 pbuf in unsent (used for asserting vs. 326 tcp_pcb.unsent_oversize only) */ 327 #endif /* TCP_OVERSIZE_DBGCHECK */ 328 #if TCP_CHECKSUM_ON_COPY 329 u16_t chksum; 330 u8_t chksum_swapped; 331 #endif /* TCP_CHECKSUM_ON_COPY */ 332 u8_t flags; 333 #define TF_SEG_OPTS_MSS (u8_t)0x01U /* Include MSS option. */ 334 #define TF_SEG_OPTS_TS (u8_t)0x02U /* Include timestamp option. */ 335 #define TF_SEG_DATA_CHECKSUMMED (u8_t)0x04U /* ALL data (not the header) is 336 checksummed into 'chksum' */ 337 #define TF_SEG_OPTS_WND_SCALE (u8_t)0x08U /* Include WND SCALE option */ 338 339 /* Adding for SACK */ 340 #define TF_SEG_OPTS_SACK (u8_t)0x10U /* Include SACK option */ 341 #define TF_SEG_OPTS_SACK_PERMITTED (u8_t)0x20U /* Include SACK Permitted option */ 342 #define TF_SEG_OPTS_SACK_OPTIONS (u8_t)0x40U /* Include SACK Options */ 343 344 /* Adding for SACK */ 345 #if LWIP_SACK 346 347 u32_t state; /* This will be used to maintain SACK scoreboard as per RFC 6675 */ 348 #define TF_SEG_NONE 0x0000U 349 #define TF_SEG_SACKED 0x0001U /* Segment Sacked */ 350 #define TF_SEG_RETRANSMITTED 0x0002U /* Retransmitted as part of SACK based loss recovery alg */ 351 352 u32_t order; /* order of the segment in the ooseq q */ 353 #if LWIP_SACK_PERF_OPT 354 u32_t pkt_trans_seq_cntr; 355 #endif 356 #endif /* LWIP_SACK */ 357 358 /* NETIF DRIVER STATUS BEGIN */ 359 #if DRIVER_STATUS_CHECK 360 u32_t seg_type; 361 #endif 362 363 struct tcp_hdr *tcphdr; /* the TCP header */ 364 }; 365 366 #define LWIP_TCP_OPT_EOL 0 367 #define LWIP_TCP_OPT_NOP 1 368 #define LWIP_TCP_OPT_MSS 2 369 #define LWIP_TCP_OPT_WS 3 370 #define LWIP_TCP_OPT_TS 8 371 372 /* Adding for SACK */ 373 #define LWIP_TCP_OPT_SACK_PERMITTED 4 374 #define LWIP_TCP_OPT_SACK 5 375 376 377 #define LWIP_TCP_OPT_LEN_MSS 4 378 #if LWIP_TCP_TIMESTAMPS 379 #define LWIP_TCP_OPT_LEN_TS 10 380 #define LWIP_TCP_OPT_LEN_TS_OUT 12 /* aligned for output (includes NOP padding) */ 381 #else 382 #define LWIP_TCP_OPT_LEN_TS_OUT 0 383 #endif 384 #if LWIP_WND_SCALE 385 #define LWIP_TCP_OPT_LEN_WS 3 386 #define LWIP_TCP_OPT_LEN_WS_OUT 4 /* aligned for output (includes NOP padding) */ 387 #else 388 #define LWIP_TCP_OPT_LEN_WS_OUT 0 389 #endif 390 391 #if LWIP_SACK 392 #define LWIP_TCP_OPT_LEN_SACK_PERMITTED 2 393 #define LWIP_TCP_OPT_LEN_SACK_PERMITTED_OUT 4 /* aligned for output (includes NOP padding) */ 394 #else 395 #define LWIP_TCP_OPT_LEN_SACK_PERMITTED_OUT 0 396 #endif 397 398 #define LWIP_TCP_OPT_LENGTH(flags) \ 399 (flags & TF_SEG_OPTS_MSS ? LWIP_TCP_OPT_LEN_MSS : 0) + \ 400 (flags & TF_SEG_OPTS_TS ? LWIP_TCP_OPT_LEN_TS_OUT : 0) + \ 401 (flags & TF_SEG_OPTS_WND_SCALE ? LWIP_TCP_OPT_LEN_WS_OUT : 0) + \ 402 (flags & TF_SEG_OPTS_SACK_PERMITTED ? LWIP_TCP_OPT_LEN_SACK_PERMITTED_OUT : 0) 403 404 /* 4 -> padding + kind + length. 8 -> each SACK block */ 405 #define LWIP_TCP_SACK_OPT_LENGTH(__cnt) __cnt > 0 ? (u8_t)(4 + (__cnt * 8)) : 0 406 407 /** This returns a TCP header option for MSS in an u32_t */ 408 #define TCP_BUILD_MSS_OPTION(mss) lwip_htonl(0x02040000 | ((u32_t)((mss) & 0xFFFF))) 409 410 #if LWIP_WND_SCALE 411 #define TCPWNDSIZE_F U32_F 412 #define TCPWND_MAX 0xFFFFFFFFU 413 #define TCPWND_CHECK16(x) LWIP_ASSERT("window size > 0xFFFF", (x) <= 0xFFFF) 414 #define TCPWND_MIN16(x) ((u16_t)LWIP_MIN((x), 0xFFFF)) 415 #else /* LWIP_WND_SCALE */ 416 #define TCPWNDSIZE_F U16_F 417 #define TCPWND_MAX 0xFFFFU 418 #define TCPWND_CHECK16(x) 419 #define TCPWND_MIN16(x) x 420 #endif /* LWIP_WND_SCALE */ 421 422 /* Global variables: */ 423 extern struct tcp_pcb *tcp_input_pcb; 424 extern u32_t tcp_ticks; 425 extern u8_t tcp_active_pcbs_changed; 426 427 /* The TCP PCB lists. */ 428 union tcp_listen_pcbs_t { /* List of all TCP PCBs in LISTEN state. */ 429 struct tcp_pcb_listen *listen_pcbs; 430 struct tcp_pcb *pcbs; 431 }; 432 extern struct tcp_pcb *tcp_bound_pcbs; 433 extern union tcp_listen_pcbs_t tcp_listen_pcbs; 434 extern struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a 435 state in which they accept or send 436 data. */ 437 extern struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */ 438 439 #define NUM_TCP_PCB_LISTS_NO_TIME_WAIT 3 440 #define NUM_TCP_PCB_LISTS 4 441 extern struct tcp_pcb **const tcp_pcb_lists[NUM_TCP_PCB_LISTS]; 442 443 /* Axioms about the above lists: 444 1) Every TCP PCB that is not CLOSED is in one of the lists. 445 2) A PCB is only in one of the lists. 446 3) All PCBs in the tcp_listen_pcbs list is in LISTEN state. 447 4) All PCBs in the tcp_tw_pcbs list is in TIME-WAIT state. 448 */ 449 /* Define two macros, TCP_REG and TCP_RMV that registers a TCP PCB 450 with a PCB list or removes a PCB from a list, respectively. */ 451 #ifndef TCP_DEBUG_PCB_LISTS 452 #define TCP_DEBUG_PCB_LISTS 0 453 #endif 454 #if TCP_DEBUG_PCB_LISTS 455 #define TCP_REG(pcbs, npcb) do {\ 456 struct tcp_pcb *tcp_tmp_pcb; \ 457 LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %d\n", (npcb), (npcb)->local_port)); \ 458 for (tcp_tmp_pcb = *(pcbs); \ 459 tcp_tmp_pcb != NULL; \ 460 tcp_tmp_pcb = tcp_tmp_pcb->next) { \ 461 LWIP_ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != (npcb)); \ 462 } \ 463 LWIP_ASSERT("TCP_REG: pcb->state != CLOSED", \ 464 ((pcbs) == &tcp_bound_pcbs) || ((npcb)->state != CLOSED)); \ 465 (npcb)->next = *(pcbs); \ 466 LWIP_ASSERT("TCP_REG: npcb->next != npcb", (npcb)->next != (npcb)); \ 467 *(pcbs) = (npcb); \ 468 LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \ 469 tcp_timer_needed(); \ 470 } while (0) 471 #define TCP_RMV(pcbs, npcb) do { \ 472 struct tcp_pcb *tcp_tmp_pcb; \ 473 LWIP_ASSERT("TCP_RMV: pcbs != NULL", *(pcbs) != NULL); \ 474 LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removing %p from %p\n", (npcb), *(pcbs))); \ 475 if (*(pcbs) == (npcb)) { \ 476 *(pcbs) = (*pcbs)->next; \ 477 } else for (tcp_tmp_pcb = *(pcbs); tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \ 478 if (tcp_tmp_pcb->next == (npcb)) { \ 479 tcp_tmp_pcb->next = (npcb)->next; \ 480 break; \ 481 } \ 482 } \ 483 (npcb)->next = NULL; \ 484 LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \ 485 LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", (npcb), *(pcbs))); \ 486 } while (0) 487 488 #else /* LWIP_DEBUG */ 489 490 #define TCP_REG(pcbs, npcb) \ 491 do { \ 492 (npcb)->next = *pcbs; \ 493 *(pcbs) = (npcb); \ 494 tcp_timer_needed(); \ 495 } while (0) 496 497 #if !LWIP_SMALL_SIZE 498 #define TCP_RMV(pcbs, npcb) \ 499 do { \ 500 if (*(pcbs) == (npcb)) { \ 501 (*(pcbs)) = (*pcbs)->next; \ 502 } \ 503 else { \ 504 struct tcp_pcb *tcp_tmp_pcb; \ 505 for (tcp_tmp_pcb = *pcbs; \ 506 tcp_tmp_pcb != NULL; \ 507 tcp_tmp_pcb = tcp_tmp_pcb->next) { \ 508 if (tcp_tmp_pcb->next == (npcb)) { \ 509 tcp_tmp_pcb->next = (npcb)->next; \ 510 break; \ 511 } \ 512 } \ 513 } \ 514 (npcb)->next = NULL; \ 515 } while (0) 516 #else 517 void tcp_remove(struct tcp_pcb **pcbs, struct tcp_pcb *npcb); 518 #define TCP_RMV(pcbs, npcb) tcp_remove(pcbs, npcb) 519 #endif 520 521 #endif /* LWIP_DEBUG */ 522 523 #define TCP_REG_ACTIVE(npcb) \ 524 do { \ 525 TCP_REG(&tcp_active_pcbs, npcb); \ 526 tcp_active_pcbs_changed = 1; \ 527 } while (0) 528 529 #define TCP_RMV_ACTIVE(npcb) \ 530 do { \ 531 TCP_RMV(&tcp_active_pcbs, npcb); \ 532 tcp_active_pcbs_changed = 1; \ 533 } while (0) 534 535 #define TCP_PCB_REMOVE_ACTIVE(pcb) \ 536 do { \ 537 tcp_pcb_remove(&tcp_active_pcbs, pcb); \ 538 tcp_active_pcbs_changed = 1; \ 539 } while (0) 540 541 /* Internal functions: */ 542 struct tcp_pcb *tcp_pcb_copy(struct tcp_pcb *pcb); 543 void tcp_pcb_purge(struct tcp_pcb *pcb); 544 void tcp_listen_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb_listen *lpcb); 545 void tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb); 546 547 #if LWIP_SACK_PERF_OPT 548 void tcp_fr_segs_free(struct tcp_sack_fast_rxmited *seg); 549 #endif 550 551 void tcp_segs_free(struct tcp_seg *seg); 552 void tcp_seg_free(struct tcp_seg *seg); 553 struct tcp_seg *tcp_seg_copy(struct tcp_seg *seg); 554 555 #define tcp_ack(pcb) \ 556 do { \ 557 if ((pcb)->flags & TF_ACK_DELAY) { \ 558 (pcb)->flags &= (tcpflags_t)~TF_ACK_DELAY; \ 559 (pcb)->flags |= TF_ACK_NOW; \ 560 } else { \ 561 (pcb)->flags |= TF_ACK_DELAY; \ 562 } \ 563 } while (0) 564 565 #define tcp_ack_now(pcb) \ 566 do { \ 567 (pcb)->flags |= TF_ACK_NOW; \ 568 } while (0) 569 570 err_t tcp_send_fin(struct tcp_pcb *pcb); 571 err_t tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags); 572 573 void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg); 574 575 void tcp_rst(u32_t seqno, u32_t ackno, 576 const ip_addr_t *local_ip, const ip_addr_t *remote_ip, 577 u16_t local_port, u16_t remote_port, struct tcp_pcb *pcb); 578 579 u32_t tcp_next_iss(struct tcp_pcb *pcb); 580 581 err_t tcp_keepalive(struct tcp_pcb *pcb); 582 err_t tcp_zero_window_probe(struct tcp_pcb *pcb); 583 void tcp_trigger_input_pcb_close(void); 584 585 #if TCP_CALCULATE_EFF_SEND_MSS 586 u16_t tcp_eff_send_mss_impl(u16_t sendmss, const ip_addr_t *dest 587 #if LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING 588 , const ip_addr_t *src 589 #endif /* LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING */ 590 , struct netif *netif); 591 #if LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING 592 #define tcp_eff_send_mss(sendmss, src, dest, netif) tcp_eff_send_mss_impl(sendmss, dest, src, netif) 593 #else /* LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING */ 594 #define tcp_eff_send_mss(sendmss, src, dest, netif) tcp_eff_send_mss_impl(sendmss, dest, netif) 595 #endif /* LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING */ 596 #endif /* TCP_CALCULATE_EFF_SEND_MSS */ 597 598 #if LWIP_CALLBACK_API 599 err_t tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err); 600 #endif /* LWIP_CALLBACK_API */ 601 602 #if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG 603 void tcp_debug_print(struct tcp_hdr *tcphdr); 604 void tcp_debug_print_flags(u8_t flags); 605 void tcp_debug_print_state(enum tcp_state s); 606 void tcp_debug_print_pcbs(void); 607 s16_t tcp_pcbs_sane(void); 608 #else 609 # define tcp_debug_print(tcphdr) 610 # define tcp_debug_print_flags(flags) 611 # define tcp_debug_print_state(s) 612 # define tcp_debug_print_pcbs() 613 # define tcp_pcbs_sane() 1 614 #endif /* TCP_DEBUG */ 615 616 /** External function (implemented in timers.c), called when TCP detects 617 * that a timer is needed (i.e. active- or time-wait-pcb found). */ 618 void tcp_timer_needed(void); 619 620 void tcp_netif_ip_addr_changed(const ip_addr_t *old_addr, const ip_addr_t *new_addr); 621 622 err_t tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb); 623 624 #if LWIP_TCP_PCB_NUM_EXT_ARGS 625 err_t tcp_ext_arg_invoke_callbacks_passive_open(struct tcp_pcb_listen *lpcb, struct tcp_pcb *cpcb); 626 #endif 627 628 #if defined (__cplusplus) && __cplusplus 629 } 630 #endif 631 632 #endif /* LWIP_TCP */ 633 634 #endif /* LWIP_HDR_TCP_PRIV_H */ 635