From 02cf7c142be2a5702bc8296d7cda904848609198 Mon Sep 17 00:00:00 2001 From: 1e1 <1e1@users.noreply.github.com> Date: Sun, 27 Oct 2024 23:10:41 +0100 Subject: [PATCH] sync IPAddress.h with ESP8266 --- cores/arduino/IPAddress.h | 268 +++++++++++++++++++++++++++++--------- 1 file changed, 206 insertions(+), 62 deletions(-) diff --git a/cores/arduino/IPAddress.h b/cores/arduino/IPAddress.h index d762f2c02..99419b92a 100644 --- a/cores/arduino/IPAddress.h +++ b/cores/arduino/IPAddress.h @@ -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 -#include "Printable.h" -#include "WString.h" +#include +#include + +#include +#include +#include + +#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(&v4()); + } + const uint8_t* raw_address() const { + return reinterpret_cast(&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(&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(ip_2_ip6(&_ip)); + } + + const uint16_t* raw6() const + { + return isV6()? reinterpret_cast(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