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