1
5
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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
65
67
68
69
70
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
159
160
161
162
163
164
165
166
167
168
170
172
174
176
180
182
184
185
186
187
188
193
194
200
201
209
210
218
219
225
226
232
233
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
262
263
265
266
267
274
275
276
277
278
279
280
281
282
283
284
285
288
289
290
291
294
295
296
297
298
301
302
303
304
309
310
311
312
313
314
319
324
325
326
327
328
329
330
331
335
336
337
340
341
342
343
344
345
346
352
354
355
356
357
358
359
360
361
366
367
368
369
370
371
372
373
374
375
376
377
385
386
387
388
389
390
391
418
419
420
425
426
431
432
437
438
439
440
441
442
443
444
445
446
447
448
458
459
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
484
485
486
487
488
489
490
495
496
501
502
503
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
/* ... */
/* ... */
#ifndef LWIP_HDR_TCP_PRIV_H
#define LWIP_HDR_TCP_PRIV_H
#include "lwip/opt.h"
#if LWIP_TCP
#include "lwip/tcp.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"
#include "lwip/prot/tcp.h"
9 includes
#ifdef __cplusplus
extern "C" {
#endif
void tcp_init (void);
void tcp_tmr (void);
/* ... */
/* ... */
void tcp_slowtmr (void);
void tcp_fasttmr (void);
/* ... */
void tcp_txnow (void);
void tcp_input (struct pbuf *p, struct netif *inp);
struct tcp_pcb * tcp_alloc (u8_t prio);
void tcp_free (struct tcp_pcb *pcb);
void tcp_abandon (struct tcp_pcb *pcb, int reset);
err_t tcp_send_empty_ack(struct tcp_pcb *pcb);
err_t tcp_rexmit (struct tcp_pcb *pcb);
err_t tcp_rexmit_rto_prepare(struct tcp_pcb *pcb);
void tcp_rexmit_rto_commit(struct tcp_pcb *pcb);
void tcp_rexmit_rto (struct tcp_pcb *pcb);
void tcp_rexmit_fast (struct tcp_pcb *pcb);
u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb);
err_t tcp_process_refused_data(struct tcp_pcb *pcb);
/* ... */
#define tcp_do_output_nagle(tpcb) ((((tpcb)->unacked == NULL) || \
((tpcb)->flags & (TF_NODELAY | TF_INFR)) || \
(((tpcb)->unsent != NULL) && (((tpcb)->unsent->next != NULL) || \
((tpcb)->unsent->len >= (tpcb)->mss))) || \
((tcp_sndbuf(tpcb) == 0) || (tcp_sndqueuelen(tpcb) >= TCP_SND_QUEUELEN)) \
) ? 1 : 0)...
#define tcp_output_nagle(tpcb) (tcp_do_output_nagle(tpcb) ? tcp_output(tpcb) : ERR_OK)
#define TCP_SEQ_LT(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) < 0)
#define TCP_SEQ_LEQ(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) <= 0)
#define TCP_SEQ_GT(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) > 0)
#define TCP_SEQ_GEQ(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) >= 0)
6 defines
#if 0
#define TCP_SEQ_BETWEEN(a,b,c) ((c)-(b) >= (a)-(b))
#endif
#define TCP_SEQ_BETWEEN(a,b,c) (TCP_SEQ_GEQ(a,b) && TCP_SEQ_LEQ(a,c))
#ifndef TCP_TMR_INTERVAL
#define TCP_TMR_INTERVAL 250
#endif
#ifndef TCP_FAST_INTERVAL
#define TCP_FAST_INTERVAL TCP_TMR_INTERVAL
#endif
#ifndef TCP_SLOW_INTERVAL
#define TCP_SLOW_INTERVAL (2*TCP_TMR_INTERVAL)
#endif
#define TCP_FIN_WAIT_TIMEOUT 20000
#define TCP_SYN_RCVD_TIMEOUT 20000
#define TCP_OOSEQ_TIMEOUT 6U
#ifndef TCP_MSL
#define TCP_MSL 60000UL
#endif
#ifndef TCP_KEEPIDLE_DEFAULT
#define TCP_KEEPIDLE_DEFAULT 7200000UL
#endif
#ifndef TCP_KEEPINTVL_DEFAULT
#define TCP_KEEPINTVL_DEFAULT 75000UL
#endif
#ifndef TCP_KEEPCNT_DEFAULT
#define TCP_KEEPCNT_DEFAULT 9U
#endif
#define TCP_MAXIDLE TCP_KEEPCNT_DEFAULT * TCP_KEEPINTVL_DEFAULT
#define TCP_TCPLEN(seg) ((seg)->len + (((TCPH_FLAGS((seg)->tcphdr) & (TCP_FIN | TCP_SYN)) != 0) ? 1U : 0U))
/* ... */
#define TF_RESET (u8_t)0x08U
#define TF_CLOSED (u8_t)0x10U
#define TF_GOT_FIN (u8_t)0x20U
5 defines
#if LWIP_EVENT_API
#define TCP_EVENT_ACCEPT(lpcb,pcb,arg,err,ret) ret = lwip_tcp_event(arg, (pcb),\
LWIP_EVENT_ACCEPT, NULL, 0, err)...
#define TCP_EVENT_SENT(pcb,space,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
LWIP_EVENT_SENT, NULL, space, ERR_OK)...
#define TCP_EVENT_RECV(pcb,p,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
LWIP_EVENT_RECV, (p), 0, (err))...
#define TCP_EVENT_CLOSED(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
LWIP_EVENT_RECV, NULL, 0, ERR_OK)...
#define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
LWIP_EVENT_CONNECTED, NULL, 0, (err))...
#define TCP_EVENT_POLL(pcb,ret) do { if ((pcb)->state != SYN_RCVD) { \
ret = lwip_tcp_event((pcb)->callback_arg, (pcb), LWIP_EVENT_POLL, NULL, 0, ERR_OK); \
}if ((pcb)->state != SYN_RCVD) { ... } else { \
ret = ERR_ARG; }else { ... } ...} while(0)...
/* ... */
#define TCP_EVENT_ERR(last_state,errf,arg,err) do { if (last_state != SYN_RCVD) { \
lwip_tcp_event((arg), NULL, LWIP_EVENT_ERR, NULL, 0, (err)); }if (last_state != SYN_RCVD) { ... } ...} while(0)...
7 defines
/* ... */#else
#define TCP_EVENT_ACCEPT(lpcb,pcb,arg,err,ret) \
do { \
if((lpcb)->accept != NULL) \
(ret) = (lpcb)->accept((arg),(pcb),(err)); \
else (ret) = ERR_ARG; \
...} while (0)...
#define TCP_EVENT_SENT(pcb,space,ret) \
do { \
if((pcb)->sent != NULL) \
(ret) = (pcb)->sent((pcb)->callback_arg,(pcb),(space)); \
else (ret) = ERR_OK; \
...} while (0)...
#define TCP_EVENT_RECV(pcb,p,err,ret) \
do { \
if((pcb)->recv != NULL) { \
(ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err));\
}if ((pcb)->recv != NULL) { ... } else { \
(ret) = tcp_recv_null(NULL, (pcb), (p), (err)); \
}else { ... } \
...} while (0)...
#define TCP_EVENT_CLOSED(pcb,ret) \
do { \
if(((pcb)->recv != NULL)) { \
(ret) = (pcb)->recv((pcb)->callback_arg,(pcb),NULL,ERR_OK);\
}if (((pcb)->recv != NULL)) { ... } else { \
(ret) = ERR_OK; \
}else { ... } \
...} while (0)...
#define TCP_EVENT_CONNECTED(pcb,err,ret) \
do { \
if((pcb)->connected != NULL) \
(ret) = (pcb)->connected((pcb)->callback_arg,(pcb),(err)); \
else (ret) = ERR_OK; \
...} while (0)...
#define TCP_EVENT_POLL(pcb,ret) \
do { \
if((pcb)->poll != NULL) \
(ret) = (pcb)->poll((pcb)->callback_arg,(pcb)); \
else (ret) = ERR_OK; \
...} while (0)...
#define TCP_EVENT_ERR(last_state,errf,arg,err) \
do { \
LWIP_UNUSED_ARG(last_state); \
if((errf) != NULL) \
(errf)((arg),(err)); \
...} while (0)...
7 defines
/* ... */#endif
#if TCP_OVERSIZE && defined(LWIP_DEBUG)
#define TCP_OVERSIZE_DBGCHECK 1
#else
#define TCP_OVERSIZE_DBGCHECK 0
#endif
#define TCP_CHECKSUM_ON_COPY (LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_TCP)
struct tcp_seg {
struct tcp_seg *next;
struct pbuf *p;
u16_t len;
#if TCP_OVERSIZE_DBGCHECK
u16_t oversize_left;
/* ... */
/* ... */#endif
#if TCP_CHECKSUM_ON_COPY
u16_t chksum;
u8_t chksum_swapped;/* ... */
#endif
u8_t flags;
#define TF_SEG_OPTS_MSS (u8_t)0x01U
#define TF_SEG_OPTS_TS (u8_t)0x02U
#define TF_SEG_DATA_CHECKSUMMED (u8_t)0x04U
/* ... */
#define TF_SEG_OPTS_WND_SCALE (u8_t)0x08U
#define TF_SEG_OPTS_SACK_PERM (u8_t)0x10U
5 defines struct tcp_hdr *tcphdr;
...};
#define LWIP_TCP_OPT_EOL 0
#define LWIP_TCP_OPT_NOP 1
#define LWIP_TCP_OPT_MSS 2
#define LWIP_TCP_OPT_WS 3
#define LWIP_TCP_OPT_SACK_PERM 4
#define LWIP_TCP_OPT_TS 8
#define LWIP_TCP_OPT_LEN_MSS 4
7 defines#if LWIP_TCP_TIMESTAMPS
#define LWIP_TCP_OPT_LEN_TS 10
#define LWIP_TCP_OPT_LEN_TS_OUT 12
/* ... */#else
#define LWIP_TCP_OPT_LEN_TS_OUT 0
#endif
#if LWIP_WND_SCALE
#define LWIP_TCP_OPT_LEN_WS 3
#define LWIP_TCP_OPT_LEN_WS_OUT 4
/* ... */#else
#define LWIP_TCP_OPT_LEN_WS_OUT 0
#endif
#if LWIP_TCP_SACK_OUT
#define LWIP_TCP_OPT_LEN_SACK_PERM 2
#define LWIP_TCP_OPT_LEN_SACK_PERM_OUT 4
/* ... */#else
#define LWIP_TCP_OPT_LEN_SACK_PERM_OUT 0
#endif
#define LWIP_TCP_OPT_LENGTH(flags) \
((flags) & TF_SEG_OPTS_MSS ? LWIP_TCP_OPT_LEN_MSS : 0) + \
((flags) & TF_SEG_OPTS_TS ? LWIP_TCP_OPT_LEN_TS_OUT : 0) + \
((flags) & TF_SEG_OPTS_WND_SCALE ? LWIP_TCP_OPT_LEN_WS_OUT : 0) + \
((flags) & TF_SEG_OPTS_SACK_PERM ? LWIP_TCP_OPT_LEN_SACK_PERM_OUT : 0)...
#define TCP_BUILD_MSS_OPTION(mss) lwip_htonl(0x02040000 | ((mss) & 0xFFFF))
#if LWIP_WND_SCALE
#define TCPWNDSIZE_F U32_F
#define TCPWND_MAX 0xFFFFFFFFU
#define TCPWND_CHECK16(x) LWIP_ASSERT("window size > 0xFFFF", (x) <= 0xFFFF)
#define TCPWND_MIN16(x) ((u16_t)LWIP_MIN((x), 0xFFFF))
/* ... */#else
#define TCPWNDSIZE_F U16_F
#define TCPWND_MAX 0xFFFFU
#define TCPWND_CHECK16(x)
#define TCPWND_MIN16(x) x
/* ... */#endif
extern struct tcp_pcb *tcp_input_pcb;
extern u32_t tcp_ticks;
extern u8_t tcp_active_pcbs_changed;
union tcp_listen_pcbs_t {
struct tcp_pcb_listen *listen_pcbs;
struct tcp_pcb *pcbs;
...};
extern struct tcp_pcb *tcp_bound_pcbs;
extern union tcp_listen_pcbs_t tcp_listen_pcbs;
extern struct tcp_pcb *tcp_active_pcbs;
/* ... */
extern struct tcp_pcb *tcp_tw_pcbs;
#define NUM_TCP_PCB_LISTS_NO_TIME_WAIT 3
#define NUM_TCP_PCB_LISTS 4
extern struct tcp_pcb ** const tcp_pcb_lists[NUM_TCP_PCB_LISTS];
/* ... */
/* ... */
#ifndef TCP_DEBUG_PCB_LISTS
#define TCP_DEBUG_PCB_LISTS 0
#endif
#if TCP_DEBUG_PCB_LISTS
#define TCP_REG(pcbs, npcb) do {\
struct tcp_pcb *tcp_tmp_pcb; \
LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %"U16_F"\n", (void *)(npcb), (npcb)->local_port)); \
for (tcp_tmp_pcb = *(pcbs); \
tcp_tmp_pcb != NULL; \
tcp_tmp_pcb = tcp_tmp_pcb->next) { \
LWIP_ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != (npcb)); \
}for (tcp_tmp_pcb = *(pcbs); \ tcp_tmp_pcb != NULL; \ tcp_tmp_pcb = tcp_tmp_pcb->next) { ... } \
LWIP_ASSERT("TCP_REG: pcb->state != CLOSED", ((pcbs) == &tcp_bound_pcbs) || ((npcb)->state != CLOSED)); \
(npcb)->next = *(pcbs); \
LWIP_ASSERT("TCP_REG: npcb->next != npcb", (npcb)->next != (npcb)); \
*(pcbs) = (npcb); \
LWIP_ASSERT("TCP_REG: tcp_pcbs sane", tcp_pcbs_sane()); \
tcp_timer_needed(); \
...} while(0)...
#define TCP_RMV(pcbs, npcb) do { \
struct tcp_pcb *tcp_tmp_pcb; \
LWIP_ASSERT("TCP_RMV: pcbs != NULL", *(pcbs) != NULL); \
LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removing %p from %p\n", (void *)(npcb), (void *)(*(pcbs)))); \
if(*(pcbs) == (npcb)) { \
*(pcbs) = (*pcbs)->next; \
}if (*(pcbs) == (npcb)) { ... } else for (tcp_tmp_pcb = *(pcbs); tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \
if(tcp_tmp_pcb->next == (npcb)) { \
tcp_tmp_pcb->next = (npcb)->next; \
break; \
}if (tcp_tmp_pcb->next == (npcb)) { ... } \
}else for (tcp_tmp_pcb = *(pcbs); tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { ... } \
(npcb)->next = NULL; \
LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \
LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", (void *)(npcb), (void *)(*(pcbs)))); \
...} while(0)...
/* ... */
#else
#define TCP_REG(pcbs, npcb) \
do { \
(npcb)->next = *pcbs; \
*(pcbs) = (npcb); \
tcp_timer_needed(); \
...} while (0)...
#define TCP_RMV(pcbs, npcb) \
do { \
if(*(pcbs) == (npcb)) { \
(*(pcbs)) = (*pcbs)->next; \
}if (*(pcbs) == (npcb)) { ... } \
else { \
struct tcp_pcb *tcp_tmp_pcb; \
for (tcp_tmp_pcb = *pcbs; \
tcp_tmp_pcb != NULL; \
tcp_tmp_pcb = tcp_tmp_pcb->next) { \
if(tcp_tmp_pcb->next == (npcb)) { \
tcp_tmp_pcb->next = (npcb)->next; \
break; \
}if (tcp_tmp_pcb->next == (npcb)) { ... } \
}for (tcp_tmp_pcb = *pcbs; \ tcp_tmp_pcb != NULL; \ tcp_tmp_pcb = tcp_tmp_pcb->next) { ... } \
}else { ... } \
(npcb)->next = NULL; \
...} while(0)...
/* ... */
#endif
#define TCP_REG_ACTIVE(npcb) \
do { \
TCP_REG(&tcp_active_pcbs, npcb); \
tcp_active_pcbs_changed = 1; \
...} while (0)...
#define TCP_RMV_ACTIVE(npcb) \
do { \
TCP_RMV(&tcp_active_pcbs, npcb); \
tcp_active_pcbs_changed = 1; \
...} while (0)...
#define TCP_PCB_REMOVE_ACTIVE(pcb) \
do { \
tcp_pcb_remove(&tcp_active_pcbs, pcb); \
tcp_active_pcbs_changed = 1; \
...} while (0)...
struct tcp_pcb *tcp_pcb_copy(struct tcp_pcb *pcb);
void tcp_pcb_purge(struct tcp_pcb *pcb);
void tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb);
void tcp_segs_free(struct tcp_seg *seg);
void tcp_seg_free(struct tcp_seg *seg);
struct tcp_seg *tcp_seg_copy(struct tcp_seg *seg);
#define tcp_ack(pcb) \
do { \
if((pcb)->flags & TF_ACK_DELAY) { \
tcp_clear_flags(pcb, TF_ACK_DELAY); \
tcp_ack_now(pcb); \
}if ((pcb)->flags & TF_ACK_DELAY) { ... } \
else { \
tcp_set_flags(pcb, TF_ACK_DELAY); \
}else { ... } \
...} while (0)...
#define tcp_ack_now(pcb) \
tcp_set_flags(pcb, TF_ACK_NOW)...
err_t tcp_send_fin(struct tcp_pcb *pcb);
err_t tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags);
void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg);
void tcp_rst(const struct tcp_pcb* pcb, u32_t seqno, u32_t ackno,
const ip_addr_t *local_ip, const ip_addr_t *remote_ip,
u16_t local_port, u16_t remote_port);
u32_t tcp_next_iss(struct tcp_pcb *pcb);
err_t tcp_keepalive(struct tcp_pcb *pcb);
err_t tcp_split_unsent_seg(struct tcp_pcb *pcb, u16_t split);
err_t tcp_zero_window_probe(struct tcp_pcb *pcb);
void tcp_trigger_input_pcb_close(void);
#if TCP_CALCULATE_EFF_SEND_MSS
u16_t tcp_eff_send_mss_netif(u16_t sendmss, struct netif *outif,
const ip_addr_t *dest);
#define tcp_eff_send_mss(sendmss, src, dest) \
tcp_eff_send_mss_netif(sendmss, ip_route(src, dest), dest)...
/* ... */#endif
#if LWIP_CALLBACK_API
err_t tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);
#endif
#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
void tcp_debug_print(struct tcp_hdr *tcphdr);
void tcp_debug_print_flags(u8_t flags);
void tcp_debug_print_state(enum tcp_state s);
void tcp_debug_print_pcbs(void);
s16_t tcp_pcbs_sane(void);/* ... */
#else
# define tcp_debug_print(tcphdr)
# define tcp_debug_print_flags(flags)
# define tcp_debug_print_state(s)
# define tcp_debug_print_pcbs()
# define tcp_pcbs_sane() 1/* ... */
#endif
/* ... */
void tcp_timer_needed(void);
void tcp_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr);
#if TCP_QUEUE_OOSEQ
void tcp_free_ooseq(struct tcp_pcb *pcb);
#endif
#if LWIP_TCP_PCB_NUM_EXT_ARGS
err_t tcp_ext_arg_invoke_callbacks_passive_open(struct tcp_pcb_listen *lpcb, struct tcp_pcb *cpcb);
#endif
#ifdef __cplusplus
}extern "C" { ... }
#endif
/* ... */
#endif
/* ... */
#endif