diff --git a/Net/Net_vs100.vcxproj b/Net/Net_vs100.vcxproj
index 190f81346..781dc997c 100644
--- a/Net/Net_vs100.vcxproj
+++ b/Net/Net_vs100.vcxproj
@@ -270,6 +270,7 @@
+
@@ -369,6 +370,7 @@
+
diff --git a/Net/Net_vs100.vcxproj.filters b/Net/Net_vs100.vcxproj.filters
index 3cbe0c129..5b0a5cf62 100644
--- a/Net/Net_vs100.vcxproj.filters
+++ b/Net/Net_vs100.vcxproj.filters
@@ -420,6 +420,9 @@
Reactor\Header Files
+
+ NetCore\Header Files
+
@@ -695,6 +698,9 @@
NetCore\Source Files
+
+ NetCore\Source Files
+
diff --git a/Net/include/Poco/Net/IPAddress.h b/Net/include/Poco/Net/IPAddress.h
index 2a3c2ecc0..1843354a9 100644
--- a/Net/include/Poco/Net/IPAddress.h
+++ b/Net/include/Poco/Net/IPAddress.h
@@ -42,6 +42,7 @@
#include "Poco/Net/Net.h"
#include "Poco/Net/SocketDefs.h"
+#include "Poco/Net/IPAddressImpl.h"
#include
@@ -53,9 +54,6 @@ class BinaryWriter;
namespace Net {
-class IPAddressImpl;
-
-
class Net_API IPAddress
/// This class represents an internet (IP) host
/// address. The address can belong either to the
@@ -80,9 +78,9 @@ public:
enum Family
/// Possible address families for IP addresses.
{
- IPv4
+ IPv4 = Poco::Net::Impl::IPAddressImpl::IPv4
#ifdef POCO_HAVE_IPv6
- ,IPv6
+ ,IPv6 = Poco::Net::Impl::IPAddressImpl::IPv6
#endif
};
@@ -143,7 +141,7 @@ public:
IPAddress& operator = (const IPAddress& addr);
/// Assigns an IPAddress.
- void swap(IPAddress& address);
+ //void swap(IPAddress& address);
/// Swaps the IPAddress with another one.
Family family() const;
@@ -387,26 +385,26 @@ public:
/// Maximum length in bytes of a socket address.
};
-protected:
- void init(IPAddressImpl* pImpl);
-
private:
- IPAddressImpl* _pImpl;
+ typedef Poco::Net::Impl::IPAddressImpl Impl;
+ typedef Impl* Ptr;
+
+ Ptr pImpl() const;
+
+ char _memory[sizeof(Poco::Net::Impl::IPv6AddressImpl)];
};
-//
-// inlines
-//
-inline void swap(IPAddress& addr1, IPAddress& addr2)
+inline IPAddress::Ptr IPAddress::pImpl() const
{
- addr1.swap(addr2);
+ return reinterpret_cast(const_cast(_memory));
}
BinaryWriter& operator << (BinaryWriter& writer, const IPAddress& value);
BinaryReader& operator >> (BinaryReader& reader, IPAddress& value);
+
} } // namespace Poco::Net
diff --git a/Net/include/Poco/Net/IPAddressImpl.h b/Net/include/Poco/Net/IPAddressImpl.h
new file mode 100644
index 000000000..b1808e50d
--- /dev/null
+++ b/Net/include/Poco/Net/IPAddressImpl.h
@@ -0,0 +1,201 @@
+//
+// IPAddressImpl.h
+//
+// $Id: //poco/1.4/Net/include/Poco/Net/IPAddressImpl.h#2 $
+//
+// Library: Net
+// Package: NetCore
+// Module: IPAddressImpl
+//
+// Definition of the IPAddressImpl class.
+//
+// Copyright (c) 2005-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#ifndef Net_IPAddressImpl_INCLUDED
+#define Net_IPAddressImpl_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/SocketDefs.h"
+#include
+
+
+namespace Poco {
+namespace Net {
+namespace Impl {
+
+
+class IPAddressImpl
+{
+public:
+ enum Family
+ /// Possible address families for IP addresses.
+ {
+ IPv4
+#ifdef POCO_HAVE_IPv6
+ ,IPv6
+#endif
+ };
+
+ virtual std::string toString() const = 0;
+ virtual poco_socklen_t length() const = 0;
+ virtual const void* addr() const = 0;
+ virtual Family family() const = 0;
+ virtual int af() const = 0;
+ virtual Poco::UInt32 scope() const = 0;
+ virtual bool isWildcard() const = 0;
+ virtual bool isBroadcast() const = 0;
+ virtual bool isLoopback() const = 0;
+ virtual bool isMulticast() const = 0;
+ virtual bool isLinkLocal() const = 0;
+ virtual bool isSiteLocal() const = 0;
+ virtual bool isIPv4Mapped() const = 0;
+ virtual bool isIPv4Compatible() const = 0;
+ virtual bool isWellKnownMC() const = 0;
+ virtual bool isNodeLocalMC() const = 0;
+ virtual bool isLinkLocalMC() const = 0;
+ virtual bool isSiteLocalMC() const = 0;
+ virtual bool isOrgLocalMC() const = 0;
+ virtual bool isGlobalMC() const = 0;
+ virtual void mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet) = 0;
+ virtual unsigned prefixLength() const = 0;
+
+ virtual IPAddressImpl* clone() const = 0;
+
+protected:
+ IPAddressImpl();
+ virtual ~IPAddressImpl();
+
+private:
+ IPAddressImpl(const IPAddressImpl&);
+ IPAddressImpl& operator = (const IPAddressImpl&);
+};
+
+
+//
+// IPv4AddressImpl
+//
+
+class IPv4AddressImpl: public IPAddressImpl
+{
+public:
+ IPv4AddressImpl();
+ IPv4AddressImpl(const void* addr);
+ IPv4AddressImpl(unsigned prefix);
+ IPv4AddressImpl(const IPv4AddressImpl& addr);
+ IPv4AddressImpl& operator = (const IPv4AddressImpl&);
+ std::string toString() const;
+ poco_socklen_t length() const;
+ const void* addr() const;
+ Family family() const;
+ int af() const;
+ unsigned prefixLength() const;
+ Poco::UInt32 scope() const;
+ bool isWildcard() const;
+ bool isBroadcast() const;
+ bool isLoopback() const;
+ bool isMulticast() const;
+ bool isLinkLocal() const;
+ bool isSiteLocal() const;
+ bool isIPv4Compatible() const;
+ bool isIPv4Mapped() const;
+ bool isWellKnownMC() const;
+ bool isNodeLocalMC() const;
+ bool isLinkLocalMC() const;
+ bool isSiteLocalMC() const;
+ bool isOrgLocalMC() const;
+ bool isGlobalMC() const;
+ static IPv4AddressImpl parse(const std::string& addr);
+ void mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet);
+ IPAddressImpl* clone() const;
+ IPv4AddressImpl operator & (const IPv4AddressImpl& addr) const;
+ IPv4AddressImpl operator | (const IPv4AddressImpl& addr) const;
+ IPv4AddressImpl operator ^ (const IPv4AddressImpl& addr) const;
+ IPv4AddressImpl operator ~ () const;
+ bool operator == (const IPv4AddressImpl& addr) const;
+ bool operator != (const IPv4AddressImpl& addr) const;
+
+private:
+ struct in_addr _addr;
+};
+
+
+//
+// IPv6AddressImpl
+//
+
+class IPv6AddressImpl: public IPAddressImpl
+{
+public:
+ IPv6AddressImpl();
+ IPv6AddressImpl(const void* addr);
+ IPv6AddressImpl(const void* addr, Poco::UInt32 scope);
+ IPv6AddressImpl(unsigned prefix);
+ std::string toString() const;
+ poco_socklen_t length() const;
+ const void* addr() const;
+ Family family() const;
+ int af() const;
+ unsigned prefixLength() const;
+ Poco::UInt32 scope() const;
+ bool isWildcard() const;
+ bool isBroadcast() const;
+ bool isLoopback() const;
+ bool isMulticast() const;
+ bool isLinkLocal() const;
+ bool isSiteLocal() const;
+ bool isIPv4Compatible() const;
+ bool isIPv4Mapped() const;
+ bool isWellKnownMC() const;
+ bool isNodeLocalMC() const;
+ bool isLinkLocalMC() const;
+ bool isSiteLocalMC() const;
+ bool isOrgLocalMC() const;
+ bool isGlobalMC() const;
+ static IPv6AddressImpl parse(const std::string& addr);
+ void mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet);
+ IPAddressImpl* clone() const;
+ IPv6AddressImpl operator & (const IPv6AddressImpl& addr) const;
+ IPv6AddressImpl operator | (const IPv6AddressImpl& addr) const;
+ IPv6AddressImpl operator ^ (const IPv6AddressImpl& addr) const;
+ IPv6AddressImpl operator ~ () const;
+ bool operator == (const IPv6AddressImpl& addr) const;
+ bool operator != (const IPv6AddressImpl& addr) const;
+ IPv6AddressImpl(const IPv6AddressImpl& addr);
+ IPv6AddressImpl& operator = (const IPv6AddressImpl&);
+
+private:
+ struct in6_addr _addr;
+ unsigned int _scope;
+};
+
+
+} } } // namespace Poco::Net::Impl
+
+
+#endif // Net_IPAddressImpl_INCLUDED
diff --git a/Net/src/IPAddress.cpp b/Net/src/IPAddress.cpp
index f598a1afc..13bce33c1 100644
--- a/Net/src/IPAddress.cpp
+++ b/Net/src/IPAddress.cpp
@@ -49,726 +49,41 @@ using Poco::NumberFormatter;
using Poco::BinaryReader;
using Poco::BinaryWriter;
using Poco::toLower;
+using Poco::trim;
using Poco::UInt8;
using Poco::UInt16;
using Poco::UInt32;
-
-
-namespace {
-
-template
-unsigned maskBits(T val, unsigned size)
- /// Returns the length of the mask (number of bits set in val).
- /// The val should be either all zeros or two contiguos areas of 1s and 0s.
- /// The algorithm ignores invalid non-contiguous series of 1s and treats val
- /// as if all bits between MSb and last non-zero bit are set to 1.
-{
- unsigned count = 0;
- if (val)
- {
- val = (val ^ (val - 1)) >> 1;
- for (count = 0; val; ++count) val >>= 1;
- }
- else count = size;
- return size - count;
-}
-
-} // namespace
+using Poco::Net::Impl::IPAddressImpl;
+using Poco::Net::Impl::IPv4AddressImpl;
+using Poco::Net::Impl::IPv6AddressImpl;
namespace Poco {
namespace Net {
-//
-// IPAddressImpl
-//
-
-
-class IPAddressImpl: public RefCountedObject
-{
-public:
- virtual std::string toString() const = 0;
- virtual poco_socklen_t length() const = 0;
- virtual const void* addr() const = 0;
- virtual IPAddress::Family family() const = 0;
- virtual int af() const = 0;
- virtual Poco::UInt32 scope() const = 0;
- virtual bool isWildcard() const = 0;
- virtual bool isBroadcast() const = 0;
- virtual bool isLoopback() const = 0;
- virtual bool isMulticast() const = 0;
- virtual bool isLinkLocal() const = 0;
- virtual bool isSiteLocal() const = 0;
- virtual bool isIPv4Mapped() const = 0;
- virtual bool isIPv4Compatible() const = 0;
- virtual bool isWellKnownMC() const = 0;
- virtual bool isNodeLocalMC() const = 0;
- virtual bool isLinkLocalMC() const = 0;
- virtual bool isSiteLocalMC() const = 0;
- virtual bool isOrgLocalMC() const = 0;
- virtual bool isGlobalMC() const = 0;
- virtual void mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet) = 0;
- virtual unsigned prefixLength() const = 0;
-
- virtual IPAddressImpl* clone() const = 0;
-
-protected:
- IPAddressImpl()
- {
- }
-
- virtual ~IPAddressImpl()
- {
- }
-
-private:
- IPAddressImpl(const IPAddressImpl&);
- IPAddressImpl& operator = (const IPAddressImpl&);
-};
-
-
-class IPv4AddressImpl: public IPAddressImpl
-{
-public:
- IPv4AddressImpl()
- {
- std::memset(&_addr, 0, sizeof(_addr));
- }
-
- IPv4AddressImpl(const void* addr)
- {
- std::memcpy(&_addr, addr, sizeof(_addr));
- }
-
- IPv4AddressImpl(unsigned prefix)
- {
- UInt32 addr = (prefix == 32) ? 0xffffffff : ~(0xffffffff >> prefix);
- _addr.s_addr = htonl(addr);
- }
-
- std::string toString() const
- {
- const UInt8* bytes = reinterpret_cast(&_addr);
- std::string result;
- result.reserve(16);
- NumberFormatter::append(result, bytes[0]);
- result.append(".");
- NumberFormatter::append(result, bytes[1]);
- result.append(".");
- NumberFormatter::append(result, bytes[2]);
- result.append(".");
- NumberFormatter::append(result, bytes[3]);
- return result;
- }
-
- poco_socklen_t length() const
- {
- return sizeof(_addr);
- }
-
- const void* addr() const
- {
- return &_addr;
- }
-
- IPAddress::Family family() const
- {
- return IPAddress::IPv4;
- }
-
- int af() const
- {
- return AF_INET;
- }
-
- unsigned prefixLength() const
- {
- return maskBits(ntohl(_addr.s_addr), 32);
- }
-
- Poco::UInt32 scope() const
- {
- return 0;
- }
-
- bool isWildcard() const
- {
- return _addr.s_addr == INADDR_ANY;
- }
-
- bool isBroadcast() const
- {
- return _addr.s_addr == INADDR_NONE;
- }
-
- bool isLoopback() const
- {
- return (ntohl(_addr.s_addr) & 0xFF000000) == 0x7F000000; // 127.0.0.1 to 127.255.255.255
- }
-
- bool isMulticast() const
- {
- return (ntohl(_addr.s_addr) & 0xF0000000) == 0xE0000000; // 224.0.0.0/24 to 239.0.0.0/24
- }
-
- bool isLinkLocal() const
- {
- return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xA9FE0000; // 169.254.0.0/16
- }
-
- bool isSiteLocal() const
- {
- UInt32 addr = ntohl(_addr.s_addr);
- return (addr & 0xFF000000) == 0x0A000000 || // 10.0.0.0/24
- (addr & 0xFFFF0000) == 0xC0A80000 || // 192.68.0.0/16
- (addr >= 0xAC100000 && addr <= 0xAC1FFFFF); // 172.16.0.0 to 172.31.255.255
- }
-
- bool isIPv4Compatible() const
- {
- return true;
- }
-
- bool isIPv4Mapped() const
- {
- return true;
- }
-
- bool isWellKnownMC() const
- {
- return (ntohl(_addr.s_addr) & 0xFFFFFF00) == 0xE0000000; // 224.0.0.0/8
- }
-
- bool isNodeLocalMC() const
- {
- return false;
- }
-
- bool isLinkLocalMC() const
- {
- return (ntohl(_addr.s_addr) & 0xFF000000) == 0xE0000000; // 244.0.0.0/24
- }
-
- bool isSiteLocalMC() const
- {
- return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xEFFF0000; // 239.255.0.0/16
- }
-
- bool isOrgLocalMC() const
- {
- return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xEFC00000; // 239.192.0.0/16
- }
-
- bool isGlobalMC() const
- {
- UInt32 addr = ntohl(_addr.s_addr);
- return addr >= 0xE0000100 && addr <= 0xEE000000; // 224.0.1.0 to 238.255.255.255
- }
-
- static IPv4AddressImpl* parse(const std::string& addr)
- {
- if (addr.empty()) return 0;
-#if defined(_WIN32)
- struct in_addr ia;
- ia.s_addr = inet_addr(addr.c_str());
- if (ia.s_addr == INADDR_NONE && addr != "255.255.255.255")
- return 0;
- else
- return new IPv4AddressImpl(&ia);
-#else
-#if __GNUC__ < 3 || defined(POCO_VXWORKS)
- struct in_addr ia;
- ia.s_addr = inet_addr(const_cast(addr.c_str()));
- if (ia.s_addr == INADDR_NONE && addr != "255.255.255.255")
- return 0;
- else
- return new IPv4AddressImpl(&ia);
-#else
- struct in_addr ia;
- if (inet_aton(addr.c_str(), &ia))
- return new IPv4AddressImpl(&ia);
- else
- return 0;
-#endif
-#endif
- }
-
- void mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet)
- {
- poco_assert (pMask->af() == AF_INET && pSet->af() == AF_INET);
-
- _addr.s_addr &= static_cast(pMask)->_addr.s_addr;
- _addr.s_addr |= static_cast(pSet)->_addr.s_addr & ~static_cast(pMask)->_addr.s_addr;
- }
-
- IPAddressImpl* clone() const
- {
- return new IPv4AddressImpl(&_addr);
- }
-
- IPv4AddressImpl operator & (const IPv4AddressImpl& addr) const
- {
- IPv4AddressImpl result(&_addr);
- result._addr.s_addr &= addr._addr.s_addr;
- return result;
- }
-
- IPv4AddressImpl operator | (const IPv4AddressImpl& addr) const
- {
- IPv4AddressImpl result(&_addr);
- result._addr.s_addr |= addr._addr.s_addr;
- return result;
- }
-
- IPv4AddressImpl operator ^ (const IPv4AddressImpl& addr) const
- {
- IPv4AddressImpl result(&_addr);
- result._addr.s_addr ^= addr._addr.s_addr;
- return result;
- }
-
- IPv4AddressImpl operator ~ () const
- {
- IPv4AddressImpl result(&_addr);
- result._addr.s_addr ^= 0xffffffff;
- return result;
- }
-
-private:
- IPv4AddressImpl(const IPv4AddressImpl& addr)
- {
- std::memcpy(&_addr, &addr._addr, sizeof(_addr));
- }
-
- IPv4AddressImpl& operator = (const IPv4AddressImpl&);
-
- struct in_addr _addr;
-};
-
-
-#if defined(POCO_HAVE_IPv6)
-
-
-class IPv6AddressImpl: public IPAddressImpl
-{
-public:
- IPv6AddressImpl():
- _scope(0)
- {
- std::memset(&_addr, 0, sizeof(_addr));
- }
-
- IPv6AddressImpl(const void* addr):
- _scope(0)
- {
- std::memcpy(&_addr, addr, sizeof(_addr));
- }
-
- IPv6AddressImpl(const void* addr, Poco::UInt32 scope):
- _scope(scope)
- {
- std::memcpy(&_addr, addr, sizeof(_addr));
- }
-
-
- IPv6AddressImpl(unsigned prefix):
- _scope(0)
- {
- unsigned i = 0;
-#ifdef POCO_OS_FAMILY_WINDOWS
- for (; prefix >= 16; ++i, prefix -= 16) {
- _addr.s6_addr16[i] = 0xffff;
- }
- if (prefix > 0)
- _addr.s6_addr16[i++] = htons(~(0xffff >> prefix));
- while (i < 8)
- _addr.s6_addr16[i++] = 0;
-#else
- for (; prefix >= 32; ++i, prefix -= 32) {
- _addr.s6_addr32[i] = 0xffffffff;
- }
- if (prefix > 0)
- _addr.s6_addr32[i++] = htonl(~(0xffffffffU >> prefix));
- while (i < 4)
- _addr.s6_addr32[i++] = 0;
-#endif
- }
-
- std::string toString() const
- {
- const UInt16* words = reinterpret_cast(&_addr);
- if (isIPv4Compatible() || isIPv4Mapped())
- {
- std::string result;
- result.reserve(24);
- if (words[5] == 0)
- result.append("::");
- else
- result.append("::ffff:");
- const UInt8* bytes = reinterpret_cast(&_addr);
- NumberFormatter::append(result, bytes[12]);
- result.append(".");
- NumberFormatter::append(result, bytes[13]);
- result.append(".");
- NumberFormatter::append(result, bytes[14]);
- result.append(".");
- NumberFormatter::append(result, bytes[15]);
- return result;
- }
- else
- {
- std::string result;
- result.reserve(64);
- bool zeroSequence = false;
- int i = 0;
- while (i < 8)
- {
- if (!zeroSequence && words[i] == 0)
- {
- int zi = i;
- while (zi < 8 && words[zi] == 0) ++zi;
- if (zi > i + 1)
- {
- i = zi;
- result.append(":");
- zeroSequence = true;
- }
- }
- if (i > 0) result.append(":");
- if (i < 8) NumberFormatter::appendHex(result, ntohs(words[i++]));
- }
- if (_scope > 0)
- {
- result.append("%");
-#if defined(_WIN32)
- NumberFormatter::append(result, _scope);
-#else
- char buffer[IFNAMSIZ];
- if (if_indextoname(_scope, buffer))
- {
- result.append(buffer);
- }
- else
- {
- NumberFormatter::append(result, _scope);
- }
-#endif
- }
- return toLower(result);
- }
- }
-
- poco_socklen_t length() const
- {
- return sizeof(_addr);
- }
-
- const void* addr() const
- {
- return &_addr;
- }
-
- IPAddress::Family family() const
- {
- return IPAddress::IPv6;
- }
-
- int af() const
- {
- return AF_INET6;
- }
-
- unsigned prefixLength() const
- {
- unsigned bits = 0;
- unsigned bitPos = 128;
-#if defined(POCO_OS_FAMILY_UNIX)
- for (int i = 3; i >= 0; --i)
- {
- unsigned addr = ntohl(_addr.s6_addr32[i]);
- if ((bits = maskBits(addr, 32))) return (bitPos - (32 - bits));
- bitPos -= 32;
- }
- return 0;
-#elif defined(POCO_OS_FAMILY_WINDOWS)
- for (int i = 7; i >= 0; --i)
- {
- unsigned short addr = ntohs(_addr.s6_addr16[i]);
- if ((bits = maskBits(addr, 16))) return (bitPos - (16 - bits));
- bitPos -= 16;
- }
- return 0;
-#else
-#warning prefixLength() not implemented
- throw NotImplementedException("prefixLength() not implemented");
-#endif
- }
- Poco::UInt32 scope() const
- {
- return _scope;
- }
-
- bool isWildcard() const
- {
- const UInt16* words = reinterpret_cast(&_addr);
- return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 &&
- words[4] == 0 && words[5] == 0 && words[6] == 0 && words[7] == 0;
- }
-
- bool isBroadcast() const
- {
- return false;
- }
-
- bool isLoopback() const
- {
- const UInt16* words = reinterpret_cast(&_addr);
- return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 &&
- words[4] == 0 && words[5] == 0 && words[6] == 0 && ntohs(words[7]) == 0x0001;
- }
-
- bool isMulticast() const
- {
- const UInt16* words = reinterpret_cast(&_addr);
- return (ntohs(words[0]) & 0xFFE0) == 0xFF00;
- }
-
- bool isLinkLocal() const
- {
- const UInt16* words = reinterpret_cast(&_addr);
- return (ntohs(words[0]) & 0xFFE0) == 0xFE80;
- }
-
- bool isSiteLocal() const
- {
- const UInt16* words = reinterpret_cast(&_addr);
- return ((ntohs(words[0]) & 0xFFE0) == 0xFEC0) || ((ntohs(words[0]) & 0xFF00) == 0xFC00);
- }
-
- bool isIPv4Compatible() const
- {
- const UInt16* words = reinterpret_cast(&_addr);
- return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && words[4] == 0 && words[5] == 0;
- }
-
- bool isIPv4Mapped() const
- {
- const UInt16* words = reinterpret_cast(&_addr);
- return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && words[4] == 0 && ntohs(words[5]) == 0xFFFF;
- }
-
- bool isWellKnownMC() const
- {
- const UInt16* words = reinterpret_cast(&_addr);
- return (ntohs(words[0]) & 0xFFF0) == 0xFF00;
- }
-
- bool isNodeLocalMC() const
- {
- const UInt16* words = reinterpret_cast(&_addr);
- return (ntohs(words[0]) & 0xFFEF) == 0xFF01;
- }
-
- bool isLinkLocalMC() const
- {
- const UInt16* words = reinterpret_cast(&_addr);
- return (ntohs(words[0]) & 0xFFEF) == 0xFF02;
- }
-
- bool isSiteLocalMC() const
- {
- const UInt16* words = reinterpret_cast(&_addr);
- return (ntohs(words[0]) & 0xFFEF) == 0xFF05;
- }
-
- bool isOrgLocalMC() const
- {
- const UInt16* words = reinterpret_cast(&_addr);
- return (ntohs(words[0]) & 0xFFEF) == 0xFF08;
- }
-
- bool isGlobalMC() const
- {
- const UInt16* words = reinterpret_cast(&_addr);
- return (ntohs(words[0]) & 0xFFEF) == 0xFF0F;
- }
-
- static IPv6AddressImpl* parse(const std::string& addr)
- {
- if (addr.empty()) return 0;
-#if defined(_WIN32)
- struct addrinfo* pAI;
- struct addrinfo hints;
- std::memset(&hints, 0, sizeof(hints));
- hints.ai_flags = AI_NUMERICHOST;
- int rc = getaddrinfo(addr.c_str(), NULL, &hints, &pAI);
- if (rc == 0)
- {
- IPv6AddressImpl* pResult = new IPv6AddressImpl(&reinterpret_cast(pAI->ai_addr)->sin6_addr, static_cast(reinterpret_cast(pAI->ai_addr)->sin6_scope_id));
- freeaddrinfo(pAI);
- return pResult;
- }
- else return 0;
-#else
- struct in6_addr ia;
- std::string::size_type pos = addr.find('%');
- if (std::string::npos != pos)
- {
- std::string::size_type start = ('[' == addr[0]) ? 1 : 0;
- std::string unscopedAddr(addr, start, pos - start);
- std::string scope(addr, pos + 1, addr.size() - start - pos);
- Poco::UInt32 scopeId(0);
- if (!(scopeId = if_nametoindex(scope.c_str())))
- return 0;
- if (inet_pton(AF_INET6, unscopedAddr.c_str(), &ia) == 1)
- return new IPv6AddressImpl(&ia, scopeId);
- else
- return 0;
- }
- else
- {
- if (inet_pton(AF_INET6, addr.c_str(), &ia) == 1)
- return new IPv6AddressImpl(&ia);
- else
- return 0;
- }
-#endif
- }
-
- void mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet)
- {
- throw Poco::NotImplementedException("mask() is only supported for IPv4 addresses");
- }
-
- IPAddressImpl* clone() const
- {
- return new IPv6AddressImpl(&_addr, _scope);
- }
-
- IPv6AddressImpl operator & (const IPv6AddressImpl& addr) const
- {
- IPv6AddressImpl result(&_addr);
-#ifdef POCO_OS_FAMILY_WINDOWS
- result._addr.s6_addr16[0] &= addr._addr.s6_addr16[0];
- result._addr.s6_addr16[1] &= addr._addr.s6_addr16[1];
- result._addr.s6_addr16[2] &= addr._addr.s6_addr16[2];
- result._addr.s6_addr16[3] &= addr._addr.s6_addr16[3];
- result._addr.s6_addr16[4] &= addr._addr.s6_addr16[4];
- result._addr.s6_addr16[5] &= addr._addr.s6_addr16[5];
- result._addr.s6_addr16[6] &= addr._addr.s6_addr16[6];
- result._addr.s6_addr16[7] &= addr._addr.s6_addr16[7];
-#else
- result._addr.s6_addr32[0] &= addr._addr.s6_addr32[0];
- result._addr.s6_addr32[1] &= addr._addr.s6_addr32[1];
- result._addr.s6_addr32[2] &= addr._addr.s6_addr32[2];
- result._addr.s6_addr32[3] &= addr._addr.s6_addr32[3];
-#endif
- return result;
- }
-
- IPv6AddressImpl operator | (const IPv6AddressImpl& addr) const
- {
- IPv6AddressImpl result(&_addr);
-#ifdef POCO_OS_FAMILY_WINDOWS
- result._addr.s6_addr16[0] |= addr._addr.s6_addr16[0];
- result._addr.s6_addr16[1] |= addr._addr.s6_addr16[1];
- result._addr.s6_addr16[2] |= addr._addr.s6_addr16[2];
- result._addr.s6_addr16[3] |= addr._addr.s6_addr16[3];
- result._addr.s6_addr16[4] |= addr._addr.s6_addr16[4];
- result._addr.s6_addr16[5] |= addr._addr.s6_addr16[5];
- result._addr.s6_addr16[6] |= addr._addr.s6_addr16[6];
- result._addr.s6_addr16[7] |= addr._addr.s6_addr16[7];
-#else
- result._addr.s6_addr32[0] |= addr._addr.s6_addr32[0];
- result._addr.s6_addr32[1] |= addr._addr.s6_addr32[1];
- result._addr.s6_addr32[2] |= addr._addr.s6_addr32[2];
- result._addr.s6_addr32[3] |= addr._addr.s6_addr32[3];
-#endif
- return result;
- }
-
- IPv6AddressImpl operator ^ (const IPv6AddressImpl& addr) const
- {
- IPv6AddressImpl result(&_addr);
-#ifdef POCO_OS_FAMILY_WINDOWS
- result._addr.s6_addr16[0] ^= addr._addr.s6_addr16[0];
- result._addr.s6_addr16[1] ^= addr._addr.s6_addr16[1];
- result._addr.s6_addr16[2] ^= addr._addr.s6_addr16[2];
- result._addr.s6_addr16[3] ^= addr._addr.s6_addr16[3];
- result._addr.s6_addr16[4] ^= addr._addr.s6_addr16[4];
- result._addr.s6_addr16[5] ^= addr._addr.s6_addr16[5];
- result._addr.s6_addr16[6] ^= addr._addr.s6_addr16[6];
- result._addr.s6_addr16[7] ^= addr._addr.s6_addr16[7];
-#else
- result._addr.s6_addr32[0] ^= addr._addr.s6_addr32[0];
- result._addr.s6_addr32[1] ^= addr._addr.s6_addr32[1];
- result._addr.s6_addr32[2] ^= addr._addr.s6_addr32[2];
- result._addr.s6_addr32[3] ^= addr._addr.s6_addr32[3];
-#endif
- return result;
- }
-
- IPv6AddressImpl operator ~ () const
- {
- IPv6AddressImpl result(&_addr);
-#ifdef POCO_OS_FAMILY_WINDOWS
- result._addr.s6_addr16[0] ^= 0xffff;
- result._addr.s6_addr16[1] ^= 0xffff;
- result._addr.s6_addr16[2] ^= 0xffff;
- result._addr.s6_addr16[3] ^= 0xffff;
- result._addr.s6_addr16[4] ^= 0xffff;
- result._addr.s6_addr16[5] ^= 0xffff;
- result._addr.s6_addr16[6] ^= 0xffff;
- result._addr.s6_addr16[7] ^= 0xffff;
-#else
- result._addr.s6_addr32[0] ^= 0xffffffff;
- result._addr.s6_addr32[1] ^= 0xffffffff;
- result._addr.s6_addr32[2] ^= 0xffffffff;
- result._addr.s6_addr32[3] ^= 0xffffffff;
-#endif
- return result;
- }
-
-private:
- IPv6AddressImpl(const IPv6AddressImpl& addr): _scope(0)
- {
- std::memcpy((void*) &_addr, (void*) &addr._addr, sizeof(_addr));
- }
-
- IPv6AddressImpl& operator = (const IPv6AddressImpl&);
-
- struct in6_addr _addr;
- Poco::UInt32 _scope;
-};
-
-
-#endif // POCO_HAVE_IPv6
-
-
-//
-// IPAddress
-//
-
-
-IPAddress::IPAddress(): _pImpl(new IPv4AddressImpl)
+IPAddress::IPAddress()
{
+ new ((void*) _memory) IPv4AddressImpl();
}
-IPAddress::IPAddress(const IPAddress& addr): _pImpl(addr._pImpl)
+IPAddress::IPAddress(const IPAddress& addr)
{
- _pImpl->duplicate();
+ if (addr.family() == IPv4)
+ std::memcpy(pImpl(), addr.pImpl(), sizeof (IPv4AddressImpl));
+ else
+ std::memcpy(pImpl(), addr.pImpl(), sizeof (IPv6AddressImpl));
}
-IPAddress::IPAddress(Family family): _pImpl(0)
+IPAddress::IPAddress(Family family)
{
if (family == IPv4)
- _pImpl = new IPv4AddressImpl();
+ new ((void*) _memory) IPv4AddressImpl();
#if defined(POCO_HAVE_IPv6)
else if (family == IPv6)
- _pImpl = new IPv6AddressImpl();
+ new ((void*) _memory) IPv6AddressImpl();
#endif
else
throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()");
@@ -777,35 +92,67 @@ IPAddress::IPAddress(Family family): _pImpl(0)
IPAddress::IPAddress(const std::string& addr)
{
- _pImpl = IPv4AddressImpl::parse(addr);
+ IPv4AddressImpl empty4 = IPv4AddressImpl();
+ if (addr.empty() || trim(addr) == "0.0.0.0")
+ {
+ std::memcpy(pImpl(), &empty4, sizeof(empty4));
+ return;
+ }
+
+ IPv4AddressImpl addr4(IPv4AddressImpl::parse(addr));
+ if (addr4 != empty4)
+ {
+ std::memcpy(pImpl(), &addr4, sizeof(addr4));
+ return;
+ }
+
#if defined(POCO_HAVE_IPv6)
- if (!_pImpl)
- _pImpl = IPv6AddressImpl::parse(addr);
+ IPv6AddressImpl empty6 = IPv6AddressImpl();
+ if (addr.empty() || trim(addr) == "::")
+ {
+ std::memcpy(pImpl(), &empty6, sizeof(empty6));
+ return;
+ }
+
+ IPv6AddressImpl addr6(IPv6AddressImpl::parse(addr));
+ if (addr6 != IPv6AddressImpl())
+ {
+ std::memcpy(pImpl(), &addr6, sizeof(addr6));
+ return;
+ }
#endif
- if (!_pImpl) throw InvalidAddressException(addr);
+
+ throw InvalidAddressException(addr);
}
-IPAddress::IPAddress(const std::string& addr, Family family): _pImpl(0)
+IPAddress::IPAddress(const std::string& addr, Family family)
{
if (family == IPv4)
- _pImpl = IPv4AddressImpl::parse(addr);
+ {
+ IPv4AddressImpl addr4(IPv4AddressImpl::parse(addr));
+ std::memcpy(pImpl(), &addr4, sizeof(addr4));
+ return;
+ }
#if defined(POCO_HAVE_IPv6)
else if (family == IPv6)
- _pImpl = IPv6AddressImpl::parse(addr);
+ {
+ IPv6AddressImpl addr6(IPv6AddressImpl::parse(addr));
+ std::memcpy(pImpl(), &addr6, sizeof(addr6));
+ return;
+ }
#endif
else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()");
- if (!_pImpl) throw InvalidAddressException(addr);
}
IPAddress::IPAddress(const void* addr, poco_socklen_t length)
{
if (length == sizeof(struct in_addr))
- _pImpl = new IPv4AddressImpl(addr);
+ new ((void*) _memory) IPv4AddressImpl(addr);
#if defined(POCO_HAVE_IPv6)
else if (length == sizeof(struct in6_addr))
- _pImpl = new IPv6AddressImpl(addr);
+ new ((void*) _memory) IPv6AddressImpl(addr);
#endif
else throw Poco::InvalidArgumentException("Invalid address length passed to IPAddress()");
}
@@ -814,34 +161,31 @@ IPAddress::IPAddress(const void* addr, poco_socklen_t length)
IPAddress::IPAddress(const void* addr, poco_socklen_t length, Poco::UInt32 scope)
{
if (length == sizeof(struct in_addr))
- _pImpl = new IPv4AddressImpl(addr);
+ new ((void*) _memory) IPv4AddressImpl(addr);
#if defined(POCO_HAVE_IPv6)
else if (length == sizeof(struct in6_addr))
- _pImpl = new IPv6AddressImpl(addr, scope);
+ new ((void*) _memory) IPv6AddressImpl(addr, scope);
#endif
else throw Poco::InvalidArgumentException("Invalid address length passed to IPAddress()");
}
-IPAddress::IPAddress(unsigned prefix, Family family): _pImpl(0)
+IPAddress::IPAddress(unsigned prefix, Family family)
{
if (family == IPv4)
{
- if (prefix <= 32) {
- _pImpl = new IPv4AddressImpl(prefix);
- }
+ if (prefix <= 32)
+ new ((void*) _memory) IPv4AddressImpl(prefix);
}
#if defined(POCO_HAVE_IPv6)
else if (family == IPv6)
{
if (prefix <= 128)
- {
- _pImpl = new IPv6AddressImpl(prefix);
- }
+ new ((void*) _memory) IPv6AddressImpl(prefix);
}
#endif
else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()");
- if (!_pImpl) throw Poco::InvalidArgumentException("Invalid prefix length passed to IPAddress()");
+ if (!pImpl()) throw Poco::InvalidArgumentException("Invalid prefix length passed to IPAddress()");
}
@@ -850,10 +194,10 @@ IPAddress::IPAddress(const SOCKET_ADDRESS& socket_address)
{
ADDRESS_FAMILY family = socket_address.lpSockaddr->sa_family;
if (family == AF_INET)
- _pImpl = new IPv4AddressImpl(&reinterpret_cast(socket_address.lpSockaddr)->sin_addr);
+ new ((void*) _memory) IPv4AddressImpl(&reinterpret_cast(socket_address.lpSockaddr)->sin_addr);
#if defined(POCO_HAVE_IPv6)
else if (family == AF_INET6)
- _pImpl = new IPv6AddressImpl(&reinterpret_cast(socket_address.lpSockaddr)->sin6_addr, reinterpret_cast(socket_address.lpSockaddr)->sin6_scope_id);
+ new ((void*) _memory) IPv6AddressImpl(&reinterpret_cast(socket_address.lpSockaddr)->sin6_addr, reinterpret_cast(socket_address.lpSockaddr)->sin6_scope_id);
#endif
else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()");
}
@@ -864,10 +208,10 @@ IPAddress::IPAddress(const struct sockaddr& sockaddr)
{
unsigned short family = sockaddr.sa_family;
if (family == AF_INET)
- _pImpl = new IPv4AddressImpl(&reinterpret_cast(&sockaddr)->sin_addr);
+ new ((void*) _memory) IPv4AddressImpl(&reinterpret_cast(&sockaddr)->sin_addr);
#if defined(POCO_HAVE_IPv6)
else if (family == AF_INET6)
- _pImpl = new IPv6AddressImpl(&reinterpret_cast(&sockaddr)->sin6_addr, reinterpret_cast(&sockaddr)->sin6_scope_id);
+ new ((void*) _memory) IPv6AddressImpl(&reinterpret_cast(&sockaddr)->sin6_addr, reinterpret_cast(&sockaddr)->sin6_scope_id);
#endif
else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()");
}
@@ -875,7 +219,6 @@ IPAddress::IPAddress(const struct sockaddr& sockaddr)
IPAddress::~IPAddress()
{
- _pImpl->release();
}
@@ -883,58 +226,54 @@ IPAddress& IPAddress::operator = (const IPAddress& addr)
{
if (&addr != this)
{
- _pImpl->release();
- _pImpl = addr._pImpl;
- _pImpl->duplicate();
+ if (addr.family() == IPAddress::IPv4)
+ std::memcpy(pImpl(), addr.pImpl(), sizeof(IPv4AddressImpl));
+ else
+ std::memcpy(pImpl(), addr.pImpl(), sizeof(IPv6AddressImpl));
}
return *this;
}
-void IPAddress::swap(IPAddress& address)
-{
- std::swap(_pImpl, address._pImpl);
-}
-
-
IPAddress::Family IPAddress::family() const
{
- return _pImpl->family();
+ return static_cast(pImpl()->family());
}
Poco::UInt32 IPAddress::scope() const
{
- return _pImpl->scope();
+ return pImpl()->scope();
}
std::string IPAddress::toString() const
{
- return _pImpl->toString();
+ return pImpl()->toString();
}
bool IPAddress::isWildcard() const
{
- return _pImpl->isWildcard();
+ return pImpl()->isWildcard();
}
-
+
+
bool IPAddress::isBroadcast() const
{
- return _pImpl->isBroadcast();
+ return pImpl()->isBroadcast();
}
bool IPAddress::isLoopback() const
{
- return _pImpl->isLoopback();
+ return pImpl()->isLoopback();
}
bool IPAddress::isMulticast() const
{
- return _pImpl->isMulticast();
+ return pImpl()->isMulticast();
}
@@ -946,61 +285,61 @@ bool IPAddress::isUnicast() const
bool IPAddress::isLinkLocal() const
{
- return _pImpl->isLinkLocal();
+ return pImpl()->isLinkLocal();
}
bool IPAddress::isSiteLocal() const
{
- return _pImpl->isSiteLocal();
+ return pImpl()->isSiteLocal();
}
bool IPAddress::isIPv4Compatible() const
{
- return _pImpl->isIPv4Compatible();
+ return pImpl()->isIPv4Compatible();
}
bool IPAddress::isIPv4Mapped() const
{
- return _pImpl->isIPv4Mapped();
+ return pImpl()->isIPv4Mapped();
}
bool IPAddress::isWellKnownMC() const
{
- return _pImpl->isWellKnownMC();
+ return pImpl()->isWellKnownMC();
}
bool IPAddress::isNodeLocalMC() const
{
- return _pImpl->isNodeLocalMC();
+ return pImpl()->isNodeLocalMC();
}
bool IPAddress::isLinkLocalMC() const
{
- return _pImpl->isLinkLocalMC();
+ return pImpl()->isLinkLocalMC();
}
bool IPAddress::isSiteLocalMC() const
{
- return _pImpl->isSiteLocalMC();
+ return pImpl()->isSiteLocalMC();
}
bool IPAddress::isOrgLocalMC() const
{
- return _pImpl->isOrgLocalMC();
+ return pImpl()->isOrgLocalMC();
}
bool IPAddress::isGlobalMC() const
{
- return _pImpl->isGlobalMC();
+ return pImpl()->isGlobalMC();
}
@@ -1076,15 +415,15 @@ IPAddress IPAddress::operator & (const IPAddress& other) const
{
if (family() == IPv4)
{
- IPv4AddressImpl t(_pImpl->addr());
- IPv4AddressImpl o(other._pImpl->addr());
+ IPv4AddressImpl t(pImpl()->addr());
+ IPv4AddressImpl o(other.pImpl()->addr());
return IPAddress((t & o).addr(), sizeof(struct in_addr));
}
#if defined(POCO_HAVE_IPv6)
else if (family() == IPv6)
{
- IPv6AddressImpl t(_pImpl->addr());
- IPv6AddressImpl o(other._pImpl->addr());
+ IPv6AddressImpl t(pImpl()->addr());
+ IPv6AddressImpl o(other.pImpl()->addr());
return IPAddress((t & o).addr(), sizeof(struct in6_addr));
}
#endif
@@ -1102,15 +441,15 @@ IPAddress IPAddress::operator | (const IPAddress& other) const
{
if (family() == IPv4)
{
- IPv4AddressImpl t(_pImpl->addr());
- IPv4AddressImpl o(other._pImpl->addr());
+ IPv4AddressImpl t(pImpl()->addr());
+ IPv4AddressImpl o(other.pImpl()->addr());
return IPAddress((t | o).addr(), sizeof(struct in_addr));
}
#if defined(POCO_HAVE_IPv6)
else if (family() == IPv6)
{
- IPv6AddressImpl t(_pImpl->addr());
- IPv6AddressImpl o(other._pImpl->addr());
+ IPv6AddressImpl t(pImpl()->addr());
+ IPv6AddressImpl o(other.pImpl()->addr());
return IPAddress((t | o).addr(), sizeof(struct in6_addr));
}
#endif
@@ -1128,15 +467,15 @@ IPAddress IPAddress::operator ^ (const IPAddress& other) const
{
if (family() == IPv4)
{
- IPv4AddressImpl t(_pImpl->addr());
- IPv4AddressImpl o(other._pImpl->addr());
+ IPv4AddressImpl t(pImpl()->addr());
+ IPv4AddressImpl o(other.pImpl()->addr());
return IPAddress((t ^ o).addr(), sizeof(struct in_addr));
}
#if defined(POCO_HAVE_IPv6)
else if (family() == IPv6)
{
- IPv6AddressImpl t(_pImpl->addr());
- IPv6AddressImpl o(other._pImpl->addr());
+ IPv6AddressImpl t(pImpl()->addr());
+ IPv6AddressImpl o(other.pImpl()->addr());
return IPAddress((t ^ o).addr(), sizeof(struct in6_addr));
}
#endif
@@ -1152,13 +491,13 @@ IPAddress IPAddress::operator ~ () const
{
if (family() == IPv4)
{
- IPv4AddressImpl self(this->_pImpl->addr());
+ IPv4AddressImpl self(this->pImpl()->addr());
return IPAddress((~self).addr(), sizeof(struct in_addr));
}
#if defined(POCO_HAVE_IPv6)
else if (family() == IPv6)
{
- IPv6AddressImpl self(this->_pImpl->addr());
+ IPv6AddressImpl self(this->pImpl()->addr());
return IPAddress((~self).addr(), sizeof(struct in6_addr));
}
#endif
@@ -1169,31 +508,25 @@ IPAddress IPAddress::operator ~ () const
poco_socklen_t IPAddress::length() const
{
- return _pImpl->length();
+ return pImpl()->length();
}
const void* IPAddress::addr() const
{
- return _pImpl->addr();
+ return pImpl()->addr();
}
int IPAddress::af() const
{
- return _pImpl->af();
+ return pImpl()->af();
}
unsigned IPAddress::prefixLength() const
{
- return _pImpl->prefixLength();
-}
-
-void IPAddress::init(IPAddressImpl* pImpl)
-{
- _pImpl->release();
- _pImpl = pImpl;
+ return pImpl()->prefixLength();
}
@@ -1205,35 +538,34 @@ IPAddress IPAddress::parse(const std::string& addr)
bool IPAddress::tryParse(const std::string& addr, IPAddress& result)
{
- IPAddressImpl* pImpl = IPv4AddressImpl::parse(addr);
-#if defined(POCO_HAVE_IPv6)
- if (!pImpl) pImpl = IPv6AddressImpl::parse(addr);
-#endif
- if (pImpl)
+ IPv4AddressImpl impl4(IPv4AddressImpl::parse(addr));
+ if (impl4 != IPv4AddressImpl())
{
- result.init(pImpl);
+ std::memcpy(result.pImpl(), &impl4, sizeof(impl4));
return true;
}
- else return false;
+#if defined(POCO_HAVE_IPv6)
+ IPv6AddressImpl impl6(IPv6AddressImpl::parse(addr));
+ if (impl6 != IPv6AddressImpl())
+ {
+ std::memcpy(result.pImpl(), &impl6, sizeof(impl6));
+ return true;
+ }
+#endif
+ return false;
}
void IPAddress::mask(const IPAddress& mask)
{
- IPAddressImpl* pClone = _pImpl->clone();
- _pImpl->release();
- _pImpl = pClone;
IPAddress null;
- _pImpl->mask(mask._pImpl, null._pImpl);
+ pImpl()->mask(mask.pImpl(), null.pImpl());
}
void IPAddress::mask(const IPAddress& mask, const IPAddress& set)
{
- IPAddressImpl* pClone = _pImpl->clone();
- _pImpl->release();
- _pImpl = pClone;
- _pImpl->mask(mask._pImpl, set._pImpl);
+ pImpl()->mask(mask.pImpl(), set.pImpl());
}
diff --git a/Net/src/IPAddressImpl.cpp b/Net/src/IPAddressImpl.cpp
new file mode 100644
index 000000000..2a5b08823
--- /dev/null
+++ b/Net/src/IPAddressImpl.cpp
@@ -0,0 +1,770 @@
+//
+// IPAddress.cpp
+//
+// $Id: //poco/1.4/Net/src/IPAddress.cpp#5 $
+//
+// Library: Net
+// Package: NetCore
+// Module: IPAddress
+//
+// Copyright (c) 2005-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#include "Poco/Net/IPAddressImpl.h"
+#include "Poco/Net/NetException.h"
+#include "Poco/RefCountedObject.h"
+#include "Poco/NumberFormatter.h"
+#include "Poco/String.h"
+#include "Poco/Types.h"
+
+
+using Poco::RefCountedObject;
+using Poco::NumberFormatter;
+using Poco::toLower;
+using Poco::UInt8;
+using Poco::UInt16;
+using Poco::UInt32;
+
+
+namespace {
+
+template
+unsigned maskBits(T val, unsigned size)
+ /// Returns the length of the mask (number of bits set in val).
+ /// The val should be either all zeros or two contiguos areas of 1s and 0s.
+ /// The algorithm ignores invalid non-contiguous series of 1s and treats val
+ /// as if all bits between MSb and last non-zero bit are set to 1.
+{
+ unsigned count = 0;
+ if (val)
+ {
+ val = (val ^ (val - 1)) >> 1;
+ for (count = 0; val; ++count) val >>= 1;
+ }
+ else count = size;
+ return size - count;
+}
+
+} // namespace
+
+
+namespace Poco {
+namespace Net {
+namespace Impl {
+
+//
+// IPAddressImpl
+//
+
+
+IPAddressImpl::IPAddressImpl()
+{
+}
+
+
+IPAddressImpl::~IPAddressImpl()
+{
+}
+
+
+//
+// IPv4AddressImpl
+//
+
+IPv4AddressImpl::IPv4AddressImpl()
+{
+ std::memset(&_addr, 0, sizeof(_addr));
+}
+
+
+IPv4AddressImpl::IPv4AddressImpl(const void* addr)
+{
+ std::memcpy(&_addr, addr, sizeof(_addr));
+}
+
+
+IPv4AddressImpl::IPv4AddressImpl(unsigned prefix)
+{
+ UInt32 addr = (prefix == 32) ? 0xffffffff : ~(0xffffffff >> prefix);
+ _addr.s_addr = htonl(addr);
+}
+
+
+IPv4AddressImpl::IPv4AddressImpl(const IPv4AddressImpl& addr)
+{
+ std::memcpy(&_addr, &addr._addr, sizeof(_addr));
+}
+
+
+IPv4AddressImpl& IPv4AddressImpl::operator = (const IPv4AddressImpl& addr)
+{
+ std::memcpy(&_addr, &addr._addr, sizeof(_addr));
+ return *this;
+}
+
+
+std::string IPv4AddressImpl::toString() const
+{
+ const UInt8* bytes = reinterpret_cast(&_addr);
+ std::string result;
+ result.reserve(16);
+ NumberFormatter::append(result, bytes[0]);
+ result.append(".");
+ NumberFormatter::append(result, bytes[1]);
+ result.append(".");
+ NumberFormatter::append(result, bytes[2]);
+ result.append(".");
+ NumberFormatter::append(result, bytes[3]);
+ return result;
+}
+
+
+poco_socklen_t IPv4AddressImpl::length() const
+{
+ return sizeof(_addr);
+}
+
+
+const void* IPv4AddressImpl::addr() const
+{
+ return &_addr;
+}
+
+
+IPAddressImpl::Family IPv4AddressImpl::family() const
+{
+ return IPAddressImpl::IPv4;
+}
+
+
+int IPv4AddressImpl::af() const
+{
+ return AF_INET;
+}
+
+
+unsigned IPv4AddressImpl::prefixLength() const
+{
+ return maskBits(ntohl(_addr.s_addr), 32);
+}
+
+
+Poco::UInt32 IPv4AddressImpl::scope() const
+{
+ return 0;
+}
+
+
+bool IPv4AddressImpl::isWildcard() const
+{
+ return _addr.s_addr == INADDR_ANY;
+}
+
+
+bool IPv4AddressImpl::isBroadcast() const
+{
+ return _addr.s_addr == INADDR_NONE;
+}
+
+
+bool IPv4AddressImpl::isLoopback() const
+{
+ return (ntohl(_addr.s_addr) & 0xFF000000) == 0x7F000000; // 127.0.0.1 to 127.255.255.255
+}
+
+
+bool IPv4AddressImpl::isMulticast() const
+{
+ return (ntohl(_addr.s_addr) & 0xF0000000) == 0xE0000000; // 224.0.0.0/24 to 239.0.0.0/24
+}
+
+
+bool IPv4AddressImpl::isLinkLocal() const
+{
+ return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xA9FE0000; // 169.254.0.0/16
+}
+
+
+bool IPv4AddressImpl::isSiteLocal() const
+{
+ UInt32 addr = ntohl(_addr.s_addr);
+ return (addr & 0xFF000000) == 0x0A000000 || // 10.0.0.0/24
+ (addr & 0xFFFF0000) == 0xC0A80000 || // 192.68.0.0/16
+ (addr >= 0xAC100000 && addr <= 0xAC1FFFFF); // 172.16.0.0 to 172.31.255.255
+}
+
+
+bool IPv4AddressImpl::isIPv4Compatible() const
+{
+ return true;
+}
+
+
+bool IPv4AddressImpl::isIPv4Mapped() const
+{
+ return true;
+}
+
+
+bool IPv4AddressImpl::isWellKnownMC() const
+{
+ return (ntohl(_addr.s_addr) & 0xFFFFFF00) == 0xE0000000; // 224.0.0.0/8
+}
+
+
+bool IPv4AddressImpl::isNodeLocalMC() const
+{
+ return false;
+}
+
+
+bool IPv4AddressImpl::isLinkLocalMC() const
+{
+ return (ntohl(_addr.s_addr) & 0xFF000000) == 0xE0000000; // 244.0.0.0/24
+}
+
+
+bool IPv4AddressImpl::isSiteLocalMC() const
+{
+ return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xEFFF0000; // 239.255.0.0/16
+}
+
+
+bool IPv4AddressImpl::isOrgLocalMC() const
+{
+ return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xEFC00000; // 239.192.0.0/16
+}
+
+
+bool IPv4AddressImpl::isGlobalMC() const
+{
+ UInt32 addr = ntohl(_addr.s_addr);
+ return addr >= 0xE0000100 && addr <= 0xEE000000; // 224.0.1.0 to 238.255.255.255
+}
+
+
+IPv4AddressImpl IPv4AddressImpl::parse(const std::string& addr)
+{
+ if (addr.empty()) return IPv4AddressImpl();
+#if defined(_WIN32)
+ struct in_addr ia;
+ ia.s_addr = inet_addr(addr.c_str());
+ if (ia.s_addr == INADDR_NONE && addr != "255.255.255.255")
+ return IPv4AddressImpl();
+ else
+ return IPv4AddressImpl(&ia);
+#else
+#if __GNUC__ < 3 || defined(POCO_VXWORKS)
+ struct in_addr ia;
+ ia.s_addr = inet_addr(const_cast(addr.c_str()));
+ if (ia.s_addr == INADDR_NONE && addr != "255.255.255.255")
+ return IPv4AddressImpl();
+ else
+ return IPv4AddressImpl(&ia);
+#else
+ struct in_addr ia;
+ if (inet_aton(addr.c_str(), &ia))
+ return IPv4AddressImpl(&ia);
+ else
+ return IPv4AddressImpl();
+#endif
+#endif
+}
+
+
+void IPv4AddressImpl::mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet)
+{
+ poco_assert (pMask->af() == AF_INET && pSet->af() == AF_INET);
+
+ _addr.s_addr &= static_cast(pMask)->_addr.s_addr;
+ _addr.s_addr |= static_cast(pSet)->_addr.s_addr & ~static_cast(pMask)->_addr.s_addr;
+}
+
+
+IPAddressImpl* IPv4AddressImpl::clone() const
+{
+ return new IPv4AddressImpl(&_addr);
+}
+
+
+IPv4AddressImpl IPv4AddressImpl::operator & (const IPv4AddressImpl& addr) const
+{
+ IPv4AddressImpl result(&_addr);
+ result._addr.s_addr &= addr._addr.s_addr;
+ return result;
+}
+
+
+IPv4AddressImpl IPv4AddressImpl::operator | (const IPv4AddressImpl& addr) const
+{
+ IPv4AddressImpl result(&_addr);
+ result._addr.s_addr |= addr._addr.s_addr;
+ return result;
+}
+
+
+IPv4AddressImpl IPv4AddressImpl::operator ^ (const IPv4AddressImpl& addr) const
+{
+ IPv4AddressImpl result(&_addr);
+ result._addr.s_addr ^= addr._addr.s_addr;
+ return result;
+}
+
+
+IPv4AddressImpl IPv4AddressImpl::operator ~ () const
+{
+IPv4AddressImpl result(&_addr);
+ result._addr.s_addr ^= 0xffffffff;
+ return result;
+}
+
+
+bool IPv4AddressImpl::operator == (const IPv4AddressImpl& addr) const
+{
+ return 0 == std::memcmp(&addr._addr, &_addr, sizeof(_addr));
+}
+
+
+bool IPv4AddressImpl::operator != (const IPv4AddressImpl& addr) const
+{
+ return !(*this == addr);
+}
+
+
+#if defined(POCO_HAVE_IPv6)
+
+
+//
+// IPv6AddressImpl
+//
+
+
+IPv6AddressImpl::IPv6AddressImpl(): _scope(0)
+{
+ std::memset(&_addr, 0, sizeof(_addr));
+}
+
+IPv6AddressImpl::IPv6AddressImpl(const void* addr): _scope(0)
+{
+ std::memcpy(&_addr, addr, sizeof(_addr));
+}
+
+IPv6AddressImpl::IPv6AddressImpl(const void* addr, Poco::UInt32 scope): _scope(scope)
+{
+ std::memcpy(&_addr, addr, sizeof(_addr));
+}
+
+
+IPv6AddressImpl::IPv6AddressImpl(const IPv6AddressImpl& addr): _scope(addr._scope)
+{
+ std::memcpy((void*) &_addr, (void*) &addr._addr, sizeof(_addr));
+}
+
+
+IPv6AddressImpl& IPv6AddressImpl::operator = (const IPv6AddressImpl& addr)
+{
+ _scope = addr._scope;
+ std::memcpy(&_addr, &addr._addr, sizeof(_addr));
+ return *this;
+}
+
+
+IPv6AddressImpl::IPv6AddressImpl(unsigned prefix):
+ _scope(0)
+{
+ unsigned i = 0;
+#ifdef POCO_OS_FAMILY_WINDOWS
+ for (; prefix >= 16; ++i, prefix -= 16) {
+ _addr.s6_addr16[i] = 0xffff;
+ }
+ if (prefix > 0)
+ _addr.s6_addr16[i++] = htons(~(0xffff >> prefix));
+ while (i < 8)
+ _addr.s6_addr16[i++] = 0;
+#else
+ for (; prefix >= 32; ++i, prefix -= 32) {
+ _addr.s6_addr32[i] = 0xffffffff;
+ }
+ if (prefix > 0)
+ _addr.s6_addr32[i++] = htonl(~(0xffffffffU >> prefix));
+ while (i < 4)
+ _addr.s6_addr32[i++] = 0;
+#endif
+}
+
+std::string IPv6AddressImpl::toString() const
+{
+ const UInt16* words = reinterpret_cast(&_addr);
+ if (isIPv4Compatible() || isIPv4Mapped())
+ {
+ std::string result;
+ result.reserve(24);
+ if (words[5] == 0)
+ result.append("::");
+ else
+ result.append("::ffff:");
+ const UInt8* bytes = reinterpret_cast(&_addr);
+ NumberFormatter::append(result, bytes[12]);
+ result.append(".");
+ NumberFormatter::append(result, bytes[13]);
+ result.append(".");
+ NumberFormatter::append(result, bytes[14]);
+ result.append(".");
+ NumberFormatter::append(result, bytes[15]);
+ return result;
+ }
+ else
+ {
+ std::string result;
+ result.reserve(64);
+ bool zeroSequence = false;
+ int i = 0;
+ while (i < 8)
+ {
+ if (!zeroSequence && words[i] == 0)
+ {
+ int zi = i;
+ while (zi < 8 && words[zi] == 0) ++zi;
+ if (zi > i + 1)
+ {
+ i = zi;
+ result.append(":");
+ zeroSequence = true;
+ }
+ }
+ if (i > 0) result.append(":");
+ if (i < 8) NumberFormatter::appendHex(result, ntohs(words[i++]));
+ }
+ if (_scope > 0)
+ {
+ result.append("%");
+#if defined(_WIN32)
+ NumberFormatter::append(result, _scope);
+#else
+ char buffer[IFNAMSIZ];
+ if (if_indextoname(_scope, buffer))
+ {
+ result.append(buffer);
+ }
+ else
+ {
+ NumberFormatter::append(result, _scope);
+ }
+#endif
+ }
+ return toLower(result);
+ }
+}
+
+poco_socklen_t IPv6AddressImpl::length() const
+{
+ return sizeof(_addr);
+}
+
+const void* IPv6AddressImpl::addr() const
+{
+ return &_addr;
+}
+
+IPAddressImpl::Family IPv6AddressImpl::family() const
+{
+ return IPAddressImpl::IPv6;
+}
+
+int IPv6AddressImpl::af() const
+{
+ return AF_INET6;
+}
+
+unsigned IPv6AddressImpl::prefixLength() const
+{
+ unsigned bits = 0;
+ unsigned bitPos = 128;
+#if defined(POCO_OS_FAMILY_UNIX)
+ for (int i = 3; i >= 0; --i)
+ {
+ unsigned addr = ntohl(_addr.s6_addr32[i]);
+ if ((bits = maskBits(addr, 32))) return (bitPos - (32 - bits));
+ bitPos -= 32;
+ }
+ return 0;
+#elif defined(POCO_OS_FAMILY_WINDOWS)
+ for (int i = 7; i >= 0; --i)
+ {
+ unsigned short addr = ntohs(_addr.s6_addr16[i]);
+ if ((bits = maskBits(addr, 16))) return (bitPos - (16 - bits));
+ bitPos -= 16;
+ }
+ return 0;
+#else
+#warning prefixLength() not implemented
+ throw NotImplementedException("prefixLength() not implemented");
+#endif
+}
+Poco::UInt32 IPv6AddressImpl::scope() const
+{
+ return _scope;
+}
+
+bool IPv6AddressImpl::isWildcard() const
+{
+ const UInt16* words = reinterpret_cast(&_addr);
+ return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 &&
+ words[4] == 0 && words[5] == 0 && words[6] == 0 && words[7] == 0;
+}
+
+bool IPv6AddressImpl::isBroadcast() const
+{
+ return false;
+}
+
+bool IPv6AddressImpl::isLoopback() const
+{
+ const UInt16* words = reinterpret_cast(&_addr);
+ return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 &&
+ words[4] == 0 && words[5] == 0 && words[6] == 0 && ntohs(words[7]) == 0x0001;
+}
+
+bool IPv6AddressImpl::isMulticast() const
+{
+ const UInt16* words = reinterpret_cast(&_addr);
+ return (ntohs(words[0]) & 0xFFE0) == 0xFF00;
+}
+
+bool IPv6AddressImpl::isLinkLocal() const
+{
+ const UInt16* words = reinterpret_cast(&_addr);
+ return (ntohs(words[0]) & 0xFFE0) == 0xFE80;
+}
+
+bool IPv6AddressImpl::isSiteLocal() const
+{
+ const UInt16* words = reinterpret_cast(&_addr);
+ return ((ntohs(words[0]) & 0xFFE0) == 0xFEC0) || ((ntohs(words[0]) & 0xFF00) == 0xFC00);
+}
+
+bool IPv6AddressImpl::isIPv4Compatible() const
+{
+ const UInt16* words = reinterpret_cast(&_addr);
+ return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && words[4] == 0 && words[5] == 0;
+}
+
+bool IPv6AddressImpl::isIPv4Mapped() const
+{
+ const UInt16* words = reinterpret_cast(&_addr);
+ return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && words[4] == 0 && ntohs(words[5]) == 0xFFFF;
+}
+
+bool IPv6AddressImpl::isWellKnownMC() const
+{
+ const UInt16* words = reinterpret_cast(&_addr);
+ return (ntohs(words[0]) & 0xFFF0) == 0xFF00;
+}
+
+bool IPv6AddressImpl::isNodeLocalMC() const
+{
+ const UInt16* words = reinterpret_cast(&_addr);
+ return (ntohs(words[0]) & 0xFFEF) == 0xFF01;
+}
+
+bool IPv6AddressImpl::isLinkLocalMC() const
+{
+ const UInt16* words = reinterpret_cast(&_addr);
+ return (ntohs(words[0]) & 0xFFEF) == 0xFF02;
+}
+
+bool IPv6AddressImpl::isSiteLocalMC() const
+{
+ const UInt16* words = reinterpret_cast(&_addr);
+ return (ntohs(words[0]) & 0xFFEF) == 0xFF05;
+}
+
+bool IPv6AddressImpl::isOrgLocalMC() const
+{
+ const UInt16* words = reinterpret_cast(&_addr);
+ return (ntohs(words[0]) & 0xFFEF) == 0xFF08;
+}
+
+bool IPv6AddressImpl::isGlobalMC() const
+{
+ const UInt16* words = reinterpret_cast(&_addr);
+ return (ntohs(words[0]) & 0xFFEF) == 0xFF0F;
+}
+
+IPv6AddressImpl IPv6AddressImpl::parse(const std::string& addr)
+{
+ if (addr.empty()) return IPv6AddressImpl();
+#if defined(_WIN32)
+ struct addrinfo* pAI;
+ struct addrinfo hints;
+ std::memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_NUMERICHOST;
+ int rc = getaddrinfo(addr.c_str(), NULL, &hints, &pAI);
+ if (rc == 0)
+ {
+ IPv6AddressImpl result = IPv6AddressImpl(&reinterpret_cast(pAI->ai_addr)->sin6_addr, static_cast(reinterpret_cast(pAI->ai_addr)->sin6_scope_id));
+ freeaddrinfo(pAI);
+ return result;
+ }
+ else return IPv6AddressImpl();
+#else
+ struct in6_addr ia;
+ std::string::size_type pos = addr.find('%');
+ if (std::string::npos != pos)
+ {
+ std::string::size_type start = ('[' == addr[0]) ? 1 : 0;
+ std::string unscopedAddr(addr, start, pos - start);
+ std::string scope(addr, pos + 1, addr.size() - start - pos);
+ Poco::UInt32 scopeId(0);
+ if (!(scopeId = if_nametoindex(scope.c_str())))
+ return 0;
+ if (inet_pton(AF_INET6, unscopedAddr.c_str(), &ia) == 1)
+ return IPv6AddressImpl(&ia, scopeId);
+ else
+ return 0;
+ }
+ else
+ {
+ if (inet_pton(AF_INET6, addr.c_str(), &ia) == 1)
+ return new IPv6AddressImpl(&ia);
+ else
+ return 0;
+ }
+#endif
+}
+
+void IPv6AddressImpl::mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet)
+{
+ throw Poco::NotImplementedException("mask() is only supported for IPv4 addresses");
+}
+
+IPAddressImpl* IPv6AddressImpl::clone() const
+{
+ return new IPv6AddressImpl(&_addr, _scope);
+}
+
+IPv6AddressImpl IPv6AddressImpl::operator & (const IPv6AddressImpl& addr) const
+{
+ IPv6AddressImpl result(&_addr);
+#ifdef POCO_OS_FAMILY_WINDOWS
+ result._addr.s6_addr16[0] &= addr._addr.s6_addr16[0];
+ result._addr.s6_addr16[1] &= addr._addr.s6_addr16[1];
+ result._addr.s6_addr16[2] &= addr._addr.s6_addr16[2];
+ result._addr.s6_addr16[3] &= addr._addr.s6_addr16[3];
+ result._addr.s6_addr16[4] &= addr._addr.s6_addr16[4];
+ result._addr.s6_addr16[5] &= addr._addr.s6_addr16[5];
+ result._addr.s6_addr16[6] &= addr._addr.s6_addr16[6];
+ result._addr.s6_addr16[7] &= addr._addr.s6_addr16[7];
+#else
+ result._addr.s6_addr32[0] &= addr._addr.s6_addr32[0];
+ result._addr.s6_addr32[1] &= addr._addr.s6_addr32[1];
+ result._addr.s6_addr32[2] &= addr._addr.s6_addr32[2];
+ result._addr.s6_addr32[3] &= addr._addr.s6_addr32[3];
+#endif
+ return result;
+}
+
+IPv6AddressImpl IPv6AddressImpl::operator | (const IPv6AddressImpl& addr) const
+{
+ IPv6AddressImpl result(&_addr);
+#ifdef POCO_OS_FAMILY_WINDOWS
+ result._addr.s6_addr16[0] |= addr._addr.s6_addr16[0];
+ result._addr.s6_addr16[1] |= addr._addr.s6_addr16[1];
+ result._addr.s6_addr16[2] |= addr._addr.s6_addr16[2];
+ result._addr.s6_addr16[3] |= addr._addr.s6_addr16[3];
+ result._addr.s6_addr16[4] |= addr._addr.s6_addr16[4];
+ result._addr.s6_addr16[5] |= addr._addr.s6_addr16[5];
+ result._addr.s6_addr16[6] |= addr._addr.s6_addr16[6];
+ result._addr.s6_addr16[7] |= addr._addr.s6_addr16[7];
+#else
+ result._addr.s6_addr32[0] |= addr._addr.s6_addr32[0];
+ result._addr.s6_addr32[1] |= addr._addr.s6_addr32[1];
+ result._addr.s6_addr32[2] |= addr._addr.s6_addr32[2];
+ result._addr.s6_addr32[3] |= addr._addr.s6_addr32[3];
+#endif
+ return result;
+}
+
+IPv6AddressImpl IPv6AddressImpl::operator ^ (const IPv6AddressImpl& addr) const
+{
+ IPv6AddressImpl result(&_addr);
+#ifdef POCO_OS_FAMILY_WINDOWS
+ result._addr.s6_addr16[0] ^= addr._addr.s6_addr16[0];
+ result._addr.s6_addr16[1] ^= addr._addr.s6_addr16[1];
+ result._addr.s6_addr16[2] ^= addr._addr.s6_addr16[2];
+ result._addr.s6_addr16[3] ^= addr._addr.s6_addr16[3];
+ result._addr.s6_addr16[4] ^= addr._addr.s6_addr16[4];
+ result._addr.s6_addr16[5] ^= addr._addr.s6_addr16[5];
+ result._addr.s6_addr16[6] ^= addr._addr.s6_addr16[6];
+ result._addr.s6_addr16[7] ^= addr._addr.s6_addr16[7];
+#else
+ result._addr.s6_addr32[0] ^= addr._addr.s6_addr32[0];
+ result._addr.s6_addr32[1] ^= addr._addr.s6_addr32[1];
+ result._addr.s6_addr32[2] ^= addr._addr.s6_addr32[2];
+ result._addr.s6_addr32[3] ^= addr._addr.s6_addr32[3];
+#endif
+ return result;
+}
+
+IPv6AddressImpl IPv6AddressImpl::operator ~ () const
+{
+ IPv6AddressImpl result(&_addr);
+#ifdef POCO_OS_FAMILY_WINDOWS
+ result._addr.s6_addr16[0] ^= 0xffff;
+ result._addr.s6_addr16[1] ^= 0xffff;
+ result._addr.s6_addr16[2] ^= 0xffff;
+ result._addr.s6_addr16[3] ^= 0xffff;
+ result._addr.s6_addr16[4] ^= 0xffff;
+ result._addr.s6_addr16[5] ^= 0xffff;
+ result._addr.s6_addr16[6] ^= 0xffff;
+ result._addr.s6_addr16[7] ^= 0xffff;
+#else
+ result._addr.s6_addr32[0] ^= 0xffffffff;
+ result._addr.s6_addr32[1] ^= 0xffffffff;
+ result._addr.s6_addr32[2] ^= 0xffffffff;
+ result._addr.s6_addr32[3] ^= 0xffffffff;
+#endif
+ return result;
+}
+
+
+bool IPv6AddressImpl::operator == (const IPv6AddressImpl& addr) const
+{
+ return 0 == std::memcmp(&addr._addr, &_addr, sizeof(_addr));
+}
+
+
+bool IPv6AddressImpl::operator != (const IPv6AddressImpl& addr) const
+{
+ return !(*this == addr);
+}
+
+
+#endif // POCO_HAVE_IPv6
+
+
+} } } // namespace Poco::Net::Impl