1
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
54
55
56
57
58
59
60
61
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
142
147
148
155
156
157
165
166
167
173
174
175
182
183
184
185
191
192
193
194
195
203
204
205
206
207
208
209
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
232
233
234
235
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
276
277
278
279
280
281
282
283
284
285
286
287
288
289
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
322
323
324
325
326
327
328
329
330
331
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
366
367
368
369
370
371
373
374
375
376
377
378
379
380
381
382
383
384
385
386
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
420
421
422
423
424
425
426
427
428
429
430
433
434
435
436
437
438
439
440
441
442
443
444
445
450
451
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
492
493
494
495
496
497
498
499
500
/* ... */
/* ... */
#ifndef LWIP_HDR_TCP_H
#define LWIP_HDR_TCP_H
#include "lwip/opt.h"
#if LWIP_TCP
#include "lwip/tcpbase.h"
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/ip.h"
#include "lwip/icmp.h"
#include "lwip/err.h"
#include "lwip/ip6.h"
#include "lwip/ip6_addr.h"
8 includes
#ifdef __cplusplus
extern "C" {
#endif
struct tcp_pcb;
struct tcp_pcb_listen;
/* ... */
typedef err_t (*tcp_accept_fn)(void *arg, struct tcp_pcb *newpcb, err_t err);
/* ... */
typedef err_t (*tcp_recv_fn)(void *arg, struct tcp_pcb *tpcb,
struct pbuf *p, err_t err);
/* ... */
typedef err_t (*tcp_sent_fn)(void *arg, struct tcp_pcb *tpcb,
u16_t len);
/* ... */
typedef err_t (*tcp_poll_fn)(void *arg, struct tcp_pcb *tpcb);
/* ... */
typedef void (*tcp_err_fn)(void *arg, err_t err);
/* ... */
typedef err_t (*tcp_connected_fn)(void *arg, struct tcp_pcb *tpcb, err_t err);
#if LWIP_WND_SCALE
#define RCV_WND_SCALE(pcb, wnd) (((wnd) >> (pcb)->rcv_scale))
#define SND_WND_SCALE(pcb, wnd) (((wnd) << (pcb)->snd_scale))
#define TCPWND16(x) ((u16_t)LWIP_MIN((x), 0xFFFF))
#define TCP_WND_MAX(pcb) ((tcpwnd_size_t)(((pcb)->flags & TF_WND_SCALE) ? TCP_WND : TCPWND16(TCP_WND)))
/* ... */#else
#define RCV_WND_SCALE(pcb, wnd) (wnd)
#define SND_WND_SCALE(pcb, wnd) (wnd)
#define TCPWND16(x) (x)
#define TCP_WND_MAX(pcb) TCP_WND
/* ... */#endif
#define TCP_WND_INC(wnd, inc) do { \
if ((tcpwnd_size_t)(wnd + inc) >= wnd) { \
wnd = (tcpwnd_size_t)(wnd + inc); \
}if ((tcpwnd_size_t)(wnd + inc) >= wnd) { ... } else { \
wnd = (tcpwnd_size_t)-1; \
}else { ... } \
...} while(0)...
#if LWIP_TCP_SACK_OUT
/* ... */
struct tcp_sack_range {
u32_t left;
u32_t right;
...};/* ... */
#endif
/* ... */
typedef void (*tcp_extarg_callback_pcb_destroyed_fn)(u8_t id, void *data);
/* ... */
typedef err_t (*tcp_extarg_callback_passive_open_fn)(u8_t id, struct tcp_pcb_listen *lpcb, struct tcp_pcb *cpcb);
struct tcp_ext_arg_callbacks {
tcp_extarg_callback_pcb_destroyed_fn destroy;
tcp_extarg_callback_passive_open_fn passive_open;
...};
#define LWIP_TCP_PCB_NUM_EXT_ARG_ID_INVALID 0xFF
#if LWIP_TCP_PCB_NUM_EXT_ARGS
struct tcp_pcb_ext_args {
const struct tcp_ext_arg_callbacks *callbacks;
void *data;
...};
#define TCP_PCB_EXTARGS struct tcp_pcb_ext_args ext_args[LWIP_TCP_PCB_NUM_EXT_ARGS];
/* ... */#else
#define TCP_PCB_EXTARGS
#endif
typedef u16_t tcpflags_t;
#define TCP_ALLFLAGS 0xffffU
/* ... */
#define TCP_PCB_COMMON(type) \
type *next; \
void *callback_arg; \
TCP_PCB_EXTARGS \
enum tcp_state state; \
u8_t prio; \
\
u16_t local_port...
struct tcp_pcb_listen {
IP_PCB;
TCP_PCB_COMMON(struct tcp_pcb_listen);
#if LWIP_CALLBACK_API
tcp_accept_fn accept;/* ... */
#endif
#if TCP_LISTEN_BACKLOG
u8_t backlog;
u8_t accepts_pending;/* ... */
#endif
...};
struct tcp_pcb {
IP_PCB;
TCP_PCB_COMMON(struct tcp_pcb);
u16_t remote_port;
tcpflags_t flags;
#define TF_ACK_DELAY 0x01U
#define TF_ACK_NOW 0x02U
#define TF_INFR 0x04U
#define TF_CLOSEPEND 0x08U
#define TF_RXCLOSED 0x10U
#define TF_FIN 0x20U
#define TF_NODELAY 0x40U
#define TF_NAGLEMEMERR 0x80U
8 defines#if LWIP_WND_SCALE
#define TF_WND_SCALE 0x0100U
#endif
#if TCP_LISTEN_BACKLOG
#define TF_BACKLOGPEND 0x0200U
#endif
#if LWIP_TCP_TIMESTAMPS
#define TF_TIMESTAMP 0x0400U
#endif
#define TF_RTO 0x0800U
#if LWIP_TCP_SACK_OUT
#define TF_SACK 0x1000U
#endif
/* ... */
u8_t polltmr, pollinterval;
u8_t last_timer;
u32_t tmr;
u32_t rcv_nxt;
tcpwnd_size_t rcv_wnd;
tcpwnd_size_t rcv_ann_wnd;
u32_t rcv_ann_right_edge;
#if LWIP_TCP_SACK_OUT
struct tcp_sack_range rcv_sacks[LWIP_TCP_MAX_SACK_NUM];
#define LWIP_TCP_SACK_VALID(pcb, idx) ((pcb)->rcv_sacks[idx].left != (pcb)->rcv_sacks[idx].right)
/* ... */#endif
s16_t rtime;
u16_t mss;
u32_t rttest;
u32_t rtseq;
s16_t sa, sv;
s16_t rto;
u8_t nrtx;
u8_t dupacks;
u32_t lastack;
tcpwnd_size_t cwnd;
tcpwnd_size_t ssthresh;
u32_t rto_end;
u32_t snd_nxt;
u32_t snd_wl1, snd_wl2;
/* ... */
u32_t snd_lbb;
tcpwnd_size_t snd_wnd;
tcpwnd_size_t snd_wnd_max;
tcpwnd_size_t snd_buf;
#define TCP_SNDQUEUELEN_OVERFLOW (0xffffU-3)
u16_t snd_queuelen;
#if TCP_OVERSIZE
u16_t unsent_oversize;/* ... */
#endif
tcpwnd_size_t bytes_acked;
struct tcp_seg *unsent;
struct tcp_seg *unacked;
#if TCP_QUEUE_OOSEQ
struct tcp_seg *ooseq;
#endif
struct pbuf *refused_data;
#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG
struct tcp_pcb_listen* listener;
#endif
#if LWIP_CALLBACK_API
tcp_sent_fn sent;
tcp_recv_fn recv;
tcp_connected_fn connected;
tcp_poll_fn poll;
tcp_err_fn errf;/* ... */
#endif
#if LWIP_TCP_TIMESTAMPS
u32_t ts_lastacksent;
u32_t ts_recent;/* ... */
#endif
u32_t keep_idle;
#if LWIP_TCP_KEEPALIVE
u32_t keep_intvl;
u32_t keep_cnt;/* ... */
#endif
u8_t persist_cnt;
u8_t persist_backoff;
u8_t persist_probe;
u8_t keep_cnt_sent;
#if LWIP_WND_SCALE
u8_t snd_scale;
u8_t rcv_scale;/* ... */
#endif
...};
#if LWIP_EVENT_API
enum lwip_event {
LWIP_EVENT_ACCEPT,
LWIP_EVENT_SENT,
LWIP_EVENT_RECV,
LWIP_EVENT_CONNECTED,
LWIP_EVENT_POLL,
LWIP_EVENT_ERR
...};
err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb,
enum lwip_event,
struct pbuf *p,
u16_t size,
err_t err);
/* ... */
#endif
struct tcp_pcb * tcp_new (void);
struct tcp_pcb * tcp_new_ip_type (u8_t type);
void tcp_arg (struct tcp_pcb *pcb, void *arg);
#if LWIP_CALLBACK_API
void tcp_recv (struct tcp_pcb *pcb, tcp_recv_fn recv);
void tcp_sent (struct tcp_pcb *pcb, tcp_sent_fn sent);
void tcp_err (struct tcp_pcb *pcb, tcp_err_fn err);
void tcp_accept (struct tcp_pcb *pcb, tcp_accept_fn accept);/* ... */
#endif
void tcp_poll (struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval);
#define tcp_set_flags(pcb, set_flags) do { (pcb)->flags = (tcpflags_t)((pcb)->flags | (set_flags)); } while(0)
#define tcp_clear_flags(pcb, clr_flags) do { (pcb)->flags = (tcpflags_t)((pcb)->flags & (tcpflags_t)(~(clr_flags) & TCP_ALLFLAGS)); } while(0)
#define tcp_is_flag_set(pcb, flag) (((pcb)->flags & (flag)) != 0)
#if LWIP_TCP_TIMESTAMPS
#define tcp_mss(pcb) (((pcb)->flags & TF_TIMESTAMP) ? ((pcb)->mss - 12) : (pcb)->mss)
#else
#define tcp_mss(pcb) ((pcb)->mss)
/* ... */#endif
#define tcp_sndbuf(pcb) (TCPWND16((pcb)->snd_buf))
#define tcp_sndqueuelen(pcb) ((pcb)->snd_queuelen)
#define tcp_nagle_disable(pcb) tcp_set_flags(pcb, TF_NODELAY)
#define tcp_nagle_enable(pcb) tcp_clear_flags(pcb, TF_NODELAY)
#define tcp_nagle_disabled(pcb) tcp_is_flag_set(pcb, TF_NODELAY)
5 defines
#if TCP_LISTEN_BACKLOG
#define tcp_backlog_set(pcb, new_backlog) do { \
LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", (pcb)->state == LISTEN); \
((struct tcp_pcb_listen *)(pcb))->backlog = ((new_backlog) ? (new_backlog) : 1); ...} while(0)...
void tcp_backlog_delayed(struct tcp_pcb* pcb);
void tcp_backlog_accepted(struct tcp_pcb* pcb);/* ... */
#else
#define tcp_backlog_set(pcb, new_backlog)
#define tcp_backlog_delayed(pcb)
#define tcp_backlog_accepted(pcb)
/* ... */#endif
#define tcp_accepted(pcb) do { LWIP_UNUSED_ARG(pcb); } while(0)
void tcp_recved (struct tcp_pcb *pcb, u16_t len);
err_t tcp_bind (struct tcp_pcb *pcb, const ip_addr_t *ipaddr,
u16_t port);
void tcp_bind_netif(struct tcp_pcb *pcb, const struct netif *netif);
err_t tcp_connect (struct tcp_pcb *pcb, const ip_addr_t *ipaddr,
u16_t port, tcp_connected_fn connected);
struct tcp_pcb * tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err);
struct tcp_pcb * tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog);
#define tcp_listen(pcb) tcp_listen_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG)
void tcp_abort (struct tcp_pcb *pcb);
err_t tcp_close (struct tcp_pcb *pcb);
err_t tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx);
err_t tcp_write (struct tcp_pcb *pcb, const void *dataptr, u16_t len,
u8_t apiflags);
void tcp_setprio (struct tcp_pcb *pcb, u8_t prio);
err_t tcp_output (struct tcp_pcb *pcb);
err_t tcp_tcp_get_tcp_addrinfo(struct tcp_pcb *pcb, int local, ip_addr_t *addr, u16_t *port);
#define tcp_dbg_get_tcp_state(pcb) ((pcb)->state)
#define tcp_new_ip6() tcp_new_ip_type(IPADDR_TYPE_V6)
#if LWIP_TCP_PCB_NUM_EXT_ARGS
u8_t tcp_ext_arg_alloc_id(void);
void tcp_ext_arg_set_callbacks(struct tcp_pcb *pcb, uint8_t id, const struct tcp_ext_arg_callbacks * const callbacks);
void tcp_ext_arg_set(struct tcp_pcb *pcb, uint8_t id, void *arg);
void *tcp_ext_arg_get(const struct tcp_pcb *pcb, uint8_t id);/* ... */
#endif
#ifdef __cplusplus
}extern "C" { ... }
#endif
/* ... */
#endif
/* ... */
#endif