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