-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
206 additions
and
62 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,78 +1,222 @@ | ||
/* | ||
IPAddress.h - Base class that provides IPAddress | ||
Copyright (c) 2011 Adrian McEwen. All right reserved. | ||
IPAddress.h - Base class that provides IPAddress | ||
Copyright (c) 2011 Adrian McEwen. All right reserved. | ||
This library is free software; you can redistribute it and/or | ||
modify it under the terms of the GNU Lesser General Public | ||
License as published by the Free Software Foundation; either | ||
version 2.1 of the License, or (at your option) any later version. | ||
This library is free software; you can redistribute it and/or | ||
modify it under the terms of the GNU Lesser General Public | ||
License as published by the Free Software Foundation; either | ||
version 2.1 of the License, or (at your option) any later version. | ||
This library is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
Lesser General Public License for more details. | ||
This library is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
Lesser General Public License for more details. | ||
You should have received a copy of the GNU Lesser General Public | ||
License along with this library; if not, write to the Free Software | ||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
*/ | ||
You should have received a copy of the GNU Lesser General Public | ||
License along with this library; if not, write to the Free Software | ||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
*/ | ||
|
||
#ifndef IPAddress_h | ||
#define IPAddress_h | ||
|
||
#include <stdint.h> | ||
#include "Printable.h" | ||
#include "WString.h" | ||
#include <WString.h> | ||
#include <Printable.h> | ||
|
||
#include <lwip/init.h> | ||
#include <lwip/ip_addr.h> | ||
#include <lwip/ip4_addr.h> | ||
|
||
#if !LWIP_IPV6 | ||
struct ip_addr: ipv4_addr { }; | ||
#endif // !LWIP_IPV6 | ||
|
||
// to display a netif id with printf: | ||
#define NETIFID_STR "%c%c%u" | ||
#define NETIFID_VAL(netif) \ | ||
((netif)? (netif)->name[0]: '-'), \ | ||
((netif)? (netif)->name[1]: '-'), \ | ||
((netif)? netif_get_index(netif): 42) | ||
|
||
// A class to make it easier to handle and pass around IP addresses | ||
// IPv6 update: | ||
// IPAddress is now a decorator class for lwIP's ip_addr_t | ||
// fully backward compatible with legacy IPv4-only Arduino's | ||
// with unchanged footprint when IPv6 is disabled | ||
|
||
class IPAddress: public Printable { | ||
private: | ||
|
||
ip_addr_t _ip; | ||
|
||
// Access the raw byte array containing the address. Because this returns a pointer | ||
// to the internal structure rather than a copy of the address this function should only | ||
// be used when you know that the usage of the returned uint8_t* will be transient and not | ||
// stored. | ||
uint8_t* raw_address() { | ||
return reinterpret_cast<uint8_t*>(&v4()); | ||
} | ||
const uint8_t* raw_address() const { | ||
return reinterpret_cast<const uint8_t*>(&v4()); | ||
} | ||
|
||
public: | ||
IPAddress(); | ||
IPAddress(const IPAddress&); | ||
IPAddress(IPAddress&&); | ||
|
||
IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet); | ||
IPAddress(uint32_t address) { *this = address; } | ||
IPAddress(unsigned long address) { *this = address; } | ||
IPAddress(int address) { *this = address; } | ||
IPAddress(const uint8_t *address) { *this = address; } | ||
|
||
bool fromString(const char *address); | ||
bool fromString(const String &address) { return fromString(address.c_str()); } | ||
|
||
// Overloaded cast operator to allow IPAddress objects to be used where a pointer | ||
// to a four-byte uint8_t array is expected | ||
operator uint32_t() const { return isV4()? v4(): (uint32_t)0; } | ||
operator uint32_t() { return isV4()? v4(): (uint32_t)0; } | ||
|
||
bool isSet () const; | ||
operator bool () const { return isSet(); } // <- | ||
operator bool () { return isSet(); } // <- both are needed | ||
|
||
// generic IPv4 wrapper to uint32-view like arduino loves to see it | ||
const uint32_t& v4() const { return ip_2_ip4(&_ip)->addr; } | ||
uint32_t& v4() { return ip_2_ip4(&_ip)->addr; } | ||
|
||
bool operator==(const IPAddress& addr) const { | ||
return ip_addr_cmp(&_ip, &addr._ip); | ||
} | ||
bool operator!=(const IPAddress& addr) const { | ||
return !ip_addr_cmp(&_ip, &addr._ip); | ||
} | ||
bool operator==(uint32_t addr) const { | ||
return isV4() && v4() == addr; | ||
} | ||
bool operator==(unsigned long addr) const { | ||
return isV4() && v4() == (uint32_t)addr; | ||
} | ||
bool operator!=(uint32_t addr) const { | ||
return !(isV4() && v4() == addr); | ||
} | ||
bool operator!=(unsigned long addr) const { | ||
return isV4() && v4() != (uint32_t)addr; | ||
} | ||
bool operator==(const uint8_t* addr) const; | ||
|
||
int operator>>(int n) const { | ||
return isV4()? v4() >> n: 0; | ||
} | ||
|
||
// Overloaded index operator to allow getting and setting individual octets of the address | ||
uint8_t operator[](int index) const { | ||
if (!isV4()) { | ||
return 0; | ||
} | ||
|
||
return ip4_addr_get_byte_val(*ip_2_ip4(&_ip), index); | ||
} | ||
|
||
uint8_t& operator[](int index) { | ||
setV4(); | ||
|
||
uint8_t* ptr = reinterpret_cast<uint8_t*>(&v4()); | ||
return *(ptr + index); | ||
} | ||
|
||
// Overloaded copy operators to allow initialisation of IPAddress objects from other types | ||
IPAddress& operator=(const uint8_t *address); | ||
IPAddress& operator=(uint32_t address); | ||
IPAddress& operator=(const IPAddress&) = default; | ||
|
||
virtual size_t printTo(Print& p) const; | ||
String toString() const; | ||
|
||
void clear(); | ||
|
||
/* | ||
check if input string(arg) is a valid IPV4 address or not. | ||
return true on valid. | ||
return false on invalid. | ||
*/ | ||
static bool isValid(const String& arg); | ||
static bool isValid(const char* arg); | ||
|
||
friend class EthernetClass; | ||
friend class UDP; | ||
friend class Client; | ||
friend class Server; | ||
friend class DhcpClass; | ||
friend class DNSClient; | ||
|
||
/* | ||
lwIP address compatibility | ||
*/ | ||
IPAddress(const ipv4_addr& fw_addr) { setV4(); v4() = fw_addr.addr; } | ||
IPAddress(const ipv4_addr* fw_addr) { setV4(); v4() = fw_addr->addr; } | ||
|
||
IPAddress& operator=(const ipv4_addr& fw_addr) { setV4(); v4() = fw_addr.addr; return *this; } | ||
IPAddress& operator=(const ipv4_addr* fw_addr) { setV4(); v4() = fw_addr->addr; return *this; } | ||
|
||
operator ip_addr_t () const { return _ip; } | ||
operator const ip_addr_t*() const { return &_ip; } | ||
operator ip_addr_t*() { return &_ip; } | ||
|
||
bool isV4() const { return IP_IS_V4_VAL(_ip); } | ||
void setV4() { IP_SET_TYPE_VAL(_ip, IPADDR_TYPE_V4); } | ||
|
||
bool isLocal () const { return ip_addr_islinklocal(&_ip); } | ||
|
||
#if LWIP_IPV6 | ||
|
||
IPAddress(const ip_addr_t& lwip_addr) { ip_addr_copy(_ip, lwip_addr); } | ||
IPAddress(const ip_addr_t* lwip_addr) { ip_addr_copy(_ip, *lwip_addr); } | ||
|
||
IPAddress& operator=(const ip_addr_t& lwip_addr) { ip_addr_copy(_ip, lwip_addr); return *this; } | ||
IPAddress& operator=(const ip_addr_t* lwip_addr) { ip_addr_copy(_ip, *lwip_addr); return *this; } | ||
|
||
uint16_t* raw6() | ||
{ | ||
setV6(); | ||
return reinterpret_cast<uint16_t*>(ip_2_ip6(&_ip)); | ||
} | ||
|
||
const uint16_t* raw6() const | ||
{ | ||
return isV6()? reinterpret_cast<const uint16_t*>(ip_2_ip6(&_ip)): nullptr; | ||
} | ||
|
||
// when not IPv6, ip_addr_t == ip4_addr_t so this one would be ambiguous | ||
// required otherwise | ||
operator const ip4_addr_t*() const { return isV4()? ip_2_ip4(&_ip): nullptr; } | ||
|
||
bool isV6() const { return IP_IS_V6_VAL(_ip); } | ||
void setV6() { IP_SET_TYPE_VAL(_ip, IPADDR_TYPE_V6); } | ||
|
||
protected: | ||
bool fromString6(const char *address); | ||
|
||
#else | ||
|
||
// allow portable code when IPv6 is not enabled | ||
|
||
uint16_t* raw6() { return nullptr; } | ||
const uint16_t* raw6() const { return nullptr; } | ||
bool isV6() const { return false; } | ||
void setV6() { } | ||
|
||
#endif | ||
|
||
protected: | ||
bool fromString4(const char *address); | ||
|
||
class IPAddress : public Printable { | ||
private: | ||
union { | ||
uint8_t bytes[4]; // IPv4 address | ||
uint32_t dword; | ||
} _address; | ||
|
||
// Access the raw byte array containing the address. Because this returns a pointer | ||
// to the internal structure rather than a copy of the address this function should only | ||
// be used when you know that the usage of the returned uint8_t* will be transient and not | ||
// stored. | ||
uint8_t* raw_address() { return _address.bytes; }; | ||
|
||
public: | ||
// Constructors | ||
IPAddress(); | ||
IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet); | ||
IPAddress(uint32_t address); | ||
IPAddress(const uint8_t *address); | ||
|
||
bool fromString(const char *address); | ||
bool fromString(const String &address) { return fromString(address.c_str()); } | ||
|
||
// Overloaded cast operator to allow IPAddress objects to be used where a pointer | ||
// to a four-byte uint8_t array is expected | ||
operator uint32_t() const { return _address.dword; }; | ||
bool operator==(const IPAddress& addr) const { return _address.dword == addr._address.dword; }; | ||
bool operator==(const uint8_t* addr) const; | ||
|
||
// Overloaded index operator to allow getting and setting individual octets of the address | ||
uint8_t operator[](int index) const { return _address.bytes[index]; }; | ||
uint8_t& operator[](int index) { return _address.bytes[index]; }; | ||
|
||
// Overloaded copy operators to allow initialisation of IPAddress objects from other types | ||
IPAddress& operator=(const uint8_t *address); | ||
IPAddress& operator=(uint32_t address); | ||
|
||
virtual size_t printTo(Print& p) const; | ||
|
||
friend class EthernetClass; | ||
friend class UDP; | ||
friend class Client; | ||
friend class Server; | ||
friend class DhcpClass; | ||
friend class DNSClient; | ||
}; | ||
|
||
const IPAddress INADDR_NONE(0,0,0,0); | ||
extern const IPAddress INADDR_ANY; | ||
extern const IPAddress INADDR_NONE; | ||
|
||
#endif |