Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Implementation:ClickHouse ClickHouse Poco IPAddressImpl: Difference between revisions

From Leeroopedia
Auto-imported from implementations/ClickHouse_ClickHouse_Poco_IPAddressImpl.md
 
Sync from local file
 
Line 5: Line 5:
[[principle::ClickHouse_ClickHouse_Network_Address_Representation]]
[[principle::ClickHouse_ClickHouse_Network_Address_Representation]]


This page documents the implementation details of the low-level `IPv4AddressImpl` and `IPv6AddressImpl` classes. The corresponding header is already documented under the [[ClickHouse_ClickHouse_Network_Address_Representation]] principle.
This page documents the implementation details of the low-level `IPv4AddressImpl` and `IPv6AddressImpl` classes. The corresponding header is already documented under the [[Principle:ClickHouse_ClickHouse_Network_Address_Representation]] principle.


== Purpose ==
== Purpose ==

Latest revision as of 10:35, 27 September 2026


base/poco/Net/src/IPAddressImpl.cpp:1-718 ClickHouse_ClickHouse ClickHouse_ClickHouse_Network_Address_Representation

This page documents the implementation details of the low-level `IPv4AddressImpl` and `IPv6AddressImpl` classes. The corresponding header is already documented under the Principle:ClickHouse_ClickHouse_Network_Address_Representation principle.

Purpose

Implements the internal `Poco::Net::Impl::IPv4AddressImpl` and `Poco::Net::Impl::IPv6AddressImpl` classes, which are the concrete address storage backends for `IPAddress`. These classes encapsulate the platform-specific `struct in_addr` (IPv4) and `struct in6_addr` (IPv6) structures and provide operations for string conversion, address classification (loopback, multicast, link-local, etc.), bitwise arithmetic, prefix mask construction, and parsing from string representations.

Code Reference

IPv4AddressImpl -- String Conversion

std::string IPv4AddressImpl::toString() const
{
    const UInt8* bytes = reinterpret_cast<const UInt8*>(&_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;
}

IPv4AddressImpl -- Address Classification

Classification methods use network-byte-order masks against standard address ranges:

bool IPv4AddressImpl::isLoopback() const
{
    return (ntohl(_addr.s_addr) & 0xFF000000) == 0x7F000000; // 127.0.0.0/8
}

bool IPv4AddressImpl::isMulticast() const
{
    return (ntohl(_addr.s_addr) & 0xF0000000) == 0xE0000000; // 224.0.0.0/4
}

bool IPv4AddressImpl::isSiteLocal() const
{
    UInt32 addr = ntohl(_addr.s_addr);
    return (addr & 0xFF000000) == 0x0A000000 ||        // 10.0.0.0/8
        (addr & 0xFFFF0000) == 0xC0A80000 ||           // 192.168.0.0/16
        (addr >= 0xAC100000 && addr <= 0xAC1FFFFF);    // 172.16.0.0/12
}

IPv4AddressImpl -- Prefix Mask Construction

IPv4AddressImpl::IPv4AddressImpl(unsigned prefix)
{
    UInt32 addr = (prefix == 32) ? 0xffffffff : ~(0xffffffff >> prefix);
    _addr.s_addr = ByteOrder::toNetwork(addr);
}

IPv6AddressImpl -- String Conversion

The IPv6 `toString` method handles IPv4-compatible/mapped addresses and zero compression (`::`):

std::string IPv6AddressImpl::toString() const
{
    const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
    if ((isIPv4Compatible() && !isLoopback()) || isIPv4Mapped())
    {
        // Format as ::ffff:a.b.c.d or ::a.b.c.d
    }
    else
    {
        // Standard colon-hex with zero-compression and scope ID
    }
}

IPv6AddressImpl -- Parsing with Scope ID

IPv6AddressImpl IPv6AddressImpl::parse(const std::string& addr)
{
    if (addr.empty()) return IPv6AddressImpl();
    struct in6_addr ia;
    std::string::size_type pos = addr.find('%');
    if (std::string::npos != pos)
    {
        // Extract scope name and resolve via if_nametoindex
        std::string unscopedAddr(addr, start, pos - start);
        std::string scope(addr, pos + 1, ...);
        Poco::UInt32 scopeId(0);
        if (!(scopeId = if_nametoindex(scope.c_str())))
            return IPv6AddressImpl();
        if (inet_pton(AF_INET6, unscopedAddr.c_str(), &ia) == 1)
            return IPv6AddressImpl(&ia, scopeId);
    }
    else
    {
        if (inet_pton(AF_INET6, addr.c_str(), &ia) == 1)
            return IPv6AddressImpl(&ia);
    }
    return IPv6AddressImpl();
}

Helper: maskBits

A template function in an anonymous namespace computes the prefix length from a bitmask value:

template <typename T>
unsigned maskBits(T val, unsigned size)
{
    unsigned count = 0;
    if (val)
    {
        val = (val ^ (val - 1)) >> 1;
        for (count = 0; val; ++count) val >>= 1;
    }
    else count = size;
    return size - count;
}

I/O Contract

Input Output Side Effects
`std::string` via `IPv4AddressImpl::parse` `IPv4AddressImpl` (default if unparseable) Uses `inet_aton` (or `inet_addr` on older GCC/VxWorks)
`std::string` via `IPv6AddressImpl::parse` `IPv6AddressImpl` (default if unparseable) Uses `inet_pton`; resolves scope names via `if_nametoindex`
`unsigned prefix` (constructor) Address impl with prefix-length mask bits set None
`IPv4AddressImpl & IPv4AddressImpl` via `operator &` Bitwise AND result None
`IPv6AddressImpl & IPv6AddressImpl` via `operator &` Bitwise AND result Throws if scope IDs mismatch
`const void*` (raw address bytes) Impl wrapping the raw bytes `std::memcpy` into internal `struct in_addr` / `struct in6_addr`

Usage Examples

// These classes are internal; usage is through IPAddress
// IPv4 parsing
Poco::Net::Impl::IPv4AddressImpl addr4 = Poco::Net::Impl::IPv4AddressImpl::parse("192.168.1.1");
std::string str = addr4.toString();  // "192.168.1.1"
bool isLoop = addr4.isLoopback();    // false

// IPv6 parsing with scope
Poco::Net::Impl::IPv6AddressImpl addr6 = Poco::Net::Impl::IPv6AddressImpl::parse("fe80::1%eth0");
unsigned prefix = addr6.prefixLength();

// Mask construction
Poco::Net::Impl::IPv4AddressImpl mask24(24);  // 255.255.255.0

Internal Details

  • `IPv4AddressImpl` stores a `struct in_addr` (4 bytes) and performs all classification by converting to host byte order via `ntohl`.
  • `IPv6AddressImpl` stores a `struct in6_addr` (16 bytes) plus a `Poco::UInt32 _scope` for the interface scope ID.
  • `IPv6AddressImpl::prefixLength` iterates through the four 32-bit words in reverse to compute the CIDR prefix length using the `maskBits` helper. This is only implemented on Unix (`POCO_OS_FAMILY_UNIX`).
  • The `mask` method is implemented only for IPv4; calling it on an IPv6 address throws `Poco::NotImplementedException`.
  • Bitwise operators on `IPv6AddressImpl` require matching scope IDs; mismatches throw `Poco::InvalidArgumentException`.
  • The `clone` method returns a heap-allocated copy, used by the pImpl reference-counting machinery.