mirror of https://github.com/ARMmbed/mbed-os.git
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
parent
455f023949
commit
62bb777c1f
|
@ -20,6 +20,7 @@
|
|||
#include "mbed.h"
|
||||
#include "SocketAddress.h"
|
||||
|
||||
|
||||
/** Enum of standardized error codes
|
||||
* @enum ns_error_t
|
||||
*/
|
||||
|
@ -50,6 +51,15 @@ enum nsapi_protocol_t {
|
|||
NSAPI_UDP, /*!< Socket is of UDP type */
|
||||
};
|
||||
|
||||
/** Maximum size of MAC address representation
|
||||
*/
|
||||
#define NSAPI_MAC_SIZE 18
|
||||
|
||||
/** Maximum number of bytes for MAC address
|
||||
*/
|
||||
#define NSAPI_MAC_BYTES 6
|
||||
|
||||
|
||||
/** NetworkInterface class
|
||||
* Common interface that is shared between all hardware that
|
||||
* can connect to a network over IP.
|
||||
|
|
|
@ -19,14 +19,95 @@
|
|||
#include <string.h>
|
||||
#include "mbed.h"
|
||||
|
||||
static bool address_is_ipv4(const char *addr)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
// Check each digit for [0-9.]
|
||||
for (; addr[i]; i++) {
|
||||
if (!(addr[i] >= '0' && addr[i] <= '9') && addr[i] != '.') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Ending with '.' garuntees host
|
||||
if (i > 0 && addr[i-1] == '.') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool address_is_ipv6(const char *addr)
|
||||
{
|
||||
// Check each digit for [0-9a-fA-F:]
|
||||
for (int i = 0; addr[i]; i++) {
|
||||
if (!(addr[i] >= '0' && addr[i] <= '9') &&
|
||||
!(addr[i] >= 'a' && addr[i] <= 'f') &&
|
||||
!(addr[i] >= 'A' && addr[i] <= 'F') &&
|
||||
addr[i] != ':') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void address_to_ipv4(uint8_t *bytes, const char *addr)
|
||||
{
|
||||
sscanf(addr, "%hhd.%hhd.%hhd.%hhd", &bytes[0], &bytes[1], &bytes[2], &bytes[3]);
|
||||
}
|
||||
|
||||
static void address_to_ipv6(uint8_t *bytes, const char *addr)
|
||||
{
|
||||
// TODO support short form (::1, 2001::ffee:100a)
|
||||
// Use a more intellegent algorithm
|
||||
uint16_t shorts[NSAPI_IPv6_BYTES/2];
|
||||
sscanf(addr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
|
||||
&shorts[0], &shorts[1], &shorts[2], &shorts[3],
|
||||
&shorts[4], &shorts[5], &shorts[6], &shorts[7]);
|
||||
|
||||
for (int i = 0; i < NSAPI_IPv6_BYTES/2; i++) {
|
||||
bytes[2*i+0] = (uint8_t)(shorts[i] >> 8);
|
||||
bytes[2*i+1] = (uint8_t)(shorts[i] >> 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void ipv4_to_address(char *addr, const uint8_t *bytes)
|
||||
{
|
||||
sprintf(addr, "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]);
|
||||
}
|
||||
|
||||
static void ipv6_to_address(char *addr, const uint8_t *bytes)
|
||||
{
|
||||
for (int i = 0; i < NSAPI_IPv6_BYTES; i+=2) {
|
||||
sprintf(&addr[5*i], "%02x%02x", bytes[i], bytes[i+1]);
|
||||
addr[5*i+4] = ':';
|
||||
}
|
||||
addr[NSAPI_IPv6_BYTES-1] = '\0';
|
||||
}
|
||||
|
||||
SocketAddress::SocketAddress(NetworkInterface *iface, const char *host, uint16_t port)
|
||||
{
|
||||
int err = iface->gethostbyname(host, _ip_address);
|
||||
set_port(port);
|
||||
|
||||
if (err) {
|
||||
_ip_address[0] = '\0';
|
||||
_port = 0;
|
||||
// Check for valid IP addresses
|
||||
if (host && address_is_ipv4(host)) {
|
||||
_ip_version = NSAPI_IPv4;
|
||||
address_to_ipv4(_ip_bytes, host);
|
||||
} else if (host && address_is_ipv6(host)) {
|
||||
_ip_version = NSAPI_IPv6;
|
||||
address_to_ipv4(_ip_bytes, host);
|
||||
} else {
|
||||
// DNS lookup
|
||||
char addr[NSAPI_IP_SIZE];
|
||||
int err = iface->gethostbyname(host, addr);
|
||||
if (!err) {
|
||||
set_ip_address(addr);
|
||||
set_port(port);
|
||||
} else {
|
||||
_ip_version = NSAPI_IPv4;
|
||||
memset(_ip_bytes, 0, NSAPI_IPv4_BYTES);
|
||||
set_port(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,16 +117,48 @@ SocketAddress::SocketAddress(const char *addr, uint16_t port)
|
|||
set_port(port);
|
||||
}
|
||||
|
||||
SocketAddress::SocketAddress(const void *bytes, nsapi_version_t version, uint16_t port)
|
||||
{
|
||||
set_ip_bytes(bytes, version);
|
||||
set_port(port);
|
||||
}
|
||||
|
||||
SocketAddress::SocketAddress(const SocketAddress &addr)
|
||||
{
|
||||
set_ip_address(addr.get_ip_address());
|
||||
set_ip_bytes(addr.get_ip_bytes(), addr.get_ip_version());
|
||||
set_port(addr.get_port());
|
||||
}
|
||||
|
||||
void SocketAddress::set_ip_address(const char *addr)
|
||||
{
|
||||
strncpy(_ip_address, addr, sizeof _ip_address);
|
||||
_ip_address[sizeof _ip_address - 1] = '\0';
|
||||
_ip_address[0] = '\0';
|
||||
|
||||
if (addr && address_is_ipv4(addr)) {
|
||||
_ip_version = NSAPI_IPv4;
|
||||
address_to_ipv4(_ip_bytes, addr);
|
||||
} else if (addr && address_is_ipv6(addr)) {
|
||||
_ip_version = NSAPI_IPv6;
|
||||
address_to_ipv4(_ip_bytes, addr);
|
||||
} else {
|
||||
_ip_version = NSAPI_IPv4;
|
||||
memset(_ip_bytes, 0, NSAPI_IPv4_BYTES);
|
||||
}
|
||||
}
|
||||
|
||||
void SocketAddress::set_ip_bytes(const void *bytes, nsapi_version_t version)
|
||||
{
|
||||
_ip_address[0] = '\0';
|
||||
|
||||
if (_ip_version == NSAPI_IPv4) {
|
||||
_ip_version = NSAPI_IPv4;
|
||||
memcpy(_ip_bytes, bytes, NSAPI_IPv4_BYTES);
|
||||
} else if (_ip_version == NSAPI_IPv6) {
|
||||
_ip_version = NSAPI_IPv6;
|
||||
memcpy(_ip_bytes, bytes, NSAPI_IPv6_BYTES);
|
||||
} else {
|
||||
_ip_version = NSAPI_IPv4;
|
||||
memset(_ip_bytes, 0, NSAPI_IPv4_BYTES);
|
||||
}
|
||||
}
|
||||
|
||||
void SocketAddress::set_port(uint16_t port)
|
||||
|
@ -55,13 +168,48 @@ void SocketAddress::set_port(uint16_t port)
|
|||
|
||||
const char *SocketAddress::get_ip_address() const
|
||||
{
|
||||
if (!_ip_address[0]) {
|
||||
return 0;
|
||||
char *ip_address = (char *)_ip_address;
|
||||
|
||||
if (!ip_address[0]) {
|
||||
if (_ip_version == NSAPI_IPv4) {
|
||||
ipv4_to_address(ip_address, _ip_bytes);
|
||||
} else if (_ip_version == NSAPI_IPv4) {
|
||||
ipv6_to_address(ip_address, _ip_bytes);
|
||||
}
|
||||
}
|
||||
return _ip_address;
|
||||
|
||||
return ip_address;
|
||||
}
|
||||
|
||||
const void *SocketAddress::get_ip_bytes() const
|
||||
{
|
||||
return _ip_bytes;
|
||||
}
|
||||
|
||||
nsapi_version_t SocketAddress::get_ip_version() const
|
||||
{
|
||||
return _ip_version;
|
||||
}
|
||||
|
||||
uint16_t SocketAddress::get_port() const
|
||||
{
|
||||
return _port;
|
||||
}
|
||||
|
||||
SocketAddress::operator bool() const
|
||||
{
|
||||
int count = 0;
|
||||
if (_ip_version == NSAPI_IPv4) {
|
||||
count = NSAPI_IPv4_BYTES;
|
||||
} else if (_ip_version == NSAPI_IPv6) {
|
||||
count = NSAPI_IPv6_BYTES;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (_ip_bytes[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -19,64 +19,118 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
/** Maximum size of IP address
|
||||
*/
|
||||
#define NSAPI_IP_SIZE 16
|
||||
|
||||
/** Maximum size of MAC address
|
||||
*/
|
||||
#define NSAPI_MAC_SIZE 18
|
||||
/** Maximum size of IP address representation
|
||||
*/
|
||||
#define NSAPI_IP_SIZE NSAPI_IPv6_SIZE
|
||||
|
||||
/** Maximum number of bytes for IP address
|
||||
*/
|
||||
#define NSAPI_IP_BYTES NSAPI_IPv6_BYTES
|
||||
|
||||
/** Enum of address families
|
||||
* @enum nsapi_family_t
|
||||
*/
|
||||
enum nsapi_version_t {
|
||||
NSAPI_IPv4, /*!< Address is IPv4 */
|
||||
NSAPI_IPv6, /*!< Address is IPv6 */
|
||||
};
|
||||
|
||||
/** Size of IPv4 representation
|
||||
*/
|
||||
#define NSAPI_IPv4_SIZE 16
|
||||
|
||||
/** Number of bytes in IPv4 address
|
||||
*/
|
||||
#define NSAPI_IPv4_BYTES 4
|
||||
|
||||
/** Size of IPv6 representation
|
||||
*/
|
||||
#define NSAPI_IPv6_SIZE 40
|
||||
|
||||
/** Number of bytes in IPv6 address
|
||||
*/
|
||||
#define NSAPI_IPv6_BYTES 16
|
||||
|
||||
// Predeclared classes
|
||||
class NetworkInterface;
|
||||
|
||||
/**
|
||||
* A general socket address composed of the IP address and port
|
||||
|
||||
/** A general address class composed of the IP address and optional port
|
||||
*/
|
||||
class SocketAddress {
|
||||
public:
|
||||
/** SocketAddress construction using DNS resolution
|
||||
* @param iface NetworkInterface to use for DNS resolution
|
||||
* @param addr Null-terminated hostname that will be resolved
|
||||
* @param port 16-bit port
|
||||
* @note on failure, IP address and port will be set to null
|
||||
* @param iface NetworkInterface to use for DNS resolution
|
||||
* @param addr Null-terminated hostname that will be resolved
|
||||
* @param port Optional 16-bit port
|
||||
* @note on failure, IP address and port will be set to zero
|
||||
*/
|
||||
SocketAddress(NetworkInterface *iface, const char *addr, uint16_t port = 0);
|
||||
|
||||
/** SocketAddress construction
|
||||
* @param addr Null-terminated IP address
|
||||
* @param port 16-bit port
|
||||
* @note on failure, IP address and port will be set to null
|
||||
* @param addr Null-terminated IP address
|
||||
* @param port Optional 16-bit port
|
||||
*/
|
||||
SocketAddress(const char *addr = 0, uint16_t port = 0);
|
||||
|
||||
/** SocketAddress construction
|
||||
* @param addr SocketAddress to copy
|
||||
* @param bytes Bytes to assign to address in big-endian order
|
||||
* @param version IP address version, NSAPI_IPv4 or NSAPI_IPv6
|
||||
* @param port Optional 16-bit port
|
||||
*/
|
||||
SocketAddress(const void *bytes, nsapi_version_t version, uint16_t port = 0);
|
||||
|
||||
/** SocketAddress construction
|
||||
* @param addr SocketAddress to copy
|
||||
*/
|
||||
SocketAddress(const SocketAddress &addr);
|
||||
|
||||
/** Set the IP address
|
||||
* @param addr Null-terminated string representing the IP address
|
||||
* @param addr Null-terminated string representing the IP address
|
||||
*/
|
||||
void set_ip_address(const char *addr);
|
||||
|
||||
/** Set the IP address bytes directly
|
||||
* @param bytes Bytes to assign to address in big-endian order
|
||||
* @param version IP address version, NSAPI_IPv4 or NSAPI_IPv6
|
||||
*/
|
||||
void set_ip_bytes(const void *bytes, nsapi_version_t version);
|
||||
|
||||
/** Set the port
|
||||
* @param port 16-bit port
|
||||
* @param port 16-bit port
|
||||
*/
|
||||
void set_port(uint16_t port);
|
||||
|
||||
/** Get the IP address
|
||||
* @return The string representation of the IP Address
|
||||
* @return The string representation of the IP Address
|
||||
*/
|
||||
const char *get_ip_address() const;
|
||||
|
||||
/** Get the IP address bytes directly
|
||||
* @return IP address bytes
|
||||
*/
|
||||
const void *get_ip_bytes() const;
|
||||
|
||||
/** Get the type of the IP address
|
||||
* @return IP address version, NSAPI_IPv4 or NSAPI_IPv6
|
||||
*/
|
||||
nsapi_version_t get_ip_version() const;
|
||||
|
||||
/** Get the port
|
||||
* @return The 16-bit port
|
||||
* @return The 16-bit port
|
||||
*/
|
||||
uint16_t get_port(void) const;
|
||||
uint16_t get_port() const;
|
||||
|
||||
/** Determine if address is all zeros
|
||||
* @return True if address is not zero address
|
||||
*/
|
||||
operator bool() const;
|
||||
|
||||
private:
|
||||
char _ip_address[NSAPI_IP_SIZE];
|
||||
uint8_t _ip_bytes[NSAPI_IP_BYTES];
|
||||
nsapi_version_t _ip_version;
|
||||
uint16_t _port;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue