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.
ip_addr.c
00001 /** 00002 * @file 00003 * This is the IPv4 address tools implementation. 00004 * 00005 */ 00006 00007 /* 00008 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 00009 * All rights reserved. 00010 * 00011 * Redistribution and use in source and binary forms, with or without modification, 00012 * are permitted provided that the following conditions are met: 00013 * 00014 * 1. Redistributions of source code must retain the above copyright notice, 00015 * this list of conditions and the following disclaimer. 00016 * 2. Redistributions in binary form must reproduce the above copyright notice, 00017 * this list of conditions and the following disclaimer in the documentation 00018 * and/or other materials provided with the distribution. 00019 * 3. The name of the author may not be used to endorse or promote products 00020 * derived from this software without specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00023 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00024 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00025 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00026 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00027 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00028 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00029 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00030 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00031 * OF SUCH DAMAGE. 00032 * 00033 * This file is part of the lwIP TCP/IP stack. 00034 * 00035 * Author: Adam Dunkels <adam@sics.se> 00036 * 00037 */ 00038 00039 #include "lwip/opt.h" 00040 #include "lwip/ip_addr.h" 00041 #include "lwip/netif.h" 00042 00043 /* used by IP_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */ 00044 const ip_addr_t ip_addr_any = { IPADDR_ANY }; 00045 const ip_addr_t ip_addr_broadcast = { IPADDR_BROADCAST }; 00046 00047 /** 00048 * Determine if an address is a broadcast address on a network interface 00049 * 00050 * @param addr address to be checked 00051 * @param netif the network interface against which the address is checked 00052 * @return returns non-zero if the address is a broadcast address 00053 */ 00054 u8_t ip_addr_isbroadcast(ip_addr_t *addr, struct netif *netif) 00055 { 00056 u32_t addr2test; 00057 00058 addr2test = ip4_addr_get_u32(addr); 00059 /* all ones (broadcast) or all zeroes (old skool broadcast) */ 00060 if ((~addr2test == IPADDR_ANY) || 00061 (addr2test == IPADDR_ANY)) 00062 return 1; 00063 /* no broadcast support on this network interface? */ 00064 else if ((netif->flags & NETIF_FLAG_BROADCAST) == 0) 00065 /* the given address cannot be a broadcast address 00066 * nor can we check against any broadcast addresses */ 00067 return 0; 00068 /* address matches network interface address exactly? => no broadcast */ 00069 else if (addr2test == ip4_addr_get_u32(&netif->ip_addr)) 00070 return 0; 00071 /* on the same (sub) network... */ 00072 else if (ip_addr_netcmp(addr, &(netif->ip_addr), &(netif->netmask)) 00073 /* ...and host identifier bits are all ones? =>... */ 00074 && ((addr2test & ~ip4_addr_get_u32(&netif->netmask)) == 00075 (IPADDR_BROADCAST & ~ip4_addr_get_u32(&netif->netmask)))) 00076 /* => network broadcast address */ 00077 return 1; 00078 else 00079 return 0; 00080 } 00081 00082 /* Here for now until needed in other places in lwIP */ 00083 #ifndef isprint 00084 #define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up) 00085 #define isprint(c) in_range(c, 0x20, 0x7f) 00086 #define isdigit(c) in_range(c, '0', '9') 00087 #define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) 00088 #define islower(c) in_range(c, 'a', 'z') 00089 #define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') 00090 #endif 00091 00092 /** 00093 * Ascii internet address interpretation routine. 00094 * The value returned is in network order. 00095 * 00096 * @param cp IP address in ascii represenation (e.g. "127.0.0.1") 00097 * @return ip address in network order 00098 */ 00099 u32_t 00100 ipaddr_addr(const char *cp) 00101 { 00102 ip_addr_t val; 00103 00104 if (ipaddr_aton(cp, &val)) { 00105 return ip4_addr_get_u32(&val); 00106 } 00107 return (IPADDR_NONE); 00108 } 00109 00110 /** 00111 * Check whether "cp" is a valid ascii representation 00112 * of an Internet address and convert to a binary address. 00113 * Returns 1 if the address is valid, 0 if not. 00114 * This replaces inet_addr, the return value from which 00115 * cannot distinguish between failure and a local broadcast address. 00116 * 00117 * @param cp IP address in ascii represenation (e.g. "127.0.0.1") 00118 * @param addr pointer to which to save the ip address in network order 00119 * @return 1 if cp could be converted to addr, 0 on failure 00120 */ 00121 int 00122 ipaddr_aton(const char *cp, ip_addr_t *addr) 00123 { 00124 u32_t val; 00125 u8_t base; 00126 char c; 00127 u32_t parts[4]; 00128 u32_t *pp = parts; 00129 00130 c = *cp; 00131 for (;;) { 00132 /* 00133 * Collect number up to ``.''. 00134 * Values are specified as for C: 00135 * 0x=hex, 0=octal, 1-9=decimal. 00136 */ 00137 if (!isdigit(c)) 00138 return (0); 00139 val = 0; 00140 base = 10; 00141 if (c == '0') { 00142 c = *++cp; 00143 if (c == 'x' || c == 'X') { 00144 base = 16; 00145 c = *++cp; 00146 } else 00147 base = 8; 00148 } 00149 for (;;) { 00150 if (isdigit(c)) { 00151 val = (val * base) + (int)(c - '0'); 00152 c = *++cp; 00153 } else if (base == 16 && isxdigit(c)) { 00154 val = (val << 4) | (int)(c + 10 - (islower(c) ? 'a' : 'A')); 00155 c = *++cp; 00156 } else 00157 break; 00158 } 00159 if (c == '.') { 00160 /* 00161 * Internet format: 00162 * a.b.c.d 00163 * a.b.c (with c treated as 16 bits) 00164 * a.b (with b treated as 24 bits) 00165 */ 00166 if (pp >= parts + 3) 00167 return (0); 00168 *pp++ = val; 00169 c = *++cp; 00170 } else 00171 break; 00172 } 00173 /* 00174 * Check for trailing characters. 00175 */ 00176 if (c != '\0' && !isspace(c)) 00177 return (0); 00178 /* 00179 * Concoct the address according to 00180 * the number of parts specified. 00181 */ 00182 switch (pp - parts + 1) { 00183 00184 case 0: 00185 return (0); /* initial nondigit */ 00186 00187 case 1: /* a -- 32 bits */ 00188 break; 00189 00190 case 2: /* a.b -- 8.24 bits */ 00191 if (val > 0xffffffUL) 00192 return (0); 00193 val |= parts[0] << 24; 00194 break; 00195 00196 case 3: /* a.b.c -- 8.8.16 bits */ 00197 if (val > 0xffff) 00198 return (0); 00199 val |= (parts[0] << 24) | (parts[1] << 16); 00200 break; 00201 00202 case 4: /* a.b.c.d -- 8.8.8.8 bits */ 00203 if (val > 0xff) 00204 return (0); 00205 val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); 00206 break; 00207 } 00208 if (addr) { 00209 ip4_addr_set_u32(addr, htonl(val)); 00210 } 00211 return (1); 00212 } 00213 00214 /** 00215 * Convert numeric IP address into decimal dotted ASCII representation. 00216 * returns ptr to static buffer; not reentrant! 00217 * 00218 * @param addr ip address in network order to convert 00219 * @return pointer to a global static (!) buffer that holds the ASCII 00220 * represenation of addr 00221 */ 00222 char * 00223 ipaddr_ntoa(ip_addr_t *addr) 00224 { 00225 static char str[16]; 00226 return ipaddr_ntoa_r(addr, str, 16); 00227 } 00228 00229 /** 00230 * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used. 00231 * 00232 * @param addr ip address in network order to convert 00233 * @param buf target buffer where the string is stored 00234 * @param buflen length of buf 00235 * @return either pointer to buf which now holds the ASCII 00236 * representation of addr or NULL if buf was too small 00237 */ 00238 char *ipaddr_ntoa_r(ip_addr_t *addr, char *buf, int buflen) 00239 { 00240 u32_t s_addr; 00241 char inv[3]; 00242 char *rp; 00243 u8_t *ap; 00244 u8_t rem; 00245 u8_t n; 00246 u8_t i; 00247 int len = 0; 00248 00249 s_addr = ip4_addr_get_u32(addr); 00250 00251 rp = buf; 00252 ap = (u8_t *)&s_addr; 00253 for(n = 0; n < 4; n++) { 00254 i = 0; 00255 do { 00256 rem = *ap % (u8_t)10; 00257 *ap /= (u8_t)10; 00258 inv[i++] = '0' + rem; 00259 } while(*ap); 00260 while(i--) { 00261 if (len++ >= buflen) { 00262 return NULL; 00263 } 00264 *rp++ = inv[i]; 00265 } 00266 if (len++ >= buflen) { 00267 return NULL; 00268 } 00269 *rp++ = '.'; 00270 ap++; 00271 } 00272 *--rp = 0; 00273 return buf; 00274 }
Generated on Tue Jul 12 2022 21:10:25 by 1.7.2