mirror of https://github.com/arendst/Tasmota.git
IPv6 improvements
This commit is contained in:
parent
6e6cbf0988
commit
4a32623a51
|
@ -1,216 +0,0 @@
|
|||
/*
|
||||
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>
|
||||
#include "IPAddress46.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);
|
||||
}
|
||||
|
||||
IPAddress46 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)
|
||||
IPAddress46 ipv4 () const { return _netif->ip_addr; }
|
||||
IPAddress46 netmask () const { return _netif->netmask; }
|
||||
IPAddress46 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(); }
|
||||
|
||||
|
||||
} // namespace AddressListImplementation
|
||||
} // namespace esp8266
|
||||
|
||||
extern esp8266::AddressListImplementation::AddressList addrList;
|
||||
|
||||
|
||||
#endif
|
|
@ -1,331 +0,0 @@
|
|||
/*
|
||||
IPAddress46.cpp - IPv6 support for ESP32
|
||||
|
||||
This class is copied from ESP8266 Arduino framework and provides
|
||||
temporary support for IPv6 on ESP32.
|
||||
|
||||
Copyright (C) 2021 Theo Arends and Stephan Hadinger
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
IPAddress.cpp - 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 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
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <IPAddress46.h>
|
||||
#include <Print.h>
|
||||
#include <StreamString.h>
|
||||
|
||||
// Tasmota Logging
|
||||
extern void AddLog(uint32_t loglevel, PGM_P formatP, ...);
|
||||
enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE};
|
||||
|
||||
IPAddress46::IPAddress46(const IPAddress46& from)
|
||||
{
|
||||
ip_addr_copy(_ip, from._ip);
|
||||
}
|
||||
|
||||
IPAddress46::IPAddress46() {
|
||||
#if LWIP_IPV6
|
||||
_ip = *IP6_ADDR_ANY;
|
||||
#else
|
||||
_ip = *IP_ADDR_ANY;
|
||||
#endif
|
||||
// _ip = *IP_ANY_TYPE; // lwIP's v4-or-v6 generic address
|
||||
}
|
||||
|
||||
bool IPAddress46::isSet () const {
|
||||
return !IP_IS_ANY_TYPE_VAL(_ip);
|
||||
// return !ip_addr_isany(&_ip) && ((*this) != IPADDR_NONE);
|
||||
}
|
||||
|
||||
IPAddress46::IPAddress46(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) {
|
||||
setV4();
|
||||
(*this)[0] = first_octet;
|
||||
(*this)[1] = second_octet;
|
||||
(*this)[2] = third_octet;
|
||||
(*this)[3] = fourth_octet;
|
||||
}
|
||||
|
||||
void IPAddress46::ctor32(uint32_t address) {
|
||||
setV4();
|
||||
v4() = address;
|
||||
}
|
||||
|
||||
IPAddress46::IPAddress46(const uint8_t *address) {
|
||||
setV4();
|
||||
(*this)[0] = address[0];
|
||||
(*this)[1] = address[1];
|
||||
(*this)[2] = address[2];
|
||||
(*this)[3] = address[3];
|
||||
}
|
||||
|
||||
bool IPAddress46::fromString(const char *address) {
|
||||
if (!fromString4(address)) {
|
||||
#if LWIP_IPV6
|
||||
return fromString6(address);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IPAddress46::fromString4(const char *address) {
|
||||
// TODO: (IPv4) add support for "a", "a.b", "a.b.c" formats
|
||||
|
||||
uint16_t acc = 0; // Accumulator
|
||||
uint8_t dots = 0;
|
||||
|
||||
while (*address)
|
||||
{
|
||||
char c = *address++;
|
||||
if (c >= '0' && c <= '9')
|
||||
{
|
||||
acc = acc * 10 + (c - '0');
|
||||
if (acc > 255) {
|
||||
// Value out of [0..255] range
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (c == '.')
|
||||
{
|
||||
if (dots == 3) {
|
||||
// Too much dots (there must be 3 dots)
|
||||
return false;
|
||||
}
|
||||
(*this)[dots++] = acc;
|
||||
acc = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalid char
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (dots != 3) {
|
||||
// Too few dots (there must be 3 dots)
|
||||
return false;
|
||||
}
|
||||
(*this)[3] = acc;
|
||||
|
||||
setV4();
|
||||
return true;
|
||||
}
|
||||
|
||||
IPAddress46& IPAddress46::operator=(const uint8_t *address) {
|
||||
setV4();
|
||||
v4() = *reinterpret_cast<const uint32_t*>(address);
|
||||
return *this;
|
||||
}
|
||||
|
||||
IPAddress46& IPAddress46::operator=(uint32_t address) {
|
||||
setV4();
|
||||
v4() = address;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool IPAddress46::operator==(const uint8_t* addr) const {
|
||||
return isV4() && v4() == *reinterpret_cast<const uint32_t*>(addr);
|
||||
}
|
||||
|
||||
size_t IPAddress46::printTo(Print& p) const {
|
||||
size_t n = 0;
|
||||
|
||||
// if (!isSet())
|
||||
// return p.print(F("(IP unset)"));
|
||||
|
||||
#if LWIP_IPV6
|
||||
if (isV6()) {
|
||||
int count0 = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
uint16_t bit = PP_NTOHS(raw6()[i]);
|
||||
if (bit || count0 < 0) {
|
||||
n += p.printf("%x", bit);
|
||||
if (count0 > 0)
|
||||
// no more hiding 0
|
||||
count0 = -8;
|
||||
} else
|
||||
count0++;
|
||||
if ((i != 7 && count0 < 2) || count0 == 7)
|
||||
n += p.print(':');
|
||||
}
|
||||
return n;
|
||||
}
|
||||
#endif
|
||||
|
||||
for(int i = 0; i < 4; i++) {
|
||||
n += p.print((*this)[i], DEC);
|
||||
if (i != 3)
|
||||
n += p.print('.');
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
String IPAddress46::toString() const
|
||||
{
|
||||
StreamString sstr;
|
||||
#if LWIP_IPV6
|
||||
if (isV6())
|
||||
sstr.reserve(40); // 8 shorts x 4 chars each + 7 colons + nullterm
|
||||
else
|
||||
#endif
|
||||
sstr.reserve(16); // 4 bytes with 3 chars max + 3 dots + nullterm, or '(IP unset)'
|
||||
printTo(sstr);
|
||||
return sstr;
|
||||
}
|
||||
|
||||
bool IPAddress46::isValid(const String& arg) {
|
||||
return IPAddress46().fromString(arg);
|
||||
}
|
||||
|
||||
bool IPAddress46::isValid(const char* arg) {
|
||||
return IPAddress46().fromString(arg);
|
||||
}
|
||||
|
||||
const IPAddress46 INADDR46_ANY; // generic "0.0.0.0" for IPv4 & IPv6
|
||||
const IPAddress46 INADDR46_NONE(255,255,255,255);
|
||||
|
||||
void IPAddress46::clear() {
|
||||
(*this) = INADDR46_ANY;
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
|
||||
#if LWIP_IPV6
|
||||
|
||||
bool IPAddress46::fromString6(const char *address) {
|
||||
// TODO: test test test
|
||||
|
||||
uint32_t acc = 0; // Accumulator
|
||||
int dots = 0, doubledots = -1;
|
||||
|
||||
while (*address)
|
||||
{
|
||||
char c = tolower(*address++);
|
||||
if (isalnum(c)) {
|
||||
if (c >= 'a')
|
||||
c -= 'a' - '0' - 10;
|
||||
acc = acc * 16 + (c - '0');
|
||||
if (acc > 0xffff)
|
||||
// Value out of range
|
||||
return false;
|
||||
}
|
||||
else if (c == ':') {
|
||||
if (*address == ':') {
|
||||
if (doubledots >= 0)
|
||||
// :: allowed once
|
||||
return false;
|
||||
// remember location
|
||||
doubledots = dots + !!acc;
|
||||
address++;
|
||||
}
|
||||
if (dots == 7)
|
||||
// too many separators
|
||||
return false;
|
||||
raw6()[dots++] = PP_HTONS(acc);
|
||||
acc = 0;
|
||||
}
|
||||
else
|
||||
// Invalid char
|
||||
return false;
|
||||
}
|
||||
|
||||
if (doubledots == -1 && dots != 7)
|
||||
// Too few separators
|
||||
return false;
|
||||
raw6()[dots++] = PP_HTONS(acc);
|
||||
|
||||
if (doubledots != -1) {
|
||||
for (int i = dots - doubledots - 1; i >= 0; i--)
|
||||
raw6()[8 - dots + doubledots + i] = raw6()[doubledots + i];
|
||||
for (int i = doubledots; i < 8 - dots + doubledots; i++)
|
||||
raw6()[i] = 0;
|
||||
}
|
||||
|
||||
setV6();
|
||||
return true;
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
// Get host by name working for IPv6
|
||||
// --------------------------------------------------
|
||||
#include "lwip/dns.h"
|
||||
|
||||
/**
|
||||
* DNS callback
|
||||
* @param name
|
||||
* @param ipaddr
|
||||
* @param callback_arg
|
||||
*/
|
||||
static void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg)
|
||||
{
|
||||
if(ipaddr) {
|
||||
(*reinterpret_cast<IPAddress46*>(callback_arg)) = IPAddress46(ipaddr);
|
||||
}
|
||||
WiFiGeneric46::DnsDone();
|
||||
// xEventGroupSetBits(_arduino_event_group, WIFI_DNS_DONE_BIT);
|
||||
}
|
||||
|
||||
int WiFiGeneric46::hostByName(const char* aHostname, IPAddress46& aResult) {
|
||||
ip_addr_t addr;
|
||||
aResult = static_cast<uint32_t>(INADDR_NONE);
|
||||
waitStatusBits(WIFI_DNS_IDLE_BIT, 16000);
|
||||
clearStatusBits(WIFI_DNS_IDLE_BIT | WIFI_DNS_DONE_BIT);
|
||||
err_t err = dns_gethostbyname_addrtype(aHostname, &addr, &wifi_dns_found_callback, &aResult, LWIP_DNS_ADDRTYPE_DEFAULT);
|
||||
AddLog(LOG_LEVEL_DEBUG, "WIF: WiFiGeneric46::hostByName err=%i", err);
|
||||
|
||||
if(err == ERR_OK) {
|
||||
aResult = IPAddress46(&addr);
|
||||
|
||||
if (!aResult.isSet()) {
|
||||
#if LWIP_IPV6
|
||||
aResult.setV6();
|
||||
#else
|
||||
aResult.setV4();
|
||||
#endif
|
||||
}
|
||||
} else if(err == ERR_INPROGRESS) {
|
||||
waitStatusBits(WIFI_DNS_DONE_BIT, 15000); //real internal timeout in lwip library is 14[s]
|
||||
clearStatusBits(WIFI_DNS_DONE_BIT);
|
||||
}
|
||||
setStatusBits(WIFI_DNS_IDLE_BIT);
|
||||
|
||||
if(err == ERR_OK) {
|
||||
AddLog(LOG_LEVEL_DEBUG, "WIF: WiFiGeneric46::hostByName Host: %s IP: %s", aHostname ? aHostname : "<null>", aResult.toString().c_str());
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,198 +0,0 @@
|
|||
/*
|
||||
IPAddress46.h - IPv6 support for ESP32
|
||||
|
||||
This class is copied from ESP8266 Arduino framework and provides
|
||||
temporary support for IPv6 on ESP32.
|
||||
|
||||
Copyright (C) 2021 Theo Arends and Stephan Hadinger
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __IPADDRESS46_H
|
||||
#define __IPADDRESS46_H
|
||||
|
||||
#include <Printable.h>
|
||||
#include <WString.h>
|
||||
#include <lwip/netif.h>
|
||||
|
||||
class IPAddress46: 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());
|
||||
}
|
||||
|
||||
void ctor32 (uint32_t);
|
||||
|
||||
public:
|
||||
// Constructors
|
||||
IPAddress46();
|
||||
IPAddress46(const IPAddress46& from);
|
||||
IPAddress46(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet);
|
||||
IPAddress46(uint32_t address) { ctor32(address); }
|
||||
IPAddress46(unsigned long address) { ctor32(address); }
|
||||
IPAddress46(int address) { ctor32(address); }
|
||||
IPAddress46(const uint8_t *address);
|
||||
|
||||
bool fromString(const char *address);
|
||||
bool fromString(const String &address) { return fromString(address.c_str()); }
|
||||
|
||||
// Overloaded cast operator to allow IPAddress46 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; } // for raw_address(const)
|
||||
uint32_t& v4() { return ip_2_ip4(&_ip)->addr; }
|
||||
|
||||
bool operator==(const IPAddress46& addr) const {
|
||||
return ip_addr_cmp(&_ip, &addr._ip);
|
||||
}
|
||||
bool operator!=(const IPAddress46& 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 {
|
||||
return isV4()? *(raw_address() + index): 0;
|
||||
}
|
||||
uint8_t& operator[](int index) {
|
||||
setV4();
|
||||
return *(raw_address() + index);
|
||||
}
|
||||
|
||||
// Overloaded copy operators to allow initialisation of IPAddress46 objects from other types
|
||||
IPAddress46& operator=(const uint8_t *address);
|
||||
IPAddress46& operator=(uint32_t address);
|
||||
IPAddress46& operator=(const IPAddress46&) = 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 UDP46;
|
||||
friend class Client;
|
||||
friend class Server;
|
||||
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); }
|
||||
|
||||
#if LWIP_IPV6
|
||||
IPAddress46(const ip_addr_t& lwip_addr) { ip_addr_copy(_ip, lwip_addr); }
|
||||
IPAddress46(const ip_addr_t* lwip_addr) { ip_addr_copy(_ip, *lwip_addr); }
|
||||
|
||||
IPAddress46& operator=(const ip_addr_t& lwip_addr) { ip_addr_copy(_ip, lwip_addr); return *this; }
|
||||
IPAddress46& 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);
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// We need to create a subclass of WiFiGenericClass to access protected methods
|
||||
// --------------------------------------------------------------------------------
|
||||
#include "WiFiGeneric.h"
|
||||
|
||||
class WiFiGeneric46 : public WiFiGenericClass
|
||||
{
|
||||
public:
|
||||
WiFiGeneric46() {};
|
||||
|
||||
static int hostByName(const char *aHostname, IPAddress46 &aResult);
|
||||
static void DnsDone(void) { setStatusBits(WIFI_DNS_DONE_BIT); };
|
||||
};
|
||||
|
||||
#endif // __IPADDRESS46_H
|
|
@ -1,93 +0,0 @@
|
|||
/*
|
||||
* Udp.cpp: Library to send/receive UDP packets.
|
||||
*
|
||||
* NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these)
|
||||
* 1) UDP does not guarantee the order in which assembled UDP packets are received. This
|
||||
* might not happen often in practice, but in larger network topologies, a UDP
|
||||
* packet can be received out of sequence.
|
||||
* 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being
|
||||
* aware of it. Again, this may not be a concern in practice on small local networks.
|
||||
* For more information, see http://www.cafeaulait.org/course/week12/35.html
|
||||
*
|
||||
* MIT License:
|
||||
* Copyright (c) 2008 Bjoern Hartmann
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* bjoern@cs.stanford.edu 12/30/2008
|
||||
*/
|
||||
|
||||
#ifndef udp46_h
|
||||
#define udp46_h
|
||||
|
||||
#include <Stream.h>
|
||||
#include <IPAddress46.h>
|
||||
|
||||
class UDP46: public Stream
|
||||
{
|
||||
|
||||
public:
|
||||
virtual uint8_t begin(uint16_t) =0; // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use
|
||||
virtual uint8_t beginMulticast(IPAddress46, uint16_t) { return 0; } // initialize, start listening on specified multicast IP address and port. Returns 1 if successful, 0 on failure
|
||||
virtual void stop() =0; // Finish with the UDP socket
|
||||
|
||||
// Sending UDP packets
|
||||
|
||||
// Start building up a packet to send to the remote host specific in ip and port
|
||||
// Returns 1 if successful, 0 if there was a problem with the supplied IP address or port
|
||||
virtual int beginPacket(IPAddress46 ip, uint16_t port) =0;
|
||||
// Start building up a packet to send to the remote host specific in host and port
|
||||
// Returns 1 if successful, 0 if there was a problem resolving the hostname or port
|
||||
virtual int beginPacket(const char *host, uint16_t port) =0;
|
||||
// Finish off this packet and send it
|
||||
// Returns 1 if the packet was sent successfully, 0 if there was an error
|
||||
virtual int endPacket() =0;
|
||||
// Write a single byte into the packet
|
||||
virtual size_t write(uint8_t) =0;
|
||||
// Write size bytes from buffer into the packet
|
||||
virtual size_t write(const uint8_t *buffer, size_t size) =0;
|
||||
|
||||
// Start processing the next available incoming packet
|
||||
// Returns the size of the packet in bytes, or 0 if no packets are available
|
||||
virtual int parsePacket() =0;
|
||||
// Number of bytes remaining in the current packet
|
||||
virtual int available() =0;
|
||||
// Read a single byte from the current packet
|
||||
virtual int read() =0;
|
||||
// Read up to len bytes from the current packet and place them into buffer
|
||||
// Returns the number of bytes read, or 0 if none are available
|
||||
virtual int read(unsigned char* buffer, size_t len) =0;
|
||||
// Read up to len characters from the current packet and place them into buffer
|
||||
// Returns the number of characters read, or 0 if none are available
|
||||
virtual int read(char* buffer, size_t len) =0;
|
||||
// Return the next byte from the current packet without moving on to the next byte
|
||||
virtual int peek() =0;
|
||||
virtual void flush() =0; // Finish reading the current packet
|
||||
|
||||
// Return the IP address of the host who sent the current incoming packet
|
||||
virtual IPAddress46 remoteIP() =0;
|
||||
// Return the port of the host who sent the current incoming packet
|
||||
virtual uint16_t remotePort() =0;
|
||||
protected:
|
||||
uint8_t* rawIPAddress(IPAddress46& addr)
|
||||
{
|
||||
return addr.raw_address();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,335 +0,0 @@
|
|||
/*
|
||||
Udp.cpp - UDP class for Raspberry Pi
|
||||
Copyright (c) 2016 Hristo Gochkov 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
|
||||
*/
|
||||
#include "WiFiUdp46.h"
|
||||
#include <lwip/sockets.h>
|
||||
#include <lwip/netdb.h>
|
||||
#include <errno.h>
|
||||
|
||||
#undef write
|
||||
#undef read
|
||||
|
||||
// Tasmota Logging
|
||||
extern void AddLog(uint32_t loglevel, PGM_P formatP, ...);
|
||||
enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE};
|
||||
|
||||
WiFiUDP46::WiFiUDP46()
|
||||
: udp_server(-1)
|
||||
, server_port(0)
|
||||
, remote_port(0)
|
||||
, tx_buffer(0)
|
||||
, tx_buffer_len(0)
|
||||
, rx_buffer(0)
|
||||
{}
|
||||
|
||||
WiFiUDP46::~WiFiUDP46(){
|
||||
stop();
|
||||
}
|
||||
|
||||
uint8_t WiFiUDP46::begin(IPAddress46 address, uint16_t port){
|
||||
stop();
|
||||
server_port = port;
|
||||
|
||||
tx_buffer = new char[1460];
|
||||
if(!tx_buffer){
|
||||
log_e("could not create tx buffer: %d", errno);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if LWIP_IPV6
|
||||
if ((udp_server=socket(AF_INET6, SOCK_DGRAM, 0)) == -1){
|
||||
#else
|
||||
if ((udp_server=socket(AF_INET, SOCK_DGRAM, 0)) == -1){
|
||||
#endif
|
||||
log_e("could not create socket: %d", errno);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// AddLog(LOG_LEVEL_DEBUG, "WiFiUDP46::begin socket called");
|
||||
int yes = 1;
|
||||
if (setsockopt(udp_server,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)) < 0) {
|
||||
log_e("could not set socket option: %d", errno);
|
||||
stop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//AddLog(LOG_LEVEL_DEBUG, "WiFiUDP46::begin setsockopt called");
|
||||
|
||||
struct sockaddr* sock_addr = NULL;
|
||||
size_t sock_size = 0;
|
||||
struct sockaddr_in addr;
|
||||
#if LWIP_IPV6
|
||||
struct sockaddr_in6 addr6;
|
||||
if (address.isV6()) {
|
||||
// AddLog(LOG_LEVEL_DEBUG, "WiFiUDP46::begin set IPv6");
|
||||
memset((char *) &addr6, 0, sizeof(sockaddr_in6));
|
||||
addr6.sin6_len = sizeof(sockaddr_in6);
|
||||
addr6.sin6_family = AF_INET6;
|
||||
addr6.sin6_port = htons(server_port);
|
||||
addr6.sin6_addr = *(in6_addr*)(ip_addr_t*)address;
|
||||
addr6.sin6_addr = in6addr_any;
|
||||
addr6.sin6_flowinfo = 0;
|
||||
sock_addr = (struct sockaddr*)&addr6;
|
||||
sock_size = sizeof(sockaddr_in6);
|
||||
|
||||
// AddLog(LOG_LEVEL_DEBUG, "SOCK_ADDR_TYPE_MATCH(name, sock)=%i", SOCK_ADDR_TYPE_MATCH(sock_addr, sock_size));
|
||||
} else
|
||||
#endif
|
||||
if (1) {
|
||||
memset((char *) &addr, 0, sizeof(sockaddr_in));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(server_port);
|
||||
addr.sin_addr.s_addr = (in_addr_t)address;
|
||||
sock_addr = (struct sockaddr*)&addr;
|
||||
sock_size = sizeof(sockaddr_in);
|
||||
}
|
||||
//AddLog(LOG_LEVEL_DEBUG, "WiFiUDP46::begin udp_server=%p sock_addr=%p sock_size=%i", udp_server, sock_addr, sock_size);
|
||||
if(bind(udp_server , sock_addr, sock_size) == -1){
|
||||
AddLog(LOG_LEVEL_DEBUG, "WIF: WiFiUDP46::begin bind error=%o", errno);
|
||||
log_e("could not bind socket: %d", errno);
|
||||
stop();
|
||||
return 0;
|
||||
}
|
||||
fcntl(udp_server, F_SETFL, O_NONBLOCK);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t WiFiUDP46::begin(uint16_t p){
|
||||
return begin(IPAddress46(), p);
|
||||
}
|
||||
|
||||
uint8_t WiFiUDP46::beginMulticast(IPAddress46 a, uint16_t p){
|
||||
if(begin(IPAddress46(), p)){
|
||||
if(!ip_addr_isany((ip_addr_t*)a)){
|
||||
struct ip_mreq mreq;
|
||||
mreq.imr_multiaddr.s_addr = (in_addr_t)a;
|
||||
mreq.imr_interface.s_addr = INADDR_ANY;
|
||||
if (setsockopt(udp_server, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
|
||||
log_e("could not join igmp: %d", errno);
|
||||
stop();
|
||||
return 0;
|
||||
}
|
||||
multicast_ip = a;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void WiFiUDP46::stop(){
|
||||
if(tx_buffer){
|
||||
delete[] tx_buffer;
|
||||
tx_buffer = NULL;
|
||||
}
|
||||
tx_buffer_len = 0;
|
||||
if(rx_buffer){
|
||||
cbuf *b = rx_buffer;
|
||||
rx_buffer = NULL;
|
||||
delete b;
|
||||
}
|
||||
if(udp_server == -1)
|
||||
return;
|
||||
if(!ip_addr_isany((ip_addr_t*)multicast_ip)){
|
||||
struct ip_mreq mreq;
|
||||
mreq.imr_multiaddr.s_addr = (in_addr_t)multicast_ip;
|
||||
mreq.imr_interface.s_addr = (in_addr_t)0;
|
||||
#if LWIP_IPV6
|
||||
setsockopt(udp_server, IPPROTO_IPV6, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq));
|
||||
#else
|
||||
setsockopt(udp_server, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq));
|
||||
#endif
|
||||
multicast_ip = IPAddress46(INADDR_ANY);
|
||||
}
|
||||
close(udp_server);
|
||||
udp_server = -1;
|
||||
}
|
||||
|
||||
int WiFiUDP46::beginMulticastPacket(){
|
||||
if(!server_port || multicast_ip == IPAddress46(INADDR_ANY))
|
||||
return 0;
|
||||
remote_ip = multicast_ip;
|
||||
remote_port = server_port;
|
||||
return beginPacket();
|
||||
}
|
||||
|
||||
int WiFiUDP46::beginPacket(){
|
||||
if(!remote_port)
|
||||
return 0;
|
||||
|
||||
// allocate tx_buffer if is necessary
|
||||
if(!tx_buffer){
|
||||
tx_buffer = new char[1460];
|
||||
if(!tx_buffer){
|
||||
log_e("could not create tx buffer: %d", errno);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
tx_buffer_len = 0;
|
||||
|
||||
// check whereas socket is already open
|
||||
if (udp_server != -1)
|
||||
return 1;
|
||||
|
||||
if ((udp_server=socket(AF_INET, SOCK_DGRAM, 0)) == -1){
|
||||
log_e("could not create socket: %d", errno);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fcntl(udp_server, F_SETFL, O_NONBLOCK);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WiFiUDP46::beginPacket(IPAddress46 ip, uint16_t port){
|
||||
remote_ip = ip;
|
||||
remote_port = port;
|
||||
return beginPacket();
|
||||
}
|
||||
|
||||
int WiFiUDP46::beginPacket(const char *host, uint16_t port){
|
||||
struct hostent *server;
|
||||
server = gethostbyname(host);
|
||||
if (server == NULL){
|
||||
log_e("could not get host from dns: %d", errno);
|
||||
return 0;
|
||||
}
|
||||
return beginPacket(IPAddress46((const uint8_t *)(server->h_addr_list[0])), port);
|
||||
}
|
||||
|
||||
int WiFiUDP46::endPacket(){
|
||||
if (remote_ip.isV4()) {
|
||||
struct sockaddr_in recipient;
|
||||
recipient.sin_len = sizeof(sockaddr_in);
|
||||
recipient.sin_addr.s_addr = (uint32_t)remote_ip;
|
||||
recipient.sin_family = AF_INET;
|
||||
recipient.sin_port = htons(remote_port);
|
||||
int sent = sendto(udp_server, tx_buffer, tx_buffer_len, 0, (struct sockaddr*) &recipient, sizeof(recipient));
|
||||
if(sent < 0){
|
||||
log_e("could not send data: %d", errno);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
struct sockaddr_in6 recipient;
|
||||
recipient.sin6_len = sizeof(sockaddr_in6);
|
||||
recipient.sin6_flowinfo = 0;
|
||||
recipient.sin6_addr = *(in6_addr*)(ip_addr_t*)remote_ip;
|
||||
// recipient.sin6_family = AF_INET6;
|
||||
recipient.sin6_port = htons(remote_port);
|
||||
int sent = sendto(udp_server, tx_buffer, tx_buffer_len, 0, (struct sockaddr*) &recipient, sizeof(recipient));
|
||||
if(sent < 0){
|
||||
log_e("could not send data: %d", errno);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t WiFiUDP46::write(uint8_t data){
|
||||
if(tx_buffer_len == 1460){
|
||||
endPacket();
|
||||
tx_buffer_len = 0;
|
||||
}
|
||||
tx_buffer[tx_buffer_len++] = data;
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t WiFiUDP46::write(const uint8_t *buffer, size_t size){
|
||||
size_t i;
|
||||
for(i=0;i<size;i++)
|
||||
write(buffer[i]);
|
||||
return i;
|
||||
}
|
||||
|
||||
int WiFiUDP46::parsePacket(){
|
||||
if(rx_buffer)
|
||||
return 0;
|
||||
struct sockaddr_in si_other;
|
||||
int slen = sizeof(si_other) , len;
|
||||
char * buf = new char[1460];
|
||||
if(!buf){
|
||||
return 0;
|
||||
}
|
||||
if ((len = recvfrom(udp_server, buf, 1460, MSG_DONTWAIT, (struct sockaddr *) &si_other, (socklen_t *)&slen)) == -1){
|
||||
delete[] buf;
|
||||
if(errno == EWOULDBLOCK){
|
||||
return 0;
|
||||
}
|
||||
log_e("could not receive data: %d", errno);
|
||||
return 0;
|
||||
}
|
||||
remote_ip = IPAddress46(si_other.sin_addr.s_addr);
|
||||
remote_port = ntohs(si_other.sin_port);
|
||||
if (len > 0) {
|
||||
rx_buffer = new cbuf(len);
|
||||
rx_buffer->write(buf, len);
|
||||
}
|
||||
delete[] buf;
|
||||
return len;
|
||||
}
|
||||
|
||||
int WiFiUDP46::available(){
|
||||
if(!rx_buffer) return 0;
|
||||
return rx_buffer->available();
|
||||
}
|
||||
|
||||
int WiFiUDP46::read(){
|
||||
if(!rx_buffer) return -1;
|
||||
int out = rx_buffer->read();
|
||||
if(!rx_buffer->available()){
|
||||
cbuf *b = rx_buffer;
|
||||
rx_buffer = 0;
|
||||
delete b;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
int WiFiUDP46::read(unsigned char* buffer, size_t len){
|
||||
return read((char *)buffer, len);
|
||||
}
|
||||
|
||||
int WiFiUDP46::read(char* buffer, size_t len){
|
||||
if(!rx_buffer) return 0;
|
||||
int out = rx_buffer->read(buffer, len);
|
||||
if(!rx_buffer->available()){
|
||||
cbuf *b = rx_buffer;
|
||||
rx_buffer = 0;
|
||||
delete b;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
int WiFiUDP46::peek(){
|
||||
if(!rx_buffer) return -1;
|
||||
return rx_buffer->peek();
|
||||
}
|
||||
|
||||
void WiFiUDP46::flush(){
|
||||
if(!rx_buffer) return;
|
||||
cbuf *b = rx_buffer;
|
||||
rx_buffer = 0;
|
||||
delete b;
|
||||
}
|
||||
|
||||
IPAddress46 WiFiUDP46::remoteIP(){
|
||||
return remote_ip;
|
||||
}
|
||||
|
||||
uint16_t WiFiUDP46::remotePort(){
|
||||
return remote_port;
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
/*
|
||||
* Udp.cpp: Library to send/receive UDP packets.
|
||||
*
|
||||
* NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these)
|
||||
* 1) UDP does not guarantee the order in which assembled UDP packets are received. This
|
||||
* might not happen often in practice, but in larger network topologies, a UDP
|
||||
* packet can be received out of sequence.
|
||||
* 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being
|
||||
* aware of it. Again, this may not be a concern in practice on small local networks.
|
||||
* For more information, see http://www.cafeaulait.org/course/week12/35.html
|
||||
*
|
||||
* MIT License:
|
||||
* Copyright (c) 2008 Bjoern Hartmann
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* bjoern@cs.stanford.edu 12/30/2008
|
||||
*/
|
||||
|
||||
#ifndef _WIFIUDP46_H_
|
||||
#define _WIFIUDP46_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Udp46.h>
|
||||
#include <cbuf.h>
|
||||
|
||||
class WiFiUDP46 : public UDP46 {
|
||||
private:
|
||||
int udp_server;
|
||||
IPAddress46 multicast_ip;
|
||||
IPAddress46 remote_ip;
|
||||
uint16_t server_port;
|
||||
uint16_t remote_port;
|
||||
char * tx_buffer;
|
||||
size_t tx_buffer_len;
|
||||
cbuf * rx_buffer;
|
||||
public:
|
||||
WiFiUDP46();
|
||||
~WiFiUDP46();
|
||||
uint8_t begin(IPAddress46 a, uint16_t p);
|
||||
uint8_t begin(uint16_t p);
|
||||
uint8_t beginMulticast(IPAddress46 a, uint16_t p);
|
||||
void stop();
|
||||
int beginMulticastPacket();
|
||||
int beginPacket();
|
||||
int beginPacket(IPAddress46 ip, uint16_t port);
|
||||
int beginPacket(const char *host, uint16_t port);
|
||||
int endPacket();
|
||||
size_t write(uint8_t);
|
||||
size_t write(const uint8_t *buffer, size_t size);
|
||||
int parsePacket();
|
||||
int available();
|
||||
int read();
|
||||
int read(unsigned char* buffer, size_t len);
|
||||
int read(char* buffer, size_t len);
|
||||
int peek();
|
||||
void flush();
|
||||
IPAddress46 remoteIP();
|
||||
uint16_t remotePort();
|
||||
};
|
||||
|
||||
#endif /* _WIFIUDP46_H_ */
|
|
@ -137,8 +137,6 @@ typedef int SerialConfig;
|
|||
//#define PortUdp_writestr(log_data) PortUdp.write((const uint8_t *)(log_data), strlen(log_data))
|
||||
#define PortUdp_write(log_data, n) PortUdp.write((const uint8_t *)(log_data), n)
|
||||
|
||||
#undef LWIP_IPV6
|
||||
|
||||
#define REASON_DEFAULT_RST 0 // "Power on" normal startup by power on
|
||||
#define REASON_WDT_RST 1 // "Hardware Watchdog" hardware watch dog reset
|
||||
#define REASON_EXCEPTION_RST 2 // "Exception" exception reset, GPIO status won’t change
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
#include <Arduino.h>
|
||||
#include <WiFiGeneric.h>
|
||||
#include <WiFiUdp46.h>
|
||||
#include <WiFiUdp.h>
|
||||
#include "be_mapping.h"
|
||||
|
||||
// Tasmota Logging
|
||||
|
@ -25,15 +25,15 @@ enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_D
|
|||
extern "C" {
|
||||
|
||||
// init()
|
||||
WiFiUDP46 *be_udp_init_ntv(void) {
|
||||
return new WiFiUDP46();
|
||||
WiFiUDP *be_udp_init_ntv(void) {
|
||||
return new WiFiUDP();
|
||||
}
|
||||
int32_t be_udp_init(struct bvm *vm) {
|
||||
return be_call_c_func(vm, (void*) &be_udp_init_ntv, "+.p", "");
|
||||
}
|
||||
|
||||
// deinit()
|
||||
void *be_udp_deinit_ntv(WiFiUDP46 *udp) {
|
||||
void *be_udp_deinit_ntv(WiFiUDP *udp) {
|
||||
if (udp != nullptr) { delete udp; }
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -42,8 +42,8 @@ extern "C" {
|
|||
}
|
||||
|
||||
// udp.begin(address:string, port:int) -> bool
|
||||
int32_t be_udp_begin_ntv(WiFiUDP46 *udp, int32_t port) {
|
||||
IPAddress46 addr;
|
||||
int32_t be_udp_begin_ntv(WiFiUDP *udp, int32_t port) {
|
||||
IPAddress addr;
|
||||
// AddLog(LOG_LEVEL_DEBUG, "BRY: udp.begin listening to '%s'", addr.toString().c_str());
|
||||
return udp->begin(addr, port);
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ extern "C" {
|
|||
}
|
||||
|
||||
// udp.stop() -> nil
|
||||
void be_udp_stop_ntv(WiFiUDP46 *udp) {
|
||||
void be_udp_stop_ntv(WiFiUDP *udp) {
|
||||
udp->stop();
|
||||
}
|
||||
int32_t be_udp_stop(struct bvm *vm) {
|
||||
|
@ -65,21 +65,21 @@ extern "C" {
|
|||
}
|
||||
|
||||
// udp.begin_multicast(address:string, port:int) -> nil
|
||||
int32_t be_udp_begin_mcast_ntv(WiFiUDP46 *udp, const char *host, int32_t port) {
|
||||
IPAddress46 addr;
|
||||
if(!WiFiGeneric46::hostByName(host, addr)){
|
||||
int32_t be_udp_begin_mcast_ntv(WiFiUDP *udp, const char *host, int32_t port) {
|
||||
IPAddress addr;
|
||||
if(!WiFiGenericClass::hostByName(host, addr)){
|
||||
return 0;
|
||||
}
|
||||
return udp->WiFiUDP46::beginMulticast(addr, port);
|
||||
return udp->WiFiUDP::beginMulticast(addr, port);
|
||||
}
|
||||
int32_t be_udp_begin_mcast(struct bvm *vm) {
|
||||
return be_call_c_func(vm, (void*) &be_udp_begin_mcast_ntv, "b", ".si");
|
||||
}
|
||||
|
||||
// udp.send(address:string, port:int, payload:bytes) -> bool
|
||||
int32_t be_udp_send_ntv(WiFiUDP46 *udp, const char *host, int32_t port, const uint8_t* buf, int32_t len) {
|
||||
IPAddress46 addr;
|
||||
if (!WiFiGeneric46::hostByName(host, addr)){
|
||||
int32_t be_udp_send_ntv(WiFiUDP *udp, const char *host, int32_t port, const uint8_t* buf, int32_t len) {
|
||||
IPAddress addr;
|
||||
if (!WiFiGenericClass::hostByName(host, addr)){
|
||||
return 0;
|
||||
}
|
||||
// AddLog(LOG_LEVEL_DEBUG, "BRY: udp.begin got host '%s'", addr.toString().c_str());
|
||||
|
@ -94,7 +94,7 @@ extern "C" {
|
|||
}
|
||||
|
||||
// udp.send_multicast(payload:bytes) -> bool
|
||||
int32_t be_udp_send_mcast_ntv(WiFiUDP46 *udp, const uint8_t* buf, int32_t len) {
|
||||
int32_t be_udp_send_mcast_ntv(WiFiUDP *udp, const uint8_t* buf, int32_t len) {
|
||||
if (!udp->beginMulticastPacket()) { return 0; }
|
||||
int bw = udp->write(buf, len);
|
||||
if (!bw) { return 0; }
|
||||
|
@ -107,7 +107,7 @@ extern "C" {
|
|||
|
||||
// udp.read() -> bytes or nil
|
||||
int32_t be_udp_read(struct bvm *vm) {
|
||||
WiFiUDP46 *udp = (WiFiUDP46*) be_convert_single_elt(vm, 1, NULL, NULL);
|
||||
WiFiUDP *udp = (WiFiUDP*) be_convert_single_elt(vm, 1, NULL, NULL);
|
||||
if (udp->parsePacket()) {
|
||||
int btr = udp->available(); // btr contains the size of bytes_to_read
|
||||
|
||||
|
@ -135,7 +135,7 @@ extern "C" {
|
|||
int32_t btr2 = udp->read(buf, btr);
|
||||
|
||||
// set remotet ip
|
||||
IPAddress46 remote_ip = udp->remoteIP();
|
||||
IPAddress remote_ip = udp->remoteIP();
|
||||
be_pushstring(vm, remote_ip.toString().c_str());
|
||||
be_setmember(vm, 1, "remote_ip");
|
||||
be_pop(vm, 1);
|
||||
|
|
|
@ -405,6 +405,12 @@
|
|||
#define WIFI_SOFT_AP_CHANNEL 1 // Soft Access Point Channel number between 1 and 13 as used by Wi-Fi Manager web GUI
|
||||
#define USE_IMPROV // Add support for IMPROV serial protocol as used by esp-web-tools (+2k code)
|
||||
|
||||
// -- IPv6 support -------------------------------
|
||||
// #define USE_IPV6 // Enable IPv6 support (if the underlying esp-idf is also configured to support it)
|
||||
// Code size increase:
|
||||
// ESP8266: tbd
|
||||
// ESP32: tbd
|
||||
|
||||
// -- ESP-NOW -------------------------------------
|
||||
//#define USE_TASMESH // Enable Tasmota Mesh using ESP-NOW (+11k code)
|
||||
|
||||
|
|
|
@ -32,6 +32,13 @@
|
|||
#include "include/i18n.h" // Language support configured by my_user_config.h
|
||||
#include "include/tasmota_template.h" // Hardware configuration
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
// If IPv6 is not support by the underlying esp-idf, disable it
|
||||
// ------------------------------------------------------------------------------------------
|
||||
#if !LWIP_IPV6
|
||||
#undef USE_IPV6
|
||||
#endif
|
||||
|
||||
// Libraries
|
||||
#include <ESP8266HTTPClient.h> // Ota
|
||||
#include <ESP8266httpUpdate.h> // Ota
|
||||
|
@ -494,7 +501,7 @@ void setup(void) {
|
|||
#ifdef ESP32
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("HDW: %s %s"), GetDeviceHardware().c_str(),
|
||||
FoundPSRAM() ? (CanUsePSRAM() ? "(PSRAM)" : "(PSRAM disabled)") : "" );
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("HDW: FoundPSRAM=%i CanUsePSRAM=%i"), FoundPSRAM(), CanUsePSRAM());
|
||||
// AddLog(LOG_LEVEL_DEBUG, PSTR("HDW: FoundPSRAM=%i CanUsePSRAM=%i"), FoundPSRAM(), CanUsePSRAM());
|
||||
#if !defined(HAS_PSRAM_FIX)
|
||||
if (FoundPSRAM() && !CanUsePSRAM()) {
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("HDW: PSRAM is disabled, requires specific compilation on this hardware (see doc)"));
|
||||
|
|
|
@ -802,24 +802,24 @@ void CmndStatus(void)
|
|||
}
|
||||
|
||||
if ((0 == payload) || (5 == payload)) {
|
||||
#if LWIP_IPV6
|
||||
#ifdef USE_IPV6
|
||||
if (5 == payload) { WifiDumpAddressesIPv6(); }
|
||||
#endif // LWIP_IPV6
|
||||
#endif // USE_IPV6
|
||||
Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS5_NETWORK "\":{\"" D_CMND_HOSTNAME "\":\"%s\",\""
|
||||
D_CMND_IPADDRESS "\":\"%_I\",\"" D_JSON_GATEWAY "\":\"%_I\",\"" D_JSON_SUBNETMASK "\":\"%_I\",\""
|
||||
D_JSON_DNSSERVER "1\":\"%_I\",\"" D_JSON_DNSSERVER "2\":\"%_I\",\""
|
||||
D_JSON_MAC "\":\"%s\""
|
||||
#if LWIP_IPV6
|
||||
#ifdef USE_IPV6
|
||||
",\"" D_JSON_IP6_GLOBAL "\":\"%s\",\"" D_JSON_IP6_LOCAL "\":\"%s\""
|
||||
#endif // LWIP_IPV6
|
||||
#endif // USE_IPV6
|
||||
),
|
||||
TasmotaGlobal.hostname,
|
||||
(uint32_t)WiFi.localIP(), Settings->ipv4_address[1], Settings->ipv4_address[2],
|
||||
Settings->ipv4_address[3], Settings->ipv4_address[4],
|
||||
WiFi.macAddress().c_str()
|
||||
#if LWIP_IPV6
|
||||
#ifdef USE_IPV6
|
||||
,WifiGetIPv6().c_str(), WifiGetIPv6LinkLocal().c_str()
|
||||
#endif // LWIP_IPV6
|
||||
#endif // USE_IPV6
|
||||
);
|
||||
#ifdef USE_TASMESH
|
||||
ResponseAppend_P(PSTR(",\"SoftAPMac\":\"%s\""), WiFi.softAPmacAddress().c_str());
|
||||
|
@ -830,17 +830,17 @@ void CmndStatus(void)
|
|||
D_JSON_DNSSERVER "1\":\"%_I\",\"" D_JSON_DNSSERVER "2\":\"%_I\",\""
|
||||
D_JSON_MAC "\":\"%s\""
|
||||
|
||||
#if LWIP_IPV6
|
||||
#ifdef USE_IPV6
|
||||
",\"" D_JSON_IP6_GLOBAL "\":\"%s\",\"" D_JSON_IP6_LOCAL "\":\"%s\""
|
||||
#endif // LWIP_IPV6
|
||||
#endif // USE_IPV6
|
||||
"}"),
|
||||
EthernetHostname(),
|
||||
(uint32_t)EthernetLocalIP(), Settings->eth_ipv4_address[1], Settings->eth_ipv4_address[2],
|
||||
Settings->eth_ipv4_address[3], Settings->eth_ipv4_address[4],
|
||||
EthernetMacAddress().c_str()
|
||||
#if LWIP_IPV6
|
||||
#ifdef USE_IPV6
|
||||
,EthernetGetIPv6().c_str(), EthernetGetIPv6LinkLocal().c_str()
|
||||
#endif // LWIP_IPV6
|
||||
#endif // USE_IPV6
|
||||
);
|
||||
#endif // USE_ETHERNET
|
||||
ResponseAppend_P(PSTR(",\"" D_CMND_WEBSERVER "\":%d,\"HTTP_API\":%d,\"" D_CMND_WIFICONFIG "\":%d,\"" D_CMND_WIFIPOWER "\":%s}}"),
|
||||
|
|
|
@ -41,13 +41,6 @@ const uint8_t WIFI_CHECK_SEC = 20; // seconds
|
|||
const uint8_t WIFI_RETRY_OFFSET_SEC = WIFI_RETRY_SECONDS; // seconds
|
||||
|
||||
#include <ESP8266WiFi.h> // Wifi, MQTT, Ota, WifiManager
|
||||
#if LWIP_IPV6
|
||||
#ifdef ESP8266
|
||||
#include <AddrList.h> // IPv6 DualStack
|
||||
#else
|
||||
#include <AddrList46.h> // IPv6 DualStack
|
||||
#endif
|
||||
#endif // LWIP_IPV6=1
|
||||
|
||||
int WifiGetRssiAsQuality(int rssi) {
|
||||
int quality = 0;
|
||||
|
@ -213,7 +206,7 @@ void WifiBegin(uint8_t flag, uint8_t channel) {
|
|||
#endif // USE_EMULATION
|
||||
|
||||
WiFi.persistent(false); // Solve possible wifi init errors (re-add at 6.2.1.16 #4044, #4083)
|
||||
#if LWIP_IPV6 && defined(ESP32)
|
||||
#if defined(USE_IPV6) && defined(ESP32)
|
||||
WiFi.IPv6(true);
|
||||
#endif
|
||||
|
||||
|
@ -465,7 +458,7 @@ void WifiSetState(uint8_t state)
|
|||
}
|
||||
}
|
||||
|
||||
#if LWIP_IPV6
|
||||
#ifdef USE_IPV6
|
||||
//
|
||||
// Scan through all interfaces to find a global or local IPv6 address
|
||||
// Arg:
|
||||
|
@ -476,8 +469,8 @@ static String WifiFindIPv6(bool is_local, const char * if_type = "st") {
|
|||
if (intf->name[0] == if_type[0] && intf->name[1] == if_type[1]) {
|
||||
for (uint32_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
|
||||
ip_addr_t *ipv6 = &intf->ip6_addr[i];
|
||||
if (IP_IS_V6_VAL(*ipv6) && !ip_addr_isloopback(ipv6) && ((bool)ip_addr_islinklocal(ipv6) == is_local)) {
|
||||
return IPAddress46(ipv6).toString();
|
||||
if (IP_IS_V6_VAL(*ipv6) && !ip_addr_isloopback(ipv6) && !ip_addr_isany(ipv6) && ((bool)ip_addr_islinklocal(ipv6) == is_local)) {
|
||||
return IPAddress(ipv6).toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -510,33 +503,28 @@ void CreateLinkLocalIPv6(void)
|
|||
void WifiDumpAddressesIPv6(void)
|
||||
{
|
||||
for (netif* intf = netif_list; intf != nullptr; intf = intf->next) {
|
||||
if (!ip_addr_isany_val(intf->ip_addr)) AddLog(LOG_LEVEL_DEBUG, "WIF: '%c%c' IPv4 %s", intf->name[0], intf->name[1], IPAddress46(intf->ip_addr).toString().c_str());
|
||||
if (!ip_addr_isany_val(intf->ip_addr)) AddLog(LOG_LEVEL_DEBUG, "WIF: '%c%c' IPv4 %s", intf->name[0], intf->name[1], IPAddress(intf->ip_addr).toString().c_str());
|
||||
for (uint32_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
|
||||
if (!ip_addr_isany_val(intf->ip6_addr[i]))
|
||||
AddLog(LOG_LEVEL_DEBUG, "WIF: '%c%c' IPv6 %s %s", intf->name[0], intf->name[1],
|
||||
IPAddress46(intf->ip6_addr[i]).toString().c_str(),
|
||||
IPAddress(intf->ip6_addr[i]).toString().c_str(),
|
||||
ip_addr_islinklocal(&intf->ip6_addr[i]) ? "local" : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // LWIP_IPV6=1
|
||||
#endif // USE_IPV6
|
||||
|
||||
// Check to see if we have any routable IP address
|
||||
bool WifiHasIP(void) {
|
||||
#if LWIP_IPV6
|
||||
for (auto a : addrList) {
|
||||
if(!ip_addr_isloopback((ip_addr_t*)a.addr()) && !a.isLocal()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
#ifdef USE_IPV6
|
||||
return !WiFi.localIP().isAny();
|
||||
#else
|
||||
return (uint32_t)WiFi.localIP() != 0;
|
||||
#endif
|
||||
#endif // USE_IPV6
|
||||
}
|
||||
|
||||
void WifiCheckIp(void) {
|
||||
#if LWIP_IPV6
|
||||
#ifdef USE_IPV6
|
||||
if (WL_CONNECTED == WiFi.status()) {
|
||||
if (!Wifi.ipv6_local_link_called) {
|
||||
WiFi.enableIpV6();
|
||||
|
@ -545,7 +533,7 @@ void WifiCheckIp(void) {
|
|||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
#endif // USE_IPV6
|
||||
|
||||
if ((WL_CONNECTED == WiFi.status()) && WifiHasIP()) {
|
||||
WifiSetState(1);
|
||||
|
@ -1081,24 +1069,23 @@ uint64_t WifiGetNtp(void) {
|
|||
// Respond to some Arduino/esp-idf events for better IPv6 support
|
||||
// --------------------------------------------------------------------------------
|
||||
#ifdef ESP32
|
||||
#include "IPAddress46.h"
|
||||
// typedef void (*WiFiEventSysCb)(arduino_event_t *event);
|
||||
void WifiEvents(arduino_event_t *event) {
|
||||
switch (event->event_id) {
|
||||
|
||||
#if LWIP_IPV6
|
||||
#ifdef USE_IPV6
|
||||
case ARDUINO_EVENT_WIFI_STA_GOT_IP6:
|
||||
case ARDUINO_EVENT_ETH_GOT_IP6:
|
||||
{
|
||||
ip_addr_t ip_addr6;
|
||||
ip_addr_copy_from_ip6(ip_addr6, event->event_info.got_ip6.ip6_info.ip);
|
||||
IPAddress46 addr(ip_addr6);
|
||||
IPAddress addr(ip_addr6);
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("%s: IPv6 %s %s"),
|
||||
event->event_id == ARDUINO_EVENT_ETH_GOT_IP6 ? "ETH" : "WIF",
|
||||
addr.isLocal() ? PSTR("Local") : PSTR("Global"), addr.toString().c_str());
|
||||
}
|
||||
break;
|
||||
#endif // LWIP_IPV6
|
||||
#endif // USE_IPV6
|
||||
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
|
||||
case ARDUINO_EVENT_ETH_GOT_IP:
|
||||
{
|
||||
|
|
|
@ -610,7 +610,7 @@ void StartWebserver(int type, IPAddress ipweb)
|
|||
Webserver->begin(); // Web server start
|
||||
}
|
||||
if (Web.state != type) {
|
||||
#if LWIP_IPV6
|
||||
#ifdef USE_IPV6
|
||||
String ipv6_addr = WifiGetIPv6();
|
||||
if (ipv6_addr!="") {
|
||||
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_ACTIVE_ON " %s%s " D_WITH_IP_ADDRESS " %_I and IPv6 global address %s "),
|
||||
|
@ -622,7 +622,7 @@ void StartWebserver(int type, IPAddress ipweb)
|
|||
#else
|
||||
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_ACTIVE_ON " %s%s " D_WITH_IP_ADDRESS " %_I"),
|
||||
NetworkHostname(), (Mdns.begun) ? PSTR(".local") : "", (uint32_t)ipweb);
|
||||
#endif // LWIP_IPV6 = 1
|
||||
#endif // USE_IPV6
|
||||
TasmotaGlobal.rules_flag.http_init = 1;
|
||||
Web.state = type;
|
||||
}
|
||||
|
@ -2359,7 +2359,7 @@ void HandleInformation(void)
|
|||
int32_t rssi = WiFi.RSSI();
|
||||
WSContentSend_P(PSTR("}1" D_AP "%d " D_SSID " (" D_RSSI ")}2%s (%d%%, %d dBm) 11%c"), Settings->sta_active +1, HtmlEscape(SettingsText(SET_STASSID1 + Settings->sta_active)).c_str(), WifiGetRssiAsQuality(rssi), rssi, pgm_read_byte(&kWifiPhyMode[WiFi.getPhyMode() & 0x3]) );
|
||||
WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), TasmotaGlobal.hostname, (Mdns.begun) ? PSTR(".local") : "");
|
||||
#if LWIP_IPV6
|
||||
#ifdef USE_IPV6
|
||||
String ipv6_addr = WifiGetIPv6();
|
||||
if (ipv6_addr != "") {
|
||||
WSContentSend_P(PSTR("}1 IPv6 Global (wifi)}2%s"), ipv6_addr.c_str());
|
||||
|
@ -2368,7 +2368,7 @@ void HandleInformation(void)
|
|||
if (ipv6_addr != "") {
|
||||
WSContentSend_P(PSTR("}1 IPv6 Local (wifi)}2%s"), ipv6_addr.c_str());
|
||||
}
|
||||
#endif // LWIP_IPV6 = 1
|
||||
#endif // USE_IPV6
|
||||
if (static_cast<uint32_t>(WiFi.localIP()) != 0) {
|
||||
WSContentSend_P(PSTR("}1" D_MAC_ADDRESS "}2%s"), WiFi.macAddress().c_str());
|
||||
WSContentSend_P(PSTR("}1" D_IP_ADDRESS " (wifi)}2%_I"), (uint32_t)WiFi.localIP());
|
||||
|
@ -2387,7 +2387,7 @@ void HandleInformation(void)
|
|||
WSContentSend_P(PSTR("}1<hr/>}2<hr/>"));
|
||||
}
|
||||
WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), EthernetHostname(), (Mdns.begun) ? PSTR(".local") : "");
|
||||
#if LWIP_IPV6
|
||||
#ifdef USE_IPV6
|
||||
String ipv6_eth_addr = EthernetGetIPv6();
|
||||
if (ipv6_eth_addr != "") {
|
||||
WSContentSend_P(PSTR("}1 IPv6 Global (eth)}2%s"), ipv6_eth_addr.c_str());
|
||||
|
@ -2396,7 +2396,7 @@ void HandleInformation(void)
|
|||
if (ipv6_eth_addr != "") {
|
||||
WSContentSend_P(PSTR("}1 IPv6 Local (eth)}2%s"), ipv6_eth_addr.c_str());
|
||||
}
|
||||
#endif // LWIP_IPV6 = 1
|
||||
#endif // USE_IPV6
|
||||
WSContentSend_P(PSTR("}1" D_MAC_ADDRESS "}2%s"), EthernetMacAddress().c_str());
|
||||
WSContentSend_P(PSTR("}1" D_IP_ADDRESS " (eth)}2%_I"), (uint32_t)EthernetLocalIP());
|
||||
}
|
||||
|
|
|
@ -971,10 +971,10 @@ void MqttConnected(void) {
|
|||
if (static_cast<uint32_t>(WiFi.localIP()) != 0) {
|
||||
ResponseAppend_P(PSTR(",\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%_I\""),
|
||||
TasmotaGlobal.hostname, (uint32_t)WiFi.localIP());
|
||||
#if LWIP_IPV6
|
||||
#ifdef USE_IPV6
|
||||
ResponseAppend_P(PSTR(",\"" D_JSON_IP6_GLOBAL "\":\"%s\""), WifiGetIPv6().c_str());
|
||||
ResponseAppend_P(PSTR(",\"" D_JSON_IP6_LOCAL "\":\"%s\""), WifiGetIPv6LinkLocal().c_str());
|
||||
#endif // LWIP_IPV6 = 1
|
||||
#endif // USE_IPV6
|
||||
}
|
||||
#if defined(ESP32) && CONFIG_IDF_TARGET_ESP32 && defined(USE_ETHERNET)
|
||||
if (static_cast<uint32_t>(EthernetLocalIP()) != 0) {
|
||||
|
|
|
@ -214,7 +214,7 @@ extern "C" {
|
|||
if (Settings->flag4.network_wifi) {
|
||||
int32_t rssi = WiFi.RSSI();
|
||||
bool show_rssi = false;
|
||||
#if LWIP_IPV6
|
||||
#ifdef USE_IPV6
|
||||
String ipv6_addr = WifiGetIPv6();
|
||||
if (ipv6_addr != "") {
|
||||
be_map_insert_str(vm, "ip6", ipv6_addr.c_str());
|
||||
|
@ -225,10 +225,10 @@ extern "C" {
|
|||
be_map_insert_str(vm, "ip6local", ipv6_addr.c_str());
|
||||
show_rssi = true;
|
||||
}
|
||||
#endif
|
||||
#endif // USE_IPV6
|
||||
if (static_cast<uint32_t>(WiFi.localIP()) != 0) {
|
||||
be_map_insert_str(vm, "mac", WiFi.macAddress().c_str());
|
||||
be_map_insert_str(vm, "ip", IPAddress46((uint32_t)WiFi.localIP()).toString().c_str()); // quick fix for IPAddress bug
|
||||
be_map_insert_str(vm, "ip", IPAddress((uint32_t)WiFi.localIP()).toString().c_str()); // quick fix for IPAddress bug
|
||||
show_rssi = true;
|
||||
}
|
||||
if (show_rssi) {
|
||||
|
@ -252,9 +252,9 @@ extern "C" {
|
|||
#ifdef USE_ETHERNET
|
||||
if (static_cast<uint32_t>(EthernetLocalIP()) != 0) {
|
||||
be_map_insert_str(vm, "mac", EthernetMacAddress().c_str());
|
||||
be_map_insert_str(vm, "ip", IPAddress46((uint32_t)EthernetLocalIP()).toString().c_str()); // quick fix for IPAddress bug
|
||||
be_map_insert_str(vm, "ip", IPAddress((uint32_t)EthernetLocalIP()).toString().c_str()); // quick fix for IPAddress bug
|
||||
}
|
||||
#if LWIP_IPV6
|
||||
#ifdef USE_IPV6
|
||||
String ipv6_addr = EthernetGetIPv6();
|
||||
if (ipv6_addr != "") {
|
||||
be_map_insert_str(vm, "ip6", ipv6_addr.c_str());
|
||||
|
@ -263,8 +263,8 @@ extern "C" {
|
|||
if (ipv6_addr != "") {
|
||||
be_map_insert_str(vm, "ip6local", ipv6_addr.c_str());
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif // USE_IPV6
|
||||
#endif // USE_ETHERNET
|
||||
be_pop(vm, 1);
|
||||
be_return(vm);
|
||||
}
|
||||
|
|
|
@ -94,9 +94,9 @@ void EthernetEvent(arduino_event_t *event) {
|
|||
break;
|
||||
|
||||
case ARDUINO_EVENT_ETH_CONNECTED:
|
||||
#if LWIP_IPV6
|
||||
#ifdef USE_IPV6
|
||||
ETH.enableIpV6(); // enable Link-Local
|
||||
#endif
|
||||
#endif // USE_IPV6
|
||||
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_ETH D_CONNECTED " at %dMbps%s, Mac %s, Hostname %s"),
|
||||
ETH.linkSpeed(), (ETH.fullDuplex()) ? " Full Duplex" : "",
|
||||
ETH.macAddress().c_str(), eth_hostname
|
||||
|
@ -143,6 +143,7 @@ void EthernetSetIp(void) {
|
|||
Settings->eth_ipv4_address[4]); // IPAddress dns2
|
||||
}
|
||||
|
||||
#ifdef USE_IPV6
|
||||
// Returns only IPv6 global address (no loopback and no link-local)
|
||||
String EthernetGetIPv6(void)
|
||||
{
|
||||
|
@ -153,6 +154,7 @@ String EthernetGetIPv6LinkLocal(void)
|
|||
{
|
||||
return WifiFindIPv6(true, "en");
|
||||
}
|
||||
#endif // USE_IPV6
|
||||
|
||||
void EthernetInit(void) {
|
||||
if (!Settings->flag4.network_ethernet) { return; }
|
||||
|
|
Loading…
Reference in New Issue