From 0e6221b8dc8575f817dc7599d70d2f29318961c8 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Mon, 1 Oct 2018 12:46:35 -0700 Subject: [PATCH] ircd::net::dns: Move closure chains out to modules/s_dns; minor reorg. --- ircd/net.cc | 152 +++++++--------------------------- modules/s_dns.cc | 211 ++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 223 insertions(+), 140 deletions(-) diff --git a/ircd/net.cc b/ircd/net.cc index f8ee6121a..3bff91310 100644 --- a/ircd/net.cc +++ b/ircd/net.cc @@ -2908,122 +2908,51 @@ ircd::net::dns::prefetch_A{[] /// intermediate results. void ircd::net::dns::resolve(const hostport &hp, - const opts &opts, - callback_ipport_one callback) + const opts &op, + callback_ipport_one cb) { - //TODO: ip6 - auto calluser{[callback(std::move(callback))] - (std::exception_ptr eptr, const hostport &hp, const uint32_t &ip) + using prototype = void (const hostport &, const opts &, callback_ipport_one); + + static mods::import function { - if(eptr) - return callback(std::move(eptr), hp, {}); + "s_dns", "_resolve_ipport" + }; - if(!ip) - { - static const net::not_found no_record - { - "Host has no A record" - }; - - return callback(std::make_exception_ptr(no_record), hp, {}); - } - - const ipport ipport{ip, port(hp)}; - callback(std::move(eptr), hp, ipport); - }}; - - if(!hp.service) - return resolve(hp, opts, [calluser(std::move(calluser))] - (std::exception_ptr eptr, const hostport &hp, const rfc1035::record::A &record) - { - calluser(std::move(eptr), hp, record.ip4); - }); - - auto srv_opts{opts}; - srv_opts.nxdomain_exceptions = false; - resolve(hp, srv_opts, [opts(opts), calluser(std::move(calluser))] - (std::exception_ptr eptr, hostport hp, const rfc1035::record::SRV &record) - mutable - { - if(eptr) - return calluser(std::move(eptr), hp, 0); - - if(record.port != 0) - hp.port = record.port; - - hp.host = record.tgt?: unmake_SRV_key(hp.host); - - // Have to kill the service name to not run another SRV query now. - hp.service = {}; - opts.srv = {}; - opts.proto = {}; - - net::dns::resolve(hp, opts, [calluser(std::move(calluser))] - (std::exception_ptr eptr, const hostport &hp, const rfc1035::record::A &record) - { - calluser(std::move(eptr), hp, record.ip4); - }); - }); + function(hp, op, std::move(cb)); } /// Convenience callback with a single SRV record which was selected from /// the vector with stochastic respect for weighting and priority. void ircd::net::dns::resolve(const hostport &hp, - const opts &opts, - callback_SRV_one callback) + const opts &op, + callback_SRV_one cb) { - resolve(hp, opts, [callback(std::move(callback))] - (std::exception_ptr eptr, const hostport &hp, const vector_view rrs) + using prototype = void (const hostport &, const opts &, callback_SRV_one); + + static mods::import function { - static const rfc1035::record::SRV empty; + "s_dns", "_resolve__SRV" + }; - if(eptr) - return callback(std::move(eptr), hp, empty); - - //TODO: prng on weight / prio plz - for(size_t i(0); i < rrs.size(); ++i) - { - const auto &rr{*rrs.at(i)}; - if(rr.type != 33) - continue; - - const auto &record(rr.as()); - return callback(std::move(eptr), hp, record); - } - - return callback(std::move(eptr), hp, empty); - }); + function(hp, op, std::move(cb)); } /// Convenience callback with a single A record which was selected from /// the vector randomly. void ircd::net::dns::resolve(const hostport &hp, - const opts &opts, - callback_A_one callback) + const opts &op, + callback_A_one cb) { - resolve(hp, opts, [callback(std::move(callback))] - (std::exception_ptr eptr, const hostport &hp, const vector_view &rrs) + using prototype = void (const hostport &, const opts &, callback_A_one); + + static mods::import function { - static const rfc1035::record::A empty; + "s_dns", "_resolve__A" + }; - if(eptr) - return callback(std::move(eptr), hp, empty); - - //TODO: prng plz - for(size_t i(0); i < rrs.size(); ++i) - { - const auto &rr{*rrs.at(i)}; - if(rr.type != 1) - continue; - - const auto &record(rr.as()); - return callback(std::move(eptr), hp, record); - } - - return callback(std::move(eptr), hp, empty); - }); + function(hp, op, std::move(cb)); } /// Fundamental callback with a vector of abstract resource records. @@ -3031,32 +2960,15 @@ void ircd::net::dns::resolve(const hostport &hp, const opts &op, callback cb) -try { - using prototype = void (const hostport &, const opts &, callback &&); + using prototype = void (const hostport &, const opts &, callback); - static mods::import _resolve_ + static mods::import function { - "s_resolver", "_resolve_" + "s_dns", "_resolve__" }; - if(op.cache_check) - if(cache::get(hp, op, cb)) - return; - - _resolve_(hp, op, std::move(cb)); -} -catch(const mods::unavailable &e) -{ - thread_local char buf[128]; - log::error - { - log, "Unable to resolve '%s' :%s", - string(buf, hp), - e.what() - }; - - throw; + function(hp, op, std::move(cb)); } /// Really assumptional and hacky right now. We're just assuming the SRV @@ -3122,7 +3034,7 @@ try static mods::import function { - "s_dns", "cache__put_error" + "s_dns", "_put_error" }; return function(question, code); @@ -3148,7 +3060,7 @@ try static mods::import function { - "s_dns", "cache__put" + "s_dns", "_put" }; return function(question, answer); @@ -3181,7 +3093,7 @@ try static mods::import function { - "s_dns", "cache__get" + "s_dns", "_get" }; return function(hp, o, cb); @@ -3214,7 +3126,7 @@ ircd::net::dns::cache::for_each(const uint16_t &type, static mods::import function { - "s_dns", "cache__for_each" + "s_dns", "_for_each" }; return function(type, c); diff --git a/modules/s_dns.cc b/modules/s_dns.cc index cece04e3f..29b66482e 100644 --- a/modules/s_dns.cc +++ b/modules/s_dns.cc @@ -8,7 +8,6 @@ // copyright notice and this permission notice is present in all copies. The // full license for this software is available in the LICENSE file. -using namespace ircd::net; using namespace ircd; mapi::header @@ -17,15 +16,187 @@ IRCD_MODULE "Server Domain Names Cache & Modular Components" }; -std::multimap> -cache_A; +namespace ircd::net::dns +{ + extern "C" void _resolve__(const hostport &, const opts &, callback); + extern "C" void _resolve__A(const hostport &, const opts &, callback_A_one); + extern "C" void _resolve__SRV(const hostport &, const opts &, callback_SRV_one); + extern "C" void _resolve_ipport(const hostport &, const opts &, callback_ipport_one); +} -std::multimap> -cache_SRV; +/// Convenience composition with a single ipport callback. This is the result of +/// an automatic chain of queries such as SRV and A/AAAA based on the input and +/// intermediate results. +void +ircd::net::dns::_resolve_ipport(const hostport &hp, + const opts &opts, + callback_ipport_one callback) +{ + //TODO: ip6 + auto calluser{[callback(std::move(callback))] + (std::exception_ptr eptr, const hostport &hp, const uint32_t &ip) + { + if(eptr) + return callback(std::move(eptr), hp, {}); -extern "C" ircd::rfc1035::record * -cache__put_error(const rfc1035::question &question, - const uint &code) + if(!ip) + { + static const net::not_found no_record + { + "Host has no A record" + }; + + return callback(std::make_exception_ptr(no_record), hp, {}); + } + + const ipport ipport{ip, port(hp)}; + callback(std::move(eptr), hp, ipport); + }}; + + if(!hp.service) + return _resolve__A(hp, opts, [calluser(std::move(calluser))] + (std::exception_ptr eptr, const hostport &hp, const rfc1035::record::A &record) + { + calluser(std::move(eptr), hp, record.ip4); + }); + + auto srv_opts{opts}; + srv_opts.nxdomain_exceptions = false; + _resolve__SRV(hp, srv_opts, [opts(opts), calluser(std::move(calluser))] + (std::exception_ptr eptr, hostport hp, const rfc1035::record::SRV &record) + mutable + { + if(eptr) + return calluser(std::move(eptr), hp, 0); + + if(record.port != 0) + hp.port = record.port; + + hp.host = record.tgt?: unmake_SRV_key(hp.host); + + // Have to kill the service name to not run another SRV query now. + hp.service = {}; + opts.srv = {}; + opts.proto = {}; + + _resolve__A(hp, opts, [calluser(std::move(calluser))] + (std::exception_ptr eptr, const hostport &hp, const rfc1035::record::A &record) + { + calluser(std::move(eptr), hp, record.ip4); + }); + }); +} + +/// Convenience callback with a single SRV record which was selected from +/// the vector with stochastic respect for weighting and priority. +void +ircd::net::dns::_resolve__SRV(const hostport &hp, + const opts &opts, + callback_SRV_one callback) +{ + _resolve__(hp, opts, [callback(std::move(callback))] + (std::exception_ptr eptr, const hostport &hp, const vector_view rrs) + { + static const rfc1035::record::SRV empty; + + if(eptr) + return callback(std::move(eptr), hp, empty); + + //TODO: prng on weight / prio plz + for(size_t i(0); i < rrs.size(); ++i) + { + const auto &rr{*rrs.at(i)}; + if(rr.type != 33) + continue; + + const auto &record(rr.as()); + return callback(std::move(eptr), hp, record); + } + + return callback(std::move(eptr), hp, empty); + }); +} + +/// Convenience callback with a single A record which was selected from +/// the vector randomly. +void +ircd::net::dns::_resolve__A(const hostport &hp, + const opts &opts, + callback_A_one callback) +{ + _resolve__(hp, opts, [callback(std::move(callback))] + (std::exception_ptr eptr, const hostport &hp, const vector_view &rrs) + { + static const rfc1035::record::A empty; + + if(eptr) + return callback(std::move(eptr), hp, empty); + + //TODO: prng plz + for(size_t i(0); i < rrs.size(); ++i) + { + const auto &rr{*rrs.at(i)}; + if(rr.type != 1) + continue; + + const auto &record(rr.as()); + return callback(std::move(eptr), hp, record); + } + + return callback(std::move(eptr), hp, empty); + }); +} + +/// Fundamental callback with a vector of abstract resource records. +void +ircd::net::dns::_resolve__(const hostport &hp, + const opts &op, + callback cb) +try +{ + using prototype = void (const hostport &, const opts &, callback &&); + + static mods::import resolver_resolve + { + "s_resolver", "_resolve_" + }; + + if(op.cache_check) + if(cache::get(hp, op, cb)) + return; + + resolver_resolve(hp, op, std::move(cb)); +} +catch(const mods::unavailable &e) +{ + thread_local char buf[128]; + log::error + { + log, "Unable to resolve '%s' :%s", + string(buf, hp), + e.what() + }; + + throw; +} + +namespace ircd::net::dns::cache +{ + std::multimap> + cache_A; + + std::multimap> + cache_SRV; + + extern "C" rfc1035::record *_put(const rfc1035::question &, const rfc1035::answer &); + extern "C" rfc1035::record *_put_error(const rfc1035::question &, const uint &code); + extern "C" bool _get(const hostport &, const opts &, const callback &); + extern "C" bool _for_each(const uint16_t &type, const closure &); +} + +ircd::rfc1035::record * +ircd::net::dns::cache::_put_error(const rfc1035::question &question, + const uint &code) { const auto &host { @@ -81,9 +252,9 @@ cache__put_error(const rfc1035::question &question, return nullptr; } -extern "C" ircd::rfc1035::record * -cache__put(const rfc1035::question &question, - const rfc1035::answer &answer) +ircd::rfc1035::record * +ircd::net::dns::cache::_put(const rfc1035::question &question, + const rfc1035::answer &answer) { const auto &host { @@ -156,10 +327,10 @@ cache__put(const rfc1035::question &question, /// indicates it did not respond and to proceed normally. The response can /// be of a cached successful result, or a cached error. Both will return /// true. -extern "C" bool -cache__get(const hostport &hp, - const dns::opts &opts, - const dns::callback &cb) +bool +ircd::net::dns::cache::_get(const hostport &hp, + const opts &opts, + const callback &cb) { // It's no use putting the result record array on the stack in case this // function is either called from an ircd::ctx or calls back an ircd::ctx. @@ -167,7 +338,7 @@ cache__get(const hostport &hp, // It's better to just force the user to conform here rather than adding // ref counting and other pornographic complications to this cache. const ctx::critical_assertion ca; - thread_local std::array record; + thread_local std::array record; std::exception_ptr eptr; size_t count{0}; @@ -178,7 +349,7 @@ cache__get(const hostport &hp, thread_local char srvbuf[512]; const string_view srvhost { - dns::make_SRV_key(srvbuf, hp, opts) + make_SRV_key(srvbuf, hp, opts) }; auto &map{cache_SRV}; @@ -269,9 +440,9 @@ cache__get(const hostport &hp, return count; } -extern "C" bool -cache__for_each(const uint16_t &type, - const dns::cache::closure &closure) +bool +ircd::net::dns::cache::_for_each(const uint16_t &type, + const closure &closure) { switch(type) {