Entrega 3er corte - sistemas embebidos

Committer:
Bethory
Date:
Wed May 30 04:46:28 2018 +0000
Revision:
1:fcdb45ee95b9
Parent:
0:6ad07c9019fd
Entrega Final

Who changed what in which revision?

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