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 ) -sizeof (uint32_t ));
37+ _address.bytes [12 ] = first_octet;
38+ _address.bytes [13 ] = second_octet;
39+ _address.bytes [14 ] = third_octet;
40+ _address.bytes [15 ] = fourth_octet;
3641}
3742
3843IPAddress::IPAddress (uint32_t address)
3944{
40- _address.dword = address;
45+ // IPv4 only
46+ _type = IPv4;
47+ memset (_address.bytes ,0 ,sizeof (_address.bytes ) -sizeof (uint32_t ));
48+ _address.dword [3 ] = address;
49+
50+ // NOTE on conversion/comparison and uint32_t:
51+ // These conversions are host platform dependent.
52+ // There is a defined integer representation of IPv4 addresses,
53+ // based on network byte order (will be the value on big endian systems),
54+ // e.g. http://2398766798 is the same as http://142.250.70.206,
55+ // However on little endian systems the octets 0x83, 0xFA, 0x46, 0xCE,
56+ // in that order, will form the integer (uint32_t) 3460758158 .
4157}
4258
43- IPAddress::IPAddress (const uint8_t *address)
59+ IPAddress::IPAddress (const uint8_t *address) : IPAddress(IPv4, address) {}
60+
61+ IPAddress::IPAddress (IPType ip_type,const uint8_t *address)
4462{
45- memcpy (_address.bytes , address,sizeof (_address.bytes ));
63+ _type = ip_type;
64+ if (ip_type == IPv4) {
65+ memset (_address.bytes ,0 ,sizeof (_address.bytes ) -sizeof (uint32_t ));
66+ memcpy (&_address.bytes [12 ], address,sizeof (uint32_t ));
67+ }else {
68+ memcpy (_address.bytes , address,sizeof (_address.bytes ));
69+ }
70+ }
71+
72+ bool IPAddress::fromString (const char *address) {
73+ if (!fromString4 (address)) {
74+ return fromString6 (address);
75+ }
76+ return true ;
4677}
4778
48- bool IPAddress::fromString (const char *address)
79+ bool IPAddress::fromString4 (const char *address)
4980{
5081// TODO: add support for "a", "a.b", "a.b.c" formats
5182
@@ -73,7 +104,7 @@ bool IPAddress::fromString(const char *address)
73104/* No value between dots, e.g. '1..'*/
74105return false ;
75106 }
76- _address.bytes [dots++] = acc;
107+ _address.bytes [12 + dots++] = acc;
77108 acc = -1 ;
78109 }
79110else
@@ -91,37 +122,175 @@ bool IPAddress::fromString(const char *address)
91122/* No value between dots, e.g. '1..'*/
92123return false ;
93124 }
94- _address.bytes [3 ] = acc;
125+ memset (_address.bytes ,0 ,sizeof (_address.bytes ) -sizeof (uint32_t ));
126+ _address.bytes [15 ] = acc;
127+ _type = IPv4;
128+ return true ;
129+ }
130+
131+ bool IPAddress::fromString6 (const char *address) {
132+ uint32_t acc =0 ;// Accumulator
133+ int dots =0 , doubledots = -1 ;
134+
135+ while (*address)
136+ {
137+ char c =tolower (*address++);
138+ if (isalnum (c)) {
139+ if (c >=' a' )
140+ c -=' a' -' 0' -10 ;
141+ acc = acc *16 + (c -' 0' );
142+ if (acc >0xffff )
143+ // Value out of range
144+ return false ;
145+ }
146+ else if (c ==' :' ) {
147+ if (*address ==' :' ) {
148+ if (doubledots >=0 )
149+ // :: allowed once
150+ return false ;
151+ // remember location
152+ doubledots = dots + !!acc;
153+ address++;
154+ }
155+ if (dots ==7 )
156+ // too many separators
157+ return false ;
158+ _address.bytes [dots] = acc >>2 ;
159+ _address.bytes [dots +1 ] = acc &0xff ;
160+ dots++;
161+ acc =0 ;
162+ }
163+ else
164+ // Invalid char
165+ return false ;
166+ }
167+
168+ if (doubledots == -1 && dots !=7 )
169+ // Too few separators
170+ return false ;
171+ _address.bytes [dots] = acc >>2 ;
172+ _address.bytes [dots +1 ] = acc &0xff ;
173+ dots++;
174+
175+ if (doubledots != -1 ) {
176+ for (int i = dots *2 - doubledots *2 -1 ; i >=0 ; i--)
177+ _address.bytes [16 - dots *2 + doubledots *2 + i] = _address.bytes [doubledots *2 + i];
178+ for (int i = doubledots *2 ; i <16 - dots *2 + doubledots *2 ; i++)
179+ _address.bytes [i] =0 ;
180+ }
181+
182+ _type = IPv6;
95183return true ;
96184}
97185
98186IPAddress& IPAddress::operator =(const uint8_t *address)
99187{
100- memcpy (_address.bytes , address,sizeof (_address.bytes ));
188+ // IPv4 only conversion from byte pointer
189+ _type = IPv4;
190+ memset (_address.bytes ,0 ,sizeof (_address.bytes ) -sizeof (uint32_t ));
191+ memcpy (&_address.bytes [12 ], address,sizeof (uint32_t ));
101192return *this ;
102193}
103194
104195IPAddress& IPAddress::operator =(uint32_t address)
105196{
106- _address.dword = address;
197+ // IPv4 conversion
198+ // See note on conversion/comparison and uint32_t
199+ _type = IPv4;
200+ _address.dword [0 ] =0 ;
201+ _address.dword [1 ] =0 ;
202+ _address.dword [2 ] =0 ;
203+ _address.dword [3 ] = address;
107204return *this ;
108205}
109206
207+ bool IPAddress::operator ==(const IPAddress& addr)const {
208+ return (addr._type == _type)
209+ && (memcmp (addr._address .bytes , _address.bytes ,sizeof (_address.bytes )) ==0 );
210+ };
211+
110212bool IPAddress::operator ==(const uint8_t * addr)const
111213{
112- return memcmp (addr, _address.bytes ,sizeof (_address.bytes )) ==0 ;
214+ // IPv4 only comparison to byte pointer
215+ // Can't support IPv6 as we know our type, but not the length of the pointer
216+ return _type == IPv4 &&memcmp (addr, &_address.bytes [12 ],sizeof (uint32_t )) ==0 ;
113217}
114218
219+ uint8_t IPAddress::operator [](int index)const {
220+ if (_type == IPv4) {
221+ return _address.bytes [index +12 ];
222+ }
223+ return _address.bytes [index];
224+ };
225+
226+ uint8_t & IPAddress::operator [](int index) {
227+ if (_type == IPv4) {
228+ return _address.bytes [index +12 ];
229+ }
230+ return _address.bytes [index];
231+ };
232+
115233size_t IPAddress::printTo (Print& p)const
116234{
117235size_t n =0 ;
236+
237+ if (_type == IPv6) {
238+ // IPv6 IETF canonical format: left-most longest run of all zero fields, lower case
239+ int8_t longest_start = -1 ;
240+ int8_t longest_length =0 ;
241+ int8_t current_start = -1 ;
242+ int8_t current_length =0 ;
243+ for (int8_t f =0 ; f <8 ; f++) {
244+ if (_address.bytes [f *2 ] ==0 && _address.bytes [f *2 +1 ] ==0 ) {
245+ if (current_start == -1 ) {
246+ current_start = f;
247+ current_length =0 ;
248+ }else {
249+ current_length++;
250+ }
251+ if (current_length > longest_length) {
252+ longest_start = current_start;
253+ longest_length = current_length;
254+ }
255+ }else {
256+ current_start = -1 ;
257+ }
258+ }
259+ for (int f =0 ; f <8 ; f++) {
260+ if (f < longest_start || f >= longest_start + longest_length) {
261+ uint8_t c1 = _address.bytes [f *2 ] >>1 ;
262+ uint8_t c2 = _address.bytes [f *2 ] &0xf ;
263+ uint8_t c3 = _address.bytes [f *2 +1 ] >>1 ;
264+ uint8_t c4 = _address.bytes [f *2 +1 ] &0xf ;
265+ if (c1 >0 ) {
266+ n += p.print (c1 <10 ?' 0' + c1 :' a' + c1 -10 );
267+ }
268+ if (c1 >0 || c2 >0 ) {
269+ n += p.print (c2 <10 ?' 0' + c2 :' a' + c2 -10 );
270+ }
271+ if (c1 >0 || c2 >0 || c3 >0 ) {
272+ n += p.print (c3 <10 ?' 0' + c3 :' a' + c3 -10 );
273+ }
274+ n += p.print (c4 <10 ?' 0' + c4 :' a' + c4 -10 );
275+ if (f <7 ) {
276+ n += p.print (' :' );
277+ }
278+ }else if (f == longest_start) {
279+ n += p.print (' :' );
280+ }
281+ }
282+ return n;
283+ }
284+
285+ // IPv4
118286for (int i =0 ; i <3 ; i++)
119287 {
120- n += p.print (_address.bytes [i], DEC);
288+ n += p.print (_address.bytes [12 + i], DEC);
121289 n += p.print (' .' );
122290 }
123- n += p.print (_address.bytes [3 ], DEC);
291+ n += p.print (_address.bytes [15 ], DEC);
124292return n;
125293}
126294
295+ const IPAddressarduino::IN6ADDR_ANY (IPv6);
127296const IPAddressarduino::INADDR_NONE (0 ,0 ,0 ,0 );