mirror of
https://github.com/matrix-construct/construct
synced 2024-12-26 15:33:54 +01:00
ircd: Various cleanup.
This commit is contained in:
parent
f1c5257201
commit
21db4baab3
9 changed files with 485 additions and 58 deletions
|
@ -248,7 +248,7 @@ ircd::json::operator<(const obj::member &a, const string_view &b)
|
|||
inline bool
|
||||
ircd::json::operator!=(const obj::member &a, const string_view &b)
|
||||
{
|
||||
return string_view(a.first.string, a.first.len) == b;
|
||||
return string_view(a.first.string, a.first.len) != b;
|
||||
}
|
||||
|
||||
inline bool
|
||||
|
|
|
@ -29,11 +29,211 @@ namespace ircd {
|
|||
namespace m {
|
||||
|
||||
struct error
|
||||
:ircd::error
|
||||
:http::error
|
||||
{
|
||||
error(const json::doc &doc);
|
||||
error(const json::obj &obj);
|
||||
template<class... args> error(const http::code &, const string_view &errcode, const char *const &fmt, args&&...);
|
||||
template<class... args> error(const string_view &errcode, const char *const &fmt, args&&...);
|
||||
error(const http::code &, const json::doc &doc = {});
|
||||
error(const http::code &, const json::obj &obj);
|
||||
};
|
||||
|
||||
struct member
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
template<const char *const &name>
|
||||
struct mem
|
||||
:member
|
||||
{
|
||||
std::string value;
|
||||
|
||||
operator const std::string &() const { return value; }
|
||||
|
||||
mem(const json::obj &obj)
|
||||
:value{obj[name]}
|
||||
{}
|
||||
|
||||
mem(const json::doc &doc)
|
||||
:value{doc[name]}
|
||||
{}
|
||||
|
||||
mem() = default;
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &s, const mem &m)
|
||||
{
|
||||
s << m.value;
|
||||
return s;
|
||||
}
|
||||
};
|
||||
|
||||
struct session
|
||||
{
|
||||
static constexpr auto _user_id { "user_id" };
|
||||
static constexpr auto _access_token { "access_token" };
|
||||
static constexpr auto _home_server { "home_server" };
|
||||
static constexpr auto _device_id { "device_id" };
|
||||
|
||||
mem<_user_id> user_id;
|
||||
mem<_access_token> access_token;
|
||||
mem<_home_server> home_server;
|
||||
mem<_device_id> device_id;
|
||||
|
||||
session(const json::obj &obj)
|
||||
:user_id{obj}
|
||||
,access_token{obj}
|
||||
,home_server{obj}
|
||||
,device_id{obj}
|
||||
{}
|
||||
|
||||
session() = default;
|
||||
};
|
||||
|
||||
struct request
|
||||
:json::obj
|
||||
{
|
||||
struct quote;
|
||||
struct versions;
|
||||
struct sync;
|
||||
struct login;
|
||||
|
||||
string_view method;
|
||||
string_view resource;
|
||||
string_view access_token;
|
||||
|
||||
request(const string_view &method,
|
||||
const string_view &resource,
|
||||
std::initializer_list<json::obj::member> body = {})
|
||||
:json::obj{std::move(body)}
|
||||
,method{method}
|
||||
,resource{resource}
|
||||
{}
|
||||
|
||||
request(const string_view &method,
|
||||
const string_view &resource,
|
||||
const json::doc &content)
|
||||
:json::obj{content}
|
||||
,method{method}
|
||||
,resource{resource}
|
||||
{}
|
||||
};
|
||||
|
||||
struct request::sync
|
||||
:request
|
||||
{
|
||||
/*
|
||||
bool full_state;
|
||||
string_view since;
|
||||
string_view filter;
|
||||
string_view set_presence;
|
||||
milliseconds timeout;
|
||||
*/
|
||||
|
||||
sync(std::initializer_list<json::obj::member> body = {})
|
||||
:request{"GET", "/_matrix/client/r0/sync", std::move(body)}
|
||||
{}
|
||||
};
|
||||
|
||||
struct request::login
|
||||
:request
|
||||
{
|
||||
/*
|
||||
string_view user;
|
||||
string_view password;
|
||||
*/
|
||||
|
||||
login(std::initializer_list<json::obj::member> body = {})
|
||||
:request{"POST", "/_matrix/client/r0/login", std::move(body)}
|
||||
{}
|
||||
};
|
||||
|
||||
struct request::quote
|
||||
:request
|
||||
{
|
||||
quote(const string_view &method,
|
||||
const string_view &resource,
|
||||
const json::doc &content)
|
||||
:request{method, resource, content}
|
||||
{}
|
||||
};
|
||||
|
||||
struct client
|
||||
:ircd::client
|
||||
{
|
||||
IRCD_EXCEPTION(ircd::error, error)
|
||||
|
||||
std::unique_ptr<session> sess;
|
||||
|
||||
// Synchronize server state
|
||||
void sync(request::sync &r);
|
||||
|
||||
// Account login
|
||||
session login(request::login &);
|
||||
|
||||
// Account registration
|
||||
void reg(const string_view &user,
|
||||
const string_view &pass,
|
||||
const string_view &type = "m.login.dummy");
|
||||
|
||||
void quote(request::quote &);
|
||||
|
||||
client(const host_port &);
|
||||
};
|
||||
|
||||
using doc_closure = std::function<void (const json::doc &)>;
|
||||
using arr_closure = std::function<void (const json::arr &)>;
|
||||
|
||||
struct request::versions
|
||||
:request
|
||||
{
|
||||
versions(client &, const doc_closure & = nullptr, std::initializer_list<json::obj::member> body = {});
|
||||
};
|
||||
|
||||
} // namespace m
|
||||
} // namespace ircd
|
||||
|
||||
inline
|
||||
ircd::m::error::error(const http::code &c,
|
||||
const json::obj &obj)
|
||||
:http::error{c, std::string{obj}}
|
||||
{}
|
||||
|
||||
inline
|
||||
ircd::m::error::error(const http::code &c,
|
||||
const json::doc &doc)
|
||||
:http::error{c, std::string{doc}}
|
||||
{}
|
||||
|
||||
template<class... args>
|
||||
ircd::m::error::error(const string_view &errcode,
|
||||
const char *const &fmt,
|
||||
args&&... a)
|
||||
:error
|
||||
{
|
||||
http::BAD_REQUEST, errcode, fmt, std::forward<args>(a)...
|
||||
}{}
|
||||
|
||||
template<class... args>
|
||||
ircd::m::error::error(const http::code &status,
|
||||
const string_view &errcode,
|
||||
const char *const &fmt,
|
||||
args&&... a)
|
||||
:http::error
|
||||
{
|
||||
status, [&]
|
||||
{
|
||||
char estr[256]; const auto estr_len
|
||||
{
|
||||
fmt::snprintf(estr, sizeof(estr), fmt, std::forward<args>(a)...)
|
||||
};
|
||||
|
||||
return std::string
|
||||
{
|
||||
json::obj
|
||||
{
|
||||
{ "errcode", errcode },
|
||||
{ "error", string_view(estr, estr_len) }
|
||||
}
|
||||
};
|
||||
}()
|
||||
}{}
|
||||
|
|
|
@ -44,8 +44,10 @@ struct resource
|
|||
protected:
|
||||
decltype(resources)::const_iterator resources_it;
|
||||
|
||||
void call_method(client &, method &, resource::request &);
|
||||
|
||||
public:
|
||||
void operator()(client &, parse::capstan &, const http::request::head &) const;
|
||||
void operator()(client &, parse::capstan &, const http::request::head &);
|
||||
|
||||
resource(const char *const &name,
|
||||
const char *const &description = "");
|
||||
|
@ -53,18 +55,25 @@ struct resource
|
|||
virtual ~resource() noexcept;
|
||||
};
|
||||
|
||||
struct resource::response
|
||||
{
|
||||
response(client &, const json::doc &doc, const http::code &code = http::OK);
|
||||
response(client &, const json::obj &obj, const http::code &code = http::OK);
|
||||
response() = default;
|
||||
~response() noexcept;
|
||||
};
|
||||
|
||||
struct resource::request
|
||||
:json::doc
|
||||
{
|
||||
const http::request::head &head;
|
||||
http::request::content &content;
|
||||
|
||||
request(const http::request::head &head, http::request::content &content)
|
||||
:json::doc{content}
|
||||
,head{head}
|
||||
,content{content}
|
||||
{}
|
||||
};
|
||||
|
||||
struct resource::response
|
||||
{
|
||||
response(client &, const json::doc &doc, const http::code & = http::OK);
|
||||
response(client &, const json::obj &obj, const http::code & = http::OK);
|
||||
response() = default;
|
||||
~response() noexcept;
|
||||
};
|
||||
|
||||
struct resource::method
|
||||
|
|
|
@ -171,7 +171,6 @@ struct line {};
|
|||
#include "rfc1459.h"
|
||||
#include "json.h"
|
||||
#include "http.h"
|
||||
#include "matrix.h"
|
||||
#include "fmt.h"
|
||||
#include "path.h"
|
||||
#include "ctx.h"
|
||||
|
@ -183,3 +182,4 @@ struct line {};
|
|||
#include "js.h"
|
||||
#include "client.h"
|
||||
#include "mods.h"
|
||||
#include "matrix.h"
|
||||
|
|
|
@ -41,10 +41,11 @@ libircd_la_SOURCES = \
|
|||
fmt.cc \
|
||||
db.cc \
|
||||
locale.cc \
|
||||
json.cc \
|
||||
http.cc \
|
||||
json.cc \
|
||||
matrix.cc \
|
||||
parse.cc
|
||||
parse.cc \
|
||||
conf.cc
|
||||
|
||||
if JS
|
||||
libircd_la_SOURCES += \
|
||||
|
|
|
@ -181,6 +181,7 @@ ircd::read_closure(client &client)
|
|||
{
|
||||
try
|
||||
{
|
||||
const char *const got(start);
|
||||
read(client, start, stop);
|
||||
}
|
||||
catch(const boost::system::system_error &e)
|
||||
|
@ -317,7 +318,7 @@ try
|
|||
string(remote_addr(client)).c_str(),
|
||||
std::string(head.resource).c_str());
|
||||
|
||||
const auto &resource(*resource::resources.at(head.resource));
|
||||
auto &resource(*resource::resources.at(head.resource));
|
||||
resource(client, pc, head);
|
||||
}
|
||||
catch(const std::out_of_range &e)
|
||||
|
|
24
ircd/conf.cc
Normal file
24
ircd/conf.cc
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (C) 2017 Charybdis Development Team
|
||||
* Copyright (C) 2017 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 {
|
||||
|
||||
} // namespace ircd
|
232
ircd/matrix.cc
232
ircd/matrix.cc
|
@ -22,30 +22,193 @@
|
|||
namespace ircd {
|
||||
namespace m {
|
||||
|
||||
db::handle accounts;
|
||||
|
||||
} // namespace m
|
||||
} // namespace ircd
|
||||
|
||||
void
|
||||
ircd::test(const string_view &what)
|
||||
try
|
||||
ircd::m::client::client(const host_port &host_port)
|
||||
:ircd::client{host_port}
|
||||
{
|
||||
const auto tok(tokens(what, " "));
|
||||
const std::string method(tok.at(2));
|
||||
const std::string rcontent(tok.size() >= 5? tok.at(4) : string_view{});
|
||||
}
|
||||
|
||||
char url[256] {0};
|
||||
snprintf(url, sizeof(url), "/_matrix/client/%s", std::string(tok.at(3)).c_str());
|
||||
|
||||
const std::string host{tok.at(0)};
|
||||
const auto port(lex_cast<uint16_t>(tok.at(1)));
|
||||
ircd::client client
|
||||
ircd::m::request::versions::versions(client &client,
|
||||
const doc_closure &closure,
|
||||
std::initializer_list<json::obj::member> body)
|
||||
:request
|
||||
{
|
||||
"GET", "/_matrix/client/versions", std::move(body)
|
||||
}
|
||||
{
|
||||
const auto handle([&](const http::code &code,
|
||||
const json::doc &doc)
|
||||
{
|
||||
{ host, port }
|
||||
switch(code)
|
||||
{
|
||||
case http::OK:
|
||||
if(closure)
|
||||
closure(doc);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
throw m::error(code, doc);
|
||||
}
|
||||
});
|
||||
|
||||
char buf[1024];
|
||||
parse::buffer pb{buf};
|
||||
parse::capstan pc{pb, read_closure(client)};
|
||||
const auto handler([&pc, &handle]
|
||||
(const http::response::head &head)
|
||||
{
|
||||
const http::response::content content{pc, head};
|
||||
const auto status(http::status(head.status));
|
||||
const json::doc doc{content};
|
||||
handle(status, doc);
|
||||
});
|
||||
|
||||
http::request
|
||||
{
|
||||
host(remote_addr(client)), method, resource, std::string(*this), write_closure(client),
|
||||
{
|
||||
{ "Content-Type"s, "application/json"s }
|
||||
}
|
||||
};
|
||||
|
||||
http::response
|
||||
{
|
||||
pc, nullptr, handler
|
||||
};
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::client::reg(const string_view &user,
|
||||
const string_view &pass,
|
||||
const string_view &type)
|
||||
{
|
||||
const json::obj auth
|
||||
{
|
||||
{ "type", type }
|
||||
};
|
||||
|
||||
const json::obj obj
|
||||
{
|
||||
{ "password", pass },
|
||||
{ "username", user },
|
||||
{ "auth", &auth },
|
||||
};
|
||||
|
||||
const auto handle([&](const http::code &code,
|
||||
const json::doc &doc)
|
||||
{
|
||||
switch(code)
|
||||
{
|
||||
case http::OK:
|
||||
std::cout << "OK!" << std::endl;
|
||||
std::cout << doc << std::endl;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw m::error(code, doc);
|
||||
}
|
||||
});
|
||||
|
||||
char buf[4096];
|
||||
parse::buffer pb{buf};
|
||||
parse::capstan pc{pb, read_closure(*this)};
|
||||
const auto handler([&pc, &handle]
|
||||
(const http::response::head &head)
|
||||
{
|
||||
const http::response::content content{pc, head};
|
||||
const auto status(http::status(head.status));
|
||||
const json::doc doc{content};
|
||||
handle(status, doc);
|
||||
});
|
||||
|
||||
http::request
|
||||
{
|
||||
host(remote_addr(*this)), "POST"s, "/_matrix/client/r0/register"s, std::string(obj), write_closure(*this),
|
||||
{
|
||||
{ "Content-Type"s, "application/json"s }
|
||||
}
|
||||
};
|
||||
|
||||
http::response
|
||||
{
|
||||
pc, nullptr, handler
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
ircd::m::session
|
||||
ircd::m::client::login(request::login &r)
|
||||
{
|
||||
session ret;
|
||||
|
||||
const auto handle([&](const http::code &code,
|
||||
const json::doc &doc)
|
||||
{
|
||||
switch(code)
|
||||
{
|
||||
case http::OK:
|
||||
ret = json::obj{doc};
|
||||
this->sess.reset(new session{doc});
|
||||
break;
|
||||
|
||||
default:
|
||||
throw m::error(code, doc);
|
||||
}
|
||||
});
|
||||
|
||||
char buf[4096];
|
||||
parse::buffer pb{buf};
|
||||
parse::capstan pc{pb, read_closure(*this)};
|
||||
const auto handler([&pc, &handle]
|
||||
(const http::response::head &head)
|
||||
{
|
||||
const http::response::content content{pc, head};
|
||||
const auto status(http::status(head.status));
|
||||
const json::doc doc{content};
|
||||
handle(status, doc);
|
||||
});
|
||||
|
||||
http::request
|
||||
{
|
||||
host(remote_addr(*this)), r.method, r.resource, std::string(r), write_closure(*this),
|
||||
{
|
||||
{ "Content-Type"s, "application/json"s }
|
||||
}
|
||||
};
|
||||
|
||||
http::response
|
||||
{
|
||||
pc, nullptr, handler
|
||||
};
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::client::sync(request::sync &r)
|
||||
{
|
||||
if(!sess)
|
||||
throw error("No active session");
|
||||
|
||||
static const auto urlfmt
|
||||
{
|
||||
"%s?access_token=%s"
|
||||
};
|
||||
|
||||
char url[1024]; const auto urllen
|
||||
{
|
||||
fmt::snprintf(url, sizeof(url), urlfmt, r.resource, string(sess->access_token))
|
||||
};
|
||||
|
||||
http::request
|
||||
{
|
||||
host, method, url, rcontent, write_closure(client),
|
||||
host(remote_addr(*this)), r.method, url, {}, write_closure(*this),
|
||||
{
|
||||
{ "Content-Type"s, "application/json"s }
|
||||
}
|
||||
|
@ -53,33 +216,34 @@ try
|
|||
|
||||
char buf[4096];
|
||||
parse::buffer pb{buf};
|
||||
parse::capstan pc{pb, read_closure(client)};
|
||||
parse::capstan pc{pb, read_closure(*this)};
|
||||
http::response
|
||||
{
|
||||
pc, nullptr, [&pc](const auto &head)
|
||||
pc, nullptr, [this, &pc](const auto &head)
|
||||
{
|
||||
http::response::content content{pc, head};
|
||||
const json::doc cdoc{content};
|
||||
http::response::content content
|
||||
{
|
||||
pc, head
|
||||
};
|
||||
|
||||
for(const auto &member : cdoc)
|
||||
std::cout << member.first << " --> " << member.second << std::endl;
|
||||
switch(http::status(head.status))
|
||||
{
|
||||
case http::OK:
|
||||
{
|
||||
const json::obj d(content, true);
|
||||
const json::arr a(d["account_data.events[0]"]);
|
||||
std::cout << a << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw m::error(http::status(head.status), json::doc(content));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
log::error("test: %s", e.what());
|
||||
throw;
|
||||
}
|
||||
|
||||
ircd::m::error::error(const json::obj &obj)
|
||||
:ircd::error{generate_skip}
|
||||
void
|
||||
ircd::m::client::quote(request::quote &r)
|
||||
{
|
||||
serialize(obj, begin(buf), end(buf));
|
||||
}
|
||||
|
||||
ircd::m::error::error(const json::doc &doc)
|
||||
:ircd::error{generate_skip}
|
||||
{
|
||||
print(buf, sizeof(buf), doc);
|
||||
}
|
||||
|
|
|
@ -56,20 +56,39 @@ void
|
|||
ircd::resource::operator()(client &client,
|
||||
parse::capstan &pc,
|
||||
const http::request::head &head)
|
||||
const try
|
||||
try
|
||||
{
|
||||
const auto &method(*methods.at(head.method));
|
||||
auto &method(*methods.at(head.method));
|
||||
http::request::content content{pc, head};
|
||||
resource::request request
|
||||
{
|
||||
head, content
|
||||
};
|
||||
|
||||
method(client, request);
|
||||
call_method(client, method, request);
|
||||
}
|
||||
catch(const std::out_of_range &e)
|
||||
{
|
||||
throw http::error(http::METHOD_NOT_ALLOWED);
|
||||
throw http::error
|
||||
{
|
||||
http::METHOD_NOT_ALLOWED
|
||||
};
|
||||
}
|
||||
|
||||
void
|
||||
ircd::resource::call_method(client &client,
|
||||
method &method,
|
||||
resource::request &request)
|
||||
try
|
||||
{
|
||||
method(client, request);
|
||||
}
|
||||
catch(const json::error &e)
|
||||
{
|
||||
throw m::error
|
||||
{
|
||||
"M_BAD_JSON", "Required JSON field: %s", e.what()
|
||||
};
|
||||
}
|
||||
|
||||
ircd::resource::method::method(struct resource &resource,
|
||||
|
@ -99,11 +118,20 @@ noexcept
|
|||
}
|
||||
|
||||
ircd::resource::response::response(client &client,
|
||||
const json::obj &doc,
|
||||
const json::obj &obj,
|
||||
const http::code &code)
|
||||
try
|
||||
{
|
||||
char cbuf[1024];
|
||||
response(client, serialize(doc, cbuf, cbuf + sizeof(cbuf)), code);
|
||||
char cbuf[1024], *out(cbuf);
|
||||
const auto doc(serialize(obj, out, cbuf + sizeof(cbuf)));
|
||||
response(client, doc, code);
|
||||
}
|
||||
catch(const json::error &e)
|
||||
{
|
||||
throw m::error
|
||||
{
|
||||
http::INTERNAL_SERVER_ERROR, "M_NOT_JSON", "Generator Protection: %s", e.what()
|
||||
};
|
||||
}
|
||||
|
||||
ircd::resource::response::response(client &client,
|
||||
|
|
Loading…
Reference in a new issue