mirror of
https://github.com/matrix-construct/construct
synced 2024-12-28 00:14:07 +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
|
struct ircd::m::keys::init
|
||||||
{
|
{
|
||||||
json::object conf;
|
json::object config;
|
||||||
|
|
||||||
void certificate();
|
void certificate();
|
||||||
void signing();
|
void signing();
|
||||||
|
@ -90,7 +90,7 @@ struct ircd::m::keys::init
|
||||||
public:
|
public:
|
||||||
void bootstrap();
|
void bootstrap();
|
||||||
|
|
||||||
init(const json::object &conf);
|
init(const json::object &config);
|
||||||
~init() noexcept;
|
~init() noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ namespace ircd
|
||||||
|
|
||||||
struct ircd::m::init
|
struct ircd::m::init
|
||||||
{
|
{
|
||||||
json::object conf;
|
json::object config;
|
||||||
|
|
||||||
void bootstrap();
|
void bootstrap();
|
||||||
void listeners();
|
void listeners();
|
||||||
|
|
|
@ -183,7 +183,7 @@ namespace ircd
|
||||||
|
|
||||||
constexpr size_t BUFSIZE { 512 };
|
constexpr size_t BUFSIZE { 512 };
|
||||||
extern const enum runlevel &runlevel;
|
extern const enum runlevel &runlevel;
|
||||||
extern const std::string &conf;
|
extern const std::string &config;
|
||||||
extern bool debugmode; ///< Toggle; available only ifdef RB_DEBUG
|
extern bool debugmode; ///< Toggle; available only ifdef RB_DEBUG
|
||||||
|
|
||||||
std::string demangle(const std::string &symbol);
|
std::string demangle(const std::string &symbol);
|
||||||
|
@ -218,6 +218,7 @@ namespace ircd
|
||||||
#include "http.h"
|
#include "http.h"
|
||||||
#include "fmt.h"
|
#include "fmt.h"
|
||||||
#include "magics.h"
|
#include "magics.h"
|
||||||
|
#include "conf.h"
|
||||||
#include "fs/fs.h"
|
#include "fs/fs.h"
|
||||||
#include "ios.h"
|
#include "ios.h"
|
||||||
#include "ctx/ctx.h"
|
#include "ctx/ctx.h"
|
||||||
|
|
|
@ -78,6 +78,7 @@ libircd_la_SOURCES = \
|
||||||
logger.cc \
|
logger.cc \
|
||||||
info.cc \
|
info.cc \
|
||||||
sodium.cc \
|
sodium.cc \
|
||||||
|
conf.cc \
|
||||||
rfc1459.cc \
|
rfc1459.cc \
|
||||||
rand.cc \
|
rand.cc \
|
||||||
hash.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
|
boost::asio::io_context *ios; // user's io service
|
||||||
struct strand *strand; // libircd event serializer
|
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
|
ctx::ctx *main_context; // Main program loop
|
||||||
bool debugmode; // meaningful ifdef RB_DEBUG
|
bool debugmode; // meaningful ifdef RB_DEBUG
|
||||||
|
|
||||||
std::string read_conf(std::string file);
|
|
||||||
void set_runlevel(const enum runlevel &);
|
void set_runlevel(const enum runlevel &);
|
||||||
void at_main_exit() noexcept;
|
void at_main_exit() noexcept;
|
||||||
void main();
|
void main();
|
||||||
|
@ -87,30 +83,16 @@ try
|
||||||
// Saves the user's runlevel_changed callback which we invoke.
|
// Saves the user's runlevel_changed callback which we invoke.
|
||||||
ircd::runlevel_changed = std::move(runlevel_changed);
|
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::init();
|
||||||
log::mark("READY");
|
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.
|
// This starts off the log with library information.
|
||||||
info::init();
|
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
|
// 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
|
// ircd::main(). The main_context is the first ircd::ctx to be spawned
|
||||||
// and will be the last to finish.
|
// and will be the last to finish.
|
||||||
|
@ -362,56 +344,3 @@ ircd::reflect(const enum runlevel &level)
|
||||||
|
|
||||||
return "??????";
|
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
|
// init
|
||||||
//
|
//
|
||||||
|
|
||||||
ircd::m::keys::init::init(const json::object &conf)
|
ircd::m::keys::init::init(const json::object &config)
|
||||||
:conf{conf}
|
:config{config}
|
||||||
{
|
{
|
||||||
certificate();
|
certificate();
|
||||||
signing();
|
signing();
|
||||||
|
@ -114,7 +114,7 @@ ircd::m::keys::init::signing()
|
||||||
{
|
{
|
||||||
const std::string sk_file
|
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))
|
if(fs::exists(sk_file))
|
||||||
|
|
30
ircd/m/m.cc
30
ircd/m/m.cc
|
@ -66,13 +66,13 @@ ircd::m::control
|
||||||
|
|
||||||
ircd::m::init::init()
|
ircd::m::init::init()
|
||||||
try
|
try
|
||||||
:conf
|
:config
|
||||||
{
|
{
|
||||||
ircd::conf
|
ircd::conf::config //TODO: X
|
||||||
}
|
}
|
||||||
,_keys
|
,_keys
|
||||||
{
|
{
|
||||||
conf
|
this->config
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
modules();
|
modules();
|
||||||
|
@ -123,8 +123,8 @@ ircd::m::init::modules()
|
||||||
|
|
||||||
namespace ircd::m
|
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 &config, 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -132,18 +132,18 @@ ircd::m::init::listeners()
|
||||||
{
|
{
|
||||||
const json::array listeners
|
const json::array listeners
|
||||||
{
|
{
|
||||||
conf["listeners"]
|
config["listeners"]
|
||||||
};
|
};
|
||||||
|
|
||||||
if(m::listeners.empty())
|
if(m::listeners.empty())
|
||||||
init_listener(conf, {});
|
init_listener(config, {});
|
||||||
else
|
else
|
||||||
for(const json::object opts : listeners)
|
for(const json::object opts : listeners)
|
||||||
init_listener(conf, opts);
|
init_listener(config, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ircd::m::init_listener(const json::object &conf,
|
ircd::m::init_listener(const json::object &config,
|
||||||
const json::object &opts)
|
const json::object &opts)
|
||||||
{
|
{
|
||||||
const json::array binds
|
const json::array binds
|
||||||
|
@ -152,14 +152,14 @@ ircd::m::init_listener(const json::object &conf,
|
||||||
};
|
};
|
||||||
|
|
||||||
if(binds.empty())
|
if(binds.empty())
|
||||||
init_listener(conf, opts, "0.0.0.0");
|
init_listener(config, opts, "0.0.0.0");
|
||||||
else
|
else
|
||||||
for(const auto &bindaddr : binds)
|
for(const auto &bindaddr : binds)
|
||||||
init_listener(conf, opts, unquote(bindaddr));
|
init_listener(config, opts, unquote(bindaddr));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ircd::m::init_listener(const json::object &conf,
|
ircd::m::init_listener(const json::object &config,
|
||||||
const json::object &opts,
|
const json::object &opts,
|
||||||
const string_view &host)
|
const string_view &host)
|
||||||
{
|
{
|
||||||
|
@ -178,9 +178,9 @@ ircd::m::init_listener(const json::object &conf,
|
||||||
{ "name", name },
|
{ "name", name },
|
||||||
{ "host", host },
|
{ "host", host },
|
||||||
{ "port", opts.get("port", 8448L) },
|
{ "port", opts.get("port", 8448L) },
|
||||||
{ "ssl_certificate_file_pem", conf["tls_certificate_path"] },
|
{ "ssl_certificate_file_pem", config["tls_certificate_path"] },
|
||||||
{ "ssl_private_key_file_pem", conf["tls_private_key_path"] },
|
{ "ssl_private_key_file_pem", config["tls_private_key_path"] },
|
||||||
{ "ssl_tmp_dh_file", conf["tls_dh_params_path"] },
|
{ "ssl_tmp_dh_file", config["tls_dh_params_path"] },
|
||||||
}};
|
}};
|
||||||
|
|
||||||
m::listeners.emplace_back(options);
|
m::listeners.emplace_back(options);
|
||||||
|
|
Loading…
Reference in a new issue