Skip to content

Commit 65df2b7

Browse files
authored
Merge branch 'master' into gpio_hal_log
2 parents a32278e + d912710 commit 65df2b7

File tree

6 files changed

+555
-241
lines changed

6 files changed

+555
-241
lines changed

Diff for: cores/esp32/IPAddress.cpp

+266-23
Original file line numberDiff line numberDiff line change
@@ -20,78 +20,244 @@
2020
#include <Arduino.h>
2121
#include <IPAddress.h>
2222
#include <Print.h>
23+
#include <StreamString.h>
2324

24-
IPAddress::IPAddress()
25+
IPAddress::IPAddress() : IPAddress(IPv4) {}
26+
27+
IPAddress::IPAddress(IPType ip_type)
2528
{
26-
_address.dword = 0;
29+
_type = ip_type;
30+
memset(_address.bytes, 0, sizeof(_address.bytes));
2731
}
2832

2933
IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet)
3034
{
31-
_address.bytes[0] = first_octet;
32-
_address.bytes[1] = second_octet;
33-
_address.bytes[2] = third_octet;
34-
_address.bytes[3] = fourth_octet;
35+
_type = IPv4;
36+
memset(_address.bytes, 0, sizeof(_address.bytes));
37+
_address.bytes[IPADDRESS_V4_BYTES_INDEX] = first_octet;
38+
_address.bytes[IPADDRESS_V4_BYTES_INDEX + 1] = second_octet;
39+
_address.bytes[IPADDRESS_V4_BYTES_INDEX + 2] = third_octet;
40+
_address.bytes[IPADDRESS_V4_BYTES_INDEX + 3] = fourth_octet;
41+
}
42+
43+
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) {
44+
_type = IPv6;
45+
_address.bytes[0] = o1;
46+
_address.bytes[1] = o2;
47+
_address.bytes[2] = o3;
48+
_address.bytes[3] = o4;
49+
_address.bytes[4] = o5;
50+
_address.bytes[5] = o6;
51+
_address.bytes[6] = o7;
52+
_address.bytes[7] = o8;
53+
_address.bytes[8] = o9;
54+
_address.bytes[9] = o10;
55+
_address.bytes[10] = o11;
56+
_address.bytes[11] = o12;
57+
_address.bytes[12] = o13;
58+
_address.bytes[13] = o14;
59+
_address.bytes[14] = o15;
60+
_address.bytes[15] = o16;
3561
}
3662

3763
IPAddress::IPAddress(uint32_t address)
3864
{
39-
_address.dword = address;
65+
// IPv4 only
66+
_type = IPv4;
67+
memset(_address.bytes, 0, sizeof(_address.bytes));
68+
_address.dword[IPADDRESS_V4_DWORD_INDEX] = address;
69+
70+
// NOTE on conversion/comparison and uint32_t:
71+
// These conversions are host platform dependent.
72+
// There is a defined integer representation of IPv4 addresses,
73+
// based on network byte order (will be the value on big endian systems),
74+
// e.g. http://2398766798 is the same as http://142.250.70.206,
75+
// However on little endian systems the octets 0x83, 0xFA, 0x46, 0xCE,
76+
// in that order, will form the integer (uint32_t) 3460758158 .
77+
}
78+
79+
IPAddress::IPAddress(const uint8_t *address) : IPAddress(IPv4, address) {}
80+
81+
IPAddress::IPAddress(IPType ip_type, const uint8_t *address)
82+
{
83+
_type = ip_type;
84+
if (ip_type == IPv4) {
85+
memset(_address.bytes, 0, sizeof(_address.bytes));
86+
memcpy(&_address.bytes[IPADDRESS_V4_BYTES_INDEX], address, sizeof(uint32_t));
87+
} else {
88+
memcpy(_address.bytes, address, sizeof(_address.bytes));
89+
}
4090
}
4191

42-
IPAddress::IPAddress(const uint8_t *address)
92+
IPAddress::IPAddress(const char *address)
4393
{
44-
memcpy(_address.bytes, address, sizeof(_address.bytes));
94+
fromString(address);
4595
}
4696

4797
IPAddress& IPAddress::operator=(const uint8_t *address)
4898
{
49-
memcpy(_address.bytes, address, sizeof(_address.bytes));
99+
// IPv4 only conversion from byte pointer
100+
_type = IPv4;
101+
memset(_address.bytes, 0, sizeof(_address.bytes));
102+
memcpy(&_address.bytes[IPADDRESS_V4_BYTES_INDEX], address, sizeof(uint32_t));
103+
return *this;
104+
}
105+
106+
IPAddress& IPAddress::operator=(const char *address)
107+
{
108+
fromString(address);
50109
return *this;
51110
}
52111

