Implementation:ClickHouse ClickHouse Poco DNS
| Source File | base/poco/Net/src/DNS.cpp |
|---|---|
| Lines of Code | 663 |
| Principle | Principle:ClickHouse_ClickHouse_DNS_Resolution |
| Domain | Networking, DNS |
| Language | C++ |
| Last Updated | 2026-02-08 00:00 GMT |
Overview
Implementation of DNS resolution functionality including hostname lookups, reverse DNS, and Internationalized Domain Names (IDN) support with Punycode encoding/decoding.
Purpose
Provides comprehensive DNS resolution services for the Poco networking library, supporting both IPv4 and IPv6 address resolution, reverse DNS lookups, and IDN domain name handling.
Key Classes
- DNS: Static class providing DNS resolution methods
Core Functionality
DNS Resolution
Main resolution methods:
// Resolve hostname to IP addresses
HostEntry DNS::hostByName(const std::string& hostname, unsigned hintFlags);
// Reverse DNS lookup
HostEntry DNS::hostByAddress(const IPAddress& address, unsigned hintFlags);
// Resolve hostname or IP address string
HostEntry DNS::resolve(const std::string& address);
// Resolve and return single IP address
IPAddress DNS::resolveOne(const std::string& address);
// Get local host information
HostEntry DNS::thisHost();
// Get local hostname
std::string DNS::hostName();
Uses either `getaddrinfo`/`getnameinfo` (modern) or `gethostbyname`/`gethostbyaddr` (legacy) depending on platform capabilities.
Internationalized Domain Names (IDN)
IDN support with Punycode encoding:
// Check if hostname contains non-ASCII characters
bool DNS::isIDN(const std::string& hostname);
// Check if hostname is Punycode encoded
bool DNS::isEncodedIDN(const std::string& hostname);
// Encode IDN to ASCII-compatible Punycode
std::string DNS::encodeIDN(const std::string& idn);
// Decode Punycode back to Unicode
std::string DNS::decodeIDN(const std::string& encodedIDN);
Punycode encoding example: "münchen.de" → "xn--mnchen-3ya.de"
Punycode Implementation
Complete Punycode encoder/decoder (RFC 3492):
static int punycode_encode(size_t input_length,
const punycode_uint input[],
size_t* output_length,
char output[]);
static int punycode_decode(size_t input_length,
const char input[],
size_t* output_length,
punycode_uint output[]);
Implements the Bootstring algorithm with parameters:
- Base: 36
- Tmin: 1, Tmax: 26
- Skew: 38, Damp: 700
- Initial bias: 72, Initial n: 0x80
Error Handling
DNS-specific exceptions:
// Convert error code to exception
void DNS::error(int code, const std::string& arg);
// Convert getaddrinfo error to exception
void DNS::aierror(int code, const std::string& arg);
// Get last DNS error code
int DNS::lastError();
Exception types:
- `HostNotFoundException`: Host not found
- `NoAddressFoundException`: No address records
- `DNSException`: General DNS errors
- `NotAuthenticatedException`: Authentication required
Thread Safety
Uses read-write lock for resolver access on systems with `libresolv`:
#if defined(POCO_HAVE_LIBRESOLV)
static Poco::RWLock resolverLock;
void DNS::reload()
{
Poco::ScopedWriteRWLock writeLock(resolverLock);
res_init();
}
#endif
Implementation Details
Hostname Resolution Flow
1. Check if input is IP address literal 2. For IDN, encode to Punycode 3. Call platform-specific resolver (`getaddrinfo` or `gethostbyname`) 4. Construct `HostEntry` from results 5. Handle errors with specific exceptions
IDN Encoding Process
1. Split hostname into labels (dot-separated) 2. For each label with non-ASCII:
* Convert UTF-8 to UTF-32 * Lowercase all characters * Apply Punycode encoding * Prefix with "xn--"
3. Reassemble hostname
Punycode Algorithm
Bootstring encoding in O(n²) time:
- Encodes variable-length integers for character positions
- Uses adaptive bias for efficient encoding
- Handles basic (ASCII) code points separately
- Encodes non-basic code points incrementally
Usage Examples
Basic DNS Resolution
// Resolve hostname
HostEntry entry = DNS::hostByName("example.com");
IPAddress ip = entry.addresses()[0];
// Reverse lookup
HostEntry host = DNS::hostByAddress(ip);
std::string name = host.name();
// Get single address
IPAddress addr = DNS::resolveOne("www.example.com");
IDN Handling
// Encode international domain
std::string encoded = DNS::encodeIDN("münchen.de");
// Returns: "xn--mnchen-3ya.de"
// Resolve IDN directly
IPAddress ip = DNS::resolveOne("日本.jp");
Local Host Info
// Get local hostname
std::string name = DNS::hostName();
// Get full host entry
HostEntry local = DNS::thisHost();
Dependencies
- `Poco::Net::IPAddress`: IP address representation
- `Poco::Net::HostEntry`: DNS resolution results
- `Poco::Net::SocketAddress`: Socket address wrapper
- `Poco::Unicode`: Unicode character operations
- `Poco::TextConverter`: Text encoding conversion
- System DNS resolver: `getaddrinfo`/`gethostbyname`
Testing Considerations
- Test with IPv4 and IPv6 addresses
- Verify IDN encoding/decoding round-trip
- Test with various IDN domain names
- Check error handling for non-existent hosts
- Verify thread safety under concurrent access
- Test timeout behavior