1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-22 21:23:07 +03:00
esp8266/cores/esp8266/AddrList.h
david gauchard af1bc71a9e
remove lwip-v1.4 specific code (#7436)
* remove lwip-v1.4 specific code

* ditto

* ditto

* fix ip4_addr definition

* CI: change debug builds to use IPv6, remove regular IPv6 builds

* ditto

* split pio CI in four (because they last twice the time of the other builds)

* remove option from pio

* remove lwIP-1.4 from doc

* restore pio CI splitting

* fix CI debug6 script

* ditto
2020-07-09 09:59:49 -07:00

222 lines
6.5 KiB
C++

/*
AddrList.h - cycle through lwIP netif's ip addresses like a c++ list
Copyright (c) 2018 david gauchard. 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 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
*/
/*
This class allows to explore all configured IP addresses
in lwIP netifs, with that kind of c++ loop:
for (auto a: addrList)
out.printf("IF='%s' index=%d legacy=%d IPv4=%d local=%d hostname='%s' addr= %s\n",
a.iface().c_str(),
a.ifnumber(),
a.addr().isLegacy(),
a.addr().isV4(),
a.addr().isLocal(),
a.hostname().c_str(),
a.addr().toString().c_str());
This loop:
while (WiFi.status() != WL_CONNECTED()) {
Serial.print('.');
delay(500);
}
can be replaced by:
for (bool configured = false; !configured; ) {
for (auto iface: addrList)
if ((configured = !iface.addr().isLocal())
break;
Serial.print('.');
delay(500);
}
waiting for an IPv6 global address:
for (bool configured = false; !configured; ) {
for (auto iface: addrList)
if ((configured = ( !iface.addr().isV4()
&& !iface.addr().isLocal())))
break;
Serial.print('.');
delay(500);
}
waiting for an IPv6 global address, on a specific interface:
for (bool configured = false; !configured; ) {
for (auto iface: addrList)
if ((configured = ( !iface.addr().isV4()
&& !iface.addr().isLocal()
&& iface.ifnumber() == STATION_IF)))
break;
Serial.print('.');
delay(500);
}
*/
#ifndef __ADDRLIST_H
#define __ADDRLIST_H
#include <IPAddress.h>
#include <lwip/netif.h>
#if LWIP_IPV6
#define IF_NUM_ADDRESSES (1 + LWIP_IPV6_NUM_ADDRESSES)
#else
#define IF_NUM_ADDRESSES (1)
#endif
namespace esp8266
{
namespace AddressListImplementation
{
struct netifWrapper
{
netifWrapper (netif* netif) : _netif(netif), _num(-1) {}
netifWrapper (const netifWrapper& o) : _netif(o._netif), _num(o._num) {}
netifWrapper& operator= (const netifWrapper& o)
{
_netif = o._netif;
_num = o._num;
return *this;
}
bool equal(const netifWrapper& o)
{
return _netif == o._netif && (!_netif || _num == o._num);
}
// address properties
IPAddress addr () const { return ipFromNetifNum(); }
bool isLegacy () const { return _num == 0; }
bool isLocal () const { return addr().isLocal(); }
bool isV4 () const { return addr().isV4(); }
bool isV6 () const { return !addr().isV4(); }
String toString() const { return addr().toString(); }
// related to legacy address (_num=0, ipv4)
IPAddress ipv4 () const { return _netif->ip_addr; }
IPAddress netmask () const { return _netif->netmask; }
IPAddress gw () const { return _netif->gw; }
// common to all addresses of this interface
String ifname () const { return String(_netif->name[0]) + _netif->name[1]; }
const char* ifhostname () const { return _netif->hostname?: emptyString.c_str(); }
const char* ifmac () const { return (const char*)_netif->hwaddr; }
int ifnumber () const { return _netif->num; }
bool ifUp () const { return !!(_netif->flags & NETIF_FLAG_UP); }
const netif* interface () const { return _netif; }
const ip_addr_t* ipFromNetifNum () const
{
#if LWIP_IPV6
return _num ? &_netif->ip6_addr[_num - 1] : &_netif->ip_addr;
#else
return &_netif->ip_addr;
#endif
}
// lwIP interface
netif* _netif;
// address index within interface
// 0: legacy address (IPv4)
// n>0: (_num-1) is IPv6 index for netif->ip6_addr[]
int _num;
};
class AddressListIterator
{
public:
AddressListIterator (const netifWrapper& o) : netIf(o) {}
AddressListIterator (netif* netif) : netIf(netif)
{
// This constructor is called with lwIP's global netif_list, or
// nullptr. operator++() is designed to loop through _configured_
// addresses. That's why netIf's _num is initialized to -1 to allow
// returning the first usable address to AddressList::begin().
(void)operator++();
}
const netifWrapper& operator* () const { return netIf; }
const netifWrapper* operator-> () const { return &netIf; }
bool operator== (AddressListIterator& o) { return netIf.equal(*o); }
bool operator!= (AddressListIterator& o) { return !netIf.equal(*o); }
AddressListIterator operator++ (int)
{
AddressListIterator ret = *this;
(void)operator++();
return ret;
}
AddressListIterator& operator++ ()
{
while (netIf._netif)
{
if (++netIf._num == IF_NUM_ADDRESSES)
{
// all addresses from current interface were iterated,
// switching to next interface
netIf = netifWrapper(netIf._netif->next);
continue;
}
if (!ip_addr_isany(netIf.ipFromNetifNum()))
// found an initialized address
break;
}
return *this;
}
netifWrapper netIf;
};
class AddressList
{
public:
using const_iterator = const AddressListIterator;
const_iterator begin () const { return const_iterator(netif_list); }
const_iterator end () const { return const_iterator(nullptr); }
};
inline AddressList::const_iterator begin (const AddressList& a) { return a.begin(); }
inline AddressList::const_iterator end (const AddressList& a) { return a.end(); }
} // AddressListImplementation
} // esp8266
extern esp8266::AddressListImplementation::AddressList addrList;
#endif