0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-06-10 22:18:54 +02:00

ircd: Various fixes.

This commit is contained in:
Jason Volk 2017-03-10 19:31:20 -08:00
parent 065395d274
commit 49c2a5361c
16 changed files with 334 additions and 133 deletions

View file

@ -42,6 +42,25 @@ struct buffer
{}
};
struct const_buffer
:buffer<const char *>
{
operator boost::asio::const_buffer() const;
using buffer<const char *>::buffer;
const_buffer(const string_view &s)
:buffer<const char *>{begin(s), end(s)}
{}
};
struct mutable_buffer
:buffer<char *>
{
operator boost::asio::mutable_buffer() const;
using buffer<char *>::buffer;
};
template<class it,
size_t align = 16>
struct unique_buffer
@ -53,22 +72,6 @@ struct unique_buffer
~unique_buffer() noexcept;
};
struct const_buffer
:buffer<const char *>
{
operator boost::asio::const_buffer() const;
using buffer<const char *>::buffer;
};
struct mutable_buffer
:buffer<char *>
{
operator boost::asio::mutable_buffer() const;
using buffer<char *>::buffer;
};
template<class T> using buffers = std::initializer_list<T>;
using const_buffers = buffers<const_buffer>;
using mutable_buffers = buffers<mutable_buffer>;

View file

