2018-04-19 13:56:14 +00:00
# include "DNSResolver.h"
2022-09-25 12:06:13 +00:00
# include <Common/CacheBase.h>
2017-08-31 12:55:19 +00:00
# include <Common/Exception.h>
2024-03-03 13:22:40 +00:00
# include <Common/NetException.h>
2019-07-04 10:38:44 +00:00
# include <Common/ProfileEvents.h>
2022-09-25 12:06:13 +00:00
# include <Common/thread_local_rng.h>
2023-04-08 04:47:21 +00:00
# include <Common/logger_useful.h>
2020-06-05 20:53:46 +00:00
# include <Poco/Net/IPAddress.h>
2017-08-31 12:55:19 +00:00
# include <Poco/Net/DNS.h>
2017-08-28 18:39:57 +00:00
# include <Poco/Net/NetException.h>
2017-08-31 12:55:19 +00:00
# include <Poco/NumberParser.h>
2018-03-29 20:21:01 +00:00
# include <atomic>
2018-06-15 13:45:19 +00:00
# include <optional>
2020-06-05 20:53:46 +00:00
# include <string_view>
2024-07-23 09:25:02 +00:00
# include "Common/MultiVersion.h"
2022-09-25 12:06:13 +00:00
# include <unordered_set>
2022-07-08 20:52:14 +00:00
# include "DNSPTRResolverProvider.h"
2017-08-07 17:01:04 +00:00
2019-07-04 10:38:44 +00:00
namespace ProfileEvents
{
2021-11-10 18:15:27 +00:00
extern const Event DNSError ;
2019-07-04 10:38:44 +00:00
}
2020-06-05 20:53:46 +00:00
namespace std
{
template < > struct hash < Poco : : Net : : IPAddress >
{
size_t operator ( ) ( const Poco : : Net : : IPAddress & address ) const noexcept
{
std : : string_view addr ( static_cast < const char * > ( address . addr ( ) ) , address . length ( ) ) ;
std : : hash < std : : string_view > hash_impl ;
return hash_impl ( addr ) ;
}
} ;
}
2017-08-07 17:01:04 +00:00
namespace DB
{
2017-09-01 18:36:03 +00:00
namespace ErrorCodes
{
extern const int BAD_ARGUMENTS ;
2020-06-05 20:53:46 +00:00
extern const int DNS_ERROR ;
2017-09-01 18:36:03 +00:00
}
2022-09-25 12:06:13 +00:00
namespace
{
2017-09-01 18:36:03 +00:00
2017-08-31 12:55:19 +00:00
/// Slightly altered implementation from https://github.com/pocoproject/poco/blob/poco-1.6.1/Net/src/SocketAddress.cpp#L86
2022-09-25 12:06:13 +00:00
void splitHostAndPort ( const std : : string & host_and_port , std : : string & out_host , UInt16 & out_port )
2017-08-31 12:55:19 +00:00
{
String port_str ;
out_host . clear ( ) ;
auto it = host_and_port . begin ( ) ;
auto end = host_and_port . end ( ) ;
if ( * it = = ' [ ' ) /// Try parse case '[<IPv6 or something else>]:<port>'
{
+ + it ;
while ( it ! = end & & * it ! = ' ] ' )
out_host + = * it + + ;
if ( it = = end )
2023-01-23 21:13:58 +00:00
throw Exception ( ErrorCodes : : BAD_ARGUMENTS , " Malformed IPv6 address " ) ;
2017-08-31 12:55:19 +00:00
+ + it ;
}
else /// Case '<IPv4 or domain name or something else>:<port>'
{
while ( it ! = end & & * it ! = ' : ' )
out_host + = * it + + ;
}
if ( it ! = end & & * it = = ' : ' )
{
+ + it ;
while ( it ! = end )
port_str + = * it + + ;
}
else
2023-01-23 21:13:58 +00:00
throw Exception ( ErrorCodes : : BAD_ARGUMENTS , " Missing port number " ) ;
2017-08-31 12:55:19 +00:00
unsigned port ;
if ( Poco : : NumberParser : : tryParseUnsigned ( port_str , port ) & & port < = 0xFFFF )
{
out_port = static_cast < UInt16 > ( port ) ;
}
else
2023-01-23 21:13:58 +00:00
throw Exception ( ErrorCodes : : BAD_ARGUMENTS , " Port must be numeric " ) ;
2017-08-31 12:55:19 +00:00
}
2022-09-25 12:06:13 +00:00
DNSResolver : : IPAddresses hostByName ( const std : : string & host )
2017-08-07 17:01:04 +00:00
{
2020-06-05 20:53:46 +00:00
/// Do not resolve IPv6 (or IPv4) if no local IPv6 (or IPv4) addresses are configured.
/// It should not affect client address checking, since client cannot connect from IPv6 address
/// if server has no IPv6 addresses.
2022-08-22 19:03:25 +00:00
auto flags = Poco : : Net : : DNS : : DNS_HINT_AI_ADDRCONFIG ;
2021-07-15 13:06:25 +00:00
DNSResolver : : IPAddresses addresses ;
try
{
addresses = Poco : : Net : : DNS : : hostByName ( host , flags ) . addresses ( ) ;
}
catch ( const Poco : : Net : : DNSException & e )
{
2024-01-23 17:04:50 +00:00
LOG_WARNING ( getLogger ( " DNSResolver " ) , " Cannot resolve host ({}), error {}: {}. " , host , e . code ( ) , e . name ( ) ) ;
2021-07-15 13:06:25 +00:00
addresses . clear ( ) ;
}
2020-06-05 20:53:46 +00:00
if ( addresses . empty ( ) )
2022-04-06 08:48:12 +00:00
{
ProfileEvents : : increment ( ProfileEvents : : DNSError ) ;
2024-03-03 13:22:40 +00:00
throw DB : : NetException ( ErrorCodes : : DNS_ERROR , " Not found address of host: {} " , host ) ;
2022-04-06 08:48:12 +00:00
}
2020-06-05 20:53:46 +00:00
return addresses ;
}
2022-09-25 12:06:13 +00:00
DNSResolver : : IPAddresses resolveIPAddressImpl ( const std : : string & host )
2022-05-16 21:47:07 +00:00
{
Poco : : Net : : IPAddress ip ;
/// NOTE:
/// - Poco::Net::DNS::resolveOne(host) doesn't work for IP addresses like 127.0.0.2
/// - Poco::Net::IPAddress::tryParse() expect hex string for IPv6 (without brackets)
if ( host . starts_with ( ' [ ' ) )
{
assert ( host . ends_with ( ' ] ' ) ) ;
if ( Poco : : Net : : IPAddress : : tryParse ( host . substr ( 1 , host . size ( ) - 2 ) , ip ) )
return DNSResolver : : IPAddresses ( 1 , ip ) ;
}
else
{
if ( Poco : : Net : : IPAddress : : tryParse ( host , ip ) )
return DNSResolver : : IPAddresses ( 1 , ip ) ;
}
DNSResolver : : IPAddresses addresses = hostByName ( host ) ;
return addresses ;
}
2022-09-25 12:06:13 +00:00
std : : unordered_set < String > reverseResolveImpl ( const Poco : : Net : : IPAddress & address )
2020-06-05 20:53:46 +00:00
{
2022-07-08 20:52:14 +00:00
auto ptr_resolver = DB : : DNSPTRResolverProvider : : get ( ) ;
2022-07-12 17:21:10 +00:00
2022-07-13 12:40:56 +00:00
if ( address . family ( ) = = Poco : : Net : : IPAddress : : Family : : IPv4 )
{
2022-07-12 17:21:10 +00:00
return ptr_resolver - > resolve ( address . toString ( ) ) ;
2022-07-13 12:40:56 +00:00
} else
{
2022-07-12 17:21:10 +00:00
return ptr_resolver - > resolve_v6 ( address . toString ( ) ) ;
}
2017-08-07 17:01:04 +00:00
}
2022-09-25 12:06:13 +00:00
std : : unordered_set < String > reverseResolveWithCache (
CacheBase < Poco : : Net : : IPAddress , std : : unordered_set < std : : string > > & cache , const Poco : : Net : : IPAddress & address )
{
auto [ result , _ ] = cache . getOrSet ( address , [ & address ] ( ) { return std : : make_shared < std : : unordered_set < String > > ( reverseResolveImpl ( address ) ) ; } ) ;
return * result ;
}
Poco : : Net : : IPAddress pickAddress ( const DNSResolver : : IPAddresses & addresses )
{
return addresses . front ( ) ;
}
}
2018-04-19 13:56:14 +00:00
struct DNSResolver : : Impl
2017-08-07 17:01:04 +00:00
{
2022-04-06 08:48:12 +00:00
using HostWithConsecutiveFailures = std : : unordered_map < String , UInt32 > ;
using AddressWithConsecutiveFailures = std : : unordered_map < Poco : : Net : : IPAddress , UInt32 > ;
2022-04-05 11:00:14 +00:00
2024-02-26 20:48:02 +00:00
CacheBase < std : : string , DNSResolver : : CacheEntry > cache_host { 1024 } ;
CacheBase < Poco : : Net : : IPAddress , std : : unordered_set < std : : string > > cache_address { 1024 } ;
2018-03-29 20:21:01 +00:00
2019-06-27 16:28:26 +00:00
std : : mutex drop_mutex ;
std : : mutex update_mutex ;
2018-06-15 13:45:19 +00:00
/// Cached server host name
std : : optional < String > host_name ;
2019-06-27 16:28:26 +00:00
/// Store hosts, which was asked to resolve from last update of DNS cache.
2022-04-05 11:00:14 +00:00
HostWithConsecutiveFailures new_hosts ;
AddressWithConsecutiveFailures new_addresses ;
2019-06-27 16:28:26 +00:00
/// Store all hosts, which was whenever asked to resolve
2022-04-05 11:00:14 +00:00
HostWithConsecutiveFailures known_hosts ;
AddressWithConsecutiveFailures known_addresses ;
2019-06-27 16:28:26 +00:00
2018-03-29 20:21:01 +00:00
/// If disabled, will not make cache lookups, will resolve addresses manually on each call
2018-04-19 13:56:14 +00:00
std : : atomic < bool > disable_cache { false } ;
2017-08-07 17:01:04 +00:00
} ;
2024-07-22 15:28:29 +00:00
struct DNSResolver : : AddressFilter
{
struct DNSFilterSettings
{
2024-07-23 09:25:02 +00:00
bool dns_allow_resolve_names_to_ipv4 { true } ;
bool dns_allow_resolve_names_to_ipv6 { true } ;
2024-07-22 15:28:29 +00:00
} ;
2024-07-23 09:25:02 +00:00
AddressFilter ( ) : settings ( std : : make_unique < DNSFilterSettings > ( ) ) { }
2024-07-22 15:28:29 +00:00
void performAddressFiltering ( DNSResolver : : IPAddresses & addresses )
{
2024-07-23 09:25:02 +00:00
const auto current_settings = settings . get ( ) ;
bool dns_resolve_ipv4 = current_settings - > dns_allow_resolve_names_to_ipv4 ;
bool dns_resolve_ipv6 = current_settings - > dns_allow_resolve_names_to_ipv6 ;
2024-07-22 15:28:29 +00:00
if ( dns_resolve_ipv4 & & dns_resolve_ipv6 )
{
return ;
}
if ( ! dns_resolve_ipv4 & & ! dns_resolve_ipv6 )
{
throw Exception ( ErrorCodes : : BAD_ARGUMENTS , " DNS can't resolve any address, because dns_resolve_ipv6_interfaces and dns_resolve_ipv4_interfaces both are disabled " ) ;
}
2024-07-23 09:25:02 +00:00
std : : erase_if ( addresses , [ dns_resolve_ipv6 , dns_resolve_ipv4 ] ( const Poco : : Net : : IPAddress & address )
{
return ( address . family ( ) = = Poco : : Net : : IPAddress : : IPv6 & & ! dns_resolve_ipv6 )
| | ( address . family ( ) = = Poco : : Net : : IPAddress : : IPv4 & & ! dns_resolve_ipv4 ) ;
} ) ;
2024-07-22 15:28:29 +00:00
}
void setSettings ( bool dns_allow_resolve_names_to_ipv4_ , bool dns_allow_resolve_names_to_ipv6_ )
{
2024-07-23 09:25:02 +00:00
settings . set ( std : : make_unique < DNSFilterSettings > ( dns_allow_resolve_names_to_ipv4_ , dns_allow_resolve_names_to_ipv6_ ) ) ;
2024-07-22 15:28:29 +00:00
}
2024-07-23 09:25:02 +00:00
MultiVersion < DNSFilterSettings > settings ;
2024-07-22 15:28:29 +00:00
} ;
DNSResolver : : DNSResolver ( )
: impl ( std : : make_unique < DNSResolver : : Impl > ( ) )
, addressFilter ( std : : make_unique < DNSResolver : : AddressFilter > ( ) )
, log ( getLogger ( " DNSResolver " ) ) { }
2017-08-07 17:01:04 +00:00
2024-07-22 15:28:29 +00:00
DNSResolver : : IPAddresses DNSResolver : : getResolvedIPAdressessWithFiltering ( const std : : string & host )
{
auto addresses = resolveIPAddressImpl ( host ) ;
addressFilter - > performAddressFiltering ( addresses ) ;
if ( addresses . empty ( ) )
{
ProfileEvents : : increment ( ProfileEvents : : DNSError ) ;
throw DB : : NetException ( ErrorCodes : : DNS_ERROR , " After filtering there are no resolved address for host({}). " , host ) ;
}
return addresses ;
}
DNSResolver : : IPAddresses DNSResolver : : resolveIPAddressWithCache ( const std : : string & host )
{
auto [ result , _ ] = impl - > cache_host . getOrSet ( host , [ & host , this ] ( ) { return std : : make_shared < DNSResolver : : CacheEntry > ( getResolvedIPAdressessWithFiltering ( host ) , std : : chrono : : system_clock : : now ( ) ) ; } ) ;
return result - > addresses ;
}
2017-08-07 17:01:04 +00:00
2018-04-19 13:56:14 +00:00
Poco : : Net : : IPAddress DNSResolver : : resolveHost ( const std : : string & host )
2020-06-05 20:53:46 +00:00
{
2024-03-06 19:28:38 +00:00
return pickAddress ( resolveHostAll ( host ) ) ; // random order -> random pick
2020-06-05 20:53:46 +00:00
}
2024-07-22 15:28:29 +00:00
void DNSResolver : : setFilterSettings ( bool dns_allow_resolve_names_to_ipv4_ , bool dns_allow_resolve_names_to_ipv6_ )
{
addressFilter - > setSettings ( dns_allow_resolve_names_to_ipv4_ , dns_allow_resolve_names_to_ipv6_ ) ;
}
2024-03-06 19:28:38 +00:00
DNSResolver : : IPAddresses DNSResolver : : resolveHostAllInOriginOrder ( const std : : string & host )
2017-08-07 17:01:04 +00:00
{
2019-06-27 16:28:26 +00:00
if ( impl - > disable_cache )
2024-07-22 15:28:29 +00:00
return getResolvedIPAdressessWithFiltering ( host ) ;
2019-06-27 16:28:26 +00:00
addToNewHosts ( host ) ;
2024-07-22 15:28:29 +00:00
return resolveIPAddressWithCache ( host ) ;
2017-08-07 17:01:04 +00:00
}
2024-03-06 19:28:38 +00:00
DNSResolver : : IPAddresses DNSResolver : : resolveHostAll ( const std : : string & host )
{
auto addresses = resolveHostAllInOriginOrder ( host ) ;
std : : shuffle ( addresses . begin ( ) , addresses . end ( ) , thread_local_rng ) ;
return addresses ;
}
2018-04-19 13:56:14 +00:00
Poco : : Net : : SocketAddress DNSResolver : : resolveAddress ( const std : : string & host_and_port )
2017-08-07 17:01:04 +00:00
{
2019-06-27 16:28:26 +00:00
if ( impl - > disable_cache )
return Poco : : Net : : SocketAddress ( host_and_port ) ;
2017-08-31 12:55:19 +00:00
String host ;
UInt16 port ;
splitHostAndPort ( host_and_port , host , port ) ;
2019-06-27 16:28:26 +00:00
addToNewHosts ( host ) ;
2024-07-22 15:28:29 +00:00
return Poco : : Net : : SocketAddress ( pickAddress ( resolveIPAddressWithCache ( host ) ) , port ) ;
2018-03-29 20:21:01 +00:00
}
2018-04-19 13:56:14 +00:00
Poco : : Net : : SocketAddress DNSResolver : : resolveAddress ( const std : : string & host , UInt16 port )
2018-03-29 20:21:01 +00:00
{
2019-06-27 16:28:26 +00:00
if ( impl - > disable_cache )
return Poco : : Net : : SocketAddress ( host , port ) ;
addToNewHosts ( host ) ;
2024-07-22 15:28:29 +00:00
return Poco : : Net : : SocketAddress ( pickAddress ( resolveIPAddressWithCache ( host ) ) , port ) ;
2020-06-05 20:53:46 +00:00
}
2022-05-16 21:47:07 +00:00
std : : vector < Poco : : Net : : SocketAddress > DNSResolver : : resolveAddressList ( const std : : string & host , UInt16 port )
{
if ( Poco : : Net : : IPAddress ip ; Poco : : Net : : IPAddress : : tryParse ( host , ip ) )
return std : : vector < Poco : : Net : : SocketAddress > { { ip , port } } ;
std : : vector < Poco : : Net : : SocketAddress > addresses ;
if ( ! impl - > disable_cache )
addToNewHosts ( host ) ;
2024-07-22 15:28:29 +00:00
std : : vector < Poco : : Net : : IPAddress > ips = impl - > disable_cache ? hostByName ( host ) : resolveIPAddressWithCache ( host ) ;
2022-05-16 21:47:07 +00:00
auto ips_end = std : : unique ( ips . begin ( ) , ips . end ( ) ) ;
2022-05-17 12:31:31 +00:00
addresses . reserve ( ips_end - ips . begin ( ) ) ;
2022-05-16 21:47:07 +00:00
for ( auto ip = ips . begin ( ) ; ip ! = ips_end ; + + ip )
addresses . emplace_back ( * ip , port ) ;
return addresses ;
}
2022-08-29 18:11:39 +00:00
std : : unordered_set < String > DNSResolver : : reverseResolve ( const Poco : : Net : : IPAddress & address )
2020-06-05 20:53:46 +00:00
{
if ( impl - > disable_cache )
return reverseResolveImpl ( address ) ;
addToNewAddresses ( address ) ;
2022-09-25 12:06:13 +00:00
return reverseResolveWithCache ( impl - > cache_address , address ) ;
2017-08-07 17:01:04 +00:00
}
2018-04-19 13:56:14 +00:00
void DNSResolver : : dropCache ( )
2017-08-07 17:01:04 +00:00
{
2023-08-14 16:25:52 +00:00
impl - > cache_host . clear ( ) ;
impl - > cache_address . clear ( ) ;
2018-06-15 13:45:19 +00:00
2019-06-27 16:28:26 +00:00
std : : scoped_lock lock ( impl - > update_mutex , impl - > drop_mutex ) ;
impl - > known_hosts . clear ( ) ;
2020-06-05 20:53:46 +00:00
impl - > known_addresses . clear ( ) ;
2019-06-27 16:28:26 +00:00
impl - > new_hosts . clear ( ) ;
2020-06-05 20:53:46 +00:00
impl - > new_addresses . clear ( ) ;
2018-06-15 13:45:19 +00:00
impl - > host_name . reset ( ) ;
2017-08-07 17:01:04 +00:00
}
2022-09-25 12:06:13 +00:00
void DNSResolver : : removeHostFromCache ( const std : : string & host )
{
impl - > cache_host . remove ( host ) ;
}
2018-04-19 13:56:14 +00:00
void DNSResolver : : setDisableCacheFlag ( bool is_disabled )
2018-03-29 20:21:01 +00:00
{
2018-04-19 13:56:14 +00:00
impl - > disable_cache = is_disabled ;
2018-03-29 20:21:01 +00:00
}
2024-03-10 14:29:18 +00:00
void DNSResolver : : setCacheMaxEntries ( UInt64 cache_max_entries )
2024-02-26 20:48:02 +00:00
{
2024-02-28 23:32:13 +00:00
impl - > cache_address . setMaxSizeInBytes ( cache_max_entries ) ;
impl - > cache_host . setMaxSizeInBytes ( cache_max_entries ) ;
2024-02-26 20:48:02 +00:00
}
2018-06-15 13:45:19 +00:00
String DNSResolver : : getHostName ( )
{
if ( impl - > disable_cache )
return Poco : : Net : : DNS : : hostName ( ) ;
2019-06-27 16:28:26 +00:00
std : : lock_guard lock ( impl - > drop_mutex ) ;
2018-06-15 13:45:19 +00:00
if ( ! impl - > host_name . has_value ( ) )
impl - > host_name . emplace ( Poco : : Net : : DNS : : hostName ( ) ) ;
return * impl - > host_name ;
}
2020-06-05 20:53:46 +00:00
static const String & cacheElemToString ( const String & str ) { return str ; }
static String cacheElemToString ( const Poco : : Net : : IPAddress & addr ) { return addr . toString ( ) ; }
2019-06-27 16:28:26 +00:00
2022-04-05 11:00:14 +00:00
template < typename UpdateF , typename ElemsT >
bool DNSResolver : : updateCacheImpl (
2023-09-21 10:54:09 +00:00
UpdateF & & update_func , // NOLINT(cppcoreguidelines-missing-std-forward)
ElemsT & & elems , // NOLINT(cppcoreguidelines-missing-std-forward)
2022-04-05 11:00:14 +00:00
UInt32 max_consecutive_failures ,
2023-08-14 16:57:40 +00:00
FormatStringHelper < String > notfound_log_msg ,
FormatStringHelper < String > dropped_log_msg )
2020-06-05 20:53:46 +00:00
{
2019-06-27 16:28:26 +00:00
bool updated = false ;
2020-06-05 20:53:46 +00:00
String lost_elems ;
2022-04-05 11:00:14 +00:00
using iterators = typename std : : remove_reference_t < decltype ( elems ) > : : iterator ;
std : : vector < iterators > elements_to_drop ;
for ( auto it = elems . begin ( ) ; it ! = elems . end ( ) ; it + + )
2019-06-27 16:28:26 +00:00
{
try
{
2022-04-05 11:00:14 +00:00
updated | = ( this - > * update_func ) ( it - > first ) ;
it - > second = 0 ;
2019-06-27 16:28:26 +00:00
}
2022-04-05 14:37:53 +00:00
catch ( const DB : : Exception & e )
2019-07-04 10:38:44 +00:00
{
2022-04-05 14:37:53 +00:00
if ( e . code ( ) ! = ErrorCodes : : DNS_ERROR )
{
tryLogCurrentException ( log , __PRETTY_FUNCTION__ ) ;
continue ;
}
2020-06-05 20:53:46 +00:00
if ( ! lost_elems . empty ( ) )
lost_elems + = " , " ;
2022-04-05 11:00:14 +00:00
lost_elems + = cacheElemToString ( it - > first ) ;
if ( max_consecutive_failures )
{
it - > second + + ;
if ( it - > second > = max_consecutive_failures )
elements_to_drop . emplace_back ( it ) ;
}
2019-07-04 10:38:44 +00:00
}
catch ( . . . )
{
2022-04-05 11:00:14 +00:00
tryLogCurrentException ( log , __PRETTY_FUNCTION__ ) ;
2019-07-04 10:38:44 +00:00
}
2019-06-27 16:28:26 +00:00
}
2019-07-04 10:38:44 +00:00
2020-06-05 20:53:46 +00:00
if ( ! lost_elems . empty ( ) )
2023-08-14 16:57:40 +00:00
LOG_INFO ( log , notfound_log_msg . format ( std : : move ( lost_elems ) ) ) ;
2022-04-05 11:00:14 +00:00
if ( elements_to_drop . size ( ) )
{
updated = true ;
String deleted_elements ;
for ( auto it : elements_to_drop )
{
if ( ! deleted_elements . empty ( ) )
deleted_elements + = " , " ;
deleted_elements + = cacheElemToString ( it - > first ) ;
elems . erase ( it ) ;
}
2023-08-14 16:57:40 +00:00
LOG_INFO ( log , dropped_log_msg . format ( std : : move ( deleted_elements ) ) ) ;
2022-04-05 11:00:14 +00:00
}
2019-07-04 10:38:44 +00:00
2019-06-27 16:28:26 +00:00
return updated ;
}
2022-04-05 11:00:14 +00:00
bool DNSResolver : : updateCache ( UInt32 max_consecutive_failures )
2020-06-05 20:53:46 +00:00
{
LOG_DEBUG ( log , " Updating DNS cache " ) ;
{
2020-07-08 14:39:48 +00:00
String updated_host_name = Poco : : Net : : DNS : : hostName ( ) ;
2020-06-05 20:53:46 +00:00
std : : lock_guard lock ( impl - > drop_mutex ) ;
2020-06-07 00:18:54 +00:00
for ( const auto & host : impl - > new_hosts )
2020-06-07 15:17:23 +00:00
impl - > known_hosts . insert ( host ) ;
2020-06-05 20:53:46 +00:00
impl - > new_hosts . clear ( ) ;
2020-06-07 00:18:54 +00:00
for ( const auto & address : impl - > new_addresses )
2020-06-07 15:17:23 +00:00
impl - > known_addresses . insert ( address ) ;
2020-06-05 20:53:46 +00:00
impl - > new_addresses . clear ( ) ;
2020-07-08 14:39:48 +00:00
impl - > host_name . emplace ( updated_host_name ) ;
2020-06-05 20:53:46 +00:00
}
2020-08-08 00:47:03 +00:00
/// FIXME Updating may take a long time because we cannot manage timeouts of getaddrinfo(...) and getnameinfo(...).
2020-06-05 20:53:46 +00:00
/// DROP DNS CACHE will wait on update_mutex (possibly while holding drop_mutex)
std : : lock_guard lock ( impl - > update_mutex ) ;
2022-04-05 11:00:14 +00:00
bool hosts_updated = updateCacheImpl (
& DNSResolver : : updateHost , impl - > known_hosts , max_consecutive_failures , " Cached hosts not found: {} " , " Cached hosts dropped: {} " ) ;
updateCacheImpl (
& DNSResolver : : updateAddress ,
impl - > known_addresses ,
max_consecutive_failures ,
" Cached addresses not found: {} " ,
" Cached addresses dropped: {} " ) ;
2020-06-05 20:53:46 +00:00
LOG_DEBUG ( log , " Updated DNS cache " ) ;
return hosts_updated ;
}
2019-06-27 16:28:26 +00:00
bool DNSResolver : : updateHost ( const String & host )
{
2024-07-22 15:28:29 +00:00
const auto old_value = resolveIPAddressWithCache ( host ) ;
auto new_value = getResolvedIPAdressessWithFiltering ( host ) ;
2022-09-25 12:06:13 +00:00
const bool result = old_value ! = new_value ;
2024-02-26 20:48:02 +00:00
impl - > cache_host . set ( host , std : : make_shared < DNSResolver : : CacheEntry > ( std : : move ( new_value ) , std : : chrono : : system_clock : : now ( ) ) ) ;
2022-09-25 12:06:13 +00:00
return result ;
2019-06-27 16:28:26 +00:00
}
2020-06-05 20:53:46 +00:00
bool DNSResolver : : updateAddress ( const Poco : : Net : : IPAddress & address )
{
2022-09-25 12:06:13 +00:00
const auto old_value = reverseResolveWithCache ( impl - > cache_address , address ) ;
auto new_value = reverseResolveImpl ( address ) ;
const bool result = old_value ! = new_value ;
impl - > cache_address . set ( address , std : : make_shared < std : : unordered_set < String > > ( std : : move ( new_value ) ) ) ;
return result ;
2020-06-05 20:53:46 +00:00
}
2019-06-27 16:28:26 +00:00
void DNSResolver : : addToNewHosts ( const String & host )
{
std : : lock_guard lock ( impl - > drop_mutex ) ;
2022-04-05 11:00:14 +00:00
UInt8 consecutive_failures = 0 ;
impl - > new_hosts . insert ( { host , consecutive_failures } ) ;
2019-06-27 16:28:26 +00:00
}
2020-06-05 20:53:46 +00:00
void DNSResolver : : addToNewAddresses ( const Poco : : Net : : IPAddress & address )
{
std : : lock_guard lock ( impl - > drop_mutex ) ;
2022-04-05 11:00:14 +00:00
UInt8 consecutive_failures = 0 ;
impl - > new_addresses . insert ( { address , consecutive_failures } ) ;
2020-06-05 20:53:46 +00:00
}
2024-02-26 20:48:02 +00:00
std : : vector < std : : pair < std : : string , DNSResolver : : CacheEntry > > DNSResolver : : cacheEntries ( ) const
{
std : : lock_guard lock ( impl - > drop_mutex ) ;
std : : vector < std : : pair < std : : string , DNSResolver : : CacheEntry > > entries ;
for ( auto & [ key , entry ] : impl - > cache_host . dump ( ) )
{
entries . emplace_back ( std : : move ( key ) , * entry ) ;
}
return entries ;
}
2018-04-19 13:56:14 +00:00
DNSResolver : : ~ DNSResolver ( ) = default ;
2017-08-07 17:01:04 +00:00
2019-08-22 03:24:05 +00:00
DNSResolver & DNSResolver : : instance ( )
{
static DNSResolver ret ;
return ret ;
}
2017-08-07 17:01:04 +00:00
}