Example program with HTTPServer and sensor data streaming over TCPSockets, using Donatien Garnier's Net APIs and services code on top of LWIP. Files StreamServer.h and .cpp encapsulate streaming over TCPSockets. Broadcast is done by sendToAll(), and all incoming data is echoed back to the client. Echo code can be replaced with some remote control of the streaming interface. See main() that shows how to periodically send some data to all subscribed clients. To subscribe, a client should open a socket at <mbed_ip> port 123. I used few lines in TCL code to set up a quick sink for the data. HTTP files are served on port 80 concurrently to the streaming.

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers tcp.h Source File

tcp.h

00001 /*
00002  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
00003  * All rights reserved. 
00004  * 
00005  * Redistribution and use in source and binary forms, with or without modification, 
00006  * are permitted provided that the following conditions are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright notice,
00009  *    this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright notice,
00011  *    this list of conditions and the following disclaimer in the documentation
00012  *    and/or other materials provided with the distribution.
00013  * 3. The name of the author may not be used to endorse or promote products
00014  *    derived from this software without specific prior written permission. 
00015  *
00016  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
00017  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
00018  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
00019  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
00020  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
00021  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
00022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
00023  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
00024  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
00025  * OF SUCH DAMAGE.
00026  *
00027  * This file is part of the lwIP TCP/IP stack.
00028  * 
00029  * Author: Adam Dunkels <adam@sics.se>
00030  *
00031  */
00032 #ifndef __LWIP_TCP_H__
00033 #define __LWIP_TCP_H__
00034 
00035 #include "lwip/opt.h"
00036 
00037 #if LWIP_TCP /* don't build if not configured for use in lwipopts.h */
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 /** Function prototype for tcp accept callback functions. Called when a new
00053  * connection can be accepted on a listening pcb.
00054  *
00055  * @param arg Additional argument to pass to the callback function (@see tcp_arg())
00056  * @param newpcb The new connection pcb
00057  * @param err An error code if there has been an error accepting.
00058  *            Only return ERR_ABRT if you have called tcp_abort from within the
00059  *            callback function!
00060  */
00061 typedef err_t (*tcp_accept_fn)(void *arg, struct tcp_pcb *newpcb, err_t err);
00062 
00063 /** Function prototype for tcp receive callback functions. Called when data has
00064  * been received.
00065  *
00066  * @param arg Additional argument to pass to the callback function (@see tcp_arg())
00067  * @param tpcb The connection pcb which received data
00068  * @param p The received data (or NULL when the connection has been closed!)
00069  * @param err An error code if there has been an error receiving
00070  *            Only return ERR_ABRT if you have called tcp_abort from within the
00071  *            callback function!
00072  */
00073 typedef err_t (*tcp_recv_fn)(void *arg, struct tcp_pcb *tpcb,
00074                              struct pbuf *p, err_t err);
00075 
00076 /** Function prototype for tcp sent callback functions. Called when sent data has
00077  * been acknowledged by the remote side. Use it to free corresponding resources.
00078  * This also means that the pcb has now space available to send new data.
00079  *
00080  * @param arg Additional argument to pass to the callback function (@see tcp_arg())
00081  * @param tpcb The connection pcb for which data has been acknowledged
00082  * @param len The amount of bytes acknowledged
00083  * @return ERR_OK: try to send some data by calling tcp_output
00084  *            Only return ERR_ABRT if you have called tcp_abort from within the
00085  *            callback function!
00086  */
00087 typedef err_t (*tcp_sent_fn)(void *arg, struct tcp_pcb *tpcb,
00088                               u16_t len);
00089 
00090 /** Function prototype for tcp poll callback functions. Called periodically as
00091  * specified by @see tcp_poll.
00092  *
00093  * @param arg Additional argument to pass to the callback function (@see tcp_arg())
00094  * @param tpcb tcp pcb
00095  * @return ERR_OK: try to send some data by calling tcp_output
00096  *            Only return ERR_ABRT if you have called tcp_abort from within the
00097  *            callback function!
00098  */
00099 typedef err_t (*tcp_poll_fn)(void *arg, struct tcp_pcb *tpcb);
00100 
00101 /** Function prototype for tcp error callback functions. Called when the pcb
00102  * receives a RST or is unexpectedly closed for any other reason.
00103  *
00104  * @note The corresponding pcb is already freed when this callback is called!
00105  *
00106  * @param arg Additional argument to pass to the callback function (@see tcp_arg())
00107  * @param err Error code to indicate why the pcb has been closed
00108  *            ERR_ABRT: aborted through tcp_abort or by a TCP timer
00109  *            ERR_RST: the connection was reset by the remote host
00110  */
00111 typedef void  (*tcp_err_fn)(void *arg, err_t err);
00112 
00113 /** Function prototype for tcp connected callback functions. Called when a pcb
00114  * is connected to the remote side after initiating a connection attempt by
00115  * calling tcp_connect().
00116  *
00117  * @param arg Additional argument to pass to the callback function (@see tcp_arg())
00118  * @param tpcb The connection pcb which is connected
00119  * @param err An unused error code, always ERR_OK currently ;-) TODO!
00120  *            Only return ERR_ABRT if you have called tcp_abort from within the
00121  *            callback function!
00122  *
00123  * @note When a connection attempt fails, the error callback is currently called!
00124  */
00125 typedef err_t (*tcp_connected_fn)(void *arg, struct tcp_pcb *tpcb, err_t err);
00126 
00127 enum tcp_state {
00128   CLOSED      = 0,
00129   LISTEN      = 1,
00130   SYN_SENT    = 2,
00131   SYN_RCVD    = 3,
00132   ESTABLISHED = 4,
00133   FIN_WAIT_1  = 5,
00134   FIN_WAIT_2  = 6,
00135   CLOSE_WAIT  = 7,
00136   CLOSING     = 8,
00137   LAST_ACK    = 9,
00138   TIME_WAIT   = 10
00139 };
00140 
00141 #if LWIP_CALLBACK_API
00142   /* Function to call when a listener has been connected.
00143    * @param arg user-supplied argument (tcp_pcb.callback_arg)
00144    * @param pcb a new tcp_pcb that now is connected
00145    * @param err an error argument (TODO: that is current always ERR_OK?)
00146    * @return ERR_OK: accept the new connection,
00147    *                 any other err_t abortsthe new connection
00148    */
00149 #define DEF_ACCEPT_CALLBACK  tcp_accept_fn accept;
00150 #else /* LWIP_CALLBACK_API */
00151 #define DEF_ACCEPT_CALLBACK
00152 #endif /* LWIP_CALLBACK_API */
00153 
00154 /**
00155  * members common to struct tcp_pcb and struct tcp_listen_pcb
00156  */
00157 #define TCP_PCB_COMMON(type) \
00158   type *next; /* for the linked list */ \
00159   enum tcp_state state; /* TCP state */ \
00160   u8_t prio; \
00161   void *callback_arg; \
00162   /* the accept callback for listen- and normal pcbs, if LWIP_CALLBACK_API */ \
00163   DEF_ACCEPT_CALLBACK \
00164   /* ports are in host byte order */ \
00165   u16_t local_port
00166 
00167 
00168 /* the TCP protocol control block */
00169 struct tcp_pcb {
00170 /** common PCB members */
00171   IP_PCB;
00172 /** protocol specific PCB members */
00173   TCP_PCB_COMMON(struct tcp_pcb);
00174 
00175   /* ports are in host byte order */
00176   u16_t remote_port;
00177   
00178   u8_t flags;
00179 #define TF_ACK_DELAY   ((u8_t)0x01U)   /* Delayed ACK. */
00180 #define TF_ACK_NOW     ((u8_t)0x02U)   /* Immediate ACK. */
00181 #define TF_INFR        ((u8_t)0x04U)   /* In fast recovery. */
00182 #define TF_TIMESTAMP   ((u8_t)0x08U)   /* Timestamp option enabled */
00183 #define TF_RXCLOSED    ((u8_t)0x10U)   /* rx closed by tcp_shutdown */
00184 #define TF_FIN         ((u8_t)0x20U)   /* Connection was closed locally (FIN segment enqueued). */
00185 #define TF_NODELAY     ((u8_t)0x40U)   /* Disable Nagle algorithm */
00186 #define TF_NAGLEMEMERR ((u8_t)0x80U)   /* nagle enabled, memerr, try to output to prevent delayed ACK to happen */
00187 
00188   /* the rest of the fields are in host byte order
00189      as we have to do some math with them */
00190   /* receiver variables */
00191   u32_t rcv_nxt;   /* next seqno expected */
00192   u16_t rcv_wnd;   /* receiver window available */
00193   u16_t rcv_ann_wnd; /* receiver window to announce */
00194   u32_t rcv_ann_right_edge; /* announced right edge of window */
00195 
00196   /* Timers */
00197   u32_t tmr;
00198   u8_t polltmr, pollinterval;
00199   
00200   /* Retransmission timer. */
00201   s16_t rtime;
00202   
00203   u16_t mss;   /* maximum segment size */
00204   
00205   /* RTT (round trip time) estimation variables */
00206   u32_t rttest; /* RTT estimate in 500ms ticks */
00207   u32_t rtseq;  /* sequence number being timed */
00208   s16_t sa, sv; /* @todo document this */
00209 
00210   s16_t rto;    /* retransmission time-out */
00211   u8_t nrtx;    /* number of retransmissions */
00212 
00213   /* fast retransmit/recovery */
00214   u32_t lastack; /* Highest acknowledged seqno. */
00215   u8_t dupacks;
00216   
00217   /* congestion avoidance/control variables */
00218   u16_t cwnd;  
00219   u16_t ssthresh;
00220 
00221   /* sender variables */
00222   u32_t snd_nxt;   /* next new seqno to be sent */
00223   u16_t snd_wnd;   /* sender window */
00224   u32_t snd_wl1, snd_wl2; /* Sequence and acknowledgement numbers of last
00225                              window update. */
00226   u32_t snd_lbb;       /* Sequence number of next byte to be buffered. */
00227 
00228   u16_t acked;
00229   
00230   u16_t snd_buf;   /* Available buffer space for sending (in bytes). */
00231 #define TCP_SNDQUEUELEN_OVERFLOW (0xffff-3)
00232   u16_t snd_queuelen; /* Available buffer space for sending (in tcp_segs). */
00233 
00234 #if TCP_OVERSIZE
00235   /* Extra bytes available at the end of the last pbuf in unsent. */
00236   u16_t unsent_oversize;
00237 #endif /* TCP_OVERSIZE */ 
00238 
00239   /* These are ordered by sequence number: */
00240   struct tcp_seg *unsent;   /* Unsent (queued) segments. */
00241   struct tcp_seg *unacked;  /* Sent but unacknowledged segments. */
00242 #if TCP_QUEUE_OOSEQ  
00243   struct tcp_seg *ooseq;    /* Received out of sequence segments. */
00244 #endif /* TCP_QUEUE_OOSEQ */
00245 
00246   struct pbuf *refused_data; /* Data previously received but not yet taken by upper layer */
00247 
00248 #if LWIP_CALLBACK_API
00249   /* Function to be called when more send buffer space is available. */
00250   tcp_sent_fn sent;
00251   /* Function to be called when (in-sequence) data has arrived. */
00252   tcp_recv_fn recv;
00253   /* Function to be called when a connection has been set up. */
00254   tcp_connected_fn connected;
00255   /* Function which is called periodically. */
00256   tcp_poll_fn poll;
00257   /* Function to be called whenever a fatal error occurs. */
00258   tcp_err_fn errf;
00259 #endif /* LWIP_CALLBACK_API */
00260 
00261 #if LWIP_TCP_TIMESTAMPS
00262   u32_t ts_lastacksent;
00263   u32_t ts_recent;
00264 #endif /* LWIP_TCP_TIMESTAMPS */
00265 
00266   /* idle time before KEEPALIVE is sent */
00267   u32_t keep_idle;
00268 #if LWIP_TCP_KEEPALIVE
00269   u32_t keep_intvl;
00270   u32_t keep_cnt;
00271 #endif /* LWIP_TCP_KEEPALIVE */
00272   
00273   /* Persist timer counter */
00274   u32_t persist_cnt;
00275   /* Persist timer back-off */
00276   u8_t persist_backoff;
00277 
00278   /* KEEPALIVE counter */
00279   u8_t keep_cnt_sent;
00280 };
00281 
00282 struct tcp_pcb_listen {  
00283 /* Common members of all PCB types */
00284   IP_PCB;
00285 /* Protocol specific PCB members */
00286   TCP_PCB_COMMON(struct tcp_pcb_listen);
00287 
00288 #if TCP_LISTEN_BACKLOG
00289   u8_t backlog;
00290   u8_t accepts_pending;
00291 #endif /* TCP_LISTEN_BACKLOG */
00292 };
00293 
00294 #if LWIP_EVENT_API
00295 
00296 enum lwip_event {
00297   LWIP_EVENT_ACCEPT,
00298   LWIP_EVENT_SENT,
00299   LWIP_EVENT_RECV,
00300   LWIP_EVENT_CONNECTED,
00301   LWIP_EVENT_POLL,
00302   LWIP_EVENT_ERR
00303 };
00304 
00305 err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb,
00306          enum lwip_event,
00307          struct pbuf *p,
00308          u16_t size,
00309          err_t err);
00310 
00311 #endif /* LWIP_EVENT_API */
00312 
00313 /* Application program's interface: */
00314 struct tcp_pcb * tcp_new     (void);
00315 
00316 void             tcp_arg     (struct tcp_pcb *pcb, void *arg);
00317 void             tcp_accept  (struct tcp_pcb *pcb, tcp_accept_fn accept);
00318 void             tcp_recv    (struct tcp_pcb *pcb, tcp_recv_fn recv);
00319 void             tcp_sent    (struct tcp_pcb *pcb, tcp_sent_fn sent);
00320 void             tcp_poll    (struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval);
00321 void             tcp_err     (struct tcp_pcb *pcb, tcp_err_fn err);
00322 
00323 #define          tcp_mss(pcb)             (((pcb)->flags & TF_TIMESTAMP) ? ((pcb)->mss - 12)  : (pcb)->mss)
00324 #define          tcp_sndbuf(pcb)          ((pcb)->snd_buf)
00325 #define          tcp_sndqueuelen(pcb)     ((pcb)->snd_queuelen)
00326 #define          tcp_nagle_disable(pcb)   ((pcb)->flags |= TF_NODELAY)
00327 #define          tcp_nagle_enable(pcb)    ((pcb)->flags &= ~TF_NODELAY)
00328 #define          tcp_nagle_disabled(pcb)  (((pcb)->flags & TF_NODELAY) != 0)
00329 
00330 #if TCP_LISTEN_BACKLOG
00331 #define          tcp_accepted(pcb) do { \
00332   LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", pcb->state == LISTEN); \
00333   (((struct tcp_pcb_listen *)(pcb))->accepts_pending--); } while(0)
00334 #else  /* TCP_LISTEN_BACKLOG */
00335 #define          tcp_accepted(pcb) LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", \
00336                                                pcb->state == LISTEN)
00337 #endif /* TCP_LISTEN_BACKLOG */
00338 
00339 void             tcp_recved  (struct tcp_pcb *pcb, u16_t len);
00340 err_t            tcp_bind    (struct tcp_pcb *pcb, ip_addr_t *ipaddr,
00341                               u16_t port);
00342 err_t            tcp_connect (struct tcp_pcb *pcb, ip_addr_t *ipaddr,
00343                               u16_t port, tcp_connected_fn connected);
00344 
00345 struct tcp_pcb * tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog);
00346 #define          tcp_listen(pcb) tcp_listen_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG)
00347 
00348 void             tcp_abort (struct tcp_pcb *pcb);
00349 err_t            tcp_close   (struct tcp_pcb *pcb);
00350 err_t            tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx);
00351 
00352 /* Flags for "apiflags" parameter in tcp_write */
00353 #define TCP_WRITE_FLAG_COPY 0x01
00354 #define TCP_WRITE_FLAG_MORE 0x02
00355 
00356 err_t            tcp_write   (struct tcp_pcb *pcb, const void *dataptr, u16_t len,
00357                               u8_t apiflags);
00358 
00359 void             tcp_setprio (struct tcp_pcb *pcb, u8_t prio);
00360 
00361 #define TCP_PRIO_MIN    1
00362 #define TCP_PRIO_NORMAL 64
00363 #define TCP_PRIO_MAX    127
00364 
00365 err_t            tcp_output  (struct tcp_pcb *pcb);
00366 
00367 
00368 const char* tcp_debug_state_str(enum tcp_state s);
00369 
00370 
00371 #ifdef __cplusplus
00372 }
00373 #endif
00374 
00375 #endif /* LWIP_TCP */
00376 
00377 #endif /* __LWIP_TCP_H__ */