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/acceptor.h>
#include <ircd/net/acceptor_udp.h>
#include <ircd/net/dns_resolver.h>
namespace ircd
{

View file

@ -93,6 +93,10 @@ namespace ircd::net::dns::cache
{
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 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.cc
libircd_la_SOURCES += net.cc
libircd_la_SOURCES += net_dns_resolver.cc
libircd_la_SOURCES += server.cc
libircd_la_SOURCES += client.cc
libircd_la_SOURCES += resource.cc
@ -193,6 +194,7 @@ magic.lo: AM_CPPFLAGS := @MAGIC_CPPFLAGS@ ${AM_CPPFLAGS}
endif
mods.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}
parse.lo: AM_CPPFLAGS := ${SPIRIT_UNIT_CPPFLAGS} ${AM_CPPFLAGS}
parse.lo: AM_CXXFLAGS := ${SPIRIT_UNIT_CXXFLAGS} ${AM_CXXFLAGS}

View file

@ -4201,6 +4201,27 @@ ircd::net::dns::log
"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
decltype(ircd::net::dns::opts_default)
ircd::net::dns::opts_default;
@ -4322,28 +4343,16 @@ bool
ircd::net::dns::expired(const json::object &rr,
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
{
is_error(rr)?
@ -4359,7 +4368,11 @@ ircd::net::dns::expired(const json::object &rr,
const time_t &rr_ts,
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();
}

View file

@ -8,11 +8,37 @@
// copyright notice and this permission notice is present in all copies. The
// full license for this software is available in the LICENSE file.
#include "net_dns.h"
decltype(ircd::net::dns::resolver_instance)
ircd::net::dns::resolver_instance;
decltype(ircd::net::dns::resolver::timeout)
ircd::net::dns::resolver::timeout
{
{ "name", "ircd.net.dns.resolver.timeout" },
{ "default", 10000L },
};
decltype(ircd::net::dns::resolver::send_rate)
ircd::net::dns::resolver::send_rate
{
{ "name", "ircd.net.dns.resolver.send_rate" },
{ "default", 67L },
};
decltype(ircd::net::dns::resolver::send_burst)
ircd::net::dns::resolver::send_burst
{
{ "name", "ircd.net.dns.resolver.send_burst" },
{ "default", 5L },
};
decltype(ircd::net::dns::resolver::retry_max)
ircd::net::dns::resolver::retry_max
{
{ "name", "ircd.net.dns.resolver.retry_max" },
{ "default", 4L },
};
decltype(ircd::net::dns::resolver::servers)
ircd::net::dns::resolver::servers
{
@ -26,34 +52,6 @@ ircd::net::dns::resolver::servers
}
};
decltype(ircd::net::dns::resolver::timeout)
ircd::net::dns::resolver::timeout
{
{ "name", "ircd.net.dns.resolver.timeout" },
{ "default", 10000L },
};
decltype(ircd::net::dns::resolver::send_rate)
ircd::net::dns::resolver::send_rate
{
{ "name", "ircd.net.dns.resolver.send_rate" },
{ "default", 60L },
};
decltype(ircd::net::dns::resolver::send_burst)
ircd::net::dns::resolver::send_burst
{
{ "name", "ircd.net.dns.resolver.send_burst" },
{ "default", 8L },
};
decltype(ircd::net::dns::resolver::retry_max)
ircd::net::dns::resolver::retry_max
{
{ "name", "ircd.net.dns.resolver.retry_max" },
{ "default", 4L },
};
//
// interface
//
@ -62,7 +60,6 @@ void
ircd::net::dns::resolver_init(answers_callback callback)
{
assert(!ircd::net::dns::resolver_instance);
ircd::net::dns::resolver_instance = new resolver
{
std::move(callback)

View file

@ -40,11 +40,10 @@ AM_LDFLAGS = \
moduledir = @moduledir@
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 += $(AM_CPPFLAGS) @BOOST_CPPFLAGS@
net_dns_la_LDFLAGS = $(AM_LDFLAGS) @BOOST_LDFLAGS@
net_dns_la_LIBADD = $(AM_LIBS) @BOOST_LIBS@
console_la_SOURCES = console.cc
web_root_la_SOURCES = web_root.cc
web_hook_la_SOURCES = web_hook.cc

View file

@ -10,19 +10,6 @@
#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
{
struct waiter;
@ -40,10 +27,6 @@ namespace ircd::net::dns::cache
void fini();
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 m::hookfn<m::vm::eval &> hook;
extern std::list<waiter> waiting;
@ -65,114 +48,3 @@ struct ircd::net::dns::cache::waiter
waiter &operator=(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"
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)
ircd::net::dns::cache::room_id
{
@ -172,7 +151,15 @@ try
rr0.~object();
array.~array();
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;
}
catch(const http::error &e)
@ -297,6 +284,14 @@ try
array.~array();
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()});
return true;
}