2 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
27 * This file is part of the lwIP TCP/IP stack.
29 * Author: Adam Dunkels <adam@sics.se>
32 #ifndef __LWIP_TCP_H__
33 #define __LWIP_TCP_H__
37 #if LWIP_TCP /* don't build if not configured for use in lwipopts.h */
41 #include "lwip/pbuf.h"
43 #include "lwip/icmp.h"
52 /** Function prototype for tcp accept callback functions. Called when a new
53 * connection can be accepted on a listening pcb.
55 * @param arg Additional argument to pass to the callback function (@see tcp_arg())
56 * @param newpcb The new connection pcb
57 * @param err An error code if there has been an error accepting.
58 * Only return ERR_ABRT if you have called tcp_abort from within the
61 typedef err_t (*tcp_accept_fn)(void *arg, struct tcp_pcb *newpcb, err_t err);
63 /** Function prototype for tcp receive callback functions. Called when data has
66 * @param arg Additional argument to pass to the callback function (@see tcp_arg())
67 * @param tpcb The connection pcb which received data
68 * @param p The received data (or NULL when the connection has been closed!)
69 * @param err An error code if there has been an error receiving
70 * Only return ERR_ABRT if you have called tcp_abort from within the
73 typedef err_t (*tcp_recv_fn)(void *arg, struct tcp_pcb *tpcb,
74 struct pbuf *p, err_t err);
76 /** Function prototype for tcp sent callback functions. Called when sent data has
77 * been acknowledged by the remote side. Use it to free corresponding resources.
78 * This also means that the pcb has now space available to send new data.
80 * @param arg Additional argument to pass to the callback function (@see tcp_arg())
81 * @param tpcb The connection pcb for which data has been acknowledged
82 * @param len The amount of bytes acknowledged
83 * @return ERR_OK: try to send some data by calling tcp_output
84 * Only return ERR_ABRT if you have called tcp_abort from within the
87 typedef err_t (*tcp_sent_fn)(void *arg, struct tcp_pcb *tpcb,
90 /** Function prototype for tcp poll callback functions. Called periodically as
91 * specified by @see tcp_poll.
93 * @param arg Additional argument to pass to the callback function (@see tcp_arg())
95 * @return ERR_OK: try to send some data by calling tcp_output
96 * Only return ERR_ABRT if you have called tcp_abort from within the
99 typedef err_t (*tcp_poll_fn)(void *arg, struct tcp_pcb *tpcb);
101 /** Function prototype for tcp error callback functions. Called when the pcb
102 * receives a RST or is unexpectedly closed for any other reason.
104 * @note The corresponding pcb is already freed when this callback is called!
106 * @param arg Additional argument to pass to the callback function (@see tcp_arg())
107 * @param err Error code to indicate why the pcb has been closed
108 * ERR_ABRT: aborted through tcp_abort or by a TCP timer
109 * ERR_RST: the connection was reset by the remote host
111 typedef void (*tcp_err_fn)(void *arg, err_t err);
113 /** Function prototype for tcp connected callback functions. Called when a pcb
114 * is connected to the remote side after initiating a connection attempt by
115 * calling tcp_connect().
117 * @param arg Additional argument to pass to the callback function (@see tcp_arg())
118 * @param tpcb The connection pcb which is connected
119 * @param err An unused error code, always ERR_OK currently ;-) TODO!
120 * Only return ERR_ABRT if you have called tcp_abort from within the
123 * @note When a connection attempt fails, the error callback is currently called!
125 typedef err_t (*tcp_connected_fn)(void *arg, struct tcp_pcb *tpcb, err_t err);
127 /* Functions for interfacing with TCP: */
129 /* Lower layer interface to TCP: */
130 #define tcp_init() /* Compatibility define, not init needed. */
131 void tcp_tmr (void); /* Must be called every
133 ms. (Typically 250 ms). */
134 /* Application program's interface: */
135 struct tcp_pcb * tcp_new (void);
136 struct tcp_pcb * tcp_alloc (u8_t prio);
138 void tcp_arg (struct tcp_pcb *pcb, void *arg);
139 void tcp_accept (struct tcp_pcb *pcb, tcp_accept_fn accept);
140 void tcp_recv (struct tcp_pcb *pcb, tcp_recv_fn recv);
141 void tcp_sent (struct tcp_pcb *pcb, tcp_sent_fn sent);
142 void tcp_poll (struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval);
143 void tcp_err (struct tcp_pcb *pcb, tcp_err_fn err);
145 #define tcp_mss(pcb) ((pcb)->mss)
146 #define tcp_sndbuf(pcb) ((pcb)->snd_buf)
147 #define tcp_nagle_disable(pcb) ((pcb)->flags |= TF_NODELAY)
148 #define tcp_nagle_enable(pcb) ((pcb)->flags &= ~TF_NODELAY)
149 #define tcp_nagle_disabled(pcb) (((pcb)->flags & TF_NODELAY) != 0)
151 #if TCP_LISTEN_BACKLOG
152 #define tcp_accepted(pcb) (((struct tcp_pcb_listen *)(pcb))->accepts_pending--)
153 #else /* TCP_LISTEN_BACKLOG */
154 #define tcp_accepted(pcb) LWIP_UNUSED_ARG(pcb);
155 #endif /* TCP_LISTEN_BACKLOG */
157 void tcp_recved (struct tcp_pcb *pcb, u16_t len);
158 err_t tcp_bind (struct tcp_pcb *pcb, struct ip_addr *ipaddr,
160 err_t tcp_connect (struct tcp_pcb *pcb, struct ip_addr *ipaddr,
161 u16_t port, tcp_connected_fn connected);
163 struct tcp_pcb * tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog);
164 #define tcp_listen(pcb) tcp_listen_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG)
166 void tcp_abandon (struct tcp_pcb *pcb, int reset);
167 #define tcp_abort(pcb) tcp_abandon((pcb), 1)
168 err_t tcp_close (struct tcp_pcb *pcb);
170 /* Flags for "apiflags" parameter in tcp_write and tcp_enqueue */
171 #define TCP_WRITE_FLAG_COPY 0x01
172 #define TCP_WRITE_FLAG_MORE 0x02
174 err_t tcp_write (struct tcp_pcb *pcb, const void *dataptr, u16_t len,
177 void tcp_setprio (struct tcp_pcb *pcb, u8_t prio);
179 #define TCP_PRIO_MIN 1
180 #define TCP_PRIO_NORMAL 64
181 #define TCP_PRIO_MAX 127
183 /* It is also possible to call these two functions at the right
184 intervals (instead of calling tcp_tmr()). */
185 void tcp_slowtmr (void);
186 void tcp_fasttmr (void);
189 /* Only used by IP to pass a TCP segment to TCP: */
190 void tcp_input (struct pbuf *p, struct netif *inp);
191 /* Used within the TCP code only: */
192 err_t tcp_send_empty_ack(struct tcp_pcb *pcb);
193 err_t tcp_output (struct tcp_pcb *pcb);
194 void tcp_rexmit (struct tcp_pcb *pcb);
195 void tcp_rexmit_rto (struct tcp_pcb *pcb);
196 void tcp_rexmit_fast (struct tcp_pcb *pcb);
197 u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb);
200 * This is the Nagle algorithm: try to combine user data to send as few TCP
201 * segments as possible. Only send if
202 * - no previously transmitted data on the connection remains unacknowledged or
203 * - the TF_NODELAY flag is set (nagle algorithm turned off for this pcb) or
204 * - the only unsent segment is at least pcb->mss bytes long (or there is more
205 * than one unsent segment - with lwIP, this can happen although unsent->len < mss)
206 * - or if we are in fast-retransmit (TF_INFR)
208 #define tcp_do_output_nagle(tpcb) ((((tpcb)->unacked == NULL) || \
209 ((tpcb)->flags & (TF_NODELAY | TF_INFR)) || \
210 (((tpcb)->unsent != NULL) && (((tpcb)->unsent->next != NULL) || \
211 ((tpcb)->unsent->len >= (tpcb)->mss))) \
213 #define tcp_output_nagle(tpcb) (tcp_do_output_nagle(tpcb) ? tcp_output(tpcb) : ERR_OK)
216 #define TCP_SEQ_LT(a,b) ((s32_t)((a)-(b)) < 0)
217 #define TCP_SEQ_LEQ(a,b) ((s32_t)((a)-(b)) <= 0)
218 #define TCP_SEQ_GT(a,b) ((s32_t)((a)-(b)) > 0)
219 #define TCP_SEQ_GEQ(a,b) ((s32_t)((a)-(b)) >= 0)
221 #if 0 /* see bug #10548 */
222 #define TCP_SEQ_BETWEEN(a,b,c) ((c)-(b) >= (a)-(b))
224 #define TCP_SEQ_BETWEEN(a,b,c) (TCP_SEQ_GEQ(a,b) && TCP_SEQ_LEQ(a,c))
225 #define TCP_FIN 0x01U
226 #define TCP_SYN 0x02U
227 #define TCP_RST 0x04U
228 #define TCP_PSH 0x08U
229 #define TCP_ACK 0x10U
230 #define TCP_URG 0x20U
231 #define TCP_ECE 0x40U
232 #define TCP_CWR 0x80U
234 #define TCP_FLAGS 0x3fU
236 /* Length of the TCP header, excluding options. */
239 #ifndef TCP_TMR_INTERVAL
240 #define TCP_TMR_INTERVAL 250 /* The TCP timer interval in milliseconds. */
241 #endif /* TCP_TMR_INTERVAL */
243 #ifndef TCP_FAST_INTERVAL
244 #define TCP_FAST_INTERVAL TCP_TMR_INTERVAL /* the fine grained timeout in milliseconds */
245 #endif /* TCP_FAST_INTERVAL */
247 #ifndef TCP_SLOW_INTERVAL
248 #define TCP_SLOW_INTERVAL (2*TCP_TMR_INTERVAL) /* the coarse grained timeout in milliseconds */
249 #endif /* TCP_SLOW_INTERVAL */
251 #define TCP_FIN_WAIT_TIMEOUT 20000 /* milliseconds */
252 #define TCP_SYN_RCVD_TIMEOUT 20000 /* milliseconds */
254 #define TCP_OOSEQ_TIMEOUT 6U /* x RTO */
257 #define TCP_MSL 60000UL /* The maximum segment lifetime in milliseconds */
260 /* Keepalive values, compliant with RFC 1122. Don't change this unless you know what you're doing */
261 #ifndef TCP_KEEPIDLE_DEFAULT
262 #define TCP_KEEPIDLE_DEFAULT 7200000UL /* Default KEEPALIVE timer in milliseconds */
265 #ifndef TCP_KEEPINTVL_DEFAULT
266 #define TCP_KEEPINTVL_DEFAULT 75000UL /* Default Time between KEEPALIVE probes in milliseconds */
269 #ifndef TCP_KEEPCNT_DEFAULT
270 #define TCP_KEEPCNT_DEFAULT 9U /* Default Counter for KEEPALIVE probes */
273 #define TCP_MAXIDLE TCP_KEEPCNT_DEFAULT * TCP_KEEPINTVL_DEFAULT /* Maximum KEEPALIVE probe time */
275 /* Fields are (of course) in network byte order.
276 * Some fields are converted to host byte order in tcp_input().
278 #ifdef PACK_STRUCT_USE_INCLUDES
279 # include "arch/bpstruct.h"
283 PACK_STRUCT_FIELD(u16_t src);
284 PACK_STRUCT_FIELD(u16_t dest);
285 PACK_STRUCT_FIELD(u32_t seqno);
286 PACK_STRUCT_FIELD(u32_t ackno);
287 PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags);
288 PACK_STRUCT_FIELD(u16_t wnd);
289 PACK_STRUCT_FIELD(u16_t chksum);
290 PACK_STRUCT_FIELD(u16_t urgp);
291 } PACK_STRUCT_STRUCT;
293 #ifdef PACK_STRUCT_USE_INCLUDES
294 # include "arch/epstruct.h"
297 #define TCPH_OFFSET(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 8)
298 #define TCPH_HDRLEN(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 12)
299 #define TCPH_FLAGS(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS)
301 #define TCPH_OFFSET_SET(phdr, offset) (phdr)->_hdrlen_rsvd_flags = htons(((offset) << 8) | TCPH_FLAGS(phdr))
302 #define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr))
303 #define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & htons((u16_t)(~(u16_t)(TCP_FLAGS)))) | htons(flags))
304 #define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | htons(flags))
305 #define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (TCPH_FLAGS(phdr) & ~(flags)) )
307 #define TCP_TCPLEN(seg) ((seg)->len + ((TCPH_FLAGS((seg)->tcphdr) & (TCP_FIN | TCP_SYN)) != 0))
323 /** Flags used on input processing, not on pcb->flags
325 #define TF_RESET (u8_t)0x08U /* Connection was reset. */
326 #define TF_CLOSED (u8_t)0x10U /* Connection was sucessfully closed. */
327 #define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */
330 #if LWIP_CALLBACK_API
331 /* Function to call when a listener has been connected.
332 * @param arg user-supplied argument (tcp_pcb.callback_arg)
333 * @param pcb a new tcp_pcb that now is connected
334 * @param err an error argument (TODO: that is current always ERR_OK?)
335 * @return ERR_OK: accept the new connection,
336 * any other err_t abortsthe new connection
338 #define DEF_ACCEPT_CALLBACK tcp_accept_fn accept
339 #else /* LWIP_CALLBACK_API */
340 #define DEF_ACCEPT_CALLBACK
341 #endif /* LWIP_CALLBACK_API */
344 * members common to struct tcp_pcb and struct tcp_listen_pcb
346 #define TCP_PCB_COMMON(type) \
347 type *next; /* for the linked list */ \
348 enum tcp_state state; /* TCP state */ \
350 void *callback_arg; \
351 /* ports are in host byte order */ \
353 /* the accept callback for listen- and normal pcbs, if LWIP_CALLBACK_API */ \
357 /* the TCP protocol control block */
359 /** common PCB members */
361 /** protocol specific PCB members */
362 TCP_PCB_COMMON(struct tcp_pcb);
364 /* ports are in host byte order */
368 #define TF_ACK_DELAY ((u8_t)0x01U) /* Delayed ACK. */
369 #define TF_ACK_NOW ((u8_t)0x02U) /* Immediate ACK. */
370 #define TF_INFR ((u8_t)0x04U) /* In fast recovery. */
371 #define TF_TIMESTAMP ((u8_t)0x08U) /* Timestamp option enabled */
372 #define TF_FIN ((u8_t)0x20U) /* Connection was closed locally (FIN segment enqueued). */
373 #define TF_NODELAY ((u8_t)0x40U) /* Disable Nagle algorithm */
374 #define TF_NAGLEMEMERR ((u8_t)0x80U) /* nagle enabled, memerr, try to output to prevent delayed ACK to happen */
376 /* the rest of the fields are in host byte order
377 as we have to do some math with them */
378 /* receiver variables */
379 u32_t rcv_nxt; /* next seqno expected */
380 u16_t rcv_wnd; /* receiver window available */
381 u16_t rcv_ann_wnd; /* receiver window to announce */
382 u32_t rcv_ann_right_edge; /* announced right edge of window */
386 u8_t polltmr, pollinterval;
388 /* Retransmission timer. */
391 u16_t mss; /* maximum segment size */
393 /* RTT (round trip time) estimation variables */
394 u32_t rttest; /* RTT estimate in 500ms ticks */
395 u32_t rtseq; /* sequence number being timed */
396 s16_t sa, sv; /* @todo document this */
398 s16_t rto; /* retransmission time-out */
399 u8_t nrtx; /* number of retransmissions */
401 /* fast retransmit/recovery */
402 u32_t lastack; /* Highest acknowledged seqno. */
405 /* congestion avoidance/control variables */
409 /* sender variables */
410 u32_t snd_nxt; /* next new seqno to be sent */
411 u16_t snd_wnd; /* sender window */
412 u32_t snd_wl1, snd_wl2; /* Sequence and acknowledgement numbers of last
414 u32_t snd_lbb; /* Sequence number of next byte to be buffered. */
418 u16_t snd_buf; /* Available buffer space for sending (in bytes). */
419 #define TCP_SNDQUEUELEN_OVERFLOW (0xffff-3)
420 u16_t snd_queuelen; /* Available buffer space for sending (in tcp_segs). */
423 /* These are ordered by sequence number: */
424 struct tcp_seg *unsent; /* Unsent (queued) segments. */
425 struct tcp_seg *unacked; /* Sent but unacknowledged segments. */
427 struct tcp_seg *ooseq; /* Received out of sequence segments. */
428 #endif /* TCP_QUEUE_OOSEQ */
430 struct pbuf *refused_data; /* Data previously received but not yet taken by upper layer */
432 #if LWIP_CALLBACK_API
433 /* Function to be called when more send buffer space is available. */
435 /* Function to be called when (in-sequence) data has arrived. */
437 /* Function to be called when a connection has been set up. */
438 tcp_connected_fn connected;
439 /* Function which is called periodically. */
441 /* Function to be called whenever a fatal error occurs. */
443 #endif /* LWIP_CALLBACK_API */
445 #if LWIP_TCP_TIMESTAMPS
446 u32_t ts_lastacksent;
448 #endif /* LWIP_TCP_TIMESTAMPS */
450 /* idle time before KEEPALIVE is sent */
452 #if LWIP_TCP_KEEPALIVE
455 #endif /* LWIP_TCP_KEEPALIVE */
457 /* Persist timer counter */
459 /* Persist timer back-off */
460 u8_t persist_backoff;
462 /* KEEPALIVE counter */
466 struct tcp_pcb_listen {
467 /* Common members of all PCB types */
469 /* Protocol specific PCB members */
470 TCP_PCB_COMMON(struct tcp_pcb_listen);
472 #if TCP_LISTEN_BACKLOG
474 u8_t accepts_pending;
475 #endif /* TCP_LISTEN_BACKLOG */
484 LWIP_EVENT_CONNECTED,
489 err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb,
495 #define TCP_EVENT_ACCEPT(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
496 LWIP_EVENT_ACCEPT, NULL, 0, err)
497 #define TCP_EVENT_SENT(pcb,space,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
498 LWIP_EVENT_SENT, NULL, space, ERR_OK)
499 #define TCP_EVENT_RECV(pcb,p,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
500 LWIP_EVENT_RECV, (p), 0, (err))
501 #define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
502 LWIP_EVENT_CONNECTED, NULL, 0, (err))
503 #define TCP_EVENT_POLL(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
504 LWIP_EVENT_POLL, NULL, 0, ERR_OK)
505 #define TCP_EVENT_ERR(errf,arg,err) lwip_tcp_event((arg), NULL, \
506 LWIP_EVENT_ERR, NULL, 0, (err))
507 #else /* LWIP_EVENT_API */
509 #define TCP_EVENT_ACCEPT(pcb,err,ret) \
511 if((pcb)->accept != NULL) \
512 (ret) = (pcb)->accept((pcb)->callback_arg,(pcb),(err)); \
513 else (ret) = ERR_OK; \
516 #define TCP_EVENT_SENT(pcb,space,ret) \
518 if((pcb)->sent != NULL) \
519 (ret) = (pcb)->sent((pcb)->callback_arg,(pcb),(space)); \
520 else (ret) = ERR_OK; \
523 #define TCP_EVENT_RECV(pcb,p,err,ret) \
525 if((pcb)->recv != NULL) { \
526 (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err)); \
528 (ret) = tcp_recv_null(NULL, (pcb), (p), (err)); \
532 #define TCP_EVENT_CONNECTED(pcb,err,ret) \
534 if((pcb)->connected != NULL) \
535 (ret) = (pcb)->connected((pcb)->callback_arg,(pcb),(err)); \
536 else (ret) = ERR_OK; \
539 #define TCP_EVENT_POLL(pcb,ret) \
541 if((pcb)->poll != NULL) \
542 (ret) = (pcb)->poll((pcb)->callback_arg,(pcb)); \
543 else (ret) = ERR_OK; \
546 #define TCP_EVENT_ERR(errf,arg,err) \
549 (errf)((arg),(err)); \
552 #endif /* LWIP_EVENT_API */
554 /* This structure represents a TCP segment on the unsent and unacked queues */
556 struct tcp_seg *next; /* used when putting segements on a queue */
557 struct pbuf *p; /* buffer containing data + TCP header */
558 void *dataptr; /* pointer to the TCP data in the pbuf */
559 u16_t len; /* the TCP length of this segment */
561 #define TF_SEG_OPTS_MSS (u8_t)0x01U /* Include MSS option. */
562 #define TF_SEG_OPTS_TS (u8_t)0x02U /* Include timestamp option. */
563 struct tcp_hdr *tcphdr; /* the TCP header */
566 #define LWIP_TCP_OPT_LENGTH(flags) \
567 (flags & TF_SEG_OPTS_MSS ? 4 : 0) + \
568 (flags & TF_SEG_OPTS_TS ? 12 : 0)
570 /** This returns a TCP header option for MSS in an u32_t */
571 #define TCP_BUILD_MSS_OPTION(x) (x) = htonl(((u32_t)2 << 24) | \
573 (((u32_t)TCP_MSS / 256) << 8) | \
576 /* Internal functions and global variables: */
577 struct tcp_pcb *tcp_pcb_copy(struct tcp_pcb *pcb);
578 void tcp_pcb_purge(struct tcp_pcb *pcb);
579 void tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb);
581 u8_t tcp_segs_free(struct tcp_seg *seg);
582 u8_t tcp_seg_free(struct tcp_seg *seg);
583 struct tcp_seg *tcp_seg_copy(struct tcp_seg *seg);
585 #define tcp_ack(pcb) \
587 if((pcb)->flags & TF_ACK_DELAY) { \
588 (pcb)->flags &= ~TF_ACK_DELAY; \
589 (pcb)->flags |= TF_ACK_NOW; \
592 (pcb)->flags |= TF_ACK_DELAY; \
596 #define tcp_ack_now(pcb) \
598 (pcb)->flags |= TF_ACK_NOW; \
601 err_t tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags);
602 err_t tcp_enqueue(struct tcp_pcb *pcb, void *dataptr, u16_t len,
603 u8_t flags, u8_t apiflags, u8_t optflags);
605 void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg);
607 void tcp_rst(u32_t seqno, u32_t ackno,
608 struct ip_addr *local_ip, struct ip_addr *remote_ip,
609 u16_t local_port, u16_t remote_port);
611 u32_t tcp_next_iss(void);
613 void tcp_keepalive(struct tcp_pcb *pcb);
614 void tcp_zero_window_probe(struct tcp_pcb *pcb);
616 #if TCP_CALCULATE_EFF_SEND_MSS
617 u16_t tcp_eff_send_mss(u16_t sendmss, struct ip_addr *addr);
618 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
620 #if LWIP_CALLBACK_API
621 err_t tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);
622 #endif /* LWIP_CALLBACK_API */
624 extern struct tcp_pcb *tcp_input_pcb;
625 extern u32_t tcp_ticks;
627 const char* tcp_debug_state_str(enum tcp_state s);
628 #if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
629 void tcp_debug_print(struct tcp_hdr *tcphdr);
630 void tcp_debug_print_flags(u8_t flags);
631 void tcp_debug_print_state(enum tcp_state s);
632 void tcp_debug_print_pcbs(void);
633 s16_t tcp_pcbs_sane(void);
635 # define tcp_debug_print(tcphdr)
636 # define tcp_debug_print_flags(flags)
637 # define tcp_debug_print_state(s)
638 # define tcp_debug_print_pcbs()
639 # define tcp_pcbs_sane() 1
640 #endif /* TCP_DEBUG */
642 void tcp_timer_needed(void);
644 /* The TCP PCB lists. */
645 union tcp_listen_pcbs_t { /* List of all TCP PCBs in LISTEN state. */
646 struct tcp_pcb_listen *listen_pcbs;
647 struct tcp_pcb *pcbs;
649 extern union tcp_listen_pcbs_t tcp_listen_pcbs;
650 extern struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a
651 state in which they accept or send
653 extern struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */
655 extern struct tcp_pcb *tcp_tmp_pcb; /* Only used for temporary storage. */
657 /* Axioms about the above lists:
658 1) Every TCP PCB that is not CLOSED is in one of the lists.
659 2) A PCB is only in one of the lists.
660 3) All PCBs in the tcp_listen_pcbs list is in LISTEN state.
661 4) All PCBs in the tcp_tw_pcbs list is in TIME-WAIT state.
664 /* Define two macros, TCP_REG and TCP_RMV that registers a TCP PCB
665 with a PCB list or removes a PCB from a list, respectively. */
667 #define TCP_REG(pcbs, npcb) do {\
668 LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %d\n", npcb, npcb->local_port)); \
669 for(tcp_tmp_pcb = *pcbs; \
670 tcp_tmp_pcb != NULL; \
671 tcp_tmp_pcb = tcp_tmp_pcb->next) { \
672 LWIP_ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != npcb); \
674 LWIP_ASSERT("TCP_REG: pcb->state != CLOSED", npcb->state != CLOSED); \
675 npcb->next = *pcbs; \
676 LWIP_ASSERT("TCP_REG: npcb->next != npcb", npcb->next != npcb); \
678 LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \
679 tcp_timer_needed(); \
681 #define TCP_RMV(pcbs, npcb) do { \
682 LWIP_ASSERT("TCP_RMV: pcbs != NULL", *pcbs != NULL); \
683 LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removing %p from %p\n", npcb, *pcbs)); \
684 if(*pcbs == npcb) { \
685 *pcbs = (*pcbs)->next; \
686 } else for(tcp_tmp_pcb = *pcbs; tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \
687 if(tcp_tmp_pcb->next == npcb) { \
688 tcp_tmp_pcb->next = npcb->next; \
693 LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \
694 LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", npcb, *pcbs)); \
697 #else /* LWIP_DEBUG */
699 #define TCP_REG(pcbs, npcb) \
701 npcb->next = *pcbs; \
703 tcp_timer_needed(); \
706 #define TCP_RMV(pcbs, npcb) \
708 if(*(pcbs) == npcb) { \
709 (*(pcbs)) = (*pcbs)->next; \
712 for(tcp_tmp_pcb = *pcbs; \
713 tcp_tmp_pcb != NULL; \
714 tcp_tmp_pcb = tcp_tmp_pcb->next) { \
715 if(tcp_tmp_pcb->next == npcb) { \
716 tcp_tmp_pcb->next = npcb->next; \
724 #endif /* LWIP_DEBUG */
730 #endif /* LWIP_TCP */
732 #endif /* __LWIP_TCP_H__ */