• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * @file
3  * TCP API (to be used from TCPIP thread)\n
4  * See also @ref tcp_raw
5  */
6 
7 /*
8  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without modification,
12  * are permitted provided that the following conditions are met:
13  *
14  * 1. Redistributions of source code must retain the above copyright notice,
15  *    this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright notice,
17  *    this list of conditions and the following disclaimer in the documentation
18  *    and/or other materials provided with the distribution.
19  * 3. The name of the author may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
23  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
25  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
27  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
31  * OF SUCH DAMAGE.
32  *
33  * This file is part of the lwIP TCP/IP stack.
34  *
35  * Author: Adam Dunkels <adam@sics.se>
36  *
37  */
38 #ifndef LWIP_HDR_TCP_H
39 #define LWIP_HDR_TCP_H
40 
41 #include "lwip/opt.h"
42 
43 #if LWIP_TCP /* don't build if not configured for use in lwipopts.h */
44 
45 #include "lwip/tcpbase.h"
46 #include "lwip/mem.h"
47 #include "lwip/pbuf.h"
48 #include "lwip/ip.h"
49 #include "lwip/icmp.h"
50 #include "lwip/err.h"
51 #include "lwip/ip6.h"
52 #include "lwip/ip6_addr.h"
53 
54 #if defined (__cplusplus) && __cplusplus
55 extern "C" {
56 #endif
57 
58 struct tcp_pcb;
59 struct tcp_pcb_listen;
60 
61 /**
62  * @brief Function prototype for TCP accept callback functions. Called when a new
63  * connection can be accepted on a listening PCB.
64  *
65  * @param arg Indicates an additional argument to pass to the callback function (Refer to tcp_arg()).
66  * @param newpcb Indicates the new connection PCB.
67  * @param err Indicates an error code if there has been an error.
68  *            This function returns ERR_ABRT if you have called tcp_abort() from within the
69  *            callback function.
70  */
71 typedef err_t (*tcp_accept_fn)(void *arg, struct tcp_pcb *newpcb, err_t err);
72 
73 /** @brief Function prototype for TCP receive callback functions. Called when data has
74  * been received.
75  *
76  * @param arg Indicates an additional argument to pass to the callback function (Refer to tcp_arg()).
77  * @param tpcb Indicates the connection PCB which received data.
78  * @param p Indicates the received data, or NULL when the connection has been closed.
79  * @param err Indicates an error code if there is an error in receiving.
80  *            This function returns ERR_ABRT if you have called tcp_abort from within the
81  *            callback function.
82  */
83 typedef err_t (*tcp_recv_fn)(void *arg, struct tcp_pcb *tpcb,
84                              struct pbuf *p, err_t err);
85 
86 /** @brief Function prototype for TCP sent callback functions. Called when sent data has
87  * been acknowledged by the remote side. Used to free corresponding resources.
88  * This also means that the PCB has now space available to send new data.
89  *
90  * @param arg Indicates an additional argument to pass to the callback function (Refer to tcp_arg()).
91  * @param tpcb Indicates the connection PCB for which data has been acknowledged.
92  * @param len Indicates the amount of bytes acknowledged.
93  * @return ERR_OK: try to send some data by calling tcp_output()
94  *            This function returns ERR_ABRT if you have called tcp_abort() from within the
95  *            callback function.
96  */
97 typedef err_t (*tcp_sent_fn)(void *arg, struct tcp_pcb *tpcb,
98                              u16_t len);
99 
100 /** @brief Function prototype for TCP poll callback functions. Called periodically as
101  * specified by tcp_poll().
102  *
103  * @param arg Indicates an additional argument to pass to the callback function
104  (Refer to tcp_arg()).
105  * @param tpcb Indicates the TCP PCB.
106  * @return ERR_OK: try to send some data by calling tcp_output()
107  *            This function returns ERR_ABRT if you have called tcp_abort() from within the
108  *            callback function.
109  */
110 typedef err_t (*tcp_poll_fn)(void *arg, struct tcp_pcb *tpcb);
111 
112 /** @brief Function prototype for TCP error callback functions. Called when the PCB
113  * receives a RST or is unexpectedly closed for any other reason.
114  *
115  * @note The corresponding PCB is already freed when this callback is called.
116  *
117  * @param arg Indicates an additional argument to pass to the callback function
118  (Refer to tcp_arg()).
119  * @param err Provides an error code to indicate why the PCB has been closed. \n
120  *            ERR_ABRT: Aborted through tcp_abort or by a TCP timer. \n
121  *            ERR_RST: The connection was reset by the remote host.
122  */
123 typedef void  (*tcp_err_fn)(void *arg, err_t err);
124 
125 /** @brief Function prototype for TCP connected callback functions. Called when a PCB
126  * is connected to the remote side after initiating a connection attempt by
127  * calling tcp_connect().
128  *
129  * @param arg Indicates an additional argument to pass to the callback function
130  (Refer to tcp_arg()).
131  * @param tpcb Indicates the connection PCB which is connected.
132  * @param err Indicates an unused error code, always ERR_OK currently.
133  *            Only return ERR_ABRT if you have called tcp_abort from within the
134  *            callback function
135  *
136  * @note When a connection attempt fails, the error callback is currently called.
137  */
138 typedef err_t (*tcp_connected_fn)(void *arg, struct tcp_pcb *tpcb, err_t err);
139 
140 #if DRIVER_STATUS_CHECK
141 typedef void (*tcp_event_sndplus_fn)(void *arg, struct tcp_pcb *tpcb);
142 #endif
143 
144 #if LWIP_WND_SCALE
145 /** Recv Window Scaling. Announce Window Size. */
146 #define RCV_WND_SCALE(pcb, wnd) (((wnd) >> (pcb)->rcv_scale))
147 /** Send Window Scaling. Sender Window Size */
148 #define SND_WND_SCALE(pcb, wnd) (((tcpwnd_size_t)(wnd)  << (pcb)->snd_scale))
149 /** Window Scaling. Actual Window Size. */
150 #define ACTUAL_WND_SIZE(pcb, wnd) ((tcpwnd_size_t)((wnd) >> (pcb)->rcv_scale) << (pcb)->rcv_scale)
151 /** TCP Window Size. */
152 #define TCPWND16(x)             ((u16_t)LWIP_MIN((x), 0xFFFF))
153 /** TCP maximum window size. */
154 #define TCP_WND_MAX(pcb)        ((tcpwnd_size_t)(((pcb)->flags & TF_WND_SCALE) ? TCP_WND : TCPWND16(TCP_WND)))
155 #else /* LWIP_WND_SCALE */
156 #define RCV_WND_SCALE(pcb, wnd) (wnd)
157 #define SND_WND_SCALE(pcb, wnd) (wnd)
158 #define TCPWND16(x)             (x)
159 #define TCP_WND_MAX(pcb)        TCP_WND
160 #endif /* LWIP_WND_SCALE */
161 
162 typedef u32_t tcpflags_t;
163 
164 #define TCP_ALLFLAGS 0xFFFFFFFFU
165 #define SNDQUEUE_MAX 0xFFFF
166 #define SNDQUEUE_MIN 5
167 
168 /* Increments a tcpwnd_size_t and holds at max value rather than rollover */
169 #define TCP_WND_INC(wnd, inc) do { \
170   if ((tcpwnd_size_t)((wnd) + (inc)) >= (wnd)) { \
171     (wnd) = (tcpwnd_size_t)((wnd) + (inc)); \
172   } else { \
173     (wnd) = (tcpwnd_size_t)-1; \
174   } \
175 } while (0)
176 
177 #define TCP_WND_DEC(wnd, dec, mss) do { \
178   if ((wnd) >= (dec) && (wnd) >= (mss)) { \
179     (wnd) = (tcpwnd_size_t)(wnd - (dec)); \
180   } else { \
181     (wnd) = (mss); \
182   } \
183 } while (0)
184 
185 #ifndef LWIP_INITIAL_CWND_OVERRIDE
186 /*
187   [RFC 5681] [3.1.  Slow Start and Congestion Avoidance]
188   IW, the initial value of cwnd, MUST be set using the following guidelines as an upper bound.
189 */
190 #define LWIP_TCP_CALC_INITIAL_CWND(SMSS, IW) do { \
191   if ((SMSS) > 2190) { \
192     (IW) = (tcpwnd_size_t)(2 * (SMSS)); \
193   } else if (((SMSS) > 1095) && ((SMSS) <= 2190)) { \
194     (IW) = (tcpwnd_size_t)(3 * (SMSS)); \
195   } else if ((SMSS) <= 1095) { \
196     (IW) = (tcpwnd_size_t)(4 * (SMSS)); \
197   } \
198 } while (0)
199 #else
200 #define LWIP_TCP_CALC_INITIAL_CWND(SMSS, IW) do { \
201   IW = (tcpwnd_size_t)((LWIP_INITIAL_CWND_OVERRIDE) * (SMSS)); \
202 } while (0)
203 #endif
204 
205 /* Increments a wnd * mss and holds at max value rather than rollover */
206 #define TCP_CALC_SSTHRESH(pcb, ssthresh, wnd, mss) do { \
207   if (((u64_t)(wnd) * (mss))  < TCP_WND_MAX(pcb)) { \
208     (ssthresh) = (tcpwnd_size_t)((wnd) * (mss)); \
209   } else { \
210     (ssthresh) = TCP_WND_MAX(pcb); \
211   } \
212 } while (0)
213 
214 #ifndef LWIP_CONGCNTRL_DUPACK_THRESH
215 /** Congestion Control duplicate Acknowledgement Threshold */
216 #define DUPACK_THRESH       3
217 #else
218 #define DUPACK_THRESH       LWIP_CONGCNTRL_DUPACK_THRESH
219 #endif
220 
221 #ifndef LWIP_CONGCNTRL_INITIAL_SSTHRESH
222 /** Initial Congestion Control Slow Start Threshold. */
223 #define INITIAL_SSTHRESH       40
224 #else
225 #define INITIAL_SSTHRESH       LWIP_CONGCNTRL_INITIAL_SSTHRESH
226 #endif
227 
228 #if DRIVER_STATUS_CHECK
229 #define DRV_READY         1
230 #define DRV_NOT_READY     0
231 #endif
232 
233 /* Indicates that this pbuf includes a TCP FIN flag and post to mbox is failed */
234 #define TCP_PBUF_FLAG_TCP_FIN_RECV_SYSPOST_FAIL 0x01U
235 
236 /* Adding for SACK */
237 #if LWIP_SACK
238 struct _sack_seq {
239   struct _sack_seq *next;
240   u32_t left;
241   u32_t right;
242   u32_t order;
243 };
244 #endif
245 
246 #if LWIP_SACK_PERF_OPT
247 struct tcp_sack_fast_rxmited {
248   struct tcp_sack_fast_rxmited *next;
249   struct tcp_seg *seg;
250 };
251 #endif
252 
253 #if LWIP_SO_SNDBUF
254 #define LWIP_SO_SNDBUF_DECL  tcpwnd_size_t snd_buf_static;   /* Configured send buffer size */
255 #else
256 #define LWIP_SO_SNDBUF_DECL
257 #endif /* LWIP_SO_SNDBUF */
258 
259 /** Function prototype for deallocation of arguments. Called *just before* the
260  * pcb is freed, so don't expect to be able to do anything with this pcb!
261  *
262  * @param id ext arg id (allocated via @ref tcp_ext_arg_alloc_id)
263  * @param data pointer to the data (set via @ref tcp_ext_arg_set before)
264  */
265 typedef void (*tcp_extarg_callback_pcb_destroyed_fn)(u8_t id, void *data);
266 
267 /** Function prototype to transition arguments from a listening pcb to an accepted pcb
268  *
269  * @param id ext arg id (allocated via @ref tcp_ext_arg_alloc_id)
270  * @param lpcb the listening pcb accepting a connection
271  * @param cpcb the newly allocated connection pcb
272  * @return ERR_OK if OK, any error if connection should be dropped
273  */
274 typedef err_t (*tcp_extarg_callback_passive_open_fn)(u8_t id, struct tcp_pcb_listen *lpcb, struct tcp_pcb *cpcb);
275 
276 /** A table of callback functions that is invoked for ext arguments */
277 struct tcp_ext_arg_callbacks {
278   /** @ref tcp_extarg_callback_pcb_destroyed_fn */
279   tcp_extarg_callback_pcb_destroyed_fn destroy;
280   /** @ref tcp_extarg_callback_passive_open_fn */
281   tcp_extarg_callback_passive_open_fn passive_open;
282 };
283 
284 #define LWIP_TCP_PCB_NUM_EXT_ARG_ID_INVALID 0xFF
285 
286 #if LWIP_TCP_PCB_NUM_EXT_ARGS
287 /* This is the structure for ext args in tcp pcbs (used as array) */
288 struct tcp_pcb_ext_args {
289   const struct tcp_ext_arg_callbacks *callbacks;
290   void *data;
291 };
292 /* This is a helper define to prevent zero size arrays if disabled */
293 #define TCP_PCB_EXTARGS struct tcp_pcb_ext_args ext_args[LWIP_TCP_PCB_NUM_EXT_ARGS];
294 #else
295 #define TCP_PCB_EXTARGS
296 #endif
297 
298 /**
299  * Indicates members common to struct tcp_pcb and struct tcp_listen_pcb.
300  */
301 #define TCP_PCB_COMMON(type) \
302   type *next; /* for the linked list */ \
303   void *callback_arg; \
304   enum tcp_state state; /* TCP state */ \
305   u8_t prio; \
306   /* ports are in host byte order */ \
307   u16_t local_port; \
308   /* Configured send buffer size */ \
309   LWIP_SO_SNDBUF_DECL
310 
311 #if LWIP_TCP_TLP_SUPPORT
312 
313 #define TCP_TLP_MAX_PROBE_CNT 2
314 
315 #define LWIP_TCP_TLP_CLEAR_VARS(_pcb) do { \
316   _pcb->tlp_pto_cnt = 0; \
317   _pcb->tlp_rtx_out = 0; \
318   _pcb->tlp_high_rxt = 0; \
319   _pcb->tlp_time_stamp = 0; \
320 } while (0)
321 
322 #define LWIP_TCP_TLP_WCDELACKT 200 /* RECOMMENDED value is 200ms */
323 #endif /* LWIP_TCP_TLP_SUPPORT */
324 
325 /** Indicates the TCP protocol control block for listening PCBs. */
326 struct tcp_pcb_listen {
327   /** Common members of all PCB types */
328   IP_PCB;
329   /** Protocol specific PCB members */
330   TCP_PCB_COMMON(struct tcp_pcb_listen)
331 
332 #if LWIP_CALLBACK_API
333   /* Function to call when a listener has been connected. */
334   tcp_accept_fn accept;
335 #endif /* LWIP_CALLBACK_API */
336 
337 #if LWIP_SO_PRIORITY
338   prio_t priority;
339 #endif /* LWIP_SO_PRIORITY */
340 
341 #if TCP_LISTEN_BACKLOG
342   u8_t backlog;
343   u8_t accepts_pending;
344 #endif /* TCP_LISTEN_BACKLOG */
345 };
346 
347 /** Delayed ACK. */
348 #define TF_ACK_DELAY   0x01U
349 /** Immediate ACK. */
350 #define TF_ACK_NOW     0x02U
351 /** In fast recovery. */
352 #define TF_INFR        0x04U
353 /** If this is set, tcp_close failed to enqueue the FIN (retried in tcp_tmr) */
354 #define TF_CLOSEPEND   0x08U
355 /** Rx is closed by tcp_shutdown */
356 #define TF_RXCLOSED    0x10U
357 /** Connection was closed locally (FIN segment enqueued). */
358 #define TF_FIN         0x20U
359 /** Disable Nagle algorithm */
360 #define TF_NODELAY     0x40U
361 /** Nagle algorithm is enabled. memerr. Try to output to prevent delayed ACK to happen */
362 #define TF_NAGLEMEMERR 0x80U
363 #if LWIP_WND_SCALE
364 /** Window Scale option enabled */
365 #define TF_WND_SCALE   0x0100U
366 #endif
367 #if TCP_LISTEN_BACKLOG
368 /** If this is set, a connection PCB has increased the backlog on its listener */
369 #define TF_BACKLOGPEND 0x0200U
370 #endif
371 #if LWIP_TCP_TIMESTAMPS
372 /** Timestamp option enabled */
373 #define TF_TIMESTAMP   0x0400U
374 #endif
375 /** Tx closed by tcp_shutdown */
376 #define TF_TXCLOSED    0x0800U
377 
378 /* TCP flags for New Reno */
379 #define TF_INFR_PACK  ((tcpflags_t)0x1000U)   /* Partial ACK recved flag */
380 #define TF_RTO        ((tcpflags_t)0x2000U)   /* RTO timer has fired, in-flight data moved to unsent and being retransmitted */
381 #define TF_INFR_FPACK        ((tcpflags_t)0x4000U)   /* Flag for wait for first parital ack */
382 
383 #if LWIP_SACK
384 /** TCP SACK option enabled. */
385 #define TF_SACK         ((tcpflags_t)0x10000U)
386 /** In SACK based Fast retransmit & loss recovery algorithm */
387 #define TF_IN_SACK_FRLR ((tcpflags_t)0x20000U)
388 /** From loss recovery, it entered to Retrasnmit timeout state. */
389 #define TF_IN_SACK_RTO  ((tcpflags_t)0x40000U)
390 #endif
391 
392 #if DRIVER_STATUS_CHECK
393 #define TF_RST_ON_DRV_WAKE  ((tcpflags_t)0x80000U)   /* From loss receovery it entered to Retrasnmit timeout state */
394 #endif
395 
396 /** the TCP protocol control block */
397 struct tcp_pcb {
398   /** common PCB members */
399   IP_PCB;
400   /** protocol specific PCB members */
401   TCP_PCB_COMMON(struct tcp_pcb)
402 
403   /* ports are in host byte order */
404   u16_t remote_port;
405   u16_t pad1;
406 
407   tcpflags_t flags;
408 
409 #if DRIVER_STATUS_CHECK
410   /* Netif driver status */
411   u8_t drv_status; /* 0 - Driver not ready. 1- Driver is ready */
412   u8_t pad0;
413 #endif
414 
415   /* the rest of the fields are in host byte order
416      as we have to do some math with them */
417   /* Timers */
418   u8_t polltmr, pollinterval;
419   u8_t last_timer;
420   u32_t tmr;
421 
422   /* receiver variables */
423   u32_t rcv_nxt;   /* next seqno expected */
424   tcpwnd_size_t rcv_wnd;   /* receiver window available */
425   tcpwnd_size_t rcv_ann_wnd; /* receiver window to announce */
426   u32_t rcv_ann_right_edge; /* announced right edge of window */
427 
428   /* Retransmission timer. */
429   s16_t rtime;
430 
431   u16_t mss;   /* maximum segment size, the real value used to do segmentation */
432   u16_t rcv_mss; /* mss from peer side */
433 
434   u16_t pad4;
435 
436   /* RTT (round trip time) estimation variables */
437   u32_t rttest;   /* The start time of RTT sample in ms, the granularity is system tick */
438   u32_t rtseq;    /* sequence number being timed */
439   s16_t sa;   /* smoothed round-trip time, 8 times of SRTT in RFC6298 */
440   s16_t sv;   /* round-trip time variation, 4 times of RTTVAR in RFC6298 */
441 
442   s16_t rto;    /* retransmission time-out (in ticks of TCP_SLOW_INTERVAL) */
443   u8_t nrtx;    /* number of retransmissions */
444 
445   /* fast retransmit/recovery */
446   u8_t dupacks;
447 
448   u16_t pad5;
449 
450   u32_t lastack; /* Highest acknowledged seqno, also knowns SND.UNA */
451 
452   /* congestion avoidance/control variables */
453   tcpwnd_size_t iw;
454   tcpwnd_size_t cwnd;
455   tcpwnd_size_t ssthresh;
456   u32_t rto_end;
457 
458   /* sender variables */
459   u32_t snd_nxt;   /* next new seqno to be sent */
460   u32_t snd_sml;   /* The last byte of the most recently transmitted small packet */
461   u32_t snd_wl1, snd_wl2; /* Sequence and acknowledgement numbers of last
462                              window update. */
463   u32_t snd_lbb;       /* Sequence number of next byte to be buffered. */
464   tcpwnd_size_t snd_wnd;   /* sender window */
465   tcpwnd_size_t snd_wnd_max; /* the maximum sender window announced by the remote host */
466 
467   tcpwnd_size_t snd_buf;   /* Available buffer space for sending (in bytes). */
468 
469   tcpwnd_size_t bytes_acked;
470 
471 #if LWIP_WND_SCALE
472 #define TCP_SNDQUEUELEN_OVERFLOW (0x03ffffffU - 3)
473 #else /* LWIP_WND_SCALE */
474 #define TCP_SNDQUEUELEN_OVERFLOW (0xffffU - 3)
475 #endif /* LWIP_WND_SCALE */
476   tcpwnd_size_t snd_queuelen; /* Available buffer space for sending (in tcp_segs). */
477 
478   tcpwnd_size_t snd_queuelen_max;
479   tcpwnd_size_t snd_queuelen_lowat;
480   tcpwnd_size_t snd_buf_lowat;
481 
482 #if TCP_OVERSIZE
483   /* Extra bytes available at the end of the last pbuf in unsent. */
484   u16_t unsent_oversize;
485   u16_t pad2;
486 #endif /* TCP_OVERSIZE */
487 
488   /* These are ordered by sequence number: */
489   struct tcp_seg *unsent;   /* Unsent (queued) segments. */
490   struct tcp_seg *unacked;  /* Sent but unacknowledged segments. */
491 #if TCP_QUEUE_OOSEQ
492   struct tcp_seg *ooseq;    /* Received out of sequence segments. */
493 #endif /* TCP_QUEUE_OOSEQ */
494 
495   struct pbuf *refused_data; /* Data previously received but not yet taken by upper layer */
496 
497 #if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG
498   struct tcp_pcb_listen *listener;
499 #endif /* LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG */
500 
501 #if LWIP_CALLBACK_API
502   /* Function to be called when more send buffer space is available. */
503   tcp_sent_fn sent;
504   /* Function to be called when (in-sequence) data has arrived. */
505   tcp_recv_fn recv;
506   /* Function to be called when a connection has been set up. */
507   tcp_connected_fn connected;
508   /* Function which is called periodically. */
509   tcp_poll_fn poll;
510   /* Function to be called whenever a fatal error occurs. */
511   tcp_err_fn errf;
512 #endif /* LWIP_CALLBACK_API */
513 
514 #if DRIVER_STATUS_CHECK
515   tcp_event_sndplus_fn  sndplus;
516 #endif
517 
518 #if LWIP_TCP_TIMESTAMPS
519   u32_t ts_lastacksent;
520   u32_t ts_recent;
521 #endif /* LWIP_TCP_TIMESTAMPS */
522 
523   /* idle time before KEEPALIVE is sent */
524   u32_t keep_idle;
525 #if LWIP_TCP_KEEPALIVE
526   u32_t keep_intvl;
527   u32_t keep_cnt;
528 #endif /* LWIP_TCP_KEEPALIVE */
529 
530   /* Persist timer counter */
531   u8_t persist_cnt;
532   /* Persist timer back-off */
533   u8_t persist_backoff;
534   /* Number of persist probes, used for timeout calculation */
535   u8_t persist_probe;
536   /* KEEPALIVE counter */
537   u8_t keep_cnt_sent;
538 
539   u32_t last_payload_len;
540 
541   u32_t fast_recovery_point; /* snd_nxt when enter fast recovery */
542 
543 #if LWIP_SACK
544   struct _sack_seq *sack_seq;
545   /* SACK based pipe algorthim Changes */
546   /* Pipe to hold the number of octets available in network */
547   u32_t pipe;
548   /* Recovery point for stopping loss recovery phase */
549   u32_t recovery_point;
550   /* highest octet covered by any received SACK block */
551   u32_t high_sacked;
552 
553   /* Loss recovery check needs to be started from this seg instead of pcb->unacked */
554   /* This excludes the rexmited and sacked seg from pcb->unacked */
555   /* That means, next_seg_for_lr points to first unsacked and  not retransmitted seg */
556   /* Optimization of SACK based pipe algorthim */
557   struct tcp_seg *next_seg_for_lr;
558 
559   /* highest data trasnfered so far, equivalent to snd_nxt */
560   u32_t high_data;
561   /* highest octet retransmitted so far, as part of SACK based loss recovery algorithm */
562   u32_t high_rxt;
563   /* Rescure rxt as per loss recovery algorithm */
564   u32_t rescue_rxt;
565 
566   u32_t num_sacks;
567   u32_t ooseq_cnt;
568 
569 #if LWIP_SACK_PERF_OPT
570   u32_t pkt_seq_num;  /* packet order on which they are transmitted out of stack */
571   u32_t high_sacked_pkt_seq;
572   struct tcp_sack_fast_rxmited *fr_segs; /* List of fast retransmitted segments */
573   /*
574    * The latest fast retransmitted segment. This stores the latest
575    * fast retransmitted segment so that when more segments are retransmitted,
576    * it can be appended to this segmetn without iterating whole list
577    */
578   struct tcp_sack_fast_rxmited *last_frseg;
579 #if LWIP_SACK_CWND_OPT
580   tcpwnd_size_t recover_cwnd;
581   tcpwnd_size_t recover_ssthresh;
582 #endif /* LWIP_SACK_CWND_OPT */
583 #endif /*LWIP_SACK_PERF_OPT*/
584   u32_t sacked; /* The total SACKed segments count */
585 
586 #if LWIP_FACK_THRESHOLD_BASED_FR
587   u32_t fack;
588 #endif /* LWIP_FACK_THRESHOLD_BASED_FR */
589 
590 #if LWIP_TCP_TLP_SUPPORT
591   u8_t tlp_pto_cnt; /* Consecutive PTOs */
592   u8_t tlp_rtx_out; /* the number of unacknowledged TLP retransmissions in current TLP episode */
593   u32_t tlp_high_rxt; /* SND.NXT at the time it starts doing TLP transmissions during a given TLP episode */
594   u32_t tlp_time_stamp; /* PTO trigger time in ms. 0 is one specially value which means PTO is not scheduled */
595 #endif /* LWIP_TCP_TLP_SUPPORT */
596 #endif /* LWIP_SACK */
597 
598 #if LWIP_SO_PRIORITY
599   prio_t priority;
600 #endif /* LWIP_SO_PRIORITY */
601 
602 #if LWIP_WND_SCALE
603   u8_t snd_scale;
604   u8_t rcv_scale;
605 #endif
606 
607   u8_t tcp_pcb_flag;
608 };
609 
610 #if LWIP_EVENT_API
611 
612 enum lwip_event {
613   LWIP_EVENT_ACCEPT,
614   LWIP_EVENT_SENT,
615   LWIP_EVENT_RECV,
616   LWIP_EVENT_CONNECTED,
617   LWIP_EVENT_POLL,
618   LWIP_EVENT_ERR
619 };
620 
621 err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb,
622                      enum lwip_event,
623                      struct pbuf *p,
624                      u16_t size,
625                      err_t err);
626 
627 #endif /* LWIP_EVENT_API */
628 
629 #if LWIP_API_RICH
630 /* Application program's interface: */
631 /**
632  * @ingroup tcp_raw
633  * Creates a new TCP protocol control block but does not place it on
634  * any of the TCP PCB lists.
635  * The PCB is not put on any list until binding using tcp_bind().
636  *
637  * @note Maybe there should be a idle TCP PCB list where these
638  * PCBs are put on. Port reservation using tcp_bind() is implemented but
639  * allocated pcbs that are not bound cannot be killed automatically if wanting
640  * to allocate a PCB with higher prio.
641  *
642  * @return Returns a new tcp_pcb that initially is in state CLOSED.
643  */
644 struct tcp_pcb *tcp_new     (void);
645 #endif /* LWIP_API_RICH */
646 
647 /**
648  * @ingroup tcp_raw
649  * Creates a new TCP protocol control block but doesn't
650  * place it on any of the TCP PCB lists.
651  * The PCB is not put on any list until binding using tcp_bind().
652  *
653  * @param type IP address type.
654  * If you want to listen to IPv4 and IPv6 (dual-stack) connections,
655  * supply @ref IPADDR_TYPE_ANY as argument and bind to @ref IP_ANY_TYPE.
656  * @return Returns a new tcp_pcb that initially is in state CLOSED.
657  */
658 struct tcp_pcb *tcp_new_ip_type (u8_t type);
659 /**
660  * @ingroup tcp_raw
661  * Used to specify the argument that should be passed callback
662  * functions.
663  *
664  * @param pcb Indicates the tcp_pcb to set the callback argument.
665  * @param arg A void pointer argument to pass to callback functions.
666  */
667 void             tcp_arg     (struct tcp_pcb *pcb, void *arg);
668 #if LWIP_CALLBACK_API
669 /**
670  * @ingroup tcp_raw
671  * Used to specify the function that should be called when a TCP
672  * connection receives data.
673  *
674  * @param pcb Indicates the tcp_pcb to set the recv callback
675  * @param recv A callback function to call for this PCB when data is received.
676  */
677 void             tcp_recv    (struct tcp_pcb *pcb, tcp_recv_fn recv);
678 /**
679  * @ingroup tcp_raw
680  * Used to specify the function that should be called when TCP data
681  * has been successfully delivered to the remote host.
682  *
683  * @param pcb Indicates the tcp_pcb to set the sent callback.
684  * @param sent A callback function to call for this pcb when data is successfully sent
685  */
686 void             tcp_sent    (struct tcp_pcb *pcb, tcp_sent_fn sent);
687 /**
688  * @ingroup tcp_raw
689  * Used to specify the function that should be called when a fatal error
690  * has occurred on the connection.
691  *
692  * @note The corresponding PCB is already freed when this callback is called!
693  *
694  * @param pcb Indicates a tcp_pcb to set the err callback.
695  * @param err callback function to call for this PCB when a fatal error
696  *        has occurred on the connection.
697  */
698 void             tcp_err     (struct tcp_pcb *pcb, tcp_err_fn err);
699 
700 /**
701  * @ingroup tcp_raw
702  * Used for specifying the function that should be called when a
703  * listening connection has been connected to another host.
704  *
705  * @param pcb Indicates the tcp_pcb to set the accept callback.
706  * @param accept callback function to call for this PCB when listening
707  *        connection has been connected to another host.
708  */
709 void             tcp_accept  (struct tcp_pcb *pcb, tcp_accept_fn accept);
710 #endif /* LWIP_CALLBACK_API */
711 /**
712  * @ingroup tcp_raw
713  * Used to specify the function that should be called periodically
714  * from TCP. The interval is specified in terms of the TCP coarse
715  * timer interval, which is called twice a second.
716  *
717  */
718 void             tcp_poll    (struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval);
719 
720 #if LWIP_LOWPOWER
721 u32_t tcp_fast_tmr_tick(void);
722 u32_t tcp_slow_tmr_tick(void);
723 #endif
724 
725 #if LWIP_TCP_TIMESTAMPS
726 #define          tcp_mss(pcb)             (((pcb)->flags & TF_TIMESTAMP) ? ((pcb)->mss - 12)  : (pcb)->mss)
727 #else /* LWIP_TCP_TIMESTAMPS */
728 #define          tcp_mss(pcb)             ((pcb)->mss)
729 #endif /* LWIP_TCP_TIMESTAMPS */
730 #define          tcp_sndbuf(pcb)          ((pcb)->snd_buf)
731 #define          tcp_sndqueuelen(pcb)     ((pcb)->snd_queuelen)
732 
733 #if LWIP_SO_SNDBUF
734 #define          tcp_set_sendbufsize(pcb, size)    ((pcb)->snd_buf_static = (tcpwnd_size_t)(size))
735 #define          tcp_get_sendbufsize(pcb)    ((pcb)->snd_buf_static)
736 #endif /* LWIP_SO_SNDBUF */
737 
738 #if LWIP_SO_PRIORITY
739 #define      tcp_getpriority(pcb)  ((pcb)->priority)
740 #endif /* LWIP_SO_PRIORITY */
741 
742 #define          tcp_set_flags(pcb, set_flags) do { \
743   (pcb)->flags = (tcpflags_t)((pcb)->flags | (set_flags)); } while (0)
744 #define          tcp_clear_flags(pcb, clr_flags) do { \
745   (pcb)->flags = (tcpflags_t)((pcb)->flags & (tcpflags_t)(~(clr_flags) & TCP_ALLFLAGS)); } while (0)
746 #define          tcp_is_flag_set(pcb, flag)        (((pcb)->flags & (flag)) != 0)
747 
748 /** @ingroup tcp_raw */
749 #define          tcp_nagle_disable(pcb)   ((pcb)->flags |= TF_NODELAY)
750 /** @ingroup tcp_raw
751 * Enables Nagle algorithm. */
752 #define          tcp_nagle_enable(pcb)    ((pcb)->flags = (tcpflags_t)((pcb)->flags & ~TF_NODELAY))
753 /** @ingroup tcp_raw
754 * Disables Nagle algorithm. */
755 #define          tcp_nagle_disabled(pcb)  (((pcb)->flags & TF_NODELAY) != 0)
756 
757 #if TCP_LISTEN_BACKLOG
758 #define          tcp_backlog_set(pcb, new_backlog) do { \
759   LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", (pcb)->state == LISTEN); \
760   ((struct tcp_pcb_listen *)(pcb))->backlog = (u8_t)((new_backlog) ? (new_backlog) : 1); } while (0)
761 void             tcp_backlog_delayed(struct tcp_pcb *pcb);
762 void             tcp_backlog_accepted(struct tcp_pcb *pcb);
763 #else /* TCP_LISTEN_BACKLOG */
764 #define          tcp_backlog_set(pcb, new_backlog)
765 #define          tcp_backlog_delayed(pcb)
766 #define          tcp_backlog_accepted(pcb)
767 #endif /* TCP_LISTEN_BACKLOG */
768 #define          tcp_accepted(pcb) do { LWIP_UNUSED_ARG(pcb); } while (0) /* compatibility define, no need any more */
769 
770 void             tcp_recved  (struct tcp_pcb *pcb, u16_t len);
771 err_t            tcp_bind    (struct tcp_pcb *pcb, const ip_addr_t *ipaddr,
772                               u16_t port);
773 err_t            tcp_connect (struct tcp_pcb *pcb, const ip_addr_t *ipaddr,
774                               u16_t port, tcp_connected_fn connected);
775 
776 struct tcp_pcb *tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err);
777 #if LWIP_API_RICH
778 struct tcp_pcb *tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog);
779 /** @ingroup tcp_raw */
780 #define          tcp_listen(pcb) tcp_listen_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG)
781 #endif /* LWIP_API_RICH */
782 
783 void             tcp_abort (struct tcp_pcb *pcb);
784 err_t            tcp_close   (struct tcp_pcb *pcb);
785 err_t            tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx);
786 
787 err_t            tcp_write   (struct tcp_pcb *pcb, const void *dataptr, tcpwnd_size_t len,
788                               u8_t apiflags);
789 
790 #if LWIP_API_RICH
791 void             tcp_setprio (struct tcp_pcb *pcb, u8_t prio);
792 #endif /* LWIP_API_RICH */
793 
794 #if LWIP_TCP_TLP_SUPPORT
795 /*
796  * This is the TLP probe timeout function as in draft-dukkipati-tcpm-tcp-loss-probe-01
797  *
798  * When PTO fires:
799  *   (a) If a new previously unsent segment exists:
800  *         -> Transmit new segment.
801  *         -> FlightSize += SMSS. cwnd remains unchanged.
802  *   (b) If no new segment exists:
803  *         -> Retransmit the last segment.
804  *   (c) Increment statistics counter for loss probes.
805  *   (d) If conditions in (2) are satisfied:
806  *         -> Reschedule next PTO.
807  *       Else:
808  *         -> Rearm RTO to fire at epoch 'now+RTO'.
809  *
810  * @param pcb Protocol control block for the TCP connection to send data
811  * @return None
812  *
813  */
814 void tcp_pto_fire(struct tcp_pcb *pcb);
815 #endif
816 
817 err_t tcp_output  (struct tcp_pcb *pcb);
818 
819 #if API_MSG_DEBUG || (defined LWIP_DEBUG)
820 const char *tcp_debug_state_str(enum tcp_state s);
821 #endif /* API_MSG_DEBUG */
822 
823 #if DRIVER_STATUS_CHECK
824 unsigned char tcp_is_netif_addr_check_success(struct tcp_pcb *pcb, struct netif *netif);
825 void tcp_flush_pcb_on_wake_queue(struct tcp_pcb *pcb, u8_t status);
826 void tcpip_flush_on_wake_queue(struct netif *netif, u8_t status);
827 void tcp_ip_flush_pcblist_on_wake_queue(struct netif *netif, struct tcp_pcb *pcb_list, u8_t status);
828 void tcpip_upd_status_to_tcp_pcbs(struct netif *netif, u8_t status);
829 void tcp_ip_event_sendplus_on_wake_queue(struct netif *netif);
830 void tcp_update_drv_status_to_pcbs(struct tcp_pcb *pcb_list, struct netif *netif, u8_t status);
831 #endif
832 
833 /* for compatibility with older implementation */
834 #define tcp_new_ip6() tcp_new_ip_type(IPADDR_TYPE_V6)
835 
836 void tcp_sndbuf_init(struct tcp_pcb *pcb);
837 
838 #if LWIP_API_RICH
839 const char *get_lwip_version(void);
840 #endif /* LWIP_API_RICH */
841 
842 void tcp_handle_closepend(void);
843 
844 #if LWIP_TCP_TLP_SUPPORT
845 void tcp_tlp_schedule_probe(struct tcp_pcb *pcb, u32_t wnd);
846 #endif /* LWIP_TCP_TLP_SUPPORT */
847 
848 #if LWIP_TCP_PCB_NUM_EXT_ARGS
849 u8_t tcp_ext_arg_alloc_id(void);
850 void tcp_ext_arg_set_callbacks(struct tcp_pcb *pcb, uint8_t id, const struct tcp_ext_arg_callbacks * const callbacks);
851 void tcp_ext_arg_set(struct tcp_pcb *pcb, uint8_t id, void *arg);
852 void *tcp_ext_arg_get(const struct tcp_pcb *pcb, uint8_t id);
853 #endif
854 
855 #if defined (__cplusplus) && __cplusplus
856 }
857 #endif
858 
859 #endif /* LWIP_TCP */
860 
861 #endif /* LWIP_HDR_TCP_H */
862