mirror of
https://github.com/matrix-construct/construct
synced 2024-11-29 10:12:39 +01:00
ircd: Split up matrix.cc.
This commit is contained in:
parent
94aac875f1
commit
92c6f6c1a9
6 changed files with 4796 additions and 3645 deletions
|
@ -74,7 +74,10 @@ libircd_la_SOURCES = \
|
|||
lexical.cc \
|
||||
locale.cc \
|
||||
logger.cc \
|
||||
matrix.cc \
|
||||
m_id.cc \
|
||||
m_io.cc \
|
||||
m_vm.cc \
|
||||
m.cc \
|
||||
mods.cc \
|
||||
net.cc \
|
||||
openssl.cc \
|
||||
|
|
502
ircd/m_id.cc
Normal file
502
ircd/m_id.cc
Normal file
|
@ -0,0 +1,502 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Charybdis Development Team
|
||||
* Copyright (C) 2016 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <ircd/spirit.h>
|
||||
#include <ircd/server.h>
|
||||
#include <ircd/m/m.h>
|
||||
|
||||
namespace spirit = boost::spirit;
|
||||
namespace qi = spirit::qi;
|
||||
namespace ascii = qi::ascii;
|
||||
using namespace ircd;
|
||||
|
||||
using qi::lit;
|
||||
using qi::string;
|
||||
using qi::char_;
|
||||
using qi::short_;
|
||||
using qi::ushort_;
|
||||
using qi::int_;
|
||||
using qi::long_;
|
||||
using qi::repeat;
|
||||
using qi::omit;
|
||||
using qi::raw;
|
||||
using qi::attr;
|
||||
using qi::eps;
|
||||
using qi::attr_cast;
|
||||
|
||||
template<class it>
|
||||
struct grammar
|
||||
:qi::grammar<it, spirit::unused_type>
|
||||
{
|
||||
template<class R = spirit::unused_type, class... S> using rule = qi::rule<it, R, S...>;
|
||||
|
||||
rule<> NUL { lit('\0') ,"nul" };
|
||||
rule<> SP { lit('\x20') ,"space" };
|
||||
rule<> HT { lit('\x09') ,"horizontal tab" };
|
||||
rule<> ws { SP | HT ,"whitespace" };
|
||||
|
||||
rule<> CR { lit('\x0D') ,"carriage return" };
|
||||
rule<> LF { lit('\x0A') ,"line feed" };
|
||||
rule<> CRLF { CR >> LF ,"carriage return, line feed" };
|
||||
|
||||
rule<> illegal { NUL | CR | LF ,"illegal" };
|
||||
/*
|
||||
rule<string_view> authority
|
||||
{
|
||||
//TODO: https://tools.ietf.org/html/rfc3986#section-3.2
|
||||
-('/' >> '/') >> raw[*(char_ - '/')] >> '/'
|
||||
};
|
||||
*/
|
||||
const rule<> port
|
||||
{
|
||||
ushort_
|
||||
,"port"
|
||||
};
|
||||
|
||||
const rule<> ip6_address
|
||||
{
|
||||
//TODO: XXX
|
||||
*char_("0-9a-fA-F:")
|
||||
,"ip6 address"
|
||||
};
|
||||
|
||||
const rule<> ip6_literal
|
||||
{
|
||||
'[' >> ip6_address >> ']'
|
||||
,"ip6 literal"
|
||||
};
|
||||
|
||||
const rule<> dns_name
|
||||
{
|
||||
ip6_literal | *(char_ - ':')
|
||||
,"dns name"
|
||||
};
|
||||
|
||||
const rule<> server_name
|
||||
{
|
||||
dns_name >> -(':' >> port)
|
||||
,"server name"
|
||||
};
|
||||
|
||||
const rule<> sigil
|
||||
{
|
||||
lit(char(m::id::EVENT)) |
|
||||
lit(char(m::id::USER)) |
|
||||
lit(char(m::id::ROOM)) |
|
||||
lit(char(m::id::ALIAS))
|
||||
,"sigil"
|
||||
};
|
||||
|
||||
const rule<> localpart
|
||||
{
|
||||
sigil >> *(char_ - ':')
|
||||
,"localpart"
|
||||
};
|
||||
|
||||
const rule<> mxid
|
||||
{
|
||||
localpart >> ':' >> server_name
|
||||
,"mxid"
|
||||
};
|
||||
|
||||
grammar()
|
||||
:grammar::base_type{rule<>{}}
|
||||
{}
|
||||
};
|
||||
|
||||
struct ircd::m::id::parser
|
||||
:grammar<const char *>
|
||||
{
|
||||
struct validator;
|
||||
|
||||
const rule<string_view> mxid_view
|
||||
{
|
||||
raw[eps > mxid]
|
||||
};
|
||||
|
||||
string_view operator()(const id::sigil &, const string_view &id) const;
|
||||
string_view operator()(const string_view &id) const;
|
||||
}
|
||||
const ircd::m::id::parser;
|
||||
|
||||
ircd::string_view
|
||||
ircd::m::id::parser::operator()(const id::sigil &sigil,
|
||||
const string_view &id)
|
||||
const
|
||||
{
|
||||
string_view out;
|
||||
const char *start{id.data()};
|
||||
const char *const stop{id.data() + id.size()};
|
||||
qi::parse(start, stop, raw[mxid_view], out);
|
||||
return out;
|
||||
}
|
||||
|
||||
ircd::string_view
|
||||
ircd::m::id::parser::operator()(const string_view &id)
|
||||
const
|
||||
{
|
||||
string_view out;
|
||||
const char *start{id.data()};
|
||||
const char *const stop{id.data() + id.size()};
|
||||
qi::parse(start, stop, raw[mxid_view], out);
|
||||
return out;
|
||||
}
|
||||
|
||||
struct ircd::m::id::parser::validator
|
||||
:grammar<const char *>
|
||||
{
|
||||
const rule<> valid
|
||||
{
|
||||
mxid
|
||||
};
|
||||
|
||||
void operator()(const id::sigil &sigil, const string_view &id) const;
|
||||
void operator()(const string_view &id) const;
|
||||
}
|
||||
const validator;
|
||||
|
||||
void
|
||||
ircd::m::id::parser::validator::operator()(const string_view &id)
|
||||
const try
|
||||
{
|
||||
const char *start{id.data()};
|
||||
const char *const stop{id.data() + id.size()};
|
||||
qi::parse(start, stop, eps > valid);
|
||||
}
|
||||
catch(const qi::expectation_failure<const char *> &e)
|
||||
{
|
||||
const auto rule
|
||||
{
|
||||
ircd::string(e.what_)
|
||||
};
|
||||
|
||||
throw INVALID_MXID
|
||||
{
|
||||
"Not a valid mxid because of an invalid %s.",
|
||||
between(rule, '<', '>')
|
||||
};
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::id::parser::validator::operator()(const id::sigil &sigil,
|
||||
const string_view &id)
|
||||
const try
|
||||
{
|
||||
const char *start{id.data()};
|
||||
const char *const stop{id.data() + id.size()};
|
||||
qi::parse(start, stop, eps > valid);
|
||||
}
|
||||
catch(const qi::expectation_failure<const char *> &e)
|
||||
{
|
||||
const auto rule
|
||||
{
|
||||
ircd::string(e.what_)
|
||||
};
|
||||
|
||||
throw INVALID_MXID
|
||||
{
|
||||
"Not a valid '%s' mxid because of an invalid %s.",
|
||||
reflect(sigil),
|
||||
between(rule, '<', '>')
|
||||
};
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// m/id.h
|
||||
//
|
||||
|
||||
struct ircd::m::id::generator
|
||||
{
|
||||
static string_view random_timebased(const id::sigil &, const mutable_buffer &);
|
||||
static string_view random_prefixed(const id::sigil &, const string_view &prefix, const mutable_buffer &);
|
||||
};
|
||||
|
||||
ircd::m::id::id(const string_view &id)
|
||||
:string_view{id}
|
||||
{
|
||||
validate(m::sigil(id), id);
|
||||
}
|
||||
|
||||
ircd::m::id::id(const id::sigil &sigil,
|
||||
const string_view &id)
|
||||
:string_view{id}
|
||||
{
|
||||
validate(sigil, id);
|
||||
}
|
||||
|
||||
ircd::m::id::id(const id::sigil &sigil,
|
||||
const mutable_buffer &buf,
|
||||
const string_view &id)
|
||||
try
|
||||
:string_view
|
||||
{[&sigil, &buf, &id]
|
||||
{
|
||||
const string_view src
|
||||
{
|
||||
buffer::data(buf),
|
||||
buffer::data(buf) != id.data()? strlcpy(buffer::data(buf), id, buffer::size(buf)) : id.size()
|
||||
};
|
||||
|
||||
return parser(sigil, src);
|
||||
}()}
|
||||
{
|
||||
}
|
||||
catch(const qi::expectation_failure<const char *> &e)
|
||||
{
|
||||
const auto rule
|
||||
{
|
||||
ircd::string(e.what_)
|
||||
};
|
||||
|
||||
throw INVALID_MXID
|
||||
{
|
||||
"Not a valid '%s' mxid because of an invalid %s.",
|
||||
reflect(sigil),
|
||||
between(rule, '<', '>')
|
||||
};
|
||||
}
|
||||
|
||||
ircd::m::id::id(const enum sigil &sigil,
|
||||
const mutable_buffer &buf,
|
||||
const string_view &name,
|
||||
const string_view &host)
|
||||
:string_view{[&]() -> string_view
|
||||
{
|
||||
using buffer::data;
|
||||
using buffer::size;
|
||||
|
||||
const size_t &max{size(buf)};
|
||||
if(!max)
|
||||
return {};
|
||||
|
||||
size_t len(0);
|
||||
if(!startswith(name, sigil))
|
||||
buf[len++] = char(sigil);
|
||||
|
||||
const auto has_sep
|
||||
{
|
||||
std::count(std::begin(name), std::end(name), ':')
|
||||
};
|
||||
|
||||
if(!has_sep && host.empty())
|
||||
{
|
||||
len += strlcpy(data(buf) + len, name, max - len);
|
||||
}
|
||||
else if(!has_sep && !host.empty())
|
||||
{
|
||||
len += fmt::snprintf(data(buf) + len, max - len, "%s:%s",
|
||||
name,
|
||||
host);
|
||||
}
|
||||
else if(has_sep == 1 && !host.empty() && !split(name, ':').second.empty())
|
||||
{
|
||||
len += strlcpy(data(buf) + len, name, max - len);
|
||||
}
|
||||
else if(has_sep >= 1 && !host.empty())
|
||||
{
|
||||
if(split(name, ':').second != host)
|
||||
throw INVALID_MXID("MXID must be on host '%s'", host);
|
||||
|
||||
len += strlcpy(data(buf) + len, name, max - len);
|
||||
}
|
||||
//else throw INVALID_MXID("Not a valid '%s' mxid", reflect(sigil));
|
||||
|
||||
return { data(buf), len };
|
||||
}()}
|
||||
{
|
||||
validate(sigil, *this);
|
||||
}
|
||||
|
||||
ircd::m::id::id(const enum sigil &sigil,
|
||||
const mutable_buffer &buf,
|
||||
const generate_t &,
|
||||
const string_view &host)
|
||||
:string_view{[&]
|
||||
{
|
||||
char name[64]; switch(sigil)
|
||||
{
|
||||
case sigil::USER:
|
||||
generator::random_prefixed(sigil::USER, "guest", name);
|
||||
break;
|
||||
|
||||
case sigil::ALIAS:
|
||||
generator::random_prefixed(sigil::ALIAS, "", name);
|
||||
break;
|
||||
|
||||
default:
|
||||
generator::random_timebased(sigil, name);
|
||||
break;
|
||||
};
|
||||
|
||||
const auto len
|
||||
{
|
||||
fmt::sprintf(buf, "%s:%s", name, host)
|
||||
};
|
||||
|
||||
return string_view { buffer::data(buf), size_t(len) };
|
||||
}()}
|
||||
{
|
||||
}
|
||||
|
||||
ircd::string_view
|
||||
ircd::m::id::generator::random_prefixed(const id::sigil &sigil,
|
||||
const string_view &prefix,
|
||||
const mutable_buffer &buf)
|
||||
{
|
||||
using buffer::data;
|
||||
|
||||
const auto len
|
||||
{
|
||||
fmt::sprintf(buf, "%c%s%u", char(sigil), prefix, rand::integer())
|
||||
};
|
||||
|
||||
return { data(buf), size_t(len) };
|
||||
}
|
||||
|
||||
ircd::string_view
|
||||
ircd::m::id::generator::random_timebased(const id::sigil &sigil,
|
||||
const mutable_buffer &buf)
|
||||
{
|
||||
using buffer::data;
|
||||
using buffer::size;
|
||||
|
||||
const auto utime(microtime());
|
||||
const auto len
|
||||
{
|
||||
snprintf(data(buf), size(buf), "%c%zd%06d", char(sigil), utime.first, utime.second)
|
||||
};
|
||||
|
||||
return { data(buf), size_t(len) };
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::validate(const id::sigil &sigil,
|
||||
const string_view &id)
|
||||
try
|
||||
{
|
||||
validator(sigil, id);
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
throw INVALID_MXID
|
||||
{
|
||||
"Not a valid '%s' mxid: %s",
|
||||
reflect(sigil),
|
||||
e.what()
|
||||
};
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::valid(const id::sigil &sigil,
|
||||
const string_view &id)
|
||||
noexcept try
|
||||
{
|
||||
validator(sigil, id);
|
||||
return true;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::valid_local(const id::sigil &sigil,
|
||||
const string_view &id)
|
||||
{
|
||||
const auto parts(split(id, ':'));
|
||||
const auto &local(parts.first);
|
||||
|
||||
// local requires a sigil plus at least one character
|
||||
if(local.size() < 2)
|
||||
return false;
|
||||
|
||||
// local requires the correct sigil type
|
||||
if(!startswith(local, sigil))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::valid_sigil(const string_view &s)
|
||||
try
|
||||
{
|
||||
return valid_sigil(s.at(0));
|
||||
}
|
||||
catch(const std::out_of_range &e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::valid_sigil(const char &c)
|
||||
{
|
||||
switch(c)
|
||||
{
|
||||
case id::EVENT:
|
||||
case id::USER:
|
||||
case id::ALIAS:
|
||||
case id::ROOM:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
enum ircd::m::id::sigil
|
||||
ircd::m::sigil(const string_view &s)
|
||||
try
|
||||
{
|
||||
return sigil(s.at(0));
|
||||
}
|
||||
catch(const std::out_of_range &e)
|
||||
{
|
||||
throw BAD_SIGIL("sigil undefined");
|
||||
}
|
||||
|
||||
enum ircd::m::id::sigil
|
||||
ircd::m::sigil(const char &c)
|
||||
{
|
||||
switch(c)
|
||||
{
|
||||
case '$': return id::EVENT;
|
||||
case '@': return id::USER;
|
||||
case '#': return id::ALIAS;
|
||||
case '!': return id::ROOM;
|
||||
}
|
||||
|
||||
throw BAD_SIGIL("'%c' is not a valid sigil", c);
|
||||
}
|
||||
|
||||
const char *
|
||||
ircd::m::reflect(const enum id::sigil &c)
|
||||
{
|
||||
switch(c)
|
||||
{
|
||||
case id::EVENT: return "EVENT";
|
||||
case id::USER: return "USER";
|
||||
case id::ALIAS: return "ALIAS";
|
||||
case id::ROOM: return "ROOM";
|
||||
}
|
||||
|
||||
return "?????";
|
||||
}
|
525
ircd/m_io.cc
Normal file
525
ircd/m_io.cc
Normal file
|
@ -0,0 +1,525 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Charybdis Development Team
|
||||
* Copyright (C) 2016 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
namespace ircd::m::io
|
||||
{
|
||||
bool acquire_local(event::fetch &);
|
||||
bool acquire_local(room::fetch &);
|
||||
bool acquire_local(room::state::fetch &);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// m/io.h
|
||||
//
|
||||
|
||||
struct ircd::m::io::fetch::opts
|
||||
const ircd::m::io::fetch::defaults
|
||||
{};
|
||||
|
||||
struct ircd::m::io::sync::opts
|
||||
const ircd::m::io::sync::defaults
|
||||
{};
|
||||
|
||||
ircd::json::object
|
||||
ircd::m::io::get(const id::event &event_id,
|
||||
const mutable_buffer &buf)
|
||||
{
|
||||
event::fetch tab
|
||||
{
|
||||
event_id, buf
|
||||
};
|
||||
|
||||
return acquire(tab);
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::io::release(event::sync &tab)
|
||||
{
|
||||
release({&tab, 1});
|
||||
if(unlikely(bool(tab.error)))
|
||||
std::rethrow_exception(tab.error);
|
||||
}
|
||||
|
||||
ircd::json::array
|
||||
ircd::m::io::acquire(room::state::fetch &tab)
|
||||
{
|
||||
acquire({&tab, 1});
|
||||
if(unlikely(bool(tab.error)))
|
||||
std::rethrow_exception(tab.error);
|
||||
|
||||
return tab.pdus;
|
||||
}
|
||||
|
||||
ircd::json::array
|
||||
ircd::m::io::acquire(room::fetch &tab)
|
||||
{
|
||||
acquire({&tab, 1});
|
||||
if(unlikely(bool(tab.error)))
|
||||
std::rethrow_exception(tab.error);
|
||||
|
||||
return tab.pdus;
|
||||
}
|
||||
|
||||
ircd::json::object
|
||||
ircd::m::io::acquire(event::fetch &tab)
|
||||
{
|
||||
acquire({&tab, 1});
|
||||
if(unlikely(bool(tab.error)))
|
||||
std::rethrow_exception(tab.error);
|
||||
|
||||
return tab.pdu;
|
||||
}
|
||||
|
||||
//
|
||||
// mass release suite
|
||||
//
|
||||
|
||||
//TODO: XXX
|
||||
namespace ircd::m::io
|
||||
{
|
||||
size_t txn_ctr
|
||||
{
|
||||
1
|
||||
};
|
||||
|
||||
net::remote
|
||||
destination_remote(const string_view &destination)
|
||||
{
|
||||
return net::remote{destination};
|
||||
}
|
||||
|
||||
m::event::id
|
||||
event_id(const event::sync &es)
|
||||
{
|
||||
const json::object &event{es.buf};
|
||||
return event.get("event_id");
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
ircd::m::io::release(vector_view<event::sync> tab)
|
||||
{
|
||||
const auto count
|
||||
{
|
||||
tab.size()
|
||||
};
|
||||
|
||||
size_t out(0);
|
||||
std::string url[count];
|
||||
m::io::request request[count];
|
||||
struct session session[count];
|
||||
for(size_t i(0); i < count; ++i) try
|
||||
{
|
||||
if(!tab[i].destination || !tab[i].buf)
|
||||
continue;
|
||||
|
||||
url[i] = fmt::snstringf
|
||||
{
|
||||
1024, "_matrix/federation/v1/send/%zu", txn_ctr++
|
||||
};
|
||||
|
||||
session[i] =
|
||||
{
|
||||
tab[i].opts->hint? tab[i].opts->hint : destination_remote(tab[i].destination)
|
||||
};
|
||||
|
||||
request[i] =
|
||||
{
|
||||
"PUT", url[i], {}, json::object{tab[i].buf}
|
||||
};
|
||||
|
||||
request[i].destination = tab[i].destination;
|
||||
request[i](session[i].server);
|
||||
++out;
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
tab[i].error = std::make_exception_ptr(e);
|
||||
log.warning("sync %s will not succeed: %s",
|
||||
string_view{event_id(tab[i])},
|
||||
e.what());
|
||||
}
|
||||
|
||||
static const size_t rbuf_size{4_KiB};
|
||||
const unique_buffer<mutable_buffer> rbuf
|
||||
{
|
||||
out * rbuf_size
|
||||
};
|
||||
|
||||
size_t in(0), ret(0);
|
||||
json::object response[count];
|
||||
for(size_t i(0); i < count; ++i) try
|
||||
{
|
||||
if(!tab[i].destination)
|
||||
continue;
|
||||
|
||||
if(bool(tab[i].error))
|
||||
continue;
|
||||
|
||||
const mutable_buffer buf
|
||||
{
|
||||
data(rbuf) + (in * rbuf_size), rbuf_size
|
||||
};
|
||||
|
||||
ircd::parse::buffer pb{buf};
|
||||
response[i] = m::io::response{session[i].server, pb};
|
||||
ret += !tab[i].error;
|
||||
++in;
|
||||
|
||||
log.debug("%s received event %s (size: %zu) error: %d",
|
||||
string(net::remote{session[i].server}),
|
||||
string_view{event_id(tab[i])},
|
||||
size(tab[i].buf),
|
||||
bool(tab[i].error));
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
tab[i].error = std::make_exception_ptr(e);
|
||||
log.warning("request to sync event_id %s failed: %s",
|
||||
string_view{event_id(tab[i])},
|
||||
e.what());
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//
|
||||
// mass acquire suite
|
||||
//
|
||||
|
||||
size_t
|
||||
ircd::m::io::acquire(vector_view<room::state::fetch> tab)
|
||||
{
|
||||
const auto count
|
||||
{
|
||||
tab.size()
|
||||
};
|
||||
|
||||
std::string url[count];
|
||||
std::string query[count];
|
||||
m::io::request request[count];
|
||||
struct session session[count];
|
||||
for(size_t i(0); i < count; ++i) try
|
||||
{
|
||||
if(!tab[i].event_id)
|
||||
continue;
|
||||
|
||||
tab[i].local_result = acquire_local(tab[i]);
|
||||
if(tab[i].local_result)
|
||||
continue;
|
||||
|
||||
static char tmp[768];
|
||||
url[i] = fmt::snstringf
|
||||
{
|
||||
1024, "_matrix/federation/v1/state/%s/", urlencode(tab[i].room_id, tmp)
|
||||
};
|
||||
|
||||
query[i] = fmt::snstringf
|
||||
{
|
||||
1024, "event_id=%s", urlencode(tab[i].event_id, tmp)
|
||||
};
|
||||
|
||||
request[i] =
|
||||
{
|
||||
"GET", url[i], query[i], {}
|
||||
};
|
||||
|
||||
session[i] =
|
||||
{
|
||||
tab[i].opts->hint? tab[i].opts->hint : tab[i].event_id.hostname()
|
||||
};
|
||||
|
||||
request[i].destination = session[i].destination;
|
||||
request[i](session[i].server);
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
tab[i].error = std::make_exception_ptr(e);
|
||||
log.warning("request for event_id %s in room_id %s will not succeed: %s",
|
||||
string_view{tab[i].event_id},
|
||||
string_view{tab[i].room_id},
|
||||
e.what());
|
||||
}
|
||||
|
||||
size_t ret(0);
|
||||
json::object response[count];
|
||||
for(size_t i(0); i < count; ++i) try
|
||||
{
|
||||
if(!tab[i].event_id)
|
||||
continue;
|
||||
|
||||
if(tab[i].local_result || bool(tab[i].error))
|
||||
continue;
|
||||
|
||||
ircd::parse::buffer pb{tab[i].buf};
|
||||
response[i] = m::io::response(session[i].server, pb);
|
||||
tab[i].auth_chain = response[i]["auth_chain"];
|
||||
tab[i].pdus = response[i]["pdus"];
|
||||
//TODO: check event id
|
||||
//TODO: check hashes
|
||||
//TODO: check signatures
|
||||
ret += !tab[i].error;
|
||||
|
||||
log.debug("%s sent us event %s in room %s pdus: %zu (size: %zu) error: %d",
|
||||
string(net::remote{session[i].server}),
|
||||
string_view{tab[i].event_id},
|
||||
string_view{tab[i].room_id},
|
||||
json::array{response[i]["pdus"]}.count(),
|
||||
string_view{response[i]}.size(),
|
||||
bool(tab[i].error));
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
tab[i].error = std::make_exception_ptr(e);
|
||||
log.warning("request for event_id %s failed: %s",
|
||||
string_view{tab[i].event_id},
|
||||
e.what());
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t
|
||||
ircd::m::io::acquire(vector_view<room::fetch> tab)
|
||||
{
|
||||
const auto count
|
||||
{
|
||||
tab.size()
|
||||
};
|
||||
|
||||
std::string url[count];
|
||||
std::string query[count];
|
||||
m::io::request request[count];
|
||||
struct session session[count];
|
||||
for(size_t i(0); i < count; ++i) try
|
||||
{
|
||||
if(!tab[i].event_id)
|
||||
continue;
|
||||
|
||||
tab[i].local_result = acquire_local(tab[i]);
|
||||
if(tab[i].local_result)
|
||||
continue;
|
||||
|
||||
static char tmp[768];
|
||||
url[i] = fmt::snstringf
|
||||
{
|
||||
1024, "_matrix/federation/v1/backfill/%s/", urlencode(tab[i].room_id, tmp)
|
||||
};
|
||||
|
||||
query[i] = fmt::snstringf
|
||||
{
|
||||
1024, "limit=%zu&v=%s", tab[i].opts->limit, urlencode(tab[i].event_id, tmp)
|
||||
};
|
||||
|
||||
session[i] =
|
||||
{
|
||||
tab[i].opts->hint? tab[i].opts->hint : tab[i].event_id.hostname()
|
||||
};
|
||||
|
||||
request[i] =
|
||||
{
|
||||
"GET", url[i], query[i], {}
|
||||
};
|
||||
|
||||
request[i].destination = session[i].destination;
|
||||
request[i](session[i].server);
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
tab[i].error = std::make_exception_ptr(e);
|
||||
log.warning("request for event_id %s in room_id %s will not succeed: %s",
|
||||
string_view{tab[i].event_id},
|
||||
string_view{tab[i].room_id},
|
||||
e.what());
|
||||
}
|
||||
|
||||
size_t ret(0);
|
||||
json::object response[count];
|
||||
for(size_t i(0); i < count; ++i) try
|
||||
{
|
||||
if(!tab[i].event_id)
|
||||
continue;
|
||||
|
||||
if(tab[i].local_result || bool(tab[i].error))
|
||||
continue;
|
||||
|
||||
ircd::parse::buffer pb{tab[i].buf};
|
||||
response[i] = m::io::response(session[i].server, pb);
|
||||
tab[i].auth_chain = response[i]["auth_chain"];
|
||||
tab[i].pdus = response[i]["pdus"];
|
||||
//TODO: check event id
|
||||
//TODO: check hashes
|
||||
//TODO: check signatures
|
||||
ret += !tab[i].error;
|
||||
|
||||
log.debug("%s sent us event %s in room %s pdus: %zu (size: %zu) error: %d",
|
||||
string(net::remote{session[i].server}),
|
||||
string_view{tab[i].event_id},
|
||||
string_view{tab[i].room_id},
|
||||
json::array{response[i]["pdus"]}.count(),
|
||||
string_view{response[i]}.size(),
|
||||
bool(tab[i].error));
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
tab[i].error = std::make_exception_ptr(e);
|
||||
log.warning("request for event_id %s failed: %s",
|
||||
string_view{tab[i].event_id},
|
||||
e.what());
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t
|
||||
ircd::m::io::acquire(vector_view<event::fetch> tab)
|
||||
{
|
||||
const auto count
|
||||
{
|
||||
tab.size()
|
||||
};
|
||||
|
||||
std::string url[count];
|
||||
m::io::request request[count];
|
||||
struct session session[count];
|
||||
for(size_t i(0); i < count; ++i) try
|
||||
{
|
||||
if(!tab[i].event_id)
|
||||
continue;
|
||||
|
||||
tab[i].local_result = acquire_local(tab[i]);
|
||||
if(tab[i].local_result)
|
||||
continue;
|
||||
|
||||
static char tmp[768];
|
||||
url[i] = fmt::snstringf
|
||||
{
|
||||
1024, "_matrix/federation/v1/event/%s/", urlencode(tab[i].event_id, tmp)
|
||||
};
|
||||
|
||||
session[i] =
|
||||
{
|
||||
tab[i].opts->hint? tab[i].opts->hint : tab[i].event_id.hostname()
|
||||
};
|
||||
|
||||
request[i] =
|
||||
{
|
||||
"GET", url[i], {}, {}
|
||||
};
|
||||
|
||||
request[i].destination = session[i].destination;
|
||||
request[i](session[i].server);
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
tab[i].error = std::make_exception_ptr(e);
|
||||
log.warning("request for event_id %s will not succeed: %s",
|
||||
string_view{tab[i].event_id},
|
||||
e.what());
|
||||
}
|
||||
|
||||
size_t ret(0);
|
||||
json::object response[count];
|
||||
for(size_t i(0); i < count; ++i) try
|
||||
{
|
||||
if(!tab[i].event_id)
|
||||
continue;
|
||||
|
||||
if(tab[i].local_result || bool(tab[i].error))
|
||||
continue;
|
||||
|
||||
ircd::parse::buffer pb{tab[i].buf};
|
||||
response[i] = m::io::response{session[i].server, pb};
|
||||
tab[i].pdu = json::array{response[i]["pdus"]}[0];
|
||||
//TODO: check event id
|
||||
//TODO: check hashes
|
||||
//TODO: check signatures
|
||||
ret += !tab[i].error;
|
||||
|
||||
log.debug("%s sent us event %s pdus: %zu (size: %zu) error: %d",
|
||||
string(net::remote{session[i].server}),
|
||||
string_view{tab[i].event_id},
|
||||
json::array{response[i]["pdus"]}.count(),
|
||||
string_view{response[i]}.size(),
|
||||
bool(tab[i].error));
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
tab[i].error = std::make_exception_ptr(e);
|
||||
log.warning("request for event_id %s failed: %s",
|
||||
string_view{tab[i].event_id},
|
||||
e.what());
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//
|
||||
// acquire_local suite.
|
||||
//
|
||||
|
||||
bool
|
||||
ircd::m::io::acquire_local(room::state::fetch &tab)
|
||||
try
|
||||
{
|
||||
return false;
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
tab.error = std::make_exception_ptr(e);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::io::acquire_local(room::fetch &tab)
|
||||
try
|
||||
{
|
||||
return false;
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
tab.error = std::make_exception_ptr(e);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::io::acquire_local(event::fetch &tab)
|
||||
try
|
||||
{
|
||||
const m::vm::query<m::vm::where::equal> query
|
||||
{
|
||||
{ "event_id", tab.event_id },
|
||||
};
|
||||
|
||||
const auto test{[&tab](const auto &event)
|
||||
{
|
||||
tab.pdu = stringify(mutable_buffer{tab.buf}, event);
|
||||
return true;
|
||||
}};
|
||||
|
||||
return m::vm::test(query, test);
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
tab.error = std::make_exception_ptr(e);
|
||||
return false;
|
||||
}
|
1907
ircd/m_vm.cc
Normal file
1907
ircd/m_vm.cc
Normal file
File diff suppressed because it is too large
Load diff
3644
ircd/matrix.cc
3644
ircd/matrix.cc
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue