Base class for IP Based Networking Libraries

Dependencies:   DnsQuery

Dependents:   TempTower BSDInterfaceTests HelloBSDInterface ESP8266InterfaceTests ... more

For a complete getting started guide see the wiki...

Network Socket API

The Network Socket API provides a common interface for using sockets on network devices. The API provides a simple class-based interface that should be familiar to users experienced with other socket APIs. Additionally, the API provides a simple interface for implementing network devices, making it easy to connect hardware agnostic programs to new devices.

Network Interfaces

The NetworkInterface provides an abstract class for network devices that support sockets. Devices should provide a DeviceInterface class that inherits this interface and adds implementation specific methods for using the device. A NetworkInterface must be provided to a Socket constructor to open a socket on the interface. Currently two subclasses are defined for common devices, EthernetInterface and WiFiInterface.

Sockets

The Socket class is used for managing network sockets. Once opened, the socket provides a pipe through which data can sent and recieved to a specific endpoint. The socket class can be instantiated as either a TCPSocket or a UDPSocket which defines the protocol used for the connection.

Committer:
Christopher Haster
Date:
Tue Apr 19 18:25:23 2016 -0500
Revision:
100:90d8f662de83
Parent:
97:68232387bc75
Child:
105:2fd212f8da61
Added support for shortened form ipv6 addresses

supported:
1.2.3.4
1:2:3:4:5:6:7:8
1:2::7:8
::

currently not supported:
1:2:3:4:5:6:1.2.3.4

Who changed what in which revision?

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