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:
dkato
Date:
Wed May 25 02:45:51 2016 +0000
Revision:
125:ea3a618e0818
Parent:
124:d2656a514a27
Fix the path of DnsQuery.lib

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 105:2fd212f8da61 18 #include "NetworkStack.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 111:df01ca3e89b3 59 int count = 0;
Christopher Haster 111:df01ca3e89b3 60 int i = 0;
Christopher Haster 111:df01ca3e89b3 61
Christopher Haster 111:df01ca3e89b3 62 for (; count < NSAPI_IPv4_BYTES; count++) {
Christopher Haster 111:df01ca3e89b3 63 int scanned = sscanf(&addr[i], "%hhu", &bytes[count]);
Christopher Haster 111:df01ca3e89b3 64 if (scanned < 1) {
Christopher Haster 111:df01ca3e89b3 65 return;
Christopher Haster 111:df01ca3e89b3 66 }
Christopher Haster 111:df01ca3e89b3 67
Christopher Haster 111:df01ca3e89b3 68 for (; addr[i] != '.'; i++) {
Christopher Haster 111:df01ca3e89b3 69 if (!addr[i]) {
Christopher Haster 111:df01ca3e89b3 70 return;
Christopher Haster 111:df01ca3e89b3 71 }
Christopher Haster 111:df01ca3e89b3 72 }
Christopher Haster 111:df01ca3e89b3 73
Christopher Haster 111:df01ca3e89b3 74 i++;
Christopher Haster 111:df01ca3e89b3 75 }
Christopher Haster 94:644df37bb05b 76 }
Christopher Haster 94:644df37bb05b 77
Christopher Haster 100:90d8f662de83 78 static int ipv6_scan_chunk(uint16_t *shorts, const char *chunk) {
Christopher Haster 100:90d8f662de83 79 int count = 0;
Christopher Haster 100:90d8f662de83 80 int i = 0;
Christopher Haster 100:90d8f662de83 81
Christopher Haster 100:90d8f662de83 82 for (; count < NSAPI_IPv6_BYTES/2; count++) {
Christopher Haster 100:90d8f662de83 83 int scanned = sscanf(&chunk[i], "%hx", &shorts[count]);
Christopher Haster 100:90d8f662de83 84 if (scanned < 1) {
Christopher Haster 100:90d8f662de83 85 return count;
Christopher Haster 100:90d8f662de83 86 }
Christopher Haster 100:90d8f662de83 87
Christopher Haster 100:90d8f662de83 88 for (; chunk[i] != ':'; i++) {
Christopher Haster 100:90d8f662de83 89 if (!chunk[i]) {
Christopher Haster 100:90d8f662de83 90 return count+1;
Christopher Haster 100:90d8f662de83 91 }
Christopher Haster 100:90d8f662de83 92 }
Christopher Haster 100:90d8f662de83 93
Christopher Haster 100:90d8f662de83 94 i++;
Christopher Haster 100:90d8f662de83 95 }
Christopher Haster 100:90d8f662de83 96
Christopher Haster 100:90d8f662de83 97 return count;
Christopher Haster 100:90d8f662de83 98 }
Christopher Haster 100:90d8f662de83 99
Christopher Haster 100:90d8f662de83 100 static void ipv6_from_address(uint8_t *bytes, const char *addr)
Christopher Haster 94:644df37bb05b 101 {
Christopher Haster 100:90d8f662de83 102 // Start with zeroed address
Christopher Haster 94:644df37bb05b 103 uint16_t shorts[NSAPI_IPv6_BYTES/2];
Christopher Haster 100:90d8f662de83 104 memset(shorts, 0, sizeof shorts);
Christopher Haster 100:90d8f662de83 105
Christopher Haster 100:90d8f662de83 106 int suffix = 0;
Christopher Haster 94:644df37bb05b 107
Christopher Haster 100:90d8f662de83 108 // Find double colons and scan suffix
Christopher Haster 100:90d8f662de83 109 for (int i = 0; addr[i]; i++) {
Christopher Haster 100:90d8f662de83 110 if (addr[i] == ':' && addr[i+1] == ':') {
Christopher Haster 100:90d8f662de83 111 suffix = ipv6_scan_chunk(shorts, &addr[i+2]);
Christopher Haster 100:90d8f662de83 112 break;
Christopher Haster 100:90d8f662de83 113 }
Christopher Haster 100:90d8f662de83 114 }
Christopher Haster 100:90d8f662de83 115
Christopher Haster 100:90d8f662de83 116 // Move suffix to end
Christopher Haster 100:90d8f662de83 117 memmove(&shorts[NSAPI_IPv6_BYTES/2-suffix], &shorts[0],
Christopher Haster 100:90d8f662de83 118 suffix*sizeof(uint16_t));
Christopher Haster 100:90d8f662de83 119
Christopher Haster 100:90d8f662de83 120 // Scan prefix
Christopher Haster 100:90d8f662de83 121 ipv6_scan_chunk(shorts, &addr[0]);
Christopher Haster 100:90d8f662de83 122
Christopher Haster 100:90d8f662de83 123 // Flip bytes
Christopher Haster 94:644df37bb05b 124 for (int i = 0; i < NSAPI_IPv6_BYTES/2; i++) {
Christopher Haster 94:644df37bb05b 125 bytes[2*i+0] = (uint8_t)(shorts[i] >> 8);
Christopher Haster 94:644df37bb05b 126 bytes[2*i+1] = (uint8_t)(shorts[i] >> 0);
Christopher Haster 94:644df37bb05b 127 }
Christopher Haster 94:644df37bb05b 128 }
Christopher Haster 94:644df37bb05b 129
Christopher Haster 94:644df37bb05b 130 static void ipv4_to_address(char *addr, const uint8_t *bytes)
Christopher Haster 94:644df37bb05b 131 {
Christopher Haster 94:644df37bb05b 132 sprintf(addr, "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]);
Christopher Haster 94:644df37bb05b 133 }
Christopher Haster 94:644df37bb05b 134
Christopher Haster 94:644df37bb05b 135 static void ipv6_to_address(char *addr, const uint8_t *bytes)
Christopher Haster 94:644df37bb05b 136 {
Christopher Haster 100:90d8f662de83 137 for (int i = 0; i < NSAPI_IPv6_BYTES/2; i++) {
Christopher Haster 100:90d8f662de83 138 sprintf(&addr[5*i], "%02x%02x", bytes[2*i], bytes[2*i+1]);
Christopher Haster 100:90d8f662de83 139 addr[5*i+4] = ':';
Christopher Haster 100:90d8f662de83 140 }
Christopher Haster 100:90d8f662de83 141 addr[NSAPI_IPv6_SIZE-1] = '\0';
Christopher Haster 100:90d8f662de83 142 }
Christopher Haster 97:68232387bc75 143
Christopher Haster 94:644df37bb05b 144
Christopher Haster 105:2fd212f8da61 145 SocketAddress::SocketAddress(NetworkStack *iface, const char *host, uint16_t port)
Christopher Haster 89:b1d417383c0d 146 {
Christopher Haster 120:6eb542426f15 147 memset(&_ip_address, 0, sizeof _ip_address);
Christopher Haster 120:6eb542426f15 148
Christopher Haster 94:644df37bb05b 149 // Check for valid IP addresses
Christopher Haster 100:90d8f662de83 150 if (host && ipv4_is_valid(host)) {
Christopher Haster 94:644df37bb05b 151 _ip_version = NSAPI_IPv4;
Christopher Haster 100:90d8f662de83 152 ipv4_from_address(_ip_bytes, host);
Christopher Haster 120:6eb542426f15 153 set_port(port);
Christopher Haster 100:90d8f662de83 154 } else if (host && ipv6_is_valid(host)) {
Christopher Haster 94:644df37bb05b 155 _ip_version = NSAPI_IPv6;
Christopher Haster 124:d2656a514a27 156 ipv6_from_address(_ip_bytes, host);
Christopher Haster 120:6eb542426f15 157 set_port(port);
Christopher Haster 94:644df37bb05b 158 } else {
Christopher Haster 94:644df37bb05b 159 // DNS lookup
Christopher Haster 95:b3c679f20d13 160 int err = iface->gethostbyname(this, host);
Christopher Haster 94:644df37bb05b 161 if (!err) {
Christopher Haster 94:644df37bb05b 162 set_port(port);
Christopher Haster 94:644df37bb05b 163 } else {
Christopher Haster 94:644df37bb05b 164 _ip_version = NSAPI_IPv4;
Christopher Haster 94:644df37bb05b 165 memset(_ip_bytes, 0, NSAPI_IPv4_BYTES);
Christopher Haster 94:644df37bb05b 166 set_port(0);
Christopher Haster 94:644df37bb05b 167 }
Christopher Haster 89:b1d417383c0d 168 }
Christopher Haster 89:b1d417383c0d 169 }
Christopher Haster 89:b1d417383c0d 170
Christopher Haster 89:b1d417383c0d 171 SocketAddress::SocketAddress(const char *addr, uint16_t port)
Christopher Haster 89:b1d417383c0d 172 {
Christopher Haster 120:6eb542426f15 173 memset(&_ip_address, 0, sizeof _ip_address);
Christopher Haster 89:b1d417383c0d 174 set_ip_address(addr);
Christopher Haster 89:b1d417383c0d 175 set_port(port);
Christopher Haster 89:b1d417383c0d 176 }
Christopher Haster 89:b1d417383c0d 177
Christopher Haster 94:644df37bb05b 178 SocketAddress::SocketAddress(const void *bytes, nsapi_version_t version, uint16_t port)
Christopher Haster 94:644df37bb05b 179 {
Christopher Haster 120:6eb542426f15 180 memset(&_ip_address, 0, sizeof _ip_address);
Christopher Haster 94:644df37bb05b 181 set_ip_bytes(bytes, version);
Christopher Haster 94:644df37bb05b 182 set_port(port);
Christopher Haster 94:644df37bb05b 183 }
Christopher Haster 94:644df37bb05b 184
Christopher Haster 89:b1d417383c0d 185 SocketAddress::SocketAddress(const SocketAddress &addr)
Christopher Haster 89:b1d417383c0d 186 {
Christopher Haster 120:6eb542426f15 187 memset(&_ip_address, 0, sizeof _ip_address);
Christopher Haster 94:644df37bb05b 188 set_ip_bytes(addr.get_ip_bytes(), addr.get_ip_version());
Christopher Haster 89:b1d417383c0d 189 set_port(addr.get_port());
Christopher Haster 89:b1d417383c0d 190 }
Christopher Haster 89:b1d417383c0d 191
Christopher Haster 89:b1d417383c0d 192 void SocketAddress::set_ip_address(const char *addr)
Christopher Haster 89:b1d417383c0d 193 {
Christopher Haster 94:644df37bb05b 194 _ip_address[0] = '\0';
Christopher Haster 94:644df37bb05b 195
Christopher Haster 100:90d8f662de83 196 if (addr && ipv4_is_valid(addr)) {
Christopher Haster 94:644df37bb05b 197 _ip_version = NSAPI_IPv4;
Christopher Haster 100:90d8f662de83 198 ipv4_from_address(_ip_bytes, addr);
Christopher Haster 100:90d8f662de83 199 } else if (addr && ipv6_is_valid(addr)) {
Christopher Haster 94:644df37bb05b 200 _ip_version = NSAPI_IPv6;
Christopher Haster 100:90d8f662de83 201 ipv6_from_address(_ip_bytes, addr);
Christopher Haster 94:644df37bb05b 202 } else {
Christopher Haster 94:644df37bb05b 203 _ip_version = NSAPI_IPv4;
Christopher Haster 94:644df37bb05b 204 memset(_ip_bytes, 0, NSAPI_IPv4_BYTES);
Christopher Haster 94:644df37bb05b 205 }
Christopher Haster 94:644df37bb05b 206 }
Christopher Haster 94:644df37bb05b 207
Christopher Haster 94:644df37bb05b 208 void SocketAddress::set_ip_bytes(const void *bytes, nsapi_version_t version)
Christopher Haster 94:644df37bb05b 209 {
Christopher Haster 94:644df37bb05b 210 _ip_address[0] = '\0';
Christopher Haster 94:644df37bb05b 211
Christopher Haster 122:b316a6631ef8 212 if (version == NSAPI_IPv4) {
Christopher Haster 94:644df37bb05b 213 _ip_version = NSAPI_IPv4;
Christopher Haster 94:644df37bb05b 214 memcpy(_ip_bytes, bytes, NSAPI_IPv4_BYTES);
Christopher Haster 122:b316a6631ef8 215 } else if (version == NSAPI_IPv6) {
Christopher Haster 94:644df37bb05b 216 _ip_version = NSAPI_IPv6;
Christopher Haster 94:644df37bb05b 217 memcpy(_ip_bytes, bytes, NSAPI_IPv6_BYTES);
Christopher Haster 94:644df37bb05b 218 } else {
Christopher Haster 94:644df37bb05b 219 _ip_version = NSAPI_IPv4;
Christopher Haster 94:644df37bb05b 220 memset(_ip_bytes, 0, NSAPI_IPv4_BYTES);
Christopher Haster 94:644df37bb05b 221 }
Christopher Haster 89:b1d417383c0d 222 }
Christopher Haster 89:b1d417383c0d 223
Christopher Haster 89:b1d417383c0d 224 void SocketAddress::set_port(uint16_t port)
Christopher Haster 89:b1d417383c0d 225 {
Christopher Haster 89:b1d417383c0d 226 _port = port;
Christopher Haster 89:b1d417383c0d 227 }
Christopher Haster 89:b1d417383c0d 228
Christopher Haster 89:b1d417383c0d 229 const char *SocketAddress::get_ip_address() const
Christopher Haster 89:b1d417383c0d 230 {
Christopher Haster 94:644df37bb05b 231 char *ip_address = (char *)_ip_address;
Christopher Haster 94:644df37bb05b 232
Christopher Haster 94:644df37bb05b 233 if (!ip_address[0]) {
Christopher Haster 94:644df37bb05b 234 if (_ip_version == NSAPI_IPv4) {
Christopher Haster 94:644df37bb05b 235 ipv4_to_address(ip_address, _ip_bytes);
Christopher Haster 97:68232387bc75 236 } else if (_ip_version == NSAPI_IPv6) {
Christopher Haster 94:644df37bb05b 237 ipv6_to_address(ip_address, _ip_bytes);
Christopher Haster 94:644df37bb05b 238 }
Christopher Haster 89:b1d417383c0d 239 }
Christopher Haster 94:644df37bb05b 240
Christopher Haster 94:644df37bb05b 241 return ip_address;
Christopher Haster 94:644df37bb05b 242 }
Christopher Haster 94:644df37bb05b 243
Christopher Haster 94:644df37bb05b 244 const void *SocketAddress::get_ip_bytes() const
Christopher Haster 94:644df37bb05b 245 {
Christopher Haster 94:644df37bb05b 246 return _ip_bytes;
Christopher Haster 94:644df37bb05b 247 }
Christopher Haster 94:644df37bb05b 248
Christopher Haster 94:644df37bb05b 249 nsapi_version_t SocketAddress::get_ip_version() const
Christopher Haster 94:644df37bb05b 250 {
Christopher Haster 94:644df37bb05b 251 return _ip_version;
Christopher Haster 89:b1d417383c0d 252 }
Christopher Haster 89:b1d417383c0d 253
Christopher Haster 89:b1d417383c0d 254 uint16_t SocketAddress::get_port() const
Christopher Haster 89:b1d417383c0d 255 {
Christopher Haster 89:b1d417383c0d 256 return _port;
Christopher Haster 89:b1d417383c0d 257 }
Christopher Haster 94:644df37bb05b 258
Christopher Haster 94:644df37bb05b 259 SocketAddress::operator bool() const
Christopher Haster 94:644df37bb05b 260 {
Christopher Haster 94:644df37bb05b 261 int count = 0;
Christopher Haster 94:644df37bb05b 262 if (_ip_version == NSAPI_IPv4) {
Christopher Haster 94:644df37bb05b 263 count = NSAPI_IPv4_BYTES;
Christopher Haster 94:644df37bb05b 264 } else if (_ip_version == NSAPI_IPv6) {
Christopher Haster 94:644df37bb05b 265 count = NSAPI_IPv6_BYTES;
Christopher Haster 94:644df37bb05b 266 }
Christopher Haster 94:644df37bb05b 267
Christopher Haster 94:644df37bb05b 268 for (int i = 0; i < count; i++) {
Christopher Haster 94:644df37bb05b 269 if (_ip_bytes[i]) {
Christopher Haster 94:644df37bb05b 270 return true;
Christopher Haster 94:644df37bb05b 271 }
Christopher Haster 94:644df37bb05b 272 }
Christopher Haster 94:644df37bb05b 273
Christopher Haster 94:644df37bb05b 274 return false;
Christopher Haster 94:644df37bb05b 275 }