From cfc76f17775fed38d6ee3fcda39e2fe0fafff54f Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Thu, 3 Oct 2019 10:47:33 -0700 Subject: [PATCH] ircd::net::dns: Move resolver into libircd proper. --- include/ircd/net/asio.h | 1 + include/ircd/net/dns.h | 4 + include/ircd/net/dns_resolver.h | 127 +++++++++++++++++++++++++ ircd/Makefile.am | 2 + ircd/net.cc | 47 ++++++---- {modules => ircd}/net_dns_resolver.cc | 33 +++---- modules/Makefile.am | 3 +- modules/net_dns.h | 128 -------------------------- modules/net_dns_cache.cc | 39 ++++---- 9 files changed, 197 insertions(+), 187 deletions(-) create mode 100644 include/ircd/net/dns_resolver.h rename {modules => ircd}/net_dns_resolver.cc (98%) diff --git a/include/ircd/net/asio.h b/include/ircd/net/asio.h index f9ac9ce57..98916b3b9 100644 --- a/include/ircd/net/asio.h +++ b/include/ircd/net/asio.h @@ -47,6 +47,7 @@ namespace ircd::net #include #include #include +#include namespace ircd { diff --git a/include/ircd/net/dns.h b/include/ircd/net/dns.h index 4d53feacf..40165a6df 100644 --- a/include/ircd/net/dns.h +++ b/include/ircd/net/dns.h @@ -93,6 +93,10 @@ namespace ircd::net::dns::cache { using closure = std::function; + extern conf::item min_ttl; + extern conf::item error_ttl; + extern conf::item nxdomain_ttl; + string_view make_type(const mutable_buffer &out, const string_view &); string_view make_type(const mutable_buffer &out, const uint16_t &); diff --git a/include/ircd/net/dns_resolver.h b/include/ircd/net/dns_resolver.h new file mode 100644 index 000000000..fdb7a14db --- /dev/null +++ b/include/ircd/net/dns_resolver.h @@ -0,0 +1,127 @@ +// Matrix Construct +// +// Copyright (C) Matrix Construct Developers, Authors & Contributors +// Copyright (C) 2016-2018 Jason Volk +// +// 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; + using answers_callback = std::function; + + 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 servers; + static conf::item timeout; + static conf::item send_rate; + static conf::item send_burst; + static conf::item retry_max; + + answers_callback callback; + std::vector 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 tags; // The active requests + steady_point send_last; // Time of last send + std::deque 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 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; +}; diff --git a/ircd/Makefile.am b/ircd/Makefile.am index 78fcdfa22..cf1710e62 100644 --- a/ircd/Makefile.am +++ b/ircd/Makefile.am @@ -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} diff --git a/ircd/net.cc b/ircd/net.cc index cbaebf43a..813ab4b13 100644 --- a/ircd/net.cc +++ b/ircd/net.cc @@ -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> min_ttl + const seconds &min_seconds { - "net_dns", "ircd::net::dns::cache::min_ttl" + cache::min_ttl }; - static mods::import> error_ttl + const seconds &err_seconds { - "net_dns", "ircd::net::dns::cache::error_ttl" + cache::error_ttl }; - const conf::item &min_ttl_item - { - static_cast &>(min_ttl) - }; - - const conf::item &error_ttl_item - { - static_cast &>(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(); } diff --git a/modules/net_dns_resolver.cc b/ircd/net_dns_resolver.cc similarity index 98% rename from modules/net_dns_resolver.cc rename to ircd/net_dns_resolver.cc index 749ec7f40..ba0842e9d 100644 --- a/modules/net_dns_resolver.cc +++ b/ircd/net_dns_resolver.cc @@ -8,24 +8,9 @@ // 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::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) ircd::net::dns::resolver::timeout { @@ -37,14 +22,14 @@ decltype(ircd::net::dns::resolver::send_rate) ircd::net::dns::resolver::send_rate { { "name", "ircd.net.dns.resolver.send_rate" }, - { "default", 60L }, + { "default", 67L }, }; decltype(ircd::net::dns::resolver::send_burst) ircd::net::dns::resolver::send_burst { { "name", "ircd.net.dns.resolver.send_burst" }, - { "default", 8L }, + { "default", 5L }, }; decltype(ircd::net::dns::resolver::retry_max) @@ -54,6 +39,19 @@ ircd::net::dns::resolver::retry_max { "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 // @@ -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) diff --git a/modules/Makefile.am b/modules/Makefile.am index 71fc392db..44253ce79 100644 --- a/modules/Makefile.am +++ b/modules/Makefile.am @@ -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 diff --git a/modules/net_dns.h b/modules/net_dns.h index b5eb84611..2c84b8464 100644 --- a/modules/net_dns.h +++ b/modules/net_dns.h @@ -10,19 +10,6 @@ #include -extern ircd::mapi::header -IRCD_MODULE; - -namespace ircd::net::dns -{ - struct tag; - - using answers = vector_view; - using answers_callback = std::function; - - 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 min_ttl IRCD_MODULE_EXPORT_DATA; - extern conf::item error_ttl IRCD_MODULE_EXPORT_DATA; - extern conf::item nxdomain_ttl IRCD_MODULE_EXPORT_DATA; - extern const m::room::id::buf room_id; extern m::hookfn hook; extern std::list 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 servers; - static conf::item timeout; - static conf::item send_rate; - static conf::item send_burst; - static conf::item retry_max; - - answers_callback callback; - std::vector 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 tags; // The active requests - steady_point send_last; // Time of last send - std::deque 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 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; -}; diff --git a/modules/net_dns_cache.cc b/modules/net_dns_cache.cc index 260ee48e4..e74bf9606 100644 --- a/modules/net_dns_cache.cc +++ b/modules/net_dns_cache.cc @@ -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; }