- 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

@ -22,6 +22,7 @@ Release 1.5.0 (2012-08-??)
- IPAddress BinaryReader/Writer << and >> operators - IPAddress BinaryReader/Writer << and >> operators
- IPAddress force IPv6 always lowercase (RFC 5952) - IPAddress force IPv6 always lowercase (RFC 5952)
- fixed SF#3538785: SMTPClientSession::sendMessage() should take recipient list - fixed SF#3538785: SMTPClientSession::sendMessage() should take recipient list
- added IPAddress::prefixLength()
Release 1.4.4 (2012-08-??) Release 1.4.4 (2012-08-??)
========================== ==========================

View File

@ -200,6 +200,11 @@ public:
return _data; return _data;
} }
MemoryInputStream& stream() const
{
return _istr;
}
private: private:
Buffer<T>& _data; Buffer<T>& _data;
MemoryInputStream _istr; MemoryInputStream _istr;

View File

@ -215,6 +215,11 @@ public:
return _data; return _data;
} }
MemoryOutputStream& stream() const
{
return _ostr;
}
private: private:
Buffer<T>& _data; Buffer<T>& _data;
MemoryOutputStream _ostr; MemoryOutputStream _ostr;

View File

@ -325,6 +325,9 @@ public:
int af() const; int af() const;
/// Returns the address family (AF_INET or AF_INET6) of the address. /// Returns the address family (AF_INET or AF_INET6) of the address.
unsigned prefixLength() const;
/// Returns the prefix length.
void mask(const IPAddress& mask); void mask(const IPAddress& mask);
/// Masks the IP address using the given netmask, which is usually /// Masks the IP address using the given netmask, which is usually

View File

@ -96,6 +96,11 @@ void Net_API uninitializeNetwork();
} } // namespace Poco::Net } } // namespace Poco::Net
// Define to enable IPv6 support
#if !defined (POCO_HAVE_IPv6)
#define POCO_HAVE_IPv6
#endif // POCO_HAVE_IPv6
#if !defined(s6_addr16) #if !defined(s6_addr16)
#if defined(POCO_OS_FAMILY_WINDOWS) #if defined(POCO_OS_FAMILY_WINDOWS)
#define s6_addr16 u.Word #define s6_addr16 u.Word

View File

@ -54,6 +54,28 @@ using Poco::UInt16;
using Poco::UInt32; 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 Poco {
namespace Net { namespace Net {
@ -87,6 +109,8 @@ public:
virtual bool isOrgLocalMC() const = 0; virtual bool isOrgLocalMC() const = 0;
virtual bool isGlobalMC() const = 0; virtual bool isGlobalMC() const = 0;
virtual void mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet) = 0; virtual void mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet) = 0;
virtual unsigned prefixLength() const = 0;
virtual IPAddressImpl* clone() const = 0; virtual IPAddressImpl* clone() const = 0;
protected: protected:
@ -163,6 +187,11 @@ public:
{ {
return AF_INET; return AF_INET;
} }
unsigned prefixLength() const
{
return maskBits(ntohl(_addr.s_addr), 32);
}
Poco::UInt32 scope() const Poco::UInt32 scope() const
{ {
@ -353,14 +382,23 @@ public:
_scope(0) _scope(0)
{ {
unsigned i = 0; unsigned i = 0;
for (; prefix > 0; ++i, prefix -= 16) { #ifdef POCO_OS_FAMILY_WINDOWS
if (prefix >= 16) for (; prefix > 16; ++i, prefix -= 16) {
_addr.s6_addr16[i] = 0xffff; _addr.s6_addr16[i] = 0xffff;
else
_addr.s6_addr16[i] = htons(~(0xffff >> prefix));
} }
if (prefix > 0)
_addr.s6_addr16[i++] = htons(~(0xffffU >> prefix));
while (i < 8) while (i < 8)
_addr.s6_addr16[i++] = 0; _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 std::string toString() const
@ -447,6 +485,31 @@ public:
return AF_INET6; 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 Poco::UInt32 scope() const
{ {
return _scope; return _scope;
@ -593,22 +656,14 @@ public:
{ {
IPv6AddressImpl result(&_addr); IPv6AddressImpl result(&_addr);
#ifdef POCO_OS_FAMILY_WINDOWS #ifdef POCO_OS_FAMILY_WINDOWS
result._addr.s6_addr[0] &= addr._addr.s6_addr[0]; result._addr.s6_addr16[0] &= addr._addr.s6_addr16[0];
result._addr.s6_addr[1] &= addr._addr.s6_addr[1]; result._addr.s6_addr16[1] &= addr._addr.s6_addr16[1];
result._addr.s6_addr[2] &= addr._addr.s6_addr[2]; result._addr.s6_addr16[2] &= addr._addr.s6_addr16[2];
result._addr.s6_addr[3] &= addr._addr.s6_addr[3]; result._addr.s6_addr16[3] &= addr._addr.s6_addr16[3];
result._addr.s6_addr[4] &= addr._addr.s6_addr[4]; result._addr.s6_addr16[4] &= addr._addr.s6_addr16[4];
result._addr.s6_addr[5] &= addr._addr.s6_addr[5]; result._addr.s6_addr16[5] &= addr._addr.s6_addr16[5];
result._addr.s6_addr[6] &= addr._addr.s6_addr[6]; result._addr.s6_addr16[6] &= addr._addr.s6_addr16[6];
result._addr.s6_addr[7] &= addr._addr.s6_addr[7]; result._addr.s6_addr16[7] &= addr._addr.s6_addr16[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];
#else #else
result._addr.s6_addr32[0] &= addr._addr.s6_addr32[0]; result._addr.s6_addr32[0] &= addr._addr.s6_addr32[0];
result._addr.s6_addr32[1] &= addr._addr.s6_addr32[1]; result._addr.s6_addr32[1] &= addr._addr.s6_addr32[1];
@ -622,22 +677,14 @@ public:
{ {
IPv6AddressImpl result(&_addr); IPv6AddressImpl result(&_addr);
#ifdef POCO_OS_FAMILY_WINDOWS #ifdef POCO_OS_FAMILY_WINDOWS
result._addr.s6_addr[0] |= addr._addr.s6_addr[0]; result._addr.s6_addr16[0] |= addr._addr.s6_addr16[0];
result._addr.s6_addr[1] |= addr._addr.s6_addr[1]; result._addr.s6_addr16[1] |= addr._addr.s6_addr16[1];
result._addr.s6_addr[2] |= addr._addr.s6_addr[2]; result._addr.s6_addr16[2] |= addr._addr.s6_addr16[2];
result._addr.s6_addr[3] |= addr._addr.s6_addr[3]; result._addr.s6_addr16[3] |= addr._addr.s6_addr16[3];
result._addr.s6_addr[4] |= addr._addr.s6_addr[4]; result._addr.s6_addr16[4] |= addr._addr.s6_addr16[4];
result._addr.s6_addr[5] |= addr._addr.s6_addr[5]; result._addr.s6_addr16[5] |= addr._addr.s6_addr16[5];
result._addr.s6_addr[6] |= addr._addr.s6_addr[6]; result._addr.s6_addr16[6] |= addr._addr.s6_addr16[6];
result._addr.s6_addr[7] |= addr._addr.s6_addr[7]; result._addr.s6_addr16[7] |= addr._addr.s6_addr16[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];
#else #else
result._addr.s6_addr32[0] |= addr._addr.s6_addr32[0]; result._addr.s6_addr32[0] |= addr._addr.s6_addr32[0];
result._addr.s6_addr32[1] |= addr._addr.s6_addr32[1]; result._addr.s6_addr32[1] |= addr._addr.s6_addr32[1];
@ -651,22 +698,14 @@ public:
{ {
IPv6AddressImpl result(&_addr); IPv6AddressImpl result(&_addr);
#ifdef POCO_OS_FAMILY_WINDOWS #ifdef POCO_OS_FAMILY_WINDOWS
result._addr.s6_addr[0] ^= addr._addr.s6_addr[0]; result._addr.s6_addr16[0] ^= addr._addr.s6_addr16[0];
result._addr.s6_addr[1] ^= addr._addr.s6_addr[1]; result._addr.s6_addr16[1] ^= addr._addr.s6_addr16[1];
result._addr.s6_addr[2] ^= addr._addr.s6_addr[2]; result._addr.s6_addr16[2] ^= addr._addr.s6_addr16[2];
result._addr.s6_addr[3] ^= addr._addr.s6_addr[3]; result._addr.s6_addr16[3] ^= addr._addr.s6_addr16[3];
result._addr.s6_addr[4] ^= addr._addr.s6_addr[4]; result._addr.s6_addr16[4] ^= addr._addr.s6_addr16[4];
result._addr.s6_addr[5] ^= addr._addr.s6_addr[5]; result._addr.s6_addr16[5] ^= addr._addr.s6_addr16[5];
result._addr.s6_addr[6] ^= addr._addr.s6_addr[6]; result._addr.s6_addr16[6] ^= addr._addr.s6_addr16[6];
result._addr.s6_addr[7] ^= addr._addr.s6_addr[7]; result._addr.s6_addr16[7] ^= addr._addr.s6_addr16[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];
#else #else
result._addr.s6_addr32[0] ^= addr._addr.s6_addr32[0]; result._addr.s6_addr32[0] ^= addr._addr.s6_addr32[0];
result._addr.s6_addr32[1] ^= addr._addr.s6_addr32[1]; result._addr.s6_addr32[1] ^= addr._addr.s6_addr32[1];
@ -680,22 +719,14 @@ public:
{ {
IPv6AddressImpl result(&_addr); IPv6AddressImpl result(&_addr);
#ifdef POCO_OS_FAMILY_WINDOWS #ifdef POCO_OS_FAMILY_WINDOWS
result._addr.s6_addr[0] ^= 0xff; result._addr.s6_addr16[0] ^= 0xffff;
result._addr.s6_addr[1] ^= 0xff; result._addr.s6_addr16[1] ^= 0xffff;
result._addr.s6_addr[2] ^= 0xff; result._addr.s6_addr16[2] ^= 0xffff;
result._addr.s6_addr[3] ^= 0xff; result._addr.s6_addr16[3] ^= 0xffff;
result._addr.s6_addr[4] ^= 0xff; result._addr.s6_addr16[4] ^= 0xffff;
result._addr.s6_addr[5] ^= 0xff; result._addr.s6_addr16[5] ^= 0xffff;
result._addr.s6_addr[6] ^= 0xff; result._addr.s6_addr16[6] ^= 0xffff;
result._addr.s6_addr[7] ^= 0xff; result._addr.s6_addr16[7] ^= 0xffff;
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;
#else #else
result._addr.s6_addr32[0] ^= 0xffffffff; result._addr.s6_addr32[0] ^= 0xffffffff;
result._addr.s6_addr32[1] ^= 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) void IPAddress::init(IPAddressImpl* pImpl)
{ {
_pImpl->release(); _pImpl->release();

View File

@ -546,9 +546,21 @@ void IPAddressTest::testBroadcast()
void IPAddressTest::testPrefixCons() void IPAddressTest::testPrefixCons()
{ {
IPAddress mask(15, IPAddress::IPv4); IPAddress ia1(15, IPAddress::IPv4);
IPAddress ia2(62, IPAddress::IPv6);
assert(mask.toString() == "255.254.0.0"); assert(ia1.toString() == "255.254.0.0");
assert(ia2.toString() == "ffff:ffff:ffff:fffc::");
}
void IPAddressTest::testPrefixLen()
{
IPAddress ia1(15, IPAddress::IPv4);
IPAddress ia2(62, IPAddress::IPv6);
assert(ia1.prefixLength() == 15);
assert(ia2.prefixLength() == 62);
} }
@ -600,6 +612,7 @@ CppUnit::Test* IPAddressTest::suite()
CppUnit_addTest(pSuite, IPAddressTest, testWildcard); CppUnit_addTest(pSuite, IPAddressTest, testWildcard);
CppUnit_addTest(pSuite, IPAddressTest, testBroadcast); CppUnit_addTest(pSuite, IPAddressTest, testBroadcast);
CppUnit_addTest(pSuite, IPAddressTest, testPrefixCons); CppUnit_addTest(pSuite, IPAddressTest, testPrefixCons);
CppUnit_addTest(pSuite, IPAddressTest, testPrefixLen);
CppUnit_addTest(pSuite, IPAddressTest, testOperators); CppUnit_addTest(pSuite, IPAddressTest, testOperators);
return pSuite; return pSuite;

View File

@ -58,6 +58,7 @@ public:
void testWildcard(); void testWildcard();
void testBroadcast(); void testBroadcast();
void testPrefixCons(); void testPrefixCons();
void testPrefixLen();
void testOperators(); void testOperators();
void setUp(); void setUp();