Maxim nexpaq / nexpaq_dev
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SocketAddress.cpp Source File

SocketAddress.cpp

00001 /* Socket
00002  * Copyright (c) 2015 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include "SocketAddress.h"
00018 #include "NetworkInterface.h"
00019 #include "NetworkStack.h"
00020 #include <string.h>
00021 #include "mbed.h"
00022 
00023 
00024 static bool ipv4_is_valid(const char *addr)
00025 {
00026     int i = 0;
00027 
00028     // Check each digit for [0-9.]
00029     for (; addr[i]; i++) {
00030         if (!(addr[i] >= '0' && addr[i] <= '9') && addr[i] != '.') {
00031             return false;
00032         }
00033     }
00034 
00035     // Ending with '.' garuntees host
00036     if (i > 0 && addr[i-1] == '.') {
00037         return false;
00038     }
00039 
00040     return true;
00041 }
00042 
00043 static bool ipv6_is_valid(const char *addr)
00044 {
00045     // Check each digit for [0-9a-fA-F:]
00046     for (int i = 0; addr[i]; i++) {
00047         if (!(addr[i] >= '0' && addr[i] <= '9') &&
00048             !(addr[i] >= 'a' && addr[i] <= 'f') &&
00049             !(addr[i] >= 'A' && addr[i] <= 'F') &&
00050             addr[i] != ':') {
00051             return false;
00052         }
00053     }
00054 
00055     return true;
00056 }
00057 
00058 static void ipv4_from_address(uint8_t *bytes, const char *addr)
00059 {
00060     int count = 0;
00061     int i = 0;
00062 
00063     for (; count < NSAPI_IPv4_BYTES; count++) {
00064         int scanned = sscanf(&addr[i], "%hhu", &bytes[count]);
00065         if (scanned < 1) {
00066             return;
00067         }
00068 
00069         for (; addr[i] != '.'; i++) {
00070             if (!addr[i]) {
00071                 return;
00072             }
00073         }
00074 
00075         i++;
00076     }
00077 }
00078 
00079 static int ipv6_scan_chunk(uint16_t *shorts, const char *chunk) {
00080     int count = 0;
00081     int i = 0;
00082 
00083     for (; count < NSAPI_IPv6_BYTES/2; count++) {
00084         int scanned = sscanf(&chunk[i], "%hx", &shorts[count]);
00085         if (scanned < 1) {
00086             return count;
00087         }
00088 
00089         for (; chunk[i] != ':'; i++) {
00090             if (!chunk[i]) {
00091                 return count+1;
00092             }
00093         }
00094 
00095         i++;
00096     }
00097 
00098     return count;
00099 }
00100 
00101 static void ipv6_from_address(uint8_t *bytes, const char *addr)
00102 {
00103     // Start with zeroed address
00104     uint16_t shorts[NSAPI_IPv6_BYTES/2];
00105     memset(shorts, 0, sizeof shorts);
00106 
00107     int suffix = 0;
00108 
00109     // Find double colons and scan suffix
00110     for (int i = 0; addr[i]; i++) {
00111         if (addr[i] == ':' && addr[i+1] == ':') {
00112             suffix = ipv6_scan_chunk(shorts, &addr[i+2]);
00113             break;
00114         }
00115     }
00116 
00117     // Move suffix to end
00118     memmove(&shorts[NSAPI_IPv6_BYTES/2-suffix], &shorts[0],
00119             suffix*sizeof(uint16_t));
00120 
00121     // Scan prefix
00122     ipv6_scan_chunk(shorts, &addr[0]);
00123 
00124     // Flip bytes
00125     for (int i = 0; i < NSAPI_IPv6_BYTES/2; i++) {
00126         bytes[2*i+0] = (uint8_t)(shorts[i] >> 8);
00127         bytes[2*i+1] = (uint8_t)(shorts[i] >> 0);
00128     }
00129 }
00130 
00131 static void ipv4_to_address(char *addr, const uint8_t *bytes)
00132 {
00133     sprintf(addr, "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]);
00134 }
00135 
00136 static void ipv6_to_address(char *addr, const uint8_t *bytes)
00137 {
00138     for (int i = 0; i < NSAPI_IPv6_BYTES/2; i++) {
00139         sprintf(&addr[5*i], "%02x%02x", bytes[2*i], bytes[2*i+1]);
00140         addr[5*i+4] = ':';
00141     }
00142     addr[NSAPI_IPv6_SIZE-1] = '\0';
00143 }
00144 
00145 
00146 SocketAddress::SocketAddress(nsapi_addr_t addr, uint16_t port)
00147 {
00148     _ip_address[0] = '\0';
00149     set_addr(addr);
00150     set_port(port);
00151 }
00152 
00153 SocketAddress::SocketAddress(const char *addr, uint16_t port)
00154 {
00155     _ip_address[0] = '\0';
00156     set_ip_address(addr);
00157     set_port(port);
00158 }
00159 
00160 SocketAddress::SocketAddress(const void *bytes, nsapi_version_t version, uint16_t port)
00161 {
00162     _ip_address[0] = '\0';
00163     set_ip_bytes(bytes, version);
00164     set_port(port);
00165 }
00166 
00167 SocketAddress::SocketAddress(const SocketAddress &addr)
00168 {
00169     _ip_address[0] = '\0';
00170     set_addr(addr.get_addr());
00171     set_port(addr.get_port());
00172 }
00173 
00174 void SocketAddress::set_ip_address(const char *addr)
00175 {
00176     _ip_address[0] = '\0';
00177 
00178     if (addr && ipv4_is_valid(addr)) {
00179         _addr.version = NSAPI_IPv4;
00180         ipv4_from_address(_addr.bytes, addr);
00181     } else if (addr && ipv6_is_valid(addr)) {
00182         _addr.version = NSAPI_IPv6;
00183         ipv6_from_address(_addr.bytes, addr);
00184     } else {
00185         _addr = nsapi_addr_t();
00186     }
00187 }
00188 
00189 void SocketAddress::set_ip_bytes(const void *bytes, nsapi_version_t version)
00190 {
00191     nsapi_addr_t addr;
00192     addr.version = version;
00193     memcpy(addr.bytes, bytes, NSAPI_IP_BYTES);
00194     set_addr(addr);
00195 }
00196 
00197 void SocketAddress::set_addr(nsapi_addr_t addr)
00198 {
00199     _ip_address[0] = '\0';
00200     _addr = addr;
00201 }
00202 
00203 void SocketAddress::set_port(uint16_t port)
00204 {
00205     _port = port;
00206 }
00207 
00208 const char *SocketAddress::get_ip_address() const
00209 {
00210     char *ip_address = (char *)_ip_address;
00211 
00212     if (!ip_address[0]) {
00213         if (_addr.version == NSAPI_IPv4) {
00214             ipv4_to_address(ip_address, _addr.bytes);
00215         } else if (_addr.version == NSAPI_IPv6) {
00216             ipv6_to_address(ip_address, _addr.bytes);
00217         }
00218     }
00219 
00220     return ip_address;
00221 }
00222 
00223 const void *SocketAddress::get_ip_bytes() const
00224 {
00225     return _addr.bytes;
00226 }
00227 
00228 nsapi_version_t SocketAddress::get_ip_version() const
00229 {
00230     return _addr.version;
00231 }
00232 
00233 nsapi_addr_t SocketAddress::get_addr() const
00234 {
00235     return _addr;
00236 }
00237 
00238 uint16_t SocketAddress::get_port() const
00239 {
00240     return _port;
00241 }
00242 
00243 SocketAddress::operator bool() const
00244 {
00245     int count = 0;
00246     if (_addr.version == NSAPI_IPv4) {
00247         count = NSAPI_IPv4_BYTES;
00248     } else if (_addr.version == NSAPI_IPv6) {
00249         count = NSAPI_IPv6_BYTES;
00250     }
00251 
00252     for (int i = 0; i < count; i++) {
00253         if (_addr.bytes[i]) {
00254             return true;
00255         }
00256     }
00257 
00258     return false;
00259 }
00260 
00261 void SocketAddress::_SocketAddress(NetworkStack *iface, const char *host, uint16_t port)
00262 {
00263     _ip_address[0] = '\0';
00264 
00265     // Check for valid IP addresses
00266     if (host && ipv4_is_valid(host)) {
00267         _addr.version = NSAPI_IPv4;
00268         ipv4_from_address(_addr.bytes, host);
00269         _port = port;
00270     } else if (host && ipv6_is_valid(host)) {
00271         _addr.version = NSAPI_IPv6;
00272         ipv6_from_address(_addr.bytes, host);
00273         _port = port;
00274     } else {
00275         // DNS lookup
00276         int err = iface->gethostbyname(this, host);
00277         _port = port;
00278         if (err) {
00279             _addr = nsapi_addr_t();
00280             _port = 0;
00281         }
00282     }
00283 }