Skip to content

Commit 246ea6d

Browse files
committed
Apply IPAddress fixes from ESP8266
esp8266/Arduino#8818
1 parent 63152a2 commit 246ea6d

File tree

2 files changed

+65
-78
lines changed

2 files changed

+65
-78
lines changed

cores/esp32/IPAddress.cpp

+43-73
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,13 @@ IPAddress::IPAddress(const IPAddress& from)
3737
}
3838

3939
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;
40+
uint8_t addr[] {
41+
first_octet,
42+
second_octet,
43+
third_octet,
44+
fourth_octet,
45+
};
46+
*this = &addr[0];
4547
}
4648

4749
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) {
@@ -65,12 +67,17 @@ IPAddress::IPAddress(uint8_t o1, uint8_t o2, uint8_t o3, uint8_t o4, uint8_t o5,
6567
}
6668

6769
IPAddress::IPAddress(IPType type, const uint8_t *address) {
70+
IPAddress(type, address, 0);
71+
}
72+
73+
IPAddress::IPAddress(IPType type, const uint8_t *address, uint8_t zone) {
6874
if (type == IPv4) {
6975
setV4();
7076
memcpy(&this->_ip.u_addr.ip4, address, 4);
7177
} else if (type == IPv6) {
7278
setV6();
7379
memcpy(&this->_ip.u_addr.ip6.addr[0], address, 16);
80+
setZone(zone);
7481
} else {
7582
#if LWIP_IPV6
7683
_ip = *IP6_ADDR_ANY;
@@ -81,19 +88,6 @@ IPAddress::IPAddress(IPType type, const uint8_t *address) {
8188

8289
}
8390

84-
void IPAddress::ctor32(uint32_t address) {
85-
setV4();
86-
v4() = address;
87-
}
88-
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];
95-
}
96-
9791
bool IPAddress::fromString(const char *address) {
9892
if (!fromString4(address)) {
9993
#if LWIP_IPV6
@@ -149,8 +143,9 @@ bool IPAddress::fromString4(const char *address) {
149143
}
150144

151145
IPAddress& IPAddress::operator=(const uint8_t *address) {
152-
setV4();
153-
v4() = *reinterpret_cast<const uint32_t*>(address);
146+
uint32_t value;
147+
memcpy_P(&value, address, sizeof(value));
148+
*this = value;
154149
return *this;
155150
}
156151

@@ -161,15 +156,19 @@ IPAddress& IPAddress::operator=(uint32_t address) {
161156
}
162157

163158
bool IPAddress::operator==(const uint8_t* addr) const {
164-
return isV4() && v4() == *reinterpret_cast<const uint32_t*>(addr);
159+
if (!isV4()) {
160+
return false;
161+
}
162+
163+
uint32_t value;
164+
memcpy_P(&value, addr, sizeof(value));
165+
166+
return v4() == value;
165167
}
166168

167169
size_t IPAddress::printTo(Print& p) const {
168170
size_t n = 0;
169171

170-
// if (!isSet())
171-
// return p.print(F("(IP unset)"));
172-
173172
#if LWIP_IPV6
174173
if (isV6()) {
175174
int count0 = 0;
@@ -185,6 +184,13 @@ size_t IPAddress::printTo(Print& p) const {
185184
if ((i != 7 && count0 < 2) || count0 == 7)
186185
n += p.print(':');
187186
}
187+
// add a zone if zone-id si non-zero
188+
if (_ip.u_addr.ip6.zone) {
189+
n += p.print('%');
190+
char if_name[NETIF_NAMESIZE];
191+
netif_index_to_name(_ip.u_addr.ip6.zone, if_name);
192+
n += p.print(if_name);
193+
}
188194
return n;
189195
}
190196
#endif
@@ -202,7 +208,7 @@ String IPAddress::toString() const
202208
StreamString sstr;
203209
#if LWIP_IPV6
204210
if (isV6())
205-
sstr.reserve(40); // 8 shorts x 4 chars each + 7 colons + nullterm
211+
sstr.reserve(44); // 8 shorts x 4 chars each + 7 colons + nullterm + '%' + zone-id
206212
else
207213
#endif
208214
sstr.reserve(16); // 4 bytes with 3 chars max + 3 dots + nullterm, or '(IP unset)'
@@ -230,56 +236,20 @@ void IPAddress::clear() {
230236
#if LWIP_IPV6
231237

232238
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;
239+
ip6_addr_t ip6;
240+
if (ip6addr_aton(address, &ip6)) {
241+
setV6();
242+
memcpy(&this->_ip.u_addr.ip6.addr[0], ip6.addr, 16);
243+
// look for '%' in string
244+
const char *s = address;
245+
while (*s && *s != '%') { s++; }
246+
if (*s == '%') {
247+
// we have a zone id
248+
setZone(netif_name_to_index(s + 1));
263249
}
264-
else
265-
// Invalid char
266-
return false;
250+
return true;
267251
}
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();
282-
return true;
252+
return false;
283253
}
284254
#endif // LWIP_IPV6
285255

cores/esp32/IPAddress.h

+22-5
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,12 @@ class IPAddress: public Printable
5454
IPAddress(const IPAddress& from);
5555
IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet);
5656
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);
57-
IPAddress(uint32_t address) { ctor32(address); }
58-
IPAddress(const uint8_t *address); // v4 only
57+
IPAddress(uint32_t address) { *this = address; }
58+
IPAddress(unsigned long address) { *this = address; }
59+
IPAddress(int address) { *this = address; }
60+
IPAddress(const uint8_t *address) { *this = address; }
5961
IPAddress(IPType type, const uint8_t *address);
62+
IPAddress(IPType type, const uint8_t *address, uint8_t zone);
6063

6164
bool fromString(const char *address);
6265
bool fromString(const String &address) { return fromString(address.c_str()); }
@@ -67,7 +70,7 @@ class IPAddress: public Printable
6770
operator uint32_t() { return isV4()? v4(): (uint32_t)0; }
6871

6972
// generic IPv4 wrapper to uint32-view like arduino loves to see it
70-
const uint32_t& v4() const { return ip_2_ip4(&_ip)->addr; } // for raw_address(const)
73+
const uint32_t& v4() const { return ip_2_ip4(&_ip)->addr; }
7174
uint32_t& v4() { return ip_2_ip4(&_ip)->addr; }
7275

7376
bool operator==(const IPAddress& addr) const {
@@ -96,11 +99,16 @@ class IPAddress: public Printable
9699

97100
// Overloaded index operator to allow getting and setting individual octets of the address
98101
uint8_t operator[](int index) const {
99-
return isV4()? *(raw_address() + index): 0;
102+
if (!isV4()) {
103+
return 0;
104+
}
105+
106+
return ip4_addr_get_byte_val(*ip_2_ip4(&_ip), index);
100107
}
101108
uint8_t& operator[](int index) {
102109
setV4();
103-
return *(raw_address() + index);
110+
uint8_t* ptr = reinterpret_cast<uint8_t*>(&v4());
111+
return *(ptr + index);
104112
}
105113

106114
// Overloaded copy operators to allow initialisation of IPAddress objects from other types
@@ -167,6 +175,13 @@ class IPAddress: public Printable
167175
IP_SET_TYPE_VAL(_ip, IPADDR_TYPE_V6);
168176
ip6_addr_clear_zone(ip_2_ip6(&_ip));
169177
}
178+
inline uint8_t zone() const { return isV6() ? ip_2_ip6(&_ip)->zone : 0; }
179+
void setZone(uint8_t zone) {
180+
if (isV6()) {
181+
ip_2_ip6(&_ip)->zone = zone;
182+
}
183+
}
184+
170185

171186
protected:
172187
bool fromString6(const char *address);
@@ -179,6 +194,8 @@ class IPAddress: public Printable
179194
const uint16_t* raw6() const { return nullptr; }
180195
bool isV6() const { return false; }
181196
void setV6() { }
197+
inline uint8_t zone() const { return 0; }
198+
void setZone(uint8_t zone) { }
182199

183200
#endif
184201

0 commit comments

Comments
 (0)