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:46 2016 -0500
Revision:
97:68232387bc75
Parent:
95:b3c679f20d13
Child:
100:90d8f662de83
Fix ipv6 addr in SocketAddress

Correctly set and return the ipv6 address.

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