diff --git a/modules/federation/get_missing_events.cc b/modules/federation/get_missing_events.cc index de9b13b30..73e85d13c 100644 --- a/modules/federation/get_missing_events.cc +++ b/modules/federation/get_missing_events.cc @@ -10,44 +10,125 @@ using namespace ircd; -mapi::header IRCD_MODULE +mapi::header +IRCD_MODULE { - "federation missing events handler" + "Federation (undocumented) :Get missing events." }; -struct send -:resource -{ - using resource::resource; -} +resource get_missing_events_resource { "/_matrix/federation/v1/get_missing_events/", { - "federation missing events handler", + "Federation (undocumented) missing events handler", resource::DIRECTORY, } }; +static resource::response get__missing_events(client &, const resource::request &); + +resource::method +method_get +{ + get_missing_events_resource, "GET", get__missing_events, + { + method_get.VERIFY_ORIGIN + } +}; + +resource::method +method_post +{ + get_missing_events_resource, "POST", get__missing_events, + { + method_post.VERIFY_ORIGIN + } +}; + +conf::item +max_limit +{ + { "name", "ircd.federation.missing_events.max_limit" }, + { "default", 128L } +}; + +conf::item +max_goose +{ + { "name", "ircd.federation.missing_events.max_goose" }, + { "default", 512L } +}; + resource::response -handle_get(client &client, - const resource::request &request) +get__missing_events(client &client, + const resource::request &request) { m::room::id::buf room_id { url::decode(request.parv[0], room_id) }; + const auto limit + { + request["limit"]? + std::min(lex_cast(request["limit"]), size_t(max_limit)): + size_t(max_limit) + }; + + const auto min_depth + { + request["min_depth"]? + lex_cast(request["min_depth"]): + 0 + }; + + const json::array &earliest + { + request["earliest_events"] + }; + + const json::array &latest + { + request["latest"] + }; + + const auto in_latest + { + [&latest](const auto &event_id) + { + return end(latest) != std::find_if(begin(latest), end(latest), [&event_id] + (const auto &latest) + { + return event_id == unquote(latest); + }); + } + }; + + std::vector ret; + ret.reserve(limit); + size_t goose{0}; + for(const auto &event_id : earliest) + { + m::room::messages it + { + room_id, unquote(event_id) + }; + + for(; it && ret.size() < limit && goose < size_t(max_goose); ++it, ++goose) + { + const m::event &event{*it}; + ret.emplace_back(json::strung{event}); + if(in_latest(at<"event_id"_>(event))) + break; + } + } + return resource::response { - client, http::NOT_FOUND + client, json::members + { + { "events", json::strung { ret.data(), ret.data() + ret.size() } } + } }; } - -resource::method method_get -{ - get_missing_events_resource, "GET", handle_get, - { - method_get.VERIFY_ORIGIN - } -};