2222
2323using namespace arduino ;
2424
25- IPAddress::IPAddress ()
25+ IPAddress::IPAddress () : IPAddress(IPv4) {}
26+
27+ IPAddress::IPAddress (IPType ip_type)
2628{
27- _address.dword =0 ;
29+ _type = ip_type;
30+ memset (_address.bytes ,0 ,sizeof (_address.bytes ));
2831}
2932
3033IPAddress::IPAddress (uint8_t first_octet,uint8_t second_octet,uint8_t third_octet,uint8_t fourth_octet)
3134{
32- _address.bytes [0 ] = first_octet;
33- _address.bytes [1 ] = second_octet;
34- _address.bytes [2 ] = third_octet;
35- _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;
3661}
3762
3863IPAddress::IPAddress (uint32_t address)
3964{
40- _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 .
4177}
4278
43- IPAddress::IPAddress (const uint8_t *address)
79+ IPAddress::IPAddress (const uint8_t *address) : IPAddress(IPv4, address) {}
80+
81+ IPAddress::IPAddress (IPType ip_type,const uint8_t *address)
4482{
45- memcpy (_address.bytes , address,sizeof (_address.bytes ));
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+ }
4690}
4791
48- bool IPAddress::fromString (const char *address)
92+ bool IPAddress::fromString (const char *address) {
93+ if (!fromString4 (address)) {
94+ return fromString6 (address);
95+ }
96+ return true ;
97+ }
98+
99+ bool IPAddress::fromString4 (const char *address)
49100{
50101// TODO: add support for "a", "a.b", "a.b.c" formats
51102
52103int16_t acc = -1 ;// Accumulator
53104uint8_t dots =0 ;
54105
106+ memset (_address.bytes ,0 ,sizeof (_address.bytes ));
55107while (*address)
56108 {
57109char c = *address++;
@@ -73,7 +125,7 @@ bool IPAddress::fromString(const char *address)
73125/* No value between dots, e.g. '1..'*/
74126return false ;
75127 }
76- _address.bytes [dots++] = acc;
128+ _address.bytes [IPADDRESS_V4_BYTES_INDEX + dots++] = acc;
77129 acc = -1 ;
78130 }
79131else
@@ -91,37 +143,188 @@ bool IPAddress::fromString(const char *address)
91143/* No value between dots, e.g. '1..'*/
92144return false ;
93145 }
94- _address.bytes [3 ] = acc;
146+ _address.bytes [IPADDRESS_V4_BYTES_INDEX +3 ] = acc;
147+ _type = IPv4;
148+ return true ;
149+ }
150+
151+ bool IPAddress::fromString6 (const char *address) {
152+ uint32_t acc =0 ;// Accumulator
153+ int colons =0 , double_colons = -1 ;
154+
155+ while (*address)
156+ {
157+ char c =tolower (*address++);
158+ if (isalnum (c) && c <=' f' ) {
159+ if (c >=' a' )
160+ c -=' a' -' 0' -10 ;
161+ acc = acc *16 + (c -' 0' );
162+ if (acc >0xffff )
163+ // Value out of range
164+ return false ;
165+ }
166+ else if (c ==' :' ) {
167+ if (*address ==' :' ) {
168+ if (double_colons >=0 ) {
169+ // :: allowed once
170+ return false ;
171+ }
172+ if (*address !=' \0 ' && *(address +1 ) ==' :' ) {
173+ // ::: not allowed
174+ return false ;
175+ }
176+ // remember location
177+ double_colons = colons + !!acc;
178+ address++;
179+ }else if (*address ==' \0 ' ) {
180+ // can't end with a single colon
181+ return false ;
182+ }
183+ if (colons ==7 )
184+ // too many separators
185+ return false ;
186+ _address.bytes [colons *2 ] = acc >>8 ;
187+ _address.bytes [colons *2 +1 ] = acc &0xff ;
188+ colons++;
189+ acc =0 ;
190+ }
191+ else
192+ // Invalid char
193+ return false ;
194+ }
195+
196+ if (double_colons == -1 && colons !=7 ) {
197+ // Too few separators
198+ return false ;
199+ }
200+ if (double_colons > -1 && colons >6 ) {
201+ // Too many segments (double colon must be at least one zero field)
202+ return false ;
203+ }
204+ _address.bytes [colons *2 ] = acc >>8 ;
205+ _address.bytes [colons *2 +1 ] = acc &0xff ;
206+ colons++;
207+
208+ if (double_colons != -1 ) {
209+ for (int i = colons *2 - double_colons *2 -1 ; i >=0 ; i--)
210+ _address.bytes [16 - colons *2 + double_colons *2 + i] = _address.bytes [double_colons *2 + i];
211+ for (int i = double_colons *2 ; i <16 - colons *2 + double_colons *2 ; i++)
212+ _address.bytes [i] =0 ;
213+ }
214+
215+ _type = IPv6;
95216return true ;
96217}
97218
98219IPAddress& IPAddress::operator =(const uint8_t *address)
99220{
100- memcpy (_address.bytes , address,sizeof (_address.bytes ));
221+ // IPv4 only conversion from byte pointer
222+ _type = IPv4;
223+ memset (_address.bytes ,0 ,sizeof (_address.bytes ));
224+ memcpy (&_address.bytes [IPADDRESS_V4_BYTES_INDEX], address,sizeof (uint32_t ));
101225return *this ;
102226}
103227
104228IPAddress& IPAddress::operator =(uint32_t address)
105229{
106- _address.dword = address;
230+ // IPv4 conversion
231+ // See note on conversion/comparison and uint32_t
232+ _type = IPv4;
233+ memset (_address.bytes ,0 ,sizeof (_address.bytes ));
234+ _address.dword [IPADDRESS_V4_DWORD_INDEX] = address;
107235return *this ;
108236}
109237
238+ bool IPAddress::operator ==(const IPAddress& addr)const {
239+ return (addr._type == _type)
240+ && (memcmp (addr._address .bytes , _address.bytes ,sizeof (_address.bytes )) ==0 );
241+ }
242+
110243bool IPAddress::operator ==(const uint8_t * addr)const
111244{
112- return memcmp (addr, _address.bytes ,sizeof (_address.bytes )) ==0 ;
245+ // IPv4 only comparison to byte pointer
246+ // Can't support IPv6 as we know our type, but not the length of the pointer
247+ return _type == IPv4 &&memcmp (addr, &_address.bytes [IPADDRESS_V4_BYTES_INDEX],sizeof (uint32_t )) ==0 ;
248+ }
249+
250+ uint8_t IPAddress::operator [](int index)const {
251+ if (_type == IPv4) {
252+ return _address.bytes [IPADDRESS_V4_BYTES_INDEX + index];
253+ }
254+ return _address.bytes [index];
255+ }
256+
257+ uint8_t & IPAddress::operator [](int index) {
258+ if (_type == IPv4) {
259+ return _address.bytes [IPADDRESS_V4_BYTES_INDEX + index];
260+ }
261+ return _address.bytes [index];
113262}
114263
115264size_t IPAddress::printTo (Print& p)const
116265{
117266size_t n =0 ;
267+
268+ if (_type == IPv6) {
269+ // IPv6 IETF canonical format: compress left-most longest run of two or more zero fields, lower case
270+ int8_t longest_start = -1 ;
271+ int8_t longest_length =1 ;
272+ int8_t current_start = -1 ;
273+ int8_t current_length =0 ;
274+ for (int8_t f =0 ; f <8 ; f++) {
275+ if (_address.bytes [f *2 ] ==0 && _address.bytes [f *2 +1 ] ==0 ) {
276+ if (current_start == -1 ) {
277+ current_start = f;
278+ current_length =1 ;
279+ }else {
280+ current_length++;
281+ }
282+ if (current_length > longest_length) {
283+ longest_start = current_start;
284+ longest_length = current_length;
285+ }
286+ }else {
287+ current_start = -1 ;
288+ }
289+ }
290+ for (int f =0 ; f <8 ; f++) {
291+ if (f < longest_start || f >= longest_start + longest_length) {
292+ uint8_t c1 = _address.bytes [f *2 ] >>4 ;
293+ uint8_t c2 = _address.bytes [f *2 ] &0xf ;
294+ uint8_t c3 = _address.bytes [f *2 +1 ] >>4 ;
295+ uint8_t c4 = _address.bytes [f *2 +1 ] &0xf ;
296+ if (c1 >0 ) {
297+ n += p.print ((char )(c1 <10 ?' 0' + c1 :' a' + c1 -10 ));
298+ }
299+ if (c1 >0 || c2 >0 ) {
300+ n += p.print ((char )(c2 <10 ?' 0' + c2 :' a' + c2 -10 ));
301+ }
302+ if (c1 >0 || c2 >0 || c3 >0 ) {
303+ n += p.print ((char )(c3 <10 ?' 0' + c3 :' a' + c3 -10 ));
304+ }
305+ n += p.print ((char )(c4 <10 ?' 0' + c4 :' a' + c4 -10 ));
306+ if (f <7 ) {
307+ n += p.print (' :' );
308+ }
309+ }else if (f == longest_start) {
310+ if (longest_start ==0 ) {
311+ n += p.print (' :' );
312+ }
313+ n += p.print (' :' );
314+ }
315+ }
316+ return n;
317+ }
318+
319+ // IPv4
118320for (int i =0 ; i <3 ; i++)
119321 {
120- n += p.print (_address.bytes [i], DEC);
322+ n += p.print (_address.bytes [IPADDRESS_V4_BYTES_INDEX + i], DEC);
121323 n += p.print (' .' );
122324 }
123- n += p.print (_address.bytes [3 ], DEC);
325+ n += p.print (_address.bytes [IPADDRESS_V4_BYTES_INDEX + 3 ], DEC);
124326return n;
125327}
126328
329+ const IPAddressarduino::IN6ADDR_ANY (IPv6);
127330const IPAddressarduino::INADDR_NONE (0 ,0 ,0 ,0 );