25#ifndef JOIN_FABRIC_RESOLVER_HPP
26#define JOIN_FABRIC_RESOLVER_HPP
35#include <unordered_map>
40#include <arpa/nameser.h>
41#include <netinet/in.h>
50 template <
class Protocol>
54 using Socket =
typename Protocol::Socket;
56 using State =
typename Socket::State;
86 ,
_buffer (
std::make_unique<char[]> (Protocol::maxMsgSize))
128 if (Socket::connect (endpoint) == -1)
133 _server = endpoint.hostname ();
136 _server = endpoint.ip ().toString ();
138 _port = endpoint.port ();
140 this->_reactor.addHandler (this->handle (),
this);
153 if (Socket::disconnect () == -1)
169 std::chrono::milliseconds timeout = std::chrono::seconds (5))
178 packet.flags = 1 << 8;
181 question.
host = host;
184 packet.questions.push_back (question);
186 if (
query (packet, timeout) == -1)
193 for (
auto const& answer : packet.answers)
195 if (!answer.addr.isWildcard () && (answer.type == question.
type))
197 addresses.push_back (answer.addr);
216 if (!addresses.empty ())
232 std::chrono::milliseconds timeout = std::chrono::seconds (5))
236 for (
auto const& family : {AF_INET, AF_INET6})
239 addresses.insert (addresses.end (), tmp.begin (), tmp.end ());
255 if (!addresses.empty ())
272 std::chrono::milliseconds timeout = std::chrono::seconds (5))
336 std::chrono::milliseconds timeout = std::chrono::seconds (5))
345 packet.flags = 1 << 8;
351 packet.questions.push_back (question);
353 if (
query (packet, timeout) == -1)
360 for (
auto const& answer : packet.answers)
364 aliases.insert (answer.name);
381 if (!aliases.empty ())
428 std::chrono::milliseconds timeout = std::chrono::seconds (5))
437 packet.flags = 1 << 8;
440 question.
host = host;
443 packet.questions.push_back (question);
445 if (
query (packet, timeout) == -1)
452 for (
auto const& answer : packet.answers)
456 servers.insert (answer.name);
473 if (!servers.empty ())
489 std::chrono::milliseconds timeout = std::chrono::seconds (5))
521 std::chrono::milliseconds timeout = std::chrono::seconds (5))
530 packet.flags = 1 << 8;
533 question.
host = host;
536 packet.questions.push_back (question);
538 if (
query (packet, timeout) == -1)
543 for (
auto const& answer : packet.answers)
564 if (!authority.empty ())
580 std::chrono::milliseconds timeout = std::chrono::seconds (5))
589 packet.flags = 1 << 8;
592 question.
host = host;
595 packet.questions.push_back (question);
597 if (
query (packet, timeout) == -1)
603 for (
auto const& answer : packet.answers)
607 exchangers.insert (answer.name);
625 if (!exchangers.empty ())
641 std::chrono::milliseconds timeout = std::chrono::seconds (5))
674 struct __res_state res;
675 if (res_ninit (&res) == 0)
677 for (
int i = 0; i < res.nscount; ++i)
679 if (res.nsaddr_list[i].sin_family == AF_INET)
681 addressList.emplace_back (&res.nsaddr_list[i].sin_addr, sizeof (
struct in_addr));
684 else if (res._u._ext.nsaddrs[i] !=
nullptr && res._u._ext.nsaddrs[i]->sin6_family == AF_INET6)
686 addressList.emplace_back (&res._u._ext.nsaddrs[i]->sin6_addr, sizeof (
struct in6_addr));
703 struct servent entry, *res;
706 int status = getservbyname_r (service.c_str (),
nullptr, &entry, buffer,
sizeof buffer, &res);
707 if ((status == 0) && (res !=
nullptr))
709 return ntohs (entry.s_port);
722 return !this->connected ();
731 virtual int reconnect (
const Endpoint& endpoint, [[maybe_unused]] std::chrono::milliseconds timeout)
741 if (this->
connect (endpoint) == -1)
758 if (this->_remote.ip ().isWildcard ())
770 this->_remote.ip (ip);
771 this->_remote.port (
_port);
774 packet.
dest = this->_remote.ip ();
775 packet.
port = this->_remote.port ();
782 if (this->
reconnect (endpoint, timeout) == -1)
789 packet.
src = this->localEndpoint ().ip ();
791 std::stringstream data;
799 std::string buffer = data.str ();
800 if (buffer.size () > Protocol::maxMsgSize)
809 auto inserted =
_pending.emplace (packet.
id, std::make_unique<PendingRequest> ());
810 if (!inserted.second)
819 if (this->write (buffer.data (), buffer.size ()) == -1)
828 if (!inserted.first->second->cond.timedWait (lock, timeout))
836 auto pendingReq = std::move (inserted.first->second);
841 lastError = pendingReq->ec;
846 packet = std::move (pendingReq->packet);
858 int size = this->read (
_buffer.get (), Protocol::maxMsgSize);
861 std::stringstream data;
862 data.rdbuf ()->pubsetbuf (
_buffer.get (), size);
866 packet.
src = this->localEndpoint ().ip ();
867 packet.
dest = this->remoteEndpoint ().ip ();
868 packet.
port = this->remoteEndpoint ().port ();
870 if (packet.
flags & 0x8000)
877 it->second->packet = packet;
879 if ((packet.
flags & 0x0200) && it->second->ec == std::error_code{})
883 it->second->cond.signal ();
893 void onClose ([[maybe_unused]]
int fd)
override final
903 static void defaultOnSuccess (
const DnsPacket& packet)
905 std::cout << std::endl;
906 std::cout <<
"SERVER: " << packet.
dest <<
"#" << packet.
port << std::endl;
908 std::cout << std::endl;
909 std::cout <<
";; QUESTION SECTION: " << std::endl;
910 for (
auto const& question : packet.
questions)
912 std::cout << question.host;
915 std::cout << std::endl;
918 std::cout << std::endl;
919 std::cout <<
";; ANSWER SECTION: " << std::endl;
920 for (
auto const& answer : packet.
answers)
922 std::cout << answer.host;
925 std::cout <<
" " << answer.ttl;
928 std::cout <<
" " << answer.addr;
932 std::cout <<
" " << answer.name;
936 std::cout <<
" " << answer.name;
940 std::cout <<
" " << answer.name;
941 std::cout <<
" " << answer.mail;
942 std::cout <<
" " << answer.serial;
943 std::cout <<
" " << answer.refresh;
944 std::cout <<
" " << answer.retry;
945 std::cout <<
" " << answer.expire;
946 std::cout <<
" " << answer.minimum;
950 std::cout <<
" " << answer.name;
954 std::cout <<
" " << answer.mxpref;
955 std::cout <<
" " << answer.name;
959 std::cout <<
" " << answer.addr;
961 std::cout << std::endl;
969 static void defaultOnFailure (
const DnsPacket& packet)
971 std::cout << std::endl;
972 std::cout <<
"SERVER: " << packet.dest <<
"#" << packet.port << std::endl;
974 std::cout << std::endl;
975 std::cout <<
";; QUESTION SECTION: " << std::endl;
976 for (
auto const& question : packet.questions)
978 std::cout << question.host;
981 std::cout << std::endl;
984 std::cout << std::endl;
985 std::cout << lastError.message () << std::endl;
1029 std::unordered_map<uint16_t, std::unique_ptr<PendingRequest>>
_pending;
1038 template <
class Protocol>
1096 if (Socket::connect (endpoint) == -1)
1101 this->
_server = this->_remote.hostname ();
1104 this->_server = this->_remote.ip ().toString ();
1106 this->_port = this->_remote.port ();
1118 if (Socket::connectEncrypted (endpoint) == -1)
1135 if (!Socket::waitEncrypted (timeout))
1152 if (!Socket::waitConnected (timeout))
1157 this->
_server = this->_remote.hostname ();
1160 this->
_server = this->_remote.ip ().toString ();
1162 this->
_port = this->_remote.port ();
1183 virtual int read (
char* data,
unsigned long maxSize)
noexcept override
1185 if (_offset < _frameHeaderSize)
1187 int nread = Socket::read (data + _offset, _frameHeaderSize - _offset);
1198 _offset +=
static_cast<size_t> (nread);
1200 if (_offset < _frameHeaderSize)
1206 _size = ntohs (*
reinterpret_cast<uint16_t*
> (data));
1208 if (_size > maxSize)
1217 int nread = Socket::read (data + (_offset - _frameHeaderSize), _size - (_offset - _frameHeaderSize));
1228 _offset +=
static_cast<size_t> (nread);
1230 if (_offset < (_size + _frameHeaderSize))
1236 int msgLen =
static_cast<int> (_size);
1249 virtual int write (
const char* data,
unsigned long size)
noexcept override
1251 uint16_t msgLength = htons (
static_cast<uint16_t
> (size));
1252 const char* p =
reinterpret_cast<const char*
> (&msgLength);
1253 unsigned long remaining =
sizeof (msgLength);
1255 while (remaining > 0)
1257 int result = Socket::write (p, remaining);
1262 if (this->waitReadyWrite ())
1268 remaining -= result;
1274 while (remaining > 0)
1276 int result = Socket::write (p, remaining);
1281 if (this->waitReadyWrite ())
1287 remaining -= result;
1290 return static_cast<int> (size);
1379 virtual int reconnect (
const Endpoint& endpoint, std::chrono::milliseconds timeout)
override
1391 if (!this->waitDisconnected (timeout.count ()))
1398 this->setAlpnProtocols ({
"dot"});
1419 static constexpr size_t _frameHeaderSize = 2;
basic DNS resolver over datagram socket.
Definition resolver.hpp:52
IpAddress resolveAddress(const std::string &host, std::chrono::milliseconds timeout=std::chrono::seconds(5))
resolve host name.
Definition resolver.hpp:304
static ExchangerList lookupAllMailExchanger(const std::string &host)
resolve all host mail exchanger.
Definition resolver.hpp:619
void notify(const DnsNotify &func, const DnsPacket &packet) const noexcept
safe way to notify DNS events.
Definition resolver.hpp:994
static IpAddressList lookupAllAddress(const std::string &host, int family)
resolve host name using system name servers and return all IP addresses found.
Definition resolver.hpp:210
BasicDatagramResolver(const BasicDatagramResolver &other)=delete
copy constructor.
static IpAddressList lookupAllAddress(const std::string &host)
resolve host name using system name servers and return all IP addresses found.
Definition resolver.hpp:250
Mutex _syncMutex
protection mutex.
Definition resolver.hpp:1032
ExchangerList resolveAllMailExchanger(const std::string &host, std::chrono::milliseconds timeout=std::chrono::seconds(5))
resolve all host mail exchanger.
Definition resolver.hpp:579
virtual int connect(const Endpoint &endpoint) override
make a connection to the given endpoint.
Definition resolver.hpp:126
std::function< void(const DnsPacket &)> DnsNotify
notification callback definition.
Definition resolver.hpp:59
static std::string lookupAuthority(const std::string &host)
resolve host start of authority name server.
Definition resolver.hpp:559
bool needReconnection() noexcept
check if client must reconnect.
Definition resolver.hpp:720
static IpAddressList nameServers() noexcept
get IP address of the currently configured name servers.
Definition resolver.hpp:670
static IpAddress lookupAddress(const std::string &host, int family)
resolve host name using system name servers.
Definition resolver.hpp:288
void onReadable(int fd) override final
method called when data are ready to be read on handle.
Definition resolver.hpp:856
DnsNotify onSuccess
callback called when a lookup sequence succeed.
Definition resolver.hpp:62
BasicDatagramResolver(const std::string &server={}, uint16_t port=Protocol::defaultPort, Reactor &reactor=ReactorThread::reactor())
construct the resolver instance.
Definition resolver.hpp:73
uint16_t _port
remote DNS server port.
Definition resolver.hpp:1012
static std::string lookupMailExchanger(const std::string &host)
resolve host mail exchanger.
Definition resolver.hpp:656
IpAddress resolveAddress(const std::string &host, int family, std::chrono::milliseconds timeout=std::chrono::seconds(5))
resolve host name using address family.
Definition resolver.hpp:271
virtual ~BasicDatagramResolver() noexcept=default
destroy instance.
virtual int reconnect(const Endpoint &endpoint, std::chrono::milliseconds timeout)
reconnect to the remote DNS server.
Definition resolver.hpp:731
typename Protocol::Endpoint Endpoint
Definition resolver.hpp:55
std::string _server
remote DNS server.
Definition resolver.hpp:1009
ServerList resolveAllNameServer(const std::string &host, std::chrono::milliseconds timeout=std::chrono::seconds(5))
resolve all host name server.
Definition resolver.hpp:427
IpAddressList resolveAllAddress(const std::string &host, int family, std::chrono::milliseconds timeout=std::chrono::seconds(5))
resolve host name and return all IP addresses found.
Definition resolver.hpp:168
std::string resolveAuthority(const std::string &host, std::chrono::milliseconds timeout=std::chrono::seconds(5))
resolve host start of authority name server.
Definition resolver.hpp:520
static std::string lookupNameServer(const std::string &host)
resolve host name server.
Definition resolver.hpp:504
BasicDatagramResolver & operator=(const BasicDatagramResolver &other)=delete
copy assignment operator.
typename Socket::State State
Definition resolver.hpp:56
static uint16_t resolveService(const std::string &service) noexcept
resolve service name.
Definition resolver.hpp:701
static IpAddress lookupAddress(const std::string &host)
resolve host name using system name servers.
Definition resolver.hpp:319
static ServerList lookupAllNameServer(const std::string &host)
resolve all host name server.
Definition resolver.hpp:468
virtual int disconnect() override
shutdown the connection.
Definition resolver.hpp:149
std::string resolveName(const IpAddress &address, std::chrono::milliseconds timeout=std::chrono::seconds(5))
resolve host address.
Definition resolver.hpp:396
static std::string lookupName(const IpAddress &address)
resolve host address.
Definition resolver.hpp:411
void onClose(int fd) override final
method called when handle is closed.
Definition resolver.hpp:893
std::string resolveNameServer(const std::string &host, std::chrono::milliseconds timeout=std::chrono::seconds(5))
resolve host name server.
Definition resolver.hpp:488
DnsMessage _message
DNS message codec.
Definition resolver.hpp:1006
std::unique_ptr< char[]> _buffer
reception buffer.
Definition resolver.hpp:1018
AliasList resolveAllName(const IpAddress &address, std::chrono::milliseconds timeout=std::chrono::seconds(5))
resolve all host address.
Definition resolver.hpp:335
static constexpr size_t _headerSize
DNS message header size.
Definition resolver.hpp:1003
int query(DnsPacket &packet, std::chrono::milliseconds timeout)
serialize and send a DNS query, waiting for a response.
Definition resolver.hpp:756
BasicDatagramResolver(BasicDatagramResolver &&other)=delete
move constructor.
typename Protocol::Socket Socket
Definition resolver.hpp:54
std::string resolveMailExchanger(const std::string &host, std::chrono::milliseconds timeout=std::chrono::seconds(5))
resolve host mail exchanger.
Definition resolver.hpp:640
DnsNotify onFailure
callback called when a lookup sequence failed.
Definition resolver.hpp:65
static AliasList lookupAllName(const IpAddress &address)
resolve all host address.
Definition resolver.hpp:376
IpAddressList resolveAllAddress(const std::string &host, std::chrono::milliseconds timeout=std::chrono::seconds(5))
resolve host name and return all IP addresses found.
Definition resolver.hpp:231
Reactor & _reactor
event loop reactor.
Definition resolver.hpp:1015
std::unordered_map< uint16_t, std::unique_ptr< PendingRequest > > _pending
synchronous requests indexed by sequence number.
Definition resolver.hpp:1029
basic DNS resolver over TLS socket (DNS over TLS).
Definition resolver.hpp:1040
static IpAddressList lookupAllAddress(const std::string &host)=delete
resolve host name using system name servers and return all IP addresses found.
static std::string lookupNameServer(const std::string &host)=delete
resolve host name server.
static std::string lookupMailExchanger(const std::string &host)=delete
resolve host mail exchanger.
static std::string lookupAuthority(const std::string &host)=delete
resolve host start of authority name server.
virtual int write(const char *data, unsigned long size) noexcept override
write a framed DoT message (2-byte length prefix).
Definition resolver.hpp:1249
BasicTlsResolver & operator=(const BasicTlsResolver &other)=delete
copy assignment operator.
virtual int connectEncrypted(const Endpoint &endpoint) override
make an encrypted connection to the given endpoint.
Definition resolver.hpp:1116
static IpAddress lookupAddress(const std::string &host)=delete
resolve host name using system name servers.
BasicTlsResolver(const BasicTlsResolver &other)=delete
copy constructor.
virtual void close() noexcept override
close the TLS connection and reset framing state.
Definition resolver.hpp:1170
typename Socket::State State
Definition resolver.hpp:1044
static AliasList lookupAllName(const IpAddress &address)=delete
resolve all host address.
static IpAddressList lookupAllAddress(const std::string &host, int family)=delete
resolve host name using system name servers and return all IP addresses found.
static ExchangerList lookupAllMailExchanger(const std::string &host)=delete
resolve all host mail exchanger.
static std::string lookupName(const IpAddress &address)=delete
resolve host address.
BasicTlsResolver(const std::string &server={}, uint16_t port=Protocol::defaultPort, Reactor &reactor=ReactorThread::reactor())
construct the DoT resolver instance.
Definition resolver.hpp:1052
typename Protocol::Endpoint Endpoint
Definition resolver.hpp:1043
static IpAddress lookupAddress(const std::string &host, int family)=delete
resolve host name using system name servers.
virtual bool waitConnected(int timeout=0) override
block until connected.
Definition resolver.hpp:1150
typename Protocol::Socket Socket
Definition resolver.hpp:1042
static ServerList lookupAllNameServer(const std::string &host)=delete
resolve all host name server.
virtual bool waitEncrypted(int timeout=0) override
wait until TLS handshake is performed or timeout occur (non blocking socket).
Definition resolver.hpp:1133
virtual ~BasicTlsResolver() noexcept=default
destroy instance.
virtual int connect(const Endpoint &endpoint) override
make a connection to the given endpoint.
Definition resolver.hpp:1094
BasicTlsResolver(BasicTlsResolver &&other)=delete
move constructor.
virtual int read(char *data, unsigned long maxSize) noexcept override
read a framed DoT message (2-byte length prefix).
Definition resolver.hpp:1183
condition variable class.
Definition condition.hpp:42
DNS message codec.
Definition dnsmessage.hpp:105
int serialize(const DnsPacket &packet, std::stringstream &data) const
serialize a DNS packet into a byte stream.
Definition dnsmessage.hpp:174
static std::string className(uint16_t recordClass)
get record class name.
Definition dnsmessage.hpp:360
@ A
Definition dnsmessage.hpp:112
@ PTR
Definition dnsmessage.hpp:116
@ SOA
Definition dnsmessage.hpp:115
@ NS
Definition dnsmessage.hpp:113
@ MX
Definition dnsmessage.hpp:117
@ CNAME
Definition dnsmessage.hpp:114
@ AAAA
Definition dnsmessage.hpp:119
int deserialize(DnsPacket &packet, std::stringstream &data) const
deserialize a DNS packet from a byte stream.
Definition dnsmessage.hpp:235
static std::error_code decodeError(uint16_t error) noexcept
convert DNS error to system error code.
Definition dnsmessage.hpp:311
@ IN
Definition dnsmessage.hpp:129
static std::string typeName(uint16_t recordType)
get record type name.
Definition dnsmessage.hpp:336
Event handler interface class.
Definition reactor.hpp:46
IPv6, IPv4 address class.
Definition ipaddress.hpp:51
bool isWildcard() const
check if IP address is a wildcard address.
Definition ipaddress.cpp:1295
static bool isIpAddress(const std::string &address)
check if the specified string is an IP address.
Definition ipaddress.cpp:1376
class used to protect shared data from being simultaneously accessed by multiple threads.
Definition mutex.hpp:37
static Reactor & reactor()
get the global Reactor instance.
Definition reactor.cpp:514
Reactor class.
Definition reactor.hpp:129
int delHandler(int fd, bool sync=true) noexcept
delete handler from reactor.
Definition reactor.cpp:155
int addHandler(int fd, EventHandler *handler, bool wantRead=true, bool wantWrite=false, bool sync=true) noexcept
add handler to reactor.
Definition reactor.cpp:100
class owning a mutex for the duration of a scoped block.
Definition mutex.hpp:246
Definition acceptor.hpp:32
std::unordered_set< std::string > ExchangerList
list of mail exchangers.
Definition dnsmessage.hpp:52
std::unordered_set< std::string > ServerList
list of name servers.
Definition dnsmessage.hpp:49
std::enable_if_t< std::numeric_limits< Type >::is_integer, Type > randomize()
create a random number.
Definition utils.hpp:403
std::unordered_set< std::string > AliasList
list of aliases.
Definition dnsmessage.hpp:46
std::error_code make_error_code(join::Errc code) noexcept
Create an std::error_code object.
Definition error.cpp:150
std::vector< IpAddress > IpAddressList
List of IP address.
Definition ipaddress.hpp:45
pending synchronous request.
Definition resolver.hpp:1022
Condition cond
Definition resolver.hpp:1023
std::error_code ec
Definition resolver.hpp:1025
DnsPacket packet
Definition resolver.hpp:1024
DNS packet.
Definition dnsmessage.hpp:89
uint16_t id
Definition dnsmessage.hpp:90
uint16_t flags
Definition dnsmessage.hpp:91
uint16_t port
Definition dnsmessage.hpp:94
std::vector< QuestionRecord > questions
Definition dnsmessage.hpp:95
IpAddress src
Definition dnsmessage.hpp:92
IpAddress dest
Definition dnsmessage.hpp:93
std::vector< ResourceRecord > answers
Definition dnsmessage.hpp:96
question record.
Definition dnsmessage.hpp:58
std::string host
Definition dnsmessage.hpp:59
uint16_t type
Definition dnsmessage.hpp:60
uint16_t dnsclass
Definition dnsmessage.hpp:61
IpAddress address
Definition tcpacceptor_test.cpp:35
uint16_t port
Definition tcpacceptor_test.cpp:36