1212// See the License for the specific language governing permissions and
1313// limitations under the License.
1414
15- //! The Redecryptor (Rd) is a layer and long-running background task which
16- //! handles redecryption of events in case we couldn't decrypt them imediatelly.
15+ //! The Redecryptor (affectionately known as R2D2) is a layer and long-running
16+ //! background task which handles redecryption of events in case we couldn't
17+ //! decrypt them imediatelly.
1718//!
18- //! Rd listens to the OlmMachine for received room keys and new
19+ //! There are various reasons why a room key might not be available imediatelly
20+ //! when the event becomes available:
21+ //! - The to-device message containing the room key just arrives late, i.e.
22+ //! after the room event.
23+ //! - The event is a historic event and we need to first download the room
24+ //! key from the backup.
25+ //! - The event is a historic event in a previously unjoined room, we need
26+ //! to receive historic room keys as defined in [MSC3061](https://github.com/matrix-org/matrix-spec/pull/1655#issuecomment-2213152255).
27+ //!
28+ //! R2D2 listens to the OlmMachine for received room keys and new
1929//! m.room_key.withheld events.
2030//!
2131//! If a new room key has been received it attempts to find any UTDs in the
22- //! [`EventCache`]. If Rd decrypts any UTDs from the event cache it will replace
23- //! the events in the cache and send out new [`RoomEventCacheUpdates`] to any of
24- //! its listeners.
32+ //! [`EventCache`]. If R2D2 decrypts any UTDs from the event cache it will
33+ //! replace the events in the cache and send out new [`RoomEventCacheUpdates`]
34+ //! to any of its listeners.
2535//!
2636//! If a new withheld info has been received it attempts to find any relevant
2737//! events and updates the [`EncryptionInfo`] of an event.
3141//! a `None` on the room keys stream and we need to re-listen to it.
3242//!
3343//! Another gotcha is that room keys might be received on another process if the
34- //! Client is operating on a iOS device. A separate process is used in this case
35- //! to receive push notifications. In this case the room key will be received
36- //! and Rd won't get notified about it. To work around this decryption requests
37- //! can be explicitly sent to Rd .
44+ //! Client is operating on a Apple device. A separate process is used in this
45+ //! case to receive push notifications. In this case the room key will be
46+ //! received and R2D2 won't get notified about it. To work around this
47+ //! decryption requests can be explicitly sent to R2D2 .
3848//!
49+ //! ```markdown
50+ //!
51+ //! .----------------------.
52+ //! | |
53+ //! | Beeb, boop! |
54+ //! | .
55+ //! ----------------------._ \
56+ //! -; _____
57+ //! .`/L|__`.
58+ //! / =[_]O|` \
59+ //! |"+_____":|
60+ //! __:='|____`-:__
61+ //! ||[] ||====|| []||
62+ //! ||[] ||====|| []||
63+ //! |:== ||====|| ==:|
64+ //! ||[] ||====|| []||
65+ //! ||[] ||====|| []||
66+ //! _||_ ||====|| _||_
67+ //! (====) |:====:| (====)
68+ //! }--{ | | | | }--{
69+ //! (____) |_| |_| (____)
3970//!
4071//! ┌─────────────┐
4172//! │ │
42- //! ┌───────────┤ Timeline │◄────────────┐
73+ //! ┌───────────┤ Timeline │◄────────────┐
4374//! │ │ │ │
44- //! │ └─────▲─ ──────┘ │
45- //! │ │ │
46- //! │ │ │
47- //! │ │ │
48- //! Decryption │ Redecryptor
49- //! request │ report
50- //! │ RoomEventCacheUpdates │
51- //! │ │ │
52- //! │ │ │
53- //! │ ┌──────────┴─ ───────────┐ │
75+ //! │ └──────▲ ──────┘ │
76+ //! │ │ │
77+ //! │ │ │
78+ //! │ │ │
79+ //! Decryption │ Redecryptor
80+ //! request │ report
81+ //! │ RoomEventCacheUpdates │
82+ //! │ │ │
83+ //! │ │ │
84+ //! │ ┌───────────┴ ───────────┐ │
5485//! │ │ │ │
55- //! └──────► Redecryptor │────────┘
86+ //! └──────► R2D2 │────────┘
5687//! │ │
5788//! └───────────▲───────────┘
5889//! │
6798//! │ OlmMachine │
6899//! │ │
69100//! └──────────────┘
101+ //! ```
70102
71103use std:: { collections:: BTreeSet , pin:: Pin , sync:: Weak } ;
72104
@@ -104,6 +136,8 @@ use tokio_stream::wrappers::{
104136} ;
105137use tracing:: { info, instrument, trace, warn} ;
106138
139+ #[ cfg( doc) ]
140+ use super :: RoomEventCache ;
107141use crate :: {
108142 Room ,
109143 event_cache:: {
@@ -437,7 +471,44 @@ impl EventCache {
437471
438472 /// Explicitly request the redecryption of a set of events.
439473 ///
440- /// TODO: Explain when and why this might be useful.
474+ /// The redecryption logic in the event cache might sometimes miss that a
475+ /// room key has become available and that a certain set of events has
476+ /// become decryptable.
477+ ///
478+ /// This might happen because some room keys might arrive in a separate
479+ /// process handling push notifications or if a room key arrives but the
480+ /// process shuts down before we could have decrypted the events.
481+ ///
482+ /// For this reason it is useful to tell the event cache explicitly that
483+ /// some events should be retried to be redecrypted.
484+ ///
485+ /// This method allows you to do so. The events that get decrypted, if any,
486+ /// will be advertised over the usual event cache subscription mechanism
487+ /// which can be accessed using the [`RoomEventCache::subscribe()`]
488+ /// method.
489+ ///
490+ /// # Examples
491+ ///
492+ /// ```no_run
493+ /// # use matrix_sdk::{Client, event_cache::DecryptionRetryRequest};
494+ /// # use url::Url;
495+ /// # use ruma::owned_room_id;
496+ /// # use std::collections::BTreeSet;
497+ /// # async {
498+ /// # let homeserver = Url::parse("http://localhost:8080")?;
499+ /// # let client = Client::new(homeserver).await?;
500+ /// let event_cache = client.event_cache();
501+ /// let room_id = owned_room_id!("!my_room:localhost");
502+ ///
503+ /// let request = DecryptionRetryRequest {
504+ /// room_id,
505+ /// utd_session_ids: BTreeSet::from(["session_id".into()]),
506+ /// refresh_info_session_ids: BTreeSet::new(),
507+ /// };
508+ ///
509+ /// event_cache.request_decryption(request);
510+ /// # anyhow::Ok(()) };
511+ /// ```
441512 pub fn request_decryption ( & self , request : DecryptionRetryRequest ) {
442513 let _ =
443514 self . inner . redecryption_channels . decryption_request_sender . send ( request) . inspect_err (
@@ -447,8 +518,47 @@ impl EventCache {
447518
448519 /// Subscribe to reports that the redecryptor generates.
449520 ///
450- /// TODO: Explain when the redecryptor might send such reports.
451- pub fn subscrube_to_decryption_reports (
521+ /// The redecryption logic in the event cache might sometimes miss that a
522+ /// room key has become available and that a certain set of events has
523+ /// become decryptable.
524+ ///
525+ /// This might happen because some room keys might arrive in a separate
526+ /// process handling push notifications or if room keys arrive faster than
527+ /// we can handle them.
528+ ///
529+ /// This stream can be used to get notified about such situations as well as
530+ /// a general channel where the event cache reports which events got
531+ /// successfully redecrypted.
532+ ///
533+ /// # Examples
534+ ///
535+ /// ```no_run
536+ /// # use matrix_sdk::{Client, event_cache::RedecryptorReport};
537+ /// # use url::Url;
538+ /// # use tokio_stream::StreamExt;
539+ /// # async {
540+ /// # let homeserver = Url::parse("http://localhost:8080")?;
541+ /// # let client = Client::new(homeserver).await?;
542+ /// let event_cache = client.event_cache();
543+ ///
544+ /// let mut stream = event_cache.subscribe_to_decryption_reports();
545+ ///
546+ /// while let Some(Ok(report)) = stream.next().await {
547+ /// match report {
548+ /// RedecryptorReport::Lagging => {
549+ /// // The event cache might have missed to redecrypt some events. We should tell
550+ /// // it which events we care about, i.e. which events we're displaying to the
551+ /// // user, and let it redecrypt things with an explicit request.
552+ /// }
553+ /// RedecryptorReport::ResolvedUtds { .. } => {
554+ /// // This may be interesting for statistical reasons or in case we'd like to
555+ /// // fetch and inspect these events in some manner.
556+ /// }
557+ /// }
558+ /// }
559+ /// # anyhow::Ok(()) };
560+ /// ```
561+ pub fn subscribe_to_decryption_reports (
452562 & self ,
453563 ) -> impl Stream < Item = Result < RedecryptorReport , BroadcastStreamRecvError > > {
454564 BroadcastStream :: new ( self . inner . redecryption_channels . utd_reporter . subscribe ( ) )
0 commit comments