Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit71773a5

Browse files
committed
Add IPv6 support; all backwards compatible (IPv4) tests pass
1 parentee040ed commit71773a5

File tree

2 files changed

+226
-30
lines changed

2 files changed

+226
-30
lines changed

‎api/IPAddress.cpp‎

Lines changed: 186 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,30 +22,61 @@
2222

2323
usingnamespacearduino;
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

3033
IPAddress::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

3843
IPAddress::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(constuint8_t *address)
59+
IPAddress::IPAddress(constuint8_t *address) : IPAddress(IPv4, address) {}
60+
61+
IPAddress::IPAddress(IPType ip_type,constuint8_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+
boolIPAddress::fromString(constchar *address) {
73+
if (!fromString4(address)) {
74+
returnfromString6(address);
75+
}
76+
returntrue;
4677
}
4778

48-
boolIPAddress::fromString(constchar *address)
79+
boolIPAddress::fromString4(constchar *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..'*/
74105
returnfalse;
75106
}
76-
_address.bytes[dots++] = acc;
107+
_address.bytes[12 +dots++] = acc;
77108
acc = -1;
78109
}
79110
else
@@ -91,37 +122,175 @@ bool IPAddress::fromString(const char *address)
91122
/* No value between dots, e.g. '1..'*/
92123
returnfalse;
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+
returntrue;
129+
}
130+
131+
boolIPAddress::fromString6(constchar *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+
returnfalse;
145+
}
146+
elseif (c ==':') {
147+
if (*address ==':') {
148+
if (doubledots >=0)
149+
// :: allowed once
150+
returnfalse;
151+
// remember location
152+
doubledots = dots + !!acc;
153+
address++;
154+
}
155+
if (dots ==7)
156+
// too many separators
157+
returnfalse;
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+
returnfalse;
166+
}
167+
168+
if (doubledots == -1 && dots !=7)
169+
// Too few separators
170+
returnfalse;
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;
95183
returntrue;
96184
}
97185

98186
IPAddress& IPAddress::operator=(constuint8_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));
101192
return *this;
102193
}
103194

104195
IPAddress& 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;
107204
return *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+
110212
bool IPAddress::operator==(constuint8_t* addr)const
111213
{
112-
returnmemcmp(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+
115233
size_tIPAddress::printTo(Print& p)const
116234
{
117235
size_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+
}elseif (f == longest_start) {
279+
n += p.print(':');
280+
}
281+
}
282+
return n;
283+
}
284+
285+
// IPv4
118286
for (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);
124292
return n;
125293
}
126294

295+
const IPAddressarduino::IN6ADDR_ANY(IPv6);
127296
const IPAddressarduino::INADDR_NONE(0,0,0,0);

‎api/IPAddress.h‎

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,55 +32,82 @@ namespace arduino {
3232

3333
// A class to make it easier to handle and pass around IP addresses
3434

35+
enum IPType {
36+
IPv4,
37+
IPv6
38+
};
39+
3540
classIPAddress :publicPrintable {
3641
private:
3742
union {
38-
uint8_t bytes[4];// IPv4 address
39-
uint32_t dword;
43+
uint8_t bytes[16];
44+
uint32_t dword[4];
4045
} _address;
46+
IPType _type;
4147

4248
// Access the raw byte array containing the address. Because this returns a pointer
4349
// to the internal structure rather than a copy of the address this function should only
4450
// be used when you know that the usage of the returned uint8_t* will be transient and not
4551
// stored.
46-
uint8_t*raw_address() {return _address.bytes; };
52+
// IPv4 only (for friends)
53+
uint8_t*raw_address() {
54+
if (_type == IPv4) {
55+
return &_address.bytes[12];
56+
}
57+
returnnullptr;
58+
};
59+
uint8_t*raw_bytes() {return _address.bytes; }
4760

4861
public:
4962
// Constructors
50-
IPAddress();
63+
IPAddress();// IPv4
64+
IPAddress(IPType ip_type);
5165
IPAddress(uint8_t first_octet,uint8_t second_octet,uint8_t third_octet,uint8_t fourth_octet);
52-
IPAddress(uint32_t address);
53-
IPAddress(constuint8_t *address);
66+
IPAddress(uint32_t address);// IPv4 only; see implementation note
67+
IPAddress(constuint8_t *address);// IPv4
68+
IPAddress(IPType ip_type,constuint8_t *address);
5469

5570
boolfromString(constchar *address);
5671
boolfromString(const String &address) {returnfromString(address.c_str()); }
5772

58-
// Overloaded cast operator to allow IPAddress objects to be used where a pointer
59-
// to a four-byte uint8_t array is expected
60-
operatoruint32_t()const {return _address.dword; };
61-
booloperator==(const IPAddress& addr)const {return _address.dword == addr._address.dword; };
62-
booloperator!=(const IPAddress& addr)const {return _address.dword != addr._address.dword; };
73+
// Overloaded cast operator to allow IPAddress objects to be used where a uint32_t is expected
74+
// IPv4 only; see implementation note
75+
operatoruint32_t()const {return _type == IPv4 ? _address.dword[3] :0; };
76+
77+
booloperator==(const IPAddress& addr)const;
78+
booloperator!=(const IPAddress& addr)const {return !(*this == addr); };
79+
80+
// IPv4 only; we don't know the length of the pointer
6381
booloperator==(constuint8_t* addr)const;
6482

6583
// Overloaded index operator to allow getting and setting individual octets of the address
66-
uint8_toperator[](int index)const {return _address.bytes[index]; };
67-
uint8_t&operator[](int index) {return _address.bytes[index]; };
84+
uint8_toperator[](int index)const;
85+
uint8_t&operator[](int index);
6886

6987
// Overloaded copy operators to allow initialisation of IPAddress objects from other types
88+
// IPv4 only
7089
IPAddress&operator=(constuint8_t *address);
90+
// IPv4 only; see implementation note
7191
IPAddress&operator=(uint32_t address);
7292

7393
virtualsize_tprintTo(Print& p)const;
7494

95+
IPTypetype() {return _type; }
96+
7597
friendclassUDP;
7698
friendclassClient;
7799
friendclassServer;
78100

79101
friend ::EthernetClass;
80102
friend ::DhcpClass;
81103
friend ::DNSClient;
104+
105+
protected:
106+
boolfromString4(constchar *address);
107+
boolfromString6(constchar *address);
82108
};
83109

110+
externconst IPAddress IN6ADDR_ANY;
84111
externconst IPAddress INADDR_NONE;
85112
}
86113

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp