mbed-os

Fork of mbed-os by erkin yucel

Committer:
elessair
Date:
Sun Oct 23 15:10:02 2016 +0000
Revision:
0:f269e3021894
Initial commit

Who changed what in which revision?

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