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.
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__ */
Generated on Tue Jul 12 2022 21:10:26 by 1.7.2