Includes library modifications to allow access to AIN_4 (AIN_0 / 5)

Committer:
bryantaylor
Date:
Tue Sep 20 21:26:12 2016 +0000
Revision:
0:eafc3fd41f75
hackathon

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bryantaylor 0:eafc3fd41f75 1 /* Socket
bryantaylor 0:eafc3fd41f75 2 * Copyright (c) 2015 ARM Limited
bryantaylor 0:eafc3fd41f75 3 *
bryantaylor 0:eafc3fd41f75 4 * Licensed under the Apache License, Version 2.0 (the "License");
bryantaylor 0:eafc3fd41f75 5 * you may not use this file except in compliance with the License.
bryantaylor 0:eafc3fd41f75 6 * You may obtain a copy of the License at
bryantaylor 0:eafc3fd41f75 7 *
bryantaylor 0:eafc3fd41f75 8 * http://www.apache.org/licenses/LICENSE-2.0
bryantaylor 0:eafc3fd41f75 9 *
bryantaylor 0:eafc3fd41f75 10 * Unless required by applicable law or agreed to in writing, software
bryantaylor 0:eafc3fd41f75 11 * distributed under the License is distributed on an "AS IS" BASIS,
bryantaylor 0:eafc3fd41f75 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
bryantaylor 0:eafc3fd41f75 13 * See the License for the specific language governing permissions and
bryantaylor 0:eafc3fd41f75 14 * limitations under the License.
bryantaylor 0:eafc3fd41f75 15 */
bryantaylor 0:eafc3fd41f75 16
bryantaylor 0:eafc3fd41f75 17 #include "SocketAddress.h"
bryantaylor 0:eafc3fd41f75 18 #include "NetworkInterface.h"
bryantaylor 0:eafc3fd41f75 19 #include "NetworkStack.h"
bryantaylor 0:eafc3fd41f75 20 #include <string.h>
bryantaylor 0:eafc3fd41f75 21 #include "mbed.h"
bryantaylor 0:eafc3fd41f75 22
bryantaylor 0:eafc3fd41f75 23
bryantaylor 0:eafc3fd41f75 24 static bool ipv4_is_valid(const char *addr)
bryantaylor 0:eafc3fd41f75 25 {
bryantaylor 0:eafc3fd41f75 26 int i = 0;
bryantaylor 0:eafc3fd41f75 27
bryantaylor 0:eafc3fd41f75 28 // Check each digit for [0-9.]
bryantaylor 0:eafc3fd41f75 29 for (; addr[i]; i++) {
bryantaylor 0:eafc3fd41f75 30 if (!(addr[i] >= '0' && addr[i] <= '9') && addr[i] != '.') {
bryantaylor 0:eafc3fd41f75 31 return false;
bryantaylor 0:eafc3fd41f75 32 }
bryantaylor 0:eafc3fd41f75 33 }
bryantaylor 0:eafc3fd41f75 34
bryantaylor 0:eafc3fd41f75 35 // Ending with '.' garuntees host
bryantaylor 0:eafc3fd41f75 36 if (i > 0 && addr[i-1] == '.') {
bryantaylor 0:eafc3fd41f75 37 return false;
bryantaylor 0:eafc3fd41f75 38 }
bryantaylor 0:eafc3fd41f75 39
bryantaylor 0:eafc3fd41f75 40 return true;
bryantaylor 0:eafc3fd41f75 41 }
bryantaylor 0:eafc3fd41f75 42
bryantaylor 0:eafc3fd41f75 43 static bool ipv6_is_valid(const char *addr)
bryantaylor 0:eafc3fd41f75 44 {
bryantaylor 0:eafc3fd41f75 45 // Check each digit for [0-9a-fA-F:]
bryantaylor 0:eafc3fd41f75 46 for (int i = 0; addr[i]; i++) {
bryantaylor 0:eafc3fd41f75 47 if (!(addr[i] >= '0' && addr[i] <= '9') &&
bryantaylor 0:eafc3fd41f75 48 !(addr[i] >= 'a' && addr[i] <= 'f') &&
bryantaylor 0:eafc3fd41f75 49 !(addr[i] >= 'A' && addr[i] <= 'F') &&
bryantaylor 0:eafc3fd41f75 50 addr[i] != ':') {
bryantaylor 0:eafc3fd41f75 51 return false;
bryantaylor 0:eafc3fd41f75 52 }
bryantaylor 0:eafc3fd41f75 53 }
bryantaylor 0:eafc3fd41f75 54
bryantaylor 0:eafc3fd41f75 55 return true;
bryantaylor 0:eafc3fd41f75 56 }
bryantaylor 0:eafc3fd41f75 57
bryantaylor 0:eafc3fd41f75 58 static void ipv4_from_address(uint8_t *bytes, const char *addr)
bryantaylor 0:eafc3fd41f75 59 {
bryantaylor 0:eafc3fd41f75 60 int count = 0;
bryantaylor 0:eafc3fd41f75 61 int i = 0;
bryantaylor 0:eafc3fd41f75 62
bryantaylor 0:eafc3fd41f75 63 for (; count < NSAPI_IPv4_BYTES; count++) {
bryantaylor 0:eafc3fd41f75 64 int scanned = sscanf(&addr[i], "%hhu", &bytes[count]);
bryantaylor 0:eafc3fd41f75 65 if (scanned < 1) {
bryantaylor 0:eafc3fd41f75 66 return;
bryantaylor 0:eafc3fd41f75 67 }
bryantaylor 0:eafc3fd41f75 68
bryantaylor 0:eafc3fd41f75 69 for (; addr[i] != '.'; i++) {
bryantaylor 0:eafc3fd41f75 70 if (!addr[i]) {
bryantaylor 0:eafc3fd41f75 71 return;
bryantaylor 0:eafc3fd41f75 72 }
bryantaylor 0:eafc3fd41f75 73 }
bryantaylor 0:eafc3fd41f75 74
bryantaylor 0:eafc3fd41f75 75 i++;
bryantaylor 0:eafc3fd41f75 76 }
bryantaylor 0:eafc3fd41f75 77 }
bryantaylor 0:eafc3fd41f75 78
bryantaylor 0:eafc3fd41f75 79 static int ipv6_scan_chunk(uint16_t *shorts, const char *chunk) {
bryantaylor 0:eafc3fd41f75 80 int count = 0;
bryantaylor 0:eafc3fd41f75 81 int i = 0;
bryantaylor 0:eafc3fd41f75 82
bryantaylor 0:eafc3fd41f75 83 for (; count < NSAPI_IPv6_BYTES/2; count++) {
bryantaylor 0:eafc3fd41f75 84 int scanned = sscanf(&chunk[i], "%hx", &shorts[count]);
bryantaylor 0:eafc3fd41f75 85 if (scanned < 1) {
bryantaylor 0:eafc3fd41f75 86 return count;
bryantaylor 0:eafc3fd41f75 87 }
bryantaylor 0:eafc3fd41f75 88
bryantaylor 0:eafc3fd41f75 89 for (; chunk[i] != ':'; i++) {
bryantaylor 0:eafc3fd41f75 90 if (!chunk[i]) {
bryantaylor 0:eafc3fd41f75 91 return count+1;
bryantaylor 0:eafc3fd41f75 92 }
bryantaylor 0:eafc3fd41f75 93 }
bryantaylor 0:eafc3fd41f75 94
bryantaylor 0:eafc3fd41f75 95 i++;
bryantaylor 0:eafc3fd41f75 96 }
bryantaylor 0:eafc3fd41f75 97
bryantaylor 0:eafc3fd41f75 98 return count;
bryantaylor 0:eafc3fd41f75 99 }
bryantaylor 0:eafc3fd41f75 100
bryantaylor 0:eafc3fd41f75 101 static void ipv6_from_address(uint8_t *bytes, const char *addr)
bryantaylor 0:eafc3fd41f75 102 {
bryantaylor 0:eafc3fd41f75 103 // Start with zeroed address
bryantaylor 0:eafc3fd41f75 104 uint16_t shorts[NSAPI_IPv6_BYTES/2];
bryantaylor 0:eafc3fd41f75 105 memset(shorts, 0, sizeof shorts);
bryantaylor 0:eafc3fd41f75 106
bryantaylor 0:eafc3fd41f75 107 int suffix = 0;
bryantaylor 0:eafc3fd41f75 108
bryantaylor 0:eafc3fd41f75 109 // Find double colons and scan suffix
bryantaylor 0:eafc3fd41f75 110 for (int i = 0; addr[i]; i++) {
bryantaylor 0:eafc3fd41f75 111 if (addr[i] == ':' && addr[i+1] == ':') {
bryantaylor 0:eafc3fd41f75 112 suffix = ipv6_scan_chunk(shorts, &addr[i+2]);
bryantaylor 0:eafc3fd41f75 113 break;
bryantaylor 0:eafc3fd41f75 114 }
bryantaylor 0:eafc3fd41f75 115 }
bryantaylor 0:eafc3fd41f75 116
bryantaylor 0:eafc3fd41f75 117 // Move suffix to end
bryantaylor 0:eafc3fd41f75 118 memmove(&shorts[NSAPI_IPv6_BYTES/2-suffix], &shorts[0],
bryantaylor 0:eafc3fd41f75 119 suffix*sizeof(uint16_t));
bryantaylor 0:eafc3fd41f75 120
bryantaylor 0:eafc3fd41f75 121 // Scan prefix
bryantaylor 0:eafc3fd41f75 122 ipv6_scan_chunk(shorts, &addr[0]);
bryantaylor 0:eafc3fd41f75 123
bryantaylor 0:eafc3fd41f75 124 // Flip bytes
bryantaylor 0:eafc3fd41f75 125 for (int i = 0; i < NSAPI_IPv6_BYTES/2; i++) {
bryantaylor 0:eafc3fd41f75 126 bytes[2*i+0] = (uint8_t)(shorts[i] >> 8);
bryantaylor 0:eafc3fd41f75 127 bytes[2*i+1] = (uint8_t)(shorts[i] >> 0);
bryantaylor 0:eafc3fd41f75 128 }
bryantaylor 0:eafc3fd41f75 129 }
bryantaylor 0:eafc3fd41f75 130
bryantaylor 0:eafc3fd41f75 131 static void ipv4_to_address(char *addr, const uint8_t *bytes)
bryantaylor 0:eafc3fd41f75 132 {
bryantaylor 0:eafc3fd41f75 133 sprintf(addr, "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]);
bryantaylor 0:eafc3fd41f75 134 }
bryantaylor 0:eafc3fd41f75 135
bryantaylor 0:eafc3fd41f75 136 static void ipv6_to_address(char *addr, const uint8_t *bytes)
bryantaylor 0:eafc3fd41f75 137 {
bryantaylor 0:eafc3fd41f75 138 for (int i = 0; i < NSAPI_IPv6_BYTES/2; i++) {
bryantaylor 0:eafc3fd41f75 139 sprintf(&addr[5*i], "%02x%02x", bytes[2*i], bytes[2*i+1]);
bryantaylor 0:eafc3fd41f75 140 addr[5*i+4] = ':';
bryantaylor 0:eafc3fd41f75 141 }
bryantaylor 0:eafc3fd41f75 142 addr[NSAPI_IPv6_SIZE-1] = '\0';
bryantaylor 0:eafc3fd41f75 143 }
bryantaylor 0:eafc3fd41f75 144
bryantaylor 0:eafc3fd41f75 145
bryantaylor 0:eafc3fd41f75 146 SocketAddress::SocketAddress(nsapi_addr_t addr, uint16_t port)
bryantaylor 0:eafc3fd41f75 147 {
bryantaylor 0:eafc3fd41f75 148 _ip_address[0] = '\0';
bryantaylor 0:eafc3fd41f75 149 set_addr(addr);
bryantaylor 0:eafc3fd41f75 150 set_port(port);
bryantaylor 0:eafc3fd41f75 151 }
bryantaylor 0:eafc3fd41f75 152
bryantaylor 0:eafc3fd41f75 153 SocketAddress::SocketAddress(const char *addr, uint16_t port)
bryantaylor 0:eafc3fd41f75 154 {
bryantaylor 0:eafc3fd41f75 155 _ip_address[0] = '\0';
bryantaylor 0:eafc3fd41f75 156 set_ip_address(addr);
bryantaylor 0:eafc3fd41f75 157 set_port(port);
bryantaylor 0:eafc3fd41f75 158 }
bryantaylor 0:eafc3fd41f75 159
bryantaylor 0:eafc3fd41f75 160 SocketAddress::SocketAddress(const void *bytes, nsapi_version_t version, uint16_t port)
bryantaylor 0:eafc3fd41f75 161 {
bryantaylor 0:eafc3fd41f75 162 _ip_address[0] = '\0';
bryantaylor 0:eafc3fd41f75 163 set_ip_bytes(bytes, version);
bryantaylor 0:eafc3fd41f75 164 set_port(port);
bryantaylor 0:eafc3fd41f75 165 }
bryantaylor 0:eafc3fd41f75 166
bryantaylor 0:eafc3fd41f75 167 SocketAddress::SocketAddress(const SocketAddress &addr)
bryantaylor 0:eafc3fd41f75 168 {
bryantaylor 0:eafc3fd41f75 169 _ip_address[0] = '\0';
bryantaylor 0:eafc3fd41f75 170 set_addr(addr.get_addr());
bryantaylor 0:eafc3fd41f75 171 set_port(addr.get_port());
bryantaylor 0:eafc3fd41f75 172 }
bryantaylor 0:eafc3fd41f75 173
bryantaylor 0:eafc3fd41f75 174 void SocketAddress::set_ip_address(const char *addr)
bryantaylor 0:eafc3fd41f75 175 {
bryantaylor 0:eafc3fd41f75 176 _ip_address[0] = '\0';
bryantaylor 0:eafc3fd41f75 177
bryantaylor 0:eafc3fd41f75 178 if (addr && ipv4_is_valid(addr)) {
bryantaylor 0:eafc3fd41f75 179 _addr.version = NSAPI_IPv4;
bryantaylor 0:eafc3fd41f75 180 ipv4_from_address(_addr.bytes, addr);
bryantaylor 0:eafc3fd41f75 181 } else if (addr && ipv6_is_valid(addr)) {
bryantaylor 0:eafc3fd41f75 182 _addr.version = NSAPI_IPv6;
bryantaylor 0:eafc3fd41f75 183 ipv6_from_address(_addr.bytes, addr);
bryantaylor 0:eafc3fd41f75 184 } else {
bryantaylor 0:eafc3fd41f75 185 _addr = nsapi_addr_t();
bryantaylor 0:eafc3fd41f75 186 }
bryantaylor 0:eafc3fd41f75 187 }
bryantaylor 0:eafc3fd41f75 188
bryantaylor 0:eafc3fd41f75 189 void SocketAddress::set_ip_bytes(const void *bytes, nsapi_version_t version)
bryantaylor 0:eafc3fd41f75 190 {
bryantaylor 0:eafc3fd41f75 191 nsapi_addr_t addr;
bryantaylor 0:eafc3fd41f75 192 addr.version = version;
bryantaylor 0:eafc3fd41f75 193 memcpy(addr.bytes, bytes, NSAPI_IP_BYTES);
bryantaylor 0:eafc3fd41f75 194 set_addr(addr);
bryantaylor 0:eafc3fd41f75 195 }
bryantaylor 0:eafc3fd41f75 196
bryantaylor 0:eafc3fd41f75 197 void SocketAddress::set_addr(nsapi_addr_t addr)
bryantaylor 0:eafc3fd41f75 198 {
bryantaylor 0:eafc3fd41f75 199 _ip_address[0] = '\0';
bryantaylor 0:eafc3fd41f75 200 _addr = addr;
bryantaylor 0:eafc3fd41f75 201 }
bryantaylor 0:eafc3fd41f75 202
bryantaylor 0:eafc3fd41f75 203 void SocketAddress::set_port(uint16_t port)
bryantaylor 0:eafc3fd41f75 204 {
bryantaylor 0:eafc3fd41f75 205 _port = port;
bryantaylor 0:eafc3fd41f75 206 }
bryantaylor 0:eafc3fd41f75 207
bryantaylor 0:eafc3fd41f75 208 const char *SocketAddress::get_ip_address() const
bryantaylor 0:eafc3fd41f75 209 {
bryantaylor 0:eafc3fd41f75 210 char *ip_address = (char *)_ip_address;
bryantaylor 0:eafc3fd41f75 211
bryantaylor 0:eafc3fd41f75 212 if (!ip_address[0]) {
bryantaylor 0:eafc3fd41f75 213 if (_addr.version == NSAPI_IPv4) {
bryantaylor 0:eafc3fd41f75 214 ipv4_to_address(ip_address, _addr.bytes);
bryantaylor 0:eafc3fd41f75 215 } else if (_addr.version == NSAPI_IPv6) {
bryantaylor 0:eafc3fd41f75 216 ipv6_to_address(ip_address, _addr.bytes);
bryantaylor 0:eafc3fd41f75 217 }
bryantaylor 0:eafc3fd41f75 218 }
bryantaylor 0:eafc3fd41f75 219
bryantaylor 0:eafc3fd41f75 220 return ip_address;
bryantaylor 0:eafc3fd41f75 221 }
bryantaylor 0:eafc3fd41f75 222
bryantaylor 0:eafc3fd41f75 223 const void *SocketAddress::get_ip_bytes() const
bryantaylor 0:eafc3fd41f75 224 {
bryantaylor 0:eafc3fd41f75 225 return _addr.bytes;
bryantaylor 0:eafc3fd41f75 226 }
bryantaylor 0:eafc3fd41f75 227
bryantaylor 0:eafc3fd41f75 228 nsapi_version_t SocketAddress::get_ip_version() const
bryantaylor 0:eafc3fd41f75 229 {
bryantaylor 0:eafc3fd41f75 230 return _addr.version;
bryantaylor 0:eafc3fd41f75 231 }
bryantaylor 0:eafc3fd41f75 232
bryantaylor 0:eafc3fd41f75 233 nsapi_addr_t SocketAddress::get_addr() const
bryantaylor 0:eafc3fd41f75 234 {
bryantaylor 0:eafc3fd41f75 235 return _addr;
bryantaylor 0:eafc3fd41f75 236 }
bryantaylor 0:eafc3fd41f75 237
bryantaylor 0:eafc3fd41f75 238 uint16_t SocketAddress::get_port() const
bryantaylor 0:eafc3fd41f75 239 {
bryantaylor 0:eafc3fd41f75 240 return _port;
bryantaylor 0:eafc3fd41f75 241 }
bryantaylor 0:eafc3fd41f75 242
bryantaylor 0:eafc3fd41f75 243 SocketAddress::operator bool() const
bryantaylor 0:eafc3fd41f75 244 {
bryantaylor 0:eafc3fd41f75 245 int count = 0;
bryantaylor 0:eafc3fd41f75 246 if (_addr.version == NSAPI_IPv4) {
bryantaylor 0:eafc3fd41f75 247 count = NSAPI_IPv4_BYTES;
bryantaylor 0:eafc3fd41f75 248 } else if (_addr.version == NSAPI_IPv6) {
bryantaylor 0:eafc3fd41f75 249 count = NSAPI_IPv6_BYTES;
bryantaylor 0:eafc3fd41f75 250 }
bryantaylor 0:eafc3fd41f75 251
bryantaylor 0:eafc3fd41f75 252 for (int i = 0; i < count; i++) {
bryantaylor 0:eafc3fd41f75 253 if (_addr.bytes[i]) {
bryantaylor 0:eafc3fd41f75 254 return true;
bryantaylor 0:eafc3fd41f75 255 }
bryantaylor 0:eafc3fd41f75 256 }
bryantaylor 0:eafc3fd41f75 257
bryantaylor 0:eafc3fd41f75 258 return false;
bryantaylor 0:eafc3fd41f75 259 }
bryantaylor 0:eafc3fd41f75 260
bryantaylor 0:eafc3fd41f75 261 void SocketAddress::_SocketAddress(NetworkStack *iface, const char *host, uint16_t port)
bryantaylor 0:eafc3fd41f75 262 {
bryantaylor 0:eafc3fd41f75 263 _ip_address[0] = '\0';
bryantaylor 0:eafc3fd41f75 264
bryantaylor 0:eafc3fd41f75 265 // Check for valid IP addresses
bryantaylor 0:eafc3fd41f75 266 if (host && ipv4_is_valid(host)) {
bryantaylor 0:eafc3fd41f75 267 _addr.version = NSAPI_IPv4;
bryantaylor 0:eafc3fd41f75 268 ipv4_from_address(_addr.bytes, host);
bryantaylor 0:eafc3fd41f75 269 _port = port;
bryantaylor 0:eafc3fd41f75 270 } else if (host && ipv6_is_valid(host)) {
bryantaylor 0:eafc3fd41f75 271 _addr.version = NSAPI_IPv6;
bryantaylor 0:eafc3fd41f75 272 ipv6_from_address(_addr.bytes, host);
bryantaylor 0:eafc3fd41f75 273 _port = port;
bryantaylor 0:eafc3fd41f75 274 } else {
bryantaylor 0:eafc3fd41f75 275 // DNS lookup
bryantaylor 0:eafc3fd41f75 276 int err = iface->gethostbyname(this, host);
bryantaylor 0:eafc3fd41f75 277 _port = port;
bryantaylor 0:eafc3fd41f75 278 if (err) {
bryantaylor 0:eafc3fd41f75 279 _addr = nsapi_addr_t();
bryantaylor 0:eafc3fd41f75 280 _port = 0;
bryantaylor 0:eafc3fd41f75 281 }
bryantaylor 0:eafc3fd41f75 282 }
bryantaylor 0:eafc3fd41f75 283 }