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