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:23:58 2016 -0500
Revision:
94:644df37bb05b
Parent:
89:b1d417383c0d
Child:
95:b3c679f20d13
Added support for storing bytes directly in SocketAddress

Bytes are stored by default, however enough space is allocated in
a SocketAddress to generate the string representation if necessary.

Currently there is no support for shortened addresses

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 94:644df37bb05b 22 static bool address_is_ipv4(const char *addr)
Christopher Haster 94:644df37bb05b 23 {
Christopher Haster 94:644df37bb05b 24 int i = 0;
Christopher Haster 94:644df37bb05b 25
Christopher Haster 94:644df37bb05b 26 // Check each digit for [0-9.]
Christopher Haster 94:644df37bb05b 27 for (; addr[i]; i++) {
Christopher Haster 94:644df37bb05b 28 if (!(addr[i] >= '0' && addr[i] <= '9') && addr[i] != '.') {
Christopher Haster 94:644df37bb05b 29 return false;
Christopher Haster 94:644df37bb05b 30 }
Christopher Haster 94:644df37bb05b 31 }
Christopher Haster 94:644df37bb05b 32
Christopher Haster 94:644df37bb05b 33 // Ending with '.' garuntees host
Christopher Haster 94:644df37bb05b 34 if (i > 0 && addr[i-1] == '.') {
Christopher Haster 94:644df37bb05b 35 return false;
Christopher Haster 94:644df37bb05b 36 }
Christopher Haster 94:644df37bb05b 37
Christopher Haster 94:644df37bb05b 38 return true;
Christopher Haster 94:644df37bb05b 39 }
Christopher Haster 94:644df37bb05b 40
Christopher Haster 94:644df37bb05b 41 static bool address_is_ipv6(const char *addr)
Christopher Haster 94:644df37bb05b 42 {
Christopher Haster 94:644df37bb05b 43 // Check each digit for [0-9a-fA-F:]
Christopher Haster 94:644df37bb05b 44 for (int i = 0; addr[i]; i++) {
Christopher Haster 94:644df37bb05b 45 if (!(addr[i] >= '0' && addr[i] <= '9') &&
Christopher Haster 94:644df37bb05b 46 !(addr[i] >= 'a' && addr[i] <= 'f') &&
Christopher Haster 94:644df37bb05b 47 !(addr[i] >= 'A' && addr[i] <= 'F') &&
Christopher Haster 94:644df37bb05b 48 addr[i] != ':') {
Christopher Haster 94:644df37bb05b 49 return false;
Christopher Haster 94:644df37bb05b 50 }
Christopher Haster 94:644df37bb05b 51 }
Christopher Haster 94:644df37bb05b 52
Christopher Haster 94:644df37bb05b 53 return true;
Christopher Haster 94:644df37bb05b 54 }
Christopher Haster 94:644df37bb05b 55
Christopher Haster 94:644df37bb05b 56 static void address_to_ipv4(uint8_t *bytes, const char *addr)
Christopher Haster 94:644df37bb05b 57 {
Christopher Haster 94:644df37bb05b 58 sscanf(addr, "%hhd.%hhd.%hhd.%hhd", &bytes[0], &bytes[1], &bytes[2], &bytes[3]);
Christopher Haster 94:644df37bb05b 59 }
Christopher Haster 94:644df37bb05b 60
Christopher Haster 94:644df37bb05b 61 static void address_to_ipv6(uint8_t *bytes, const char *addr)
Christopher Haster 94:644df37bb05b 62 {
Christopher Haster 94:644df37bb05b 63 // TODO support short form (::1, 2001::ffee:100a)
Christopher Haster 94:644df37bb05b 64 // Use a more intellegent algorithm
Christopher Haster 94:644df37bb05b 65 uint16_t shorts[NSAPI_IPv6_BYTES/2];
Christopher Haster 94:644df37bb05b 66 sscanf(addr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
Christopher Haster 94:644df37bb05b 67 &shorts[0], &shorts[1], &shorts[2], &shorts[3],
Christopher Haster 94:644df37bb05b 68 &shorts[4], &shorts[5], &shorts[6], &shorts[7]);
Christopher Haster 94:644df37bb05b 69
Christopher Haster 94:644df37bb05b 70 for (int i = 0; i < NSAPI_IPv6_BYTES/2; i++) {
Christopher Haster 94:644df37bb05b 71 bytes[2*i+0] = (uint8_t)(shorts[i] >> 8);
Christopher Haster 94:644df37bb05b 72 bytes[2*i+1] = (uint8_t)(shorts[i] >> 0);
Christopher Haster 94:644df37bb05b 73 }
Christopher Haster 94:644df37bb05b 74 }
Christopher Haster 94:644df37bb05b 75
Christopher Haster 94:644df37bb05b 76 static void ipv4_to_address(char *addr, const uint8_t *bytes)
Christopher Haster 94:644df37bb05b 77 {
Christopher Haster 94:644df37bb05b 78 sprintf(addr, "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]);
Christopher Haster 94:644df37bb05b 79 }
Christopher Haster 94:644df37bb05b 80
Christopher Haster 94:644df37bb05b 81 static void ipv6_to_address(char *addr, const uint8_t *bytes)
Christopher Haster 94:644df37bb05b 82 {
Christopher Haster 94:644df37bb05b 83 for (int i = 0; i < NSAPI_IPv6_BYTES; i+=2) {
Christopher Haster 94:644df37bb05b 84 sprintf(&addr[5*i], "%02x%02x", bytes[i], bytes[i+1]);
Christopher Haster 94:644df37bb05b 85 addr[5*i+4] = ':';
Christopher Haster 94:644df37bb05b 86 }
Christopher Haster 94:644df37bb05b 87 addr[NSAPI_IPv6_BYTES-1] = '\0';
Christopher Haster 94:644df37bb05b 88 }
Christopher Haster 94:644df37bb05b 89
Christopher Haster 89:b1d417383c0d 90 SocketAddress::SocketAddress(NetworkInterface *iface, const char *host, uint16_t port)
Christopher Haster 89:b1d417383c0d 91 {
Christopher Haster 94:644df37bb05b 92 // Check for valid IP addresses
Christopher Haster 94:644df37bb05b 93 if (host && address_is_ipv4(host)) {
Christopher Haster 94:644df37bb05b 94 _ip_version = NSAPI_IPv4;
Christopher Haster 94:644df37bb05b 95 address_to_ipv4(_ip_bytes, host);
Christopher Haster 94:644df37bb05b 96 } else if (host && address_is_ipv6(host)) {
Christopher Haster 94:644df37bb05b 97 _ip_version = NSAPI_IPv6;
Christopher Haster 94:644df37bb05b 98 address_to_ipv4(_ip_bytes, host);
Christopher Haster 94:644df37bb05b 99 } else {
Christopher Haster 94:644df37bb05b 100 // DNS lookup
Christopher Haster 94:644df37bb05b 101 char addr[NSAPI_IP_SIZE];
Christopher Haster 94:644df37bb05b 102 int err = iface->gethostbyname(host, addr);
Christopher Haster 94:644df37bb05b 103 if (!err) {
Christopher Haster 94:644df37bb05b 104 set_ip_address(addr);
Christopher Haster 94:644df37bb05b 105 set_port(port);
Christopher Haster 94:644df37bb05b 106 } else {
Christopher Haster 94:644df37bb05b 107 _ip_version = NSAPI_IPv4;
Christopher Haster 94:644df37bb05b 108 memset(_ip_bytes, 0, NSAPI_IPv4_BYTES);
Christopher Haster 94:644df37bb05b 109 set_port(0);
Christopher Haster 94:644df37bb05b 110 }
Christopher Haster 89:b1d417383c0d 111 }
Christopher Haster 89:b1d417383c0d 112 }
Christopher Haster 89:b1d417383c0d 113
Christopher Haster 89:b1d417383c0d 114 SocketAddress::SocketAddress(const char *addr, uint16_t port)
Christopher Haster 89:b1d417383c0d 115 {
Christopher Haster 89:b1d417383c0d 116 set_ip_address(addr);
Christopher Haster 89:b1d417383c0d 117 set_port(port);
Christopher Haster 89:b1d417383c0d 118 }
Christopher Haster 89:b1d417383c0d 119
Christopher Haster 94:644df37bb05b 120 SocketAddress::SocketAddress(const void *bytes, nsapi_version_t version, uint16_t port)
Christopher Haster 94:644df37bb05b 121 {
Christopher Haster 94:644df37bb05b 122 set_ip_bytes(bytes, version);
Christopher Haster 94:644df37bb05b 123 set_port(port);
Christopher Haster 94:644df37bb05b 124 }
Christopher Haster 94:644df37bb05b 125
Christopher Haster 89:b1d417383c0d 126 SocketAddress::SocketAddress(const SocketAddress &addr)
Christopher Haster 89:b1d417383c0d 127 {
Christopher Haster 94:644df37bb05b 128 set_ip_bytes(addr.get_ip_bytes(), addr.get_ip_version());
Christopher Haster 89:b1d417383c0d 129 set_port(addr.get_port());
Christopher Haster 89:b1d417383c0d 130 }
Christopher Haster 89:b1d417383c0d 131
Christopher Haster 89:b1d417383c0d 132 void SocketAddress::set_ip_address(const char *addr)
Christopher Haster 89:b1d417383c0d 133 {
Christopher Haster 94:644df37bb05b 134 _ip_address[0] = '\0';
Christopher Haster 94:644df37bb05b 135
Christopher Haster 94:644df37bb05b 136 if (addr && address_is_ipv4(addr)) {
Christopher Haster 94:644df37bb05b 137 _ip_version = NSAPI_IPv4;
Christopher Haster 94:644df37bb05b 138 address_to_ipv4(_ip_bytes, addr);
Christopher Haster 94:644df37bb05b 139 } else if (addr && address_is_ipv6(addr)) {
Christopher Haster 94:644df37bb05b 140 _ip_version = NSAPI_IPv6;
Christopher Haster 94:644df37bb05b 141 address_to_ipv4(_ip_bytes, addr);
Christopher Haster 94:644df37bb05b 142 } else {
Christopher Haster 94:644df37bb05b 143 _ip_version = NSAPI_IPv4;
Christopher Haster 94:644df37bb05b 144 memset(_ip_bytes, 0, NSAPI_IPv4_BYTES);
Christopher Haster 94:644df37bb05b 145 }
Christopher Haster 94:644df37bb05b 146 }
Christopher Haster 94:644df37bb05b 147
Christopher Haster 94:644df37bb05b 148 void SocketAddress::set_ip_bytes(const void *bytes, nsapi_version_t version)
Christopher Haster 94:644df37bb05b 149 {
Christopher Haster 94:644df37bb05b 150 _ip_address[0] = '\0';
Christopher Haster 94:644df37bb05b 151
Christopher Haster 94:644df37bb05b 152 if (_ip_version == NSAPI_IPv4) {
Christopher Haster 94:644df37bb05b 153 _ip_version = NSAPI_IPv4;
Christopher Haster 94:644df37bb05b 154 memcpy(_ip_bytes, bytes, NSAPI_IPv4_BYTES);
Christopher Haster 94:644df37bb05b 155 } else if (_ip_version == NSAPI_IPv6) {
Christopher Haster 94:644df37bb05b 156 _ip_version = NSAPI_IPv6;
Christopher Haster 94:644df37bb05b 157 memcpy(_ip_bytes, bytes, NSAPI_IPv6_BYTES);
Christopher Haster 94:644df37bb05b 158 } else {
Christopher Haster 94:644df37bb05b 159 _ip_version = NSAPI_IPv4;
Christopher Haster 94:644df37bb05b 160 memset(_ip_bytes, 0, NSAPI_IPv4_BYTES);
Christopher Haster 94:644df37bb05b 161 }
Christopher Haster 89:b1d417383c0d 162 }
Christopher Haster 89:b1d417383c0d 163
Christopher Haster 89:b1d417383c0d 164 void SocketAddress::set_port(uint16_t port)
Christopher Haster 89:b1d417383c0d 165 {
Christopher Haster 89:b1d417383c0d 166 _port = port;
Christopher Haster 89:b1d417383c0d 167 }
Christopher Haster 89:b1d417383c0d 168
Christopher Haster 89:b1d417383c0d 169 const char *SocketAddress::get_ip_address() const
Christopher Haster 89:b1d417383c0d 170 {
Christopher Haster 94:644df37bb05b 171 char *ip_address = (char *)_ip_address;
Christopher Haster 94:644df37bb05b 172
Christopher Haster 94:644df37bb05b 173 if (!ip_address[0]) {
Christopher Haster 94:644df37bb05b 174 if (_ip_version == NSAPI_IPv4) {
Christopher Haster 94:644df37bb05b 175 ipv4_to_address(ip_address, _ip_bytes);
Christopher Haster 94:644df37bb05b 176 } else if (_ip_version == NSAPI_IPv4) {
Christopher Haster 94:644df37bb05b 177 ipv6_to_address(ip_address, _ip_bytes);
Christopher Haster 94:644df37bb05b 178 }
Christopher Haster 89:b1d417383c0d 179 }
Christopher Haster 94:644df37bb05b 180
Christopher Haster 94:644df37bb05b 181 return ip_address;
Christopher Haster 94:644df37bb05b 182 }
Christopher Haster 94:644df37bb05b 183
Christopher Haster 94:644df37bb05b 184 const void *SocketAddress::get_ip_bytes() const
Christopher Haster 94:644df37bb05b 185 {
Christopher Haster 94:644df37bb05b 186 return _ip_bytes;
Christopher Haster 94:644df37bb05b 187 }
Christopher Haster 94:644df37bb05b 188
Christopher Haster 94:644df37bb05b 189 nsapi_version_t SocketAddress::get_ip_version() const
Christopher Haster 94:644df37bb05b 190 {
Christopher Haster 94:644df37bb05b 191 return _ip_version;
Christopher Haster 89:b1d417383c0d 192 }
Christopher Haster 89:b1d417383c0d 193
Christopher Haster 89:b1d417383c0d 194 uint16_t SocketAddress::get_port() const
Christopher Haster 89:b1d417383c0d 195 {
Christopher Haster 89:b1d417383c0d 196 return _port;
Christopher Haster 89:b1d417383c0d 197 }
Christopher Haster 94:644df37bb05b 198
Christopher Haster 94:644df37bb05b 199 SocketAddress::operator bool() const
Christopher Haster 94:644df37bb05b 200 {
Christopher Haster 94:644df37bb05b 201 int count = 0;
Christopher Haster 94:644df37bb05b 202 if (_ip_version == NSAPI_IPv4) {
Christopher Haster 94:644df37bb05b 203 count = NSAPI_IPv4_BYTES;
Christopher Haster 94:644df37bb05b 204 } else if (_ip_version == NSAPI_IPv6) {
Christopher Haster 94:644df37bb05b 205 count = NSAPI_IPv6_BYTES;
Christopher Haster 94:644df37bb05b 206 }
Christopher Haster 94:644df37bb05b 207
Christopher Haster 94:644df37bb05b 208 for (int i = 0; i < count; i++) {
Christopher Haster 94:644df37bb05b 209 if (_ip_bytes[i]) {
Christopher Haster 94:644df37bb05b 210 return true;
Christopher Haster 94:644df37bb05b 211 }
Christopher Haster 94:644df37bb05b 212 }
Christopher Haster 94:644df37bb05b 213
Christopher Haster 94:644df37bb05b 214 return false;
Christopher Haster 94:644df37bb05b 215 }