mirror of
https://github.com/matrix-construct/construct
synced 2024-11-16 15:00:51 +01:00
ircd::net::dns: Add explicit qtype to opts and integrate w/ query stack.
This commit is contained in:
parent
58c7a4885b
commit
95c6f69e5d
6 changed files with 94 additions and 40 deletions
|
@ -48,6 +48,13 @@ namespace ircd::net::dns
|
|||
/// DNS resolution options
|
||||
struct ircd::net::dns::opts
|
||||
{
|
||||
/// Specifies the rfc1035 query type. If this is non-zero a query of this
|
||||
/// type will be made or an exception will be thrown if it is not possible
|
||||
/// to make the query with this type. A zero value means automatic and the
|
||||
/// type will deduced and set internally. To translate a string type like
|
||||
/// "SRV" to the type integer for this value see ircd/rfc1035.h.
|
||||
uint16_t qtype {0};
|
||||
|
||||
/// Overrides the SRV query to make for this resolution. If empty an
|
||||
/// SRV query may still be made from other deductions. This string is
|
||||
/// copied at the start of the resolution. It must be a fully qualified
|
||||
|
|
|
@ -73,11 +73,7 @@ ircd::net::dns::_resolve_ipport(const hostport &hp,
|
|||
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 = {};
|
||||
opts.qtype = 0;
|
||||
|
||||
_resolve__A(hp, opts, [calluser(std::move(calluser))]
|
||||
(std::exception_ptr eptr, const hostport &hp, const rfc1035::record::A &record)
|
||||
|
@ -91,9 +87,25 @@ ircd::net::dns::_resolve_ipport(const hostport &hp,
|
|||
/// the vector with stochastic respect for weighting and priority.
|
||||
void
|
||||
ircd::net::dns::_resolve__SRV(const hostport &hp,
|
||||
const opts &opts,
|
||||
opts opts,
|
||||
callback_SRV_one callback)
|
||||
{
|
||||
static const auto &qtype
|
||||
{
|
||||
rfc1035::qtype.at("SRV")
|
||||
};
|
||||
|
||||
if(unlikely(opts.qtype && opts.qtype != qtype))
|
||||
throw error
|
||||
{
|
||||
"Specified query type '%s' (%u) but user's callback is for SRV records only.",
|
||||
rfc1035::rqtype.at(opts.qtype),
|
||||
opts.qtype
|
||||
};
|
||||
|
||||
if(!opts.qtype)
|
||||
opts.qtype = qtype;
|
||||
|
||||
_resolve__(hp, opts, [callback(std::move(callback))]
|
||||
(std::exception_ptr eptr, const hostport &hp, const vector_view<const rfc1035::record *> rrs)
|
||||
{
|
||||
|
@ -121,9 +133,25 @@ ircd::net::dns::_resolve__SRV(const hostport &hp,
|
|||
/// the vector randomly.
|
||||
void
|
||||
ircd::net::dns::_resolve__A(const hostport &hp,
|
||||
const opts &opts,
|
||||
opts opts,
|
||||
callback_A_one callback)
|
||||
{
|
||||
static const auto &qtype
|
||||
{
|
||||
rfc1035::qtype.at("A")
|
||||
};
|
||||
|
||||
if(unlikely(opts.qtype && opts.qtype != qtype))
|
||||
throw error
|
||||
{
|
||||
"Specified query type '%s' (%u) but user's callback is for A records only.",
|
||||
rfc1035::rqtype.at(opts.qtype),
|
||||
opts.qtype
|
||||
};
|
||||
|
||||
if(!opts.qtype)
|
||||
opts.qtype = qtype;
|
||||
|
||||
_resolve__(hp, opts, [callback(std::move(callback))]
|
||||
(std::exception_ptr eptr, const hostport &hp, const vector_view<const rfc1035::record *> &rrs)
|
||||
{
|
||||
|
@ -150,12 +178,18 @@ ircd::net::dns::_resolve__A(const hostport &hp,
|
|||
/// Fundamental callback with a vector of abstract resource records.
|
||||
void
|
||||
ircd::net::dns::_resolve__(const hostport &hp,
|
||||
const opts &op,
|
||||
const opts &opts,
|
||||
callback cb)
|
||||
{
|
||||
if(op.cache_check)
|
||||
if(cache::get(hp, op, cb))
|
||||
if(unlikely(!opts.qtype))
|
||||
throw error
|
||||
{
|
||||
"A query type is required; not specified; cannot be deduced here."
|
||||
};
|
||||
|
||||
if(opts.cache_check)
|
||||
if(cache::get(hp, opts, cb))
|
||||
return;
|
||||
|
||||
resolver_call(hp, op, std::move(cb));
|
||||
resolver_call(hp, opts, std::move(cb));
|
||||
}
|
||||
|
|
|
@ -17,8 +17,8 @@ namespace ircd::net::dns
|
|||
constexpr const size_t MAX_COUNT {64};
|
||||
|
||||
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__A(const hostport &, opts, callback_A_one);
|
||||
extern "C" void _resolve__SRV(const hostport &, opts, callback_SRV_one);
|
||||
extern "C" void _resolve_ipport(const hostport &, const opts &, callback_ipport_one);
|
||||
}
|
||||
|
||||
|
|
|
@ -178,8 +178,7 @@ ircd::net::dns::cache::_get(const hostport &hp,
|
|||
std::exception_ptr eptr;
|
||||
size_t count{0};
|
||||
|
||||
//TODO: Better deduction
|
||||
if(hp.service || opts.srv) // deduced SRV query
|
||||
if(opts.qtype == 33) // deduced SRV query
|
||||
{
|
||||
assert(!empty(host(hp)));
|
||||
thread_local char srvbuf[512];
|
||||
|
@ -224,7 +223,7 @@ ircd::net::dns::cache::_get(const hostport &hp,
|
|||
++it;
|
||||
}
|
||||
}
|
||||
else // Deduced A query (for now)
|
||||
else if(opts.qtype == 1)
|
||||
{
|
||||
auto &map{cache_A};
|
||||
const auto &key{rstrip(host(hp), '.')};
|
||||
|
|
|
@ -60,20 +60,6 @@ ircd::net::dns::resolver::retry_max
|
|||
// interface
|
||||
//
|
||||
|
||||
void
|
||||
ircd::net::dns::resolver_call(const hostport &hp,
|
||||
const opts &opts,
|
||||
callback &&cb)
|
||||
{
|
||||
if(unlikely(!resolver))
|
||||
throw error
|
||||
{
|
||||
"Cannot resolve '%s': resolver unavailable"
|
||||
};
|
||||
|
||||
(*resolver)(hp, opts, std::move(cb));
|
||||
}
|
||||
|
||||
void
|
||||
ircd::net::dns::resolver_init()
|
||||
{
|
||||
|
@ -88,6 +74,20 @@ ircd::net::dns::resolver_fini()
|
|||
ircd::net::dns::resolver = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
ircd::net::dns::resolver_call(const hostport &hp,
|
||||
const opts &opts,
|
||||
callback &&cb)
|
||||
{
|
||||
if(unlikely(!resolver))
|
||||
throw error
|
||||
{
|
||||
"Cannot resolve '%s': resolver unavailable"
|
||||
};
|
||||
|
||||
(*resolver)(hp, opts, std::move(cb));
|
||||
}
|
||||
|
||||
//
|
||||
// resolver::resolver
|
||||
//
|
||||
|
@ -291,22 +291,34 @@ ircd::net::dns::resolver::operator()(const hostport &hp,
|
|||
ircd::const_buffer
|
||||
ircd::net::dns::resolver::make_query(const mutable_buffer &buf,
|
||||
const tag &tag)
|
||||
const
|
||||
{
|
||||
//TODO: Better deduction
|
||||
if(tag.hp.service || tag.opts.srv)
|
||||
thread_local char hostbuf[512];
|
||||
string_view hoststr;
|
||||
switch(tag.opts.qtype)
|
||||
{
|
||||
thread_local char srvbuf[512];
|
||||
const string_view srvhost
|
||||
case 0: throw error
|
||||
{
|
||||
make_SRV_key(srvbuf, host(tag.hp), tag.opts)
|
||||
"A query type is required to form a question."
|
||||
};
|
||||
|
||||
const rfc1035::question question{srvhost, "SRV"};
|
||||
return rfc1035::make_query(buf, tag.id, question);
|
||||
case 33: // SRV
|
||||
{
|
||||
hoststr = make_SRV_key(hostbuf, host(tag.hp), tag.opts);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
hoststr = host(tag.hp);
|
||||
break;
|
||||
}
|
||||
|
||||
const rfc1035::question question{host(tag.hp), "A"};
|
||||
assert(hoststr);
|
||||
assert(tag.opts.qtype);
|
||||
const rfc1035::question question
|
||||
{
|
||||
hoststr, tag.opts.qtype
|
||||
};
|
||||
|
||||
return rfc1035::make_query(buf, tag.id, question);
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ struct ircd::net::dns::resolver
|
|||
void submit(tag &);
|
||||
|
||||
template<class... A> tag &set_tag(A&&...);
|
||||
const_buffer make_query(const mutable_buffer &buf, const tag &) const;
|
||||
static const_buffer make_query(const mutable_buffer &buf, const tag &);
|
||||
void operator()(const hostport &, const opts &, callback &&);
|
||||
|
||||
bool check_timeout(const uint16_t &id, tag &, const steady_point &expired);
|
||||
|
@ -75,6 +75,8 @@ struct ircd::net::dns::resolver::tag
|
|||
char qbuf[384];
|
||||
|
||||
tag(const hostport &, const dns::opts &, callback &&);
|
||||
tag(tag &&) = delete;
|
||||
tag(const tag &) = delete;
|
||||
};
|
||||
|
||||
inline
|
||||
|
|
Loading…
Reference in a new issue