matrix_sdk_ui/timeline/
to_device.rs

1// Copyright 2023 The Matrix.org Foundation C.I.C.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::iter;
16
17use matrix_sdk::{event_handler::EventHandler, Client};
18use ruma::{
19    events::{forwarded_room_key::ToDeviceForwardedRoomKeyEvent, room_key::ToDeviceRoomKeyEvent},
20    OwnedRoomId,
21};
22use tracing::{debug_span, error, trace, Instrument};
23
24use super::controller::TimelineController;
25
26pub(super) fn handle_room_key_event(
27    timeline: TimelineController,
28    room_id: OwnedRoomId,
29) -> impl EventHandler<ToDeviceRoomKeyEvent, (Client,)> {
30    move |event: ToDeviceRoomKeyEvent, client: Client| {
31        async move {
32            let event_room_id = event.content.room_id;
33            let session_id = event.content.session_id;
34            retry_decryption(client, timeline, room_id, event_room_id, session_id).await;
35        }
36        .instrument(debug_span!("handle_room_key_event"))
37    }
38}
39
40pub(super) fn handle_forwarded_room_key_event(
41    timeline: TimelineController,
42    room_id: OwnedRoomId,
43) -> impl EventHandler<ToDeviceForwardedRoomKeyEvent, (Client,)> {
44    move |event: ToDeviceForwardedRoomKeyEvent, client: Client| {
45        async move {
46            let event_room_id = event.content.room_id;
47            let session_id = event.content.session_id;
48            retry_decryption(client, timeline, room_id, event_room_id, session_id).await;
49        }
50        .instrument(debug_span!("handle_forwarded_room_key_event"))
51    }
52}
53
54async fn retry_decryption(
55    client: Client,
56    timeline: TimelineController,
57    room_id: OwnedRoomId,
58    event_room_id: OwnedRoomId,
59    session_id: String,
60) {
61    if event_room_id != room_id {
62        trace!(
63            ?event_room_id, timeline_room_id = ?room_id, ?session_id,
64            "Received to-device room key event for a different room, ignoring"
65        );
66        return;
67    }
68
69    let Some(room) = client.get_room(&room_id) else {
70        error!("Failed to fetch room object");
71        return;
72    };
73
74    timeline.retry_event_decryption(&room, Some(iter::once(session_id).collect())).await;
75}