Skip to content

Commit

Permalink
revert broken IPv6nchang
Browse files Browse the repository at this point in the history
  • Loading branch information
Jason2866 committed Dec 18, 2023
1 parent 8694a2d commit ad8a1a7
Showing 1 changed file with 133 additions and 38 deletions.
171 changes: 133 additions & 38 deletions cores/esp32/IPAddress.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,79 +20,115 @@
#ifndef IPAddress_h
#define IPAddress_h

#include <stdint.h>
#include <WString.h>
#include <Printable.h>

// A class to make it easier to handle and pass around IP addresses

#define IPADDRESS_V4_BYTES_INDEX 12
#define IPADDRESS_V4_DWORD_INDEX 3
#include <lwip/netif.h>

enum IPType
{
IPv4,
IPv6
IPv4 = IPADDR_TYPE_V4,
IPv6 = IPADDR_TYPE_V6
};

class IPAddress: public Printable
{
private:
union {
uint8_t bytes[16];
uint32_t dword[4];
} _address;
IPType _type;
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 _type == IPv4 ? &_address.bytes[IPADDRESS_V4_BYTES_INDEX] : _address.bytes;
uint8_t* raw_address() {
return reinterpret_cast<uint8_t*>(&v4());
}
const uint8_t* raw_address() const {
return reinterpret_cast<const uint8_t*>(&v4());
}

void ctor32 (uint32_t);

public:
// Constructors
IPAddress();
IPAddress(IPType ip_type);
IPAddress(const IPAddress& from);
IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet);
IPAddress(uint8_t o1, uint8_t o2, uint8_t o3, uint8_t o4, uint8_t o5, uint8_t o6, uint8_t o7, uint8_t o8, uint8_t o9, uint8_t o10, uint8_t o11, uint8_t o12, uint8_t o13, uint8_t o14, uint8_t o15, uint8_t o16);
IPAddress(uint32_t address);
IPAddress(const uint8_t *address);
IPAddress(IPType ip_type, const uint8_t *address);
// If IPv4 fails tries IPv6 see fromString function
IPAddress(const char *address);
virtual ~IPAddress() {}
IPAddress(uint32_t address) { *this = address; }
IPAddress(int address) { *this = address; }
IPAddress(const uint8_t *address) { *this = address; }
IPAddress(IPType type, const uint8_t *address);
IPAddress(IPType type, const uint8_t *address, uint8_t zone);

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
// uint32_t is expected
operator uint32_t() const
{
return _type == IPv4 ? _address.dword[IPADDRESS_V4_DWORD_INDEX] : 0;
}
// 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; }

// 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;
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;
uint8_t& operator[](int index);
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);
// If IPv4 fails tries IPv6 see fromString function
IPAddress& operator=(const char *address);
IPAddress& operator=(const IPAddress&) = default;

IPType type() const { return (IPType)_ip.type; }

virtual size_t printTo(Print& p) const;
String toString() const;

IPType type() const { return _type; }
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;
Expand All @@ -101,14 +137,73 @@ class IPAddress: public Printable
friend class DhcpClass;
friend class DNSClient;

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); }
bool isAny() const { return ip_addr_isany_val(_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);
ip6_addr_clear_zone(ip_2_ip6(&_ip));
}
inline uint8_t zone() const { return isV6() ? ip_2_ip6(&_ip)->zone : 0; }
void setZone(uint8_t zone) {
if (isV6()) {
ip_2_ip6(&_ip)->zone = zone;
}
}


protected:
bool fromString4(const char *address);
bool fromString6(const char *address);
String toString4() const;
String toString6() const;

#else /* !LWIP_IPV6 */

// 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() { }
inline uint8_t zone() const { return 0; }
void setZone(uint8_t zone) { }

#endif

protected:
bool fromString4(const char *address);
};

// changed to extern because const declaration creates copies in BSS of INADDR_NONE for each CPP unit that includes it
extern IPAddress INADDR_NONE;
extern IPAddress IN6ADDR_ANY;

#endif

0 comments on commit ad8a1a7

Please sign in to comment.