/src/poco/Net/src/IPAddress.cpp
Line | Count | Source |
1 | | // |
2 | | // IPAddress.cpp |
3 | | // |
4 | | // Library: Net |
5 | | // Package: NetCore |
6 | | // Module: IPAddress |
7 | | // |
8 | | // Copyright (c) 2005-2011, Applied Informatics Software Engineering GmbH. |
9 | | // and Contributors. |
10 | | // |
11 | | // SPDX-License-Identifier: BSL-1.0 |
12 | | // |
13 | | |
14 | | |
15 | | #include "Poco/Net/IPAddress.h" |
16 | | #include "Poco/Net/NetException.h" |
17 | | #include "Poco/RefCountedObject.h" |
18 | | #include "Poco/NumberFormatter.h" |
19 | | #include "Poco/BinaryReader.h" |
20 | | #include "Poco/BinaryWriter.h" |
21 | | #include "Poco/String.h" |
22 | | #include "Poco/Format.h" |
23 | | #include "Poco/Types.h" |
24 | | |
25 | | |
26 | | using Poco::RefCountedObject; |
27 | | using Poco::NumberFormatter; |
28 | | using Poco::BinaryReader; |
29 | | using Poco::BinaryWriter; |
30 | | using Poco::toLower; |
31 | | using Poco::trim; |
32 | | using Poco::UInt8; |
33 | | using Poco::UInt16; |
34 | | using Poco::UInt32; |
35 | | using Poco::Net::Impl::IPAddressImpl; |
36 | | using Poco::Net::Impl::IPv4AddressImpl; |
37 | | #if defined(POCO_HAVE_IPv6) |
38 | | using Poco::Net::Impl::IPv6AddressImpl; |
39 | | #endif |
40 | | |
41 | | |
42 | | namespace Poco { |
43 | | namespace Net { |
44 | | |
45 | | |
46 | | #if !defined(_MSC_VER) || defined(__STDC__) |
47 | | // Go home MSVC, you're drunk... |
48 | | // See http://stackoverflow.com/questions/5899857/multiple-definition-error-for-static-const-class-members |
49 | | const IPAddress::Family IPAddress::IPv4; |
50 | | #if defined(POCO_HAVE_IPv6) |
51 | | const IPAddress::Family IPAddress::IPv6; |
52 | | #endif |
53 | | #endif |
54 | | |
55 | | |
56 | | IPAddress::IPAddress() |
57 | 0 | { |
58 | 0 | newIPv4(); |
59 | 0 | } |
60 | | |
61 | | |
62 | | IPAddress::IPAddress(const IPAddress& addr) |
63 | 0 | { |
64 | 0 | if (addr.family() == IPv4) |
65 | 0 | newIPv4(addr.addr()); |
66 | 0 | #if defined(POCO_HAVE_IPv6) |
67 | 0 | else |
68 | 0 | newIPv6(addr.addr(), addr.scope()); |
69 | 0 | #endif |
70 | 0 | } |
71 | | |
72 | | |
73 | 0 | IPAddress::IPAddress(IPAddress&& addr): _pImpl(std::move(addr._pImpl)) |
74 | 0 | { |
75 | 0 | } |
76 | | |
77 | | |
78 | | IPAddress::IPAddress(Family family) |
79 | 0 | { |
80 | 0 | if (family == IPv4) |
81 | 0 | newIPv4(); |
82 | 0 | #if defined(POCO_HAVE_IPv6) |
83 | 0 | else if (family == IPv6) |
84 | 0 | newIPv6(); |
85 | 0 | #endif |
86 | 0 | else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); |
87 | 0 | } |
88 | | |
89 | | |
90 | | IPAddress::IPAddress(const std::string& addr) |
91 | 0 | { |
92 | 0 | IPv4AddressImpl empty4 = IPv4AddressImpl(); |
93 | 0 | if (addr.empty() || trim(addr) == "0.0.0.0") |
94 | 0 | { |
95 | 0 | newIPv4(empty4.addr()); |
96 | 0 | return; |
97 | 0 | } |
98 | | |
99 | 0 | IPv4AddressImpl addr4(IPv4AddressImpl::parse(addr)); |
100 | 0 | if (addr4 != empty4) |
101 | 0 | { |
102 | 0 | newIPv4(addr4.addr()); |
103 | 0 | return; |
104 | 0 | } |
105 | | |
106 | 0 | #if defined(POCO_HAVE_IPv6) |
107 | 0 | IPv6AddressImpl empty6 = IPv6AddressImpl(); |
108 | 0 | if (addr.empty() || trimIPv6(addr) == "::") |
109 | 0 | { |
110 | 0 | newIPv6(empty6.addr()); |
111 | 0 | return; |
112 | 0 | } |
113 | | |
114 | 0 | IPv6AddressImpl addr6(IPv6AddressImpl::parse(addr)); |
115 | 0 | if (addr6 != IPv6AddressImpl()) |
116 | 0 | { |
117 | 0 | newIPv6(addr6.addr(), addr6.scope()); |
118 | 0 | return; |
119 | 0 | } |
120 | 0 | #endif |
121 | | |
122 | 0 | throw InvalidAddressException(addr); |
123 | 0 | } |
124 | | |
125 | | |
126 | | IPAddress::IPAddress(const std::string& addr, Family family) |
127 | 0 | { |
128 | 0 | if (family == IPv4) |
129 | 0 | { |
130 | 0 | IPv4AddressImpl addr4(IPv4AddressImpl::parse(addr)); |
131 | 0 | newIPv4(addr4.addr()); |
132 | 0 | return; |
133 | 0 | } |
134 | 0 | #if defined(POCO_HAVE_IPv6) |
135 | 0 | else if (family == IPv6) |
136 | 0 | { |
137 | 0 | IPv6AddressImpl addr6(IPv6AddressImpl::parse(addr)); |
138 | 0 | newIPv6(addr6.addr(), addr6.scope()); |
139 | 0 | return; |
140 | 0 | } |
141 | 0 | #endif |
142 | 0 | else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); |
143 | 0 | } |
144 | | |
145 | | |
146 | | IPAddress::IPAddress(const void* addr, poco_socklen_t length) |
147 | 0 | : _pImpl(nullptr) |
148 | 0 | { |
149 | 0 | if (length == sizeof(struct in_addr)) |
150 | 0 | newIPv4(addr); |
151 | 0 | #if defined(POCO_HAVE_IPv6) |
152 | 0 | else if (length == sizeof(struct in6_addr)) |
153 | 0 | newIPv6(addr); |
154 | 0 | #endif |
155 | 0 | else throw Poco::InvalidArgumentException("Invalid address length passed to IPAddress()"); |
156 | 0 | } |
157 | | |
158 | | |
159 | | IPAddress::IPAddress(const void* addr, poco_socklen_t length, Poco::UInt32 scope) |
160 | 0 | { |
161 | 0 | if (length == sizeof(struct in_addr)) |
162 | 0 | newIPv4(addr); |
163 | 0 | #if defined(POCO_HAVE_IPv6) |
164 | 0 | else if (length == sizeof(struct in6_addr)) |
165 | 0 | newIPv6(addr, scope); |
166 | 0 | #endif |
167 | 0 | else throw Poco::InvalidArgumentException("Invalid address length passed to IPAddress()"); |
168 | 0 | } |
169 | | |
170 | | |
171 | | IPAddress::IPAddress(unsigned prefix, Family family) |
172 | 0 | { |
173 | 0 | if (family == IPv4) |
174 | 0 | { |
175 | 0 | if (prefix <= 32) |
176 | 0 | newIPv4(prefix); |
177 | 0 | else |
178 | 0 | throw Poco::InvalidArgumentException("Invalid prefix length passed to IPAddress()"); |
179 | 0 | } |
180 | 0 | #if defined(POCO_HAVE_IPv6) |
181 | 0 | else if (family == IPv6) |
182 | 0 | { |
183 | 0 | if (prefix <= 128) |
184 | 0 | newIPv6(prefix); |
185 | 0 | else |
186 | 0 | throw Poco::InvalidArgumentException("Invalid prefix length passed to IPAddress()"); |
187 | 0 | } |
188 | 0 | #endif |
189 | 0 | else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); |
190 | 0 | } |
191 | | |
192 | | |
193 | | #if defined(_WIN32) |
194 | | IPAddress::IPAddress(const SOCKET_ADDRESS& socket_address) |
195 | | : _pImpl(nullptr) |
196 | | { |
197 | | ADDRESS_FAMILY family = socket_address.lpSockaddr->sa_family; |
198 | | if (family == AF_INET) |
199 | | newIPv4(&reinterpret_cast<const struct sockaddr_in*>(socket_address.lpSockaddr)->sin_addr); |
200 | | #if defined(POCO_HAVE_IPv6) |
201 | | else if (family == AF_INET6) |
202 | | newIPv6(&reinterpret_cast<const struct sockaddr_in6*>(socket_address.lpSockaddr)->sin6_addr, |
203 | | reinterpret_cast<const struct sockaddr_in6*>(socket_address.lpSockaddr)->sin6_scope_id); |
204 | | #endif |
205 | | else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); |
206 | | } |
207 | | #endif |
208 | | |
209 | | |
210 | | IPAddress::IPAddress(const struct sockaddr& sockaddr) |
211 | 0 | { |
212 | 0 | unsigned short family = sockaddr.sa_family; |
213 | 0 | if (family == AF_INET) |
214 | 0 | newIPv4(&reinterpret_cast<const struct sockaddr_in*>(&sockaddr)->sin_addr); |
215 | 0 | #if defined(POCO_HAVE_IPv6) |
216 | 0 | else if (family == AF_INET6) |
217 | 0 | newIPv6(&reinterpret_cast<const struct sockaddr_in6*>(&sockaddr)->sin6_addr, |
218 | 0 | reinterpret_cast<const struct sockaddr_in6*>(&sockaddr)->sin6_scope_id); |
219 | 0 | #endif |
220 | 0 | else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); |
221 | 0 | } |
222 | | |
223 | | |
224 | | IPAddress::~IPAddress() |
225 | 0 | { |
226 | 0 | } |
227 | | |
228 | | |
229 | | IPAddress& IPAddress::operator = (const IPAddress& addr) |
230 | 0 | { |
231 | 0 | if (&addr != this) |
232 | 0 | { |
233 | 0 | if (addr.family() == IPAddress::IPv4) |
234 | 0 | newIPv4(addr.addr()); |
235 | 0 | #if defined(POCO_HAVE_IPv6) |
236 | 0 | else if (addr.family() == IPAddress::IPv6) |
237 | 0 | newIPv6(addr.addr(), addr.scope()); |
238 | 0 | #endif |
239 | 0 | else |
240 | 0 | throw Poco::InvalidArgumentException("Invalid or unsupported address family"); |
241 | 0 | } |
242 | 0 | return *this; |
243 | 0 | } |
244 | | |
245 | | |
246 | | IPAddress& IPAddress::operator = (IPAddress&& addr) |
247 | 0 | { |
248 | 0 | _pImpl = std::move(addr._pImpl); |
249 | 0 | return *this; |
250 | 0 | } |
251 | | |
252 | | |
253 | | IPAddress::Family IPAddress::family() const |
254 | 0 | { |
255 | 0 | return pImpl()->family(); |
256 | 0 | } |
257 | | |
258 | | |
259 | | Poco::UInt32 IPAddress::scope() const |
260 | 0 | { |
261 | 0 | return pImpl()->scope(); |
262 | 0 | } |
263 | | |
264 | | |
265 | | std::string IPAddress::toString() const |
266 | 0 | { |
267 | 0 | return pImpl()->toString(); |
268 | 0 | } |
269 | | |
270 | | |
271 | | bool IPAddress::isWildcard() const |
272 | 0 | { |
273 | 0 | return pImpl()->isWildcard(); |
274 | 0 | } |
275 | | |
276 | | |
277 | | bool IPAddress::isBroadcast() const |
278 | 0 | { |
279 | 0 | return pImpl()->isBroadcast(); |
280 | 0 | } |
281 | | |
282 | | |
283 | | bool IPAddress::isLoopback() const |
284 | 0 | { |
285 | 0 | return pImpl()->isLoopback(); |
286 | 0 | } |
287 | | |
288 | | |
289 | | bool IPAddress::isMulticast() const |
290 | 0 | { |
291 | 0 | return pImpl()->isMulticast(); |
292 | 0 | } |
293 | | |
294 | | |
295 | | bool IPAddress::isUnicast() const |
296 | 0 | { |
297 | 0 | return !isWildcard() && !isBroadcast() && !isMulticast(); |
298 | 0 | } |
299 | | |
300 | | |
301 | | bool IPAddress::isLinkLocal() const |
302 | 0 | { |
303 | 0 | return pImpl()->isLinkLocal(); |
304 | 0 | } |
305 | | |
306 | | |
307 | | bool IPAddress::isSiteLocal() const |
308 | 0 | { |
309 | 0 | return pImpl()->isSiteLocal(); |
310 | 0 | } |
311 | | |
312 | | |
313 | | bool IPAddress::isIPv4Compatible() const |
314 | 0 | { |
315 | 0 | return pImpl()->isIPv4Compatible(); |
316 | 0 | } |
317 | | |
318 | | |
319 | | bool IPAddress::isIPv4Mapped() const |
320 | 0 | { |
321 | 0 | return pImpl()->isIPv4Mapped(); |
322 | 0 | } |
323 | | |
324 | | |
325 | | bool IPAddress::isWellKnownMC() const |
326 | 0 | { |
327 | 0 | return pImpl()->isWellKnownMC(); |
328 | 0 | } |
329 | | |
330 | | |
331 | | bool IPAddress::isNodeLocalMC() const |
332 | 0 | { |
333 | 0 | return pImpl()->isNodeLocalMC(); |
334 | 0 | } |
335 | | |
336 | | |
337 | | bool IPAddress::isLinkLocalMC() const |
338 | 0 | { |
339 | 0 | return pImpl()->isLinkLocalMC(); |
340 | 0 | } |
341 | | |
342 | | |
343 | | bool IPAddress::isSiteLocalMC() const |
344 | 0 | { |
345 | 0 | return pImpl()->isSiteLocalMC(); |
346 | 0 | } |
347 | | |
348 | | |
349 | | bool IPAddress::isOrgLocalMC() const |
350 | 0 | { |
351 | 0 | return pImpl()->isOrgLocalMC(); |
352 | 0 | } |
353 | | |
354 | | |
355 | | bool IPAddress::isGlobalMC() const |
356 | 0 | { |
357 | 0 | return pImpl()->isGlobalMC(); |
358 | 0 | } |
359 | | |
360 | | |
361 | | bool IPAddress::operator == (const IPAddress& a) const |
362 | 0 | { |
363 | 0 | poco_socklen_t l1 = length(); |
364 | 0 | poco_socklen_t l2 = a.length(); |
365 | 0 | if (l1 == l2) |
366 | 0 | { |
367 | 0 | #if defined(POCO_HAVE_IPv6) |
368 | 0 | if ( scope() != a.scope() ) |
369 | 0 | return false; |
370 | 0 | #endif |
371 | 0 | return std::memcmp(addr(), a.addr(), l1) == 0; |
372 | 0 | } |
373 | 0 | else return false; |
374 | 0 | } |
375 | | |
376 | | |
377 | | bool IPAddress::operator != (const IPAddress& a) const |
378 | 0 | { |
379 | 0 | return !(*this == a); |
380 | 0 | } |
381 | | |
382 | | |
383 | | bool IPAddress::operator < (const IPAddress& a) const |
384 | 0 | { |
385 | 0 | poco_socklen_t l1 = length(); |
386 | 0 | poco_socklen_t l2 = a.length(); |
387 | 0 | if (l1 == l2) |
388 | 0 | { |
389 | 0 | #if defined(POCO_HAVE_IPv6) |
390 | 0 | if ( scope() != a.scope() ) |
391 | 0 | return scope() < a.scope(); |
392 | 0 | #endif |
393 | 0 | return std::memcmp(addr(), a.addr(), l1) < 0; |
394 | 0 | } |
395 | 0 | else return l1 < l2; |
396 | 0 | } |
397 | | |
398 | | |
399 | | bool IPAddress::operator <= (const IPAddress& a) const |
400 | 0 | { |
401 | 0 | return !(a < *this); |
402 | 0 | } |
403 | | |
404 | | |
405 | | bool IPAddress::operator > (const IPAddress& a) const |
406 | 0 | { |
407 | 0 | return a < *this; |
408 | 0 | } |
409 | | |
410 | | |
411 | | bool IPAddress::operator >= (const IPAddress& a) const |
412 | 0 | { |
413 | 0 | return !(*this < a); |
414 | 0 | } |
415 | | |
416 | | |
417 | | IPAddress IPAddress::operator & (const IPAddress& other) const |
418 | 0 | { |
419 | 0 | if (family() == other.family()) |
420 | 0 | { |
421 | 0 | if (family() == IPv4) |
422 | 0 | { |
423 | 0 | IPv4AddressImpl t(pImpl()->addr()); |
424 | 0 | IPv4AddressImpl o(other.pImpl()->addr()); |
425 | 0 | return IPAddress((t & o).addr(), sizeof(struct in_addr)); |
426 | 0 | } |
427 | 0 | #if defined(POCO_HAVE_IPv6) |
428 | 0 | else if (family() == IPv6) |
429 | 0 | { |
430 | 0 | const IPv6AddressImpl t(pImpl()->addr(), pImpl()->scope()); |
431 | 0 | const IPv6AddressImpl o(other.pImpl()->addr(), other.pImpl()->scope()); |
432 | 0 | const IPv6AddressImpl r = t & o; |
433 | 0 | return IPAddress(r.addr(), sizeof(struct in6_addr), r.scope()); |
434 | 0 | } |
435 | 0 | #endif |
436 | 0 | else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); |
437 | 0 | } |
438 | 0 | else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); |
439 | 0 | } |
440 | | |
441 | | |
442 | | IPAddress IPAddress::operator | (const IPAddress& other) const |
443 | 0 | { |
444 | 0 | if (family() == other.family()) |
445 | 0 | { |
446 | 0 | if (family() == IPv4) |
447 | 0 | { |
448 | 0 | IPv4AddressImpl t(pImpl()->addr()); |
449 | 0 | IPv4AddressImpl o(other.pImpl()->addr()); |
450 | 0 | return IPAddress((t | o).addr(), sizeof(struct in_addr)); |
451 | 0 | } |
452 | 0 | #if defined(POCO_HAVE_IPv6) |
453 | 0 | else if (family() == IPv6) |
454 | 0 | { |
455 | 0 | const IPv6AddressImpl t(pImpl()->addr(), pImpl()->scope()); |
456 | 0 | const IPv6AddressImpl o(other.pImpl()->addr(), other.pImpl()->scope()); |
457 | 0 | const IPv6AddressImpl r = t | o; |
458 | 0 | return IPAddress(r.addr(), sizeof(struct in6_addr), r.scope()); |
459 | 0 | } |
460 | 0 | #endif |
461 | 0 | else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); |
462 | 0 | } |
463 | 0 | else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); |
464 | 0 | } |
465 | | |
466 | | |
467 | | IPAddress IPAddress::operator ^ (const IPAddress& other) const |
468 | 0 | { |
469 | 0 | if (family() == other.family()) |
470 | 0 | { |
471 | 0 | if (family() == IPv4) |
472 | 0 | { |
473 | 0 | IPv4AddressImpl t(pImpl()->addr()); |
474 | 0 | IPv4AddressImpl o(other.pImpl()->addr()); |
475 | 0 | return IPAddress((t ^ o).addr(), sizeof(struct in_addr)); |
476 | 0 | } |
477 | 0 | #if defined(POCO_HAVE_IPv6) |
478 | 0 | else if (family() == IPv6) |
479 | 0 | { |
480 | 0 | const IPv6AddressImpl t(pImpl()->addr(), pImpl()->scope()); |
481 | 0 | const IPv6AddressImpl o(other.pImpl()->addr(), other.pImpl()->scope()); |
482 | 0 | const IPv6AddressImpl r = t ^ o; |
483 | 0 | return IPAddress(r.addr(), sizeof(struct in6_addr), r.scope()); |
484 | 0 | } |
485 | 0 | #endif |
486 | 0 | else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); |
487 | 0 | } |
488 | 0 | else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); |
489 | 0 | } |
490 | | |
491 | | |
492 | | IPAddress IPAddress::operator ~ () const |
493 | 0 | { |
494 | 0 | if (family() == IPv4) |
495 | 0 | { |
496 | 0 | IPv4AddressImpl self(this->pImpl()->addr()); |
497 | 0 | return IPAddress((~self).addr(), sizeof(struct in_addr)); |
498 | 0 | } |
499 | 0 | #if defined(POCO_HAVE_IPv6) |
500 | 0 | else if (family() == IPv6) |
501 | 0 | { |
502 | 0 | const IPv6AddressImpl self(pImpl()->addr(), pImpl()->scope()); |
503 | 0 | const IPv6AddressImpl r = ~self; |
504 | 0 | return IPAddress(r.addr(), sizeof(struct in6_addr), r.scope()); |
505 | 0 | } |
506 | 0 | #endif |
507 | 0 | else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); |
508 | 0 | } |
509 | | |
510 | | |
511 | | poco_socklen_t IPAddress::length() const |
512 | 0 | { |
513 | 0 | return pImpl()->length(); |
514 | 0 | } |
515 | | |
516 | | |
517 | | const void* IPAddress::addr() const |
518 | 0 | { |
519 | 0 | return pImpl()->addr(); |
520 | 0 | } |
521 | | |
522 | | |
523 | | int IPAddress::af() const |
524 | 0 | { |
525 | 0 | return pImpl()->af(); |
526 | 0 | } |
527 | | |
528 | | |
529 | | unsigned IPAddress::prefixLength() const |
530 | 0 | { |
531 | 0 | return pImpl()->prefixLength(); |
532 | 0 | } |
533 | | |
534 | | |
535 | | std::string& IPAddress::compressV6(std::string& v6addr) |
536 | 0 | { |
537 | | // get rid of leading zeros at the beginning |
538 | 0 | while (v6addr.size() && v6addr[0] == '0') v6addr.erase(v6addr.begin()); |
539 | | |
540 | | // get rid of leading zeros in the middle |
541 | 0 | while (v6addr.find(":0") != std::string::npos) |
542 | 0 | Poco::replaceInPlace(v6addr, ":0", ":"); |
543 | | |
544 | | // get rid of extraneous colons |
545 | 0 | while (v6addr.find(":::") != std::string::npos) |
546 | 0 | Poco::replaceInPlace(v6addr, ":::", "::"); |
547 | |
|
548 | 0 | return v6addr; |
549 | 0 | } |
550 | | |
551 | | |
552 | | std::string IPAddress::trimIPv6(const std::string& v6Addr) |
553 | 0 | { |
554 | 0 | std::string v6addr(v6Addr); |
555 | 0 | std::string::size_type len = v6addr.length(); |
556 | 0 | int dblColOcc = 0; |
557 | 0 | auto pos = v6addr.find("::"); |
558 | 0 | while ((pos <= len-2) && (pos != std::string::npos)) |
559 | 0 | { |
560 | 0 | ++dblColOcc; |
561 | 0 | pos = v6addr.find("::", pos + 2); |
562 | 0 | } |
563 | |
|
564 | 0 | if ((dblColOcc > 1) || |
565 | 0 | (std::count(v6addr.begin(), v6addr.end(), ':') > 8) || |
566 | 0 | (v6addr.find(":::") != std::string::npos) || |
567 | 0 | ((len >= 2) && ((v6addr[len-1] == ':') && v6addr[len-2] != ':'))) |
568 | 0 | { |
569 | 0 | return v6addr; |
570 | 0 | } |
571 | | |
572 | 0 | return compressV6(v6addr); |
573 | 0 | } |
574 | | |
575 | | |
576 | | IPAddress IPAddress::parse(const std::string& addr) |
577 | 0 | { |
578 | 0 | return IPAddress(addr); |
579 | 0 | } |
580 | | |
581 | | |
582 | | bool IPAddress::tryParse(const std::string& addr, IPAddress& result) |
583 | 0 | { |
584 | 0 | IPv4AddressImpl impl4(IPv4AddressImpl::parse(addr)); |
585 | 0 | if (impl4 != IPv4AddressImpl() || trim(addr) == "0.0.0.0") |
586 | 0 | { |
587 | 0 | result.newIPv4(impl4.addr()); |
588 | 0 | return true; |
589 | 0 | } |
590 | 0 | #if defined(POCO_HAVE_IPv6) |
591 | 0 | IPv6AddressImpl impl6(IPv6AddressImpl::parse(addr)); |
592 | 0 | if (impl6 != IPv6AddressImpl() || trimIPv6(addr) == "::") |
593 | 0 | { |
594 | 0 | result.newIPv6(impl6.addr(), impl6.scope()); |
595 | 0 | return true; |
596 | 0 | } |
597 | 0 | #endif |
598 | 0 | return false; |
599 | 0 | } |
600 | | |
601 | | |
602 | | void IPAddress::mask(const IPAddress& mask) |
603 | 0 | { |
604 | 0 | IPAddress null; |
605 | 0 | pImpl()->mask(mask.pImpl(), null.pImpl()); |
606 | 0 | } |
607 | | |
608 | | |
609 | | void IPAddress::mask(const IPAddress& mask, const IPAddress& set) |
610 | 0 | { |
611 | 0 | pImpl()->mask(mask.pImpl(), set.pImpl()); |
612 | 0 | } |
613 | | |
614 | | |
615 | | IPAddress IPAddress::wildcard(Family family) |
616 | 0 | { |
617 | 0 | return IPAddress(family); |
618 | 0 | } |
619 | | |
620 | | |
621 | | IPAddress IPAddress::broadcast() |
622 | 0 | { |
623 | 0 | struct in_addr ia; |
624 | 0 | ia.s_addr = INADDR_NONE; |
625 | 0 | return IPAddress(&ia, sizeof(ia)); |
626 | 0 | } |
627 | | |
628 | | |
629 | | IPAddress::RawIPv4 IPAddress::toV4Bytes() const |
630 | 0 | { |
631 | 0 | if (family() != IPv4) |
632 | 0 | throw Poco::InvalidAccessException(Poco::format("IPAddress::toV4Bytes(%d)", (int)family())); |
633 | | |
634 | 0 | RawIPv4 bytes; |
635 | 0 | std::memcpy(&bytes[0], addr(), IPv4Size); |
636 | 0 | return bytes; |
637 | 0 | } |
638 | | |
639 | | |
640 | | IPAddress::RawIPv6 IPAddress::toV6Bytes() const |
641 | 0 | { |
642 | 0 | if (family() != IPv6) |
643 | 0 | throw Poco::InvalidAccessException(Poco::format("IPAddress::toV6Bytes(%d)", (int)family())); |
644 | | |
645 | 0 | RawIPv6 bytes; |
646 | 0 | std::memcpy(&bytes[0], addr(), IPv6Size); |
647 | 0 | return bytes; |
648 | 0 | } |
649 | | |
650 | | |
651 | | std::vector<unsigned char> IPAddress::toBytes() const |
652 | 0 | { |
653 | 0 | std::size_t sz = 0; |
654 | 0 | std::vector<unsigned char> bytes; |
655 | 0 | const void* ptr = nullptr; |
656 | 0 | switch (family()) |
657 | 0 | { |
658 | 0 | case IPv4: |
659 | 0 | sz = sizeof(in_addr); |
660 | 0 | ptr = addr(); |
661 | 0 | break; |
662 | 0 | #if defined(POCO_HAVE_IPv6) |
663 | 0 | case IPv6: |
664 | 0 | sz = sizeof(in6_addr); |
665 | 0 | ptr = addr(); |
666 | 0 | break; |
667 | 0 | #endif |
668 | 0 | default: |
669 | 0 | throw Poco::IllegalStateException(Poco::format("IPAddress::toBytes(%d)", (int)family())); |
670 | 0 | } |
671 | 0 | bytes.resize(sz); |
672 | 0 | std::memcpy(&bytes[0], ptr, sz); |
673 | 0 | return bytes; |
674 | 0 | } |
675 | | |
676 | | |
677 | | Poco::BinaryWriter& operator << (Poco::BinaryWriter& writer, const Poco::Net::IPAddress& value) |
678 | 0 | { |
679 | 0 | writer << static_cast<Poco::UInt8>(value.length()); |
680 | 0 | writer.writeRaw(reinterpret_cast<const char*>(value.addr()), value.length()); |
681 | 0 | return writer; |
682 | 0 | } |
683 | | |
684 | | |
685 | | Poco::BinaryReader& operator >> (Poco::BinaryReader& reader, Poco::Net::IPAddress& value) |
686 | 0 | { |
687 | 0 | char buf[Poco::Net::IPAddress::MAX_ADDRESS_LENGTH]; |
688 | 0 | Poco::UInt8 length; |
689 | 0 | reader >> length; |
690 | 0 | reader.readRaw(buf, length); |
691 | 0 | value = Poco::Net::IPAddress(buf, length); |
692 | 0 | return reader; |
693 | 0 | } |
694 | | |
695 | | |
696 | | std::ostream& operator << (std::ostream& ostr, const Poco::Net::IPAddress& addr) |
697 | 0 | { |
698 | 0 | ostr << addr.toString(); |
699 | 0 | return ostr; |
700 | 0 | } |
701 | | |
702 | | |
703 | | } } // namespace Poco::Net |
704 | | |