Skip to content

Commit

Permalink
timeline: store UTDs in decrypt_room_event
Browse files Browse the repository at this point in the history
When `decrypt_room_event` fails to decrypt an event, return the UTD as a
`TimelineEvent` instead of an Error.
  • Loading branch information
richvdh committed Oct 10, 2024
1 parent 5c40ecb commit ab28964
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 34 deletions.
8 changes: 8 additions & 0 deletions crates/matrix-sdk-common/src/deserialized_responses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,14 @@ pub enum UnableToDecryptReason {
SenderIdentityNotTrusted(VerificationLevel),
}

impl UnableToDecryptReason {
/// Returns true if this UTD is due to a missing room key (and hence might
/// resolve itself if we wait a bit.)
pub fn is_missing_room_key(&self) -> bool {
matches!(self, Self::MissingMegolmSession | Self::UnknownMegolmMessageIndex)
}
}

/// Deserialization helper for [`SyncTimelineEvent`], for the modern format.
///
/// This has the exact same fields as [`SyncTimelineEvent`] itself, but has a
Expand Down
54 changes: 31 additions & 23 deletions crates/matrix-sdk-ui/src/notification_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,7 @@ use std::{
use futures_util::{pin_mut, StreamExt as _};
use matrix_sdk::{room::Room, Client, ClientBuildError, SlidingSyncList, SlidingSyncMode};
use matrix_sdk_base::{
crypto::{vodozemac, MegolmError},
deserialized_responses::TimelineEvent,
sliding_sync::http,
RoomState, StoreError,
deserialized_responses::TimelineEvent, sliding_sync::http, RoomState, StoreError,
};
use ruma::{
assign,
Expand Down Expand Up @@ -216,24 +213,24 @@ impl NotificationClient {

tokio::time::sleep(Duration::from_millis(wait)).await;

match room.decrypt_event(raw_event.cast_ref()).await {
Ok(new_event) => {
let new_event = room.decrypt_event(raw_event.cast_ref()).await?;

match new_event.kind {
matrix_sdk::deserialized_responses::TimelineEventKind::UnableToDecrypt (
utd_event) => {
if utd_event.utd_info.reason.is_missing_room_key() {
// Decryption error that could be caused by a missing room
// key; retry in a few.
wait *= 2;
} else {
trace!("Event could not be decrypted, but waiting longer is unlikely to help: {:?}", utd_event.utd_info.reason);
return Ok(None);
}
}
_ => {
trace!("Waiting succeeded and event could be decrypted!");
return Ok(Some(new_event));
}
Err(matrix_sdk::Error::MegolmError(
MegolmError::MissingRoomKey(_)
| MegolmError::Decryption(
vodozemac::megolm::DecryptionError::UnknownMessageIndex(_, _),
),
)) => {
// Decryption error that could be caused by a missing room key;
// retry in a few.
wait *= 2;
}
Err(err) => {
return Err(err.into());
}
}
}

Expand All @@ -259,10 +256,21 @@ impl NotificationClient {
match encryption_sync {
Ok(sync) => match sync.run_fixed_iterations(2, sync_permit_guard).await {
Ok(()) => match room.decrypt_event(raw_event.cast_ref()).await {
Ok(new_event) => {
trace!("Encryption sync managed to decrypt the event.");
Ok(Some(new_event))
}
Ok(new_event) => match new_event.kind {
matrix_sdk::deserialized_responses::TimelineEventKind::UnableToDecrypt(
utd_event,
) => {
trace!(
"Encryption sync failed to decrypt the event: {:?}",
utd_event.utd_info.reason
);
Ok(None)
}
_ => {
trace!("Encryption sync managed to decrypt the event.");
Ok(Some(new_event))
}
},
Err(err) => {
trace!("Encryption sync failed to decrypt the event: {err}");
Ok(None)
Expand Down
20 changes: 9 additions & 11 deletions crates/matrix-sdk/src/room/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use futures_util::{
#[cfg(all(feature = "e2e-encryption", not(target_arch = "wasm32")))]
pub use identity_status_changes::IdentityStatusChanges;
#[cfg(feature = "e2e-encryption")]
use matrix_sdk_base::crypto::DecryptionSettings;
use matrix_sdk_base::crypto::{DecryptionSettings, RoomEventDecryptionResult};
#[cfg(all(feature = "e2e-encryption", not(target_arch = "wasm32")))]
use matrix_sdk_base::crypto::{IdentityStatusChange, RoomIdentityProvider, UserIdentity};
use matrix_sdk_base::{
Expand Down Expand Up @@ -1210,7 +1210,8 @@ impl Room {
/// # Arguments
/// * `event` - The room event to be decrypted.
///
/// Returns the decrypted event.
/// Returns the decrypted event. In the case of a decryption error, returns
/// a `TimelineEvent` representing the decryption error.
#[cfg(feature = "e2e-encryption")]
pub async fn decrypt_event(
&self,
Expand All @@ -1222,24 +1223,21 @@ impl Room {
let decryption_settings = DecryptionSettings {
sender_device_trust_requirement: self.client.base_client().decryption_trust_requirement,
};
let decrypted = match machine
.decrypt_room_event(event.cast_ref(), self.inner.room_id(), &decryption_settings)
.await
let mut event: TimelineEvent = match machine
.try_decrypt_room_event(event.cast_ref(), self.inner.room_id(), &decryption_settings)
.await?
{
Ok(event) => event,
Err(e) => {
RoomEventDecryptionResult::Decrypted(decrypted) => decrypted.into(),
RoomEventDecryptionResult::UnableToDecrypt(utd_info) => {
self.client
.encryption()
.backups()
.maybe_download_room_key(self.room_id().to_owned(), event.clone());

return Err(e.into());
TimelineEvent::new_utd_event(event.clone().cast(), utd_info)
}
};

let mut event: TimelineEvent = decrypted.into();
event.push_actions = self.event_push_actions(event.raw()).await?;

Ok(event)
}

Expand Down

0 comments on commit ab28964

Please sign in to comment.