BBR 1 Ebene

Committer:
borlanic
Date:
Mon May 14 11:29:06 2018 +0000
Revision:
0:fbdae7e6d805
BBR

Who changed what in which revision?

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