@ -30,6 +30,8 @@ namespace http {
enum code
{
OK = 200,
BAD_REQUEST = 400,
NOT_FOUND = 404,
METHOD_NOT_ALLOWED = 405,
@ -37,7 +39,7 @@ enum code
INTERNAL_SERVER_ERROR = 500,
};
extern std::map<code, string_view> reason;
extern std::map<code, std::string> reason;
struct error
:ircd::error

View file

@ -29,32 +29,30 @@ struct doc
:string_view
{
struct member;
struct iterator;
struct const_iterator;
using key_type = string_view;
using mapped_type = string_view;
using value_type = const member;
using pointer = value_type *;
using reference = value_type &;
using const_iterator = iterator;
using iterator = const_iterator;
using size_type = size_t;
using difference_type = std::ptrdiff_t;
using key_compare = std::less<member>;
bool contains(const string_view &) const;
iterator end() const;
iterator begin() const;
const_iterator end() const;
const_iterator begin() const;
iterator find(const char *const &name) const;
const_iterator find(const char *const &name) const;
size_t count() const;
string_view at(const char *const &name) const;
string_view operator[](const char *const &name) const;
doc(const string_view &s = {})
:string_view{s}
{}
using string_view::string_view;
friend size_t print(char *const &buf, const size_t &max, const doc &);
friend std::ostream &operator<<(std::ostream &, const doc &);
@ -75,7 +73,7 @@ struct doc::member
friend std::ostream &operator<<(std::ostream &, const doc::member &);
};
struct doc::iterator
struct doc::const_iterator
{
using value_type = const member;
using pointer = value_type *;
@ -90,7 +88,7 @@ struct doc::iterator
const char *stop;
mutable member state;
iterator(const char *const &start, const char *const &stop)
const_iterator(const char *const &start, const char *const &stop)
:start{start}
,stop{stop}
{}
@ -99,48 +97,48 @@ struct doc::iterator
value_type *operator->() const { return &state; }
value_type &operator*() const { return *operator->(); }
iterator &operator++();
const_iterator &operator++();
friend bool operator==(const doc::iterator &, const doc::iterator &);
friend bool operator!=(const doc::iterator &, const doc::iterator &);
friend bool operator<=(const doc::iterator &, const doc::iterator &);
friend bool operator>=(const doc::iterator &, const doc::iterator &);
friend bool operator<(const doc::iterator &, const doc::iterator &);
friend bool operator>(const doc::iterator &, const doc::iterator &);
friend bool operator==(const doc::const_iterator &, const doc::const_iterator &);
friend bool operator!=(const doc::const_iterator &, const doc::const_iterator &);
friend bool operator<=(const doc::const_iterator &, const doc::const_iterator &);
friend bool operator>=(const doc::const_iterator &, const doc::const_iterator &);
friend bool operator<(const doc::const_iterator &, const doc::const_iterator &);
friend bool operator>(const doc::const_iterator &, const doc::const_iterator &);
};
inline bool
operator==(const doc::iterator &a, const doc::iterator &b)
operator==(const doc::const_iterator &a, const doc::const_iterator &b)
{
return a.start == b.start;
}
inline bool
operator!=(const doc::iterator &a, const doc::iterator &b)
operator!=(const doc::const_iterator &a, const doc::const_iterator &b)
{
return a.start != b.start;
}
inline bool
operator<=(const doc::iterator &a, const doc::iterator &b)
operator<=(const doc::const_iterator &a, const doc::const_iterator &b)
{
return a.start <= b.start;
}
inline bool
operator>=(const doc::iterator &a, const doc::iterator &b)
operator>=(const doc::const_iterator &a, const doc::const_iterator &b)
{
return a.start >= b.start;
}
inline bool
operator<(const doc::iterator &a, const doc::iterator &b)
operator<(const doc::const_iterator &a, const doc::const_iterator &b)
{
return a.start < b.start;
}
inline bool
operator>(const doc::iterator &a, const doc::iterator &b)
operator>(const doc::const_iterator &a, const doc::const_iterator &b)
{
return a.start > b.start;
}
@ -205,7 +203,7 @@ const
return it->second;
}
inline ircd::json::doc::iterator
inline ircd::json::doc::const_iterator
ircd::json::doc::find(const char *const &name)
const
{

View file

@ -38,7 +38,7 @@ struct obj
using size_type = size_t;
using difference_type = std::ptrdiff_t;
using key_compare = std::less<member>;
using index = std::set<member>;
using index = std::vector<member>;
doc state;
index idx;
@ -67,7 +67,7 @@ struct obj
delta operator[](const char *const &name);
obj(const doc &d);
obj() = default;
obj();
obj(obj &&) = default;
explicit obj(const obj &);
~obj() noexcept;
@ -105,6 +105,7 @@ struct obj::delta
void set(const std::string &);
void set(const char *const &);
void set(const string_view &);
void set(const json::obj &);
public:
delta(struct obj &, obj::member &, const string_view &);
@ -193,14 +194,14 @@ const
inline ircd::json::obj::iterator
ircd::json::obj::find(const char *const &name)
{
return { *this, idx.find(string_view{name}) };
return { *this, std::find(std::begin(idx), std::end(idx), string_view{name}) };
}
inline ircd::json::obj::const_iterator
ircd::json::obj::find(const char *const &name)
const
{
return idx.find(string_view{name});
return std::find(std::begin(idx), std::end(idx), string_view{name});
}
inline size_t

View file

@ -55,7 +55,9 @@ struct resource
struct resource::response
{
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;
};
@ -66,9 +68,9 @@ struct resource::request
};
struct resource::method
:std::function<void (client &, request &, response &)>
:std::function<response (client &, request &)>
{
using handler = std::function<void (client &, request &, response &)>;
using handler = std::function<response (client &, request &)>;
protected:
public:

View file

@ -20,7 +20,7 @@
*/
#pragma once
#define HAVE_IRCD_CLIENT_SOCK_H
#define HAVE_IRCD_CLIENT_SOCKET_H
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
@ -156,12 +156,6 @@ struct socket::init
~init() noexcept;
};
char *read(socket &, char *&start, char *const &stop);
string_view readline(socket &, char *&start, char *const &stop);
size_t write(socket &, const char *const &buf, const size_t &max);
size_t write(socket &, const string_view &);
ip::address remote_address(const socket &);
std::string remote_ip(const socket &);
uint16_t remote_port(const socket &);
@ -169,6 +163,12 @@ ip::address local_address(const socket &);
std::string local_ip(const socket &);
uint16_t local_port(const socket &);
char *read(socket &, char *&start, char *const &stop);
string_view readline(socket &, char *&start, char *const &stop);
size_t write(socket &, const char *const &buf, const size_t &max);
size_t write(socket &, const string_view &);
inline
socket::io::io(struct socket &sock,

View file

@ -80,7 +80,7 @@ template<template<class, class, class>
class T = string_view,
class Comp = std::less<T>,
class A>
C<T, Comp, A> token(A allocator, const string_view &str, const char *const &sep);
C<T, Comp, A> tokens(A allocator, const string_view &str, const char *const &sep);
// Receive token view into new associative container
template<template<class, class, class>
@ -88,7 +88,7 @@ template<template<class, class, class>
class T = string_view,
class Comp = std::less<T>,
class A = std::allocator<T>>
C<T, Comp, A> token(const string_view &str, const char *const &sep);
C<T, Comp, A> tokens(const string_view &str, const char *const &sep);
// Convenience to get individual tokens
size_t tokens_count(const string_view &str, const char *const &sep);

View file

@ -445,7 +445,7 @@ at(It &&start,
It &&stop,
ssize_t i)
{
for(; start != stop; --i, std::next(start, 1))
for(; start != stop; --i, std::advance(start, 1))
if(!i)
return start;

View file

@ -105,7 +105,7 @@ catch(const http::error &e)
{ "HTTP/1.1 ", 9 },
{ e.what(), strlen(e.what()) },
{ "\r\n", 2 },
{ content_len, size_t(content_len_len) },
{ string_view(content_len) },
{ "\r\n", 2 },
{ e.content.data(), e.content.size() }
};

View file

@ -382,13 +382,15 @@ ircd::http::line::line(parse::context &pc)
namespace ircd {
namespace http {
std::map<code, string_view> reason
std::map<code, std::string> reason
{
{ code::BAD_REQUEST, "Bad Request" },
{ code::NOT_FOUND, "Not Found" },
{ code::METHOD_NOT_ALLOWED, "Method Not Allowed" },
{ code::OK, "OK"s },
{ code::INTERNAL_SERVER_ERROR, "Internal Server Error" },
{ code::BAD_REQUEST, "Bad Request"s },
{ code::NOT_FOUND, "Not Found"s },
{ code::METHOD_NOT_ALLOWED, "Method Not Allowed"s },
{ code::INTERNAL_SERVER_ERROR, "Internal Server Error"s },
};
} // namespace http

View file

@ -34,14 +34,7 @@ BOOST_FUSION_ADAPT_STRUCT
( decltype(ircd::json::doc::member::first), first )
( decltype(ircd::json::doc::member::second), second )
)
/*
BOOST_FUSION_ADAPT_STRUCT
(
ircd::json::obj::member,
( decltype(ircd::json::obj::member::first), first )
( decltype(ircd::json::obj::member::second), second )
)
*/
namespace ircd {
namespace json {
@ -69,6 +62,7 @@ using karma::char_;
using karma::maxwidth;
using karma::buffer;
using karma::eps;
using karma::attr_cast;
template<class it>
struct input
@ -266,26 +260,22 @@ struct output
rule<string_view> string { quote << chars << quote ,"string" };
rule<string_view> name { string ,"name" };
rule<string_view> value { rule<string_view>{} ,"value" };
rule<string_view> value { karma::string ,"value" };
rule<const json::array &> elems { *(value % value_sep) ,"elements" };
rule<const json::array &> elems { (value % value_sep) ,"elements" };
rule<const json::array &> array { array_begin << elems << array_end ,"array" };
rule<doc::member> dmember { name << name_sep << value ,"member" };
rule<const json::doc &> dmembers { *(dmember % value_sep) ,"members" };
rule<const json::doc &> dmembers { (dmember % value_sep) ,"members" };
rule<const json::doc &> document { object_begin << dmembers << object_end ,"document" };
rule<doc::member> member { name << name_sep << value ,"member" };
rule<const json::obj &> members { *(member % value_sep) ,"members" };
rule<const json::obj &> members { (member % value_sep) ,"members" };
rule<const json::obj &> object { object_begin << members << object_end ,"object" };
output()
:output::base_type{rule<>{}}
{
array %= array_begin << elems << array_end;
object %= object_begin << members << object_end;
document %= object_begin << dmembers << object_end;
}
{}
};
} // namespace json
@ -304,14 +294,14 @@ const parser;
struct printer
:output<char *>
{
using output<char *>::output;
printer();
}
const printer;
struct ostreamer
:output<karma::ostream_iterator<char>>
{
using output<karma::ostream_iterator<char>>::output;
ostreamer();
}
const ostreamer;
@ -326,6 +316,49 @@ std::ostream &operator<<(std::ostream &, const obj &);
} // namespace json
} // namespace ircd
ircd::json::printer::printer()
{
const auto recursor([this](auto &a, auto &b, auto &c)
{
const auto recurse_document([&]
{
char *out(const_cast<char *>(a.data()));
karma::generate(out, maxwidth(a.size())[document], json::doc(a));
a.resize(size_t(out - a.data()));
});
if(likely(!a.empty())) switch(a.front())
{
case '{': recurse_document(); break;
default: break;
}
});
value %= karma::string[recursor];
}
ircd::json::ostreamer::ostreamer()
{
const auto recursor([this](auto &a, auto &b, auto &c)
{
const auto recurse_document([&]
{
char *out(const_cast<char *>(a.data()));
const auto count(print(out, a.size(), json::doc(a)));
a.resize(count);
});
if(likely(!a.empty())) switch(a.front())
{
case '{': recurse_document(); break;
case '[': c = false; break;
default: break;
}
});
value %= karma::string[recursor];
}
size_t
ircd::json::print(char *const &buf,
const size_t &max,
@ -387,6 +420,11 @@ ircd::json::operator<<(std::ostream &s, const obj &obj)
return s;
}
ircd::json::obj::obj()
:owns_state{false}
{
}
ircd::json::obj::obj(const doc &doc)
:state{doc}
,idx{std::begin(doc), std::end(doc)}
@ -449,8 +487,8 @@ const
ircd::json::obj::delta
ircd::json::obj::operator[](const char *const &name)
{
auto pit(idx.emplace(string_view{name}, string_view{}));
auto &member(const_cast<obj::member &>(*pit.first));
const auto it(idx.emplace(idx.end(), string_view{name}, string_view{}));
auto &member(const_cast<obj::member &>(*it));
/*
if(pit.second)
{
@ -468,7 +506,7 @@ ircd::json::obj::operator[](const char *const &name)
ircd::json::obj::delta
ircd::json::obj::at(const char *const &name)
{
const auto it(idx.find(string_view{name}));
const auto it(std::find(std::begin(idx), std::end(idx), string_view{name}));
if(unlikely(it == idx.end()))
throw not_found("name \"%s\"", name);
@ -549,6 +587,18 @@ ircd::json::obj::delta::delta(struct obj &obj,
{
}
void
ircd::json::obj::delta::set(const json::obj &obj)
{
const size_t size(obj.size());
std::unique_ptr<char[]> buf(new char[size + 1]);
const auto doc(serialize(obj, buf.get(), buf.get() + size));
buf.get()[size] = '\0';
commit(doc);
member->owns_second = true;
buf.release();
}
void
ircd::json::obj::delta::set(const string_view &value)
{
@ -667,13 +717,14 @@ ircd::json::print(char *const &buf,
std::ostream &
ircd::json::operator<<(std::ostream &s, const doc &doc)
{
const auto &os(ostreamer);
static const auto throws([]
{
throw print_error("The JSON generator failed to output document to stream");
});
karma::ostream_iterator<char> osi(s);
karma::generate(osi, ostreamer.document | eps[throws], doc);
karma::generate(osi, os.document | eps[throws], doc);
return s;
}
@ -690,8 +741,8 @@ ircd::json::operator<<(std::ostream &s, const doc::member &member)
return s;
}
ircd::json::doc::iterator &
ircd::json::doc::iterator::operator++()
ircd::json::doc::const_iterator &
ircd::json::doc::const_iterator::operator++()
{
static const qi::rule<const char *, json::doc::member> member
{
@ -711,7 +762,7 @@ ircd::json::doc::iterator::operator++()
return *this;
}
ircd::json::doc::iterator
ircd::json::doc::const_iterator
ircd::json::doc::begin()
const
{
@ -732,7 +783,7 @@ const
return ret;
}
ircd::json::doc::iterator
ircd::json::doc::const_iterator
ircd::json::doc::end()
const
{

View file

@ -19,6 +19,8 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <ircd/socket.h>
namespace ircd {
IRCD_INIT_PRIORITY(STD_CONTAINER)
@ -65,8 +67,7 @@ const try
head, content
};
resource::response response;
method(client, request, response);
response r(method(client, request));
}
catch(const std::out_of_range &e)
{
@ -99,8 +100,57 @@ noexcept
resource->methods.erase(methods_it);
}
ircd::resource::response::response()
ircd::resource::response::response(client &client,
const json::obj &doc,
const http::code &code)
{
char cbuf[1024];
mutable_buffer buf(cbuf, sizeof(cbuf));
response(client, serialize(doc, data(buf), data(buf) + size(buf)), code);
}
ircd::resource::response::response(client &client,
const json::doc &doc,
const http::code &code)
{
char status_line[64]; const auto status_line_len
{
snprintf(status_line, sizeof(status_line), "HTTP/1.1 %u %s\r\n",
uint(code),
http::reason[code].data())
};
char server_line[128]; const auto server_line_len
{
snprintf(server_line, sizeof(server_line), "Server: %s (IRCd) %s\r\n",
BRANDING_NAME,
BRANDING_VERSION)
};
const time_t ltime(time(nullptr));
struct tm *const tm(localtime(&ltime));
char date_line[64]; const auto date_line_len
{
strftime(date_line, sizeof(date_line), "Date: %a, %d %b %Y %T %z\r\n", tm)
};
char content_len[64]; const auto content_len_len
{
snprintf(content_len, sizeof(content_len), "Content-Length: %zu\r\n",
doc.size())
};
const const_buffers iov
{
{ status_line, size_t(status_line_len) },
{ server_line, size_t(server_line_len) },
{ date_line, size_t(date_line_len) },
{ content_len, size_t(content_len_len) },
{ "\r\n", 2 },
{ doc.data(), doc.size() }
};
client.sock->write(iov);
}
ircd::resource::response::~response()

View file

@ -26,12 +26,12 @@ AM_LDFLAGS += \
# library is client_X.so in the main modules dir.
client_moduledir=@moduledir@
client_client_versions_la_SOURCES = client/versions.cc
client_client_login_la_SOURCES = client/login.cc
client_client_register_la_SOURCES = client/register.cc
client_client_login_la_SOURCES = client/login.cc
client_module_LTLIBRARIES = \
client/client_versions.la \
client/client_login.la \
client/client_register.la
client/client_register.la \
client/client_login.la
moduledir=@moduledir@
listen_la_SOURCES = listen.cc

View file

@ -37,8 +37,8 @@ resource login_resource
resource::method getter
{login_resource, "POST", [](client &client,
resource::request &request,
resource::response &response)
resource::request &request)
-> resource::response
{
char head[256], body[256];
static const auto headfmt
@ -97,6 +97,7 @@ resource::method getter
};
client.sock->write(iov);
return {};
}};
mapi::header IRCD_MODULE

View file

@ -23,55 +23,144 @@
//ircd::db::handle logins("login", db::opt::READ_ONLY);
using namespace ircd;
mapi::header IRCD_MODULE
ircd::mapi::header IRCD_MODULE
{
"registers the resource 'client/register' to handle requests"
};
resource register_resource
ircd::resource register_resource
{
"/_matrix/client/r0/register",
"Register for an account on this homeserver. (3.3.1)"
};
void valid_username(const string_view &s);
void handle_post(client &client, resource::request &request, resource::response &response);
auto generate_access_token([] { });
auto generate_refresh_token([] { });
void valid_username(const ircd::string_view &s);
ircd::resource::response handle_post(ircd::client &client, ircd::resource::request &request);
resource::member username { "username", json::STRING, valid_username };
resource::member bind_email { "bind_email", json::LITERAL };
resource::method on_post
template<class T>
struct in
{
};
template<class T>
struct out
{
};
template<class T>
struct query
{
};
struct string
{
};
struct object
{
};
struct boolean
{
};
template<>
struct in<string>
{
in(const char *const &name, const std::function<void (const ircd::string_view &)> &valid = nullptr) {}
};
template<>
struct in<object>
{
in(const char *const &name) {}
};
template<>
struct in<boolean>
{
in(const char *const &name) {}
};
template<>
struct query<boolean>
{
template<class A, class B> query(A&&, B&&) {}
};
template<>
struct out<string>
{
template<class T> out(const char *const &name, T&&) {}
};
//
// Inputs
//
in<string> username { "username", valid_username };
in<string> password { "password" };
in<object> auth { "auth" };
in<string> session { "auth.session" };
in<string> type { "auth.type" };
in<boolean> bind_email { "bind_email" };
//
// Queries
//
ircd::db::handle users { "users" };
query<boolean> username_exists { users, username };
//
// Commitments
//
//
// Outputs
//
out<string> user_id { "user_id", username };
out<string> home_server { "home_server", "pitcock's playground" };
out<string> access_token { "access_token", generate_access_token };
out<string> refresh_token { "refresh_token", generate_refresh_token };
ircd::resource::method post
{
register_resource, "POST", handle_post,
{
&username,
&bind_email,
//&username,
//&bind_email,
}
};
void handle_post(client &client,
resource::request &request,
resource::response &response)
ircd::resource::response
handle_post(ircd::client &client,
ircd::resource::request &request)
{
using namespace ircd;
const json::doc in{request.content};
char head[256], body[25];
static const auto headfmt
{
"HTTP/1.1 200 OK\r\n"
"Content-Length: %zu\r\n"
"\r\n"
};
json::obj hoo;
hoo["kaa"] = "\"choo\"";
std::cout << request.content << std::endl;
//std::cout << in << std::endl;
json::obj foo;
foo["yea"] = "\"pie\"";
foo["hoo"] = &hoo;
// write(client, in);
json::obj out;
out["user_id"] = in["username"];
out["access_token"] = "\"ABCDEFG\"";
out["home_server"] = "\"dereferenced\"";
out["refresh_token"] = "\"tokenizeddd\"";
return { client, out };
}
void valid_username(const string_view &s)
void valid_username(const ircd::string_view &s)
{
using namespace ircd;
static conf::item<size_t> max_len
{
"client.register.username.max_len", 15

View file

@ -59,18 +59,20 @@ resource versions_resource
};
resource::method getter
{versions_resource, "GET", [](client &client,
resource::request &request,
resource::response &response)
{
static const const_buffers iov
versions_resource, "GET", []
(client &client, resource::request &request) -> resource::response
{
{ header.data(), header.size() },
{ body.data(), body.size() },
};
static const const_buffers iov
{
{ header.data(), header.size() },
{ body.data(), body.size() },
};
client.sock->write(iov);
}};
client.sock->write(iov);
return {};
}
};
mapi::header IRCD_MODULE
{