Skip to content

Commit

Permalink
sync IPAddress.h with ESP8266
Browse files Browse the repository at this point in the history
  • Loading branch information
1e1 authored Oct 27, 2024
1 parent c8c514c commit 02cf7c1
Showing 1 changed file with 206 additions and 62 deletions.
268 changes: 206 additions & 62 deletions cores/arduino/IPAddress.h
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

0 comments on commit 02cf7c1

Please sign in to comment.