diff --git a/include/ircd/m/v1/query.h b/include/ircd/m/v1/query.h new file mode 100644 index 000000000..0e2ff2725 --- /dev/null +++ b/include/ircd/m/v1/query.h @@ -0,0 +1,60 @@ +// Matrix Construct +// +// Copyright (C) Matrix Construct Developers, Authors & Contributors +// Copyright (C) 2016-2018 Jason Volk +// +// 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_V1_QUERY_H + +namespace ircd::m::v1 +{ + struct query; +}; + +struct ircd::m::v1::query +:server::request +{ + struct opts; + struct profile; + struct directory; + + explicit operator json::object() const + { + const json::object object{in.content}; + return object; + } + + query(const string_view &type, const string_view &args, const mutable_buffer &, opts); +}; + +struct ircd::m::v1::query::opts +{ + net::hostport remote; + m::request request; + server::out out; + server::in in; + const struct server::request::opts *sopts {nullptr}; + + opts(const net::hostport &remote) + :remote{remote} + {} + + opts() = default; +}; + +struct ircd::m::v1::query::profile +:query +{ + profile(const id::user &user_id, const mutable_buffer &, opts); +}; + +struct ircd::m::v1::query::directory +:query +{ + directory(const id::room_alias &room_alias, const mutable_buffer &, opts); +}; diff --git a/include/ircd/m/v1/v1.h b/include/ircd/m/v1/v1.h index 5534c0fc7..cd84f3ffc 100644 --- a/include/ircd/m/v1/v1.h +++ b/include/ircd/m/v1/v1.h @@ -12,6 +12,7 @@ #define HAVE_IRCD_M_V1_H #include "version.h" +#include "query.h" #include "make_join.h" #include "send_join.h" #include "event.h" diff --git a/ircd/m/v1.cc b/ircd/m/v1.cc index f6d78e702..0889b33c8 100644 --- a/ircd/m/v1.cc +++ b/ircd/m/v1.cc @@ -495,6 +495,96 @@ ircd::m::v1::make_join::make_join(const room::id &room_id, { } +/////////////////////////////////////////////////////////////////////////////// +// +// v1/query.h +// + +namespace ircd::m::v1 +{ + thread_local char query_arg_buf[1024]; +} + +ircd::m::v1::query::directory::directory(const id::room_alias &room_alias, + const mutable_buffer &buf, + opts opts) +:query +{ + "directory", + fmt::sprintf + { + query_arg_buf, "room_alias=%s", string_view{room_alias} + }, + buf, + opts +} +{ +} + +ircd::m::v1::query::profile::profile(const id::user &user_id, + const mutable_buffer &buf, + opts opts) +:query +{ + "profile", + fmt::sprintf + { + query_arg_buf, "user_id=%s", string_view{user_id} + }, + buf, + opts +} +{ +} + +ircd::m::v1::query::query(const string_view &type, + const string_view &args, + const mutable_buffer &buf, + opts opts) +:server::request{[&] +{ + assert(!!opts.remote); + + if(!defined(json::get<"origin"_>(opts.request))) + json::get<"origin"_>(opts.request) = my_host(); + + if(!defined(json::get<"destination"_>(opts.request))) + json::get<"destination"_>(opts.request) = host(opts.remote); + + if(!defined(json::get<"uri"_>(opts.request))) + { + thread_local char urlbuf[2048]; + json::get<"uri"_>(opts.request) = fmt::sprintf + { + urlbuf, "/_matrix/federation/v1/query/%s?%s", + type, + args + }; + } + + json::get<"method"_>(opts.request) = "GET"; + opts.out.head = opts.request(buf); + + if(!size(opts.in)) + { + const auto in_max + { + std::max(ssize_t(size(buf) - size(opts.out.head)), ssize_t(0)) + }; + + assert(in_max >= ssize_t(size(buf) / 2)); + opts.in.head = { data(buf) + size(opts.out.head), size_t(in_max) }; + opts.in.content = opts.in.head; + } + + return server::request + { + opts.remote, std::move(opts.out), std::move(opts.in), opts.sopts + }; +}()} +{ +} + /////////////////////////////////////////////////////////////////////////////// // // v1/version.h