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.
tcp.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_H__ 00033 #define __LWIP_TCP_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/sys.h" 00040 #include "lwip/mem.h" 00041 #include "lwip/pbuf.h" 00042 #include "lwip/ip.h" 00043 #include "lwip/icmp.h" 00044 #include "lwip/err.h" 00045 00046 #ifdef __cplusplus 00047 extern "C" { 00048 #endif 00049 00050 struct tcp_pcb; 00051 00052 /* Functions for interfacing with TCP: */ 00053 00054 /* Lower layer interface to TCP: */ 00055 #define tcp_init() /* Compatibility define, not init needed. */ 00056 void tcp_tmr (void); /* Must be called every 00057 TCP_TMR_INTERVAL 00058 ms. (Typically 250 ms). */ 00059 /* Application program's interface: */ 00060 struct tcp_pcb * tcp_new (void); 00061 struct tcp_pcb * tcp_alloc (u8_t prio); 00062 00063 void tcp_arg (struct tcp_pcb *pcb, void *arg); 00064 void tcp_accept (struct tcp_pcb *pcb, 00065 err_t (* accept)(void *arg, struct tcp_pcb *newpcb, 00066 err_t err)); 00067 void tcp_recv (struct tcp_pcb *pcb, 00068 err_t (* recv)(void *arg, struct tcp_pcb *tpcb, 00069 struct pbuf *p, err_t err)); 00070 void tcp_sent (struct tcp_pcb *pcb, 00071 err_t (* sent)(void *arg, struct tcp_pcb *tpcb, 00072 u16_t len)); 00073 void tcp_poll (struct tcp_pcb *pcb, 00074 err_t (* poll)(void *arg, struct tcp_pcb *tpcb), 00075 u8_t interval); 00076 void tcp_err (struct tcp_pcb *pcb, 00077 void (* err)(void *arg, err_t err)); 00078 00079 #define tcp_mss(pcb) ((pcb)->mss) 00080 #define tcp_sndbuf(pcb) ((pcb)->snd_buf) 00081 00082 #if TCP_LISTEN_BACKLOG 00083 #define tcp_accepted(pcb) (((struct tcp_pcb_listen *)(pcb))->accepts_pending--) 00084 #else /* TCP_LISTEN_BACKLOG */ 00085 #define tcp_accepted(pcb) 00086 #endif /* TCP_LISTEN_BACKLOG */ 00087 00088 void tcp_recved (struct tcp_pcb *pcb, u16_t len); 00089 err_t tcp_bind (struct tcp_pcb *pcb, struct ip_addr *ipaddr, 00090 u16_t port); 00091 err_t tcp_connect (struct tcp_pcb *pcb, struct ip_addr *ipaddr, 00092 u16_t port, err_t (* connected)(void *arg, 00093 struct tcp_pcb *tpcb, 00094 err_t err)); 00095 00096 struct tcp_pcb * tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog); 00097 #define tcp_listen(pcb) tcp_listen_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG) 00098 00099 void tcp_abandon (struct tcp_pcb *pcb, int reset); 00100 #define tcp_abort(pcb) tcp_abandon((pcb), 1) 00101 err_t tcp_close (struct tcp_pcb *pcb); 00102 00103 /* Flags for "apiflags" parameter in tcp_write and tcp_enqueue */ 00104 #define TCP_WRITE_FLAG_COPY 0x01 00105 #define TCP_WRITE_FLAG_MORE 0x02 00106 00107 err_t tcp_write (struct tcp_pcb *pcb, const void *dataptr, u16_t len, 00108 u8_t apiflags); 00109 00110 void tcp_setprio (struct tcp_pcb *pcb, u8_t prio); 00111 00112 #define TCP_PRIO_MIN 1 00113 #define TCP_PRIO_NORMAL 64 00114 #define TCP_PRIO_MAX 127 00115 00116 /* It is also possible to call these two functions at the right 00117 intervals (instead of calling tcp_tmr()). */ 00118 void tcp_slowtmr (void); 00119 void tcp_fasttmr (void); 00120 00121 00122 /* Only used by IP to pass a TCP segment to TCP: */ 00123 void tcp_input (struct pbuf *p, struct netif *inp); 00124 /* Used within the TCP code only: */ 00125 err_t tcp_output (struct tcp_pcb *pcb); 00126 void tcp_rexmit (struct tcp_pcb *pcb); 00127 void tcp_rexmit_rto (struct tcp_pcb *pcb); 00128 void tcp_rexmit_fast (struct tcp_pcb *pcb); 00129 u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb); 00130 00131 /** 00132 * This is the Nagle algorithm: try to combine user data to send as few TCP 00133 * segments as possible. Only send if 00134 * - no previously transmitted data on the connection remains unacknowledged or 00135 * - the TF_NODELAY flag is set (nagle algorithm turned off for this pcb) or 00136 * - the only unsent segment is at least pcb->mss bytes long (or there is more 00137 * than one unsent segment - with lwIP, this can happen although unsent->len < mss) 00138 */ 00139 #define tcp_do_output_nagle(tpcb) ((((tpcb)->unacked == NULL) || \ 00140 ((tpcb)->flags & TF_NODELAY) || \ 00141 (((tpcb)->unsent != NULL) && (((tpcb)->unsent->next != NULL) || \ 00142 ((tpcb)->unsent->len >= (tpcb)->mss))) \ 00143 ) ? 1 : 0) 00144 #define tcp_output_nagle(tpcb) (tcp_do_output_nagle(tpcb) ? tcp_output(tpcb) : ERR_OK) 00145 00146 00147 #define TCP_SEQ_LT(a,b) ((s32_t)((a)-(b)) < 0) 00148 #define TCP_SEQ_LEQ(a,b) ((s32_t)((a)-(b)) <= 0) 00149 #define TCP_SEQ_GT(a,b) ((s32_t)((a)-(b)) > 0) 00150 #define TCP_SEQ_GEQ(a,b) ((s32_t)((a)-(b)) >= 0) 00151 /* is b<=a<=c? */ 00152 #if 0 /* see bug #10548 */ 00153 #define TCP_SEQ_BETWEEN(a,b,c) ((c)-(b) >= (a)-(b)) 00154 #endif 00155 #define TCP_SEQ_BETWEEN(a,b,c) (TCP_SEQ_GEQ(a,b) && TCP_SEQ_LEQ(a,c)) 00156 #define TCP_FIN 0x01U 00157 #define TCP_SYN 0x02U 00158 #define TCP_RST 0x04U 00159 #define TCP_PSH 0x08U 00160 #define TCP_ACK 0x10U 00161 #define TCP_URG 0x20U 00162 #define TCP_ECE 0x40U 00163 #define TCP_CWR 0x80U 00164 00165 #define TCP_FLAGS 0x3fU 00166 00167 /* Length of the TCP header, excluding options. */ 00168 #define TCP_HLEN 20 00169 00170 #ifndef TCP_TMR_INTERVAL 00171 #define TCP_TMR_INTERVAL 250 /* The TCP timer interval in milliseconds. */ 00172 #endif /* TCP_TMR_INTERVAL */ 00173 00174 #ifndef TCP_FAST_INTERVAL 00175 #define TCP_FAST_INTERVAL TCP_TMR_INTERVAL /* the fine grained timeout in milliseconds */ 00176 #endif /* TCP_FAST_INTERVAL */ 00177 00178 #ifndef TCP_SLOW_INTERVAL 00179 #define TCP_SLOW_INTERVAL (2*TCP_TMR_INTERVAL) /* the coarse grained timeout in milliseconds */ 00180 #endif /* TCP_SLOW_INTERVAL */ 00181 00182 #define TCP_FIN_WAIT_TIMEOUT 20000 /* milliseconds */ 00183 #define TCP_SYN_RCVD_TIMEOUT 20000 /* milliseconds */ 00184 00185 #define TCP_OOSEQ_TIMEOUT 6U /* x RTO */ 00186 00187 #ifndef TCP_MSL 00188 #define TCP_MSL 60000UL /* The maximum segment lifetime in milliseconds */ 00189 #endif 00190 00191 /* Keepalive values, compliant with RFC 1122. Don't change this unless you know what you're doing */ 00192 #ifndef TCP_KEEPIDLE_DEFAULT 00193 #define TCP_KEEPIDLE_DEFAULT 7200000UL /* Default KEEPALIVE timer in milliseconds */ 00194 #endif 00195 00196 #ifndef TCP_KEEPINTVL_DEFAULT 00197 #define TCP_KEEPINTVL_DEFAULT 75000UL /* Default Time between KEEPALIVE probes in milliseconds */ 00198 #endif 00199 00200 #ifndef TCP_KEEPCNT_DEFAULT 00201 #define TCP_KEEPCNT_DEFAULT 9U /* Default Counter for KEEPALIVE probes */ 00202 #endif 00203 00204 #define TCP_MAXIDLE TCP_KEEPCNT_DEFAULT * TCP_KEEPINTVL_DEFAULT /* Maximum KEEPALIVE probe time */ 00205 00206 /* Fields are (of course) in network byte order. 00207 * Some fields are converted to host byte order in tcp_input(). 00208 */ 00209 #ifdef PACK_STRUCT_USE_INCLUDES 00210 # include "arch/bpstruct.h" 00211 #endif 00212 PACK_STRUCT_BEGIN 00213 struct tcp_hdr { 00214 PACK_STRUCT_FIELD(u16_t src); 00215 PACK_STRUCT_FIELD(u16_t dest); 00216 PACK_STRUCT_FIELD(u32_t seqno); 00217 PACK_STRUCT_FIELD(u32_t ackno); 00218 PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags); 00219 PACK_STRUCT_FIELD(u16_t wnd); 00220 PACK_STRUCT_FIELD(u16_t chksum); 00221 PACK_STRUCT_FIELD(u16_t urgp); 00222 } PACK_STRUCT_STRUCT; 00223 PACK_STRUCT_END 00224 #ifdef PACK_STRUCT_USE_INCLUDES 00225 # include "arch/epstruct.h" 00226 #endif 00227 00228 #define TCPH_OFFSET(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 8) 00229 #define TCPH_HDRLEN(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 12) 00230 #define TCPH_FLAGS(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS) 00231 00232 #define TCPH_OFFSET_SET(phdr, offset) (phdr)->_hdrlen_rsvd_flags = htons(((offset) << 8) | TCPH_FLAGS(phdr)) 00233 #define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr)) 00234 #define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & htons((u16_t)(~(u16_t)(TCP_FLAGS)))) | htons(flags)) 00235 #define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | htons(flags)) 00236 #define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (TCPH_FLAGS(phdr) & ~(flags)) ) 00237 00238 #define TCP_TCPLEN(seg) ((seg)->len + ((TCPH_FLAGS((seg)->tcphdr) & (TCP_FIN | TCP_SYN)) != 0)) 00239 00240 enum tcp_state { 00241 CLOSED = 0, 00242 LISTEN = 1, 00243 SYN_SENT = 2, 00244 SYN_RCVD = 3, 00245 ESTABLISHED = 4, 00246 FIN_WAIT_1 = 5, 00247 FIN_WAIT_2 = 6, 00248 CLOSE_WAIT = 7, 00249 CLOSING = 8, 00250 LAST_ACK = 9, 00251 TIME_WAIT = 10 00252 }; 00253 00254 /** Flags used on input processing, not on pcb->flags 00255 */ 00256 #define TF_RESET (u8_t)0x08U /* Connection was reset. */ 00257 #define TF_CLOSED (u8_t)0x10U /* Connection was sucessfully closed. */ 00258 #define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */ 00259 00260 00261 #if LWIP_CALLBACK_API 00262 /* Function to call when a listener has been connected. 00263 * @param arg user-supplied argument (tcp_pcb.callback_arg) 00264 * @param pcb a new tcp_pcb that now is connected 00265 * @param err an error argument (TODO: that is current always ERR_OK?) 00266 * @return ERR_OK: accept the new connection, 00267 * any other err_t abortsthe new connection 00268 */ 00269 #define DEF_ACCEPT_CALLBACK err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err) 00270 #else /* LWIP_CALLBACK_API */ 00271 #define DEF_ACCEPT_CALLBACK 00272 #endif /* LWIP_CALLBACK_API */ 00273 00274 /** 00275 * members common to struct tcp_pcb and struct tcp_listen_pcb 00276 */ 00277 #define TCP_PCB_COMMON(type) \ 00278 type *next; /* for the linked list */ \ 00279 enum tcp_state state; /* TCP state */ \ 00280 u8_t prio; \ 00281 void *callback_arg; \ 00282 /* ports are in host byte order */ \ 00283 u16_t local_port; \ 00284 /* the accept callback for listen- and normal pcbs, if LWIP_CALLBACK_API */ \ 00285 DEF_ACCEPT_CALLBACK 00286 00287 00288 /* the TCP protocol control block */ 00289 struct tcp_pcb { 00290 /** common PCB members */ 00291 IP_PCB; 00292 /** protocol specific PCB members */ 00293 TCP_PCB_COMMON(struct tcp_pcb); 00294 00295 /* ports are in host byte order */ 00296 u16_t remote_port; 00297 00298 u8_t flags; 00299 #define TF_ACK_DELAY ((u8_t)0x01U) /* Delayed ACK. */ 00300 #define TF_ACK_NOW ((u8_t)0x02U) /* Immediate ACK. */ 00301 #define TF_INFR ((u8_t)0x04U) /* In fast recovery. */ 00302 #define TF_TIMESTAMP ((u8_t)0x08U) /* Timestamp option enabled */ 00303 #define TF_FIN ((u8_t)0x20U) /* Connection was closed locally (FIN segment enqueued). */ 00304 #define TF_NODELAY ((u8_t)0x40U) /* Disable Nagle algorithm */ 00305 #define TF_NAGLEMEMERR ((u8_t)0x80U) /* nagle enabled, memerr, try to output to prevent delayed ACK to happen */ 00306 00307 /* the rest of the fields are in host byte order 00308 as we have to do some math with them */ 00309 /* receiver variables */ 00310 u32_t rcv_nxt; /* next seqno expected */ 00311 u16_t rcv_wnd; /* receiver window available */ 00312 u16_t rcv_ann_wnd; /* receiver window to announce */ 00313 u32_t rcv_ann_right_edge; /* announced right edge of window */ 00314 00315 /* Timers */ 00316 u32_t tmr; 00317 u8_t polltmr, pollinterval; 00318 00319 /* Retransmission timer. */ 00320 s16_t rtime; 00321 00322 u16_t mss; /* maximum segment size */ 00323 00324 /* RTT (round trip time) estimation variables */ 00325 u32_t rttest; /* RTT estimate in 500ms ticks */ 00326 u32_t rtseq; /* sequence number being timed */ 00327 s16_t sa, sv; /* @todo document this */ 00328 00329 s16_t rto; /* retransmission time-out */ 00330 u8_t nrtx; /* number of retransmissions */ 00331 00332 /* fast retransmit/recovery */ 00333 u32_t lastack; /* Highest acknowledged seqno. */ 00334 u8_t dupacks; 00335 00336 /* congestion avoidance/control variables */ 00337 u16_t cwnd; 00338 u16_t ssthresh; 00339 00340 /* sender variables */ 00341 u32_t snd_nxt; /* next new seqno to be sent */ 00342 u16_t snd_wnd; /* sender window */ 00343 u32_t snd_wl1, snd_wl2; /* Sequence and acknowledgement numbers of last 00344 window update. */ 00345 u32_t snd_lbb; /* Sequence number of next byte to be buffered. */ 00346 00347 u16_t acked; 00348 00349 u16_t snd_buf; /* Available buffer space for sending (in bytes). */ 00350 #define TCP_SNDQUEUELEN_OVERFLOW (0xffff-3) 00351 u16_t snd_queuelen; /* Available buffer space for sending (in tcp_segs). */ 00352 00353 00354 /* These are ordered by sequence number: */ 00355 struct tcp_seg *unsent; /* Unsent (queued) segments. */ 00356 struct tcp_seg *unacked; /* Sent but unacknowledged segments. */ 00357 #if TCP_QUEUE_OOSEQ 00358 struct tcp_seg *ooseq; /* Received out of sequence segments. */ 00359 #endif /* TCP_QUEUE_OOSEQ */ 00360 00361 struct pbuf *refused_data; /* Data previously received but not yet taken by upper layer */ 00362 00363 #if LWIP_CALLBACK_API 00364 /* Function to be called when more send buffer space is available. 00365 * @param arg user-supplied argument (tcp_pcb.callback_arg) 00366 * @param pcb the tcp_pcb which has send buffer space available 00367 * @param space the amount of bytes available 00368 * @return ERR_OK: try to send some data by calling tcp_output 00369 */ 00370 err_t (* sent)(void *arg, struct tcp_pcb *pcb, u16_t space); 00371 00372 /* Function to be called when (in-sequence) data has arrived. 00373 * @param arg user-supplied argument (tcp_pcb.callback_arg) 00374 * @param pcb the tcp_pcb for which data has arrived 00375 * @param p the packet buffer which arrived 00376 * @param err an error argument (TODO: that is current always ERR_OK?) 00377 * @return ERR_OK: try to send some data by calling tcp_output 00378 */ 00379 err_t (* recv)(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err); 00380 00381 /* Function to be called when a connection has been set up. 00382 * @param arg user-supplied argument (tcp_pcb.callback_arg) 00383 * @param pcb the tcp_pcb that now is connected 00384 * @param err an error argument (TODO: that is current always ERR_OK?) 00385 * @return value is currently ignored 00386 */ 00387 err_t (* connected)(void *arg, struct tcp_pcb *pcb, err_t err); 00388 00389 /* Function which is called periodically. 00390 * The period can be adjusted in multiples of the TCP slow timer interval 00391 * by changing tcp_pcb.polltmr. 00392 * @param arg user-supplied argument (tcp_pcb.callback_arg) 00393 * @param pcb the tcp_pcb to poll for 00394 * @return ERR_OK: try to send some data by calling tcp_output 00395 */ 00396 err_t (* poll)(void *arg, struct tcp_pcb *pcb); 00397 00398 /* Function to be called whenever a fatal error occurs. 00399 * There is no pcb parameter since most of the times, the pcb is 00400 * already deallocated (or there is no pcb) when this function is called. 00401 * @param arg user-supplied argument (tcp_pcb.callback_arg) 00402 * @param err an indication why the error callback is called: 00403 * ERR_ABRT: aborted through tcp_abort or by a TCP timer 00404 * ERR_RST: the connection was reset by the remote host 00405 */ 00406 void (* errf)(void *arg, err_t err); 00407 #endif /* LWIP_CALLBACK_API */ 00408 00409 #if LWIP_TCP_TIMESTAMPS 00410 u32_t ts_lastacksent; 00411 u32_t ts_recent; 00412 #endif /* LWIP_TCP_TIMESTAMPS */ 00413 00414 /* idle time before KEEPALIVE is sent */ 00415 u32_t keep_idle; 00416 #if LWIP_TCP_KEEPALIVE 00417 u32_t keep_intvl; 00418 u32_t keep_cnt; 00419 #endif /* LWIP_TCP_KEEPALIVE */ 00420 00421 /* Persist timer counter */ 00422 u32_t persist_cnt; 00423 /* Persist timer back-off */ 00424 u8_t persist_backoff; 00425 00426 /* KEEPALIVE counter */ 00427 u8_t keep_cnt_sent; 00428 }; 00429 00430 struct tcp_pcb_listen { 00431 /* Common members of all PCB types */ 00432 IP_PCB; 00433 /* Protocol specific PCB members */ 00434 TCP_PCB_COMMON(struct tcp_pcb_listen); 00435 00436 #if TCP_LISTEN_BACKLOG 00437 u8_t backlog; 00438 u8_t accepts_pending; 00439 #endif /* TCP_LISTEN_BACKLOG */ 00440 }; 00441 00442 #if LWIP_EVENT_API 00443 00444 enum lwip_event { 00445 LWIP_EVENT_ACCEPT, 00446 LWIP_EVENT_SENT, 00447 LWIP_EVENT_RECV, 00448 LWIP_EVENT_CONNECTED, 00449 LWIP_EVENT_POLL, 00450 LWIP_EVENT_ERR 00451 }; 00452 00453 err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb, 00454 enum lwip_event, 00455 struct pbuf *p, 00456 u16_t size, 00457 err_t err); 00458 00459 #define TCP_EVENT_ACCEPT(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ 00460 LWIP_EVENT_ACCEPT, NULL, 0, err) 00461 #define TCP_EVENT_SENT(pcb,space,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ 00462 LWIP_EVENT_SENT, NULL, space, ERR_OK) 00463 #define TCP_EVENT_RECV(pcb,p,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ 00464 LWIP_EVENT_RECV, (p), 0, (err)) 00465 #define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ 00466 LWIP_EVENT_CONNECTED, NULL, 0, (err)) 00467 #define TCP_EVENT_POLL(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ 00468 LWIP_EVENT_POLL, NULL, 0, ERR_OK) 00469 #define TCP_EVENT_ERR(errf,arg,err) lwip_tcp_event((arg), NULL, \ 00470 LWIP_EVENT_ERR, NULL, 0, (err)) 00471 #else /* LWIP_EVENT_API */ 00472 00473 #define TCP_EVENT_ACCEPT(pcb,err,ret) \ 00474 do { \ 00475 if((pcb)->accept != NULL) \ 00476 (ret) = (pcb)->accept((pcb)->callback_arg,(pcb),(err)); \ 00477 else (ret) = ERR_OK; \ 00478 } while (0) 00479 00480 #define TCP_EVENT_SENT(pcb,space,ret) \ 00481 do { \ 00482 if((pcb)->sent != NULL) \ 00483 (ret) = (pcb)->sent((pcb)->callback_arg,(pcb),(space)); \ 00484 else (ret) = ERR_OK; \ 00485 } while (0) 00486 00487 #define TCP_EVENT_RECV(pcb,p,err,ret) \ 00488 do { \ 00489 if((pcb)->recv != NULL) { \ 00490 (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err)); \ 00491 } else { \ 00492 (ret) = ERR_OK; \ 00493 if (p != NULL) { \ 00494 tcp_recved((pcb), ((struct pbuf*)(p))->tot_len); \ 00495 pbuf_free(p); \ 00496 } \ 00497 } \ 00498 } while (0) 00499 00500 #define TCP_EVENT_CONNECTED(pcb,err,ret) \ 00501 do { \ 00502 if((pcb)->connected != NULL) \ 00503 (ret) = (pcb)->connected((pcb)->callback_arg,(pcb),(err)); \ 00504 else (ret) = ERR_OK; \ 00505 } while (0) 00506 00507 #define TCP_EVENT_POLL(pcb,ret) \ 00508 do { \ 00509 if((pcb)->poll != NULL) \ 00510 (ret) = (pcb)->poll((pcb)->callback_arg,(pcb)); \ 00511 else (ret) = ERR_OK; \ 00512 } while (0) 00513 00514 #define TCP_EVENT_ERR(errf,arg,err) \ 00515 do { \ 00516 if((errf) != NULL) \ 00517 (errf)((arg),(err)); \ 00518 } while (0) 00519 00520 #endif /* LWIP_EVENT_API */ 00521 00522 /* This structure represents a TCP segment on the unsent and unacked queues */ 00523 struct tcp_seg { 00524 struct tcp_seg *next; /* used when putting segements on a queue */ 00525 struct pbuf *p; /* buffer containing data + TCP header */ 00526 void *dataptr; /* pointer to the TCP data in the pbuf */ 00527 u16_t len; /* the TCP length of this segment */ 00528 u8_t flags; 00529 #define TF_SEG_OPTS_MSS (u8_t)0x01U /* Include MSS option. */ 00530 #define TF_SEG_OPTS_TS (u8_t)0x02U /* Include timestamp option. */ 00531 struct tcp_hdr *tcphdr; /* the TCP header */ 00532 }; 00533 00534 #define LWIP_TCP_OPT_LENGTH(flags) \ 00535 (flags & TF_SEG_OPTS_MSS ? 4 : 0) + \ 00536 (flags & TF_SEG_OPTS_TS ? 12 : 0) 00537 00538 /** This returns a TCP header option for MSS in an u32_t */ 00539 #define TCP_BUILD_MSS_OPTION(x) (x) = htonl(((u32_t)2 << 24) | \ 00540 ((u32_t)4 << 16) | \ 00541 (((u32_t)TCP_MSS / 256) << 8) | \ 00542 (TCP_MSS & 255)) 00543 00544 /* Internal functions and global variables: */ 00545 struct tcp_pcb *tcp_pcb_copy(struct tcp_pcb *pcb); 00546 void tcp_pcb_purge(struct tcp_pcb *pcb); 00547 void tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb); 00548 00549 u8_t tcp_segs_free(struct tcp_seg *seg); 00550 u8_t tcp_seg_free(struct tcp_seg *seg); 00551 struct tcp_seg *tcp_seg_copy(struct tcp_seg *seg); 00552 00553 #define tcp_ack(pcb) \ 00554 do { \ 00555 if((pcb)->flags & TF_ACK_DELAY) { \ 00556 (pcb)->flags &= ~TF_ACK_DELAY; \ 00557 (pcb)->flags |= TF_ACK_NOW; \ 00558 tcp_output(pcb); \ 00559 } \ 00560 else { \ 00561 (pcb)->flags |= TF_ACK_DELAY; \ 00562 } \ 00563 } while (0) 00564 00565 #define tcp_ack_now(pcb) \ 00566 do { \ 00567 (pcb)->flags |= TF_ACK_NOW; \ 00568 tcp_output(pcb); \ 00569 } while (0) 00570 00571 err_t tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags); 00572 err_t tcp_enqueue(struct tcp_pcb *pcb, void *dataptr, u16_t len, 00573 u8_t flags, u8_t apiflags, u8_t optflags); 00574 00575 void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg); 00576 00577 void tcp_rst(u32_t seqno, u32_t ackno, 00578 struct ip_addr *local_ip, struct ip_addr *remote_ip, 00579 u16_t local_port, u16_t remote_port); 00580 00581 u32_t tcp_next_iss(void); 00582 00583 void tcp_keepalive(struct tcp_pcb *pcb); 00584 void tcp_zero_window_probe(struct tcp_pcb *pcb); 00585 00586 #if TCP_CALCULATE_EFF_SEND_MSS 00587 u16_t tcp_eff_send_mss(u16_t sendmss, struct ip_addr *addr); 00588 #endif /* TCP_CALCULATE_EFF_SEND_MSS */ 00589 00590 extern struct tcp_pcb *tcp_input_pcb; 00591 extern u32_t tcp_ticks; 00592 00593 const char* tcp_debug_state_str(enum tcp_state s); 00594 #if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG 00595 void tcp_debug_print(struct tcp_hdr *tcphdr); 00596 void tcp_debug_print_flags(u8_t flags); 00597 void tcp_debug_print_state(enum tcp_state s); 00598 void tcp_debug_print_pcbs(void); 00599 s16_t tcp_pcbs_sane(void); 00600 #else 00601 # define tcp_debug_print(tcphdr) 00602 # define tcp_debug_print_flags(flags) 00603 # define tcp_debug_print_state(s) 00604 # define tcp_debug_print_pcbs() 00605 # define tcp_pcbs_sane() 1 00606 #endif /* TCP_DEBUG */ 00607 00608 #if NO_SYS 00609 #define tcp_timer_needed() 00610 #else 00611 void tcp_timer_needed(void); 00612 #endif 00613 00614 /* The TCP PCB lists. */ 00615 union tcp_listen_pcbs_t { /* List of all TCP PCBs in LISTEN state. */ 00616 struct tcp_pcb_listen *listen_pcbs; 00617 struct tcp_pcb *pcbs; 00618 }; 00619 extern union tcp_listen_pcbs_t tcp_listen_pcbs; 00620 extern struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a 00621 state in which they accept or send 00622 data. */ 00623 extern struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */ 00624 00625 extern struct tcp_pcb *tcp_tmp_pcb; /* Only used for temporary storage. */ 00626 00627 /* Axioms about the above lists: 00628 1) Every TCP PCB that is not CLOSED is in one of the lists. 00629 2) A PCB is only in one of the lists. 00630 3) All PCBs in the tcp_listen_pcbs list is in LISTEN state. 00631 4) All PCBs in the tcp_tw_pcbs list is in TIME-WAIT state. 00632 */ 00633 00634 /* Define two macros, TCP_REG and TCP_RMV that registers a TCP PCB 00635 with a PCB list or removes a PCB from a list, respectively. */ 00636 #if 0 00637 #define TCP_REG(pcbs, npcb) do {\ 00638 LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %d\n", npcb, npcb->local_port)); \ 00639 for(tcp_tmp_pcb = *pcbs; \ 00640 tcp_tmp_pcb != NULL; \ 00641 tcp_tmp_pcb = tcp_tmp_pcb->next) { \ 00642 LWIP_ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != npcb); \ 00643 } \ 00644 LWIP_ASSERT("TCP_REG: pcb->state != CLOSED", npcb->state != CLOSED); \ 00645 npcb->next = *pcbs; \ 00646 LWIP_ASSERT("TCP_REG: npcb->next != npcb", npcb->next != npcb); \ 00647 *(pcbs) = npcb; \ 00648 LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \ 00649 tcp_timer_needed(); \ 00650 } while(0) 00651 #define TCP_RMV(pcbs, npcb) do { \ 00652 LWIP_ASSERT("TCP_RMV: pcbs != NULL", *pcbs != NULL); \ 00653 LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removing %p from %p\n", npcb, *pcbs)); \ 00654 if(*pcbs == npcb) { \ 00655 *pcbs = (*pcbs)->next; \ 00656 } else for(tcp_tmp_pcb = *pcbs; tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \ 00657 if(tcp_tmp_pcb->next == npcb) { \ 00658 tcp_tmp_pcb->next = npcb->next; \ 00659 break; \ 00660 } \ 00661 } \ 00662 npcb->next = NULL; \ 00663 LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \ 00664 LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", npcb, *pcbs)); \ 00665 } while(0) 00666 00667 #else /* LWIP_DEBUG */ 00668 00669 #define TCP_REG(pcbs, npcb) \ 00670 do { \ 00671 npcb->next = *pcbs; \ 00672 *(pcbs) = npcb; \ 00673 tcp_timer_needed(); \ 00674 } while (0) 00675 00676 #define TCP_RMV(pcbs, npcb) \ 00677 do { \ 00678 if(*(pcbs) == npcb) { \ 00679 (*(pcbs)) = (*pcbs)->next; \ 00680 } \ 00681 else { \ 00682 for(tcp_tmp_pcb = *pcbs; \ 00683 tcp_tmp_pcb != NULL; \ 00684 tcp_tmp_pcb = tcp_tmp_pcb->next) { \ 00685 if(tcp_tmp_pcb->next == npcb) { \ 00686 tcp_tmp_pcb->next = npcb->next; \ 00687 break; \ 00688 } \ 00689 } \ 00690 } \ 00691 npcb->next = NULL; \ 00692 } while(0) 00693 00694 #endif /* LWIP_DEBUG */ 00695 00696 #ifdef __cplusplus 00697 } 00698 #endif 00699 00700 #endif /* LWIP_TCP */ 00701 00702 #endif /* __LWIP_TCP_H__ */
Generated on Wed Jul 13 2022 07:13:44 by
1.7.2