restrictcommands: cache the parsed restriction list (config_gen-tagged) instead of re-tokenizing every restrictcommand line on every command; clone only the one matched rule so the ext borrow drops before the server is used mutably
This commit is contained in:
parent
cd46cfc49f
commit
d4d3886379
1 changed files with 23 additions and 5 deletions
|
|
@ -15,6 +15,7 @@ use crate::server::{now, Server};
|
||||||
use crate::Uid;
|
use crate::Uid;
|
||||||
|
|
||||||
/// One parsed `restrictcommand` line.
|
/// One parsed `restrictcommand` line.
|
||||||
|
#[derive(Clone)]
|
||||||
struct Restriction {
|
struct Restriction {
|
||||||
command: String, // uppercased
|
command: String, // uppercased
|
||||||
connectdelay: u64,
|
connectdelay: u64,
|
||||||
|
|
@ -95,6 +96,13 @@ fn parse(s: &Server) -> Vec<Restriction> {
|
||||||
out
|
out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parsed restrictions cached against the config generation they were parsed at.
|
||||||
|
#[derive(Default)]
|
||||||
|
struct RestrictCache {
|
||||||
|
gen: u64,
|
||||||
|
rules: Vec<Restriction>,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct RestrictCommands;
|
pub struct RestrictCommands;
|
||||||
|
|
||||||
impl Module for RestrictCommands {
|
impl Module for RestrictCommands {
|
||||||
|
|
@ -113,11 +121,21 @@ impl Module for RestrictCommands {
|
||||||
if srv.conf_all("restrictcommand").is_empty() {
|
if srv.conf_all("restrictcommand").is_empty() {
|
||||||
return ModResult::Passthru;
|
return ModResult::Passthru;
|
||||||
}
|
}
|
||||||
let restrictions = parse(srv);
|
// cache the parsed restrictions (config_gen-tagged); re-parse only on rehash,
|
||||||
let Some(r) = restrictions
|
// not on every command. Clone the one matched rule so the ext borrow drops
|
||||||
.iter()
|
// before we touch the server mutably below.
|
||||||
.find(|r| r.command.eq_ignore_ascii_case(cmd))
|
let gen = srv.config_gen;
|
||||||
else {
|
let stale = srv.ext.get::<RestrictCache>().map(|c| c.gen != gen).unwrap_or(true);
|
||||||
|
if stale {
|
||||||
|
let rules = parse(srv);
|
||||||
|
srv.ext.set(RestrictCache { gen, rules });
|
||||||
|
}
|
||||||
|
let Some(r) = srv.ext.get::<RestrictCache>().and_then(|c| {
|
||||||
|
c.rules
|
||||||
|
.iter()
|
||||||
|
.find(|r| r.command.eq_ignore_ascii_case(cmd))
|
||||||
|
.cloned()
|
||||||
|
}) else {
|
||||||
return ModResult::Passthru;
|
return ModResult::Passthru;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue