1717 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1818*/
1919
20- #include < Arduino.h >
21- #include < IPAddress.h >
20+ #include " IPAddress.h "
21+ #include " Print.h "
2222
23- IPAddress::IPAddress ()
23+ IPAddress::IPAddress () : IPAddress(IPv4) {}
24+
25+ IPAddress::IPAddress (IPType ip_type)
2426{
25- _address.dword = 0 ;
27+ _type = ip_type;
28+ memset (_address.bytes , 0 , sizeof (_address.bytes ));
2629}
2730
2831IPAddress::IPAddress (uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet)
2932{
30- _address.bytes [0 ] = first_octet;
31- _address.bytes [1 ] = second_octet;
32- _address.bytes [2 ] = third_octet;
33- _address.bytes [3 ] = fourth_octet;
33+ _type = IPv4;
34+ memset (_address.bytes , 0 , sizeof (_address.bytes ));
35+ _address.bytes [IPADDRESS_V4_BYTES_INDEX] = first_octet;
36+ _address.bytes [IPADDRESS_V4_BYTES_INDEX + 1 ] = second_octet;
37+ _address.bytes [IPADDRESS_V4_BYTES_INDEX + 2 ] = third_octet;
38+ _address.bytes [IPADDRESS_V4_BYTES_INDEX + 3 ] = fourth_octet;
39+ }
40+
41+ 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)
42+ {
43+ _type = IPv6;
44+ _address.bytes [0 ] = o1;
45+ _address.bytes [1 ] = o2;
46+ _address.bytes [2 ] = o3;
47+ _address.bytes [3 ] = o4;
48+ _address.bytes [4 ] = o5;
49+ _address.bytes [5 ] = o6;
50+ _address.bytes [6 ] = o7;
51+ _address.bytes [7 ] = o8;
52+ _address.bytes [8 ] = o9;
53+ _address.bytes [9 ] = o10;
54+ _address.bytes [10 ] = o11;
55+ _address.bytes [11 ] = o12;
56+ _address.bytes [12 ] = o13;
57+ _address.bytes [13 ] = o14;
58+ _address.bytes [14 ] = o15;
59+ _address.bytes [15 ] = o16;
3460}
3561
3662IPAddress::IPAddress (uint32_t address)
3763{
38- _address.dword = address;
64+ // IPv4 only
65+ _type = IPv4;
66+ memset (_address.bytes , 0 , sizeof (_address.bytes ));
67+ _address.dword [IPADDRESS_V4_DWORD_INDEX] = address;
68+
69+ // NOTE on conversion/comparison and uint32_t:
70+ // These conversions are host platform dependent.
71+ // There is a defined integer representation of IPv4 addresses,
72+ // based on network byte order (will be the value on big endian systems),
73+ // e.g. http://2398766798 is the same as http://142.250.70.206,
74+ // However on little endian systems the octets 0x83, 0xFA, 0x46, 0xCE,
75+ // in that order, will form the integer (uint32_t) 3460758158 .
76+ }
77+
78+ IPAddress::IPAddress (const uint8_t *address) : IPAddress(IPv4, address) {}
79+
80+ IPAddress::IPAddress (IPType ip_type, const uint8_t *address)
81+ {
82+ _type = ip_type;
83+ if (ip_type == IPv4) {
84+ memset (_address.bytes , 0 , sizeof (_address.bytes ));
85+ memcpy (&_address.bytes [IPADDRESS_V4_BYTES_INDEX], address, sizeof (uint32_t ));
86+ } else {
87+ memcpy (_address.bytes , address, sizeof (_address.bytes ));
88+ }
89+ }
90+
91+ IPAddress::IPAddress (const char *address)
92+ {
93+ fromString (address);
94+ }
95+
96+ String IPAddress::toString4 () const
97+ {
98+ char szRet[16 ];
99+ 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 ]);
100+ return String (szRet);
39101}
40102
41- IPAddress::IPAddress ( const uint8_t *address)
103+ String IPAddress::toString6 () const
42104{
43- memcpy (_address.bytes , address, sizeof (_address.bytes ));
105+ char szRet[40 ];
106+ snprintf (szRet, sizeof (szRet), " %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x" ,
107+ _address.bytes [0 ], _address.bytes [1 ], _address.bytes [2 ], _address.bytes [3 ],
108+ _address.bytes [4 ], _address.bytes [5 ], _address.bytes [6 ], _address.bytes [7 ],
109+ _address.bytes [8 ], _address.bytes [9 ], _address.bytes [10 ], _address.bytes [11 ],
110+ _address.bytes [12 ], _address.bytes [13 ], _address.bytes [14 ], _address.bytes [15 ]);
111+ return String (szRet);
112+ }
113+
114+ String IPAddress::toString () const
115+ {
116+ if (_type == IPv4) {
117+ return toString4 ();
118+ } else {
119+ return toString6 ();
120+ }
44121}
45122
46123bool IPAddress::fromString (const char *address)
124+ {
125+ if (!fromString4 (address)) {
126+ return fromString6 (address);
127+ }
128+ return true ;
129+ }
130+
131+ bool IPAddress::fromString4 (const char *address)
47132{
48133 // TODO: add support for "a", "a.b", "a.b.c" formats
49134
50- uint16_t acc = 0 ; // Accumulator
135+ int16_t acc = - 1 ; // Accumulator
51136 uint8_t dots = 0 ;
52137
138+ memset (_address.bytes , 0 , sizeof (_address.bytes ));
53139 while (*address) {
54140 char c = *address++;
55141 if (c >= ' 0' && c <= ' 9' ) {
56- acc = acc * 10 + (c - ' 0' );
142+ acc = (acc < 0 ) ? (c - ' 0 ' ) : acc * 10 + (c - ' 0' );
57143 if (acc > 255 ) {
58144 // Value out of [0..255] range
59145 return false ;
60146 }
61147 } else if (c == ' .' ) {
62148 if (dots == 3 ) {
63- // Too much dots (there must be 3 dots)
149+ // Too many dots (there must be 3 dots)
64150 return false ;
65151 }
66- _address.bytes [dots++] = acc;
67- acc = 0 ;
152+ if (acc < 0 ) {
153+ /* No value between dots, e.g. '1..' */
154+ return false ;
155+ }
156+ _address.bytes [IPADDRESS_V4_BYTES_INDEX + dots++] = acc;
157+ acc = -1 ;
68158 } else {
69159 // Invalid char
70160 return false ;
@@ -75,35 +165,207 @@ bool IPAddress::fromString(const char *address)
75165 // Too few dots (there must be 3 dots)
76166 return false ;
77167 }
78- _address.bytes [3 ] = acc;
168+ if (acc < 0 ) {
169+ /* No value between dots, e.g. '1..' */
170+ return false ;
171+ }
172+ _address.bytes [IPADDRESS_V4_BYTES_INDEX + 3 ] = acc;
173+ _type = IPv4;
174+ return true ;
175+ }
176+
177+ bool IPAddress::fromString6 (const char *address)
178+ {
179+ uint32_t acc = 0 ; // Accumulator
180+ int colons = 0 , double_colons = -1 ;
181+
182+ while (*address) {
183+ char c = tolower (*address++);
184+ if (isalnum (c) && c <= ' f' ) {
185+ if (c >= ' a' ) {
186+ c -= ' a' - ' 0' - 10 ;
187+ }
188+ acc = acc * 16 + (c - ' 0' );
189+ if (acc > 0xffff )
190+ // Value out of range
191+ {
192+ return false ;
193+ }
194+ } else if (c == ' :' ) {
195+ if (*address == ' :' ) {
196+ if (double_colons >= 0 ) {
197+ // :: allowed once
198+ return false ;
199+ }
200+ if (*address != ' \0 ' && *(address + 1 ) == ' :' ) {
201+ // ::: not allowed
202+ return false ;
203+ }
204+ // remember location
205+ double_colons = colons + !!acc;
206+ address++;
207+ } else if (*address == ' \0 ' ) {
208+ // can't end with a single colon
209+ return false ;
210+ }
211+ if (colons == 7 )
212+ // too many separators
213+ {
214+ return false ;
215+ }
216+ _address.bytes [colons * 2 ] = acc >> 8 ;
217+ _address.bytes [colons * 2 + 1 ] = acc & 0xff ;
218+ colons++;
219+ acc = 0 ;
220+ } else
221+ // Invalid char
222+ {
223+ return false ;
224+ }
225+ }
226+
227+ if (double_colons == -1 && colons != 7 ) {
228+ // Too few separators
229+ return false ;
230+ }
231+ if (double_colons > -1 && colons > 6 ) {
232+ // Too many segments (double colon must be at least one zero field)
233+ return false ;
234+ }
235+ _address.bytes [colons * 2 ] = acc >> 8 ;
236+ _address.bytes [colons * 2 + 1 ] = acc & 0xff ;
237+ colons++;
238+
239+ if (double_colons != -1 ) {
240+ for (int i = colons * 2 - double_colons * 2 - 1 ; i >= 0 ; i--) {
241+ _address.bytes [16 - colons * 2 + double_colons * 2 + i] = _address.bytes [double_colons * 2 + i];
242+ }
243+ for (int i = double_colons * 2 ; i < 16 - colons * 2 + double_colons * 2 ; i++) {
244+ _address.bytes [i] = 0 ;
245+ }
246+ }
247+
248+ _type = IPv6;
79249 return true ;
80250}
81251
82252IPAddress &IPAddress::operator =(const uint8_t *address)
83253{
84- memcpy (_address.bytes , address, sizeof (_address.bytes ));
254+ // IPv4 only conversion from byte pointer
255+ _type = IPv4;
256+ memset (_address.bytes , 0 , sizeof (_address.bytes ));
257+ memcpy (&_address.bytes [IPADDRESS_V4_BYTES_INDEX], address, sizeof (uint32_t ));
258+ return *this ;
259+ }
260+
261+ IPAddress &IPAddress::operator =(const char *address)
262+ {
263+ fromString (address);
85264 return *this ;
86265}
87266
88267IPAddress &IPAddress::operator =(uint32_t address)
89268{
90- _address.dword = address;
269+ // IPv4 conversion
270+ // See note on conversion/comparison and uint32_t
271+ _type = IPv4;
272+ memset (_address.bytes , 0 , sizeof (_address.bytes ));
273+ _address.dword [IPADDRESS_V4_DWORD_INDEX] = address;
91274 return *this ;
92275}
93276
277+ bool IPAddress::operator ==(const IPAddress &addr) const
278+ {
279+ return (addr._type == _type)
280+ && (memcmp (addr._address .bytes , _address.bytes , sizeof (_address.bytes )) == 0 );
281+ }
282+
94283bool IPAddress::operator ==(const uint8_t *addr) const
95284{
96- return memcmp (addr, _address.bytes , sizeof (_address.bytes )) == 0 ;
285+ // IPv4 only comparison to byte pointer
286+ // Can't support IPv6 as we know our type, but not the length of the pointer
287+ return _type == IPv4 && memcmp (addr, &_address.bytes [IPADDRESS_V4_BYTES_INDEX], sizeof (uint32_t )) == 0 ;
288+ }
289+
290+ uint8_t IPAddress::operator [](int index) const
291+ {
292+ if (_type == IPv4) {
293+ return _address.bytes [IPADDRESS_V4_BYTES_INDEX + index];
294+ }
295+ return _address.bytes [index];
296+ }
297+
298+ uint8_t &IPAddress::operator [](int index)
299+ {
300+ if (_type == IPv4) {
301+ return _address.bytes [IPADDRESS_V4_BYTES_INDEX + index];
302+ }
303+ return _address.bytes [index];
97304}
98305
99306size_t IPAddress::printTo (Print &p) const
100307{
101308 size_t n = 0 ;
309+
310+ if (_type == IPv6) {
311+ // IPv6 IETF canonical format: compress left-most longest run of two or more zero fields, lower case
312+ int8_t longest_start = -1 ;
313+ int8_t longest_length = 1 ;
314+ int8_t current_start = -1 ;
315+ int8_t current_length = 0 ;
316+ for (int8_t f = 0 ; f < 8 ; f++) {
317+ if (_address.bytes [f * 2 ] == 0 && _address.bytes [f * 2 + 1 ] == 0 ) {
318+ if (current_start == -1 ) {
319+ current_start = f;
320+ current_length = 1 ;
321+ } else {
322+ current_length++;
323+ }
324+ if (current_length > longest_length) {
325+ longest_start = current_start;
326+ longest_length = current_length;
327+ }
328+ } else {
329+ current_start = -1 ;
330+ }
331+ }
332+ for (int f = 0 ; f < 8 ; f++) {
333+ if (f < longest_start || f >= longest_start + longest_length) {
334+ uint8_t c1 = _address.bytes [f * 2 ] >> 4 ;
335+ uint8_t c2 = _address.bytes [f * 2 ] & 0xf ;
336+ uint8_t c3 = _address.bytes [f * 2 + 1 ] >> 4 ;
337+ uint8_t c4 = _address.bytes [f * 2 + 1 ] & 0xf ;
338+ if (c1 > 0 ) {
339+ n += p.print ((char )(c1 < 10 ? ' 0' + c1 : ' a' + c1 - 10 ));
340+ }
341+ if (c1 > 0 || c2 > 0 ) {
342+ n += p.print ((char )(c2 < 10 ? ' 0' + c2 : ' a' + c2 - 10 ));
343+ }
344+ if (c1 > 0 || c2 > 0 || c3 > 0 ) {
345+ n += p.print ((char )(c3 < 10 ? ' 0' + c3 : ' a' + c3 - 10 ));
346+ }
347+ n += p.print ((char )(c4 < 10 ? ' 0' + c4 : ' a' + c4 - 10 ));
348+ if (f < 7 ) {
349+ n += p.print (' :' );
350+ }
351+ } else if (f == longest_start) {
352+ if (longest_start == 0 ) {
353+ n += p.print (' :' );
354+ }
355+ n += p.print (' :' );
356+ }
357+ }
358+ return n;
359+ }
360+
361+ // IPv4
102362 for (int i = 0 ; i < 3 ; i++) {
103- n += p.print (_address.bytes [i], DEC);
363+ n += p.print (_address.bytes [IPADDRESS_V4_BYTES_INDEX + i], DEC);
104364 n += p.print (' .' );
105365 }
106- n += p.print (_address.bytes [3 ], DEC);
366+ n += p.print (_address.bytes [IPADDRESS_V4_BYTES_INDEX + 3 ], DEC);
107367 return n;
108368}
109369
370+ const IPAddress IN6ADDR_ANY (IPv6);
371+ const IPAddress INADDR_NONE (0 , 0 , 0 , 0 );
0 commit comments