Klika Tech / Mbed 2 deprecated Nucleo-AWS-IoT-mbed

Dependencies:   X_NUCLEO_IKS01A1 mbed FP MQTTPacket DnsQuery ATParser

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 "NetworkStack.h"
00019 #include <string.h>
00020 #include "mbed.h"
00021 
00022 
00023 static bool ipv4_is_valid(const char *addr)
00024 {
00025     int i = 0;
00026 
00027     // Check each digit for [0-9.]
00028     for (; addr[i]; i++) {
00029         if (!(addr[i] >= '0' && addr[i] <= '9') && addr[i] != '.') {
00030             return false;
00031         }
00032     }
00033 
00034     // Ending with '.' garuntees host
00035     if (i > 0 && addr[i-1] == '.') {
00036         return false;
00037     }
00038 
00039     return true;
00040 }
00041 
00042 static bool ipv6_is_valid(const char *addr)
00043 {
00044     // Check each digit for [0-9a-fA-F:]
00045     for (int i = 0; addr[i]; i++) {
00046         if (!(addr[i] >= '0' && addr[i] <= '9') &&
00047             !(addr[i] >= 'a' && addr[i] <= 'f') &&
00048             !(addr[i] >= 'A' && addr[i] <= 'F') &&
00049             addr[i] != ':') {
00050             return false;
00051         }
00052     }
00053 
00054     return true;
00055 }
00056 
00057 static void ipv4_from_address(uint8_t *bytes, const char *addr)
00058 {
00059     int count = 0;
00060     int i = 0;
00061 
00062     for (; count < NSAPI_IPv4_BYTES; count++) {
00063         int scanned = sscanf(&addr[i], "%hhu", &bytes[count]);
00064         if (scanned < 1) {
00065             return;
00066         }
00067 
00068         for (; addr[i] != '.'; i++) {
00069             if (!addr[i]) {
00070                 return;
00071             }
00072         }
00073 
00074         i++;
00075     }
00076 }
00077 
00078 static int ipv6_scan_chunk(uint16_t *shorts, const char *chunk) {
00079     int count = 0;
00080     int i = 0;
00081 
00082     for (; count < NSAPI_IPv6_BYTES/2; count++) {
00083         int scanned = sscanf(&chunk[i], "%hx", &shorts[count]);
00084         if (scanned < 1) {
00085             return count;
00086         }
00087 
00088         for (; chunk[i] != ':'; i++) {
00089             if (!chunk[i]) {
00090                 return count+1;
00091             }
00092         }
00093 
00094         i++;
00095     }
00096 
00097     return count;
00098 }
00099 
00100 static void ipv6_from_address(uint8_t *bytes, const char *addr)
00101 {
00102     // Start with zeroed address
00103     uint16_t shorts[NSAPI_IPv6_BYTES/2];
00104     memset(shorts, 0, sizeof shorts);
00105 
00106     int suffix = 0;
00107 
00108     // Find double colons and scan suffix
00109     for (int i = 0; addr[i]; i++) {
00110         if (addr[i] == ':' && addr[i+1] == ':') {
00111             suffix = ipv6_scan_chunk(shorts, &addr[i+2]);
00112             break;
00113         }
00114     }
00115 
00116     // Move suffix to end
00117     memmove(&shorts[NSAPI_IPv6_BYTES/2-suffix], &shorts[0],
00118             suffix*sizeof(uint16_t));
00119 
00120     // Scan prefix
00121     ipv6_scan_chunk(shorts, &addr[0]);
00122 
00123     // Flip bytes
00124     for (int i = 0; i < NSAPI_IPv6_BYTES/2; i++) {
00125         bytes[2*i+0] = (uint8_t)(shorts[i] >> 8);
00126         bytes[2*i+1] = (uint8_t)(shorts[i] >> 0);
00127     }
00128 }
00129 
00130 static void ipv4_to_address(char *addr, const uint8_t *bytes)
00131 {
00132     sprintf(addr, "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]);
00133 }
00134 
00135 static void ipv6_to_address(char *addr, const uint8_t *bytes)
00136 {
00137     for (int i = 0; i < NSAPI_IPv6_BYTES/2; i++) {
00138         sprintf(&addr[5*i], "%02x%02x", bytes[2*i], bytes[2*i+1]);
00139         addr[5*i+4] = ':';
00140     }
00141     addr[NSAPI_IPv6_SIZE-1] = '\0';
00142 }
00143 
00144 
00145 SocketAddress::SocketAddress(NetworkStack *iface, const char *host, uint16_t port)
00146 {
00147     memset(&_ip_address, 0, sizeof _ip_address);
00148 
00149     // Check for valid IP addresses
00150     if (host && ipv4_is_valid(host)) {
00151         _ip_version = NSAPI_IPv4;
00152         ipv4_from_address(_ip_bytes, host);
00153         set_port(port);
00154     } else if (host && ipv6_is_valid(host)) {
00155         _ip_version = NSAPI_IPv6;
00156         ipv6_from_address(_ip_bytes, host);
00157         set_port(port);
00158     } else {
00159         // DNS lookup
00160         int err = iface->gethostbyname(this, host);
00161         if (!err) {
00162             set_port(port);
00163         } else {
00164             _ip_version = NSAPI_IPv4;
00165             memset(_ip_bytes, 0, NSAPI_IPv4_BYTES);
00166             set_port(0);
00167         }
00168     }
00169 }
00170 
00171 SocketAddress::SocketAddress(const char *addr, uint16_t port)
00172 {
00173     memset(&_ip_address, 0, sizeof _ip_address);
00174     set_ip_address(addr);
00175     set_port(port);
00176 }
00177 
00178 SocketAddress::SocketAddress(const void *bytes, nsapi_version_t version, uint16_t port)
00179 {
00180     memset(&_ip_address, 0, sizeof _ip_address);
00181     set_ip_bytes(bytes, version);
00182     set_port(port);
00183 }
00184 
00185 SocketAddress::SocketAddress(const SocketAddress &addr)
00186 {
00187     memset(&_ip_address, 0, sizeof _ip_address);
00188     set_ip_bytes(addr.get_ip_bytes(), addr.get_ip_version());
00189     set_port(addr.get_port());
00190 }
00191 
00192 void SocketAddress::set_ip_address(const char *addr)
00193 {
00194     _ip_address[0] = '\0';
00195 
00196     if (addr && ipv4_is_valid(addr)) {
00197         _ip_version = NSAPI_IPv4;
00198         ipv4_from_address(_ip_bytes, addr);
00199     } else if (addr && ipv6_is_valid(addr)) {
00200         _ip_version = NSAPI_IPv6;
00201         ipv6_from_address(_ip_bytes, addr);
00202     } else {
00203         _ip_version = NSAPI_IPv4;
00204         memset(_ip_bytes, 0, NSAPI_IPv4_BYTES);
00205     }
00206 }
00207 
00208 void SocketAddress::set_ip_bytes(const void *bytes, nsapi_version_t version)
00209 {
00210     _ip_address[0] = '\0';
00211 
00212     if (version == NSAPI_IPv4) {
00213         _ip_version = NSAPI_IPv4;
00214         memcpy(_ip_bytes, bytes, NSAPI_IPv4_BYTES);
00215     } else if (version == NSAPI_IPv6) {
00216         _ip_version = NSAPI_IPv6;
00217         memcpy(_ip_bytes, bytes, NSAPI_IPv6_BYTES);
00218     } else {
00219         _ip_version = NSAPI_IPv4;
00220         memset(_ip_bytes, 0, NSAPI_IPv4_BYTES);
00221     }
00222 }
00223 
00224 void SocketAddress::set_port(uint16_t port)
00225 {
00226     _port = port;
00227 }
00228 
00229 const char *SocketAddress::get_ip_address() const
00230 {
00231     char *ip_address = (char *)_ip_address;
00232 
00233     if (!ip_address[0]) {
00234         if (_ip_version == NSAPI_IPv4) {
00235             ipv4_to_address(ip_address, _ip_bytes);
00236         } else if (_ip_version == NSAPI_IPv6) {
00237             ipv6_to_address(ip_address, _ip_bytes);
00238         }
00239     }
00240 
00241     return ip_address;
00242 }
00243 
00244 const void *SocketAddress::get_ip_bytes() const
00245 {
00246     return _ip_bytes;
00247 }
00248 
00249 nsapi_version_t SocketAddress::get_ip_version() const
00250 {
00251     return _ip_version;
00252 }
00253 
00254 uint16_t SocketAddress::get_port() const
00255 {
00256     return _port;
00257 }
00258 
00259 SocketAddress::operator bool() const
00260 {
00261     int count = 0;
00262     if (_ip_version == NSAPI_IPv4) {
00263         count = NSAPI_IPv4_BYTES;
00264     } else if (_ip_version == NSAPI_IPv6) {
00265         count = NSAPI_IPv6_BYTES;
00266     }
00267 
00268     for (int i = 0; i < count; i++) {
00269         if (_ip_bytes[i]) {
00270             return true;
00271         }
00272     }
00273 
00274     return false;
00275 }