Preliminary main mbed library for nexpaq development

Committer:
nexpaq
Date:
Fri Nov 04 20:27:58 2016 +0000
Revision:
0:6c56fb4bc5f0
Moving to library for sharing updates

Who changed what in which revision?

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