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
@@ -101,6 +133,8 @@ use tokio_stream::wrappers::{
101133} ;
102134use tracing:: { info, instrument, trace, warn} ;
103135
136+ #[ cfg( doc) ]
137+ use super :: RoomEventCache ;
104138use crate :: {
105139 Room ,
106140 event_cache:: {
@@ -434,7 +468,44 @@ impl EventCache {
434468
435469 /// Explicitly request the redecryption of a set of events.
436470 ///
437- /// TODO: Explain when and why this might be useful.
471+ /// The redecryption logic in the event cache might sometimes miss that a
472+ /// room key has become available and that a certain set of events has
473+ /// become decryptable.
474+ ///
475+ /// This might happen because some room keys might arrive in a separate
476+ /// process handling push notifications or if a room key arrives but the
477+ /// process shuts down before we could have decrypted the events.
478+ ///
479+ /// For this reason it is useful to tell the event cache explicitly that
480+ /// some events should be retried to be redecrypted.
481+ ///
482+ /// This method allows you to do so. The events that get decrypted, if any,
483+ /// will be advertised over the usual event cache subscription mechanism
484+ /// which can be accessed using the [`RoomEventCache::subscribe()`]
485+ /// method.
486+ ///
487+ /// # Examples
488+ ///
489+ /// ```no_run
490+ /// # use matrix_sdk::{Client, event_cache::DecryptionRetryRequest};
491+ /// # use url::Url;
492+ /// # use ruma::owned_room_id;
493+ /// # use std::collections::BTreeSet;
494+ /// # async {
495+ /// # let homeserver = Url::parse("http://localhost:8080")?;
496+ /// # let client = Client::new(homeserver).await?;
497+ /// let event_cache = client.event_cache();
498+ /// let room_id = owned_room_id!("!my_room:localhost");
499+ ///
500+ /// let request = DecryptionRetryRequest {
501+ /// room_id,
502+ /// utd_session_ids: BTreeSet::from(["session_id".into()]),
503+ /// refresh_info_session_ids: BTreeSet::new(),
504+ /// };
505+ ///
506+ /// event_cache.request_decryption(request);
507+ /// # anyhow::Ok(()) };
508+ /// ```
438509 pub fn request_decryption ( & self , request : DecryptionRetryRequest ) {
439510 let _ =
440511 self . inner . redecryption_channels . decryption_request_sender . send ( request) . inspect_err (
@@ -444,8 +515,47 @@ impl EventCache {
444515
445516 /// Subscribe to reports that the redecryptor generates.
446517 ///
447- /// TODO: Explain when the redecryptor might send such reports.
448- pub fn subscrube_to_decryption_reports (
518+ /// The redecryption logic in the event cache might sometimes miss that a
519+ /// room key has become available and that a certain set of events has
520+ /// become decryptable.
521+ ///
522+ /// This might happen because some room keys might arrive in a separate
523+ /// process handling push notifications or if room keys arrive faster than
524+ /// we can handle them.
525+ ///
526+ /// This stream can be used to get notified about such situations as well as
527+ /// a general channel where the event cache reports which events got
528+ /// successfully redecrypted.
529+ ///
530+ /// # Examples
531+ ///
532+ /// ```no_run
533+ /// # use matrix_sdk::{Client, event_cache::RedecryptorReport};
534+ /// # use url::Url;
535+ /// # use tokio_stream::StreamExt;
536+ /// # async {
537+ /// # let homeserver = Url::parse("http://localhost:8080")?;
538+ /// # let client = Client::new(homeserver).await?;
539+ /// let event_cache = client.event_cache();
540+ ///
541+ /// let mut stream = event_cache.subscribe_to_decryption_reports();
542+ ///
543+ /// while let Some(Ok(report)) = stream.next().await {
544+ /// match report {
545+ /// RedecryptorReport::Lagging => {
546+ /// // The event cache might have missed to redecrypt some events. We should tell
547+ /// // it which events we care about, i.e. which events we're displaying to the
548+ /// // user, and let it redecrypt things with an explicit request.
549+ /// }
550+ /// RedecryptorReport::ResolvedUtds { .. } => {
551+ /// // This may be interesting for statistical reasons or in case we'd like to
552+ /// // fetch and inspect these events in some manner.
553+ /// }
554+ /// }
555+ /// }
556+ /// # anyhow::Ok(()) };
557+ /// ```
558+ pub fn subscribe_to_decryption_reports (
449559 & self ,
450560 ) -> impl Stream < Item = Result < RedecryptorReport , BroadcastStreamRecvError > > {
451561 BroadcastStream :: new ( self . inner . redecryption_channels . utd_reporter . subscribe ( ) )
0 commit comments