Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Release 1.0
[palacios.git] / geekos / include / lwip / lwip / tcp.h
1 /*
2  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
3  * All rights reserved. 
4  * 
5  * Redistribution and use in source and binary forms, with or without modification, 
6  * are permitted provided that the following conditions are met:
7  *
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. 
15  *
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 
25  * OF SUCH DAMAGE.
26  *
27  * This file is part of the lwIP TCP/IP stack.
28  * 
29  * Author: Adam Dunkels <adam@sics.se>
30  *
31  */
32 #ifndef __LWIP_TCP_H__
33 #define __LWIP_TCP_H__
34
35 #include "lwip/opt.h"
36
37 #if LWIP_TCP /* don't build if not configured for use in lwipopts.h */
38
39 #include "lwip/sys.h"
40 #include "lwip/mem.h"
41 #include "lwip/pbuf.h"
42 #include "lwip/ip.h"
43 #include "lwip/icmp.h"
44 #include "lwip/err.h"
45
46 #ifdef __cplusplus
47 extern "C" {
48 #endif
49
50 struct tcp_pcb;
51
52 /* Functions for interfacing with TCP: */
53
54 /* Lower layer interface to TCP: */
55 #define tcp_init() /* Compatibility define, not init needed. */
56 void             tcp_tmr     (void);  /* Must be called every
57                                          TCP_TMR_INTERVAL
58                                          ms. (Typically 250 ms). */
59 /* Application program's interface: */
60 struct tcp_pcb * tcp_new     (void);
61 struct tcp_pcb * tcp_alloc   (u8_t prio);
62
63 void             tcp_arg     (struct tcp_pcb *pcb, void *arg);
64 void             tcp_accept  (struct tcp_pcb *pcb,
65                               err_t (* accept)(void *arg, struct tcp_pcb *newpcb,
66                  err_t err));
67 void             tcp_recv    (struct tcp_pcb *pcb,
68                               err_t (* recv)(void *arg, struct tcp_pcb *tpcb,
69                               struct pbuf *p, err_t err));
70 void             tcp_sent    (struct tcp_pcb *pcb,
71                               err_t (* sent)(void *arg, struct tcp_pcb *tpcb,
72                               u16_t len));
73 void             tcp_poll    (struct tcp_pcb *pcb,
74                               err_t (* poll)(void *arg, struct tcp_pcb *tpcb),
75                               u8_t interval);
76 void             tcp_err     (struct tcp_pcb *pcb,
77                               void (* err)(void *arg, err_t err));
78
79 #define          tcp_mss(pcb)      ((pcb)->mss)
80 #define          tcp_sndbuf(pcb)   ((pcb)->snd_buf)
81
82 #if TCP_LISTEN_BACKLOG
83 #define          tcp_accepted(pcb) (((struct tcp_pcb_listen *)(pcb))->accepts_pending--)
84 #else  /* TCP_LISTEN_BACKLOG */
85 #define          tcp_accepted(pcb)
86 #endif /* TCP_LISTEN_BACKLOG */
87
88 void             tcp_recved  (struct tcp_pcb *pcb, u16_t len);
89 err_t            tcp_bind    (struct tcp_pcb *pcb, struct ip_addr *ipaddr,
90                               u16_t port);
91 err_t            tcp_connect (struct tcp_pcb *pcb, struct ip_addr *ipaddr,
92                               u16_t port, err_t (* connected)(void *arg,
93                               struct tcp_pcb *tpcb,
94                               err_t err));
95
96 struct tcp_pcb * tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog);
97 #define          tcp_listen(pcb) tcp_listen_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG)
98
99 void             tcp_abort   (struct tcp_pcb *pcb);
100 err_t            tcp_close   (struct tcp_pcb *pcb);
101
102 /* Flags for "apiflags" parameter in tcp_write and tcp_enqueue */
103 #define TCP_WRITE_FLAG_COPY 0x01
104 #define TCP_WRITE_FLAG_MORE 0x02
105
106 err_t            tcp_write   (struct tcp_pcb *pcb, const void *dataptr, u16_t len,
107                               u8_t apiflags);
108
109 void             tcp_setprio (struct tcp_pcb *pcb, u8_t prio);
110
111 #define TCP_PRIO_MIN    1
112 #define TCP_PRIO_NORMAL 64
113 #define TCP_PRIO_MAX    127
114
115 /* It is also possible to call these two functions at the right
116    intervals (instead of calling tcp_tmr()). */
117 void             tcp_slowtmr (void);
118 void             tcp_fasttmr (void);
119
120
121 /* Only used by IP to pass a TCP segment to TCP: */
122 void             tcp_input   (struct pbuf *p, struct netif *inp);
123 /* Used within the TCP code only: */
124 err_t            tcp_output  (struct tcp_pcb *pcb);
125 void             tcp_rexmit  (struct tcp_pcb *pcb);
126 void             tcp_rexmit_rto  (struct tcp_pcb *pcb);
127
128 /**
129  * This is the Nagle algorithm: inhibit the sending of new TCP
130  * segments when new outgoing data arrives from the user if any
131  * previously transmitted data on the connection remains
132  * unacknowledged.
133  */
134 #define tcp_do_output_nagle(tpcb) ((((tpcb)->unacked == NULL) || \
135                             ((tpcb)->flags & TF_NODELAY) || \
136                             (((tpcb)->unsent != NULL) && ((tpcb)->unsent->next != NULL))) ? \
137                                 1 : 0)
138 #define tcp_output_nagle(tpcb) (tcp_do_output_nagle(tpcb) ? tcp_output(tpcb) : ERR_OK)
139
140
141 /** This returns a TCP header option for MSS in an u32_t */
142 #define TCP_BUILD_MSS_OPTION()  htonl(((u32_t)2 << 24) | \
143                                 ((u32_t)4 << 16) | \
144                                 (((u32_t)TCP_MSS / 256) << 8) | \
145                                 (TCP_MSS & 255))
146
147 #define TCP_SEQ_LT(a,b)     ((s32_t)((a)-(b)) < 0)
148 #define TCP_SEQ_LEQ(a,b)    ((s32_t)((a)-(b)) <= 0)
149 #define TCP_SEQ_GT(a,b)     ((s32_t)((a)-(b)) > 0)
150 #define TCP_SEQ_GEQ(a,b)    ((s32_t)((a)-(b)) >= 0)
151 /* is b<=a<=c? */
152 #if 0 /* see bug #10548 */
153 #define TCP_SEQ_BETWEEN(a,b,c) ((c)-(b) >= (a)-(b))
154 #endif
155 #define TCP_SEQ_BETWEEN(a,b,c) (TCP_SEQ_GEQ(a,b) && TCP_SEQ_LEQ(a,c))
156 #define TCP_FIN 0x01U
157 #define TCP_SYN 0x02U
158 #define TCP_RST 0x04U
159 #define TCP_PSH 0x08U
160 #define TCP_ACK 0x10U
161 #define TCP_URG 0x20U
162 #define TCP_ECE 0x40U
163 #define TCP_CWR 0x80U
164
165 #define TCP_FLAGS 0x3fU
166
167 /* Length of the TCP header, excluding options. */
168 #define TCP_HLEN 20
169
170 #ifndef TCP_TMR_INTERVAL
171 #define TCP_TMR_INTERVAL       250  /* The TCP timer interval in milliseconds. */
172 #endif /* TCP_TMR_INTERVAL */
173
174 #ifndef TCP_FAST_INTERVAL
175 #define TCP_FAST_INTERVAL      TCP_TMR_INTERVAL /* the fine grained timeout in milliseconds */
176 #endif /* TCP_FAST_INTERVAL */
177
178 #ifndef TCP_SLOW_INTERVAL
179 #define TCP_SLOW_INTERVAL      (2*TCP_TMR_INTERVAL)  /* the coarse grained timeout in milliseconds */
180 #endif /* TCP_SLOW_INTERVAL */
181
182 #define TCP_FIN_WAIT_TIMEOUT 20000 /* milliseconds */
183 #define TCP_SYN_RCVD_TIMEOUT 20000 /* milliseconds */
184
185 #define TCP_OOSEQ_TIMEOUT        6U /* x RTO */
186
187 #ifndef TCP_MSL
188 #define TCP_MSL 60000U /* The maximum segment lifetime in milliseconds */
189 #endif
190
191 /* Keepalive values, compliant with RFC 1122. Don't change this unless you know what you're doing */
192 #ifndef  TCP_KEEPIDLE_DEFAULT
193 #define  TCP_KEEPIDLE_DEFAULT     7200000UL /* Default KEEPALIVE timer in milliseconds */
194 #endif
195
196 #ifndef  TCP_KEEPINTVL_DEFAULT
197 #define  TCP_KEEPINTVL_DEFAULT    75000UL   /* Default Time between KEEPALIVE probes in milliseconds */
198 #endif
199
200 #ifndef  TCP_KEEPCNT_DEFAULT
201 #define  TCP_KEEPCNT_DEFAULT      9U        /* Default Counter for KEEPALIVE probes */
202 #endif
203
204 #define  TCP_MAXIDLE              TCP_KEEPCNT_DEFAULT * TCP_KEEPINTVL_DEFAULT  /* Maximum KEEPALIVE probe time */
205
206 /* Fields are (of course) in network byte order.
207  * Some fields are converted to host byte order in tcp_input().
208  */
209 #ifdef PACK_STRUCT_USE_INCLUDES
210 #  include "arch/bpstruct.h"
211 #endif
212 PACK_STRUCT_BEGIN
213 struct tcp_hdr {
214   PACK_STRUCT_FIELD(u16_t src);
215   PACK_STRUCT_FIELD(u16_t dest);
216   PACK_STRUCT_FIELD(u32_t seqno);
217   PACK_STRUCT_FIELD(u32_t ackno);
218   PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags);
219   PACK_STRUCT_FIELD(u16_t wnd);
220   PACK_STRUCT_FIELD(u16_t chksum);
221   PACK_STRUCT_FIELD(u16_t urgp);
222 } PACK_STRUCT_STRUCT;
223 PACK_STRUCT_END
224 #ifdef PACK_STRUCT_USE_INCLUDES
225 #  include "arch/epstruct.h"
226 #endif
227
228 #define TCPH_OFFSET(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 8)
229 #define TCPH_HDRLEN(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 12)
230 #define TCPH_FLAGS(phdr)  (ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS)
231
232 #define TCPH_OFFSET_SET(phdr, offset) (phdr)->_hdrlen_rsvd_flags = htons(((offset) << 8) | TCPH_FLAGS(phdr))
233 #define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr))
234 #define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons((ntohs((phdr)->_hdrlen_rsvd_flags) & ~TCP_FLAGS) | (flags))
235 #define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (flags))
236 #define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (TCPH_FLAGS(phdr) & ~(flags)) )
237
238 #define TCP_TCPLEN(seg) ((seg)->len + ((TCPH_FLAGS((seg)->tcphdr) & TCP_FIN || \
239           TCPH_FLAGS((seg)->tcphdr) & TCP_SYN)? 1: 0))
240
241 enum tcp_state {
242   CLOSED      = 0,
243   LISTEN      = 1,
244   SYN_SENT    = 2,
245   SYN_RCVD    = 3,
246   ESTABLISHED = 4,
247   FIN_WAIT_1  = 5,
248   FIN_WAIT_2  = 6,
249   CLOSE_WAIT  = 7,
250   CLOSING     = 8,
251   LAST_ACK    = 9,
252   TIME_WAIT   = 10
253 };
254
255 /** Flags used on input processing, not on pcb->flags
256 */
257 #define TF_RESET     (u8_t)0x08U   /* Connection was reset. */
258 #define TF_CLOSED    (u8_t)0x10U   /* Connection was sucessfully closed. */
259 #define TF_GOT_FIN   (u8_t)0x20U   /* Connection was closed by the remote end. */
260
261 /**
262  * members common to struct tcp_pcb and struct tcp_listen_pcb
263  */
264 #define TCP_PCB_COMMON(type) \
265   type *next; /* for the linked list */ \
266   enum tcp_state state; /* TCP state */ \
267   u8_t prio; \
268   void *callback_arg; \
269   /* ports are in host byte order */ \
270   u16_t local_port
271
272 /* the TCP protocol control block */
273 struct tcp_pcb {
274 /** common PCB members */
275   IP_PCB;
276 /** protocol specific PCB members */
277   TCP_PCB_COMMON(struct tcp_pcb);
278
279   /* ports are in host byte order */
280   u16_t remote_port;
281   
282   u8_t flags;
283 #define TF_ACK_DELAY   (u8_t)0x01U   /* Delayed ACK. */
284 #define TF_ACK_NOW     (u8_t)0x02U   /* Immediate ACK. */
285 #define TF_INFR        (u8_t)0x04U   /* In fast recovery. */
286 #define TF_FIN         (u8_t)0x20U   /* Connection was closed locally (FIN segment enqueued). */
287 #define TF_NODELAY     (u8_t)0x40U   /* Disable Nagle algorithm */
288 #define TF_NAGLEMEMERR (u8_t)0x80U /* nagle enabled, memerr, try to output to prevent delayed ACK to happen */
289
290   /* the rest of the fields are in host byte order
291      as we have to do some math with them */
292   /* receiver variables */
293   u32_t rcv_nxt;   /* next seqno expected */
294   u16_t rcv_wnd;   /* receiver window */
295   u16_t rcv_ann_wnd; /* announced receive window */
296
297   /* Timers */
298   u32_t tmr;
299   u8_t polltmr, pollinterval;
300   
301   /* Retransmission timer. */
302   s16_t rtime;
303   
304   u16_t mss;   /* maximum segment size */
305   
306   /* RTT (round trip time) estimation variables */
307   u32_t rttest; /* RTT estimate in 500ms ticks */
308   u32_t rtseq;  /* sequence number being timed */
309   s16_t sa, sv; /* @todo document this */
310
311   s16_t rto;    /* retransmission time-out */
312   u8_t nrtx;    /* number of retransmissions */
313
314   /* fast retransmit/recovery */
315   u32_t lastack; /* Highest acknowledged seqno. */
316   u8_t dupacks;
317   
318   /* congestion avoidance/control variables */
319   u16_t cwnd;  
320   u16_t ssthresh;
321
322   /* sender variables */
323   u32_t snd_nxt,   /* next seqno to be sent */
324     snd_max;       /* Highest seqno sent. */
325   u16_t snd_wnd;   /* sender window */
326   u32_t snd_wl1, snd_wl2, /* Sequence and acknowledgement numbers of last
327                              window update. */
328     snd_lbb;       /* Sequence number of next byte to be buffered. */
329
330   u16_t acked;
331   
332   u16_t snd_buf;   /* Available buffer space for sending (in bytes). */
333 #define TCP_SNDQUEUELEN_OVERFLOW (0xffff-3)
334   u16_t snd_queuelen; /* Available buffer space for sending (in tcp_segs). */
335   
336   
337   /* These are ordered by sequence number: */
338   struct tcp_seg *unsent;   /* Unsent (queued) segments. */
339   struct tcp_seg *unacked;  /* Sent but unacknowledged segments. */
340 #if TCP_QUEUE_OOSEQ  
341   struct tcp_seg *ooseq;    /* Received out of sequence segments. */
342 #endif /* TCP_QUEUE_OOSEQ */
343
344   struct pbuf *refused_data; /* Data previously received but not yet taken by upper layer */
345
346 #if LWIP_CALLBACK_API
347   /* Function to be called when more send buffer space is available.
348    * @param arg user-supplied argument (tcp_pcb.callback_arg)
349    * @param pcb the tcp_pcb which has send buffer space available
350    * @param space the amount of bytes available
351    * @return ERR_OK: try to send some data by calling tcp_output
352    */
353   err_t (* sent)(void *arg, struct tcp_pcb *pcb, u16_t space);
354   
355   /* Function to be called when (in-sequence) data has arrived.
356    * @param arg user-supplied argument (tcp_pcb.callback_arg)
357    * @param pcb the tcp_pcb for which data has arrived
358    * @param p the packet buffer which arrived
359    * @param err an error argument (TODO: that is current always ERR_OK?)
360    * @return ERR_OK: try to send some data by calling tcp_output
361    */
362   err_t (* recv)(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);
363
364   /* Function to be called when a connection has been set up.
365    * @param arg user-supplied argument (tcp_pcb.callback_arg)
366    * @param pcb the tcp_pcb that now is connected
367    * @param err an error argument (TODO: that is current always ERR_OK?)
368    * @return value is currently ignored
369    */
370   err_t (* connected)(void *arg, struct tcp_pcb *pcb, err_t err);
371
372   /* Function to call when a listener has been connected.
373    * @param arg user-supplied argument (tcp_pcb.callback_arg)
374    * @param pcb a new tcp_pcb that now is connected
375    * @param err an error argument (TODO: that is current always ERR_OK?)
376    * @return ERR_OK: accept the new connection,
377    *                 any other err_t abortsthe new connection
378    */
379   err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err);
380
381   /* Function which is called periodically.
382    * The period can be adjusted in multiples of the TCP slow timer interval
383    * by changing tcp_pcb.polltmr.
384    * @param arg user-supplied argument (tcp_pcb.callback_arg)
385    * @param pcb the tcp_pcb to poll for
386    * @return ERR_OK: try to send some data by calling tcp_output
387    */
388   err_t (* poll)(void *arg, struct tcp_pcb *pcb);
389
390   /* Function to be called whenever a fatal error occurs.
391    * There is no pcb parameter since most of the times, the pcb is
392    * already deallocated (or there is no pcb) when this function is called.
393    * @param arg user-supplied argument (tcp_pcb.callback_arg)
394    * @param err an indication why the error callback is called:
395    *            ERR_ABRT: aborted through tcp_abort or by a TCP timer
396    *            ERR_RST: the connection was reset by the remote host
397    */
398   void (* errf)(void *arg, err_t err);
399 #endif /* LWIP_CALLBACK_API */
400
401   /* idle time before KEEPALIVE is sent */
402   u32_t keep_idle;
403 #if LWIP_TCP_KEEPALIVE
404   u32_t keep_intvl;
405   u32_t keep_cnt;
406 #endif /* LWIP_TCP_KEEPALIVE */
407   
408   /* Persist timer counter */
409   u32_t persist_cnt;
410   /* Persist timer back-off */
411   u8_t persist_backoff;
412
413   /* KEEPALIVE counter */
414   u8_t keep_cnt_sent;
415 };
416
417 struct tcp_pcb_listen {  
418 /* Common members of all PCB types */
419   IP_PCB;
420 /* Protocol specific PCB members */
421   TCP_PCB_COMMON(struct tcp_pcb_listen);
422
423 #if LWIP_CALLBACK_API
424   /* Function to call when a listener has been connected.
425    * @param arg user-supplied argument (tcp_pcb.callback_arg)
426    * @param pcb a new tcp_pcb that now is connected
427    * @param err an error argument (TODO: that is current always ERR_OK?)
428    * @return ERR_OK: accept the new connection,
429    *                 any other err_t abortsthe new connection
430    */
431   err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err);
432 #endif /* LWIP_CALLBACK_API */
433 #if TCP_LISTEN_BACKLOG
434   u8_t backlog;
435   u8_t accepts_pending;
436 #endif /* TCP_LISTEN_BACKLOG */
437 };
438
439 #if LWIP_EVENT_API
440
441 enum lwip_event {
442   LWIP_EVENT_ACCEPT,
443   LWIP_EVENT_SENT,
444   LWIP_EVENT_RECV,
445   LWIP_EVENT_CONNECTED,
446   LWIP_EVENT_POLL,
447   LWIP_EVENT_ERR
448 };
449
450 err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb,
451          enum lwip_event,
452          struct pbuf *p,
453          u16_t size,
454          err_t err);
455
456 #define TCP_EVENT_ACCEPT(pcb,err,ret)    ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
457                 LWIP_EVENT_ACCEPT, NULL, 0, err)
458 #define TCP_EVENT_SENT(pcb,space,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
459                    LWIP_EVENT_SENT, NULL, space, ERR_OK)
460 #define TCP_EVENT_RECV(pcb,p,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
461                 LWIP_EVENT_RECV, (p), 0, (err))
462 #define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
463                 LWIP_EVENT_CONNECTED, NULL, 0, (err))
464 #define TCP_EVENT_POLL(pcb,ret)       ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
465                 LWIP_EVENT_POLL, NULL, 0, ERR_OK)
466 #define TCP_EVENT_ERR(errf,arg,err)  lwip_tcp_event((arg), NULL, \
467                 LWIP_EVENT_ERR, NULL, 0, (err))
468 #else /* LWIP_EVENT_API */
469 #define TCP_EVENT_ACCEPT(pcb,err,ret)     \
470                         if((pcb)->accept != NULL) \
471                         (ret = (pcb)->accept((pcb)->callback_arg,(pcb),(err)))
472 #define TCP_EVENT_SENT(pcb,space,ret) \
473                         if((pcb)->sent != NULL) \
474                         (ret = (pcb)->sent((pcb)->callback_arg,(pcb),(space)))
475 #define TCP_EVENT_RECV(pcb,p,err,ret) \
476                         if((pcb)->recv != NULL) \
477                         { ret = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err)); } else { \
478                           ret = ERR_OK; \
479                           if (p) pbuf_free(p); }
480 #define TCP_EVENT_CONNECTED(pcb,err,ret) \
481                         if((pcb)->connected != NULL) \
482                         (ret = (pcb)->connected((pcb)->callback_arg,(pcb),(err)))
483 #define TCP_EVENT_POLL(pcb,ret) \
484                         if((pcb)->poll != NULL) \
485                         (ret = (pcb)->poll((pcb)->callback_arg,(pcb)))
486 #define TCP_EVENT_ERR(errf,arg,err) \
487                         if((errf) != NULL) \
488                         (errf)((arg),(err))
489 #endif /* LWIP_EVENT_API */
490
491 /* This structure represents a TCP segment on the unsent and unacked queues */
492 struct tcp_seg {
493   struct tcp_seg *next;    /* used when putting segements on a queue */
494   struct pbuf *p;          /* buffer containing data + TCP header */
495   void *dataptr;           /* pointer to the TCP data in the pbuf */
496   u16_t len;               /* the TCP length of this segment */
497   struct tcp_hdr *tcphdr;  /* the TCP header */
498 };
499
500 /* Internal functions and global variables: */
501 struct tcp_pcb *tcp_pcb_copy(struct tcp_pcb *pcb);
502 void tcp_pcb_purge(struct tcp_pcb *pcb);
503 void tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb);
504
505 u8_t tcp_segs_free(struct tcp_seg *seg);
506 u8_t tcp_seg_free(struct tcp_seg *seg);
507 struct tcp_seg *tcp_seg_copy(struct tcp_seg *seg);
508
509 #define tcp_ack(pcb)     if((pcb)->flags & TF_ACK_DELAY) { \
510                             (pcb)->flags &= ~TF_ACK_DELAY; \
511                             (pcb)->flags |= TF_ACK_NOW; \
512                             tcp_output(pcb); \
513                          } else { \
514                             (pcb)->flags |= TF_ACK_DELAY; \
515                          }
516
517 #define tcp_ack_now(pcb) (pcb)->flags |= TF_ACK_NOW; \
518                          tcp_output(pcb)
519
520 err_t tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags);
521 err_t tcp_enqueue(struct tcp_pcb *pcb, void *dataptr, u16_t len,
522     u8_t flags, u8_t apiflags,
523                 u8_t *optdata, u8_t optlen);
524
525 void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg);
526
527 void tcp_rst(u32_t seqno, u32_t ackno,
528        struct ip_addr *local_ip, struct ip_addr *remote_ip,
529        u16_t local_port, u16_t remote_port);
530
531 u32_t tcp_next_iss(void);
532
533 void tcp_keepalive(struct tcp_pcb *pcb);
534 void tcp_zero_window_probe(struct tcp_pcb *pcb);
535
536 #if TCP_CALCULATE_EFF_SEND_MSS
537 u16_t tcp_eff_send_mss(u16_t sendmss, struct ip_addr *addr);
538 #endif /* TCP_CALCULATE_EFF_SEND_MSS */
539
540 extern struct tcp_pcb *tcp_input_pcb;
541 extern u32_t tcp_ticks;
542
543 #if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
544 void tcp_debug_print(struct tcp_hdr *tcphdr);
545 void tcp_debug_print_flags(u8_t flags);
546 void tcp_debug_print_state(enum tcp_state s);
547 void tcp_debug_print_pcbs(void);
548 s16_t tcp_pcbs_sane(void);
549 #else
550 #  define tcp_debug_print(tcphdr)
551 #  define tcp_debug_print_flags(flags)
552 #  define tcp_debug_print_state(s)
553 #  define tcp_debug_print_pcbs()
554 #  define tcp_pcbs_sane() 1
555 #endif /* TCP_DEBUG */
556
557 #if NO_SYS
558 #define tcp_timer_needed()
559 #else
560 void tcp_timer_needed(void);
561 #endif
562
563 /* The TCP PCB lists. */
564 union tcp_listen_pcbs_t { /* List of all TCP PCBs in LISTEN state. */
565   struct tcp_pcb_listen *listen_pcbs; 
566   struct tcp_pcb *pcbs;
567 };
568 extern union tcp_listen_pcbs_t tcp_listen_pcbs;
569 extern struct tcp_pcb *tcp_active_pcbs;  /* List of all TCP PCBs that are in a
570               state in which they accept or send
571               data. */
572 extern struct tcp_pcb *tcp_tw_pcbs;      /* List of all TCP PCBs in TIME-WAIT. */
573
574 extern struct tcp_pcb *tcp_tmp_pcb;      /* Only used for temporary storage. */
575
576 /* Axioms about the above lists:   
577    1) Every TCP PCB that is not CLOSED is in one of the lists.
578    2) A PCB is only in one of the lists.
579    3) All PCBs in the tcp_listen_pcbs list is in LISTEN state.
580    4) All PCBs in the tcp_tw_pcbs list is in TIME-WAIT state.
581 */
582
583 /* Define two macros, TCP_REG and TCP_RMV that registers a TCP PCB
584    with a PCB list or removes a PCB from a list, respectively. */
585 #if 0
586 #define TCP_REG(pcbs, npcb) do {\
587                             LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %d\n", npcb, npcb->local_port)); \
588                             for(tcp_tmp_pcb = *pcbs; \
589           tcp_tmp_pcb != NULL; \
590         tcp_tmp_pcb = tcp_tmp_pcb->next) { \
591                                 LWIP_ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != npcb); \
592                             } \
593                             LWIP_ASSERT("TCP_REG: pcb->state != CLOSED", npcb->state != CLOSED); \
594                             npcb->next = *pcbs; \
595                             LWIP_ASSERT("TCP_REG: npcb->next != npcb", npcb->next != npcb); \
596                             *(pcbs) = npcb; \
597                             LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \
598               tcp_timer_needed(); \
599                             } while(0)
600 #define TCP_RMV(pcbs, npcb) do { \
601                             LWIP_ASSERT("TCP_RMV: pcbs != NULL", *pcbs != NULL); \
602                             LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removing %p from %p\n", npcb, *pcbs)); \
603                             if(*pcbs == npcb) { \
604                                *pcbs = (*pcbs)->next; \
605                             } else for(tcp_tmp_pcb = *pcbs; tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \
606                                if(tcp_tmp_pcb->next != NULL && tcp_tmp_pcb->next == npcb) { \
607                                   tcp_tmp_pcb->next = npcb->next; \
608                                   break; \
609                                } \
610                             } \
611                             npcb->next = NULL; \
612                             LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \
613                             LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", npcb, *pcbs)); \
614                             } while(0)
615
616 #else /* LWIP_DEBUG */
617 #define TCP_REG(pcbs, npcb) do { \
618                             npcb->next = *pcbs; \
619                             *(pcbs) = npcb; \
620               tcp_timer_needed(); \
621                             } while(0)
622 #define TCP_RMV(pcbs, npcb) do { \
623                             if(*(pcbs) == npcb) { \
624                                (*(pcbs)) = (*pcbs)->next; \
625                             } else for(tcp_tmp_pcb = *pcbs; tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \
626                                if(tcp_tmp_pcb->next != NULL && tcp_tmp_pcb->next == npcb) { \
627                                   tcp_tmp_pcb->next = npcb->next; \
628                                   break; \
629                                } \
630                             } \
631                             npcb->next = NULL; \
632                             } while(0)
633 #endif /* LWIP_DEBUG */
634
635 #ifdef __cplusplus
636 }
637 #endif
638
639 #endif /* LWIP_TCP */
640
641 #endif /* __LWIP_TCP_H__ */