53112
IPAddress& IPAddress::operator=(uint32_t address)
54113
{
55-
_address.dword = address;
114+
// IPv4 conversion
115+
// See note on conversion/comparison and uint32_t
116+
_type = IPv4;
117+
memset(_address.bytes, 0, sizeof(_address.bytes));
118+
_address.dword[IPADDRESS_V4_DWORD_INDEX] = address;
56119
return *this;
57120
}
58121

122+
bool IPAddress::operator==(const IPAddress& addr) const
123+
{
124+
return (addr._type == _type)
125+
&& (memcmp(addr._address.bytes, _address.bytes, sizeof(_address.bytes)) == 0);
126+
}
127+
59128
bool IPAddress::operator==(const uint8_t* addr) const
60129
{
61-
return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0;
130+
// IPv4 only comparison to byte pointer
131+
// Can't support IPv6 as we know our type, but not the length of the pointer
132+
return _type == IPv4 && memcmp(addr, &_address.bytes[IPADDRESS_V4_BYTES_INDEX], sizeof(uint32_t)) == 0;
133+
}
134+
135+
uint8_t IPAddress::operator[](int index) const {
136+
if (_type == IPv4) {
137+
return _address.bytes[IPADDRESS_V4_BYTES_INDEX + index];
138+
}
139+
return _address.bytes[index];
140+
}
141+
142+
uint8_t& IPAddress::operator[](int index) {
143+
if (_type == IPv4) {
144+
return _address.bytes[IPADDRESS_V4_BYTES_INDEX + index];
145+
}
146+
return _address.bytes[index];
62147
}
63148

