00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifndef __LWIP_TCP_H__
00033 #define __LWIP_TCP_H__
00034
00035 #include "lwip/opt.h"
00036
00037 #if LWIP_TCP
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
00053
00054
00055 #define tcp_init()
00056 void tcp_tmr (void);
00057
00058
00059
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 #define tcp_nagle_disable(pcb) ((pcb)->flags |= TF_NODELAY)
00082 #define tcp_nagle_enable(pcb) ((pcb)->flags &= ~TF_NODELAY)
00083 #define tcp_nagle_disabled(pcb) (((pcb)->flags & TF_NODELAY) != 0)
00084
00085 #if TCP_LISTEN_BACKLOG
00086 #define tcp_accepted(pcb) (((struct tcp_pcb_listen *)(pcb))->accepts_pending--)
00087 #else
00088 #define tcp_accepted(pcb)
00089 #endif
00090
00091 void tcp_recved (struct tcp_pcb *pcb, u16_t len);
00092 err_t tcp_bind (struct tcp_pcb *pcb, struct ip_addr *ipaddr,
00093 u16_t port);
00094 err_t tcp_connect (struct tcp_pcb *pcb, struct ip_addr *ipaddr,
00095 u16_t port, err_t (* connected)(void *arg,
00096 struct tcp_pcb *tpcb,
00097 err_t err));
00098
00099 struct tcp_pcb * tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog);
00100 #define tcp_listen(pcb) tcp_listen_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG)
00101
00102 void tcp_abandon (struct tcp_pcb *pcb, int reset);
00103 #define tcp_abort(pcb) tcp_abandon((pcb), 1)
00104 err_t tcp_close (struct tcp_pcb *pcb);
00105
00106
00107 #define TCP_WRITE_FLAG_COPY 0x01
00108 #define TCP_WRITE_FLAG_MORE 0x02
00109
00110 err_t tcp_write (struct tcp_pcb *pcb, const void *dataptr, u16_t len,
00111 u8_t apiflags);
00112
00113 void tcp_setprio (struct tcp_pcb *pcb, u8_t prio);
00114
00115 #define TCP_PRIO_MIN 1
00116 #define TCP_PRIO_NORMAL 64
00117 #define TCP_PRIO_MAX 127
00118
00119
00120
00121 void tcp_slowtmr (void);
00122 void tcp_fasttmr (void);
00123
00124
00125
00126 void tcp_input (struct pbuf *p, struct netif *inp);
00127
00128 err_t tcp_send_empty_ack(struct tcp_pcb *pcb);
00129 err_t tcp_output (struct tcp_pcb *pcb);
00130 void tcp_rexmit (struct tcp_pcb *pcb);
00131 void tcp_rexmit_rto (struct tcp_pcb *pcb);
00132 void tcp_rexmit_fast (struct tcp_pcb *pcb);
00133 u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb);
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144 #define tcp_do_output_nagle(tpcb) ((((tpcb)->unacked == NULL) || \
00145 ((tpcb)->flags & (TF_NODELAY | TF_INFR)) || \
00146 (((tpcb)->unsent != NULL) && (((tpcb)->unsent->next != NULL) || \
00147 ((tpcb)->unsent->len >= (tpcb)->mss))) \
00148 ) ? 1 : 0)
00149 #define tcp_output_nagle(tpcb) (tcp_do_output_nagle(tpcb) ? tcp_output(tpcb) : ERR_OK)
00150
00151
00152 #define TCP_SEQ_LT(a,b) ((s32_t)((a)-(b)) < 0)
00153 #define TCP_SEQ_LEQ(a,b) ((s32_t)((a)-(b)) <= 0)
00154 #define TCP_SEQ_GT(a,b) ((s32_t)((a)-(b)) > 0)
00155 #define TCP_SEQ_GEQ(a,b) ((s32_t)((a)-(b)) >= 0)
00156
00157 #if 0
00158 #define TCP_SEQ_BETWEEN(a,b,c) ((c)-(b) >= (a)-(b))
00159 #endif
00160 #define TCP_SEQ_BETWEEN(a,b,c) (TCP_SEQ_GEQ(a,b) && TCP_SEQ_LEQ(a,c))
00161 #define TCP_FIN 0x01U
00162 #define TCP_SYN 0x02U
00163 #define TCP_RST 0x04U
00164 #define TCP_PSH 0x08U
00165 #define TCP_ACK 0x10U
00166 #define TCP_URG 0x20U
00167 #define TCP_ECE 0x40U
00168 #define TCP_CWR 0x80U
00169
00170 #define TCP_FLAGS 0x3fU
00171
00172
00173 #define TCP_HLEN 20
00174
00175 #ifndef TCP_TMR_INTERVAL
00176 #define TCP_TMR_INTERVAL 250
00177 #endif
00178
00179 #ifndef TCP_FAST_INTERVAL
00180 #define TCP_FAST_INTERVAL TCP_TMR_INTERVAL
00181 #endif
00182
00183 #ifndef TCP_SLOW_INTERVAL
00184 #define TCP_SLOW_INTERVAL (2*TCP_TMR_INTERVAL)
00185 #endif
00186
00187 #define TCP_FIN_WAIT_TIMEOUT 20000
00188 #define TCP_SYN_RCVD_TIMEOUT 20000
00189
00190 #define TCP_OOSEQ_TIMEOUT 6U
00191
00192 #ifndef TCP_MSL
00193 #define TCP_MSL 60000UL
00194 #endif
00195
00196
00197 #ifndef TCP_KEEPIDLE_DEFAULT
00198 #define TCP_KEEPIDLE_DEFAULT 7200000UL
00199 #endif
00200
00201 #ifndef TCP_KEEPINTVL_DEFAULT
00202 #define TCP_KEEPINTVL_DEFAULT 75000UL
00203 #endif
00204
00205 #ifndef TCP_KEEPCNT_DEFAULT
00206 #define TCP_KEEPCNT_DEFAULT 9U
00207 #endif
00208
00209 #define TCP_MAXIDLE TCP_KEEPCNT_DEFAULT * TCP_KEEPINTVL_DEFAULT
00210
00211
00212
00213
00214 #ifdef PACK_STRUCT_USE_INCLUDES
00215 # include "arch/bpstruct.h"
00216 #endif
00217 PACK_STRUCT_BEGIN
00218 struct tcp_hdr {
00219 PACK_STRUCT_FIELD(u16_t src);
00220 PACK_STRUCT_FIELD(u16_t dest);
00221 PACK_STRUCT_FIELD(u32_t seqno);
00222 PACK_STRUCT_FIELD(u32_t ackno);
00223 PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags);
00224 PACK_STRUCT_FIELD(u16_t wnd);
00225 PACK_STRUCT_FIELD(u16_t chksum);
00226 PACK_STRUCT_FIELD(u16_t urgp);
00227 } PACK_STRUCT_STRUCT;
00228 PACK_STRUCT_END
00229 #ifdef PACK_STRUCT_USE_INCLUDES
00230 # include "arch/epstruct.h"
00231 #endif
00232
00233 #define TCPH_OFFSET(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 8)
00234 #define TCPH_HDRLEN(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 12)
00235 #define TCPH_FLAGS(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS)
00236
00237 #define TCPH_OFFSET_SET(phdr, offset) (phdr)->_hdrlen_rsvd_flags = htons(((offset) << 8) | TCPH_FLAGS(phdr))
00238 #define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr))
00239 #define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & htons((u16_t)(~(u16_t)(TCP_FLAGS)))) | htons(flags))
00240 #define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | htons(flags))
00241 #define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (TCPH_FLAGS(phdr) & ~(flags)) )
00242
00243 #define TCP_TCPLEN(seg) ((seg)->len + ((TCPH_FLAGS((seg)->tcphdr) & (TCP_FIN | TCP_SYN)) != 0))
00244
00245 enum tcp_state {
00246 CLOSED = 0,
00247 LISTEN = 1,
00248 SYN_SENT = 2,
00249 SYN_RCVD = 3,
00250 ESTABLISHED = 4,
00251 FIN_WAIT_1 = 5,
00252 FIN_WAIT_2 = 6,
00253 CLOSE_WAIT = 7,
00254 CLOSING = 8,
00255 LAST_ACK = 9,
00256 TIME_WAIT = 10
00257 };
00258
00259
00260
00261 #define TF_RESET (u8_t)0x08U
00262 #define TF_CLOSED (u8_t)0x10U
00263 #define TF_GOT_FIN (u8_t)0x20U
00264
00265
00266 #if LWIP_CALLBACK_API
00267
00268
00269
00270
00271
00272
00273
00274 #define DEF_ACCEPT_CALLBACK err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err)
00275 #else
00276 #define DEF_ACCEPT_CALLBACK
00277 #endif
00278
00279
00280
00281
00282 #define TCP_PCB_COMMON(type) \
00283 type *next; \
00284 enum tcp_state state; \
00285 u8_t prio; \
00286 void *callback_arg; \
00287 \
00288 u16_t local_port; \
00289 \
00290 DEF_ACCEPT_CALLBACK
00291
00292
00293
00294 struct tcp_pcb {
00295
00296 IP_PCB;
00297
00298 TCP_PCB_COMMON(struct tcp_pcb);
00299
00300
00301 u16_t remote_port;
00302
00303 u8_t flags;
00304 #define TF_ACK_DELAY ((u8_t)0x01U)
00305 #define TF_ACK_NOW ((u8_t)0x02U)
00306 #define TF_INFR ((u8_t)0x04U)
00307 #define TF_TIMESTAMP ((u8_t)0x08U)
00308 #define TF_FIN ((u8_t)0x20U)
00309 #define TF_NODELAY ((u8_t)0x40U)
00310 #define TF_NAGLEMEMERR ((u8_t)0x80U)
00311
00312
00313
00314
00315 u32_t rcv_nxt;
00316 u16_t rcv_wnd;
00317 u16_t rcv_ann_wnd;
00318 u32_t rcv_ann_right_edge;
00319
00320
00321 u32_t tmr;
00322 u8_t polltmr, pollinterval;
00323
00324
00325 s16_t rtime;
00326
00327 u16_t mss;
00328
00329
00330 u32_t rttest;
00331 u32_t rtseq;
00332 s16_t sa, sv;
00333
00334 s16_t rto;
00335 u8_t nrtx;
00336
00337
00338 u32_t lastack;
00339 u8_t dupacks;
00340
00341
00342 u16_t cwnd;
00343 u16_t ssthresh;
00344
00345
00346 u32_t snd_nxt;
00347 u16_t snd_wnd;
00348 u32_t snd_wl1, snd_wl2;
00349
00350 u32_t snd_lbb;
00351
00352 u16_t acked;
00353
00354 u16_t snd_buf;
00355 #define TCP_SNDQUEUELEN_OVERFLOW (0xffff-3)
00356 u16_t snd_queuelen;
00357
00358
00359
00360 struct tcp_seg *unsent;
00361 struct tcp_seg *unacked;
00362 #if TCP_QUEUE_OOSEQ
00363 struct tcp_seg *ooseq;
00364 #endif
00365
00366 struct pbuf *refused_data;
00367
00368 #if LWIP_CALLBACK_API
00369
00370
00371
00372
00373
00374
00375 err_t (* sent)(void *arg, struct tcp_pcb *pcb, u16_t space);
00376
00377
00378
00379
00380
00381
00382
00383
00384 err_t (* recv)(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);
00385
00386
00387
00388
00389
00390
00391
00392 err_t (* connected)(void *arg, struct tcp_pcb *pcb, err_t err);
00393
00394
00395
00396
00397
00398
00399
00400
00401 err_t (* poll)(void *arg, struct tcp_pcb *pcb);
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411 void (* errf)(void *arg, err_t err);
00412 #endif
00413
00414 #if LWIP_TCP_TIMESTAMPS
00415 u32_t ts_lastacksent;
00416 u32_t ts_recent;
00417 #endif
00418
00419
00420 u32_t keep_idle;
00421 #if LWIP_TCP_KEEPALIVE
00422 u32_t keep_intvl;
00423 u32_t keep_cnt;
00424 #endif
00425
00426
00427 u32_t persist_cnt;
00428
00429 u8_t persist_backoff;
00430
00431
00432 u8_t keep_cnt_sent;
00433 };
00434
00435 struct tcp_pcb_listen {
00436
00437 IP_PCB;
00438
00439 TCP_PCB_COMMON(struct tcp_pcb_listen);
00440
00441 #if TCP_LISTEN_BACKLOG
00442 u8_t backlog;
00443 u8_t accepts_pending;
00444 #endif
00445 };
00446
00447 #if LWIP_EVENT_API
00448
00449 enum lwip_event {
00450 LWIP_EVENT_ACCEPT,
00451 LWIP_EVENT_SENT,
00452 LWIP_EVENT_RECV,
00453 LWIP_EVENT_CONNECTED,
00454 LWIP_EVENT_POLL,
00455 LWIP_EVENT_ERR
00456 };
00457
00458 err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb,
00459 enum lwip_event,
00460 struct pbuf *p,
00461 u16_t size,
00462 err_t err);
00463
00464 #define TCP_EVENT_ACCEPT(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
00465 LWIP_EVENT_ACCEPT, NULL, 0, err)
00466 #define TCP_EVENT_SENT(pcb,space,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
00467 LWIP_EVENT_SENT, NULL, space, ERR_OK)
00468 #define TCP_EVENT_RECV(pcb,p,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
00469 LWIP_EVENT_RECV, (p), 0, (err))
00470 #define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
00471 LWIP_EVENT_CONNECTED, NULL, 0, (err))
00472 #define TCP_EVENT_POLL(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
00473 LWIP_EVENT_POLL, NULL, 0, ERR_OK)
00474 #define TCP_EVENT_ERR(errf,arg,err) lwip_tcp_event((arg), NULL, \
00475 LWIP_EVENT_ERR, NULL, 0, (err))
00476 #else
00477
00478 #define TCP_EVENT_ACCEPT(pcb,err,ret) \
00479 do { \
00480 if((pcb)->accept != NULL) \
00481 (ret) = (pcb)->accept((pcb)->callback_arg,(pcb),(err)); \
00482 else (ret) = ERR_OK; \
00483 } while (0)
00484
00485 #define TCP_EVENT_SENT(pcb,space,ret) \
00486 do { \
00487 if((pcb)->sent != NULL) \
00488 (ret) = (pcb)->sent((pcb)->callback_arg,(pcb),(space)); \
00489 else (ret) = ERR_OK; \
00490 } while (0)
00491
00492 #define TCP_EVENT_RECV(pcb,p,err,ret) \
00493 do { \
00494 if((pcb)->recv != NULL) { \
00495 (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err)); \
00496 } else { \
00497 (ret) = tcp_recv_null(NULL, (pcb), (p), (err)); \
00498 } \
00499 } while (0)
00500
00501 #define TCP_EVENT_CONNECTED(pcb,err,ret) \
00502 do { \
00503 if((pcb)->connected != NULL) \
00504 (ret) = (pcb)->connected((pcb)->callback_arg,(pcb),(err)); \
00505 else (ret) = ERR_OK; \
00506 } while (0)
00507
00508 #define TCP_EVENT_POLL(pcb,ret) \
00509 do { \
00510 if((pcb)->poll != NULL) \
00511 (ret) = (pcb)->poll((pcb)->callback_arg,(pcb)); \
00512 else (ret) = ERR_OK; \
00513 } while (0)
00514
00515 #define TCP_EVENT_ERR(errf,arg,err) \
00516 do { \
00517 if((errf) != NULL) \
00518 (errf)((arg),(err)); \
00519 } while (0)
00520
00521 #endif
00522
00523
00524 struct tcp_seg {
00525 struct tcp_seg *next;
00526 struct pbuf *p;
00527 void *dataptr;
00528 u16_t len;
00529 u8_t flags;
00530 #define TF_SEG_OPTS_MSS (u8_t)0x01U
00531 #define TF_SEG_OPTS_TS (u8_t)0x02U
00532 struct tcp_hdr *tcphdr;
00533 };
00534
00535 #define LWIP_TCP_OPT_LENGTH(flags) \
00536 (flags & TF_SEG_OPTS_MSS ? 4 : 0) + \
00537 (flags & TF_SEG_OPTS_TS ? 12 : 0)
00538
00539
00540 #define TCP_BUILD_MSS_OPTION(x) (x) = htonl(((u32_t)2 << 24) | \
00541 ((u32_t)4 << 16) | \
00542 (((u32_t)TCP_MSS / 256) << 8) | \
00543 (TCP_MSS & 255))
00544
00545
00546 struct tcp_pcb *tcp_pcb_copy(struct tcp_pcb *pcb);
00547 void tcp_pcb_purge(struct tcp_pcb *pcb);
00548 void tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb);
00549
00550 u8_t tcp_segs_free(struct tcp_seg *seg);
00551 u8_t tcp_seg_free(struct tcp_seg *seg);
00552 struct tcp_seg *tcp_seg_copy(struct tcp_seg *seg);
00553
00554 #define tcp_ack(pcb) \
00555 do { \
00556 if((pcb)->flags & TF_ACK_DELAY) { \
00557 (pcb)->flags &= ~TF_ACK_DELAY; \
00558 (pcb)->flags |= TF_ACK_NOW; \
00559 tcp_output(pcb); \
00560 } \
00561 else { \
00562 (pcb)->flags |= TF_ACK_DELAY; \
00563 } \
00564 } while (0)
00565
00566 #define tcp_ack_now(pcb) \
00567 do { \
00568 (pcb)->flags |= TF_ACK_NOW; \
00569 tcp_output(pcb); \
00570 } while (0)
00571
00572 err_t tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags);
00573 err_t tcp_enqueue(struct tcp_pcb *pcb, void *dataptr, u16_t len,
00574 u8_t flags, u8_t apiflags, u8_t optflags);
00575
00576 void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg);
00577
00578 void tcp_rst(u32_t seqno, u32_t ackno,
00579 struct ip_addr *local_ip, struct ip_addr *remote_ip,
00580 u16_t local_port, u16_t remote_port);
00581
00582 u32_t tcp_next_iss(void);
00583
00584 void tcp_keepalive(struct tcp_pcb *pcb);
00585 void tcp_zero_window_probe(struct tcp_pcb *pcb);
00586
00587 #if TCP_CALCULATE_EFF_SEND_MSS
00588 u16_t tcp_eff_send_mss(u16_t sendmss, struct ip_addr *addr);
00589 #endif
00590
00591 #if LWIP_CALLBACK_API
00592 err_t tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);
00593 #endif
00594
00595 extern struct tcp_pcb *tcp_input_pcb;
00596 extern u32_t tcp_ticks;
00597
00598 const char* tcp_debug_state_str(enum tcp_state s);
00599 #if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
00600 void tcp_debug_print(struct tcp_hdr *tcphdr);
00601 void tcp_debug_print_flags(u8_t flags);
00602 void tcp_debug_print_state(enum tcp_state s);
00603 void tcp_debug_print_pcbs(void);
00604 s16_t tcp_pcbs_sane(void);
00605 #else
00606 # define tcp_debug_print(tcphdr)
00607 # define tcp_debug_print_flags(flags)
00608 # define tcp_debug_print_state(s)
00609 # define tcp_debug_print_pcbs()
00610 # define tcp_pcbs_sane() 1
00611 #endif
00612
00613 #if NO_SYS
00614 #define tcp_timer_needed()
00615 #else
00616 void tcp_timer_needed(void);
00617 #endif
00618
00619
00620 union tcp_listen_pcbs_t {
00621 struct tcp_pcb_listen *listen_pcbs;
00622 struct tcp_pcb *pcbs;
00623 };
00624 extern union tcp_listen_pcbs_t tcp_listen_pcbs;
00625 extern struct tcp_pcb *tcp_active_pcbs;
00626
00627
00628 extern struct tcp_pcb *tcp_tw_pcbs;
00629
00630 extern struct tcp_pcb *tcp_tmp_pcb;
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641 #if 0
00642 #define TCP_REG(pcbs, npcb) do {\
00643 LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %d\n", npcb, npcb->local_port)); \
00644 for(tcp_tmp_pcb = *pcbs; \
00645 tcp_tmp_pcb != NULL; \
00646 tcp_tmp_pcb = tcp_tmp_pcb->next) { \
00647 LWIP_ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != npcb); \
00648 } \
00649 LWIP_ASSERT("TCP_REG: pcb->state != CLOSED", npcb->state != CLOSED); \
00650 npcb->next = *pcbs; \
00651 LWIP_ASSERT("TCP_REG: npcb->next != npcb", npcb->next != npcb); \
00652 *(pcbs) = npcb; \
00653 LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \
00654 tcp_timer_needed(); \
00655 } while(0)
00656 #define TCP_RMV(pcbs, npcb) do { \
00657 LWIP_ASSERT("TCP_RMV: pcbs != NULL", *pcbs != NULL); \
00658 LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removing %p from %p\n", npcb, *pcbs)); \
00659 if(*pcbs == npcb) { \
00660 *pcbs = (*pcbs)->next; \
00661 } else for(tcp_tmp_pcb = *pcbs; tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \
00662 if(tcp_tmp_pcb->next == npcb) { \
00663 tcp_tmp_pcb->next = npcb->next; \
00664 break; \
00665 } \
00666 } \
00667 npcb->next = NULL; \
00668 LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \
00669 LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", npcb, *pcbs)); \
00670 } while(0)
00671
00672 #else
00673
00674 #define TCP_REG(pcbs, npcb) \
00675 do { \
00676 npcb->next = *pcbs; \
00677 *(pcbs) = npcb; \
00678 tcp_timer_needed(); \
00679 } while (0)
00680
00681 #define TCP_RMV(pcbs, npcb) \
00682 do { \
00683 if(*(pcbs) == npcb) { \
00684 (*(pcbs)) = (*pcbs)->next; \
00685 } \
00686 else { \
00687 for(tcp_tmp_pcb = *pcbs; \
00688 tcp_tmp_pcb != NULL; \
00689 tcp_tmp_pcb = tcp_tmp_pcb->next) { \
00690 if(tcp_tmp_pcb->next == npcb) { \
00691 tcp_tmp_pcb->next = npcb->next; \
00692 break; \
00693 } \
00694 } \
00695 } \
00696 npcb->next = NULL; \
00697 } while(0)
00698
00699 #endif
00700
00701 #ifdef __cplusplus
00702 }
00703 #endif
00704
00705 #endif
00706
00707 #endif