- added IPaddress::prefixLength

- return MemoryStreams from MemoryWriters
This commit is contained in:
Aleksandar Fabijanic
2012-07-30 04:22:25 +00:00
parent 03ddca58f5
commit 219a945cc9
8 changed files with 140 additions and 71 deletions

View File

@@ -54,6 +54,28 @@ using Poco::UInt16;
using Poco::UInt32;
namespace {
template <typename T>
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 {
@@ -87,6 +109,8 @@ public:
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:
@@ -163,6 +187,11 @@ public:
{
return AF_INET;
}
unsigned prefixLength() const
{
return maskBits(ntohl(_addr.s_addr), 32);
}
Poco::UInt32 scope() const
{
@@ -353,14 +382,23 @@ public:
_scope(0)
{
unsigned i = 0;
for (; prefix > 0; ++i, prefix -= 16) {
if (prefix >= 16)
_addr.s6_addr16[i] = 0xffff;
else
_addr.s6_addr16[i] = htons(~(0xffff >> prefix));
#ifdef POCO_OS_FAMILY_WINDOWS
for (; prefix > 16; ++i, prefix -= 16) {
_addr.s6_addr16[i] = 0xffff;
}
if (prefix > 0)
_addr.s6_addr16[i++] = htons(~(0xffffU >> 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
@@ -447,6 +485,31 @@ public:
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;
@@ -593,22 +656,14 @@ public:
{
IPv6AddressImpl result(&_addr);
#ifdef POCO_OS_FAMILY_WINDOWS
result._addr.s6_addr[0] &= addr._addr.s6_addr[0];
result._addr.s6_addr[1] &= addr._addr.s6_addr[1];
result._addr.s6_addr[2] &= addr._addr.s6_addr[2];
result._addr.s6_addr[3] &= addr._addr.s6_addr[3];
result._addr.s6_addr[4] &= addr._addr.s6_addr[4];
result._addr.s6_addr[5] &= addr._addr.s6_addr[5];
result._addr.s6_addr[6] &= addr._addr.s6_addr[6];
result._addr.s6_addr[7] &= addr._addr.s6_addr[7];
result._addr.s6_addr[8] &= addr._addr.s6_addr[8];
result._addr.s6_addr[9] &= addr._addr.s6_addr[9];
result._addr.s6_addr[10] &= addr._addr.s6_addr[10];
result._addr.s6_addr[11] &= addr._addr.s6_addr[11];
result._addr.s6_addr[12] &= addr._addr.s6_addr[12];
result._addr.s6_addr[13] &= addr._addr.s6_addr[13];
result._addr.s6_addr[14] &= addr._addr.s6_addr[14];
result._addr.s6_addr[15] &= addr._addr.s6_addr[15];
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];
@@ -622,22 +677,14 @@ public:
{
IPv6AddressImpl result(&_addr);
#ifdef POCO_OS_FAMILY_WINDOWS
result._addr.s6_addr[0] |= addr._addr.s6_addr[0];
result._addr.s6_addr[1] |= addr._addr.s6_addr[1];
result._addr.s6_addr[2] |= addr._addr.s6_addr[2];
result._addr.s6_addr[3] |= addr._addr.s6_addr[3];
result._addr.s6_addr[4] |= addr._addr.s6_addr[4];
result._addr.s6_addr[5] |= addr._addr.s6_addr[5];
result._addr.s6_addr[6] |= addr._addr.s6_addr[6];
result._addr.s6_addr[7] |= addr._addr.s6_addr[7];
result._addr.s6_addr[8] |= addr._addr.s6_addr[8];
result._addr.s6_addr[9] |= addr._addr.s6_addr[9];
result._addr.s6_addr[10] |= addr._addr.s6_addr[10];
result._addr.s6_addr[11] |= addr._addr.s6_addr[11];
result._addr.s6_addr[12] |= addr._addr.s6_addr[12];
result._addr.s6_addr[13] |= addr._addr.s6_addr[13];
result._addr.s6_addr[14] |= addr._addr.s6_addr[14];
result._addr.s6_addr[15] |= addr._addr.s6_addr[15];
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];
@@ -651,22 +698,14 @@ public:
{
IPv6AddressImpl result(&_addr);
#ifdef POCO_OS_FAMILY_WINDOWS
result._addr.s6_addr[0] ^= addr._addr.s6_addr[0];
result._addr.s6_addr[1] ^= addr._addr.s6_addr[1];
result._addr.s6_addr[2] ^= addr._addr.s6_addr[2];
result._addr.s6_addr[3] ^= addr._addr.s6_addr[3];
result._addr.s6_addr[4] ^= addr._addr.s6_addr[4];
result._addr.s6_addr[5] ^= addr._addr.s6_addr[5];
result._addr.s6_addr[6] ^= addr._addr.s6_addr[6];
result._addr.s6_addr[7] ^= addr._addr.s6_addr[7];
result._addr.s6_addr[8] ^= addr._addr.s6_addr[8];
result._addr.s6_addr[9] ^= addr._addr.s6_addr[9];
result._addr.s6_addr[10] ^= addr._addr.s6_addr[10];
result._addr.s6_addr[11] ^= addr._addr.s6_addr[11];
result._addr.s6_addr[12] ^= addr._addr.s6_addr[12];
result._addr.s6_addr[13] ^= addr._addr.s6_addr[13];
result._addr.s6_addr[14] ^= addr._addr.s6_addr[14];
result._addr.s6_addr[15] ^= addr._addr.s6_addr[15];
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];
@@ -680,22 +719,14 @@ public:
{
IPv6AddressImpl result(&_addr);
#ifdef POCO_OS_FAMILY_WINDOWS
result._addr.s6_addr[0] ^= 0xff;
result._addr.s6_addr[1] ^= 0xff;
result._addr.s6_addr[2] ^= 0xff;
result._addr.s6_addr[3] ^= 0xff;
result._addr.s6_addr[4] ^= 0xff;
result._addr.s6_addr[5] ^= 0xff;
result._addr.s6_addr[6] ^= 0xff;
result._addr.s6_addr[7] ^= 0xff;
result._addr.s6_addr[8] ^= 0xff;
result._addr.s6_addr[9] ^= 0xff;
result._addr.s6_addr[10] ^= 0xff;
result._addr.s6_addr[11] ^= 0xff;
result._addr.s6_addr[12] ^= 0xff;
result._addr.s6_addr[13] ^= 0xff;
result._addr.s6_addr[14] ^= 0xff;
result._addr.s6_addr[15] ^= 0xff;
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;
@@ -1160,6 +1191,11 @@ int IPAddress::af() const
}
unsigned IPAddress::prefixLength() const
{
return _pImpl->prefixLength();
}
void IPAddress::init(IPAddressImpl* pImpl)
{
_pImpl->release();