0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-06-11 22:48:56 +02:00

ircd::net::dns::cache: Move cache waiter calling out of module.

This commit is contained in:
Jason Volk 2020-04-24 23:35:18 -07:00
parent e08fc4b99f
commit 637b6ecede
3 changed files with 92 additions and 96 deletions

View file

@ -11,12 +11,20 @@
/// (internal) DNS cache
namespace ircd::net::dns::cache
{
struct waiter;
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;
extern ctx::dock dock;
extern ctx::mutex mutex;
extern std::list<waiter> waiting;
bool operator==(const waiter &, const waiter &) noexcept;
bool operator!=(const waiter &, const waiter &) noexcept;
string_view make_type(const mutable_buffer &out, const string_view &);
string_view make_type(const mutable_buffer &out, const uint16_t &);
@ -27,19 +35,6 @@ namespace ircd::net::dns::cache
bool put(const hostport &, const opts &, const uint &code, const string_view &msg = {});
}
/// (internal) DNS cache
namespace ircd::net::dns::cache
{
struct waiter;
bool operator==(const waiter &, const waiter &) noexcept;
bool operator!=(const waiter &, const waiter &) noexcept;
extern std::list<waiter> waiting;
extern ctx::mutex mutex;
extern ctx::dock dock;
}
/// DNS cache result waiter
struct ircd::net::dns::cache::waiter
{
@ -54,4 +49,7 @@ struct ircd::net::dns::cache::waiter
waiter(const waiter &) = delete;
waiter &operator=(waiter &&) = delete;
waiter &operator=(const waiter &) = delete;
static bool call(waiter &, const uint16_t &type, const string_view &tgt, const json::array &rrs);
static size_t call(const uint16_t &type, const string_view &tgt, const json::array &rrs);
};

View file

@ -234,3 +234,79 @@ ircd::net::dns::cache::waiter::waiter(const hostport &hp,
this->opts.proto = {};
assert(this->opts.qtype);
}
/// Note complications due to reentrance and other factors:
/// - This function is invoked from several different places on both the
/// timeout and receive contexts, in addition to any evaluator context.
/// - This function calls back to users making DNS queries, and they may
/// conduct another query in their callback frame -- mid-loop in this
/// function.
size_t
ircd::net::dns::cache::waiter::call(const uint16_t &type,
const string_view &tgt,
const json::array &rrs)
{
const ctx::uninterruptible::nothrow ui;
size_t ret(0), last; do
{
const std::lock_guard lock
{
mutex
};
auto it(begin(waiting));
for(last = ret; it != end(waiting); ++it)
if(call(*it, type, tgt, rrs))
{
it = waiting.erase(it);
++ret;
break;
}
}
while(last < ret);
if(ret)
dock.notify_all();
return ret;
}
bool
ircd::net::dns::cache::waiter::call(waiter &waiter,
const uint16_t &type,
const string_view &tgt,
const json::array &rrs)
try
{
if(tgt != waiter.key)
return false;
if(type != waiter.opts.qtype)
return false;
const hostport &target
{
waiter.opts.qtype == 33?
unmake_SRV_key(waiter.key):
waiter.key,
waiter.port
};
assert(waiter.callback);
waiter.callback(target, rrs);
return true;
}
catch(const std::exception &e)
{
log::critical
{
log, "callback:%p %s,%s :%s",
(const void *)&waiter,
type,
tgt,
e.what(),
};
return true;
}

View file

@ -10,8 +10,6 @@
namespace ircd::net::dns::cache
{
static bool call_waiter(const string_view &, const string_view &, const json::array &, waiter &);
static size_t call_waiters(const string_view &, const string_view &, const json::array &);
static void handle(const m::event &, m::vm::eval &);
static bool put(const string_view &type, const string_view &state_key, const records &rrs);
@ -200,7 +198,7 @@ catch(const http::error &e)
const json::value error_records{&error_value, 1};
const json::strung error{error_records};
call_waiters(type, state_key, error);
waiter::call(rfc1035::qtype.at(lstrip(type, "ircd.dns.rrs.")), state_key, error);
return false;
}
catch(const std::exception &e)
@ -224,7 +222,7 @@ catch(const std::exception &e)
const json::value error_value{error_object};
const json::value error_records{&error_value, 1};
const json::strung error{error_records};
call_waiters(type, state_key, error);
waiter::call(rfc1035::qtype.at(lstrip(type, "ircd.dns.rrs.")), state_key, error);
return false;
}
@ -327,7 +325,7 @@ catch(const http::error &e)
const json::value error_records{&error_value, 1};
const json::strung error{error_records};
call_waiters(type, state_key, error);
waiter::call(rfc1035::qtype.at(lstrip(type, "ircd.dns.rrs.")), state_key, error);
return false;
}
catch(const std::exception &e)
@ -350,7 +348,7 @@ catch(const std::exception &e)
const json::value error_value{error_object};
const json::value error_records{&error_value, 1};
const json::strung error{error_records};
call_waiters(type, state_key, error);
waiter::call(rfc1035::qtype.at(lstrip(type, "ircd.dns.rrs.")), state_key, error);
return false;
}
@ -536,7 +534,7 @@ try
json::get<"content"_>(event).get("")
};
call_waiters(type, state_key, rrs);
waiter::call(rfc1035::qtype.at(lstrip(type, "ircd.dns.rrs.")), state_key, rrs);
}
catch(const std::exception &e)
{
@ -546,82 +544,6 @@ catch(const std::exception &e)
};
}
/// Note complications due to reentrance and other factors:
/// - This function is invoked from several different places on both the
/// timeout and receive contexts, in addition to any evaluator context.
/// - This function calls back to users making DNS queries, and they may
/// conduct another query in their callback frame -- mid-loop in this
/// function.
size_t
ircd::net::dns::cache::call_waiters(const string_view &type,
const string_view &state_key,
const json::array &rrs)
{
const ctx::uninterruptible::nothrow ui;
size_t ret(0), last; do
{
const std::lock_guard lock
{
mutex
};
auto it(begin(waiting));
for(last = ret; it != end(waiting); ++it)
if(call_waiter(type, state_key, rrs, *it))
{
it = waiting.erase(it);
++ret;
break;
}
}
while(last < ret);
if(ret)
dock.notify_all();
return ret;
}
bool
ircd::net::dns::cache::call_waiter(const string_view &type,
const string_view &state_key,
const json::array &rrs,
waiter &waiter)
try
{
if(state_key != waiter.key)
return false;
if(lstrip(type, "ircd.dns.rrs.") != rfc1035::rqtype.at(waiter.opts.qtype))
return false;
const hostport &target
{
waiter.opts.qtype == 33?
unmake_SRV_key(waiter.key):
waiter.key,
waiter.port
};
assert(waiter.callback);
waiter.callback(target, rrs);
return true;
}
catch(const std::exception &e)
{
log::critical
{
log, "callback:%p %s,%s :%s",
(const void *)&waiter,
type,
state_key,
e.what(),
};
return true;
}
//
// cache room creation
//