25#ifndef JOIN_FABRIC_NAMESERVER_HPP
26#define JOIN_FABRIC_NAMESERVER_HPP
41 template <
typename Protocol>
45 using Socket =
typename Protocol::Socket;
54 ,
_buffer (
std::make_unique<char[]> (Protocol::maxMsgSize))
96 if (
_socket.bind (endpoint) == -1)
124 int reply (
const DnsPacket& query,
const std::vector<ResourceRecord>& answers = {},
125 const std::vector<ResourceRecord>& authorities = {},
126 const std::vector<ResourceRecord>& additionals = {}, uint16_t rcode = 0)
129 packet.id = query.
id;
130 packet.flags = (uint16_t (1) << 15) | (query.
flags & 0x7800) | (uint16_t (1) << 10) | (rcode & 0x000F);
131 packet.dest = query.
src;
132 packet.port = query.
port;
135 packet.answers = answers;
136 packet.authorities = authorities;
137 packet.additionals = additionals;
139 return send (packet);
156 ssize_t size =
_socket.readFrom (
_buffer.get (), Protocol::maxMsgSize, &from);
165 packet.
src = from.ip ();
167 packet.
port = from.port ();
169 if ((packet.
flags & 0x8000) == 0)
183 char buffer[Protocol::maxMsgSize];
190 if (
_socket.writeTo (buffer,
static_cast<size_t> (size), {packet.dest, packet.port}) == -1)
217 template <
typename Protocol>
301 IpAddress maddress = Protocol::multicastAddress (family);
304 if ((this->
_socket.opened () ==
false) && (this->_socket.open (endpoint.protocol ()) == -1))
309 if (this->
_socket.setOption (Socket::ReusePort, 1) == -1)
317 if (this->
_socket.bind (endpoint) == -1)
325 if (endpoint.protocol ().family () == AF_INET6)
328 ::memcpy (&mreq.ipv6mr_multiaddr, maddress.
addr (), maddress.
length ());
330 if (::setsockopt (this->
_socket.handle (), IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof (mreq)) ==
334 lastError = std::error_code (errno, std::generic_category ());
339 if (::setsockopt (this->
_socket.handle (), IPPROTO_IPV6, IPV6_MULTICAST_IF, &
_ifindex,
343 lastError = std::error_code (errno, std::generic_category ());
353 ::memcpy (&mreq.imr_multiaddr, maddress.
addr (), maddress.
length ());
354 mreq.imr_ifindex =
static_cast<int> (
_ifindex);
355 if (::setsockopt (this->
_socket.handle (), IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof (mreq)) == -1)
357 lastError = std::error_code (errno, std::generic_category ());
361 if (::setsockopt (this->
_socket.handle (), IPPROTO_IP, IP_MULTICAST_IF, &mreq, sizeof (mreq)) == -1)
363 lastError = std::error_code (errno, std::generic_category ());
371 if (this->
_socket.setOption (Socket::MulticastLoop, 0) == -1)
390 int probe (
const std::vector<ResourceRecord>& records)
392 if (records.empty ())
403 packet.port = Protocol::defaultPort;
405 for (
auto const& record : records)
408 question.
host = record.host;
411 packet.questions.push_back (question);
413 packet.authorities.push_back (record);
416 return this->
send (packet);
424 int announce (
const std::vector<ResourceRecord>& records)
426 if (records.empty ())
434 packet.flags = (uint16_t (1) << 15) | (uint16_t (1) << 10);
437 packet.port = Protocol::defaultPort;
439 for (
auto const& record : records)
441 packet.answers.push_back (record);
444 return this->
send (packet);
452 int goodbye (
const std::vector<ResourceRecord>& records)
454 if (records.empty ())
462 packet.flags = (uint16_t (1) << 15) | (uint16_t (1) << 10);
465 packet.port = Protocol::defaultPort;
467 for (
auto const& record : records)
471 packet.answers.push_back (
goodbye);
474 return this->
send (packet);
482 int browse (
const std::string& serviceType)
484 if (serviceType.empty ())
495 packet.port = Protocol::defaultPort;
498 question.
host = serviceType;
501 packet.questions.push_back (question);
503 return this->
send (packet);
514 std::chrono::milliseconds timeout = std::chrono::seconds (5))
523 packet.flags = 1 << 8;
526 question.
host = host;
529 packet.questions.push_back (question);
531 if (
query (packet, timeout) == -1)
538 for (
auto const& answer : packet.answers)
540 if (!answer.addr.isWildcard () && (answer.type == question.
type))
542 addresses.push_back (answer.addr);
556 std::chrono::milliseconds timeout = std::chrono::seconds (5))
560 for (
auto const& family : {AF_INET, AF_INET6})
563 addresses.insert (addresses.end (), tmp.begin (), tmp.end ());
577 std::chrono::milliseconds timeout = std::chrono::seconds (5))
610 std::chrono::milliseconds timeout = std::chrono::seconds (5))
619 packet.flags = 1 << 8;
625 packet.questions.push_back (question);
627 if (
query (packet, timeout) == -1)
634 for (
auto const& answer : packet.answers)
638 aliases.insert (answer.name);
675 ssize_t size = this->
_socket.readFrom (this->
_buffer.get (), Protocol::maxMsgSize, &from);
679 if (this->
_message.
deserialize (packet, this->_buffer.get (),
static_cast<size_t> (size)) == -1)
685 packet.
src = from.ip ();
687 packet.
port = from.port ();
689 if ((packet.
flags & 0x8000) == 0)
691 bool unicast =
false;
694 if (q.dnsclass & 0x8000)
716 it->second->packet = packet;
718 it->second->cond.signal ();
732 static void defaultOnSuccess (
const DnsPacket& packet)
734 std::cout << std::endl;
735 std::cout <<
"PEER: " << packet.
dest <<
"#" << packet.
port << std::endl;
737 std::cout << std::endl;
738 std::cout <<
";; QUESTION SECTION: " << std::endl;
739 for (
auto const& question : packet.
questions)
741 std::cout << question.host;
744 std::cout << std::endl;
747 std::cout << std::endl;
748 std::cout <<
";; ANSWER SECTION: " << std::endl;
749 for (
auto const& answer : packet.
answers)
751 std::cout << answer.host;
754 std::cout <<
" " << answer.ttl;
757 std::cout <<
" " << answer.addr;
761 std::cout <<
" " << answer.name;
765 std::cout <<
" " << answer.addr;
767 std::cout << std::endl;
775 static void defaultOnFailure (
const DnsPacket& packet)
777 std::cout << std::endl;
778 std::cout <<
"PEER: " << packet.dest <<
"#" << packet.port << std::endl;
780 std::cout << std::endl;
781 std::cout <<
";; QUESTION SECTION: " << std::endl;
782 for (
auto const& question : packet.questions)
784 std::cout << question.host;
787 std::cout << std::endl;
790 std::cout << std::endl;
791 std::cout << lastError.message () << std::endl;
818 packet.
port = Protocol::defaultPort;
820 char buffer[Protocol::maxMsgSize];
829 auto inserted =
_pending.emplace (packet.
id, std::make_unique<PendingRequest> ());
830 if (!inserted.second)
839 if (this->
_socket.writeTo (buffer,
static_cast<size_t> (size), {packet.dest, packet.port}) == -1)
848 if (!inserted.first->second->cond.timedWait (lock, timeout))
858 auto pendingReq = std::move (inserted.first->second);
864 lastError = pendingReq->ec;
870 packet = std::move (pendingReq->packet);
888 std::unordered_map<uint16_t, std::unique_ptr<PendingRequest>>
_pending;
basic DNS name server over datagram socket.
Definition nameserver.hpp:43
int reply(const DnsPacket &query, const std::vector< ResourceRecord > &answers={}, const std::vector< ResourceRecord > &authorities={}, const std::vector< ResourceRecord > &additionals={}, uint16_t rcode=0)
reply to a DNS query.
Definition nameserver.hpp:124
virtual void close() noexcept
close the socket and unregister from the reactor.
Definition nameserver.hpp:109
typename Protocol::Socket Socket
Definition nameserver.hpp:45
BasicDatagramNameServer(Reactor &reactor=ReactorThread::reactor())
construct the name server instance.
Definition nameserver.hpp:52
DnsMessage _message
DNS message codec.
Definition nameserver.hpp:202
virtual int bind(const Endpoint &endpoint) noexcept
bind the socket to the given endpoint and register with the reactor.
Definition nameserver.hpp:94
BasicDatagramNameServer(const BasicDatagramNameServer &other)=delete
copy constructor.
std::unique_ptr< char[]> _buffer
reception buffer.
Definition nameserver.hpp:211
Reactor & _reactor
event loop reactor.
Definition nameserver.hpp:208
virtual ~BasicDatagramNameServer() noexcept=default
destroy instance.
virtual void onQuery(const DnsPacket &packet)=0
method called when a DNS query is received.
Socket _socket
underlying socket.
Definition nameserver.hpp:205
virtual void onReadable(int fd) override
method called when data are ready to be read on handle.
Definition nameserver.hpp:153
BasicDatagramNameServer & operator=(const BasicDatagramNameServer &other)=delete
copy assignment operator.
BasicDatagramNameServer(BasicDatagramNameServer &&other)=delete
move constructor.
int send(DnsPacket &packet)
serialize and send a DNS packet.
Definition nameserver.hpp:181
static constexpr size_t _headerSize
DNS message header size.
Definition nameserver.hpp:199
typename Protocol::Endpoint Endpoint
Definition nameserver.hpp:46
mDNS peer.
Definition nameserver.hpp:219
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 nameserver.hpp:513
int probe(const std::vector< ResourceRecord > &records)
probe the local network for the presence of a service.
Definition nameserver.hpp:390
typename BasicDatagramNameServer< Protocol >::Socket Socket
Definition nameserver.hpp:221
virtual ~BasicDatagramPeer() noexcept=default
destroy instance.
BasicDatagramPeer(unsigned int ifindex, Reactor &reactor=ReactorThread::reactor())
construct the mDNS peer instance.
Definition nameserver.hpp:238
BasicDatagramPeer(BasicDatagramPeer &&other)=delete
move constructor.
IpAddress resolveAddress(const std::string &host, std::chrono::milliseconds timeout=std::chrono::seconds(5))
resolve host name.
Definition nameserver.hpp:593
BasicDatagramPeer(const BasicDatagramPeer &other)=delete
copy constructor.
virtual void onAnnouncement(const DnsPacket &packet)=0
method called when a DNS query is received.
int browse(const std::string &serviceType)
browse for services on the local network.
Definition nameserver.hpp:482
typename BasicDatagramNameServer< Protocol >::Endpoint Endpoint
Definition nameserver.hpp:222
IpAddress resolveAddress(const std::string &host, int family, std::chrono::milliseconds timeout=std::chrono::seconds(5))
resolve host name using address family.
Definition nameserver.hpp:576
void onReadable(int fd) override final
method called when data are ready to be read on handle.
Definition nameserver.hpp:672
AliasList resolveAllName(const IpAddress &address, std::chrono::milliseconds timeout=std::chrono::seconds(5))
resolve all host address.
Definition nameserver.hpp:609
int query(DnsPacket &packet, std::chrono::milliseconds timeout)
serialize and send a DNS query, waiting for a response.
Definition nameserver.hpp:814
std::unordered_map< uint16_t, std::unique_ptr< PendingRequest > > _pending
synchronous requests indexed by sequence number.
Definition nameserver.hpp:888
std::string resolveName(const IpAddress &address, std::chrono::milliseconds timeout=std::chrono::seconds(5))
resolve host address.
Definition nameserver.hpp:651
DnsNotify onFailure
callback called when a lookup sequence failed.
Definition nameserver.hpp:231
DnsNotify onSuccess
callback called when a lookup sequence succeed.
Definition nameserver.hpp:228
void notify(const DnsNotify &func, const DnsPacket &packet) const noexcept
safe way to notify DNS events.
Definition nameserver.hpp:800
int goodbye(const std::vector< ResourceRecord > &records)
send a goodbye message.
Definition nameserver.hpp:452
BasicDatagramPeer & operator=(const BasicDatagramPeer &other)=delete
copy assignment operator.
BasicDatagramPeer(const std::string &interface, Reactor &reactor=ReactorThread::reactor())
construct the mDNS peer instance.
Definition nameserver.hpp:256
int announce(const std::vector< ResourceRecord > &records)
announce the presence of a service on the local network.
Definition nameserver.hpp:424
int bind(int family) noexcept
bind the socket to specified address family.
Definition nameserver.hpp:299
std::function< void(const DnsPacket &)> DnsNotify
DNS notification callback type.
Definition nameserver.hpp:225
Mutex _syncMutex
protection mutex.
Definition nameserver.hpp:891
unsigned int _ifindex
interface index.
Definition nameserver.hpp:877
IpAddressList resolveAllAddress(const std::string &host, std::chrono::milliseconds timeout=std::chrono::seconds(5))
resolve host name and return all IP addresses found.
Definition nameserver.hpp:555
condition variable class.
Definition condition.hpp:42
DNS message codec.
Definition dns_message.hpp:104
int deserialize(DnsPacket &packet, const char *data, size_t size) const
deserialize a DNS packet from a buffer.
Definition dns_message.hpp:228
static std::string className(uint16_t recordClass)
get record class name.
Definition dns_message.hpp:356
@ A
Definition dns_message.hpp:111
@ PTR
Definition dns_message.hpp:115
@ ANY
Definition dns_message.hpp:120
@ AAAA
Definition dns_message.hpp:118
ssize_t serialize(const DnsPacket &packet, char *data, size_t maxSize) const
serialize a DNS packet into a buffer.
Definition dns_message.hpp:174
static std::error_code decodeError(uint16_t error) noexcept
convert DNS error to system error code.
Definition dns_message.hpp:307
@ IN
Definition dns_message.hpp:128
static std::string typeName(uint16_t recordType)
get record type name.
Definition dns_message.hpp:332
Event handler interface class.
Definition reactor.hpp:51
IPv6, IPv4 address class.
Definition ip_address.hpp:52
socklen_t length() const
get the size in byte of the internal address structure.
Definition ip_address.cpp:1268
const void * addr() const
get the internal address structure.
Definition ip_address.cpp:1259
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:612
Reactor class.
Definition reactor.hpp:159
int delHandler(int fd, bool sync=true) noexcept
delete handler from reactor.
Definition reactor.cpp:156
int addHandler(int fd, EventHandler *handler, bool wantRead=true, bool wantWrite=false, bool sync=true) noexcept
add handler to reactor.
Definition reactor.cpp:101
class owning a mutex for the duration of a scoped block.
Definition mutex.hpp:249
Definition acceptor.hpp:32
std::unordered_set< std::string > AliasList
list of aliases.
Definition dns_message.hpp:45
Type randomize()
create a random number.
Definition utils.hpp:402
std::error_code make_error_code(join::Errc code) noexcept
Create an std::error_code object.
Definition error.cpp:195
std::vector< IpAddress > IpAddressList
List of IP address.
Definition ip_address.hpp:46
pending synchronous request.
Definition nameserver.hpp:881
std::error_code ec
Definition nameserver.hpp:884
DnsPacket packet
Definition nameserver.hpp:883
Condition cond
Definition nameserver.hpp:882
DNS packet.
Definition dns_message.hpp:88
uint16_t id
Definition dns_message.hpp:89
uint16_t flags
Definition dns_message.hpp:90
uint16_t port
Definition dns_message.hpp:93
std::vector< QuestionRecord > questions
Definition dns_message.hpp:94
IpAddress src
Definition dns_message.hpp:91
IpAddress dest
Definition dns_message.hpp:92
std::vector< ResourceRecord > answers
Definition dns_message.hpp:95
question record.
Definition dns_message.hpp:57
std::string host
Definition dns_message.hpp:58
uint16_t type
Definition dns_message.hpp:59
uint16_t dnsclass
Definition dns_message.hpp:60
resource record.
Definition dns_message.hpp:67
uint32_t ttl
Definition dns_message.hpp:68
IpAddress address
Definition tcp_acceptor_test.cpp:35