mirror of
https://github.com/matrix-construct/construct
synced 2024-11-29 10:12:39 +01:00
ircd:Ⓜ️:homeserver: Refactor conf related; patch self:: related; console cmds.
This commit is contained in:
parent
08ea932c59
commit
6f798df65c
6 changed files with 497 additions and 522 deletions
|
@ -43,6 +43,7 @@ struct ircd::m::homeserver
|
|||
struct key;
|
||||
struct cert;
|
||||
struct opts;
|
||||
struct conf;
|
||||
|
||||
/// Internal state; use m::my().
|
||||
static homeserver *primary;
|
||||
|
@ -60,6 +61,9 @@ struct ircd::m::homeserver
|
|||
/// a user representing the server.
|
||||
m::user::id::buf self;
|
||||
|
||||
/// Configuration
|
||||
std::unique_ptr<struct conf> conf;
|
||||
|
||||
/// Loaded modules.
|
||||
std::list<ircd::module> modules;
|
||||
|
||||
|
@ -91,15 +95,33 @@ struct ircd::m::homeserver::key
|
|||
/// Current ed25519:ident string
|
||||
std::string public_key_id;
|
||||
|
||||
key(const string_view &origin);
|
||||
key(const struct opts &);
|
||||
key() = default;
|
||||
};
|
||||
|
||||
struct ircd::m::homeserver::cert
|
||||
struct ircd::m::homeserver::conf
|
||||
{
|
||||
std::string tls_private_key_path;
|
||||
std::string tls_public_key_path;
|
||||
std::string tls_cert_path;
|
||||
/// !conf:origin
|
||||
m::room::id::buf room_id;
|
||||
|
||||
/// Convenience
|
||||
m::room room;
|
||||
|
||||
/// Register the conf item init callback //TODO: XXX
|
||||
decltype(ircd::conf::on_init)::callback item_init;
|
||||
|
||||
/// Register the !conf room item message hook.
|
||||
hookfn<vm::eval &> conf_updated;
|
||||
|
||||
// Interface
|
||||
bool get(const string_view &key, const std::function<void (const string_view &)> &) const;
|
||||
event::id::buf set(const string_view &key, const string_view &val) const;
|
||||
|
||||
size_t defaults(const string_view &prefix = {}) const;
|
||||
size_t load(const string_view &prefix = {}) const;
|
||||
size_t store(const string_view &prefix = {}, const bool &force = false) const;
|
||||
|
||||
conf(const struct opts &);
|
||||
};
|
||||
|
||||
struct ircd::m::homeserver::opts
|
||||
|
|
|
@ -18,9 +18,7 @@ namespace ircd::m::self
|
|||
|
||||
// Similar to my_host(), but the comparison is relaxed to allow port
|
||||
// numbers to be a factor: myself.com:8448 input will match if a homeserver
|
||||
// here has a network_name of myself.com. OTOH, myself.com:1234 (i.e some
|
||||
// non-canonical port) can only match a homeserver here with the explicit
|
||||
// name of myself.com:1234.
|
||||
// here has a network_name of myself.com.
|
||||
bool host(const string_view &);
|
||||
|
||||
// Alias for origin(my()); primary homeserver's network name
|
||||
|
|
|
@ -120,7 +120,6 @@ libircd_matrix_la_SOURCES += sync.cc
|
|||
libircd_matrix_la_SOURCES += typing.cc
|
||||
libircd_matrix_la_SOURCES += users.cc
|
||||
libircd_matrix_la_SOURCES += users_servers.cc
|
||||
libircd_matrix_la_SOURCES += conf.cc
|
||||
libircd_matrix_la_SOURCES += error.cc
|
||||
libircd_matrix_la_SOURCES += filter.cc
|
||||
libircd_matrix_la_SOURCES += txn.cc
|
||||
|
|
357
matrix/conf.cc
357
matrix/conf.cc
|
@ -1,357 +0,0 @@
|
|||
// Matrix Construct
|
||||
//
|
||||
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
||||
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice is present in all copies. The
|
||||
// full license for this software is available in the LICENSE file.
|
||||
|
||||
namespace ircd::m
|
||||
{
|
||||
struct conf_room;
|
||||
}
|
||||
|
||||
using namespace ircd;
|
||||
|
||||
extern "C" void default_conf(const string_view &prefix);
|
||||
extern "C" void rehash_conf(const string_view &prefix, const bool &existing);
|
||||
extern "C" void reload_conf();
|
||||
extern "C" void refresh_conf();
|
||||
static void init_conf_item(conf::item<> &);
|
||||
|
||||
struct ircd::m::conf_room
|
||||
{
|
||||
m::room::id::buf room_id
|
||||
{
|
||||
"conf", my_host()
|
||||
};
|
||||
|
||||
m::room room
|
||||
{
|
||||
room_id
|
||||
};
|
||||
|
||||
operator const m::room &() const
|
||||
{
|
||||
return room;
|
||||
}
|
||||
};
|
||||
|
||||
// This module registers with conf::on_init to be called back
|
||||
// when a conf item is initialized; when this module is unloaded
|
||||
// we have to unregister that listener using this state.
|
||||
decltype(conf::on_init)::const_iterator
|
||||
conf_on_init_iter
|
||||
{
|
||||
end(conf::on_init)
|
||||
};
|
||||
|
||||
void conf_on_init()
|
||||
{
|
||||
conf_on_init_iter = conf::on_init.emplace(end(conf::on_init), init_conf_item);
|
||||
reload_conf();
|
||||
}
|
||||
|
||||
void conf_on_fini()
|
||||
{
|
||||
assert(conf_on_init_iter != end(conf::on_init));
|
||||
conf::on_init.erase(conf_on_init_iter);
|
||||
}
|
||||
|
||||
/// Set to false to quiet errors from a conf item failing to set
|
||||
bool
|
||||
item_error_log
|
||||
{
|
||||
true
|
||||
};
|
||||
|
||||
extern "C" m::event::id::buf
|
||||
set_conf_item(const m::user::id &sender,
|
||||
const string_view &key,
|
||||
const string_view &val)
|
||||
{
|
||||
if(conf::exists(key) && !conf::persists(key))
|
||||
{
|
||||
conf::set(key, val);
|
||||
return {};
|
||||
}
|
||||
|
||||
const m::conf_room conf_room;
|
||||
return send(conf_room, sender, "ircd.conf.item", key,
|
||||
{
|
||||
{ "value", val }
|
||||
});
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
get_conf_item(const string_view &key,
|
||||
const std::function<void (const string_view &)> &closure)
|
||||
{
|
||||
static const m::event::fetch::opts fopts
|
||||
{
|
||||
m::event::keys::include { "content" }
|
||||
};
|
||||
|
||||
const m::conf_room conf_room;
|
||||
const m::room::state state
|
||||
{
|
||||
conf_room, &fopts
|
||||
};
|
||||
|
||||
state.get("ircd.conf.item", key, [&closure]
|
||||
(const m::event &event)
|
||||
{
|
||||
const auto &value
|
||||
{
|
||||
unquote(at<"content"_>(event).at("value"))
|
||||
};
|
||||
|
||||
closure(value);
|
||||
});
|
||||
}
|
||||
|
||||
static void
|
||||
conf_updated(const m::event &event)
|
||||
try
|
||||
{
|
||||
const auto &content
|
||||
{
|
||||
at<"content"_>(event)
|
||||
};
|
||||
|
||||
const auto &key
|
||||
{
|
||||
at<"state_key"_>(event)
|
||||
};
|
||||
|
||||
const string_view &value
|
||||
{
|
||||
unquote(content.at("value"))
|
||||
};
|
||||
|
||||
if(run::level == run::level::START && !conf::exists(key))
|
||||
return;
|
||||
|
||||
// Conf items marked with a persist=false property are not read from
|
||||
// the conf room into the item, even if the value exists in the room.
|
||||
if(conf::exists(key) && !conf::persists(key))
|
||||
return;
|
||||
|
||||
log::debug
|
||||
{
|
||||
"Updating conf [%s] => %s", key, value
|
||||
};
|
||||
|
||||
ircd::conf::set(key, value);
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
if(item_error_log)
|
||||
log::error
|
||||
{
|
||||
"Failed to set conf item '%s' :%s",
|
||||
json::get<"state_key"_>(event),
|
||||
e.what()
|
||||
};
|
||||
}
|
||||
|
||||
static void
|
||||
conf_updated(const m::event::idx &event_idx)
|
||||
try
|
||||
{
|
||||
static const m::event::fetch::opts fopts
|
||||
{
|
||||
m::event::keys::include { "content", "state_key" }
|
||||
};
|
||||
|
||||
const m::event::fetch event
|
||||
{
|
||||
event_idx, fopts
|
||||
};
|
||||
|
||||
conf_updated(event);
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
if(item_error_log)
|
||||
log::error
|
||||
{
|
||||
"Failed to set conf item by event_idx:%lu :%s",
|
||||
event_idx,
|
||||
e.what()
|
||||
};
|
||||
}
|
||||
|
||||
static void
|
||||
handle_conf_updated(const m::event &event,
|
||||
m::vm::eval &)
|
||||
{
|
||||
conf_updated(event);
|
||||
}
|
||||
|
||||
m::hookfn<m::vm::eval &>
|
||||
conf_updated_hook
|
||||
{
|
||||
handle_conf_updated,
|
||||
{
|
||||
{ "_site", "vm.effect" },
|
||||
{ "room_id", "!conf" },
|
||||
{ "type", "ircd.conf.item" },
|
||||
}
|
||||
};
|
||||
|
||||
static void
|
||||
init_conf_items()
|
||||
{
|
||||
static const m::event::fetch::opts fopts
|
||||
{
|
||||
m::event::keys::include { "content", "state_key" }
|
||||
};
|
||||
|
||||
const m::conf_room conf_room;
|
||||
const m::room::state state
|
||||
{
|
||||
conf_room, &fopts
|
||||
};
|
||||
|
||||
state.prefetch("ircd.conf.item");
|
||||
state.for_each("ircd.conf.item", []
|
||||
(const auto &, const auto &state_key, const auto &event_idx)
|
||||
{
|
||||
if(!conf::exists(state_key))
|
||||
return true;
|
||||
|
||||
conf_updated(event_idx);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
static void
|
||||
init_conf_item(conf::item<> &item)
|
||||
{
|
||||
const m::conf_room conf_room;
|
||||
const m::room::state state
|
||||
{
|
||||
conf_room
|
||||
};
|
||||
|
||||
const auto &event_idx
|
||||
{
|
||||
state.get(std::nothrow, "ircd.conf.item", item.name)
|
||||
};
|
||||
|
||||
if(!event_idx)
|
||||
return;
|
||||
|
||||
conf_updated(event_idx);
|
||||
}
|
||||
|
||||
static m::event::id::buf
|
||||
create_conf_item(const string_view &key,
|
||||
const conf::item<> &item)
|
||||
try
|
||||
{
|
||||
thread_local char vbuf[4_KiB];
|
||||
const string_view &val
|
||||
{
|
||||
item.get(vbuf)
|
||||
};
|
||||
|
||||
return set_conf_item(m::me(), key, val);
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
if(item_error_log) log::error
|
||||
{
|
||||
"Failed to create conf item '%s' :%s",
|
||||
key,
|
||||
e.what()
|
||||
};
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
static void
|
||||
create_conf_room(const m::event &,
|
||||
m::vm::eval &)
|
||||
{
|
||||
const m::conf_room conf_room;
|
||||
m::create(conf_room.room_id, m::me());
|
||||
//rehash_conf({}, true);
|
||||
}
|
||||
|
||||
m::hookfn<m::vm::eval &>
|
||||
create_conf_room_hook
|
||||
{
|
||||
create_conf_room,
|
||||
{
|
||||
{ "_site", "vm.effect" },
|
||||
{ "room_id", "!ircd" },
|
||||
{ "type", "m.room.create" },
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
rehash_conf(const string_view &prefix,
|
||||
const bool &existing)
|
||||
{
|
||||
const m::conf_room conf_room;
|
||||
const m::room::state state
|
||||
{
|
||||
conf_room
|
||||
};
|
||||
|
||||
for(const auto &p : conf::items)
|
||||
{
|
||||
const auto &key{p.first};
|
||||
if(prefix && !startswith(key, prefix))
|
||||
continue;
|
||||
|
||||
const auto &item{p.second}; assert(item);
|
||||
|
||||
// Conf items marked with a persist=false property are not written
|
||||
// to the conf room.
|
||||
if(!item->feature.get("persist", true))
|
||||
continue;
|
||||
|
||||
// Use the `existing` argument to toggle a force-overwrite
|
||||
if(!existing)
|
||||
if(state.has("ircd.conf.item", key))
|
||||
continue;
|
||||
|
||||
create_conf_item(key, *item);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
default_conf(const string_view &prefix)
|
||||
{
|
||||
for(const auto &p : conf::items)
|
||||
{
|
||||
const auto &key{p.first};
|
||||
if(prefix && !startswith(key, prefix))
|
||||
continue;
|
||||
|
||||
const auto &item{p.second}; assert(item);
|
||||
const auto value
|
||||
{
|
||||
unquote(item->feature["default"])
|
||||
};
|
||||
|
||||
conf::set(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
reload_conf()
|
||||
{
|
||||
init_conf_items();
|
||||
}
|
||||
|
||||
void
|
||||
refresh_conf()
|
||||
{
|
||||
ircd::conf::reset();
|
||||
}
|
|
@ -177,26 +177,25 @@ ircd::m::homeserver::homeserver(const struct opts *const &opts)
|
|||
}
|
||||
,opts{[this, &opts]
|
||||
{
|
||||
//TODO: xxx
|
||||
primary = primary?: this;
|
||||
primary = primary?: this; //TODO: xxx
|
||||
return opts;
|
||||
}()}
|
||||
,key
|
||||
{
|
||||
std::make_unique<struct key>(opts->origin)
|
||||
std::make_unique<struct key>(*opts)
|
||||
}
|
||||
,database
|
||||
{
|
||||
std::make_shared<dbs::init>(opts->server_name, std::string{})
|
||||
}
|
||||
,rooms
|
||||
{
|
||||
{ "ircd", opts->origin },
|
||||
std::make_shared<dbs::init>(opts->server_name)
|
||||
}
|
||||
,self
|
||||
{
|
||||
"ircd", opts->origin
|
||||
}
|
||||
,conf
|
||||
{
|
||||
std::make_unique<struct conf>(*opts)
|
||||
}
|
||||
,modules
|
||||
{
|
||||
begin(matrix::module_names), end(matrix::module_names)
|
||||
|
@ -223,7 +222,7 @@ noexcept
|
|||
}
|
||||
|
||||
//
|
||||
// homeserver::keys
|
||||
// homeserver::key
|
||||
//
|
||||
|
||||
/*
|
||||
|
@ -305,14 +304,10 @@ ircd::m::self::init::federation_ed25519()
|
|||
}
|
||||
*/
|
||||
|
||||
//
|
||||
// create_my_key
|
||||
//
|
||||
|
||||
ircd::m::homeserver::key::key(const string_view &origin)
|
||||
ircd::m::homeserver::key::key(const struct opts &opts)
|
||||
:secret_key_path
|
||||
{
|
||||
(("%s.ed25519"_snstringf, rfc3986::DOMAIN_BUFSIZE + 16UL), origin)
|
||||
(("%s.ed25519"_snstringf, rfc3986::DOMAIN_BUFSIZE + 16UL), opts.origin)
|
||||
}
|
||||
,secret_key
|
||||
{
|
||||
|
@ -374,62 +369,321 @@ ircd::m::homeserver::key::key(const string_view &origin)
|
|||
*/
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// m/self.h
|
||||
// homeserver::conf
|
||||
//
|
||||
|
||||
ircd::string_view
|
||||
ircd::m::self::my_host()
|
||||
namespace ircd::m
|
||||
{
|
||||
return origin(my());
|
||||
static bool load_conf_item(const event &);
|
||||
static bool load_conf_item(const event::idx &);
|
||||
static size_t load_conf_items(const room &, const string_view &prefix);
|
||||
|
||||
static void handle_conf_room_hook(const event &, vm::eval &);
|
||||
static void handle_item_init(const room &, conf::item<> &);
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::self::host(const string_view &other)
|
||||
//
|
||||
// homeserver::conf::conf
|
||||
//
|
||||
|
||||
ircd::m::homeserver::conf::conf(const struct opts &opts)
|
||||
:room_id
|
||||
{
|
||||
const net::hostport other_host{other};
|
||||
for(const auto &[my_network, hs_p] : homeserver::map)
|
||||
"conf", opts.origin
|
||||
}
|
||||
,room
|
||||
{
|
||||
room_id
|
||||
}
|
||||
,item_init
|
||||
{
|
||||
ircd::conf::on_init, [this](ircd::conf::item<> &item)
|
||||
{
|
||||
// port() is 0 when the origin has no port (and implies 8448)
|
||||
const auto port
|
||||
handle_item_init(room, item);
|
||||
}
|
||||
}
|
||||
,conf_updated
|
||||
{
|
||||
handle_conf_room_hook,
|
||||
{
|
||||
{ "_site", "vm.effect" },
|
||||
{ "room_id", room_id },
|
||||
{ "type", "ircd.conf.item" },
|
||||
}
|
||||
}
|
||||
{
|
||||
}
|
||||
|
||||
size_t
|
||||
ircd::m::homeserver::conf::store(const string_view &prefix,
|
||||
const bool &force)
|
||||
const
|
||||
{
|
||||
size_t ret(0);
|
||||
for(const auto &[key, item] : ircd::conf::items) try
|
||||
{
|
||||
if(prefix && !startswith(key, prefix))
|
||||
continue;
|
||||
|
||||
// Conf items marked with a persist=false property are not written
|
||||
// to the conf room; regardless of force=true
|
||||
if(!item->feature.get("persist", true))
|
||||
continue;
|
||||
|
||||
thread_local char buf[4_KiB];
|
||||
const auto &val
|
||||
{
|
||||
net::port(net::hostport(my_network))
|
||||
item->get(buf)
|
||||
};
|
||||
|
||||
// If my_host has a port number, then the argument must also have the
|
||||
// same port number.
|
||||
if(port && my_network == other)
|
||||
return true;
|
||||
else if(port)
|
||||
bool dup{false}, exists{false};
|
||||
if(!force)
|
||||
get(key, [&exists, &dup, &val](const string_view &val_)
|
||||
{
|
||||
exists = true;
|
||||
dup = val == val_;
|
||||
});
|
||||
|
||||
// No reason to store the same value
|
||||
if(!force && dup)
|
||||
continue;
|
||||
|
||||
/// If my_host has no port number, then the argument can have port
|
||||
/// 8448 or no port number, which will initialize net::hostport.port to
|
||||
/// the "canon_port" of 8448.
|
||||
assert(net::canon_port == 8448);
|
||||
if(net::port(other_host) != net::canon_port)
|
||||
const json::string &default_value
|
||||
{
|
||||
item->feature["default"]
|
||||
};
|
||||
|
||||
// When the !conf room has nothing for a key, and this store request
|
||||
// is asking us to write the default value, that is rejected here.
|
||||
if(!force && !exists && val == default_value)
|
||||
continue;
|
||||
|
||||
/// Both myself and input are using 8448; now the name has to match.
|
||||
if(my_network != host(other_host))
|
||||
continue;
|
||||
|
||||
return true;
|
||||
set(key, val);
|
||||
ret++;
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
log::error
|
||||
{
|
||||
"Failed to create conf item '%s' :%s",
|
||||
key,
|
||||
e.what()
|
||||
};
|
||||
}
|
||||
|
||||
return false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t
|
||||
ircd::m::homeserver::conf::load(const string_view &prefix)
|
||||
const
|
||||
{
|
||||
return load_conf_items(room, prefix);
|
||||
}
|
||||
|
||||
size_t
|
||||
ircd::m::homeserver::conf::defaults(const string_view &prefix)
|
||||
const
|
||||
{
|
||||
size_t ret(0);
|
||||
for(const auto &[key, item] : ircd::conf::items)
|
||||
{
|
||||
if(prefix && !startswith(key, prefix))
|
||||
continue;
|
||||
|
||||
assert(item);
|
||||
const json::string &default_value
|
||||
{
|
||||
item->feature["default"]
|
||||
};
|
||||
|
||||
ret += ircd::conf::set(key, default_value);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ircd::m::event::id::buf
|
||||
ircd::m::homeserver::conf::set(const string_view &key,
|
||||
const string_view &val)
|
||||
const
|
||||
{
|
||||
// Branch for conf items that do not persist. We don't send a message to
|
||||
// the conf room to update them; the value is put directly into the item.
|
||||
if(ircd::conf::exists(key) && !ircd::conf::persists(key))
|
||||
{
|
||||
ircd::conf::set(key, val);
|
||||
return {};
|
||||
}
|
||||
|
||||
const m::user::id::buf sender
|
||||
{
|
||||
"ircd", room_id.hostname()
|
||||
};
|
||||
|
||||
return send(room, sender, "ircd.conf.item", key, json::members
|
||||
{
|
||||
{ "value", val }
|
||||
});
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::self::my_host(const string_view &name)
|
||||
ircd::m::homeserver::conf::get(const string_view &key,
|
||||
const std::function<void (const string_view &)> &closure)
|
||||
const
|
||||
{
|
||||
const auto it
|
||||
const auto &event_idx
|
||||
{
|
||||
homeserver::map.find(name)
|
||||
room.get("ircd.conf.item", key)
|
||||
};
|
||||
|
||||
return it != end(homeserver::map);
|
||||
return m::get(std::nothrow, event_idx, "content", [&closure]
|
||||
(const json::object &content)
|
||||
{
|
||||
const json::string &value
|
||||
{
|
||||
content["value"]
|
||||
};
|
||||
|
||||
closure(value);
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::handle_item_init(const room &room,
|
||||
conf::item<> &item)
|
||||
{
|
||||
const auto event_idx
|
||||
{
|
||||
room.get(std::nothrow, "ircd.conf.item", item.name)
|
||||
};
|
||||
|
||||
if(!event_idx)
|
||||
return;
|
||||
|
||||
load_conf_item(event_idx);
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::handle_conf_room_hook(const event &event,
|
||||
vm::eval &eval)
|
||||
{
|
||||
if(!homeserver::primary)
|
||||
return;
|
||||
|
||||
assert(homeserver::primary->conf);
|
||||
const m::room::id &primary_room
|
||||
{
|
||||
homeserver::primary->conf->room_id
|
||||
};
|
||||
|
||||
// Only the primary homeserver controls the global conf items.
|
||||
if(json::get<"room_id"_>(event) != primary_room)
|
||||
return;
|
||||
|
||||
load_conf_item(event);
|
||||
}
|
||||
|
||||
size_t
|
||||
ircd::m::load_conf_items(const m::room &room,
|
||||
const string_view &prefix)
|
||||
{
|
||||
const m::room::state state
|
||||
{
|
||||
room
|
||||
};
|
||||
|
||||
state.for_each("ircd.conf.item", [&prefix]
|
||||
(const auto &, const auto &state_key, const auto &event_idx)
|
||||
{
|
||||
static const m::event::fetch::opts fopts
|
||||
{
|
||||
m::event::keys::include { "content", "state_key" }
|
||||
};
|
||||
|
||||
if(prefix && !startswith(state_key, prefix))
|
||||
return true;
|
||||
|
||||
m::prefetch(event_idx, fopts);
|
||||
return true;
|
||||
});
|
||||
|
||||
size_t ret(0);
|
||||
state.for_each("ircd.conf.item", [&ret, &prefix]
|
||||
(const auto &, const auto &state_key, const auto &event_idx)
|
||||
{
|
||||
if(prefix && !startswith(state_key, prefix))
|
||||
return true;
|
||||
|
||||
if(!conf::exists(state_key))
|
||||
return true;
|
||||
|
||||
ret += load_conf_item(event_idx);
|
||||
return true;
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::load_conf_item(const m::event::idx &event_idx)
|
||||
{
|
||||
static const m::event::fetch::opts fopts
|
||||
{
|
||||
m::event::keys::include { "content", "state_key" }
|
||||
};
|
||||
|
||||
const m::event::fetch event
|
||||
{
|
||||
event_idx, std::nothrow, fopts
|
||||
};
|
||||
|
||||
return event.valid && load_conf_item(event);
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::load_conf_item(const m::event &event)
|
||||
try
|
||||
{
|
||||
const auto &key
|
||||
{
|
||||
at<"state_key"_>(event)
|
||||
};
|
||||
|
||||
const auto &content
|
||||
{
|
||||
at<"content"_>(event)
|
||||
};
|
||||
|
||||
const json::string &value
|
||||
{
|
||||
content.get("value")
|
||||
};
|
||||
|
||||
// Conf items marked with a persist=false property are not read from
|
||||
// the conf room into the item, even if the value exists in the room.
|
||||
if(conf::exists(key) && !conf::persists(key))
|
||||
return false;
|
||||
|
||||
log::debug
|
||||
{
|
||||
"Updating conf [%s] => [%s]", key, value
|
||||
};
|
||||
|
||||
ircd::conf::set(key, value);
|
||||
return true;
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
log::error
|
||||
{
|
||||
"Failed to set conf item '%s' :%s",
|
||||
json::get<"state_key"_>(event),
|
||||
e.what()
|
||||
};
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -464,49 +718,10 @@ ircd::m::signoff(homeserver &homeserver)
|
|||
presence::set(homeserver.self, "offline", offline_status_msg);
|
||||
}
|
||||
|
||||
/*
|
||||
//
|
||||
// init
|
||||
// bootstrap
|
||||
//
|
||||
|
||||
ircd::m::self::init::init()
|
||||
try
|
||||
{
|
||||
// Sanity check that these are valid hostname strings. This was likely
|
||||
// already checked, so these validators will simply throw without very
|
||||
// useful error messages if invalid strings ever make it this far.
|
||||
|
||||
ircd_user_id = {"ircd", origin};
|
||||
m::me = {ircd_user_id};
|
||||
|
||||
ircd_room_id = {"ircd", origin};
|
||||
m::my_room = {ircd_room_id};
|
||||
|
||||
if(origin == "localhost")
|
||||
log::warning
|
||||
{
|
||||
"The origin is configured or has defaulted to 'localhost'"
|
||||
};
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
log::critical
|
||||
{
|
||||
m::log, "Failed to init self origin[%s] servername[%s]",
|
||||
origin,
|
||||
servername,
|
||||
};
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
static const auto self_init{[]
|
||||
{
|
||||
ircd::m::self::init();
|
||||
return true;
|
||||
}()};
|
||||
*/
|
||||
|
||||
void
|
||||
ircd::m::bootstrap(homeserver &homeserver)
|
||||
try
|
||||
|
@ -583,6 +798,25 @@ try
|
|||
{ "topic", "The daemon's den." }
|
||||
});
|
||||
|
||||
const m::room::id::buf conf_room_id
|
||||
{
|
||||
"conf", origin(homeserver)
|
||||
};
|
||||
|
||||
const m::room conf_room
|
||||
{
|
||||
conf_room_id
|
||||
};
|
||||
|
||||
if(!exists(conf_room))
|
||||
create(conf_room, me);
|
||||
|
||||
if(!conf_room.has("m.room.name",""))
|
||||
send(conf_room, me, "m.room.name", "",
|
||||
{
|
||||
{ "name", "Server Configuration" }
|
||||
});
|
||||
|
||||
const m::room::id::buf tokens_room_id
|
||||
{
|
||||
"tokens", origin(homeserver)
|
||||
|
@ -616,3 +850,81 @@ catch(const std::exception &e)
|
|||
e.what()
|
||||
};
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// m/self.h
|
||||
//
|
||||
//
|
||||
// !!! DEPRECATED !!!
|
||||
//
|
||||
// These items are being replaced, but their widespread use throughout the
|
||||
// codebase is keeping them here for now.
|
||||
//
|
||||
|
||||
namespace ircd::m::self
|
||||
{
|
||||
static bool match(const net::hostport &a, const net::hostport &b) noexcept;
|
||||
}
|
||||
|
||||
/// Get network name (origin) of the primary homeserver. Use of this function
|
||||
/// is discouraged, though it's not marked as deprecated to reduce warnings
|
||||
/// for now until an actual effort is made to eliminate all callsites. Instead
|
||||
/// of using this function, try to obtain a more specific homeserver instance
|
||||
/// being hosted from this server based on the context of the callsite.
|
||||
ircd::string_view
|
||||
ircd::m::self::my_host()
|
||||
{
|
||||
return origin(my());
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::self::my_host(const string_view &name)
|
||||
{
|
||||
const auto it
|
||||
{
|
||||
homeserver::map.find(name)
|
||||
};
|
||||
|
||||
return it != end(homeserver::map);
|
||||
}
|
||||
|
||||
/// Determine if argument string is one of my homeserver's network names. This
|
||||
/// is not a simple string comparison; strings postfixed with port :8448 are
|
||||
/// compared equal to strings without a port.
|
||||
bool
|
||||
ircd::m::self::host(const string_view &other)
|
||||
{
|
||||
assert(net::canon_port == 8448);
|
||||
const net::hostport other_host{other};
|
||||
for(const auto &[my_network, hs_p] : homeserver::map)
|
||||
if(match(my_network, other))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::self::match(const net::hostport &a,
|
||||
const net::hostport &b)
|
||||
noexcept
|
||||
{
|
||||
// port() is 0 when the origin has no port (and implies 8448)
|
||||
const auto my_port
|
||||
{
|
||||
port(a)?: 8448
|
||||
};
|
||||
|
||||
// If my_host has a non-canonical port number, then the argument must
|
||||
// also have the same port number, or there is no possible match.
|
||||
if(my_port != net::canon_port)
|
||||
return my_port == port(b) && host(a) == host(b);
|
||||
|
||||
// Since my host is on the canonical port, if other host has some
|
||||
// different port number, there is no possible match.
|
||||
if(port(b) != net::canon_port)
|
||||
return false;
|
||||
|
||||
// Both myself and input are using 8448; now the name has to match.
|
||||
return host(a) == host(b);
|
||||
}
|
||||
|
|
|
@ -1643,14 +1643,14 @@ console_cmd__conf__list(opt &out, const string_view &line)
|
|||
};
|
||||
|
||||
thread_local char val[4_KiB];
|
||||
for(const auto &item : conf::items)
|
||||
for(const auto &[key, item_p] : conf::items)
|
||||
{
|
||||
if(prefix && !startswith(item.first, prefix))
|
||||
if(prefix && !startswith(key, prefix))
|
||||
continue;
|
||||
|
||||
out
|
||||
<< std::setw(64) << std::left << std::setfill('_') << item.first
|
||||
<< " " << item.second->get(val)
|
||||
<< std::setw(64) << std::left << std::setfill('_') << key
|
||||
<< " " << item_p->get(val)
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
|
@ -1663,11 +1663,6 @@ console_cmd__conf(opt &out, const string_view &line)
|
|||
return console_cmd__conf__list(out, line);
|
||||
}
|
||||
|
||||
extern "C" ircd::m::event::id::buf
|
||||
set_conf_item(const ircd::m::user::id &,
|
||||
const ircd::string_view &key,
|
||||
const ircd::string_view &val);
|
||||
|
||||
bool
|
||||
console_cmd__conf__set(opt &out, const string_view &line)
|
||||
{
|
||||
|
@ -1688,7 +1683,7 @@ console_cmd__conf__set(opt &out, const string_view &line)
|
|||
|
||||
const auto event_id
|
||||
{
|
||||
set_conf_item(m::me(), key, val)
|
||||
m::my().conf->set(key, val)
|
||||
};
|
||||
|
||||
out << event_id << " <- " << key << " = " << val << std::endl;
|
||||
|
@ -1732,15 +1727,9 @@ console_cmd__conf__rehash(opt &out, const string_view &line)
|
|||
{
|
||||
const params param{line, " ",
|
||||
{
|
||||
"prefix", "force"
|
||||
"prefix"
|
||||
}};
|
||||
|
||||
using prototype = void (const string_view &, const bool &);
|
||||
static mods::import<prototype> rehash_conf
|
||||
{
|
||||
"conf", "rehash_conf"
|
||||
};
|
||||
|
||||
string_view prefix
|
||||
{
|
||||
param.at("prefix", "*"_sv)
|
||||
|
@ -1749,18 +1738,18 @@ console_cmd__conf__rehash(opt &out, const string_view &line)
|
|||
if(prefix == "*")
|
||||
prefix = string_view{};
|
||||
|
||||
const bool force
|
||||
const auto stored
|
||||
{
|
||||
param["force"] == "force"
|
||||
m::my().conf->store(prefix)
|
||||
};
|
||||
|
||||
rehash_conf(prefix, force);
|
||||
|
||||
out << "Saved runtime conf items"
|
||||
<< (prefix? " with the prefix "_sv : string_view{})
|
||||
<< (prefix? prefix : string_view{})
|
||||
<< " from the current state into !conf:" << my_host()
|
||||
<< std::endl;
|
||||
out
|
||||
<< "Saved runtime conf items"
|
||||
<< (prefix? " with the prefix "_sv : string_view{})
|
||||
<< (prefix? prefix : string_view{})
|
||||
<< " from the current state into "
|
||||
<< m::my().conf->room_id
|
||||
<< std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1773,47 +1762,66 @@ console_cmd__conf__default(opt &out, const string_view &line)
|
|||
"prefix"
|
||||
}};
|
||||
|
||||
using prototype = void (const string_view &);
|
||||
static mods::import<prototype> default_conf
|
||||
const auto &prefix
|
||||
{
|
||||
"conf", "default_conf"
|
||||
param["prefix"]
|
||||
};
|
||||
|
||||
string_view prefix
|
||||
const auto defaulted
|
||||
{
|
||||
param.at("prefix", "*"_sv)
|
||||
m::my().conf->defaults(prefix)
|
||||
};
|
||||
|
||||
if(prefix == "*")
|
||||
prefix = string_view{};
|
||||
|
||||
default_conf(prefix);
|
||||
|
||||
out << "Set runtime conf items"
|
||||
<< (prefix? " with the prefix "_sv : string_view{})
|
||||
<< (prefix? prefix : string_view{})
|
||||
<< " to their default value."
|
||||
<< std::endl
|
||||
<< "Note: These values must be saved with the rehash command"
|
||||
<< " to survive a restart/reload."
|
||||
<< std::endl;
|
||||
out
|
||||
<< "Set "
|
||||
<< defaulted
|
||||
<< " runtime conf items"
|
||||
<< (prefix? " with the prefix "_sv : string_view{})
|
||||
<< (prefix? prefix : string_view{})
|
||||
<< " to their default value."
|
||||
<< std::endl
|
||||
<< "Note: These values must be saved with the rehash command"
|
||||
<< " to survive a restart/reload."
|
||||
<< std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
console_cmd__conf__reload(opt &out, const string_view &line)
|
||||
console_cmd__conf__load(opt &out, const string_view &line)
|
||||
{
|
||||
using prototype = void ();
|
||||
static mods::import<prototype> reload_conf
|
||||
const params param{line, " ",
|
||||
{
|
||||
"conf", "reload_conf"
|
||||
"room_id", "prefix"
|
||||
}};
|
||||
|
||||
const auto &room_id
|
||||
{
|
||||
startswith(param["room_id"], '!')?
|
||||
param["room_id"]:
|
||||
m::my().conf->room_id
|
||||
};
|
||||
|
||||
reload_conf();
|
||||
out << "Updated any runtime conf items"
|
||||
<< " from the current state in !conf:" << my_host()
|
||||
<< std::endl;
|
||||
const auto &prefix
|
||||
{
|
||||
startswith(param["room_id"], '!')?
|
||||
param["prefix"]:
|
||||
param["room_id"]
|
||||
};
|
||||
|
||||
// TODO: interface for room_id
|
||||
|
||||
const auto loaded
|
||||
{
|
||||
m::my().conf->load(prefix)
|
||||
};
|
||||
|
||||
out
|
||||
<< "Updated "
|
||||
<< loaded
|
||||
<< " runtime conf items from the current state in "
|
||||
<< room_id
|
||||
<< std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1821,13 +1829,7 @@ console_cmd__conf__reload(opt &out, const string_view &line)
|
|||
bool
|
||||
console_cmd__conf__reset(opt &out, const string_view &line)
|
||||
{
|
||||
using prototype = void ();
|
||||
static mods::import<prototype> refresh_conf
|
||||
{
|
||||
"conf", "refresh_conf"
|
||||
};
|
||||
|
||||
refresh_conf();
|
||||
ircd::conf::reset();
|
||||
out << "All conf items which execute code upon a change"
|
||||
<< " have done so with the latest runtime value."
|
||||
<< std::endl;
|
||||
|
@ -5881,8 +5883,16 @@ console_cmd__resource(opt &out, const string_view &line)
|
|||
}
|
||||
|
||||
//
|
||||
// me
|
||||
//
|
||||
//
|
||||
|
||||
bool
|
||||
console_cmd__me(opt &out, const string_view &line)
|
||||
{
|
||||
out << m::me() << std::endl;
|
||||
out << m::public_key_id(m::my()) << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// key
|
||||
|
@ -5901,15 +5911,6 @@ console_cmd__key(opt &out, const string_view &line)
|
|||
param["server_name"]
|
||||
};
|
||||
|
||||
// information on my current key
|
||||
if(!server_name)
|
||||
{
|
||||
out << "origin: " << m::my_host() << std::endl;
|
||||
out << "public key ID: " << m::public_key_id(m::my()) << std::endl;
|
||||
//out << "public key base64: " << m::self::public_key_b64 << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
// keys cached for server by param.
|
||||
m::keys::cache::for_each(server_name, [&out]
|
||||
(const m::keys &keys)
|
||||
|
|
Loading…
Reference in a new issue