From ca80d66e851d06f626aab0d394f5e978caf62aca Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Thu, 27 Apr 2023 11:58:37 -0700 Subject: [PATCH] ircd::m::user::devices: Complete the m.device_list_update broadcast w/ keys; reinterface. --- include/ircd/m/user/devices.h | 12 +++- matrix/user_devices.cc | 103 ++++++++++++++++++++++++---------- modules/console.cc | 42 ++++++-------- 3 files changed, 100 insertions(+), 57 deletions(-) diff --git a/include/ircd/m/user/devices.h b/include/ircd/m/user/devices.h index 3447c3d83..c01fd3c44 100644 --- a/include/ircd/m/user/devices.h +++ b/include/ircd/m/user/devices.h @@ -13,6 +13,8 @@ struct ircd::m::user::devices { + struct send; + using closure = std::function; using closure_bool = std::function; @@ -36,9 +38,17 @@ struct ircd::m::user::devices ///TODO: XXX junk static std::map count_one_time_keys(const m::user &, const string_view &); static bool update(const device_list_update &); - static bool send(json::iov &content); devices(const m::user &user) :user{user} {} }; + +/// Broadcast m.device_list_update. +/// +struct ircd::m::user::devices::send +{ + send(const m::user::devices &, + const m::id::device &, + const string_view = {}); +}; diff --git a/matrix/user_devices.cc b/matrix/user_devices.cc index 359b31d34..6db9b660b 100644 --- a/matrix/user_devices.cc +++ b/matrix/user_devices.cc @@ -8,26 +8,81 @@ // copyright notice and this permission notice is present in all copies. The // full license for this software is available in the LICENSE file. -bool -ircd::m::user::devices::send(json::iov &content) +ircd::m::user::devices::send::send(const m::user::devices &devices, + const m::id::device &device_id, + const string_view room_id) try { - assert(content.has("user_id")); - assert(content.has("device_id")); + assert(device_id); + + const auto &user_id + { + devices.user.user_id + }; + + const bool deleted + { + devices.has(device_id) + }; + + const m::user::keys user_keys + { + user_id + }; + + const bool has_keys + { + !deleted && user_keys.has_device(device_id) + }; + + const unique_mutable_buffer keys_buf + { + has_keys? 4_KiB: 0_KiB + }; + + json::stack keys{keys_buf}; + if(has_keys) + { + json::stack::object top{keys}; + user_keys.device(top, device_id); + } // Triggers a devices request from the remote; also see // modules/federation/user_devices.cc - const long &stream_id - { - 1L - }; + static const auto stream_id{1L}; - json::iov event; + json::iov event, content; const json::iov::push push[] { { event, { "type", "m.device_list_update" } }, - { event, { "sender", content.at("user_id") } }, + { event, { "sender", user_id } }, + { content, { "deleted", deleted } }, + { content, { "device_id", device_id } }, { content, { "stream_id", stream_id } }, + { content, { "user_id", user_id } }, + }; + + const json::iov::push push_keys + { + content, has_keys, + { + "keys", [&keys] + { + return keys.completed(); + } + } + }; + + // For diagnostic purposes; usually not defined. + const json::iov::push push_room_id + { + event, m::valid(m::id::ROOM, room_id), + { + "room_id", [&room_id] + { + return room_id; + } + } }; m::vm::copts opts; @@ -39,8 +94,6 @@ try { event, content, opts }; - - return true; } catch(const ctx::interrupted &) { @@ -51,12 +104,10 @@ catch(const std::exception &e) log::error { m::log, "Send m.device_list_update for '%s' belonging to %s :%s", - content.at("device_id"), - content.at("user_id"), + string_view{device_id}, + string_view{devices.user.user_id}, e.what(), }; - - return false; } bool @@ -185,21 +236,11 @@ const m::redact(user_room, user_room.user, event_id, "deleted") }; - if(!my(user)) - return true; - - json::iov content; - const json::iov::push push[] - { - { content, { "user_id", user.user_id } }, - { content, { "device_id", id } }, - { content, { "deleted", true } }, - }; - - const bool broadcasted - { - user::devices::send(content) - }; + if(my(user)) + user::devices::send + { + *this, id + }; return true; } diff --git a/modules/console.cc b/modules/console.cc index 9b308c4e3..4767d62f1 100644 --- a/modules/console.cc +++ b/modules/console.cc @@ -14449,7 +14449,7 @@ console_cmd__user__devices__update(opt &out, const string_view &line) { const params param{line, " ", { - "user_id", "device_id", "deleted" + "user_id", "device_id", "room_id" }}; const m::user::id &user_id @@ -14457,14 +14457,16 @@ console_cmd__user__devices__update(opt &out, const string_view &line) param.at("user_id") }; - const string_view &device_id_ + const string_view &device_id { param.at("device_id", "*"_sv) }; - const bool deleted + const m::room::id::buf room_id { - param["deleted"] == "deleted" + m::valid(m::id::ROOM, param["room_id"])? + m::room_id(param["room_id"]): + m::room::id::buf{} }; const m::user::devices devices @@ -14472,45 +14474,35 @@ console_cmd__user__devices__update(opt &out, const string_view &line) user_id }; - const auto update{[&out, &user_id, &deleted] + const auto update{[&out, &devices, &user_id, &room_id] (const auto &device_id) { - json::iov content; - const json::iov::push push[] + m::user::devices::send { - { content, { "user_id", user_id } }, - { content, { "device_id", device_id } }, - { content, { "deleted", deleted } }, - }; - - const bool broadcasted - { - m::user::devices::send(content) + devices, device_id, room_id }; out - << "broadcast:" - << broadcasted - << ' ' + << "broadcast: " << device_id << std::endl; }}; const bool found { - !devices.for_each([&update, &device_id_] - (const auto &, const string_view &device_id) + !devices.for_each([&update, &device_id] + (const auto &, const string_view &_device_id) { - if(device_id_ != "*" && device_id != device_id_) + if(device_id != "*" && _device_id != device_id) return true; - update(device_id); - return device_id != device_id_; // false to break + update(_device_id); + return _device_id != device_id; // false to break }) }; - if(!found && deleted) - update(device_id_); + if(device_id != "*" && !found) + update(device_id); return true; }