64149
size_t IPAddress::printTo(Print& p) const
65150
{
66151
size_t n = 0;
67-
for(int i = 0; i < 3; i++) {
68-
n += p.print(_address.bytes[i], DEC);
152+
153+
if (_type == IPv6) {
154+
// IPv6 IETF canonical format: compress left-most longest run of two or more zero fields, lower case
155+
int8_t longest_start = -1;
156+
int8_t longest_length = 1;
157+
int8_t current_start = -1;
158+
int8_t current_length = 0;
159+
for (int8_t f = 0; f < 8; f++) {
160+
if (_address.bytes[f * 2] == 0 && _address.bytes[f * 2 + 1] == 0) {
161+
if (current_start == -1) {
162+
current_start = f;
163+
current_length = 1;
164+
} else {
165+
current_length++;
166+
}
167+
if (current_length > longest_length) {
168+
longest_start = current_start;
169+
longest_length = current_length;
170+
}
171+
} else {
172+
current_start = -1;
173+
}
174+
}
175+
for (int f = 0; f < 8; f++) {
176+
if (f < longest_start || f >= longest_start + longest_length) {
177+
uint8_t c1 = _address.bytes[f * 2] >> 4;
178+
uint8_t c2 = _address.bytes[f * 2] & 0xf;
179+
uint8_t c3 = _address.bytes[f * 2 + 1] >> 4;
180+
uint8_t c4 = _address.bytes[f * 2 + 1] & 0xf;
181+
if (c1 > 0) {
182+
n += p.print((char)(c1 < 10 ? '0' + c1 : 'a' + c1 - 10));
183+
}
184+
if (c1 > 0 || c2 > 0) {
185+
n += p.print((char)(c2 < 10 ? '0' + c2 : 'a' + c2 - 10));
186+
}
187+
if (c1 > 0 || c2 > 0 || c3 > 0) {
188+
n += p.print((char)(c3 < 10 ? '0' + c3 : 'a' + c3 - 10));
189+
}
190+
n += p.print((char)(c4 < 10 ? '0' + c4 : 'a' + c4 - 10));
191+
if (f < 7) {
192+
n += p.print(':');
193+
}
194+
} else if (f == longest_start) {
195+
if (longest_start == 0) {
196+
n += p.print(':');
197+
}
198+
n += p.print(':');
199+
}
200+
}
201+
return n;
202+
}
203+
204+
// IPv4
205+
for (int i =0; i < 3; i++)
206+
{
207+
n += p.print(_address.bytes[IPADDRESS_V4_BYTES_INDEX + i], DEC);
69208
n += p.print('.');
70209
}
71-
n += p.print(_address.bytes[3], DEC);
210+
n += p.print(_address.bytes[IPADDRESS_V4_BYTES_INDEX + 3], DEC);
72211
return n;
73212
}
74213

75-
String IPAddress::toString() const
214+
String IPAddress::toString4() const
76215
{
77216
char szRet[16];
78-
sprintf(szRet,"%u.%u.%u.%u", _address.bytes[0], _address.bytes[1], _address.bytes[2], _address.bytes[3]);
217+
snprintf(szRet, sizeof(szRet), "%u.%u.%u.%u", _address.bytes[IPADDRESS_V4_BYTES_INDEX], _address.bytes[IPADDRESS_V4_BYTES_INDEX + 1], _address.bytes[IPADDRESS_V4_BYTES_INDEX + 2], _address.bytes[IPADDRESS_V4_BYTES_INDEX + 3]);
79218
return String(szRet);
80219
}
81220

221+
String IPAddress::toString6() const
222+
{
223+
StreamString s;
224+
s.reserve(40);
225+
printTo(s);
226+
return s;
227+
}
228+
229+
String IPAddress::toString() const
230+
{
231+
if (_type == IPv4) {
232+
return toString4();
233+
} else {
234+
return toString6();
235+
}
236+
}
237+
82238
bool IPAddress::fromString(const char *address)
239+
{
240+
if (!fromString4(address))
241+
{
242+
return fromString6(address);
243+
}
244+
return true;
245+
}
246+
247+
bool IPAddress::fromString4(const char *address)
83248
{
84249
// TODO: add support for "a", "a.b", "a.b.c" formats
85250

86-
uint16_t acc = 0; // Accumulator
251+
int16_t acc = -1; // Accumulator
87252
uint8_t dots = 0;
88253

254+
memset(_address.bytes, 0, sizeof(_address.bytes));
89255
while (*address)
90256
{
91257
char c = *address++;
92258
if (c >= '0' && c <= '9')
93259
{
94-
acc = acc * 10 + (c - '0');
260+
acc = (acc < 0) ? (c - '0') : acc * 10 + (c - '0');
95261
if (acc > 255) {
96262
// Value out of [0..255] range
97263
return false;
@@ -100,11 +266,15 @@ bool IPAddress::fromString(const char *address)
100266
else if (c == '.')
101267
{
102268
if (dots == 3) {
103-
// Too much dots (there must be 3 dots)
269+
// Too many dots (there must be 3 dots)
104270
return false;
105271
}
106-
_address.bytes[dots++] = acc;
107-
acc = 0;
272+
if (acc < 0) {
273+
/* No value between dots, e.g. '1..' */
274+
return false;
275+
}
276+
_address.bytes[IPADDRESS_V4_BYTES_INDEX + dots++] = acc;
277+
acc = -1;
108278
}
109279
else
110280
{
@@ -117,7 +287,80 @@ bool IPAddress::fromString(const char *address)
117287
// Too few dots (there must be 3 dots)
118288
return false;
119289
}
120-
_address.bytes[3] = acc;
290+
if (acc < 0) {
291+
/* No value between dots, e.g. '1..' */
292+
return false;
293+
}
294+
_address.bytes[IPADDRESS_V4_BYTES_INDEX + 3] = acc;
295+
_type = IPv4;
296+
return true;
297+
}
298+
299+
bool IPAddress::fromString6(const char *address) {
300+
uint32_t acc = 0; // Accumulator
301+
int colons = 0, double_colons = -1;
302+
303+
while (*address)
304+
{
305+
char c = tolower(*address++);
306+
if (isalnum(c) && c <= 'f') {
307+
if (c >= 'a')
308+
c -= 'a' - '0' - 10;
309+
acc = acc * 16 + (c - '0');
310+
if (acc > 0xffff)
311+
// Value out of range
312+
return false;
313+
}
314+
else if (c == ':') {
315+
if (*address == ':') {
316+
if (double_colons >= 0) {
317+
// :: allowed once
318+
return false;
319+
}
320+
if (*address != '\0' && *(address + 1) == ':') {
321+
// ::: not allowed
322+
return false;
323+
}
324+
// remember location
325+
double_colons = colons + !!acc;
326+
address++;
327+
} else if (*address == '\0') {
328+
// can't end with a single colon
329+
return false;
330+
}
331+
if (colons == 7)
332+
// too many separators
333+
return false;
334+
_address.bytes[colons * 2] = acc >> 8;
335+
_address.bytes[colons * 2 + 1] = acc & 0xff;
336+
colons++;
337+
acc = 0;
338+
}
339+
else
340+
// Invalid char
341+
return false;
342+
}
343+
344+
if (double_colons == -1 && colons != 7) {
345+
// Too few separators
346+
return false;
347+
}
348+
if (double_colons > -1 && colons > 6) {
349+
// Too many segments (double colon must be at least one zero field)
350+
return false;
351+
}
352+
_address.bytes[colons * 2] = acc >> 8;
353+
_address.bytes[colons * 2 + 1] = acc & 0xff;
354+
colons++;
355+
356+
if (double_colons != -1) {
357+
for (int i = colons * 2 - double_colons * 2 - 1; i >= 0; i--)
358+
_address.bytes[16 - colons * 2 + double_colons * 2 + i] = _address.bytes[double_colons * 2 + i];
359+
for (int i = double_colons * 2; i < 16 - colons * 2 + double_colons * 2; i++)
360+
_address.bytes[i] = 0;
361+
}
362+
363+
_type = IPv6;
121364
return true;
122365
}
123366

0 commit comments

Comments
 (0)