mirror of
https://github.com/matrix-construct/construct
synced 2024-06-10 14:08:56 +02:00
ircd:Ⓜ️:vm: Create a conform hook; move checks into conform hookfns.
This commit is contained in:
parent
e501c6434a
commit
197168059b
|
@ -21,8 +21,6 @@ namespace ircd::m
|
|||
bool my(const event &);
|
||||
size_t degree(const event &);
|
||||
string_view membership(const event &);
|
||||
bool check_size(std::nothrow_t, const event &);
|
||||
void check_size(const event &);
|
||||
|
||||
// [GET]
|
||||
bool exists(const id::event &);
|
||||
|
|
|
@ -52,6 +52,7 @@ struct ircd::m::vm::eval
|
|||
|
||||
const vm::opts *opts {&default_opts};
|
||||
const vm::copts *copts {nullptr};
|
||||
event::conforms report;
|
||||
|
||||
uint64_t sequence {0};
|
||||
db::txn *txn {nullptr};
|
||||
|
@ -113,6 +114,9 @@ enum ircd::m::vm::fault
|
|||
/// Evaluation Options
|
||||
struct ircd::m::vm::opts
|
||||
{
|
||||
/// Call conform hooks (detailed behavior can be tweaked below)
|
||||
bool conform {true};
|
||||
|
||||
/// Make fetches or false to bypass fetch stage.
|
||||
bool fetch {true};
|
||||
|
||||
|
|
|
@ -2406,35 +2406,6 @@ ircd::m::exists(const id::event &event_id)
|
|||
return has(column, event_id);
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::check_size(const event &event)
|
||||
{
|
||||
const size_t &event_size
|
||||
{
|
||||
serialized(event)
|
||||
};
|
||||
|
||||
if(event_size > size_t(event::max_size))
|
||||
throw m::BAD_JSON
|
||||
{
|
||||
"Event is %zu bytes which is larger than the maximum %zu bytes",
|
||||
event_size,
|
||||
size_t(event::max_size)
|
||||
};
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::check_size(std::nothrow_t,
|
||||
const event &event)
|
||||
{
|
||||
const size_t &event_size
|
||||
{
|
||||
serialized(event)
|
||||
};
|
||||
|
||||
return event_size <= size_t(event::max_size);
|
||||
}
|
||||
|
||||
ircd::string_view
|
||||
ircd::m::membership(const event &event)
|
||||
{
|
||||
|
|
|
@ -55,6 +55,7 @@ handle_edu(client &client,
|
|||
vmopts.non_conform.set(m::event::conforms::MISSING_ORIGIN_SIGNATURE);
|
||||
vmopts.non_conform.set(m::event::conforms::MISSING_SIGNATURES);
|
||||
vmopts.non_conform.set(m::event::conforms::MISSING_PREV_EVENTS);
|
||||
vmopts.non_conform.set(m::event::conforms::MISSING_AUTH_EVENTS);
|
||||
vmopts.non_conform.set(m::event::conforms::MISSING_PREV_STATE);
|
||||
vmopts.non_conform.set(m::event::conforms::DEPTH_ZERO);
|
||||
m::vm::eval eval
|
||||
|
|
|
@ -8,15 +8,101 @@
|
|||
// 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::m;
|
||||
using namespace ircd;
|
||||
|
||||
mapi::header
|
||||
ircd::mapi::header
|
||||
IRCD_MODULE
|
||||
{
|
||||
"Matrix event library; modular components."
|
||||
};
|
||||
|
||||
namespace ircd::m::vm
|
||||
{
|
||||
extern const m::hookfn<eval &> issue_missing_auth;
|
||||
extern const m::hookfn<eval &> conform_check_origin;
|
||||
extern const m::hookfn<eval &> conform_check_size;
|
||||
extern const m::hookfn<eval &> conform_report;
|
||||
}
|
||||
|
||||
/// Check if an eval with a copts structure (indicating this server is
|
||||
/// creating the event) has an origin set to !my_host().
|
||||
decltype(ircd::m::vm::conform_check_origin)
|
||||
ircd::m::vm::conform_check_origin
|
||||
{
|
||||
{
|
||||
{ "_site", "vm.conform" }
|
||||
},
|
||||
[](const m::event &event, eval &eval)
|
||||
{
|
||||
if(unlikely(eval.copts && !my_host(at<"origin"_>(event))))
|
||||
throw error
|
||||
{
|
||||
fault::GENERAL, "Issuing event for origin: %s", at<"origin"_>(event)
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// Check if an event originating from this server exceeds maximum size.
|
||||
decltype(ircd::m::vm::conform_check_size)
|
||||
ircd::m::vm::conform_check_size
|
||||
{
|
||||
{
|
||||
{ "_site", "vm.conform" },
|
||||
{ "origin", my_host() }
|
||||
},
|
||||
[](const m::event &event, eval &eval)
|
||||
{
|
||||
const size_t &event_size
|
||||
{
|
||||
serialized(event)
|
||||
};
|
||||
|
||||
if(event_size > size_t(event::max_size))
|
||||
throw m::BAD_JSON
|
||||
{
|
||||
"Event is %zu bytes which is larger than the maximum %zu bytes",
|
||||
event_size,
|
||||
size_t(event::max_size)
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// Check if an event originating from this server exceeds maximum size.
|
||||
decltype(ircd::m::vm::conform_report)
|
||||
ircd::m::vm::conform_report
|
||||
{
|
||||
{
|
||||
{ "_site", "vm.conform" }
|
||||
},
|
||||
[](const m::event &event, eval &eval)
|
||||
{
|
||||
assert(eval.opts);
|
||||
auto &opts(*eval.opts);
|
||||
|
||||
// When opts.conformed is set the report is already generated
|
||||
if(opts.conformed)
|
||||
{
|
||||
eval.report = opts.report;
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate the report here.
|
||||
eval.report = event::conforms
|
||||
{
|
||||
event, opts.non_conform.report
|
||||
};
|
||||
|
||||
// When opts.conforming is false a bad report is not an error.
|
||||
if(!opts.conforming)
|
||||
return;
|
||||
|
||||
// Otherwise this will kill the eval
|
||||
if(!eval.report.clean())
|
||||
throw error
|
||||
{
|
||||
fault::INVALID, "Non-conforming event: %s", string(eval.report)
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
std::ostream &
|
||||
IRCD_MODULE_EXPORT
|
||||
ircd::m::pretty(std::ostream &s,
|
||||
|
|
|
@ -25,9 +25,10 @@ namespace ircd::m::vm
|
|||
static void init();
|
||||
static void fini();
|
||||
|
||||
extern hook::site<eval &> issue_hook; ///< Called when this server issues event
|
||||
extern hook::site<eval &> issue_hook; ///< Called when this server is issuing event
|
||||
extern hook::site<eval &> conform_hook; ///< Called for static evaluations of event
|
||||
extern hook::site<eval &> fetch_hook; ///< Called to resolve dependencies
|
||||
extern hook::site<eval &> eval_hook; ///< Called when evaluating event
|
||||
extern hook::site<eval &> eval_hook; ///< Called for final event evaluation
|
||||
extern hook::site<eval &> post_hook; ///< Called to apply effects pre-notify
|
||||
extern hook::site<eval &> notify_hook; ///< Called to broadcast successful eval
|
||||
extern hook::site<eval &> effect_hook; ///< Called to apply effects post-notify
|
||||
|
@ -63,6 +64,12 @@ ircd::m::vm::issue_hook
|
|||
{ "name", "vm.issue" }
|
||||
};
|
||||
|
||||
decltype(ircd::m::vm::conform_hook)
|
||||
ircd::m::vm::conform_hook
|
||||
{
|
||||
{ "name", "vm.conform" }
|
||||
};
|
||||
|
||||
decltype(ircd::m::vm::fetch_hook)
|
||||
ircd::m::vm::fetch_hook
|
||||
{
|
||||
|
@ -448,47 +455,23 @@ try
|
|||
assert(eval.event_);
|
||||
assert(eval.id);
|
||||
assert(eval.ctx);
|
||||
|
||||
const auto &opts
|
||||
{
|
||||
*eval.opts
|
||||
};
|
||||
|
||||
if(eval.copts)
|
||||
{
|
||||
if(unlikely(!my_host(at<"origin"_>(event))))
|
||||
throw error
|
||||
{
|
||||
fault::GENERAL, "Committing event for origin: %s", at<"origin"_>(event)
|
||||
};
|
||||
|
||||
if(eval.copts->debuglog_precommit)
|
||||
log::debug
|
||||
{
|
||||
log, "Injecting event %s", pretty_oneline(event)
|
||||
};
|
||||
|
||||
check_size(event);
|
||||
|
||||
if(eval.copts->issue)
|
||||
issue_hook(event, eval);
|
||||
}
|
||||
|
||||
event::conforms report
|
||||
{
|
||||
opts.conforming && !opts.conformed?
|
||||
event::conforms{event, opts.non_conform.report}:
|
||||
opts.report
|
||||
};
|
||||
|
||||
report.del(event::conforms::MISSING_AUTH_EVENTS);
|
||||
|
||||
if(opts.conforming && !report.clean())
|
||||
throw error
|
||||
if(eval.copts && eval.copts->debuglog_precommit)
|
||||
log::debug
|
||||
{
|
||||
fault::INVALID, "Non-conforming event: %s", string(report)
|
||||
log, "Issuing: %s", pretty_oneline(event)
|
||||
};
|
||||
|
||||
if(eval.copts && eval.copts->issue)
|
||||
issue_hook(event, eval);
|
||||
|
||||
if(opts.conform)
|
||||
conform_hook(event, eval);
|
||||
|
||||
// A conforming (with lots of masks) event without an event_id is an EDU.
|
||||
const fault ret
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue