mirror of
https://github.com/matrix-construct/construct
synced 2024-12-26 15:33:54 +01:00
ircd: Mein conf.
This commit is contained in:
parent
15ec746fc6
commit
97e593a77e
9 changed files with 250 additions and 100 deletions
84
include/ircd/conf.h
Normal file
84
include/ircd/conf.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
// 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.
|
||||
|
||||
#pragma once
|
||||
#define HAVE_IRCD_CONF_H
|
||||
|
||||
namespace ircd::conf
|
||||
{
|
||||
template<class T = void> struct item; // doesn't exist
|
||||
template<class T> struct value; // abstraction for carrying item value
|
||||
template<> struct item<void>; // base class of all conf items
|
||||
template<> struct item<seconds>;
|
||||
|
||||
IRCD_EXCEPTION(ircd::error, error)
|
||||
|
||||
extern const std::string &config; //TODO: X
|
||||
|
||||
void init(const string_view &configfile);
|
||||
}
|
||||
|
||||
/// Conf item base class. You don't create this directly; use one of the
|
||||
/// derived templates instead.
|
||||
template<>
|
||||
struct ircd::conf::item<void>
|
||||
:instance_list<ircd::conf::item<>>
|
||||
{
|
||||
json::strung feature_;
|
||||
json::object feature;
|
||||
string_view name;
|
||||
|
||||
virtual bool refresh();
|
||||
|
||||
item(const json::members &);
|
||||
virtual ~item() noexcept;
|
||||
};
|
||||
|
||||
/// Conf item value abstraction. If possible, the conf item will also
|
||||
/// inherit from this template to deduplicate functionality between
|
||||
/// conf items which contain similar classes of values.
|
||||
template<class T>
|
||||
struct ircd::conf::value
|
||||
:conf::item<>
|
||||
{
|
||||
using value_type = T;
|
||||
|
||||
T _value;
|
||||
std::function<bool (T &)> refresher;
|
||||
|
||||
operator const T &() const
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
bool refresh() override
|
||||
{
|
||||
return refresher? refresher(_value) : false;
|
||||
}
|
||||
|
||||
template<class U>
|
||||
value(const json::members &memb, U&& t)
|
||||
:conf::item<>{memb}
|
||||
,_value{std::forward<U>(t)}
|
||||
{}
|
||||
|
||||
value(const json::members &memb = {})
|
||||
:conf::item<>{memb}
|
||||
,_value{feature.get<T>("default", T{})}
|
||||
{}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ircd::conf::item<ircd::seconds>
|
||||
:conf::value<seconds>
|
||||
{
|
||||
using value_type = seconds;
|
||||
using value::value;
|
||||
};
|
|
@ -82,7 +82,7 @@ struct ircd::m::keys
|
|||
|
||||
struct ircd::m::keys::init
|
||||
{
|
||||
json::object conf;
|
||||
json::object config;
|
||||
|
||||
void certificate();
|
||||
void signing();
|
||||
|
@ -90,7 +90,7 @@ struct ircd::m::keys::init
|
|||
public:
|
||||
void bootstrap();
|
||||
|
||||
init(const json::object &conf);
|
||||
init(const json::object &config);
|
||||
~init() noexcept;
|
||||
};
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ namespace ircd
|
|||
|
||||
struct ircd::m::init
|
||||
{
|
||||
json::object conf;
|
||||
json::object config;
|
||||
|
||||
void bootstrap();
|
||||
void listeners();
|
||||
|
|
|
@ -183,7 +183,7 @@ namespace ircd
|
|||
|
||||
constexpr size_t BUFSIZE { 512 };
|
||||
extern const enum runlevel &runlevel;
|
||||
extern const std::string &conf;
|
||||
extern const std::string &config;
|
||||
extern bool debugmode; ///< Toggle; available only ifdef RB_DEBUG
|
||||
|
||||
std::string demangle(const std::string &symbol);
|
||||
|
@ -218,6 +218,7 @@ namespace ircd
|
|||
#include "http.h"
|
||||
#include "fmt.h"
|
||||
#include "magics.h"
|
||||
#include "conf.h"
|
||||
#include "fs/fs.h"
|
||||
#include "ios.h"
|
||||
#include "ctx/ctx.h"
|
||||
|
|
|
@ -78,6 +78,7 @@ libircd_la_SOURCES = \
|
|||
logger.cc \
|
||||
info.cc \
|
||||
sodium.cc \
|
||||
conf.cc \
|
||||
rfc1459.cc \
|
||||
rand.cc \
|
||||
hash.cc \
|
||||
|
|
135
ircd/conf.cc
Normal file
135
ircd/conf.cc
Normal file
|
@ -0,0 +1,135 @@
|
|||
// 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::conf
|
||||
{
|
||||
std::string _config;
|
||||
static std::string read_json_file(string_view filename);
|
||||
}
|
||||
|
||||
//TODO: X
|
||||
decltype(ircd::conf::config)
|
||||
ircd::conf::config
|
||||
{
|
||||
_config
|
||||
};
|
||||
|
||||
// The configuration file is a user-converted Synapse homeserver.yaml
|
||||
// converted into JSON. The configuration file is only truly necessary
|
||||
// the first time IRCd is ever run. It does not have to be passed again
|
||||
// to subsequent executions of IRCd if the database can be found. If
|
||||
// the database is found, data passed in the configfile will be used
|
||||
// to override the databased values. In this case, the complete config
|
||||
// is not required to be specified in the file; only what is present
|
||||
// will be used to override.
|
||||
//
|
||||
// *NOTE* This expects *canonical JSON* right now. That means converting
|
||||
// your homeserver.yaml may be a two step process: 1. YAML to JSON, 2.
|
||||
// whitespace-stripping the JSON. Tools to do both of these things are
|
||||
// first hits in a google search.
|
||||
void
|
||||
ircd::conf::init(const string_view &filename)
|
||||
{
|
||||
_config = read_json_file(filename);
|
||||
}
|
||||
|
||||
//
|
||||
// item
|
||||
//
|
||||
|
||||
template<>
|
||||
decltype(ircd::instance_list<ircd::conf::item<>>::list)
|
||||
ircd::instance_list<ircd::conf::item<>>::list
|
||||
{};
|
||||
|
||||
/// Conf item abstract constructor.
|
||||
ircd::conf::item<void>::item(const json::members &opts)
|
||||
:feature_
|
||||
{
|
||||
opts
|
||||
}
|
||||
,feature
|
||||
{
|
||||
feature_
|
||||
}
|
||||
,name
|
||||
{
|
||||
feature.has("name")? unquote(feature["name"]) : "<unnamed>"_sv
|
||||
}
|
||||
{
|
||||
}
|
||||
|
||||
ircd::conf::item<void>::~item()
|
||||
noexcept
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::conf::item<void>::refresh()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// misc
|
||||
//
|
||||
|
||||
std::string
|
||||
ircd::conf::read_json_file(string_view filename)
|
||||
try
|
||||
{
|
||||
if(!filename.empty())
|
||||
log::debug
|
||||
{
|
||||
"User supplied a configuration file path: `%s'", filename
|
||||
};
|
||||
|
||||
if(filename.empty())
|
||||
filename = fs::CPATH;
|
||||
|
||||
if(!fs::exists(filename))
|
||||
return {};
|
||||
|
||||
std::string read
|
||||
{
|
||||
fs::read(filename)
|
||||
};
|
||||
|
||||
// ensure any trailing cruft is removed to not set off the validator
|
||||
if(endswith(read, '\n'))
|
||||
read.pop_back();
|
||||
|
||||
if(endswith(read, '\r'))
|
||||
read.pop_back();
|
||||
|
||||
// grammar check; throws on error
|
||||
json::valid(read);
|
||||
|
||||
const json::object object{read};
|
||||
const size_t key_count{object.count()};
|
||||
log::info
|
||||
{
|
||||
"Using configuration from: `%s': JSON object with %zu members in %zu bytes",
|
||||
filename,
|
||||
key_count,
|
||||
read.size()
|
||||
};
|
||||
|
||||
return read;
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
log::error
|
||||
{
|
||||
"Configuration @ `%s': %s", filename, e.what()
|
||||
};
|
||||
|
||||
throw;
|
||||
}
|
79
ircd/ircd.cc
79
ircd/ircd.cc
|
@ -20,13 +20,9 @@ namespace ircd
|
|||
boost::asio::io_context *ios; // user's io service
|
||||
struct strand *strand; // libircd event serializer
|
||||
|
||||
std::string _conf; // JSON read from configfile
|
||||
const std::string &conf{_conf}; // Observer for conf data
|
||||
|
||||
ctx::ctx *main_context; // Main program loop
|
||||
bool debugmode; // meaningful ifdef RB_DEBUG
|
||||
|
||||
std::string read_conf(std::string file);
|
||||
void set_runlevel(const enum runlevel &);
|
||||
void at_main_exit() noexcept;
|
||||
void main();
|
||||
|
@ -87,30 +83,16 @@ try
|
|||
// Saves the user's runlevel_changed callback which we invoke.
|
||||
ircd::runlevel_changed = std::move(runlevel_changed);
|
||||
|
||||
// The log is available, but it is console-only until conf opens files.
|
||||
// The log is available. but it is console-only until conf opens files.
|
||||
log::init();
|
||||
log::mark("READY");
|
||||
|
||||
// The conf supplied by the user is read in; see: ircd::conf.
|
||||
conf::init(configfile);
|
||||
|
||||
// This starts off the log with library information.
|
||||
info::init();
|
||||
|
||||
// The configuration file is a user-converted Synapse homeserver.yaml
|
||||
// converted into JSON. The configuration file is only truly meaningful
|
||||
// the first time IRCd is ever run. Subsequently, only the database must
|
||||
// be found. Real configuration is stored in the !config channel.
|
||||
//
|
||||
// This subroutine reads a file either at the user-supplied path or the
|
||||
// default path specified in ircd::fs, vets for basic syntax issues, and
|
||||
// then returns a string of JSON (the file's contents). The validity of
|
||||
// the actual configuration is not known until specific subsystems are
|
||||
// init'ed later.
|
||||
//
|
||||
// *NOTE* This expects *canonical JSON* right now. That means converting
|
||||
// your homeserver.yaml may be a two step process: 1. YAML to JSON, 2.
|
||||
// whitespace-stripping the JSON. Tools to do both of these things are
|
||||
// first hits in a google search.
|
||||
ircd::_conf = read_conf(configfile);
|
||||
|
||||
// Setup the main context, which is a new stack executing the function
|
||||
// ircd::main(). The main_context is the first ircd::ctx to be spawned
|
||||
// and will be the last to finish.
|
||||
|
@ -362,56 +344,3 @@ ircd::reflect(const enum runlevel &level)
|
|||
|
||||
return "??????";
|
||||
}
|
||||
|
||||
std::string
|
||||
ircd::read_conf(std::string filename)
|
||||
try
|
||||
{
|
||||
if(!filename.empty())
|
||||
log::debug
|
||||
{
|
||||
"User supplied a configuration file path: `%s'", filename
|
||||
};
|
||||
|
||||
if(filename.empty())
|
||||
filename = fs::CPATH;
|
||||
|
||||
if(!fs::exists(filename))
|
||||
return {};
|
||||
|
||||
std::string read
|
||||
{
|
||||
fs::read(filename)
|
||||
};
|
||||
|
||||
// ensure any trailing cruft is removed to not set off the validator
|
||||
if(endswith(read, '\n'))
|
||||
read.pop_back();
|
||||
|
||||
if(endswith(read, '\r'))
|
||||
read.pop_back();
|
||||
|
||||
// grammar check; throws on error
|
||||
json::valid(read);
|
||||
|
||||
const json::object object{read};
|
||||
const size_t key_count{object.count()};
|
||||
log::info
|
||||
{
|
||||
"Using configuration from: `%s': JSON object with %zu members in %zu bytes",
|
||||
filename,
|
||||
key_count,
|
||||
read.size()
|
||||
};
|
||||
|
||||
return read;
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
log::error
|
||||
{
|
||||
"Configuration @ `%s': %s", filename, e.what()
|
||||
};
|
||||
|
||||
throw;
|
||||
}
|
||||
|
|
|
@ -52,8 +52,8 @@ ircd::m::self::tls_cert_der_sha256_b64
|
|||
// init
|
||||
//
|
||||
|
||||
ircd::m::keys::init::init(const json::object &conf)
|
||||
:conf{conf}
|
||||
ircd::m::keys::init::init(const json::object &config)
|
||||
:config{config}
|
||||
{
|
||||
certificate();
|
||||
signing();
|
||||
|
@ -114,7 +114,7 @@ ircd::m::keys::init::signing()
|
|||
{
|
||||
const std::string sk_file
|
||||
{
|
||||
unquote(conf.get("signing_key_path", "construct.sk"))
|
||||
unquote(config.get("signing_key_path", "construct.sk"))
|
||||
};
|
||||
|
||||
if(fs::exists(sk_file))
|
||||
|
|
36
ircd/m/m.cc
36
ircd/m/m.cc
|
@ -66,13 +66,13 @@ ircd::m::control
|
|||
|
||||
ircd::m::init::init()
|
||||
try
|
||||
:conf
|
||||
:config
|
||||
{
|
||||
ircd::conf
|
||||
ircd::conf::config //TODO: X
|
||||
}
|
||||
,_keys
|
||||
{
|
||||
conf
|
||||
this->config
|
||||
}
|
||||
{
|
||||
modules();
|
||||
|
@ -123,8 +123,8 @@ ircd::m::init::modules()
|
|||
|
||||
namespace ircd::m
|
||||
{
|
||||
static void init_listener(const json::object &conf, const json::object &opts, const string_view &bindaddr);
|
||||
static void init_listener(const json::object &conf, const json::object &opts);
|
||||
static void init_listener(const json::object &config, const json::object &opts, const string_view &bindaddr);
|
||||
static void init_listener(const json::object &config, const json::object &opts);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -132,18 +132,18 @@ ircd::m::init::listeners()
|
|||
{
|
||||
const json::array listeners
|
||||
{
|
||||
conf["listeners"]
|
||||
config["listeners"]
|
||||
};
|
||||
|
||||
if(m::listeners.empty())
|
||||
init_listener(conf, {});
|
||||
init_listener(config, {});
|
||||
else
|
||||
for(const json::object opts : listeners)
|
||||
init_listener(conf, opts);
|
||||
init_listener(config, opts);
|
||||
}
|
||||
|
||||
static void
|
||||
ircd::m::init_listener(const json::object &conf,
|
||||
ircd::m::init_listener(const json::object &config,
|
||||
const json::object &opts)
|
||||
{
|
||||
const json::array binds
|
||||
|
@ -152,14 +152,14 @@ ircd::m::init_listener(const json::object &conf,
|
|||
};
|
||||
|
||||
if(binds.empty())
|
||||
init_listener(conf, opts, "0.0.0.0");
|
||||
init_listener(config, opts, "0.0.0.0");
|
||||
else
|
||||
for(const auto &bindaddr : binds)
|
||||
init_listener(conf, opts, unquote(bindaddr));
|
||||
init_listener(config, opts, unquote(bindaddr));
|
||||
}
|
||||
|
||||
static void
|
||||
ircd::m::init_listener(const json::object &conf,
|
||||
ircd::m::init_listener(const json::object &config,
|
||||
const json::object &opts,
|
||||
const string_view &host)
|
||||
{
|
||||
|
@ -175,12 +175,12 @@ ircd::m::init_listener(const json::object &conf,
|
|||
// Translate synapse options to our options (which reflect asio::ssl)
|
||||
const json::strung options{json::members
|
||||
{
|
||||
{ "name", name },
|
||||
{ "host", host },
|
||||
{ "port", opts.get("port", 8448L) },
|
||||
{ "ssl_certificate_file_pem", conf["tls_certificate_path"] },
|
||||
{ "ssl_private_key_file_pem", conf["tls_private_key_path"] },
|
||||
{ "ssl_tmp_dh_file", conf["tls_dh_params_path"] },
|
||||
{ "name", name },
|
||||
{ "host", host },
|
||||
{ "port", opts.get("port", 8448L) },
|
||||
{ "ssl_certificate_file_pem", config["tls_certificate_path"] },
|
||||
{ "ssl_private_key_file_pem", config["tls_private_key_path"] },
|
||||
{ "ssl_tmp_dh_file", config["tls_dh_params_path"] },
|
||||
}};
|
||||
|
||||
m::listeners.emplace_back(options);
|
||||
|
|
Loading…
Reference in a new issue