From 2d7b011bba916290fa8e7b5bf30b4750af89d437 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Sun, 3 Jun 2018 18:43:17 -0700 Subject: [PATCH] ircd::m::v1: Add frontfill request. --- include/ircd/m/v1/frontfill.h | 50 ++++++++++++++++ include/ircd/m/v1/v1.h | 1 + ircd/m/v1.cc | 105 ++++++++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+) create mode 100644 include/ircd/m/v1/frontfill.h diff --git a/include/ircd/m/v1/frontfill.h b/include/ircd/m/v1/frontfill.h new file mode 100644 index 000000000..dbba1b285 --- /dev/null +++ b/include/ircd/m/v1/frontfill.h @@ -0,0 +1,50 @@ +// 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_FRONTFILL_H + +namespace ircd::m::v1 +{ + struct frontfill; +}; + +struct ircd::m::v1::frontfill +:server::request +{ + struct opts; + using span = std::pair; + using vector = vector_view; + using ranges = std::pair; + + static const_buffer make_content(const mutable_buffer &, const ranges &, const opts &); + + explicit operator json::array() const + { + const json::object content{in.content}; + return content.get("events"); + } + + frontfill(const room::id &, const ranges &, const mutable_buffer &, opts); + frontfill(const room::id &, const span &, const mutable_buffer &, opts); + frontfill() = default; +}; + +struct ircd::m::v1::frontfill::opts +{ + net::hostport remote; + size_t limit {64}; + uint64_t min_depth {0}; + m::request request; + server::out out; + server::in in; + const struct server::request::opts *sopts {nullptr}; + bool dynamic {true}; +}; diff --git a/include/ircd/m/v1/v1.h b/include/ircd/m/v1/v1.h index e3ff7b4c5..a02d924f4 100644 --- a/include/ircd/m/v1/v1.h +++ b/include/ircd/m/v1/v1.h @@ -28,6 +28,7 @@ namespace ircd::m::v1 #include "event_auth.h" #include "state.h" #include "backfill.h" +#include "frontfill.h" #include "public_rooms.h" #include "send.h" #include "groups.h" diff --git a/ircd/m/v1.cc b/ircd/m/v1.cc index be970b16b..9433a9abc 100644 --- a/ircd/m/v1.cc +++ b/ircd/m/v1.cc @@ -213,6 +213,111 @@ ircd::m::v1::public_rooms::public_rooms(const net::hostport &remote, { } +/////////////////////////////////////////////////////////////////////////////// +// +// v1/frontfill.h +// + +ircd::m::v1::frontfill::frontfill(const room::id &room_id, + const span &span, + const mutable_buffer &buf, + opts opts) +:frontfill +{ + room_id, + ranges { vector(&span.first, 1), vector(&span.second, 1) }, + buf, + std::move(opts) +} +{ +} + +ircd::m::v1::frontfill::frontfill(const room::id &room_id, + const ranges &pair, + 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<"content"_>(opts.request))) + opts.out.content = json::get<"content"_>(opts.request); + + if(!defined(json::get<"uri"_>(opts.request))) + { + thread_local char urlbuf[1024], ridbuf[768]; + json::get<"uri"_>(opts.request) = fmt::sprintf + { + urlbuf, "/_matrix/federation/v1/get_missing_events/%s/", + url::encode(room_id, ridbuf) + }; + } + + window_buffer buf{buf_}; + if(!defined(json::get<"content"_>(opts.request))) + { + buf([&pair, &opts](const mutable_buffer &buf) + { + return make_content(buf, pair, opts); + }); + + json::get<"content"_>(opts.request) = json::object{buf.completed()}; + opts.out.content = json::get<"content"_>(opts.request); + } + + json::get<"method"_>(opts.request) = "POST"; + opts.out.head = opts.request(buf); + + if(!size(opts.in)) + { + opts.in.head = buf + size(opts.out.head); + opts.in.content = opts.dynamic? + mutable_buffer{}: // server::request will allocate new mem + opts.in.head; // server::request will auto partition + } + + return server::request + { + opts.remote, std::move(opts.out), std::move(opts.in), opts.sopts + }; +}()} +{ +} + +ircd::const_buffer +ircd::m::v1::frontfill::make_content(const mutable_buffer &buf, + const ranges &pair, + const opts &opts) +{ + json::stack out{buf}; + { + // note: This object must be in abc order + json::stack::object top{out}; + { + json::stack::member earliest{top, "earliest_events"}; + json::stack::array array{earliest}; + for(const auto &id : pair.first) + array.append(id); + } + { + json::stack::member latest{top, "latest_events"}; + json::stack::array array{latest}; + for(const auto &id : pair.second) + array.append(id); + } + json::stack::member{top, "limit", json::value(int64_t(opts.limit))}; + json::stack::member{top, "min_depth", json::value(int64_t(opts.min_depth))}; + } + + return out.completed(); +} + /////////////////////////////////////////////////////////////////////////////// // // v1/backfill.h