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 ip_addr.c Source File

ip_addr.c

Go to the documentation of this file.
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 }