Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-os by
tcp_priv.h
00001 /** 00002 * @file 00003 * TCP internal implementations (do not use in application code) 00004 */ 00005 00006 /* 00007 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 00008 * All rights reserved. 00009 * 00010 * Redistribution and use in source and binary forms, with or without modification, 00011 * are permitted provided that the following conditions are met: 00012 * 00013 * 1. Redistributions of source code must retain the above copyright notice, 00014 * this list of conditions and the following disclaimer. 00015 * 2. Redistributions in binary form must reproduce the above copyright notice, 00016 * this list of conditions and the following disclaimer in the documentation 00017 * and/or other materials provided with the distribution. 00018 * 3. The name of the author may not be used to endorse or promote products 00019 * derived from this software without specific prior written permission. 00020 * 00021 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00022 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00024 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00025 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00026 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00027 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00028 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00029 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00030 * OF SUCH DAMAGE. 00031 * 00032 * This file is part of the lwIP TCP/IP stack. 00033 * 00034 * Author: Adam Dunkels <adam@sics.se> 00035 * 00036 */ 00037 #ifndef LWIP_HDR_TCP_IMPL_H 00038 #define LWIP_HDR_TCP_IMPL_H 00039 00040 #include "lwip/opt.h" 00041 00042 #if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ 00043 00044 #include "lwip/tcp.h" 00045 #include "lwip/mem.h" 00046 #include "lwip/pbuf.h" 00047 #include "lwip/ip.h" 00048 #include "lwip/icmp.h" 00049 #include "lwip/err.h" 00050 #include "lwip/ip6.h" 00051 #include "lwip/ip6_addr.h" 00052 00053 #ifdef __cplusplus 00054 extern "C" { 00055 #endif 00056 00057 /* Functions for interfacing with TCP: */ 00058 00059 /* Lower layer interface to TCP: */ 00060 void tcp_init (void); /* Initialize this module. */ 00061 void tcp_tmr (void); /* Must be called every 00062 TCP_TMR_INTERVAL 00063 ms. (Typically 250 ms). */ 00064 /* It is also possible to call these two functions at the right 00065 intervals (instead of calling tcp_tmr()). */ 00066 void tcp_slowtmr (void); 00067 void tcp_fasttmr (void); 00068 00069 /* Call this from a netif driver (watch out for threading issues!) that has 00070 returned a memory error on transmit and now has free buffers to send more. 00071 This iterates all active pcbs that had an error and tries to call 00072 tcp_output, so use this with care as it might slow down the system. */ 00073 void tcp_txnow (void); 00074 00075 /* Only used by IP to pass a TCP segment to TCP: */ 00076 void tcp_input (struct pbuf *p, struct netif *inp); 00077 /* Used within the TCP code only: */ 00078 struct tcp_pcb * tcp_alloc (u8_t prio); 00079 void tcp_abandon (struct tcp_pcb *pcb, int reset); 00080 err_t tcp_send_empty_ack(struct tcp_pcb *pcb); 00081 void tcp_rexmit (struct tcp_pcb *pcb); 00082 void tcp_rexmit_rto (struct tcp_pcb *pcb); 00083 void tcp_rexmit_fast (struct tcp_pcb *pcb); 00084 u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb); 00085 err_t tcp_process_refused_data(struct tcp_pcb *pcb); 00086 00087 /** 00088 * This is the Nagle algorithm: try to combine user data to send as few TCP 00089 * segments as possible. Only send if 00090 * - no previously transmitted data on the connection remains unacknowledged or 00091 * - the TF_NODELAY flag is set (nagle algorithm turned off for this pcb) or 00092 * - the only unsent segment is at least pcb->mss bytes long (or there is more 00093 * than one unsent segment - with lwIP, this can happen although unsent->len < mss) 00094 * - or if we are in fast-retransmit (TF_INFR) 00095 */ 00096 #define tcp_do_output_nagle(tpcb) ((((tpcb)->unacked == NULL) || \ 00097 ((tpcb)->flags & (TF_NODELAY | TF_INFR)) || \ 00098 (((tpcb)->unsent != NULL) && (((tpcb)->unsent->next != NULL) || \ 00099 ((tpcb)->unsent->len >= (tpcb)->mss))) || \ 00100 ((tcp_sndbuf(tpcb) == 0) || (tcp_sndqueuelen(tpcb) >= TCP_SND_QUEUELEN)) \ 00101 ) ? 1 : 0) 00102 #define tcp_output_nagle(tpcb) (tcp_do_output_nagle(tpcb) ? tcp_output(tpcb) : ERR_OK) 00103 00104 00105 #define TCP_SEQ_LT(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) < 0) 00106 #define TCP_SEQ_LEQ(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) <= 0) 00107 #define TCP_SEQ_GT(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) > 0) 00108 #define TCP_SEQ_GEQ(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) >= 0) 00109 /* is b<=a<=c? */ 00110 #if 0 /* see bug #10548 */ 00111 #define TCP_SEQ_BETWEEN(a,b,c) ((c)-(b) >= (a)-(b)) 00112 #endif 00113 #define TCP_SEQ_BETWEEN(a,b,c) (TCP_SEQ_GEQ(a,b) && TCP_SEQ_LEQ(a,c)) 00114 #define TCP_FIN 0x01U 00115 #define TCP_SYN 0x02U 00116 #define TCP_RST 0x04U 00117 #define TCP_PSH 0x08U 00118 #define TCP_ACK 0x10U 00119 #define TCP_URG 0x20U 00120 #define TCP_ECE 0x40U 00121 #define TCP_CWR 0x80U 00122 00123 #define TCP_FLAGS 0x3fU 00124 00125 /* Length of the TCP header, excluding options. */ 00126 #define TCP_HLEN 20 00127 00128 #ifndef TCP_TMR_INTERVAL 00129 #define TCP_TMR_INTERVAL 250 /* The TCP timer interval in milliseconds. */ 00130 #endif /* TCP_TMR_INTERVAL */ 00131 00132 #ifndef TCP_FAST_INTERVAL 00133 #define TCP_FAST_INTERVAL TCP_TMR_INTERVAL /* the fine grained timeout in milliseconds */ 00134 #endif /* TCP_FAST_INTERVAL */ 00135 00136 #ifndef TCP_SLOW_INTERVAL 00137 #define TCP_SLOW_INTERVAL (2*TCP_TMR_INTERVAL) /* the coarse grained timeout in milliseconds */ 00138 #endif /* TCP_SLOW_INTERVAL */ 00139 00140 #define TCP_FIN_WAIT_TIMEOUT 20000 /* milliseconds */ 00141 #define TCP_SYN_RCVD_TIMEOUT 20000 /* milliseconds */ 00142 00143 #define TCP_OOSEQ_TIMEOUT 6U /* x RTO */ 00144 00145 #ifndef TCP_MSL 00146 #define TCP_MSL 60000UL /* The maximum segment lifetime in milliseconds */ 00147 #endif 00148 00149 /* Keepalive values, compliant with RFC 1122. Don't change this unless you know what you're doing */ 00150 #ifndef TCP_KEEPIDLE_DEFAULT 00151 #define TCP_KEEPIDLE_DEFAULT 7200000UL /* Default KEEPALIVE timer in milliseconds */ 00152 #endif 00153 00154 #ifndef TCP_KEEPINTVL_DEFAULT 00155 #define TCP_KEEPINTVL_DEFAULT 75000UL /* Default Time between KEEPALIVE probes in milliseconds */ 00156 #endif 00157 00158 #ifndef TCP_KEEPCNT_DEFAULT 00159 #define TCP_KEEPCNT_DEFAULT 9U /* Default Counter for KEEPALIVE probes */ 00160 #endif 00161 00162 #define TCP_MAXIDLE TCP_KEEPCNT_DEFAULT * TCP_KEEPINTVL_DEFAULT /* Maximum KEEPALIVE probe time */ 00163 00164 /* Fields are (of course) in network byte order. 00165 * Some fields are converted to host byte order in tcp_input(). 00166 */ 00167 #ifdef PACK_STRUCT_USE_INCLUDES 00168 # include "arch/bpstruct.h" 00169 #endif 00170 PACK_STRUCT_BEGIN 00171 struct tcp_hdr { 00172 PACK_STRUCT_FIELD(u16_t src); 00173 PACK_STRUCT_FIELD(u16_t dest); 00174 PACK_STRUCT_FIELD(u32_t seqno); 00175 PACK_STRUCT_FIELD(u32_t ackno); 00176 PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags); 00177 PACK_STRUCT_FIELD(u16_t wnd); 00178 PACK_STRUCT_FIELD(u16_t chksum); 00179 PACK_STRUCT_FIELD(u16_t urgp); 00180 } PACK_STRUCT_STRUCT; 00181 PACK_STRUCT_END 00182 #ifdef PACK_STRUCT_USE_INCLUDES 00183 # include "arch/epstruct.h" 00184 #endif 00185 00186 #define TCPH_HDRLEN(phdr) ((u16_t)(ntohs((phdr)->_hdrlen_rsvd_flags) >> 12)) 00187 #define TCPH_FLAGS(phdr) ((u16_t)(ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS)) 00188 00189 #define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr)) 00190 #define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & PP_HTONS(~TCP_FLAGS)) | htons(flags)) 00191 #define TCPH_HDRLEN_FLAGS_SET(phdr, len, flags) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | (flags)) 00192 00193 #define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | htons(flags)) 00194 #define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags & ~htons(flags)) 00195 00196 #define TCP_TCPLEN(seg) ((seg)->len + (((TCPH_FLAGS((seg)->tcphdr) & (TCP_FIN | TCP_SYN)) != 0) ? 1U : 0U)) 00197 00198 /** Flags used on input processing, not on pcb->flags 00199 */ 00200 #define TF_RESET (u8_t)0x08U /* Connection was reset. */ 00201 #define TF_CLOSED (u8_t)0x10U /* Connection was successfully closed. */ 00202 #define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */ 00203 00204 00205 #if LWIP_EVENT_API 00206 00207 #define TCP_EVENT_ACCEPT(lpcb,pcb,arg,err,ret) ret = lwip_tcp_event(arg, (pcb),\ 00208 LWIP_EVENT_ACCEPT, NULL, 0, err) 00209 #define TCP_EVENT_SENT(pcb,space,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ 00210 LWIP_EVENT_SENT, NULL, space, ERR_OK) 00211 #define TCP_EVENT_RECV(pcb,p,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ 00212 LWIP_EVENT_RECV, (p), 0, (err)) 00213 #define TCP_EVENT_CLOSED(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ 00214 LWIP_EVENT_RECV, NULL, 0, ERR_OK) 00215 #define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ 00216 LWIP_EVENT_CONNECTED, NULL, 0, (err)) 00217 #define TCP_EVENT_POLL(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ 00218 LWIP_EVENT_POLL, NULL, 0, ERR_OK) 00219 #define TCP_EVENT_ERR(errf,arg,err) lwip_tcp_event((arg), NULL, \ 00220 LWIP_EVENT_ERR, NULL, 0, (err)) 00221 00222 #else /* LWIP_EVENT_API */ 00223 00224 #define TCP_EVENT_ACCEPT(lpcb,pcb,arg,err,ret) \ 00225 do { \ 00226 if((lpcb != NULL) && ((lpcb)->accept != NULL)) \ 00227 (ret) = (lpcb)->accept((arg),(pcb),(err)); \ 00228 else (ret) = ERR_ARG; \ 00229 } while (0) 00230 00231 #define TCP_EVENT_SENT(pcb,space,ret) \ 00232 do { \ 00233 if((pcb)->sent != NULL) \ 00234 (ret) = (pcb)->sent((pcb)->callback_arg,(pcb),(space)); \ 00235 else (ret) = ERR_OK; \ 00236 } while (0) 00237 00238 #define TCP_EVENT_RECV(pcb,p,err,ret) \ 00239 do { \ 00240 if((pcb)->recv != NULL) { \ 00241 (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err));\ 00242 } else { \ 00243 (ret) = tcp_recv_null(NULL, (pcb), (p), (err)); \ 00244 } \ 00245 } while (0) 00246 00247 #define TCP_EVENT_CLOSED(pcb,ret) \ 00248 do { \ 00249 if(((pcb)->recv != NULL)) { \ 00250 (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),NULL,ERR_OK);\ 00251 } else { \ 00252 (ret) = ERR_OK; \ 00253 } \ 00254 } while (0) 00255 00256 #define TCP_EVENT_CONNECTED(pcb,err,ret) \ 00257 do { \ 00258 if((pcb)->connected != NULL) \ 00259 (ret) = (pcb)->connected((pcb)->callback_arg,(pcb),(err)); \ 00260 else (ret) = ERR_OK; \ 00261 } while (0) 00262 00263 #define TCP_EVENT_POLL(pcb,ret) \ 00264 do { \ 00265 if((pcb)->poll != NULL) \ 00266 (ret) = (pcb)->poll((pcb)->callback_arg,(pcb)); \ 00267 else (ret) = ERR_OK; \ 00268 } while (0) 00269 00270 #define TCP_EVENT_ERR(errf,arg,err) \ 00271 do { \ 00272 if((errf) != NULL) \ 00273 (errf)((arg),(err)); \ 00274 } while (0) 00275 00276 #endif /* LWIP_EVENT_API */ 00277 00278 /** Enabled extra-check for TCP_OVERSIZE if LWIP_DEBUG is enabled */ 00279 #if TCP_OVERSIZE && defined(LWIP_DEBUG) 00280 #define TCP_OVERSIZE_DBGCHECK 1 00281 #else 00282 #define TCP_OVERSIZE_DBGCHECK 0 00283 #endif 00284 00285 /** Don't generate checksum on copy if CHECKSUM_GEN_TCP is disabled */ 00286 #define TCP_CHECKSUM_ON_COPY (LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_TCP) 00287 00288 /* This structure represents a TCP segment on the unsent, unacked and ooseq queues */ 00289 struct tcp_seg { 00290 struct tcp_seg *next; /* used when putting segments on a queue */ 00291 struct pbuf *p; /* buffer containing data + TCP header */ 00292 u16_t len; /* the TCP length of this segment */ 00293 #if TCP_OVERSIZE_DBGCHECK 00294 u16_t oversize_left; /* Extra bytes available at the end of the last 00295 pbuf in unsent (used for asserting vs. 00296 tcp_pcb.unsent_oversized only) */ 00297 #endif /* TCP_OVERSIZE_DBGCHECK */ 00298 #if TCP_CHECKSUM_ON_COPY 00299 u16_t chksum; 00300 u8_t chksum_swapped; 00301 #endif /* TCP_CHECKSUM_ON_COPY */ 00302 u8_t flags; 00303 #define TF_SEG_OPTS_MSS (u8_t)0x01U /* Include MSS option. */ 00304 #define TF_SEG_OPTS_TS (u8_t)0x02U /* Include timestamp option. */ 00305 #define TF_SEG_DATA_CHECKSUMMED (u8_t)0x04U /* ALL data (not the header) is 00306 checksummed into 'chksum' */ 00307 #define TF_SEG_OPTS_WND_SCALE (u8_t)0x08U /* Include WND SCALE option */ 00308 struct tcp_hdr *tcphdr; /* the TCP header */ 00309 }; 00310 00311 #define LWIP_TCP_OPT_EOL 0 00312 #define LWIP_TCP_OPT_NOP 1 00313 #define LWIP_TCP_OPT_MSS 2 00314 #define LWIP_TCP_OPT_WS 3 00315 #define LWIP_TCP_OPT_TS 8 00316 00317 #define LWIP_TCP_OPT_LEN_MSS 4 00318 #if LWIP_TCP_TIMESTAMPS 00319 #define LWIP_TCP_OPT_LEN_TS 10 00320 #define LWIP_TCP_OPT_LEN_TS_OUT 12 /* aligned for output (includes NOP padding) */ 00321 #else 00322 #define LWIP_TCP_OPT_LEN_TS_OUT 0 00323 #endif 00324 #if LWIP_WND_SCALE 00325 #define LWIP_TCP_OPT_LEN_WS 3 00326 #define LWIP_TCP_OPT_LEN_WS_OUT 4 /* aligned for output (includes NOP padding) */ 00327 #else 00328 #define LWIP_TCP_OPT_LEN_WS_OUT 0 00329 #endif 00330 00331 #define LWIP_TCP_OPT_LENGTH(flags) \ 00332 (flags & TF_SEG_OPTS_MSS ? LWIP_TCP_OPT_LEN_MSS : 0) + \ 00333 (flags & TF_SEG_OPTS_TS ? LWIP_TCP_OPT_LEN_TS_OUT : 0) + \ 00334 (flags & TF_SEG_OPTS_WND_SCALE ? LWIP_TCP_OPT_LEN_WS_OUT : 0) 00335 00336 /** This returns a TCP header option for MSS in an u32_t */ 00337 #define TCP_BUILD_MSS_OPTION(mss) htonl(0x02040000 | ((mss) & 0xFFFF)) 00338 00339 #if LWIP_WND_SCALE 00340 #define TCPWNDSIZE_F U32_F 00341 #define TCPWND_MAX 0xFFFFFFFFU 00342 #define TCPWND_CHECK16(x) LWIP_ASSERT("window size > 0xFFFF", (x) <= 0xFFFF) 00343 #define TCPWND_MIN16(x) ((u16_t)LWIP_MIN((x), 0xFFFF)) 00344 #else /* LWIP_WND_SCALE */ 00345 #define TCPWNDSIZE_F U16_F 00346 #define TCPWND_MAX 0xFFFFU 00347 #define TCPWND_CHECK16(x) 00348 #define TCPWND_MIN16(x) x 00349 #endif /* LWIP_WND_SCALE */ 00350 00351 /* Global variables: */ 00352 extern struct tcp_pcb *tcp_input_pcb; 00353 extern u32_t tcp_ticks; 00354 extern u8_t tcp_active_pcbs_changed; 00355 00356 /* The TCP PCB lists. */ 00357 union tcp_listen_pcbs_t { /* List of all TCP PCBs in LISTEN state. */ 00358 struct tcp_pcb_listen *listen_pcbs; 00359 struct tcp_pcb *pcbs; 00360 }; 00361 extern struct tcp_pcb *tcp_bound_pcbs; 00362 extern union tcp_listen_pcbs_t tcp_listen_pcbs; 00363 extern struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a 00364 state in which they accept or send 00365 data. */ 00366 extern struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */ 00367 00368 #define NUM_TCP_PCB_LISTS_NO_TIME_WAIT 3 00369 #define NUM_TCP_PCB_LISTS 4 00370 extern struct tcp_pcb ** const tcp_pcb_lists[NUM_TCP_PCB_LISTS]; 00371 00372 /* Axioms about the above lists: 00373 1) Every TCP PCB that is not CLOSED is in one of the lists. 00374 2) A PCB is only in one of the lists. 00375 3) All PCBs in the tcp_listen_pcbs list is in LISTEN state. 00376 4) All PCBs in the tcp_tw_pcbs list is in TIME-WAIT state. 00377 */ 00378 /* Define two macros, TCP_REG and TCP_RMV that registers a TCP PCB 00379 with a PCB list or removes a PCB from a list, respectively. */ 00380 #ifndef TCP_DEBUG_PCB_LISTS 00381 #define TCP_DEBUG_PCB_LISTS 0 00382 #endif 00383 #if TCP_DEBUG_PCB_LISTS 00384 #define TCP_REG(pcbs, npcb) do {\ 00385 struct tcp_pcb *tcp_tmp_pcb; \ 00386 LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %d\n", (npcb), (npcb)->local_port)); \ 00387 for (tcp_tmp_pcb = *(pcbs); \ 00388 tcp_tmp_pcb != NULL; \ 00389 tcp_tmp_pcb = tcp_tmp_pcb->next) { \ 00390 LWIP_ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != (npcb)); \ 00391 } \ 00392 LWIP_ASSERT("TCP_REG: pcb->state != CLOSED", ((pcbs) == &tcp_bound_pcbs) || ((npcb)->state != CLOSED)); \ 00393 (npcb)->next = *(pcbs); \ 00394 LWIP_ASSERT("TCP_REG: npcb->next != npcb", (npcb)->next != (npcb)); \ 00395 *(pcbs) = (npcb); \ 00396 LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \ 00397 tcp_timer_needed(); \ 00398 } while(0) 00399 #define TCP_RMV(pcbs, npcb) do { \ 00400 struct tcp_pcb *tcp_tmp_pcb; \ 00401 LWIP_ASSERT("TCP_RMV: pcbs != NULL", *(pcbs) != NULL); \ 00402 LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removing %p from %p\n", (npcb), *(pcbs))); \ 00403 if(*(pcbs) == (npcb)) { \ 00404 *(pcbs) = (*pcbs)->next; \ 00405 } else for (tcp_tmp_pcb = *(pcbs); tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \ 00406 if(tcp_tmp_pcb->next == (npcb)) { \ 00407 tcp_tmp_pcb->next = (npcb)->next; \ 00408 break; \ 00409 } \ 00410 } \ 00411 (npcb)->next = NULL; \ 00412 LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \ 00413 LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", (npcb), *(pcbs))); \ 00414 } while(0) 00415 00416 #else /* LWIP_DEBUG */ 00417 00418 #define TCP_REG(pcbs, npcb) \ 00419 do { \ 00420 (npcb)->next = *pcbs; \ 00421 *(pcbs) = (npcb); \ 00422 tcp_timer_needed(); \ 00423 } while (0) 00424 00425 #define TCP_RMV(pcbs, npcb) \ 00426 do { \ 00427 if(*(pcbs) == (npcb)) { \ 00428 (*(pcbs)) = (*pcbs)->next; \ 00429 } \ 00430 else { \ 00431 struct tcp_pcb *tcp_tmp_pcb; \ 00432 for (tcp_tmp_pcb = *pcbs; \ 00433 tcp_tmp_pcb != NULL; \ 00434 tcp_tmp_pcb = tcp_tmp_pcb->next) { \ 00435 if(tcp_tmp_pcb->next == (npcb)) { \ 00436 tcp_tmp_pcb->next = (npcb)->next; \ 00437 break; \ 00438 } \ 00439 } \ 00440 } \ 00441 (npcb)->next = NULL; \ 00442 } while(0) 00443 00444 #endif /* LWIP_DEBUG */ 00445 00446 #define TCP_REG_ACTIVE(npcb) \ 00447 do { \ 00448 TCP_REG(&tcp_active_pcbs, npcb); \ 00449 tcp_active_pcbs_changed = 1; \ 00450 } while (0) 00451 00452 #define TCP_RMV_ACTIVE(npcb) \ 00453 do { \ 00454 TCP_RMV(&tcp_active_pcbs, npcb); \ 00455 tcp_active_pcbs_changed = 1; \ 00456 } while (0) 00457 00458 #define TCP_PCB_REMOVE_ACTIVE(pcb) \ 00459 do { \ 00460 tcp_pcb_remove(&tcp_active_pcbs, pcb); \ 00461 tcp_active_pcbs_changed = 1; \ 00462 } while (0) 00463 00464 00465 /* Internal functions: */ 00466 struct tcp_pcb *tcp_pcb_copy(struct tcp_pcb *pcb); 00467 void tcp_pcb_purge(struct tcp_pcb *pcb); 00468 void tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb); 00469 00470 void tcp_segs_free(struct tcp_seg *seg); 00471 void tcp_seg_free(struct tcp_seg *seg); 00472 struct tcp_seg *tcp_seg_copy(struct tcp_seg *seg); 00473 00474 #define tcp_ack(pcb) \ 00475 do { \ 00476 if((pcb)->flags & TF_ACK_DELAY) { \ 00477 (pcb)->flags &= ~TF_ACK_DELAY; \ 00478 (pcb)->flags |= TF_ACK_NOW; \ 00479 } \ 00480 else { \ 00481 (pcb)->flags |= TF_ACK_DELAY; \ 00482 } \ 00483 } while (0) 00484 00485 #define tcp_ack_now(pcb) \ 00486 do { \ 00487 (pcb)->flags |= TF_ACK_NOW; \ 00488 } while (0) 00489 00490 err_t tcp_send_fin(struct tcp_pcb *pcb); 00491 err_t tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags); 00492 00493 void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg); 00494 00495 void tcp_rst(u32_t seqno, u32_t ackno, 00496 const ip_addr_t *local_ip, const ip_addr_t *remote_ip, 00497 u16_t local_port, u16_t remote_port); 00498 00499 u32_t tcp_next_iss(void); 00500 00501 err_t tcp_keepalive(struct tcp_pcb *pcb); 00502 err_t tcp_zero_window_probe(struct tcp_pcb *pcb); 00503 void tcp_trigger_input_pcb_close(void); 00504 00505 #if TCP_CALCULATE_EFF_SEND_MSS 00506 u16_t tcp_eff_send_mss_impl(u16_t sendmss, const ip_addr_t *dest 00507 #if LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING 00508 , const ip_addr_t *src 00509 #endif /* LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING */ 00510 ); 00511 #if LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING 00512 #define tcp_eff_send_mss(sendmss, src, dest) tcp_eff_send_mss_impl(sendmss, dest, src) 00513 #else /* LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING */ 00514 #define tcp_eff_send_mss(sendmss, src, dest) tcp_eff_send_mss_impl(sendmss, dest) 00515 #endif /* LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING */ 00516 #endif /* TCP_CALCULATE_EFF_SEND_MSS */ 00517 00518 #if LWIP_CALLBACK_API 00519 err_t tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err); 00520 #endif /* LWIP_CALLBACK_API */ 00521 00522 #if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG 00523 void tcp_debug_print(struct tcp_hdr *tcphdr); 00524 void tcp_debug_print_flags(u8_t flags); 00525 void tcp_debug_print_state(enum tcp_state s); 00526 void tcp_debug_print_pcbs(void); 00527 s16_t tcp_pcbs_sane(void); 00528 #else 00529 # define tcp_debug_print(tcphdr) 00530 # define tcp_debug_print_flags(flags) 00531 # define tcp_debug_print_state(s) 00532 # define tcp_debug_print_pcbs() 00533 # define tcp_pcbs_sane() 1 00534 #endif /* TCP_DEBUG */ 00535 00536 /** External function (implemented in timers.c), called when TCP detects 00537 * that a timer is needed (i.e. active- or time-wait-pcb found). */ 00538 void tcp_timer_needed(void); 00539 00540 #if LWIP_IPV4 00541 void tcp_netif_ipv4_addr_changed(const ip4_addr_t* old_addr, const ip4_addr_t* new_addr); 00542 #endif /* LWIP_IPV4 */ 00543 00544 #ifdef __cplusplus 00545 } 00546 #endif 00547 00548 #endif /* LWIP_TCP */ 00549 00550 #endif /* LWIP_HDR_TCP_H */
Generated on Tue Jul 12 2022 13:16:13 by
