diff --git a/modules/Makefile.am b/modules/Makefile.am index f3a18b2a3..b17d42793 100644 --- a/modules/Makefile.am +++ b/modules/Makefile.am @@ -249,6 +249,7 @@ federation_federation_state_ids_la_SOURCES = federation/state_ids.cc federation_federation_state_la_SOURCES = federation/state.cc federation_federation_make_leave_la_SOURCES = federation/make_leave.cc federation_federation_send_leave_la_SOURCES = federation/send_leave.cc +federation_federation_backfill_la_SOURCES = federation/backfill.cc federation_module_LTLIBRARIES = \ federation/federation_send.la \ @@ -265,6 +266,7 @@ federation_module_LTLIBRARIES = \ federation/federation_state.la \ federation/federation_make_leave.la \ federation/federation_send_leave.la \ + federation/federation_backfill.la \ ### ############################################################################### diff --git a/modules/federation/backfill.cc b/modules/federation/backfill.cc new file mode 100644 index 000000000..dc3f5d897 --- /dev/null +++ b/modules/federation/backfill.cc @@ -0,0 +1,131 @@ +// 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. + +using namespace ircd; + +mapi::header +IRCD_MODULE +{ + "federation backfill" +}; + +resource +backfill_resource +{ + "/_matrix/federation/v1/backfill/", + { + "federation backfill", + resource::DIRECTORY, + } +}; + +conf::item +backfill_limit_max +{ + { "name", "ircd.federation.backfill.limit.max" }, + { "default", 512L /* TODO: hiiigherrrr */ }, +}; + +conf::item +backfill_limit_default +{ + { "name", "ircd.federation.backfill.limit.default" }, + { "default", 64L }, +}; + +static size_t +calc_limit(const resource::request &request) +{ + const auto &limit + { + request.query["limit"] + }; + + if(!limit) + return size_t(backfill_limit_default); + + size_t ret + { + lex_cast(limit) + }; + + return std::min(ret, size_t(backfill_limit_max)); +} + +resource::response +get__backfill(client &client, + const resource::request &request) +{ + m::room::id::buf room_id + { + url::decode(request.parv[0], room_id) + }; + + m::event::id::buf event_id + { + request.query["v"]? + url::decode(request.query.at("v"), event_id): + m::head(room_id) + }; + + const size_t limit + { + calc_limit(request) + }; + + m::room::messages it + { + room_id, event_id + }; + + //TODO: chunk direct to socket + const unique_buffer buf + { + 64_KiB * limit //TODO: XXX + }; + + json::stack out{buf}; + { + json::stack::object top{out}; + json::stack::member pdus_m + { + top, "pdus" + }; + + json::stack::array pdus + { + pdus_m + }; + + size_t count{0}; + for(; it && count < limit; ++count, --it) + { + const m::event &event{*it}; + pdus.append(event); + } + } + + return resource::response + { + client, json::object + { + out.completed() + } + }; +} + +resource::method +method_get +{ + backfill_resource, "GET", get__backfill, + { + method_get.VERIFY_ORIGIN + } +};