mirror of
https://github.com/matrix-construct/construct
synced 2024-05-20 03:43:47 +02:00
matrix: Add m::homeserver; preliminary virtual origin networks.
This commit is contained in:
parent
b17b8b0bef
commit
dbb3c55db5
|
@ -68,7 +68,6 @@ construct_LDADD = \
|
|||
|
||||
construct_SOURCES = \
|
||||
construct.cc \
|
||||
matrix.cc \
|
||||
signals.cc \
|
||||
console.cc \
|
||||
lgetopt.cc \
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include <ircd/asio.h>
|
||||
#include "lgetopt.h"
|
||||
#include "construct.h"
|
||||
#include "matrix.h"
|
||||
#include "signals.h"
|
||||
#include "console.h"
|
||||
|
||||
|
@ -120,8 +119,13 @@ noexcept try
|
|||
if(printversion)
|
||||
return print_version();
|
||||
|
||||
// The matrix origin is the first positional argument after any switched
|
||||
// arguments. The matrix origin is the hostpart of MXID's for the server.
|
||||
// Sets various other conf items based on the program options captured into
|
||||
// the globals preceding this frame.
|
||||
applyargs();
|
||||
|
||||
// The network name (matrix origin) is the first positional argument after
|
||||
// any switched arguments. The matrix origin is the hostpart of MXID's for
|
||||
// the server.
|
||||
const ircd::string_view origin
|
||||
{
|
||||
argc > 0?
|
||||
|
@ -129,46 +133,42 @@ noexcept try
|
|||
nullptr
|
||||
};
|
||||
|
||||
// The hostname is the unique name for this specific server. This is
|
||||
// The server_name is the unique name for this specific server. This is
|
||||
// generally the same as origin; but if origin is example.org with an
|
||||
// SRV record redirecting to matrix.example.org then hostname is
|
||||
// SRV record redirecting to matrix.example.org then server_name is
|
||||
// matrix.example.org. In clusters serving a single origin, all
|
||||
// hostnames must be different.
|
||||
const ircd::string_view hostname
|
||||
// server_names must be different.
|
||||
const ircd::string_view server_name
|
||||
{
|
||||
argc > 1? // hostname given on command line
|
||||
argc > 1? // server_name given on command line
|
||||
argv[1]:
|
||||
argc > 0? // hostname matches origin
|
||||
argc > 0? // server_name matches origin
|
||||
argv[0]:
|
||||
nullptr
|
||||
};
|
||||
|
||||
// at least one hostname argument is required for now.
|
||||
if(!hostname)
|
||||
// at least one server_name argument is required for now.
|
||||
if(!server_name)
|
||||
throw ircd::user_error
|
||||
{
|
||||
"usage :%s <origin> [servername]", progname
|
||||
};
|
||||
|
||||
// Set the required name conf items based on the positional program
|
||||
// arguments. This operation will throw if the strings are not fit for
|
||||
// purpose as host/domain names.
|
||||
ircd::network_name.set(origin);
|
||||
ircd::server_name.set(hostname);
|
||||
|
||||
// Sets various other conf items based on the program options captured into
|
||||
// the globals preceding this frame.
|
||||
applyargs();
|
||||
|
||||
// The smoketest uses this ircd::run::level callback to set a flag when
|
||||
// each ircd::run::level is reached. All flags must be set to pass. The
|
||||
// smoketest is inert unless the -smoketest program option is used.
|
||||
const ircd::run::changed smoketester{[](const auto &level)
|
||||
// smoketest is inert unless the -smoketest program option is used. Note
|
||||
// the special case for run::level::RUN, which initiates the transition
|
||||
// to QUIT; the ircd::post allows any operations queued in the io_context
|
||||
// to run in case the smoketest isn't the only callback being invoked.
|
||||
const ircd::run::changed smoketester
|
||||
{
|
||||
smoketest.at(size_t(level) + 1) = true;
|
||||
if(smoketest[0] && level == ircd::run::level::RUN)
|
||||
ircd::post {[] { ircd::quit(); }};
|
||||
}};
|
||||
[](const auto &level)
|
||||
{
|
||||
smoketest.at(size_t(level) + 1) = true;
|
||||
if(smoketest[0] && level == ircd::run::level::RUN)
|
||||
ircd::post {[] { ircd::quit(); }};
|
||||
}
|
||||
};
|
||||
|
||||
// This is the sole io_context for Construct, and the ios.run() below is the
|
||||
// the only place where the program actually blocks.
|
||||
|
@ -187,9 +187,88 @@ noexcept try
|
|||
// to that io_context. Execution of IRCd will then occur during ios::run()
|
||||
ircd::init(ios);
|
||||
|
||||
// Start matrix application.
|
||||
if(likely(!nomatrix))
|
||||
construct::matrix::init();
|
||||
// Setup synchronization primitives on this stack for starting and stopping
|
||||
// the application (matrix homeserver). Note this stack cannot actually use
|
||||
// these; they'll be used to synchronize the closures below running in
|
||||
// different contexts.
|
||||
ircd::ctx::latch start(2), quit(2);
|
||||
|
||||
// Setup the matrix homeserver application. This will be executed on an
|
||||
// ircd::context (dedicated stack). We construct several objects on the
|
||||
// stack which are the basis for our matrix homeserver. When the stack
|
||||
// unwinds, the homeserver will go out of service.
|
||||
const auto homeserver{[&origin, &server_name, &start, &quit]
|
||||
{
|
||||
// 5
|
||||
struct ircd::m::homeserver::opts opts;
|
||||
opts.origin = origin;
|
||||
opts.server_name = server_name;
|
||||
|
||||
// 6
|
||||
// Load the matrix library dynamic shared object
|
||||
ircd::matrix matrix;
|
||||
|
||||
// 7
|
||||
// Run a primary homeserver based on the program options given.
|
||||
const ircd::custom_ptr<ircd::m::homeserver> homeserver
|
||||
{
|
||||
// 7.1
|
||||
matrix.init(&opts), [&matrix]
|
||||
(ircd::m::homeserver *const homeserver)
|
||||
{
|
||||
// 13.1
|
||||
matrix.fini(homeserver);
|
||||
}
|
||||
};
|
||||
|
||||
// 8
|
||||
// Notify the loader the homeserver is ready for service.
|
||||
start.count_down_and_wait();
|
||||
|
||||
// 9
|
||||
// Yield until the loader notifies us; this stack will then unwind.
|
||||
quit.count_down_and_wait();
|
||||
|
||||
// 13
|
||||
}};
|
||||
|
||||
// This object registers a callback for a specific event in libircd; the
|
||||
// closure is called from the main context (#1) running ircd::main().
|
||||
// after libircd is ready for service in runlevel START but before entering
|
||||
// runlevel RUN. It is called again immediately after entering runlevel
|
||||
// QUIT, but before any functionality of libircd destructs. This cues us
|
||||
// to start and stop the homeserver.
|
||||
const decltype(ircd::run::main)::callback loader
|
||||
{
|
||||
ircd::run::main, [&homeserver, &start, &quit]
|
||||
{
|
||||
static ircd::context context;
|
||||
|
||||
// 2 This branch is taken the first time this function is called,
|
||||
// and not taken the second time.
|
||||
if(!context)
|
||||
{
|
||||
// 3 Launch the homeserver context (asynchronous).
|
||||
context = { "matrix", homeserver };
|
||||
|
||||
// 4 Yield until the homeserver function notifies `start`; waiting
|
||||
// here prevents ircd::main() from entering runlevel RUN.
|
||||
start.count_down_and_wait();
|
||||
|
||||
// 10
|
||||
return;
|
||||
}
|
||||
|
||||
// 11
|
||||
// Notify the waiting homeserver context to quit; this will
|
||||
// start shutting down the homeserver.
|
||||
quit.count_down_and_wait();
|
||||
|
||||
// 12
|
||||
// Wait for the homeserver context to finish before we return.
|
||||
context.join();
|
||||
}
|
||||
};
|
||||
|
||||
// If the user wants to immediately drop to an interactive command line
|
||||
// without having to send a ctrl-c for it, that is provided here. This does
|
||||
|
@ -207,10 +286,12 @@ noexcept try
|
|||
if(norun)
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
// 1
|
||||
// Execution.
|
||||
// Blocks until a clean exit from a quit() or an exception comes out of it.
|
||||
ios.run();
|
||||
|
||||
// 14
|
||||
// The smoketest is enabled if the first value is true; then all of the
|
||||
// values must be true for the smoketest to pass.
|
||||
if(smoketest[0])
|
||||
|
@ -331,6 +412,8 @@ enable_coredumps()
|
|||
}
|
||||
#endif
|
||||
|
||||
/// These operations are safe to call before ircd::init() and anytime after
|
||||
/// static initialization.
|
||||
void
|
||||
applyargs()
|
||||
{
|
||||
|
|
|
@ -1,116 +0,0 @@
|
|||
// Matrix Construct
|
||||
//
|
||||
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
||||
// Copyright (C) 2016-2019 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.
|
||||
|
||||
#include <ircd/matrix.h>
|
||||
#include "construct.h"
|
||||
#include "matrix.h"
|
||||
|
||||
decltype(construct::matrix)
|
||||
construct::matrix;
|
||||
|
||||
void
|
||||
construct::matrix::init()
|
||||
{
|
||||
assert(construct::matrix == nullptr);
|
||||
construct::matrix = new matrix{};
|
||||
}
|
||||
|
||||
void
|
||||
construct::matrix::quit()
|
||||
{
|
||||
if(!construct::matrix)
|
||||
return;
|
||||
|
||||
construct::matrix->context.terminate();
|
||||
}
|
||||
|
||||
construct::matrix::matrix()
|
||||
:context
|
||||
{
|
||||
"matrix",
|
||||
1048576,
|
||||
std::bind(&matrix::main, this),
|
||||
ircd::context::DISPATCH,
|
||||
}
|
||||
{
|
||||
}
|
||||
|
||||
construct::matrix::~matrix()
|
||||
noexcept
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
construct::matrix::main()
|
||||
noexcept try
|
||||
{
|
||||
ircd::run::changed::dock.wait([]
|
||||
{
|
||||
return ircd::run::level != ircd::run::level::READY;
|
||||
});
|
||||
|
||||
if(ircd::run::level != ircd::run::level::START || ircd::run::level != ircd::run::level::RUN)
|
||||
return;
|
||||
|
||||
ircd::matrix instance
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
const ircd::scope_restore this_instance
|
||||
{
|
||||
this->instance, std::addressof(instance)
|
||||
};
|
||||
|
||||
ircd::mods::import<ircd::log::log> log
|
||||
{
|
||||
instance.module, "ircd::m::log"
|
||||
};
|
||||
|
||||
ircd::log::notice
|
||||
{
|
||||
log, "Matrix Constructed"
|
||||
};
|
||||
|
||||
dock.notify_all();
|
||||
ircd::run::changed::dock.wait([]
|
||||
{
|
||||
return false
|
||||
|| ircd::run::level == ircd::run::level::QUIT
|
||||
|| ircd::run::level == ircd::run::level::HALT
|
||||
;
|
||||
});
|
||||
|
||||
ircd::log::notice
|
||||
{
|
||||
log, "Matrix Shutdown..."
|
||||
};
|
||||
}
|
||||
catch(const ircd::ctx::interrupted &e)
|
||||
{
|
||||
ircd::log::debug
|
||||
{
|
||||
"construct::matrix :%s", e.what()
|
||||
};
|
||||
}
|
||||
catch(const ircd::ctx::terminated &e)
|
||||
{
|
||||
ircd::log::debug
|
||||
{
|
||||
"construct::matrix: terminated."
|
||||
};
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
ircd::log::error
|
||||
{
|
||||
"construct::matrix :%s", e.what()
|
||||
};
|
||||
}
|
|
@ -1,34 +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
|
||||
{
|
||||
struct matrix;
|
||||
}
|
||||
|
||||
namespace construct
|
||||
{
|
||||
struct matrix;
|
||||
}
|
||||
|
||||
struct construct::matrix
|
||||
{
|
||||
ircd::ctx::dock dock;
|
||||
ircd::context context;
|
||||
ircd::matrix *instance {nullptr};
|
||||
|
||||
void main() noexcept;
|
||||
|
||||
matrix();
|
||||
~matrix() noexcept;
|
||||
|
||||
static void init();
|
||||
static void quit();
|
||||
};
|
|
@ -13,7 +13,6 @@
|
|||
#include "construct.h"
|
||||
#include "signals.h"
|
||||
#include "console.h"
|
||||
#include "matrix.h"
|
||||
|
||||
namespace construct
|
||||
{
|
||||
|
|
|
@ -82,9 +82,6 @@ namespace ircd
|
|||
extern conf::item<bool> write_avoid;
|
||||
extern conf::item<bool> soft_assert;
|
||||
|
||||
extern conf::item<std::string> server_name;
|
||||
extern conf::item<std::string> network_name;
|
||||
|
||||
seconds uptime();
|
||||
void init(boost::asio::io_context &ios);
|
||||
void cont() noexcept;
|
||||
|
|
|
@ -11,6 +11,12 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_M_EVENT_APPEND
|
||||
|
||||
//XXX fwd decl
|
||||
namespace ircd::m
|
||||
{
|
||||
struct room;
|
||||
};
|
||||
|
||||
/// Used when transmitting events to clients. This tries to hide and provide
|
||||
/// as much boilerplate as possible which we abstracted from all of the
|
||||
/// different locations where an event may be revealed to a client. This device
|
||||
|
|
115
include/ircd/m/homeserver.h
Normal file
115
include/ircd/m/homeserver.h
Normal file
|
@ -0,0 +1,115 @@
|
|||
// 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_M_HOMESERVER_H
|
||||
|
||||
namespace ircd::m
|
||||
{
|
||||
struct homeserver;
|
||||
|
||||
IRCD_M_EXCEPTION(error, NOT_MY_HOMESERVER, http::NOT_FOUND)
|
||||
IRCD_M_EXCEPTION(error, NOT_A_HOMESERVER, http::SERVICE_UNAVAILABLE)
|
||||
|
||||
string_view origin(const homeserver &);
|
||||
string_view server_name(const homeserver &);
|
||||
|
||||
bool origin(const homeserver &, const string_view &);
|
||||
bool server_name(const homeserver &, const string_view &);
|
||||
|
||||
string_view public_key_id(const homeserver &);
|
||||
const ed25519::sk &secret_key(const homeserver &);
|
||||
|
||||
bool for_each(const std::function<bool (homeserver &)> &);
|
||||
|
||||
homeserver &my(const string_view &origin);
|
||||
homeserver &my(); // primary
|
||||
|
||||
user::id me(const string_view &origin);
|
||||
user::id me(); // primary
|
||||
}
|
||||
|
||||
///NOTE: instance_multimap is used because there is no instance_map yet.
|
||||
struct ircd::m::homeserver
|
||||
:instance_multimap<string_view, homeserver, std::less<>>
|
||||
{
|
||||
struct key;
|
||||
struct cert;
|
||||
struct opts;
|
||||
|
||||
/// Internal state; use m::my().
|
||||
static homeserver *primary;
|
||||
|
||||
/// Options from the user.
|
||||
const struct opts *opts;
|
||||
|
||||
/// Federation key related.
|
||||
std::unique_ptr<struct key> key;
|
||||
|
||||
/// Database
|
||||
std::shared_ptr<dbs::init> database;
|
||||
|
||||
/// List of special room specific to this homeserver. This includes the
|
||||
/// fundamental !ircd room, !conf room, etc. This list generally doesn't
|
||||
/// change after construction, but it's mutable to allow modules to add
|
||||
/// new rooms to the list.
|
||||
std::set<m::room::id::buf> rooms;
|
||||
|
||||
/// An inscription of @ircd:network.name to root various references to
|
||||
/// a user representing the server.
|
||||
m::user::id::buf self;
|
||||
|
||||
/// Loaded modules.
|
||||
std::list<ircd::module> modules;
|
||||
|
||||
homeserver(const struct opts *const &);
|
||||
~homeserver() noexcept;
|
||||
|
||||
/// Factory to create homeserver with single procedure for shlib purposes.
|
||||
static homeserver *init(const struct opts *);
|
||||
static void fini(homeserver *) noexcept;
|
||||
};
|
||||
|
||||
struct ircd::m::homeserver::key
|
||||
{
|
||||
/// Current federation secret key instance
|
||||
ed25519::sk secret_key;
|
||||
|
||||
/// Current federation public key instance
|
||||
ed25519::pk public_key;
|
||||
|
||||
/// Current federation public key base64
|
||||
std::string public_key_b64;
|
||||
|
||||
/// Current ed25519:ident string
|
||||
std::string public_key_id;
|
||||
|
||||
key(const string_view &origin);
|
||||
key() = default;
|
||||
};
|
||||
|
||||
struct ircd::m::homeserver::cert
|
||||
{
|
||||
std::string tls_private_key_path;
|
||||
std::string tls_public_key_path;
|
||||
std::string tls_cert_path;
|
||||
};
|
||||
|
||||
struct ircd::m::homeserver::opts
|
||||
{
|
||||
/// Network name. This is the mxid hostpart (i.e @user:origin).
|
||||
string_view origin;
|
||||
|
||||
/// This server's name. This is the unique domain-name of this server
|
||||
/// participating in the cluster to serve the origin. The servername may
|
||||
/// be the origin itself; otherwise, SRV/well-known indirection is required
|
||||
/// to reach the servername starting from the origin.
|
||||
string_view server_name;
|
||||
};
|
|
@ -35,6 +35,7 @@ namespace ircd::m
|
|||
namespace ircd::m
|
||||
{
|
||||
struct matrix;
|
||||
struct homeserver;
|
||||
|
||||
IRCD_OVERLOAD(generate)
|
||||
|
||||
|
@ -48,9 +49,8 @@ namespace ircd
|
|||
|
||||
#include "name.h"
|
||||
#include "error.h"
|
||||
#include "self.h"
|
||||
#include "init.h"
|
||||
#include "id.h"
|
||||
#include "self.h"
|
||||
#include "event/event.h"
|
||||
#include "get.h"
|
||||
#include "query.h"
|
||||
|
@ -89,9 +89,13 @@ namespace ircd
|
|||
#include "media.h"
|
||||
#include "search.h"
|
||||
#include "resource.h"
|
||||
#include "homeserver.h"
|
||||
|
||||
struct ircd::m::matrix
|
||||
{
|
||||
static const std::vector<string_view> module_names;
|
||||
static const std::vector<string_view> module_names_optional;
|
||||
|
||||
std::string module_path
|
||||
{
|
||||
fs::path_string(fs::base::LIB, "libircd_matrix")
|
||||
|
@ -101,4 +105,16 @@ struct ircd::m::matrix
|
|||
{
|
||||
module_path
|
||||
};
|
||||
|
||||
using init_proto = m::homeserver *(const struct m::homeserver::opts *);
|
||||
mods::import<init_proto> init
|
||||
{
|
||||
module, "ircd::m::homeserver::init"
|
||||
};
|
||||
|
||||
using fini_proto = void (m::homeserver *) noexcept;
|
||||
mods::import<fini_proto> fini
|
||||
{
|
||||
module, "ircd::m::homeserver::fini"
|
||||
};
|
||||
};
|
||||
|
|
|
@ -13,56 +13,27 @@
|
|||
|
||||
namespace ircd::m::self
|
||||
{
|
||||
struct init;
|
||||
// Test if provided string is one of my homeserver's network_name()'s.
|
||||
bool my_host(const string_view &);
|
||||
|
||||
extern std::string origin;
|
||||
extern std::string servername;
|
||||
extern ed25519::sk secret_key;
|
||||
extern ed25519::pk public_key;
|
||||
extern std::string public_key_b64;
|
||||
extern std::string public_key_id;
|
||||
extern std::string tls_cert_der;
|
||||
extern std::string tls_cert_der_sha256_b64;
|
||||
|
||||
string_view host();
|
||||
// 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.
|
||||
bool host(const string_view &);
|
||||
|
||||
void create_my_key();
|
||||
void signon(), signoff();
|
||||
// Alias for origin(my()); primary homeserver's network name
|
||||
string_view my_host(); //__attribute__((deprecated));
|
||||
}
|
||||
|
||||
namespace ircd::m
|
||||
{
|
||||
extern struct user me;
|
||||
extern struct room my_room;
|
||||
extern struct node my_node;
|
||||
|
||||
string_view my_host();
|
||||
bool my_host(const string_view &);
|
||||
using self::my_host;
|
||||
using self::host;
|
||||
}
|
||||
|
||||
namespace ircd
|
||||
{
|
||||
using m::my_host;
|
||||
}
|
||||
|
||||
struct ircd::m::self::init
|
||||
{
|
||||
static void federation_ed25519();
|
||||
static void tls_certificate();
|
||||
static void keys();
|
||||
|
||||
init();
|
||||
};
|
||||
|
||||
inline ircd::string_view
|
||||
ircd::m::my_host()
|
||||
{
|
||||
return self::host();
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::m::my_host(const string_view &host)
|
||||
{
|
||||
return self::host(host);
|
||||
}
|
||||
|
|
|
@ -48,8 +48,6 @@ struct ircd::m::user
|
|||
using closure = std::function<void (const user &)>;
|
||||
using closure_bool = std::function<bool (const user &)>;
|
||||
|
||||
static m::room tokens;
|
||||
|
||||
id user_id;
|
||||
|
||||
operator const id &() const;
|
||||
|
|
36
ircd/ircd.cc
36
ircd/ircd.cc
|
@ -88,42 +88,6 @@ ircd::restart
|
|||
{ "persist", false },
|
||||
};
|
||||
|
||||
decltype(ircd::server_name)
|
||||
ircd::server_name
|
||||
{
|
||||
{
|
||||
{ "name", "ircd.name.server" },
|
||||
{ "default", "localhost" },
|
||||
{ "persist", false },
|
||||
}, []
|
||||
{
|
||||
if(!rfc3986::valid_remote(std::nothrow, ircd::server_name))
|
||||
throw user_error
|
||||
{
|
||||
"The 'ircd.name.server' conf \"%s\" is not a valid hostname.",
|
||||
string_view(server_name),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
decltype(ircd::network_name)
|
||||
ircd::network_name
|
||||
{
|
||||
{
|
||||
{ "name", "ircd.name.network" },
|
||||
{ "default", "localhost" },
|
||||
{ "persist", false },
|
||||
}, []
|
||||
{
|
||||
if(!rfc3986::valid_remote(std::nothrow, ircd::network_name))
|
||||
throw user_error
|
||||
{
|
||||
"The 'ircd.name.network' conf \"%s\" is not a valid hostname.",
|
||||
string_view(network_name),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
decltype(ircd::main_context)
|
||||
ircd::main_context;
|
||||
|
||||
|
|
|
@ -57,7 +57,6 @@ libircd_matrix_la_SOURCES =#
|
|||
libircd_matrix_la_SOURCES += name.cc
|
||||
libircd_matrix_la_SOURCES += id.cc
|
||||
libircd_matrix_la_SOURCES += dbs.cc
|
||||
libircd_matrix_la_SOURCES += self.cc
|
||||
libircd_matrix_la_SOURCES += hook.cc
|
||||
libircd_matrix_la_SOURCES += event.cc
|
||||
libircd_matrix_la_SOURCES += event_cached.cc
|
||||
|
@ -127,7 +126,7 @@ libircd_matrix_la_SOURCES += filter.cc
|
|||
libircd_matrix_la_SOURCES += txn.cc
|
||||
libircd_matrix_la_SOURCES += vm.cc
|
||||
libircd_matrix_la_SOURCES += init_backfill.cc
|
||||
libircd_matrix_la_SOURCES += init_bootstrap.cc
|
||||
libircd_matrix_la_SOURCES += homeserver.cc
|
||||
libircd_matrix_la_SOURCES += resource.cc
|
||||
libircd_matrix_la_SOURCES += matrix.cc
|
||||
|
||||
|
|
|
@ -259,7 +259,7 @@ try
|
|||
item.get(vbuf)
|
||||
};
|
||||
|
||||
return set_conf_item(m::me.user_id, key, val);
|
||||
return set_conf_item(m::me(), key, val);
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
|
@ -278,7 +278,7 @@ create_conf_room(const m::event &,
|
|||
m::vm::eval &)
|
||||
{
|
||||
const m::conf_room conf_room;
|
||||
m::create(conf_room.room_id, m::me.user_id);
|
||||
m::create(conf_room.room_id, m::me());
|
||||
//rehash_conf({}, true);
|
||||
}
|
||||
|
||||
|
|
|
@ -302,7 +302,16 @@ IRCD_MODULE_EXPORT
|
|||
ircd::m::device::access_token_to_id(const string_view &token,
|
||||
const closure &closure)
|
||||
{
|
||||
const m::room::state &state{m::user::tokens};
|
||||
const m::room::id::buf tokens
|
||||
{
|
||||
"tokens", origin(my())
|
||||
};
|
||||
|
||||
const m::room::state &state
|
||||
{
|
||||
tokens
|
||||
};
|
||||
|
||||
const m::event::idx &event_idx
|
||||
{
|
||||
state.get(std::nothrow, "ircd.access_token", token)
|
||||
|
|
|
@ -182,20 +182,30 @@ ircd::m::event::signatures(const mutable_buffer &out,
|
|||
json::iov &event,
|
||||
const json::iov &content)
|
||||
{
|
||||
const string_view &origin
|
||||
{
|
||||
event.at("origin")
|
||||
};
|
||||
|
||||
const ed25519::sig sig
|
||||
{
|
||||
sign(event, content)
|
||||
};
|
||||
|
||||
const string_view public_key_id
|
||||
{
|
||||
m::public_key_id(my(origin))
|
||||
};
|
||||
|
||||
thread_local char sigb64buf[b64encode_size(sizeof(sig))];
|
||||
const json::members sigb64
|
||||
{
|
||||
{ self::public_key_id, b64encode_unpadded(sigb64buf, sig) }
|
||||
{ public_key_id, b64encode_unpadded(sigb64buf, sig) }
|
||||
};
|
||||
|
||||
const json::members sigs
|
||||
{
|
||||
{ event.at("origin"), sigb64 }
|
||||
{ origin, sigb64 }
|
||||
};
|
||||
|
||||
return json::stringify(mutable_buffer{out}, sigs);
|
||||
|
@ -222,19 +232,22 @@ ircd::m::signatures(const mutable_buffer &out_,
|
|||
sign(preimage)
|
||||
};
|
||||
|
||||
const auto sig_host
|
||||
const auto &origin
|
||||
{
|
||||
my_host(json::get<"origin"_>(event))?
|
||||
json::get<"origin"_>(event):
|
||||
my_host()
|
||||
json::at<"origin"_>(event)
|
||||
};
|
||||
|
||||
const string_view public_key_id
|
||||
{
|
||||
m::public_key_id(my(origin))
|
||||
};
|
||||
|
||||
thread_local char sigb64buf[b64encode_size(sizeof(sig))];
|
||||
const json::member my_sig
|
||||
{
|
||||
sig_host, json::members
|
||||
origin, json::members
|
||||
{
|
||||
{ self::public_key_id, b64encode_unpadded(sigb64buf, sig) }
|
||||
{ public_key_id, b64encode_unpadded(sigb64buf, sig) }
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -257,7 +270,17 @@ ircd::ed25519::sig
|
|||
ircd::m::event::sign(json::iov &event,
|
||||
const json::iov &contents)
|
||||
{
|
||||
return sign(event, contents, self::secret_key);
|
||||
const string_view &origin
|
||||
{
|
||||
event.at("origin")
|
||||
};
|
||||
|
||||
const auto &secret_key
|
||||
{
|
||||
m::secret_key(my(origin))
|
||||
};
|
||||
|
||||
return sign(event, contents, secret_key);
|
||||
}
|
||||
|
||||
ircd::ed25519::sig
|
||||
|
@ -278,7 +301,17 @@ ircd::m::event::sign(json::iov &event,
|
|||
ircd::ed25519::sig
|
||||
ircd::m::sign(const event &event)
|
||||
{
|
||||
return sign(event, self::secret_key);
|
||||
const string_view &origin
|
||||
{
|
||||
json::at<"origin"_>(event)
|
||||
};
|
||||
|
||||
const auto &secret_key
|
||||
{
|
||||
m::secret_key(my(origin))
|
||||
};
|
||||
|
||||
return sign(event, secret_key);
|
||||
}
|
||||
|
||||
ircd::ed25519::sig
|
||||
|
@ -297,7 +330,17 @@ ircd::m::sign(const event &event,
|
|||
ircd::ed25519::sig
|
||||
ircd::m::event::sign(const json::object &event)
|
||||
{
|
||||
return sign(event, self::secret_key);
|
||||
const json::string &origin
|
||||
{
|
||||
event.at("origin")
|
||||
};
|
||||
|
||||
const auto &secret_key
|
||||
{
|
||||
m::secret_key(my(origin))
|
||||
};
|
||||
|
||||
return sign(event, secret_key);
|
||||
}
|
||||
|
||||
ircd::ed25519::sig
|
||||
|
@ -317,7 +360,17 @@ ircd::m::event::sign(const json::object &event,
|
|||
ircd::ed25519::sig
|
||||
ircd::m::event::sign(const string_view &event)
|
||||
{
|
||||
return sign(event, self::secret_key);
|
||||
const json::string &origin
|
||||
{
|
||||
json::object(event).at("origin")
|
||||
};
|
||||
|
||||
const auto &secret_key
|
||||
{
|
||||
m::secret_key(my(origin))
|
||||
};
|
||||
|
||||
return sign(event, secret_key);
|
||||
}
|
||||
|
||||
ircd::ed25519::sig
|
||||
|
@ -766,7 +819,7 @@ ircd::m::make_id(const event &event,
|
|||
{
|
||||
const id::event ret
|
||||
{
|
||||
buf, b64tob64url(readable, b64encode_unpadded(readable, hash)), my_host()
|
||||
buf, b64tob64url(readable, b64encode_unpadded(readable, hash)), at<"origin"_>(event)
|
||||
};
|
||||
|
||||
buf.assigned(ret);
|
||||
|
|
|
@ -87,7 +87,6 @@ ircd::m::vm::conform_check_size
|
|||
{
|
||||
{
|
||||
{ "_site", "vm.conform" },
|
||||
{ "origin", my_host() }
|
||||
},
|
||||
[](const m::event &event, eval &eval)
|
||||
{
|
||||
|
|
559
matrix/homeserver.cc
Normal file
559
matrix/homeserver.cc
Normal file
|
@ -0,0 +1,559 @@
|
|||
// 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
|
||||
{
|
||||
static void bootstrap(homeserver &);
|
||||
}
|
||||
|
||||
// Linkage for the container of all active clients for iteration purposes.
|
||||
template<>
|
||||
decltype(ircd::util::instance_multimap<ircd::string_view, ircd::m::homeserver, std::less<>>::map)
|
||||
ircd::util::instance_multimap<ircd::string_view, ircd::m::homeserver, std::less<>>::map
|
||||
{};
|
||||
|
||||
[[gnu::hot]]
|
||||
ircd::m::user::id
|
||||
ircd::m::me()
|
||||
{
|
||||
auto &my
|
||||
{
|
||||
m::my()
|
||||
};
|
||||
|
||||
return my.self;
|
||||
}
|
||||
|
||||
[[gnu::hot]]
|
||||
ircd::m::user::id
|
||||
ircd::m::me(const string_view &origin)
|
||||
{
|
||||
auto &my
|
||||
{
|
||||
m::my(origin)
|
||||
};
|
||||
|
||||
return my.self;
|
||||
}
|
||||
|
||||
[[gnu::hot]]
|
||||
ircd::m::homeserver &
|
||||
ircd::m::my()
|
||||
{
|
||||
if(unlikely(!homeserver::primary))
|
||||
throw m::NOT_A_HOMESERVER
|
||||
{
|
||||
"I do not host any homeserver here."
|
||||
};
|
||||
|
||||
return *homeserver::primary;
|
||||
}
|
||||
|
||||
[[gnu::hot]]
|
||||
ircd::m::homeserver &
|
||||
ircd::m::my(const string_view &name)
|
||||
{
|
||||
const auto &it
|
||||
{
|
||||
homeserver::map.find(name)
|
||||
};
|
||||
|
||||
if(unlikely(it == end(homeserver::map)))
|
||||
throw m::NOT_MY_HOMESERVER
|
||||
{
|
||||
"I do not host any '%s' homeserver here.",
|
||||
name,
|
||||
};
|
||||
|
||||
const auto &ptr
|
||||
{
|
||||
it->second
|
||||
};
|
||||
|
||||
assert(ptr);
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::for_each(const std::function<bool (homeserver &)> &closure)
|
||||
{
|
||||
for(auto &[name, hs_p] : homeserver::map)
|
||||
if(!closure(*hs_p))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const ircd::ed25519::sk &
|
||||
ircd::m::secret_key(const homeserver &homeserver)
|
||||
{
|
||||
assert(homeserver.key);
|
||||
return homeserver.key->secret_key;
|
||||
}
|
||||
|
||||
ircd::string_view
|
||||
ircd::m::public_key_id(const homeserver &homeserver)
|
||||
{
|
||||
assert(homeserver.key);
|
||||
return homeserver.key->public_key_id;
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::server_name(const homeserver &homeserver,
|
||||
const string_view &server_name)
|
||||
{
|
||||
return server_name == m::server_name(homeserver);
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::origin(const homeserver &homeserver,
|
||||
const string_view &origin)
|
||||
{
|
||||
return origin == m::origin(homeserver);
|
||||
}
|
||||
|
||||
ircd::string_view
|
||||
ircd::m::server_name(const homeserver &homeserver)
|
||||
{
|
||||
assert(homeserver.opts);
|
||||
return homeserver.opts->server_name;
|
||||
}
|
||||
|
||||
ircd::string_view
|
||||
ircd::m::origin(const homeserver &homeserver)
|
||||
{
|
||||
assert(homeserver.opts);
|
||||
return homeserver.opts->origin;
|
||||
}
|
||||
|
||||
//
|
||||
// homeserver::homeserver
|
||||
//
|
||||
|
||||
decltype(ircd::m::homeserver::primary)
|
||||
ircd::m::homeserver::primary;
|
||||
|
||||
ircd::m::homeserver *
|
||||
IRCD_MODULE_EXPORT
|
||||
ircd::m::homeserver::init(const struct opts *const opts)
|
||||
{
|
||||
return new homeserver
|
||||
{
|
||||
opts
|
||||
};
|
||||
}
|
||||
|
||||
void
|
||||
IRCD_MODULE_EXPORT
|
||||
ircd::m::homeserver::fini(homeserver *const homeserver)
|
||||
noexcept
|
||||
{
|
||||
delete homeserver;
|
||||
}
|
||||
|
||||
//
|
||||
// homeserver::homeserver::homeserver
|
||||
//
|
||||
|
||||
IRCD_MODULE_EXPORT
|
||||
ircd::m::homeserver::homeserver(const struct opts *const &opts)
|
||||
:instance_multimap
|
||||
{
|
||||
string_view{opts->origin}
|
||||
}
|
||||
,opts
|
||||
{
|
||||
opts
|
||||
}
|
||||
,key
|
||||
{
|
||||
std::make_unique<struct key>(opts->origin)
|
||||
}
|
||||
,database
|
||||
{
|
||||
std::make_shared<dbs::init>(opts->server_name, std::string{})
|
||||
}
|
||||
,rooms
|
||||
{
|
||||
{ "ircd", opts->origin },
|
||||
}
|
||||
,self
|
||||
{
|
||||
"ircd", opts->origin
|
||||
}
|
||||
{
|
||||
primary = primary?: this;
|
||||
|
||||
modules =
|
||||
{
|
||||
begin(matrix::module_names), end(matrix::module_names)
|
||||
};
|
||||
|
||||
if(primary == this && dbs::events && sequence(*dbs::events) == 0)
|
||||
bootstrap(*this);
|
||||
}
|
||||
|
||||
ircd::m::homeserver::~homeserver()
|
||||
noexcept
|
||||
{
|
||||
while(!modules.empty())
|
||||
modules.pop_back();
|
||||
}
|
||||
|
||||
//
|
||||
// homeserver::keys
|
||||
//
|
||||
|
||||
/*
|
||||
namespace ircd::m
|
||||
{
|
||||
extern conf::item<std::string> ed25519_key_dir;
|
||||
}
|
||||
|
||||
decltype(ircd::m::ed25519_key_dir)
|
||||
ircd::m::ed25519_key_dir
|
||||
{
|
||||
{ "name", "ircd.keys.ed25519_key_dir" },
|
||||
{ "default", fs::cwd() },
|
||||
};
|
||||
|
||||
void
|
||||
IRCD_MODULE_EXPORT
|
||||
ircd::m::self::init::federation_ed25519()
|
||||
{
|
||||
if(empty(m::self::origin))
|
||||
throw error
|
||||
{
|
||||
"The m::self::origin must be set to init my ed25519 key."
|
||||
};
|
||||
|
||||
const std::string path_parts[]
|
||||
{
|
||||
std::string{ed25519_key_dir},
|
||||
m::self::origin + ".ed25519",
|
||||
};
|
||||
|
||||
const std::string sk_file
|
||||
{
|
||||
ircd::string(fs::PATH_MAX_LEN, [&](const mutable_buffer &buf)
|
||||
{
|
||||
return fs::path(buf, path_parts);
|
||||
})
|
||||
};
|
||||
|
||||
if(fs::exists(sk_file) || ircd::write_avoid)
|
||||
log::info
|
||||
{
|
||||
m::log, "Using ed25519 secret key @ `%s'", sk_file
|
||||
};
|
||||
else
|
||||
log::notice
|
||||
{
|
||||
m::log, "Creating ed25519 secret key @ `%s'", sk_file
|
||||
};
|
||||
|
||||
m::self::secret_key = ed25519::sk
|
||||
{
|
||||
sk_file, &m::self::public_key
|
||||
};
|
||||
|
||||
m::self::public_key_b64 = b64encode_unpadded(m::self::public_key);
|
||||
const fixed_buffer<const_buffer, sha256::digest_size> hash
|
||||
{
|
||||
sha256{m::self::public_key}
|
||||
};
|
||||
|
||||
const auto public_key_hash_b58
|
||||
{
|
||||
b58encode(hash)
|
||||
};
|
||||
|
||||
static const auto trunc_size{8};
|
||||
m::self::public_key_id = fmt::snstringf
|
||||
{
|
||||
32, "ed25519:%s", trunc(public_key_hash_b58, trunc_size)
|
||||
};
|
||||
|
||||
log::info
|
||||
{
|
||||
m::log, "Current key is '%s' and the public key is: %s",
|
||||
m::self::public_key_id,
|
||||
m::self::public_key_b64
|
||||
};
|
||||
}
|
||||
*/
|
||||
|
||||
//
|
||||
// create_my_key
|
||||
//
|
||||
|
||||
ircd::m::homeserver::key::key(const string_view &origin)
|
||||
{
|
||||
/*
|
||||
const json::members verify_keys_
|
||||
{{
|
||||
string_view{m::self::public_key_id},
|
||||
{
|
||||
{ "key", m::self::public_key_b64 }
|
||||
}
|
||||
}};
|
||||
|
||||
m::keys my_key;
|
||||
json::get<"server_name"_>(my_key) = my_host();
|
||||
json::get<"old_verify_keys"_>(my_key) = "{}";
|
||||
|
||||
//TODO: conf
|
||||
json::get<"valid_until_ts"_>(my_key) =
|
||||
ircd::time<milliseconds>() + milliseconds(1000UL * 60 * 60 * 24 * 180).count();
|
||||
|
||||
const json::strung verify_keys{verify_keys_}; // must be on stack until my_keys serialized.
|
||||
json::get<"verify_keys"_>(my_key) = verify_keys;
|
||||
|
||||
const json::strung presig
|
||||
{
|
||||
my_key
|
||||
};
|
||||
|
||||
const ed25519::sig sig
|
||||
{
|
||||
m::self::secret_key.sign(const_buffer{presig})
|
||||
};
|
||||
|
||||
char signature[256];
|
||||
const json::strung signatures{json::members
|
||||
{
|
||||
{ my_host(),
|
||||
{
|
||||
{ string_view{m::self::public_key_id}, b64encode_unpadded(signature, sig) }
|
||||
}}
|
||||
}};
|
||||
|
||||
json::get<"signatures"_>(my_key) = signatures;
|
||||
keys::cache::set(json::strung{my_key});
|
||||
*/
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// m/self.h
|
||||
//
|
||||
|
||||
ircd::string_view
|
||||
ircd::m::self::my_host()
|
||||
{
|
||||
return origin(my());
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::self::host(const string_view &other)
|
||||
{
|
||||
const net::hostport other_host{other};
|
||||
for(const auto &[my_network, hs_p] : homeserver::map)
|
||||
{
|
||||
// port() is 0 when the origin has no port (and implies 8448)
|
||||
const auto port
|
||||
{
|
||||
net::port(net::hostport(my_network))
|
||||
};
|
||||
|
||||
// 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)
|
||||
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)
|
||||
continue;
|
||||
|
||||
/// Both myself and input are using 8448; now the name has to match.
|
||||
if(my_network != host(other_host))
|
||||
continue;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::self::my_host(const string_view &name)
|
||||
{
|
||||
const auto it
|
||||
{
|
||||
homeserver::map.find(name)
|
||||
};
|
||||
|
||||
return it != end(homeserver::map);
|
||||
}
|
||||
|
||||
//
|
||||
// signon/signoff greetings
|
||||
//
|
||||
|
||||
/*
|
||||
namespace ircd::m::self
|
||||
{
|
||||
void signon(), signoff();
|
||||
}
|
||||
|
||||
ircd::conf::item<std::string>
|
||||
me_online_status_msg
|
||||
{
|
||||
{ "name", "ircd.me.online.status_msg" },
|
||||
{ "default", "Wanna chat? IRCd at your service!" }
|
||||
};
|
||||
|
||||
ircd::conf::item<std::string>
|
||||
me_offline_status_msg
|
||||
{
|
||||
{ "name", "ircd.me.offline.status_msg" },
|
||||
{ "default", "Catch ya on the flip side..." }
|
||||
};
|
||||
|
||||
void
|
||||
ircd::m::self::signon()
|
||||
{
|
||||
if(!ircd::write_avoid && vm::sequence::retired != 0)
|
||||
presence::set(me, "online", me_online_status_msg);
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::self::signoff()
|
||||
{
|
||||
if(!std::uncaught_exceptions() && !ircd::write_avoid)
|
||||
presence::set(me, "offline", me_offline_status_msg);
|
||||
}
|
||||
|
||||
//
|
||||
// init
|
||||
//
|
||||
|
||||
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.
|
||||
rfc3986::valid_host(origin);
|
||||
rfc3986::valid_host(servername);
|
||||
|
||||
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
|
||||
{
|
||||
assert(dbs::events);
|
||||
assert(db::sequence(*dbs::events) == 0);
|
||||
if(homeserver.self.hostname() == "localhost")
|
||||
log::warning
|
||||
{
|
||||
"The server's name is configured to localhost. This is probably not what you want."
|
||||
};
|
||||
|
||||
if(!exists(homeserver.self))
|
||||
{
|
||||
create(homeserver.self);
|
||||
user(homeserver.self).activate();
|
||||
}
|
||||
|
||||
const m::room::id::buf node_room_id
|
||||
{
|
||||
node(origin(homeserver)).room_id()
|
||||
};
|
||||
|
||||
if(!exists(node_room_id))
|
||||
create(room(node_room_id));
|
||||
|
||||
const m::room::id::buf my_room
|
||||
{
|
||||
"ircd", origin(homeserver)
|
||||
};
|
||||
|
||||
if(!exists(my_room))
|
||||
create(my_room, homeserver.self, "internal");
|
||||
|
||||
if(!membership(my_room, homeserver.self, "join"))
|
||||
join(room(my_room), user(homeserver.self));
|
||||
|
||||
if(!room(my_room).has("m.room.name", ""))
|
||||
send(my_room, homeserver.self, "m.room.name", "",
|
||||
{
|
||||
{ "name", "IRCd's Room" }
|
||||
});
|
||||
|
||||
if(!room(my_room).has("m.room.topic", ""))
|
||||
send(my_room, homeserver.self, "m.room.topic", "",
|
||||
{
|
||||
{ "topic", "The daemon's den." }
|
||||
});
|
||||
|
||||
const m::room::id::buf tokens_room
|
||||
{
|
||||
"tokens", origin(homeserver)
|
||||
};
|
||||
|
||||
if(!exists(tokens_room))
|
||||
create(tokens_room, homeserver.self);
|
||||
|
||||
if(!room(tokens_room).has("m.room.name",""))
|
||||
send(tokens_room, homeserver.self, "m.room.name", "",
|
||||
{
|
||||
{ "name", "User Tokens" }
|
||||
});
|
||||
|
||||
log::info
|
||||
{
|
||||
log, "Bootstrap event generation completed nominally."
|
||||
};
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
throw ircd::panic
|
||||
{
|
||||
"bootstrap %s error :%s",
|
||||
server_name(homeserver),
|
||||
e.what()
|
||||
};
|
||||
}
|
|
@ -207,7 +207,7 @@ const
|
|||
ircd::m::hook::base::base(const json::members &members)
|
||||
:_feature
|
||||
{
|
||||
_hook_make_feature(members)
|
||||
members // _hook_make_feature(members)
|
||||
}
|
||||
,feature
|
||||
{
|
||||
|
|
|
@ -8,6 +8,11 @@
|
|||
// 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::init
|
||||
{
|
||||
struct backfill;
|
||||
}
|
||||
|
||||
/// This should be a namespace but we're stuck in struct m::init for now, so
|
||||
/// this code should be portable for a future when m::init is unstructured.
|
||||
struct ircd::m::init::backfill
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
// Matrix Construct
|
||||
//
|
||||
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
||||
// Copyright (C) 2016-2019 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.
|
||||
|
||||
ircd::m::init::bootstrap::bootstrap()
|
||||
try
|
||||
{
|
||||
assert(dbs::events);
|
||||
assert(db::sequence(*dbs::events) == 0);
|
||||
if(me.user_id.hostname() == "localhost")
|
||||
log::warning
|
||||
{
|
||||
"The ircd.origin is configured to localhost. This is probably not"
|
||||
" what you want. To fix this now, you will have to remove the "
|
||||
" database and start over."
|
||||
};
|
||||
|
||||
if(!exists(me))
|
||||
{
|
||||
create(me.user_id);
|
||||
me.activate();
|
||||
}
|
||||
|
||||
if(!exists(my_node))
|
||||
create(my_node);
|
||||
|
||||
if(!exists(my_room))
|
||||
create(my_room, me.user_id, "internal");
|
||||
|
||||
if(!membership(my_room, me, "join"))
|
||||
join(my_room, me.user_id);
|
||||
|
||||
if(!my_room.has("m.room.name", ""))
|
||||
send(my_room, me.user_id, "m.room.name", "",
|
||||
{
|
||||
{ "name", "IRCd's Room" }
|
||||
});
|
||||
|
||||
if(!my_room.has("m.room.topic", ""))
|
||||
send(my_room, me.user_id, "m.room.topic", "",
|
||||
{
|
||||
{ "topic", "The daemon's den." }
|
||||
});
|
||||
|
||||
if(!exists(user::tokens))
|
||||
create(user::tokens, me.user_id);
|
||||
|
||||
if(!user::tokens.has("m.room.name",""))
|
||||
send(user::tokens, me.user_id, "m.room.name", "",
|
||||
{
|
||||
{ "name", "User Tokens" }
|
||||
});
|
||||
|
||||
log::info
|
||||
{
|
||||
log, "Bootstrap event generation completed nominally."
|
||||
};
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
throw ircd::panic
|
||||
{
|
||||
"bootstrap error :%s", e.what()
|
||||
};
|
||||
}
|
|
@ -476,7 +476,7 @@ ircd::m::keys::cache::set(const json::object &keys)
|
|||
};
|
||||
|
||||
if(!exists(node_room.room_id))
|
||||
create(node_room, m::me.user_id);
|
||||
create(node_room, me());
|
||||
|
||||
const json::object &vks
|
||||
{
|
||||
|
@ -490,7 +490,7 @@ ircd::m::keys::cache::set(const json::object &keys)
|
|||
return ret;
|
||||
|
||||
const auto &key_id(unquote(member.first));
|
||||
send(node_room, m::me.user_id, "ircd.key", key_id, keys);
|
||||
send(node_room, me(), "ircd.key", key_id, keys);
|
||||
++ret;
|
||||
}
|
||||
|
||||
|
|
324
matrix/matrix.cc
324
matrix/matrix.cc
|
@ -28,169 +28,12 @@ ircd::m::log
|
|||
"m", 'm'
|
||||
};
|
||||
|
||||
//
|
||||
// init
|
||||
//
|
||||
|
||||
/// --- tmp ---
|
||||
|
||||
extern "C" void
|
||||
reload_conf();
|
||||
|
||||
namespace ircd::m
|
||||
{
|
||||
std::unique_ptr<dbs::init> _dbs;
|
||||
std::unique_ptr<fetch::init> _fetch;
|
||||
std::unique_ptr<init::modules> _modules;
|
||||
}
|
||||
|
||||
/// --- /tmp ---
|
||||
|
||||
void
|
||||
ircd::m::on_load()
|
||||
try
|
||||
{
|
||||
assert(ircd::run::level == run::level::START);
|
||||
m::self::init::keys();
|
||||
_dbs = std::make_unique<dbs::init>(ircd::server_name, std::string{});
|
||||
reload_conf();
|
||||
_fetch = std::make_unique<fetch::init>();
|
||||
_modules = std::make_unique<init::modules>();
|
||||
self::signon();
|
||||
}
|
||||
catch(const m::error &e)
|
||||
{
|
||||
log::error
|
||||
{
|
||||
log, "Failed to start matrix (%u) %s :%s :%s",
|
||||
uint(e.code),
|
||||
http::status(e.code),
|
||||
e.errcode(),
|
||||
e.errstr(),
|
||||
};
|
||||
|
||||
throw;
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
log::error
|
||||
{
|
||||
log, "Failed to start matrix :%s", e.what()
|
||||
};
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::on_unload()
|
||||
noexcept try
|
||||
{
|
||||
mods::imports.erase("m_listen"s);
|
||||
|
||||
if(m::sync::pool.size())
|
||||
m::sync::pool.join();
|
||||
|
||||
self::signoff();
|
||||
_fetch.reset(nullptr);
|
||||
_modules.reset(nullptr);
|
||||
_dbs.reset(nullptr);
|
||||
|
||||
//TODO: remove this for non-interfering shutdown
|
||||
server::interrupt_all();
|
||||
client::terminate_all();
|
||||
client::close_all();
|
||||
server::close_all();
|
||||
server::wait_all();
|
||||
client::wait_all();
|
||||
}
|
||||
catch(const m::error &e)
|
||||
{
|
||||
log::critical
|
||||
{
|
||||
log, "%s %s", e.what(), e.content
|
||||
};
|
||||
|
||||
ircd::terminate();
|
||||
}
|
||||
|
||||
//
|
||||
// init::modules
|
||||
//
|
||||
|
||||
namespace ircd::m
|
||||
{
|
||||
extern const std::vector<string_view> module_names;
|
||||
extern const std::vector<string_view> module_names_optional;
|
||||
}
|
||||
|
||||
ircd::m::init::modules::modules()
|
||||
{
|
||||
const unwind::exceptional unload{[this]
|
||||
{
|
||||
this->fini_imports();
|
||||
}};
|
||||
|
||||
init_imports();
|
||||
}
|
||||
|
||||
ircd::m::init::modules::~modules()
|
||||
noexcept
|
||||
{
|
||||
fini_imports();
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::init::modules::init_imports()
|
||||
{
|
||||
if(!bool(ircd::mods::autoload))
|
||||
{
|
||||
log::warning
|
||||
{
|
||||
"Not loading modules because noautomod flag is set. "
|
||||
"You may still load modules manually."
|
||||
};
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for(const auto &name : module_names) try
|
||||
{
|
||||
mods::imports.emplace(name, name);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
const auto &optional(module_names_optional);
|
||||
if(std::count(begin(optional), end(optional), name))
|
||||
continue;
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
if(vm::sequence::retired == 0)
|
||||
{
|
||||
log::notice
|
||||
{
|
||||
log, "This appears to be your first time running IRCd because the events "
|
||||
"database is empty. I will be bootstrapping it with initial events now..."
|
||||
};
|
||||
|
||||
m::init::bootstrap{};
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::init::modules::fini_imports()
|
||||
noexcept
|
||||
{
|
||||
for(auto it(module_names.rbegin()); it != module_names.rend(); ++it)
|
||||
mods::imports.erase(*it);
|
||||
}
|
||||
|
||||
/// This is an ordered list for loading and unloading modules. This is not the
|
||||
/// solution I really want at all so consider it temporary. Modules are loaded
|
||||
/// in the order of the lines and unloaded in reverse order.
|
||||
decltype(ircd::m::module_names)
|
||||
ircd::m::module_names
|
||||
IRCD_MODULE_EXPORT_DATA
|
||||
decltype(ircd::m::matrix::module_names)
|
||||
ircd::m::matrix::module_names
|
||||
{
|
||||
"m_noop",
|
||||
"m_breadcrumb_rooms",
|
||||
|
@ -313,8 +156,165 @@ ircd::m::module_names
|
|||
|
||||
/// This is a list of modules that are considered "optional" and any loading
|
||||
/// error for them will not propagate and interrupt m::init.
|
||||
decltype(ircd::m::module_names_optional)
|
||||
ircd::m::module_names_optional
|
||||
IRCD_MODULE_EXPORT_DATA
|
||||
decltype(ircd::m::matrix::module_names_optional)
|
||||
ircd::m::matrix::module_names_optional
|
||||
{
|
||||
"web_hook",
|
||||
};
|
||||
|
||||
//
|
||||
// init
|
||||
//
|
||||
|
||||
/// --- tmp ---
|
||||
|
||||
extern "C" void
|
||||
reload_conf();
|
||||
|
||||
namespace ircd::m::init
|
||||
{
|
||||
struct modules;
|
||||
}
|
||||
|
||||
namespace ircd::m
|
||||
{
|
||||
std::unique_ptr<dbs::init> _dbs;
|
||||
std::unique_ptr<fetch::init> _fetch;
|
||||
//std::unique_ptr<init::modules> _modules;
|
||||
}
|
||||
|
||||
/// --- /tmp ---
|
||||
|
||||
void
|
||||
ircd::m::on_load()
|
||||
try
|
||||
{
|
||||
assert(ircd::run::level == run::level::START);
|
||||
//reload_conf();
|
||||
_fetch = std::make_unique<fetch::init>();
|
||||
//_modules = std::make_unique<init::modules>();
|
||||
//self::signon();
|
||||
}
|
||||
catch(const m::error &e)
|
||||
{
|
||||
log::error
|
||||
{
|
||||
log, "Failed to start matrix (%u) %s :%s :%s",
|
||||
uint(e.code),
|
||||
http::status(e.code),
|
||||
e.errcode(),
|
||||
e.errstr(),
|
||||
};
|
||||
|
||||
throw;
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
log::error
|
||||
{
|
||||
log, "Failed to start matrix :%s", e.what()
|
||||
};
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::on_unload()
|
||||
noexcept try
|
||||
{
|
||||
//mods::imports.erase("m_listen"s);
|
||||
|
||||
if(m::sync::pool.size())
|
||||
m::sync::pool.join();
|
||||
|
||||
//self::signoff();
|
||||
_fetch.reset(nullptr);
|
||||
//_modules.reset(nullptr);
|
||||
|
||||
//TODO: remove this for non-interfering shutdown
|
||||
//server::interrupt_all();
|
||||
//client::terminate_all();
|
||||
//client::close_all();
|
||||
//server::close_all();
|
||||
//server::wait_all();
|
||||
//client::wait_all();
|
||||
}
|
||||
catch(const m::error &e)
|
||||
{
|
||||
log::critical
|
||||
{
|
||||
log, "%s %s", e.what(), e.content
|
||||
};
|
||||
|
||||
ircd::terminate();
|
||||
}
|
||||
|
||||
//
|
||||
// init::modules
|
||||
//
|
||||
|
||||
/*
|
||||
ircd::m::init::modules::modules()
|
||||
{
|
||||
const unwind::exceptional unload{[this]
|
||||
{
|
||||
this->fini_imports();
|
||||
}};
|
||||
|
||||
init_imports();
|
||||
}
|
||||
|
||||
ircd::m::init::modules::~modules()
|
||||
noexcept
|
||||
{
|
||||
fini_imports();
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::init::modules::init_imports()
|
||||
{
|
||||
if(!bool(ircd::mods::autoload))
|
||||
{
|
||||
log::warning
|
||||
{
|
||||
"Not loading modules because noautomod flag is set. "
|
||||
"You may still load modules manually."
|
||||
};
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for(const auto &name : module_names) try
|
||||
{
|
||||
mods::imports.emplace(name, name);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
const auto &optional(module_names_optional);
|
||||
if(std::count(begin(optional), end(optional), name))
|
||||
continue;
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
if(vm::sequence::retired == 0)
|
||||
{
|
||||
log::notice
|
||||
{
|
||||
log, "This appears to be your first time running IRCd because the events "
|
||||
"database is empty. I will be bootstrapping it with initial events now..."
|
||||
};
|
||||
|
||||
m::init::bootstrap{};
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::init::modules::fini_imports()
|
||||
noexcept
|
||||
{
|
||||
for(auto it(module_names.rbegin()); it != module_names.rend(); ++it)
|
||||
mods::imports.erase(*it);
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -123,7 +123,7 @@ ircd::m::create(const node &node,
|
|||
node.room_id()
|
||||
};
|
||||
|
||||
create(room_id, m::me.user_id);
|
||||
create(room_id, me());
|
||||
return node;
|
||||
}
|
||||
|
||||
|
|
|
@ -99,11 +99,29 @@ const
|
|||
thread_local char x_matrix[2_KiB];
|
||||
if(startswith(json::at<"uri"_>(*this), "/_matrix/federation"))
|
||||
{
|
||||
const auto &sk{self::secret_key};
|
||||
const auto &pkid{self::public_key_id};
|
||||
const json::string &origin
|
||||
{
|
||||
json::at<"origin"_>(*this)
|
||||
};
|
||||
|
||||
const auto &my
|
||||
{
|
||||
m::my(origin)
|
||||
};
|
||||
|
||||
const auto &secret_key
|
||||
{
|
||||
m::secret_key(my)
|
||||
};
|
||||
|
||||
const auto &public_key_id
|
||||
{
|
||||
m::public_key_id(my)
|
||||
};
|
||||
|
||||
header[headers++] =
|
||||
{
|
||||
"Authorization", generate(x_matrix, sk, pkid)
|
||||
"Authorization", generate(x_matrix, secret_key, public_key_id)
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -169,14 +187,19 @@ const
|
|||
stringify(mutable_buffer{buf}, *this)
|
||||
};
|
||||
|
||||
const ed25519::sig sig
|
||||
const json::string &origin
|
||||
{
|
||||
self::secret_key.sign(object)
|
||||
json::at<"origin"_>(*this)
|
||||
};
|
||||
|
||||
const auto &origin
|
||||
const auto &secret_key
|
||||
{
|
||||
unquote(string_view{json::at<"origin"_>(*this)})
|
||||
m::secret_key(my(origin))
|
||||
};
|
||||
|
||||
const ed25519::sig sig
|
||||
{
|
||||
secret_key.sign(object)
|
||||
};
|
||||
|
||||
thread_local char sigb64[1_KiB];
|
||||
|
|
|
@ -212,9 +212,14 @@ ircd::m::authenticate_user(const resource::method &method,
|
|||
m::event::keys::include {"sender"}
|
||||
};
|
||||
|
||||
const m::room::id::buf tokens_room
|
||||
{
|
||||
"tokens", origin(my())
|
||||
};
|
||||
|
||||
const m::room::state tokens
|
||||
{
|
||||
m::user::tokens, &fopts
|
||||
tokens_room, &fopts
|
||||
};
|
||||
|
||||
tokens.get(std::nothrow, "ircd.access_token", request.access_token, [&request]
|
||||
|
|
|
@ -107,7 +107,7 @@ ircd::m::event::id::buf
|
|||
ircd::m::notice(const room &room,
|
||||
const string_view &body)
|
||||
{
|
||||
return message(room, me.user_id, body, "m.notice");
|
||||
return message(room, me(), body, "m.notice");
|
||||
}
|
||||
|
||||
ircd::m::event::id::buf
|
||||
|
@ -744,7 +744,12 @@ ircd::m::local_joined(const room &room)
|
|||
room
|
||||
};
|
||||
|
||||
return !members.empty("join", my_host());
|
||||
return !for_each([&members]
|
||||
(const homeserver &homeserver)
|
||||
{
|
||||
// return false to break and return false; true to continue
|
||||
return members.empty("join", origin(homeserver));
|
||||
});
|
||||
}
|
||||
|
||||
/// Member(s) from another server are presently joined to the room. For example
|
||||
|
@ -848,7 +853,7 @@ ircd::m::internal(const id::room &room_id)
|
|||
if(!exists(room))
|
||||
return false;
|
||||
|
||||
if(!creator(room, m::me))
|
||||
if(!creator(room, me()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -868,7 +873,7 @@ ircd::m::exists(const id::room &room_id)
|
|||
if(likely(it.depth() < 2UL))
|
||||
return true;
|
||||
|
||||
if(my_host(room_id.host()) && creator(room_id, m::me))
|
||||
if(my_host(room_id.host()) && creator(room_id, me()))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
|
|
@ -12,22 +12,8 @@ namespace ircd::m
|
|||
{
|
||||
extern conf::item<seconds> alias_fetch_timeout;
|
||||
extern conf::item<seconds> alias_cache_ttl;
|
||||
extern const room::id::buf alias_room_id;
|
||||
extern const room alias_room;
|
||||
}
|
||||
|
||||
decltype(ircd::m::alias_room_id)
|
||||
ircd::m::alias_room_id
|
||||
{
|
||||
"alias", ircd::my_host()
|
||||
};
|
||||
|
||||
decltype(ircd::m::alias_room)
|
||||
ircd::m::alias_room
|
||||
{
|
||||
alias_room_id
|
||||
};
|
||||
|
||||
decltype(ircd::m::alias_cache_ttl)
|
||||
ircd::m::alias_cache_ttl
|
||||
{
|
||||
|
@ -168,6 +154,16 @@ ircd::m::room::aliases::cache::del(const alias &alias)
|
|||
make_key(buf, alias)
|
||||
};
|
||||
|
||||
const m::room::id::buf alias_room_id
|
||||
{
|
||||
"alias", origin(my())
|
||||
};
|
||||
|
||||
const m::room alias_room
|
||||
{
|
||||
alias_room_id
|
||||
};
|
||||
|
||||
const auto &event_idx
|
||||
{
|
||||
alias_room.get(std::nothrow, "ircd.room.alias", key)
|
||||
|
@ -186,7 +182,7 @@ ircd::m::room::aliases::cache::del(const alias &alias)
|
|||
|
||||
const auto ret
|
||||
{
|
||||
redact(alias_room, m::me.user_id, event_id, "deleted")
|
||||
redact(alias_room, me(), event_id, "deleted")
|
||||
};
|
||||
|
||||
return true;
|
||||
|
@ -203,9 +199,19 @@ ircd::m::room::aliases::cache::set(const alias &alias,
|
|||
make_key(buf, alias)
|
||||
};
|
||||
|
||||
const m::room::id::buf alias_room_id
|
||||
{
|
||||
"alias", origin(my())
|
||||
};
|
||||
|
||||
const m::room alias_room
|
||||
{
|
||||
alias_room_id
|
||||
};
|
||||
|
||||
const auto ret
|
||||
{
|
||||
send(alias_room, m::me.user_id, "ircd.room.alias", key,
|
||||
send(alias_room, me(), "ircd.room.alias", key,
|
||||
{
|
||||
{ "room_id", id }
|
||||
})
|
||||
|
@ -427,9 +433,14 @@ IRCD_MODULE_EXPORT
|
|||
ircd::m::room::aliases::cache::for_each(const string_view &server,
|
||||
const closure_bool &closure)
|
||||
{
|
||||
const m::room::id::buf alias_room_id
|
||||
{
|
||||
"alias", origin(my())
|
||||
};
|
||||
|
||||
const m::room::state state
|
||||
{
|
||||
alias_room
|
||||
alias_room_id
|
||||
};
|
||||
|
||||
bool ret{true};
|
||||
|
@ -574,6 +585,16 @@ ircd::m::room::aliases::cache::getidx(const alias &alias)
|
|||
tolower(buf, swapped)
|
||||
};
|
||||
|
||||
const m::room::id::buf alias_room_id
|
||||
{
|
||||
"alias", origin(my())
|
||||
};
|
||||
|
||||
const m::room alias_room
|
||||
{
|
||||
alias_room_id
|
||||
};
|
||||
|
||||
const auto &event_idx
|
||||
{
|
||||
alias_room.get(std::nothrow, "ircd.room.alias", key)
|
||||
|
|
|
@ -13,16 +13,9 @@ namespace ircd::m::rooms::summary
|
|||
static void chunk_remote(const room &, json::stack::object &o);
|
||||
static void chunk_local(const room &, json::stack::object &o);
|
||||
|
||||
extern const room::id::buf public_room_id;
|
||||
extern hookfn<vm::eval &> create_public_room;
|
||||
}
|
||||
|
||||
decltype(ircd::m::rooms::summary::public_room_id)
|
||||
ircd::m::rooms::summary::public_room_id
|
||||
{
|
||||
"public", ircd::my_host()
|
||||
};
|
||||
|
||||
/// Create the public rooms room during initial database bootstrap.
|
||||
/// This hooks the creation of the !ircd room which is a fundamental
|
||||
/// event indicating the database has just been created.
|
||||
|
@ -34,9 +27,19 @@ ircd::m::rooms::summary::create_public_room
|
|||
{ "room_id", "!ircd" },
|
||||
{ "type", "m.room.create" },
|
||||
},
|
||||
[](const m::event &, m::vm::eval &)
|
||||
[](const m::event &event, m::vm::eval &)
|
||||
{
|
||||
m::create(public_room_id, m::me.user_id);
|
||||
auto &my
|
||||
{
|
||||
m::my(at<"origin"_>(event))
|
||||
};
|
||||
|
||||
const auto &public_room_id
|
||||
{
|
||||
*my.rooms.emplace("public", origin(my)).first
|
||||
};
|
||||
|
||||
m::create(public_room_id, me());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -140,6 +143,11 @@ IRCD_MODULE_EXPORT
|
|||
ircd::m::rooms::summary::del(const m::room &room,
|
||||
const string_view &origin)
|
||||
{
|
||||
const m::room::id::buf public_room_id
|
||||
{
|
||||
"public", my_host()
|
||||
};
|
||||
|
||||
const m::room::state state
|
||||
{
|
||||
public_room_id
|
||||
|
@ -164,7 +172,7 @@ ircd::m::rooms::summary::del(const m::room &room,
|
|||
m::event_id(event_idx)
|
||||
};
|
||||
|
||||
return redact(public_room_id, m::me, event_id, "delisted");
|
||||
return redact(public_room_id, me(), event_id, "delisted");
|
||||
}
|
||||
|
||||
ircd::m::event::id::buf
|
||||
|
@ -197,13 +205,19 @@ ircd::m::rooms::summary::set(const m::room::id &room_id,
|
|||
const string_view &origin,
|
||||
const json::object &summary)
|
||||
{
|
||||
const m::room::id::buf public_room_id
|
||||
{
|
||||
"public", my_host()
|
||||
};
|
||||
|
||||
|
||||
char state_key_buf[event::STATE_KEY_MAX_SIZE];
|
||||
const auto state_key
|
||||
{
|
||||
make_state_key(state_key_buf, room_id, origin)
|
||||
};
|
||||
|
||||
return send(public_room_id, m::me, "ircd.rooms.summary", state_key, summary);
|
||||
return send(public_room_id, me(), "ircd.rooms.summary", state_key, summary);
|
||||
}
|
||||
|
||||
ircd::json::object
|
||||
|
@ -275,6 +289,11 @@ IRCD_MODULE_EXPORT
|
|||
ircd::m::rooms::summary::for_each(const room::id &room_id,
|
||||
const closure_idx &closure)
|
||||
{
|
||||
const m::room::id::buf public_room_id
|
||||
{
|
||||
"public", my_host()
|
||||
};
|
||||
|
||||
const m::room::state state
|
||||
{
|
||||
public_room_id
|
||||
|
|
215
matrix/self.cc
215
matrix/self.cc
|
@ -1,215 +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.
|
||||
|
||||
std::string
|
||||
ircd::m::self::origin
|
||||
{
|
||||
ircd::string_view{ircd::network_name}
|
||||
};
|
||||
|
||||
std::string
|
||||
ircd::m::self::servername
|
||||
{
|
||||
ircd::string_view{ircd::server_name}
|
||||
};
|
||||
|
||||
ircd::ed25519::sk
|
||||
ircd::m::self::secret_key
|
||||
{};
|
||||
|
||||
ircd::ed25519::pk
|
||||
ircd::m::self::public_key
|
||||
{};
|
||||
|
||||
std::string
|
||||
ircd::m::self::public_key_b64
|
||||
{};
|
||||
|
||||
std::string
|
||||
ircd::m::self::public_key_id
|
||||
{};
|
||||
|
||||
std::string
|
||||
ircd::m::self::tls_cert_der
|
||||
{};
|
||||
|
||||
std::string
|
||||
ircd::m::self::tls_cert_der_sha256_b64
|
||||
{};
|
||||
|
||||
//
|
||||
// my user
|
||||
//
|
||||
|
||||
ircd::m::user::id::buf
|
||||
ircd_user_id
|
||||
{
|
||||
"ircd", ircd::my_host()
|
||||
};
|
||||
|
||||
ircd::m::user
|
||||
ircd::m::me
|
||||
{
|
||||
ircd_user_id
|
||||
};
|
||||
|
||||
//
|
||||
// my room
|
||||
//
|
||||
|
||||
ircd::m::room::id::buf
|
||||
ircd_room_id
|
||||
{
|
||||
"ircd", ircd::my_host()
|
||||
};
|
||||
|
||||
ircd::m::room
|
||||
ircd::m::my_room
|
||||
{
|
||||
ircd_room_id
|
||||
};
|
||||
|
||||
//
|
||||
// my node
|
||||
//
|
||||
|
||||
ircd::m::node
|
||||
ircd::m::my_node
|
||||
{
|
||||
ircd::my_host()
|
||||
};
|
||||
|
||||
//
|
||||
// signon/signoff greetings
|
||||
//
|
||||
|
||||
ircd::conf::item<std::string>
|
||||
me_online_status_msg
|
||||
{
|
||||
{ "name", "ircd.me.online.status_msg" },
|
||||
{ "default", "Wanna chat? IRCd at your service!" }
|
||||
};
|
||||
|
||||
ircd::conf::item<std::string>
|
||||
me_offline_status_msg
|
||||
{
|
||||
{ "name", "ircd.me.offline.status_msg" },
|
||||
{ "default", "Catch ya on the flip side..." }
|
||||
};
|
||||
|
||||
void
|
||||
ircd::m::self::signon()
|
||||
{
|
||||
if(!ircd::write_avoid && vm::sequence::retired != 0)
|
||||
presence::set(me, "online", me_online_status_msg);
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::self::signoff()
|
||||
{
|
||||
if(!std::uncaught_exceptions() && !ircd::write_avoid)
|
||||
presence::set(me, "offline", me_offline_status_msg);
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::self::host(const string_view &other)
|
||||
{
|
||||
// port() is 0 when the origin has no port (and implies 8448)
|
||||
const auto port
|
||||
{
|
||||
net::port(hostport(origin))
|
||||
};
|
||||
|
||||
// If my_host has a port number, then the argument must also have the
|
||||
// same port number.
|
||||
if(port)
|
||||
return host() == other;
|
||||
|
||||
/// 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);
|
||||
const net::hostport _other{other};
|
||||
if(net::port(_other) != net::canon_port)
|
||||
return false;
|
||||
|
||||
if(host() != host(_other))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ircd::string_view
|
||||
ircd::m::self::host()
|
||||
{
|
||||
return m::self::origin;
|
||||
}
|
||||
|
||||
//
|
||||
// init
|
||||
//
|
||||
|
||||
/// ID of the room which stores ephemeral tokens (an instance of the room is
|
||||
/// provided below).
|
||||
ircd::m::room::id::buf
|
||||
tokens_room_id
|
||||
{
|
||||
"tokens", ircd::my_host()
|
||||
};
|
||||
|
||||
/// The tokens room serves as a key-value lookup for various tokens to
|
||||
/// users, etc. It primarily serves to store access tokens for users. This
|
||||
/// is a separate room from the users room because in the future it may
|
||||
/// have an optimized configuration as well as being more easily cleared.
|
||||
///
|
||||
ircd::m::room
|
||||
ircd::m::user::tokens
|
||||
{
|
||||
tokens_room_id
|
||||
};
|
||||
|
||||
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.
|
||||
rfc3986::valid_host(origin);
|
||||
rfc3986::valid_host(servername);
|
||||
|
||||
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;
|
||||
}()};
|
|
@ -67,7 +67,7 @@ ircd::m::create_user_room(const user::id &user_id,
|
|||
const json::members &contents)
|
||||
try
|
||||
{
|
||||
return create(room_id, m::me.user_id, "user");
|
||||
return create(room_id, me(), "user");
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
|
@ -115,16 +115,26 @@ const
|
|||
char b58[size(hash) * 2];
|
||||
return
|
||||
{
|
||||
buf, b58encode(b58, hash), my_host()
|
||||
buf, b58encode(b58, hash), origin(my())
|
||||
};
|
||||
}
|
||||
|
||||
ircd::m::device::id::buf
|
||||
ircd::m::user::get_device_from_access_token(const string_view &token)
|
||||
{
|
||||
const m::room::id::buf tokens_room_id
|
||||
{
|
||||
"tokens", origin(my())
|
||||
};
|
||||
|
||||
const m::room tokens
|
||||
{
|
||||
tokens_room_id
|
||||
};
|
||||
|
||||
const event::idx event_idx
|
||||
{
|
||||
user::tokens.get("ircd.access_token", token)
|
||||
tokens.get("ircd.access_token", token)
|
||||
};
|
||||
|
||||
device::id::buf ret;
|
||||
|
|
|
@ -45,7 +45,7 @@ const
|
|||
// specified. TODO: isn't that guest reg?
|
||||
const m::id::user::buf user_id
|
||||
{
|
||||
username, my_host()
|
||||
username, origin(my())
|
||||
};
|
||||
|
||||
// Check if the the user_id is acceptably formed for this server or throws
|
||||
|
@ -155,9 +155,14 @@ const
|
|||
json::STRING
|
||||
};
|
||||
|
||||
const m::room::id::buf user_tokens
|
||||
{
|
||||
"tokens", user_id.host()
|
||||
};
|
||||
|
||||
const m::event::id::buf access_token_id
|
||||
{
|
||||
m::send(m::user::tokens, user_id, "ircd.access_token", access_token, json::members
|
||||
m::send(user_tokens, user_id, "ircd.access_token", access_token, json::members
|
||||
{
|
||||
{ "ip", last_seen_ip },
|
||||
{ "device_id", device_id },
|
||||
|
|
|
@ -43,7 +43,7 @@ void
|
|||
ircd::m::app::init()
|
||||
{
|
||||
if(!m::exists(app_room_id))
|
||||
m::create(app_room_id, m::me, "internal");
|
||||
m::create(app_room_id, me(), "internal");
|
||||
|
||||
init_apps();
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ activate__user(const m::user &user)
|
|||
user
|
||||
};
|
||||
|
||||
return send(user_room, m::me.user_id, "ircd.account", "active", json::members
|
||||
return send(user_room, m::me(), "ircd.account", "active", json::members
|
||||
{
|
||||
{ "value", true }
|
||||
});
|
||||
|
|
|
@ -74,7 +74,7 @@ deactivate__user(const m::user &user,
|
|||
user
|
||||
};
|
||||
|
||||
return send(user_room, m::me.user_id, "ircd.account", "active", json::members
|
||||
return send(user_room, m::me(), "ircd.account", "active", json::members
|
||||
{
|
||||
{ "value", false }
|
||||
});
|
||||
|
|
|
@ -110,12 +110,17 @@ post__login_password(client &client,
|
|||
string(remote_buf, remote(client)), json::STRING
|
||||
};
|
||||
|
||||
const m::room::id::buf tokens_room
|
||||
{
|
||||
"tokens", origin(m::my())
|
||||
};
|
||||
|
||||
// Log the user in by issuing an event in the tokens room containing
|
||||
// the generated token. When this call completes without throwing the
|
||||
// access_token will be committed and the user will be logged in.
|
||||
const m::event::id::buf access_token_id
|
||||
{
|
||||
m::send(m::user::tokens, user_id, "ircd.access_token", access_token,
|
||||
m::send(tokens_room, user_id, "ircd.access_token", access_token,
|
||||
{
|
||||
{ "ip", last_seen_ip },
|
||||
{ "device_id", device_id },
|
||||
|
|
|
@ -76,9 +76,14 @@ post__logout(client &client,
|
|||
request.access_token
|
||||
};
|
||||
|
||||
const m::room::id::buf tokens_room_id
|
||||
{
|
||||
"tokens", origin(m::my())
|
||||
};
|
||||
|
||||
const m::room::state tokens
|
||||
{
|
||||
m::user::tokens
|
||||
tokens_room_id
|
||||
};
|
||||
|
||||
const auto token_event_idx
|
||||
|
@ -98,9 +103,14 @@ m::resource::response
|
|||
post__logout_all(client &client,
|
||||
const m::resource::request &request)
|
||||
{
|
||||
const m::room::id::buf tokens_room_id
|
||||
{
|
||||
"tokens", origin(m::my())
|
||||
};
|
||||
|
||||
const m::room::state tokens
|
||||
{
|
||||
m::user::tokens
|
||||
tokens_room_id
|
||||
};
|
||||
|
||||
long count(0);
|
||||
|
@ -145,9 +155,14 @@ try
|
|||
m::event_id(token_event_idx)
|
||||
};
|
||||
|
||||
const m::room::id::buf tokens_room_id
|
||||
{
|
||||
"tokens", origin(m::my())
|
||||
};
|
||||
|
||||
const auto redaction_event_id
|
||||
{
|
||||
m::redact(m::user::tokens, user_id, token_event_id, reason)
|
||||
m::redact(tokens_room_id, user_id, token_event_id, reason)
|
||||
};
|
||||
|
||||
return true;
|
||||
|
|
|
@ -14,12 +14,6 @@ using namespace ircd;
|
|||
|
||||
static void create_report_room(const m::event &, m::vm::eval &);
|
||||
|
||||
const m::room::id::buf
|
||||
report_room_id
|
||||
{
|
||||
"abuse", m::my_host()
|
||||
};
|
||||
|
||||
conf::item<size_t>
|
||||
reason_max
|
||||
{
|
||||
|
@ -78,6 +72,11 @@ post__report(client &client,
|
|||
request.at("reason")
|
||||
};
|
||||
|
||||
const m::room::id::buf report_room_id
|
||||
{
|
||||
"abuse", request.user_id.host()
|
||||
};
|
||||
|
||||
const m::room room
|
||||
{
|
||||
report_room_id
|
||||
|
@ -104,16 +103,26 @@ post__report(client &client,
|
|||
}
|
||||
|
||||
void
|
||||
create_report_room(const m::event &,
|
||||
create_report_room(const m::event &event,
|
||||
m::vm::eval &)
|
||||
try
|
||||
{
|
||||
const auto &origin
|
||||
{
|
||||
at<"origin"_>(event)
|
||||
};
|
||||
|
||||
const m::room::id::buf report_room_id
|
||||
{
|
||||
"abuse", origin
|
||||
};
|
||||
|
||||
if(m::exists(report_room_id))
|
||||
return;
|
||||
|
||||
const m::room room
|
||||
{
|
||||
m::create(report_room_id, m::me, "internal")
|
||||
m::create(report_room_id, m::my(origin).self, "internal")
|
||||
};
|
||||
|
||||
log::debug
|
||||
|
@ -126,8 +135,7 @@ catch(const std::exception &e)
|
|||
{
|
||||
log::critical
|
||||
{
|
||||
m::log, "Creating the '%s' room failed :%s",
|
||||
string_view{report_room_id},
|
||||
m::log, "Creating the !abuse room failed :%s",
|
||||
e.what()
|
||||
};
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ ircd::m::sync::room_timeline_linear(data &data)
|
|||
{
|
||||
*data.room == data.user_room &&
|
||||
startswith(json::get<"type"_>(*data.event), "ircd.cmd") &&
|
||||
(json::get<"sender"_>(*data.event) == m::me.user_id ||
|
||||
(json::get<"sender"_>(*data.event) == me() ||
|
||||
json::get<"sender"_>(*data.event) == data.user.user_id)
|
||||
};
|
||||
|
||||
|
|
|
@ -1688,7 +1688,7 @@ console_cmd__conf__set(opt &out, const string_view &line)
|
|||
|
||||
const auto event_id
|
||||
{
|
||||
set_conf_item(m::me, key, val)
|
||||
set_conf_item(m::me(), key, val)
|
||||
};
|
||||
|
||||
out << event_id << " <- " << key << " = " << val << std::endl;
|
||||
|
@ -5506,9 +5506,14 @@ console_cmd__net__listen(opt &out, const string_view &line)
|
|||
for(const auto &[name, prop] : addl)
|
||||
opts = insert(opts, json::member(name, prop));
|
||||
|
||||
const m::room::id::buf my_room
|
||||
{
|
||||
"ircd", origin(m::my())
|
||||
};
|
||||
|
||||
const auto eid
|
||||
{
|
||||
m::send(m::my_room, m::me, "ircd.listen", token.at("name"), opts)
|
||||
m::send(my_room, m::me(), "ircd.listen", token.at("name"), opts)
|
||||
};
|
||||
|
||||
out << eid << std::endl;
|
||||
|
@ -5523,9 +5528,19 @@ console_cmd__net__listen__del(opt &out, const string_view &line)
|
|||
"name"
|
||||
}};
|
||||
|
||||
const m::room::id::buf my_room_id
|
||||
{
|
||||
"ircd", origin(m::my())
|
||||
};
|
||||
|
||||
const m::room my_room
|
||||
{
|
||||
my_room_id
|
||||
};
|
||||
|
||||
const auto event_idx
|
||||
{
|
||||
m::my_room.get("ircd.listen", token.at("name"))
|
||||
my_room.get("ircd.listen", token.at("name"))
|
||||
};
|
||||
|
||||
const auto event_id
|
||||
|
@ -5535,7 +5550,7 @@ console_cmd__net__listen__del(opt &out, const string_view &line)
|
|||
|
||||
const auto redact_id
|
||||
{
|
||||
m::redact(m::my_room, m::me, event_id, "deleted")
|
||||
m::redact(my_room, m::me(), event_id, "deleted")
|
||||
};
|
||||
|
||||
out << "Removed listener '" << token.at("name") << "' configuration. " << std::endl
|
||||
|
@ -5890,8 +5905,8 @@ console_cmd__key(opt &out, const string_view &line)
|
|||
if(!server_name)
|
||||
{
|
||||
out << "origin: " << m::my_host() << std::endl;
|
||||
out << "public key ID: " << m::self::public_key_id << std::endl;
|
||||
out << "public key base64: " << m::self::public_key_b64 << 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;
|
||||
}
|
||||
|
||||
|
@ -5950,14 +5965,6 @@ console_cmd__key__get(opt &out, const string_view &line)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
console_cmd__key__create(opt &out, const string_view &line)
|
||||
{
|
||||
m::self::create_my_key();
|
||||
out << "done" << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// stage
|
||||
//
|
||||
|
@ -6008,6 +6015,11 @@ console_cmd__stage(opt &out, const string_view &line)
|
|||
key? tokens_after(line, ' ', 1) : string_view{}
|
||||
};
|
||||
|
||||
const m::room::id::buf my_room
|
||||
{
|
||||
"ircd", origin(m::my())
|
||||
};
|
||||
|
||||
if(stage.size() == id)
|
||||
{
|
||||
m::event base_event{json::members
|
||||
|
@ -6015,8 +6027,8 @@ console_cmd__stage(opt &out, const string_view &line)
|
|||
{ "depth", json::undefined_number },
|
||||
{ "origin", my_host() },
|
||||
{ "origin_server_ts", time<milliseconds>() },
|
||||
{ "sender", m::me.user_id },
|
||||
{ "room_id", m::my_room.room_id },
|
||||
{ "sender", m::me() },
|
||||
{ "room_id", my_room },
|
||||
{ "type", "m.room.message" },
|
||||
{ "prev_state", "[]" },
|
||||
}};
|
||||
|
@ -10332,7 +10344,7 @@ console_cmd__room__create(opt &out, const string_view &line)
|
|||
|
||||
const m::user::id creator
|
||||
{
|
||||
param.at(1, m::me.user_id)
|
||||
param.at(1, m::me())
|
||||
};
|
||||
|
||||
const string_view type
|
||||
|
@ -10976,7 +10988,7 @@ console_cmd__user__read__ignore(opt &out, const string_view &line)
|
|||
|
||||
const auto eid
|
||||
{
|
||||
send(user_room, m::me.user_id, "ircd.read.ignore", target, json::object{})
|
||||
send(user_room, m::me(), "ircd.read.ignore", target, json::object{})
|
||||
};
|
||||
|
||||
out << "User " << my_user.user_id << " will not send receipts for"
|
||||
|
@ -11170,9 +11182,14 @@ console_cmd__user__tokens(opt &out, const string_view &line)
|
|||
param["clear"] == "clear"
|
||||
};
|
||||
|
||||
const m::room::id::buf tokens_room
|
||||
{
|
||||
"tokens", origin(m::my())
|
||||
};
|
||||
|
||||
const m::room::state &tokens
|
||||
{
|
||||
m::user::tokens
|
||||
tokens_room
|
||||
};
|
||||
|
||||
tokens.for_each("ircd.access_token", m::event::closure_idx{[&out, &user, &clear]
|
||||
|
@ -11216,12 +11233,16 @@ console_cmd__user__tokens(opt &out, const string_view &line)
|
|||
<< " "
|
||||
<< string_view{event.event_id};
|
||||
|
||||
|
||||
if(clear)
|
||||
{
|
||||
const m::room::id::buf tokens_room
|
||||
{
|
||||
"tokens", origin(m::my())
|
||||
};
|
||||
|
||||
const auto eid
|
||||
{
|
||||
m::redact(m::user::tokens, user.user_id, event.event_id, "cleared")
|
||||
m::redact(tokens_room, user.user_id, event.event_id, "cleared")
|
||||
};
|
||||
|
||||
out << " - cleared by " << eid;
|
||||
|
@ -12079,7 +12100,7 @@ console_cmd__feds__heads(opt &out, const string_view &line)
|
|||
|
||||
const m::user::id &user_id
|
||||
{
|
||||
param.at(1, m::me.user_id)
|
||||
param.at(1, m::me())
|
||||
};
|
||||
|
||||
using closure_prototype = bool (const string_view &,
|
||||
|
@ -13863,7 +13884,7 @@ console_cmd__file__download(opt &out, const string_view &line)
|
|||
|
||||
const auto room_id
|
||||
{
|
||||
m::media::file::download(mxc, m::me.user_id, remote)
|
||||
m::media::file::download(mxc, m::me(), remote)
|
||||
};
|
||||
|
||||
out << room_id << std::endl;
|
||||
|
|
|
@ -113,7 +113,7 @@ try
|
|||
|
||||
const auto &response_sender
|
||||
{
|
||||
public_response? user : m::me
|
||||
public_response? user : m::user(m::me())
|
||||
};
|
||||
|
||||
const auto &response_room
|
||||
|
|
|
@ -100,7 +100,7 @@ noexcept try
|
|||
"no alt text"
|
||||
};
|
||||
|
||||
msghtml(control_room, m::me.user_id, str, alt, "m.notice");
|
||||
msghtml(control_room, m::me(), str, alt, "m.notice");
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
|
@ -127,15 +127,15 @@ static void
|
|||
create_control_room(const m::event &,
|
||||
m::vm::eval &)
|
||||
{
|
||||
create(control_room_id, m::me.user_id);
|
||||
join(control_room, m::me.user_id);
|
||||
send(control_room, m::me.user_id, "m.room.name", "",
|
||||
create(control_room_id, m::me());
|
||||
join(control_room, m::me());
|
||||
send(control_room, m::me(), "m.room.name", "",
|
||||
{
|
||||
{ "name", "Control Room" }
|
||||
});
|
||||
|
||||
notice(control_room, m::me.user_id, "Welcome to the control room.");
|
||||
notice(control_room, m::me.user_id, "I am the daemon. You can talk to me in this room by highlighting me.");
|
||||
notice(control_room, m::me(), "Welcome to the control room.");
|
||||
notice(control_room, m::me(), "I am the daemon. You can talk to me in this room by highlighting me.");
|
||||
}
|
||||
|
||||
m::hookfn<m::vm::eval &>
|
||||
|
|
|
@ -56,6 +56,11 @@ ircd::m::_access_token_delete(const m::event &event,
|
|||
unquote(content.at(""))
|
||||
};
|
||||
|
||||
m::redact(m::user::tokens, at<"sender"_>(event), token_event_id, "device deleted");
|
||||
const m::room::id::buf tokens_room
|
||||
{
|
||||
"tokens", origin(m::my())
|
||||
};
|
||||
|
||||
m::redact(tokens_room, at<"sender"_>(event), token_event_id, "device deleted");
|
||||
});
|
||||
};
|
||||
|
|
|
@ -104,8 +104,17 @@ on_quit()
|
|||
void
|
||||
init_listeners()
|
||||
{
|
||||
m::room::state{m::my_room}.for_each("ircd.listen", []
|
||||
(const m::event &event)
|
||||
const m::room::id::buf my_room
|
||||
{
|
||||
"ircd", m::origin(m::my())
|
||||
};
|
||||
|
||||
const m::room::state state
|
||||
{
|
||||
my_room
|
||||
};
|
||||
|
||||
state.for_each("ircd.listen", [](const m::event &event)
|
||||
{
|
||||
load_listener(event);
|
||||
});
|
||||
|
@ -150,7 +159,16 @@ load_listener(const string_view &name)
|
|||
try
|
||||
{
|
||||
bool ret{false};
|
||||
const m::room::state state{m::my_room};
|
||||
const m::room::id::buf my_room
|
||||
{
|
||||
"ircd", m::origin(m::my())
|
||||
};
|
||||
|
||||
const m::room::state state
|
||||
{
|
||||
my_room
|
||||
};
|
||||
|
||||
state.get("ircd.listen", name, [&ret]
|
||||
(const m::event &event)
|
||||
{
|
||||
|
|
|
@ -28,18 +28,6 @@ IRCD_MODULE
|
|||
"Matrix m.room.aliases"
|
||||
};
|
||||
|
||||
decltype(ircd::m::alias_room_id)
|
||||
ircd::m::alias_room_id
|
||||
{
|
||||
"alias", ircd::my_host()
|
||||
};
|
||||
|
||||
decltype(ircd::m::alias_room)
|
||||
ircd::m::alias_room
|
||||
{
|
||||
alias_room_id
|
||||
};
|
||||
|
||||
//
|
||||
// create the alias room as an effect of !ircd created on bootstrap
|
||||
//
|
||||
|
@ -53,9 +41,19 @@ ircd::m::create_alias_room_hookfn
|
|||
{ "type", "m.room.create" },
|
||||
},
|
||||
|
||||
[](const m::event &, m::vm::eval &)
|
||||
[](const m::event &event, m::vm::eval &)
|
||||
{
|
||||
create(alias_room_id, m::me.user_id);
|
||||
auto &my
|
||||
{
|
||||
m::my(at<"origin"_>(event))
|
||||
};
|
||||
|
||||
const auto &alias_room_id
|
||||
{
|
||||
*my.rooms.emplace("alias", origin(my)).first
|
||||
};
|
||||
|
||||
create(alias_room_id, my.self);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ try
|
|||
|
||||
const auto &level
|
||||
{
|
||||
my(sender) && sender != m::me?
|
||||
my(sender) && sender != me()?
|
||||
log::INFO:
|
||||
log::DEBUG
|
||||
};
|
||||
|
|
|
@ -135,7 +135,7 @@ ircd::m::vm::init()
|
|||
log::info
|
||||
{
|
||||
log, "BOOT %s @%lu [%s] db:%lu",
|
||||
string_view{m::my_node.node_id},
|
||||
server_name(my()),
|
||||
sequence::retired,
|
||||
sequence::retired?
|
||||
string_view{event_id} : "NO EVENTS"_sv,
|
||||
|
@ -175,7 +175,7 @@ ircd::m::vm::fini()
|
|||
log::info
|
||||
{
|
||||
log, "HALT '%s' @%lu [%s] vm:%lu:%lu:%lu db:%lu",
|
||||
string_view{m::my_node.node_id},
|
||||
server_name(my()),
|
||||
retired,
|
||||
retired?
|
||||
string_view{event_id} : "NO EVENTS"_sv,
|
||||
|
|
|
@ -65,7 +65,7 @@ get__download(client &client,
|
|||
{
|
||||
request.user_id?
|
||||
m::user::id{request.user_id}:
|
||||
m::me.user_id
|
||||
m::me()
|
||||
};
|
||||
|
||||
const bool allow_remote
|
||||
|
|
|
@ -122,7 +122,7 @@ get__thumbnail(client &client,
|
|||
{
|
||||
request.user_id?
|
||||
m::user::id{request.user_id}:
|
||||
m::me.user_id
|
||||
m::me()
|
||||
};
|
||||
|
||||
if(!m::media::thumbnail::enable_remote)
|
||||
|
|
|
@ -172,7 +172,7 @@ try
|
|||
rr0.~object();
|
||||
array.~array();
|
||||
content.~object();
|
||||
send(room_id, m::me, type, state_key, json::object(out.completed()));
|
||||
send(room_id, m::me(), type, state_key, json::object(out.completed()));
|
||||
return true;
|
||||
}
|
||||
catch(const http::error &e)
|
||||
|
@ -297,7 +297,7 @@ try
|
|||
|
||||
array.~array();
|
||||
content.~object();
|
||||
send(room_id, m::me, type, state_key, json::object{out.completed()});
|
||||
send(room_id, m::me(), type, state_key, json::object{out.completed()});
|
||||
return true;
|
||||
}
|
||||
catch(const http::error &e)
|
||||
|
@ -695,7 +695,7 @@ try
|
|||
{
|
||||
const m::room room
|
||||
{
|
||||
m::create(room_id, m::me, "internal")
|
||||
m::create(room_id, m::me(), "internal")
|
||||
};
|
||||
|
||||
log::debug
|
||||
|
|
|
@ -80,7 +80,7 @@ handle_matrix_server(client &client,
|
|||
{
|
||||
client, json::members
|
||||
{
|
||||
{ "m.server", m::self::servername }
|
||||
{ "m.server", m::server_name(m::my()) }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue