0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-11-12 13:01:07 +01:00

ircd::net::dns: Move resolver into libircd proper.

This commit is contained in:
Jason Volk 2019-10-03 10:47:33 -07:00
parent 7e51d5dfca
commit cfc76f1777
9 changed files with 197 additions and 187 deletions

View file

@ -47,6 +47,7 @@ namespace ircd::net
#include <ircd/net/socket.h> #include <ircd/net/socket.h>
#include <ircd/net/acceptor.h> #include <ircd/net/acceptor.h>
#include <ircd/net/acceptor_udp.h> #include <ircd/net/acceptor_udp.h>
#include <ircd/net/dns_resolver.h>
namespace ircd namespace ircd
{ {

View file

@ -93,6 +93,10 @@ namespace ircd::net::dns::cache
{ {
using closure = std::function<bool (const string_view &, const json::object &)>; using closure = std::function<bool (const string_view &, const json::object &)>;
extern conf::item<seconds> min_ttl;
extern conf::item<seconds> error_ttl;
extern conf::item<seconds> nxdomain_ttl;
string_view make_type(const mutable_buffer &out, const string_view &); string_view make_type(const mutable_buffer &out, const string_view &);
string_view make_type(const mutable_buffer &out, const uint16_t &); string_view make_type(const mutable_buffer &out, const uint16_t &);

View file

@ -0,0 +1,127 @@
// Matrix Construct
//
// Copyright (C) Matrix Construct Developers, Authors & Contributors
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice is present in all copies. The
// full license for this software is available in the LICENSE file.
//
// This file is not part of the ircd.h precompiled header because it contains
// boost::asio assets which we cannot forward declare. It is part of the
// ircd/asio.h precompiled header.
//
namespace ircd::net::dns
{
struct tag;
struct resolver extern *resolver_instance;
using answers = vector_view<const rfc1035::answer>;
using answers_callback = std::function<void (std::exception_ptr, const tag &, const answers &)>;
constexpr const size_t MAX_COUNT {64};
uint16_t resolver_call(const hostport &, const opts &);
void resolver_init(answers_callback);
void resolver_fini();
}
struct ircd::net::dns::resolver
{
using header = rfc1035::header;
static conf::item<std::string> servers;
static conf::item<milliseconds> timeout;
static conf::item<milliseconds> send_rate;
static conf::item<size_t> send_burst;
static conf::item<size_t> retry_max;
answers_callback callback;
std::vector<ip::udp::endpoint> server; // The list of active servers
size_t server_next{0}; // Round-robin state to hit servers
ctx::dock dock, done;
ctx::mutex mutex;
std::map<uint16_t, tag> tags; // The active requests
steady_point send_last; // Time of last send
std::deque<uint16_t> sendq; // Queue of frames for rate-limiting
ip::udp::socket ns; // A pollable activity object
// util
void add_server(const ipport &);
void add_server(const string_view &);
void set_servers(const string_view &list);
void set_servers();
// removal (must have lock)
void unqueue(tag &);
void remove(tag &);
decltype(tags)::iterator remove(tag &, const decltype(tags)::iterator &);
void error_one(tag &, const std::exception_ptr &, const bool &remove = true);
void error_one(tag &, const std::system_error &, const bool &remove = true);
void error_all(const std::error_code &, const bool &remove = true);
void cancel_all(const bool &remove = true);
// reception
bool handle_error(const header &, tag &);
void handle_reply(const header &, const const_buffer &body, tag &);
void handle_reply(const ipport &, const header &, const const_buffer &body);
void handle(const ipport &, const mutable_buffer &);
void recv_worker();
ctx::context recv_context;
// submission
void send_query(const ip::udp::endpoint &, tag &);
void queue_query(tag &);
void send_query(tag &);
void submit(tag &);
// timeout
bool check_timeout(const uint16_t &id, tag &, const steady_point &expired);
void check_timeouts(const milliseconds &timeout);
void timeout_worker();
ctx::context timeout_context;
// sendq
void flush(const uint16_t &);
void sendq_work();
void sendq_clear();
void sendq_worker();
ctx::context sendq_context;
template<class... A> tag &set_tag(A&&...);
const_buffer make_query(const mutable_buffer &buf, tag &);
uint16_t operator()(const hostport &, const opts &);
resolver(answers_callback);
~resolver() noexcept;
};
struct ircd::net::dns::tag
{
uint16_t id {0};
hostport hp;
dns::opts opts; // note: invalid after query sent
const_buffer question;
steady_point last {steady_point::min()};
uint8_t tries {0};
uint rcode {0};
ipport server;
char hostbuf[rfc1035::NAME_BUFSIZE];
char qbuf[512];
tag(const hostport &hp, const dns::opts &opts)
:hp{hp}
,opts{opts}
{
this->hp.host = { hostbuf, copy(hostbuf, hp.host) };
this->hp.service = {};
}
tag(tag &&) = delete;
tag(const tag &) = delete;
tag &operator=(tag &&) = delete;
tag &operator=(const tag &) = delete;
};

View file

@ -147,6 +147,7 @@ libircd_la_SOURCES += db_port.cc
libircd_la_SOURCES += db_env.cc libircd_la_SOURCES += db_env.cc
libircd_la_SOURCES += db.cc libircd_la_SOURCES += db.cc
libircd_la_SOURCES += net.cc libircd_la_SOURCES += net.cc
libircd_la_SOURCES += net_dns_resolver.cc
libircd_la_SOURCES += server.cc libircd_la_SOURCES += server.cc
libircd_la_SOURCES += client.cc libircd_la_SOURCES += client.cc
libircd_la_SOURCES += resource.cc libircd_la_SOURCES += resource.cc
@ -193,6 +194,7 @@ magic.lo: AM_CPPFLAGS := @MAGIC_CPPFLAGS@ ${AM_CPPFLAGS}
endif endif
mods.lo: AM_CPPFLAGS := ${ASIO_UNIT_CPPFLAGS} ${AM_CPPFLAGS} mods.lo: AM_CPPFLAGS := ${ASIO_UNIT_CPPFLAGS} ${AM_CPPFLAGS}
net.lo: AM_CPPFLAGS := ${ASIO_UNIT_CPPFLAGS} ${AM_CPPFLAGS} net.lo: AM_CPPFLAGS := ${ASIO_UNIT_CPPFLAGS} ${AM_CPPFLAGS}
net_dns_resolver.lo: AM_CPPFLAGS := ${ASIO_UNIT_CPPFLAGS} ${AM_CPPFLAGS}
openssl.lo: AM_CPPFLAGS := @SSL_CPPFLAGS@ @CRYPTO_CPPFLAGS@ ${AM_CPPFLAGS} openssl.lo: AM_CPPFLAGS := @SSL_CPPFLAGS@ @CRYPTO_CPPFLAGS@ ${AM_CPPFLAGS}
parse.lo: AM_CPPFLAGS := ${SPIRIT_UNIT_CPPFLAGS} ${AM_CPPFLAGS} parse.lo: AM_CPPFLAGS := ${SPIRIT_UNIT_CPPFLAGS} ${AM_CPPFLAGS}
parse.lo: AM_CXXFLAGS := ${SPIRIT_UNIT_CXXFLAGS} ${AM_CXXFLAGS} parse.lo: AM_CXXFLAGS := ${SPIRIT_UNIT_CXXFLAGS} ${AM_CXXFLAGS}

View file

@ -4201,6 +4201,27 @@ ircd::net::dns::log
"net.dns" "net.dns"
}; };
decltype(ircd::net::dns::cache::min_ttl)
ircd::net::dns::cache::min_ttl
{
{ "name", "ircd.net.dns.cache.min_ttl" },
{ "default", 28800L },
};
decltype(ircd::net::dns::cache::error_ttl)
ircd::net::dns::cache::error_ttl
{
{ "name", "ircd.net.dns.cache.error_ttl" },
{ "default", 1200L },
};
decltype(ircd::net::dns::cache::nxdomain_ttl)
ircd::net::dns::cache::nxdomain_ttl
{
{ "name", "ircd.net.dns.cache.nxdomain_ttl" },
{ "default", 86400L },
};
/// Linkage for default opts /// Linkage for default opts
decltype(ircd::net::dns::opts_default) decltype(ircd::net::dns::opts_default)
ircd::net::dns::opts_default; ircd::net::dns::opts_default;
@ -4322,28 +4343,16 @@ bool
ircd::net::dns::expired(const json::object &rr, ircd::net::dns::expired(const json::object &rr,
const time_t &rr_ts) const time_t &rr_ts)
{ {
static mods::import<conf::item<seconds>> min_ttl const seconds &min_seconds
{ {
"net_dns", "ircd::net::dns::cache::min_ttl" cache::min_ttl
}; };
static mods::import<conf::item<seconds>> error_ttl const seconds &err_seconds
{ {
"net_dns", "ircd::net::dns::cache::error_ttl" cache::error_ttl
}; };
const conf::item<seconds> &min_ttl_item
{
static_cast<conf::item<seconds> &>(min_ttl)
};
const conf::item<seconds> &error_ttl_item
{
static_cast<conf::item<seconds> &>(error_ttl)
};
const seconds &min_seconds(min_ttl_item);
const seconds &err_seconds(error_ttl_item);
const time_t &min const time_t &min
{ {
is_error(rr)? is_error(rr)?
@ -4359,7 +4368,11 @@ ircd::net::dns::expired(const json::object &rr,
const time_t &rr_ts, const time_t &rr_ts,
const time_t &min_ttl) const time_t &min_ttl)
{ {
const auto ttl(get_ttl(rr)); const auto &ttl
{
get_ttl(rr)
};
return rr_ts + std::max(ttl, min_ttl) < ircd::time(); return rr_ts + std::max(ttl, min_ttl) < ircd::time();
} }

View file

@ -8,24 +8,9 @@
// copyright notice and this permission notice is present in all copies. The // copyright notice and this permission notice is present in all copies. The
// full license for this software is available in the LICENSE file. // full license for this software is available in the LICENSE file.
#include "net_dns.h"
decltype(ircd::net::dns::resolver_instance) decltype(ircd::net::dns::resolver_instance)
ircd::net::dns::resolver_instance; ircd::net::dns::resolver_instance;
decltype(ircd::net::dns::resolver::servers)
ircd::net::dns::resolver::servers
{
{
{ "name", "ircd.net.dns.resolver.servers" },
{ "default", "4.2.2.1 4.2.2.2 4.2.2.3 4.2.2.4 4.2.2.5 4.2.2.6" },
}, []
{
if(bool(ircd::net::dns::resolver_instance))
ircd::net::dns::resolver_instance->set_servers();
}
};
decltype(ircd::net::dns::resolver::timeout) decltype(ircd::net::dns::resolver::timeout)
ircd::net::dns::resolver::timeout ircd::net::dns::resolver::timeout
{ {
@ -37,14 +22,14 @@ decltype(ircd::net::dns::resolver::send_rate)
ircd::net::dns::resolver::send_rate ircd::net::dns::resolver::send_rate
{ {
{ "name", "ircd.net.dns.resolver.send_rate" }, { "name", "ircd.net.dns.resolver.send_rate" },
{ "default", 60L }, { "default", 67L },
}; };
decltype(ircd::net::dns::resolver::send_burst) decltype(ircd::net::dns::resolver::send_burst)
ircd::net::dns::resolver::send_burst ircd::net::dns::resolver::send_burst
{ {
{ "name", "ircd.net.dns.resolver.send_burst" }, { "name", "ircd.net.dns.resolver.send_burst" },
{ "default", 8L }, { "default", 5L },
}; };
decltype(ircd::net::dns::resolver::retry_max) decltype(ircd::net::dns::resolver::retry_max)
@ -54,6 +39,19 @@ ircd::net::dns::resolver::retry_max
{ "default", 4L }, { "default", 4L },
}; };
decltype(ircd::net::dns::resolver::servers)
ircd::net::dns::resolver::servers
{
{
{ "name", "ircd.net.dns.resolver.servers" },
{ "default", "4.2.2.1 4.2.2.2 4.2.2.3 4.2.2.4 4.2.2.5 4.2.2.6" },
}, []
{
if(bool(ircd::net::dns::resolver_instance))
ircd::net::dns::resolver_instance->set_servers();
}
};
// //
// interface // interface
// //
@ -62,7 +60,6 @@ void
ircd::net::dns::resolver_init(answers_callback callback) ircd::net::dns::resolver_init(answers_callback callback)
{ {
assert(!ircd::net::dns::resolver_instance); assert(!ircd::net::dns::resolver_instance);
ircd::net::dns::resolver_instance = new resolver ircd::net::dns::resolver_instance = new resolver
{ {
std::move(callback) std::move(callback)

View file

@ -40,11 +40,10 @@ AM_LDFLAGS = \
moduledir = @moduledir@ moduledir = @moduledir@
stats_la_SOURCES = stats.cc stats_la_SOURCES = stats.cc
net_dns_la_SOURCES = net_dns.cc net_dns_cache.cc net_dns_resolver.cc net_dns_la_SOURCES = net_dns_cache.cc net_dns.cc
net_dns_la_CPPFLAGS = -include $(top_srcdir)/include/ircd/asio.h net_dns_la_CPPFLAGS = -include $(top_srcdir)/include/ircd/asio.h
net_dns_la_CPPFLAGS += $(AM_CPPFLAGS) @BOOST_CPPFLAGS@ net_dns_la_CPPFLAGS += $(AM_CPPFLAGS) @BOOST_CPPFLAGS@
net_dns_la_LDFLAGS = $(AM_LDFLAGS) @BOOST_LDFLAGS@ net_dns_la_LDFLAGS = $(AM_LDFLAGS) @BOOST_LDFLAGS@
net_dns_la_LIBADD = $(AM_LIBS) @BOOST_LIBS@
console_la_SOURCES = console.cc console_la_SOURCES = console.cc
web_root_la_SOURCES = web_root.cc web_root_la_SOURCES = web_root.cc
web_hook_la_SOURCES = web_hook.cc web_hook_la_SOURCES = web_hook.cc

View file

@ -10,19 +10,6 @@
#include <ircd/asio.h> #include <ircd/asio.h>
extern ircd::mapi::header
IRCD_MODULE;
namespace ircd::net::dns
{
struct tag;
using answers = vector_view<const rfc1035::answer>;
using answers_callback = std::function<void (std::exception_ptr, const tag &, const answers &)>;
constexpr const size_t MAX_COUNT {64};
}
namespace ircd::net::dns::cache namespace ircd::net::dns::cache
{ {
struct waiter; struct waiter;
@ -40,10 +27,6 @@ namespace ircd::net::dns::cache
void fini(); void fini();
void init(); void init();
extern conf::item<seconds> min_ttl IRCD_MODULE_EXPORT_DATA;
extern conf::item<seconds> error_ttl IRCD_MODULE_EXPORT_DATA;
extern conf::item<seconds> nxdomain_ttl IRCD_MODULE_EXPORT_DATA;
extern const m::room::id::buf room_id; extern const m::room::id::buf room_id;
extern m::hookfn<m::vm::eval &> hook; extern m::hookfn<m::vm::eval &> hook;
extern std::list<waiter> waiting; extern std::list<waiter> waiting;
@ -65,114 +48,3 @@ struct ircd::net::dns::cache::waiter
waiter &operator=(waiter &&) = delete; waiter &operator=(waiter &&) = delete;
waiter &operator=(const waiter &) = delete; waiter &operator=(const waiter &) = delete;
}; };
//
// s_dns_resolver.cc
//
namespace ircd::net::dns
{
// Resolver instance
struct resolver extern *resolver_instance;
uint16_t resolver_call(const hostport &, const opts &);
void resolver_init(answers_callback);
void resolver_fini();
}
struct ircd::net::dns::resolver
{
using header = rfc1035::header;
static conf::item<std::string> servers;
static conf::item<milliseconds> timeout;
static conf::item<milliseconds> send_rate;
static conf::item<size_t> send_burst;
static conf::item<size_t> retry_max;
answers_callback callback;
std::vector<ip::udp::endpoint> server; // The list of active servers
size_t server_next{0}; // Round-robin state to hit servers
ctx::dock dock, done;
ctx::mutex mutex;
std::map<uint16_t, tag> tags; // The active requests
steady_point send_last; // Time of last send
std::deque<uint16_t> sendq; // Queue of frames for rate-limiting
ip::udp::socket ns; // A pollable activity object
// util
void add_server(const ipport &);
void add_server(const string_view &);
void set_servers(const string_view &list);
void set_servers();
// removal (must have lock)
void unqueue(tag &);
void remove(tag &);
decltype(tags)::iterator remove(tag &, const decltype(tags)::iterator &);
void error_one(tag &, const std::exception_ptr &, const bool &remove = true);
void error_one(tag &, const std::system_error &, const bool &remove = true);
void error_all(const std::error_code &, const bool &remove = true);
void cancel_all(const bool &remove = true);
// reception
bool handle_error(const header &, tag &);
void handle_reply(const header &, const const_buffer &body, tag &);
void handle_reply(const ipport &, const header &, const const_buffer &body);
void handle(const ipport &, const mutable_buffer &);
void recv_worker();
ctx::context recv_context;
// submission
void send_query(const ip::udp::endpoint &, tag &);
void queue_query(tag &);
void send_query(tag &);
void submit(tag &);
// timeout
bool check_timeout(const uint16_t &id, tag &, const steady_point &expired);
void check_timeouts(const milliseconds &timeout);
void timeout_worker();
ctx::context timeout_context;
// sendq
void flush(const uint16_t &);
void sendq_work();
void sendq_clear();
void sendq_worker();
ctx::context sendq_context;
template<class... A> tag &set_tag(A&&...);
const_buffer make_query(const mutable_buffer &buf, tag &);
uint16_t operator()(const hostport &, const opts &);
resolver(answers_callback);
~resolver() noexcept;
};
struct ircd::net::dns::tag
{
uint16_t id {0};
hostport hp;
dns::opts opts; // note: invalid after query sent
const_buffer question;
steady_point last {steady_point::min()};
uint8_t tries {0};
uint rcode {0};
ipport server;
char hostbuf[rfc1035::NAME_BUFSIZE];
char qbuf[512];
tag(const hostport &hp, const dns::opts &opts)
:hp{hp}
,opts{opts}
{
this->hp.host = { hostbuf, copy(hostbuf, hp.host) };
this->hp.service = {};
}
tag(tag &&) = delete;
tag(const tag &) = delete;
tag &operator=(tag &&) = delete;
tag &operator=(const tag &) = delete;
};

View file

@ -10,27 +10,6 @@
#include "net_dns.h" #include "net_dns.h"
decltype(ircd::net::dns::cache::error_ttl)
ircd::net::dns::cache::error_ttl
{
{ "name", "ircd.net.dns.cache.error_ttl" },
{ "default", 1200L },
};
decltype(ircd::net::dns::cache::nxdomain_ttl)
ircd::net::dns::cache::nxdomain_ttl
{
{ "name", "ircd.net.dns.cache.nxdomain_ttl" },
{ "default", 86400L },
};
decltype(ircd::net::dns::cache::min_ttl)
ircd::net::dns::cache::min_ttl
{
{ "name", "ircd.net.dns.cache.min_ttl" },
{ "default", 28800L },
};
decltype(ircd::net::dns::cache::room_id) decltype(ircd::net::dns::cache::room_id)
ircd::net::dns::cache::room_id ircd::net::dns::cache::room_id
{ {
@ -172,7 +151,15 @@ try
rr0.~object(); rr0.~object();
array.~array(); array.~array();
content.~object(); content.~object();
send(room_id, m::me(), type, state_key, json::object(out.completed())); const m::room room
{
room_id
};
if(unlikely(!exists(room)))
create(room);
send(room, m::me(), type, state_key, json::object(out.completed()));
return true; return true;
} }
catch(const http::error &e) catch(const http::error &e)
@ -297,6 +284,14 @@ try
array.~array(); array.~array();
content.~object(); content.~object();
const m::room room
{
room_id
};
if(unlikely(!exists(room)))
create(room);
send(room_id, m::me(), type, state_key, json::object{out.completed()}); send(room_id, m::me(), type, state_key, json::object{out.completed()});
return true; return true;
} }