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:24:24 2016 -0500
Revision:
95:b3c679f20d13
Parent:
94:644df37bb05b
Child:
97:68232387bc75
Move to SocketAddress in gethostbyname

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 95:b3c679f20d13 101 int err = iface->gethostbyname(this, host);
Christopher Haster 94:644df37bb05b 102 if (!err) {
Christopher Haster 94:644df37bb05b 103 set_port(port);
Christopher Haster 94:644df37bb05b 104 } else {
Christopher Haster 94:644df37bb05b 105 _ip_version = NSAPI_IPv4;
Christopher Haster 94:644df37bb05b 106 memset(_ip_bytes, 0, NSAPI_IPv4_BYTES);
Christopher Haster 94:644df37bb05b 107 set_port(0);
Christopher Haster 94:644df37bb05b 108 }
Christopher Haster 89:b1d417383c0d 109 }
Christopher Haster 89:b1d417383c0d 110 }
Christopher Haster 89:b1d417383c0d 111
Christopher Haster 89:b1d417383c0d 112 SocketAddress::SocketAddress(const char *addr, uint16_t port)
Christopher Haster 89:b1d417383c0d 113 {
Christopher Haster 89:b1d417383c0d 114 set_ip_address(addr);
Christopher Haster 89:b1d417383c0d 115 set_port(port);
Christopher Haster 89:b1d417383c0d 116 }
Christopher Haster 89:b1d417383c0d 117
Christopher Haster 94:644df37bb05b 118 SocketAddress::SocketAddress(const void *bytes, nsapi_version_t version, uint16_t port)
Christopher Haster 94:644df37bb05b 119 {
Christopher Haster 94:644df37bb05b 120 set_ip_bytes(bytes, version);
Christopher Haster 94:644df37bb05b 121 set_port(port);
Christopher Haster 94:644df37bb05b 122 }
Christopher Haster 94:644df37bb05b 123
Christopher Haster 89:b1d417383c0d 124 SocketAddress::SocketAddress(const SocketAddress &addr)
Christopher Haster 89:b1d417383c0d 125 {
Christopher Haster 94:644df37bb05b 126 set_ip_bytes(addr.get_ip_bytes(), addr.get_ip_version());
Christopher Haster 89:b1d417383c0d 127 set_port(addr.get_port());
Christopher Haster 89:b1d417383c0d 128 }
Christopher Haster 89:b1d417383c0d 129
Christopher Haster 89:b1d417383c0d 130 void SocketAddress::set_ip_address(const char *addr)
Christopher Haster 89:b1d417383c0d 131 {
Christopher Haster 94:644df37bb05b 132 _ip_address[0] = '\0';
Christopher Haster 94:644df37bb05b 133
Christopher Haster 94:644df37bb05b 134 if (addr && address_is_ipv4(addr)) {
Christopher Haster 94:644df37bb05b 135 _ip_version = NSAPI_IPv4;
Christopher Haster 94:644df37bb05b 136 address_to_ipv4(_ip_bytes, addr);
Christopher Haster 94:644df37bb05b 137 } else if (addr && address_is_ipv6(addr)) {
Christopher Haster 94:644df37bb05b 138 _ip_version = NSAPI_IPv6;
Christopher Haster 94:644df37bb05b 139 address_to_ipv4(_ip_bytes, addr);
Christopher Haster 94:644df37bb05b 140 } else {
Christopher Haster 94:644df37bb05b 141 _ip_version = NSAPI_IPv4;
Christopher Haster 94:644df37bb05b 142 memset(_ip_bytes, 0, NSAPI_IPv4_BYTES);
Christopher Haster 94:644df37bb05b 143 }
Christopher Haster 94:644df37bb05b 144 }
Christopher Haster 94:644df37bb05b 145
Christopher Haster 94:644df37bb05b 146 void SocketAddress::set_ip_bytes(const void *bytes, nsapi_version_t version)
Christopher Haster 94:644df37bb05b 147 {
Christopher Haster 94:644df37bb05b 148 _ip_address[0] = '\0';
Christopher Haster 94:644df37bb05b 149
Christopher Haster 94:644df37bb05b 150 if (_ip_version == NSAPI_IPv4) {
Christopher Haster 94:644df37bb05b 151 _ip_version = NSAPI_IPv4;
Christopher Haster 94:644df37bb05b 152 memcpy(_ip_bytes, bytes, NSAPI_IPv4_BYTES);
Christopher Haster 94:644df37bb05b 153 } else if (_ip_version == NSAPI_IPv6) {
Christopher Haster 94:644df37bb05b 154 _ip_version = NSAPI_IPv6;
Christopher Haster 94:644df37bb05b 155 memcpy(_ip_bytes, bytes, NSAPI_IPv6_BYTES);
Christopher Haster 94:644df37bb05b 156 } else {
Christopher Haster 94:644df37bb05b 157 _ip_version = NSAPI_IPv4;
Christopher Haster 94:644df37bb05b 158 memset(_ip_bytes, 0, NSAPI_IPv4_BYTES);
Christopher Haster 94:644df37bb05b 159 }
Christopher Haster 89:b1d417383c0d 160 }
Christopher Haster 89:b1d417383c0d 161
Christopher Haster 89:b1d417383c0d 162 void SocketAddress::set_port(uint16_t port)
Christopher Haster 89:b1d417383c0d 163 {
Christopher Haster 89:b1d417383c0d 164 _port = port;
Christopher Haster 89:b1d417383c0d 165 }
Christopher Haster 89:b1d417383c0d 166
Christopher Haster 89:b1d417383c0d 167 const char *SocketAddress::get_ip_address() const
Christopher Haster 89:b1d417383c0d 168 {
Christopher Haster 94:644df37bb05b 169 char *ip_address = (char *)_ip_address;
Christopher Haster 94:644df37bb05b 170
Christopher Haster 94:644df37bb05b 171 if (!ip_address[0]) {
Christopher Haster 94:644df37bb05b 172 if (_ip_version == NSAPI_IPv4) {
Christopher Haster 94:644df37bb05b 173 ipv4_to_address(ip_address, _ip_bytes);
Christopher Haster 94:644df37bb05b 174 } else if (_ip_version == NSAPI_IPv4) {
Christopher Haster 94:644df37bb05b 175 ipv6_to_address(ip_address, _ip_bytes);
Christopher Haster 94:644df37bb05b 176 }
Christopher Haster 89:b1d417383c0d 177 }
Christopher Haster 94:644df37bb05b 178
Christopher Haster 94:644df37bb05b 179 return ip_address;
Christopher Haster 94:644df37bb05b 180 }
Christopher Haster 94:644df37bb05b 181
Christopher Haster 94:644df37bb05b 182 const void *SocketAddress::get_ip_bytes() const
Christopher Haster 94:644df37bb05b 183 {
Christopher Haster 94:644df37bb05b 184 return _ip_bytes;
Christopher Haster 94:644df37bb05b 185 }
Christopher Haster 94:644df37bb05b 186
Christopher Haster 94:644df37bb05b 187 nsapi_version_t SocketAddress::get_ip_version() const
Christopher Haster 94:644df37bb05b 188 {
Christopher Haster 94:644df37bb05b 189 return _ip_version;
Christopher Haster 89:b1d417383c0d 190 }
Christopher Haster 89:b1d417383c0d 191
Christopher Haster 89:b1d417383c0d 192 uint16_t SocketAddress::get_port() const
Christopher Haster 89:b1d417383c0d 193 {
Christopher Haster 89:b1d417383c0d 194 return _port;
Christopher Haster 89:b1d417383c0d 195 }
Christopher Haster 94:644df37bb05b 196
Christopher Haster 94:644df37bb05b 197 SocketAddress::operator bool() const
Christopher Haster 94:644df37bb05b 198 {
Christopher Haster 94:644df37bb05b 199 int count = 0;
Christopher Haster 94:644df37bb05b 200 if (_ip_version == NSAPI_IPv4) {
Christopher Haster 94:644df37bb05b 201 count = NSAPI_IPv4_BYTES;
Christopher Haster 94:644df37bb05b 202 } else if (_ip_version == NSAPI_IPv6) {
Christopher Haster 94:644df37bb05b 203 count = NSAPI_IPv6_BYTES;
Christopher Haster 94:644df37bb05b 204 }
Christopher Haster 94:644df37bb05b 205
Christopher Haster 94:644df37bb05b 206 for (int i = 0; i < count; i++) {
Christopher Haster 94:644df37bb05b 207 if (_ip_bytes[i]) {
Christopher Haster 94:644df37bb05b 208 return true;
Christopher Haster 94:644df37bb05b 209 }
Christopher Haster 94:644df37bb05b 210 }
Christopher Haster 94:644df37bb05b 211
Christopher Haster 94:644df37bb05b 212 return false;
Christopher Haster 94:644df37bb05b 213 }