Skip to content

Commit 77b46de

Browse files
Jason2866P-R-O-C-H-YsanketwadekarRefactorFactorysebastianbergner
authored
Tasmota with IPv6 (#172)
* LEDC - AnalogWrite new API + ledcAttachPin duty fix (espressif#7346) * Add enableScenes API in Rainmaker (espressif#7436) * Added enableScenes API * Added enableScenes API documentation * Added enableScenes API to example Co-authored-by: Jan Procházka <[email protected]> * How to use USBHID classes with ESP32-S2 and ESP32-S3 (espressif#7214) These instructions are based on esp32-arduino-lib-builder's build process, including https://github.com/espressif/esp32-arduino-lib-builder/blob/master/tools/update-components.sh which explains how to clone tinyusb. * Add I2C and SPI pin definitions to wt32-eth01 pins configuration (espressif#7237) * Add I2C and SPI pin definitions to wt32-eth01 pins Added missing pins based on testing using a RTC (I2C) and SD card reader (SPI). * Remove define macros Co-authored-by: Rodrigo Garcia <[email protected]> Co-authored-by: Jan Procházka <[email protected]> * Changed Rainmaker WiFi/Factory reset time. (espressif#7514) * Ipv6 support v2 * Update header * Update IPAddress implementation to support V6 * Fix cut and paste error * Explicit not equals * Explicitly reference StreamString * Remove != test (it is causing a conflict) * IPv6 support: Add proper link-local and SLAAC in STA and WifiMulti This patch partially depends on: espressif/esp32-arduino-lib-builder#67 Without this patch we will get only Link local IPv6 (still useful for MDNS and etc). With patch we will get also global IPv6 address by SLAAC. By default IPv6 disabled, until it is properly tested. Tested on BasicHttpClient by adding: wifiMulti.IPv6(true); before: wifiMulti.addAP() call Enabling Core Debug Level: verbose If IP6 obtained, in logs will be visible: [ 8028][V][WiFiGeneric.cpp:380] _arduino_event_cb(): IF[0] Got IPv6: IP Index: 0, Zone: 2, fe80:0000:0000:0000:xxxx:xxxx:xxxx:xxxx [ 8028][D][WiFiGeneric.cpp:852] _eventCallback(): Arduino Event: 8 - STA_GOT_IP6 [ 11028][V][WiFiGeneric.cpp:380] _arduino_event_cb(): IF[0] Got IPv6: IP Index: 1, Zone: 0, 2a0d:yyyy:0000:4000:yyyy:yyyy:yyyy:yyyy [ 11028][D][WiFiGeneric.cpp:852] _eventCallback(): Arduino Event: 8 - STA_GOT_IP6 This is linked to: espressif#6242 Signed-off-by: Denys Fedoryshchenko <[email protected]> * Add IPv6 support to WiFiServer One of most useful features of IPv6 to have arduino accessible from internet, without any port forward and etc. Change is fairly trivial and backward compatible with old code, tested with WiFiTelnetToSerial and AsyncUDPServer. Signed-off-by: Denys Fedoryshchenko <[email protected]> * WiFiClient::remoteIP and remoteIP6 IPv6 support For RemoteIP and AF_INET6 socket i added support ip6 to ip4 mapping, so .remoteIP will return IPv4 address on dual stack socket, if available. Scenarios tested: WiFiTelnetToSerial, wifiMulti.IPv6(true), connect both from IPv4 and IPv6 WiFiTelnetToSerial, wifiMulti.IPv6(true); but set to listen on IPv4 only. WiFiTelnetToSerial, IPv6 disabled, with or without bind to specific IP4. AsyncUDPServer, without IPv6 support. Signed-off-by: Denys Fedoryshchenko <[email protected]> * Add WiFiTelnetToSerialIPv6 example To demonstrate new abilities of dual stack WiFiServer and remoteIP6 we add this example. Signed-off-by: Denys Fedoryshchenko <[email protected]> * Add IPv6 to WifiClient (client) We need to be able to connect to remote servers over IPv6 too, and thats need different approach in DNS queries and connect(). As i'm trying to keep maximum compatibility, i introduce different behaviour if IPv6 is enabled, and backward compatible (as much as possible), if IPv6 is not enabled. IN future when IPv6 functions are tested well enough, it can be simplified. This implementation tested on esp32 in following scenarios using BasicHttpClient: IPv6 true: IPv6 only website (caveat 1) - OK Website with A and AAAA is present (caveat 1) - OK IPv4 only website - OK IPv6 not enabled: IPv6 only website - wont open (expected) Website with A and AAAA is present - OK, opens over IPv4 IPv4 only website - OK caveat 1 - sometimes SLAAC is slower than DHCPv4, so we might have status WL_CONNECTED, but IPv6 global scope is not ready yet. Signed-off-by: Denys Fedoryshchenko <[email protected]> * WiFiTelnetToSerialIPv6.ino: fix obsolete remoteIP6 call to remoteIP Example contained API from previous IPv6 implementation, fixing it. Signed-off-by: Denys Fedoryshchenko <[email protected]> Signed-off-by: Denys Fedoryshchenko <[email protected]> Co-authored-by: Sly Gryphon <[email protected]> Co-authored-by: Denys Fedoryshchenko <[email protected]> * Fix toString() for IPv4 * Full support for IPv6 * Full support for IPv6 * Fixed ambiguous definitions * Fix sizeof * Simplify initilization and remove memset * Enable support for IPv6 in UDP * Update PlatformIO build script PR 7579 * Fix IPv6 size Signed-off-by: Denys Fedoryshchenko <[email protected]> Co-authored-by: Jan Procházka <[email protected]> Co-authored-by: Sanket Wadekar <[email protected]> Co-authored-by: RefactorFactory <[email protected]> Co-authored-by: Sebastian Bergner <[email protected]> Co-authored-by: Rodrigo Garcia <[email protected]> Co-authored-by: Sly Gryphon <[email protected]> Co-authored-by: Denys Fedoryshchenko <[email protected]> Co-authored-by: s-hadinger <[email protected]>
1 parent 3ae32d6 commit 77b46de

26 files changed

+807
-203
lines changed

Diff for: cores/esp32/IPAddress.cpp

+208-46
Original file line numberDiff line numberDiff line change
@@ -20,68 +20,93 @@
2020
#include <Arduino.h>
2121
#include <IPAddress.h>
2222
#include <Print.h>
23+
#include <StreamString.h>
2324

24-
IPAddress::IPAddress()
25-
{
26-
_address.dword = 0;
25+
IPAddress::IPAddress() {
26+
#if LWIP_IPV6
27+
_ip = *IP6_ADDR_ANY;
28+
#else
29+
_ip = *IP_ADDR_ANY;
30+
#endif
31+
// _ip = *IP_ANY_TYPE; // lwIP's v4-or-v6 generic address
2732
}
2833

29-
IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet)
34+
IPAddress::IPAddress(const IPAddress& from)
3035
{
31-
_address.bytes[0] = first_octet;
32-
_address.bytes[1] = second_octet;
33-
_address.bytes[2] = third_octet;
34-
_address.bytes[3] = fourth_octet;
36+
ip_addr_copy(_ip, from._ip);
3537
}
3638

37-
IPAddress::IPAddress(uint32_t address)
38-
{
39-
_address.dword = address;
39+
IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) {
40+
setV4();
41+
(*this)[0] = first_octet;
42+
(*this)[1] = second_octet;
43+
(*this)[2] = third_octet;
44+
(*this)[3] = fourth_octet;
4045
}
4146

42-
IPAddress::IPAddress(const uint8_t *address)
43-
{
44-
memcpy(_address.bytes, address, sizeof(_address.bytes));
47+
IPAddress::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) {
48+
setV6();
49+
(*this)[0] = o1;
50+
(*this)[1] = o2;
51+
(*this)[2] = o3;
52+
(*this)[3] = o4;
53+
(*this)[4] = o5;
54+
(*this)[5] = o6;
55+
(*this)[6] = o7;
56+
(*this)[7] = o8;
57+
(*this)[8] = o9;
58+
(*this)[9] = o10;
59+
(*this)[10] = o11;
60+
(*this)[11] = o12;
61+
(*this)[12] = o13;
62+
(*this)[13] = o14;
63+
(*this)[14] = o15;
64+
(*this)[15] = o16;
4565
}
4666

47-
IPAddress& IPAddress::operator=(const uint8_t *address)
48-
{
49-
memcpy(_address.bytes, address, sizeof(_address.bytes));
50-
return *this;
67+
IPAddress::IPAddress(IPType type, const uint8_t *address) {
68+
if (type == IPv4) {
69+
setV4();
70+
memcpy(&this->_ip.u_addr.ip4, address, 4);
71+
} else if (type == IPv6) {
72+
setV6();
73+
memcpy(&this->_ip.u_addr.ip6.addr[0], address, 16);
74+
} else {
75+
#if LWIP_IPV6
76+
_ip = *IP6_ADDR_ANY;
77+
#else
78+
_ip = *IP_ADDR_ANY;
79+
#endif
80+
}
81+
5182
}
5283

53-
IPAddress& IPAddress::operator=(uint32_t address)
54-
{
55-
_address.dword = address;
56-
return *this;
84+
void IPAddress::ctor32(uint32_t address) {
85+
setV4();
86+
v4() = address;
5787
}
5888

59-
bool IPAddress::operator==(const uint8_t* addr) const
60-
{
61-
return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0;
89+
IPAddress::IPAddress(const uint8_t *address) {
90+
setV4();
91+
(*this)[0] = address[0];
92+
(*this)[1] = address[1];
93+
(*this)[2] = address[2];
94+
(*this)[3] = address[3];
6295
}
6396

64-
size_t IPAddress::printTo(Print& p) const
65-
{
66-
size_t n = 0;
67-
for(int i = 0; i < 3; i++) {
68-
n += p.print(_address.bytes[i], DEC);
69-
n += p.print('.');
97+
bool IPAddress::fromString(const char *address) {
98+
if (!fromString4(address)) {
99+
#if LWIP_IPV6
100+
return fromString6(address);
101+
#else
102+
return false;
103+
#endif
70104
}
71-
n += p.print(_address.bytes[3], DEC);
72-
return n;
105+
return true;
73106
}
74107

75-
String IPAddress::toString() const
76-
{
77-
char szRet[16];
78-
sprintf(szRet,"%u.%u.%u.%u", _address.bytes[0], _address.bytes[1], _address.bytes[2], _address.bytes[3]);
79-
return String(szRet);
80-
}
81-
82-
bool IPAddress::fromString(const char *address)
83-
{
84-
// TODO: add support for "a", "a.b", "a.b.c" formats
108+
bool IPAddress::fromString4(const char *address) {
109+
// TODO: (IPv4) add support for "a", "a.b", "a.b.c" formats
85110

86111
uint16_t acc = 0; // Accumulator
87112
uint8_t dots = 0;
@@ -103,7 +128,7 @@ bool IPAddress::fromString(const char *address)
103128
// Too much dots (there must be 3 dots)
104129
return false;
105130
}
106-
_address.bytes[dots++] = acc;
131+
(*this)[dots++] = acc;
107132
acc = 0;
108133
}
109134
else
@@ -117,9 +142,146 @@ bool IPAddress::fromString(const char *address)
117142
// Too few dots (there must be 3 dots)
118143
return false;
119144
}
120-
_address.bytes[3] = acc;
145+
(*this)[3] = acc;
146+
147+
setV4();
148+
return true;
149+
}
150+
151+
IPAddress& IPAddress::operator=(const uint8_t *address) {
152+
setV4();
153+
v4() = *reinterpret_cast<const uint32_t*>(address);
154+
return *this;
155+
}
156+
157+
IPAddress& IPAddress::operator=(uint32_t address) {
158+
setV4();
159+
v4() = address;
160+
return *this;
161+
}
162+
163+
bool IPAddress::operator==(const uint8_t* addr) const {
164+
return isV4() && v4() == *reinterpret_cast<const uint32_t*>(addr);
165+
}
166+
167+
size_t IPAddress::printTo(Print& p) const {
168+
size_t n = 0;
169+
170+
// if (!isSet())
171+
// return p.print(F("(IP unset)"));
172+
173+
#if LWIP_IPV6
174+
if (isV6()) {
175+
int count0 = 0;
176+
for (int i = 0; i < 8; i++) {
177+
uint16_t bit = PP_NTOHS(raw6()[i]);
178+
if (bit || count0 < 0) {
179+
n += p.printf("%x", bit);
180+
if (count0 > 0)
181+
// no more hiding 0
182+
count0 = -8;
183+
} else
184+
count0++;
185+
if ((i != 7 && count0 < 2) || count0 == 7)
186+
n += p.print(':');
187+
}
188+
return n;
189+
}
190+
#endif
191+
192+
for(int i = 0; i < 4; i++) {
193+
n += p.print((*this)[i], DEC);
194+
if (i != 3)
195+
n += p.print('.');
196+
}
197+
return n;
198+
}
199+
200+
String IPAddress::toString() const
201+
{
202+
StreamString sstr;
203+
#if LWIP_IPV6
204+
if (isV6())
205+
sstr.reserve(40); // 8 shorts x 4 chars each + 7 colons + nullterm
206+
else
207+
#endif
208+
sstr.reserve(16); // 4 bytes with 3 chars max + 3 dots + nullterm, or '(IP unset)'
209+
printTo(sstr);
210+
return sstr;
211+
}
212+
213+
bool IPAddress::isValid(const String& arg) {
214+
return IPAddress().fromString(arg);
215+
}
216+
217+
bool IPAddress::isValid(const char* arg) {
218+
return IPAddress().fromString(arg);
219+
}
220+
221+
const IPAddress INADDR46_ANY; // generic "0.0.0.0" for IPv4 & IPv6
222+
const IPAddress INADDR46_NONE(255,255,255,255);
223+
224+
void IPAddress::clear() {
225+
(*this) = INADDR46_ANY;
226+
}
227+
228+
/**************************************/
229+
230+
#if LWIP_IPV6
231+
232+
bool IPAddress::fromString6(const char *address) {
233+
// TODO: test test test
234+
235+
uint32_t acc = 0; // Accumulator
236+
int dots = 0, doubledots = -1;
237+
238+
while (*address)
239+
{
240+
char c = tolower(*address++);
241+
if (isalnum(c)) {
242+
if (c >= 'a')
243+
c -= 'a' - '0' - 10;
244+
acc = acc * 16 + (c - '0');
245+
if (acc > 0xffff)
246+
// Value out of range
247+
return false;
248+
}
249+
else if (c == ':') {
250+
if (*address == ':') {
251+
if (doubledots >= 0)
252+
// :: allowed once
253+
return false;
254+
// remember location
255+
doubledots = dots + !!acc;
256+
address++;
257+
}
258+
if (dots == 7)
259+
// too many separators
260+
return false;
261+
raw6()[dots++] = PP_HTONS(acc);
262+
acc = 0;
263+
}
264+
else
265+
// Invalid char
266+
return false;
267+
}
268+
269+
if (doubledots == -1 && dots != 7)
270+
// Too few separators
271+
return false;
272+
raw6()[dots++] = PP_HTONS(acc);
273+
274+
if (doubledots != -1) {
275+
for (int i = dots - doubledots - 1; i >= 0; i--)
276+
raw6()[8 - dots + doubledots + i] = raw6()[doubledots + i];
277+
for (int i = doubledots; i < 8 - dots + doubledots; i++)
278+
raw6()[i] = 0;
279+
}
280+
281+
setV6();
121282
return true;
122283
}
284+
#endif // LWIP_IPV6
123285

124286
// declared one time - as external in IPAddress.h
125-
IPAddress INADDR_NONE(0, 0, 0, 0);
287+
IPAddress INADDR_NONE(0, 0, 0, 0); // TODO

0 commit comments

Comments
 (0)