pub struct DehydratedDevices { /* private fields */ }e2e-encryption only.Expand description
High-level handle returned by
Encryption::dehydrated_devices.
Implementations§
Source§impl DehydratedDevices
impl DehydratedDevices
Sourcepub fn state_stream(
&self,
) -> impl Stream<Item = Result<DehydratedDeviceEvent, BroadcastStreamRecvError>> + use<>
pub fn state_stream( &self, ) -> impl Stream<Item = Result<DehydratedDeviceEvent, BroadcastStreamRecvError>> + use<>
Subscribe to the stream of DehydratedDeviceEvents.
Each call returns a fresh stream. If a subscriber is slow enough to
fall behind the channel’s buffer, it receives a
BroadcastStreamRecvError reporting the number of skipped events
and the stream continues from the most recent event.
§Example
let dehydrated = client.encryption().dehydrated_devices();
let mut stream = dehydrated.state_stream();
while let Some(Ok(event)) = stream.next().await {
println!("dehydrated devices: {event:?}");
}Sourcepub async fn is_supported(&self) -> Result<bool, DehydratedDeviceError>
pub async fn is_supported(&self) -> Result<bool, DehydratedDeviceError>
Return whether the homeserver advertises dehydrated-device support.
Probes by issuing GET /dehydrated_device and inspecting the errcode
of the response:
M_UNRECOGNIZEDmeans the server does not understand the endpoint.M_NOT_FOUNDor a successful response means the server understands the endpoint (whether or not the user currently has a dehydrated device on file).
Any other transport or API failure is propagated.
Sourcepub async fn create(
&self,
display_name: Option<&str>,
pickle_key: &DehydratedDeviceKey,
) -> Result<OwnedDeviceId, DehydratedDeviceError>
pub async fn create( &self, display_name: Option<&str>, pickle_key: &DehydratedDeviceKey, ) -> Result<OwnedDeviceId, DehydratedDeviceError>
Create a fresh dehydrated device and upload it to the homeserver.
The pickle key is used by vodozemac to encrypt the private parts of the device. The application is responsible for safely storing the pickle key (typically in Secret Storage so future sessions can rehydrate the device).
§Arguments
display_name- Optional human-readable name uploaded as the dehydrated device’sinitial_device_display_name. Defaults to"Dehydrated device".pickle_key- 32-byte key used to encrypt the dehydrated device.
§Example
let pickle_key = DehydratedDeviceKey::new();
let device_id = client
.encryption()
.dehydrated_devices()
.create(Some("Offline catcher"), &pickle_key)
.await?;
println!("Uploaded dehydrated device {device_id}");Sourcepub async fn rehydrate(
&self,
pickle_key: &DehydratedDeviceKey,
) -> Result<bool, DehydratedDeviceError>
pub async fn rehydrate( &self, pickle_key: &DehydratedDeviceKey, ) -> Result<bool, DehydratedDeviceError>
Rehydrate the dehydrated device currently on the server, if any.
Downloads the dehydrated device, decrypts it with pickle_key,
drains all queued to-device events to import their room keys, and
finally deletes the device from the server.
Returns Ok(false) if the server reports no dehydrated device
(M_NOT_FOUND) or does not implement the endpoint
(M_UNRECOGNIZED). Returns Ok(true) once the rehydration cycle
has completed end to end.
If the drain stops defensively before the server’s queue is
exhausted, the device is left on the server and
DehydratedDeviceError::DrainTruncated is returned. Calling this
method again restarts the drain from the beginning of the queue;
room keys imported by the earlier attempt import idempotently.
§Example
let rehydrated =
client.encryption().dehydrated_devices().rehydrate(&pickle_key).await?;
if rehydrated {
println!("Caught up on offline room keys");
}Sourcepub async fn is_key_stored(
&self,
secret_store: &SecretStore,
) -> Result<bool, DehydratedDeviceError>
pub async fn is_key_stored( &self, secret_store: &SecretStore, ) -> Result<bool, DehydratedDeviceError>
Return whether the pickle key is stored in the given Secret Storage.
The key is looked up by the account-data event type
org.matrix.msc3814 (the unstable name reserved by MSC3814).
§Example
let stored =
client.encryption().dehydrated_devices().is_key_stored(&store).await?;Sourcepub async fn reset_key(
&self,
secret_store: &SecretStore,
) -> Result<DehydratedDeviceKey, DehydratedDeviceError>
pub async fn reset_key( &self, secret_store: &SecretStore, ) -> Result<DehydratedDeviceKey, DehydratedDeviceError>
Generate a new random pickle key, persist it in Secret Storage, and cache it in the local crypto store.
The previous key (if any) is overwritten in both places. Any dehydrated device that was encrypted with the previous key becomes unrehydratable until rotated.
§Example
let fresh_key =
client.encryption().dehydrated_devices().reset_key(&store).await?;Sourcepub fn start<'a>(
&'a self,
secret_store: &'a SecretStore,
) -> StartDehydration<'a>
pub fn start<'a>( &'a self, secret_store: &'a SecretStore, ) -> StartDehydration<'a>
Start using dehydrated devices for this client.
Returns a StartDehydration future. Await it directly for the default
behavior, or configure it first with
StartDehydration::create_new_key,
StartDehydration::skip_rehydration, and
StartDehydration::only_if_key_cached.
The caller is expected to have unlocked Secret Storage and bootstrapped cross-signing before this call; otherwise the underlying account-data reads and writes will fail mid-flight.
Awaiting the future performs the following steps:
- If
StartDehydration::only_if_key_cachedwas set, return early when no pickle key is cached locally. - Stop any previously scheduled rotation.
- Unless
StartDehydration::skip_rehydrationwas set, attempt to rehydrate the existing dehydrated device. Failures are logged and emitted asDehydratedDeviceEvent::RehydrationErrorbut do not abort the start. - If
StartDehydration::create_new_keywas set and the rehydration step succeeded (or was skipped), replace the pickle key in Secret Storage with a fresh random one. A failed rehydration suppresses the reset so the stored key can still recover the existing dehydrated device on another client. - Create a new dehydrated device now and schedule rotation once a week.
The rotation task resolves the pickle key from the local crypto store on
each tick. The local cache is the only key source available to the task
because reopening Secret Storage requires the recovery key, which is not
retained. Per-tick failures emit
DehydratedDeviceEvent::RotationError without aborting the schedule.
§Example
client.encryption().dehydrated_devices().start(&store).await?;Sourcepub fn stop(&self)
pub fn stop(&self)
Stop the scheduled dehydrated-device rotation, if any.
Has no effect when no rotation is scheduled. Existing dehydrated
devices on the server are left in place; pair with
Self::delete to clean those up.
Sourcepub async fn delete(&self) -> Result<(), DehydratedDeviceError>
pub async fn delete(&self) -> Result<(), DehydratedDeviceError>
Delete the current dehydrated device, if one exists.
Also stops any scheduled rotation, so the next tick will not immediately recreate the device the caller just asked to remove.
Returns Ok(()) silently if no dehydrated device is on the server or
the server does not implement the endpoint.
§Example
client.encryption().dehydrated_devices().delete().await?;Trait Implementations§
Source§impl Clone for DehydratedDevices
impl Clone for DehydratedDevices
Source§fn clone(&self) -> DehydratedDevices
fn clone(&self) -> DehydratedDevices
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl !RefUnwindSafe for DehydratedDevices
impl !UnwindSafe for DehydratedDevices
impl Freeze for DehydratedDevices
impl Send for DehydratedDevices
impl Sync for DehydratedDevices
impl Unpin for DehydratedDevices
impl UnsafeUnpin for DehydratedDevices
Blanket Implementations§
impl<T> Any for Twhere
T: Any,
impl<T> AsyncTraitDeps for T
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<T> CloneAny for T
impl<T> CloneAnySend for T
impl<T> CloneAnySendSync for T
impl<T> CloneAnySync for T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> CompatExt for T
impl<T> CompatExt for T
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> DropFlavorWrapper<T> for T
impl<T> DropFlavorWrapper<T> for T
impl<T> ErasedDestructor for Twhere
T: 'static,
impl<T> Fruit for T
§impl<T, UT> HandleAlloc<UT> for T
impl<T, UT> HandleAlloc<UT> for T
§fn new_handle(value: Arc<T>) -> Handle
fn new_handle(value: Arc<T>) -> Handle
§unsafe fn clone_handle(handle: Handle) -> Handle
unsafe fn clone_handle(handle: Handle) -> Handle
§unsafe fn consume_handle(handle: Handle) -> Arc<T>
unsafe fn consume_handle(handle: Handle) -> Arc<T>
Arc<> Read moreSource§impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
Source§impl<T> Identity for Twhere
T: ?Sized,
impl<T> Identity for Twhere
T: ?Sized,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more