// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // Copyright by contributors to this project. // SPDX-License-Identifier: (Apache-2.0 OR MIT)
use alloc::collections::VecDeque; use alloc::vec::Vec; use core::fmt::{self, Debug}; use mls_rs_codec::{MlsDecode, MlsEncode}; use mls_rs_core::group::{EpochRecord, GroupState}; use mls_rs_core::{error::IntoAnyError, group::GroupStateStorage, key_package::KeyPackageStorage};
#[cfg(feature = "psk")] use mls_rs_core::psk::PreSharedKey;
/// A set of changes to apply to a GroupStateStorage implementation. These changes MUST /// be made in a single transaction to avoid creating invalid states. #[derive(Default, Clone, Debug)] struct EpochStorageCommit { pub(crate) inserts: VecDeque<PriorEpoch>, pub(crate) updates: Vec<PriorEpoch>,
}
#[cfg(feature = "private_message")] #[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)] pubasyncfn get_epoch_mut(
&mutself,
epoch_id: u64,
) -> Result<Option<&mut PriorEpoch>, MlsError> { // Search the local inserts cache iflet Some(min) = self.pending_commit.inserts.front().map(|e| e.epoch_id()) { if epoch_id >= min { return Ok(self
.pending_commit
.inserts
.get_mut((epoch_id - min) as usize));
}
}
// Look in the cached updates map, and if not found look in disk storage // and insert into the updates map for future caching matchself.find_pending(epoch_id) {
Some(i) => self.pending_commit.updates.get_mut(i).map(Ok),
None => self
.storage
.epoch(&self.group_id, epoch_id)
.await
.map_err(|e| MlsError::GroupStorageError(e.into_any_error()))?
.and_then(|epoch| {
PriorEpoch::mls_decode(&mut &*epoch)
.map(|epoch| { self.pending_commit.updates.push(epoch); self.pending_commit.updates.last_mut()
})
.transpose()
}),
}
.transpose()
.map_err(Into::into)
}
// Make sure you can recall an epoch sitting as a pending insert let resumption = test_repo.resumption_secret(&psk_id).await.unwrap(); let prior_epoch = test_repo.get_epoch_mut(0).await.unwrap().cloned();
// Write to the storage let snapshot = test_snapshot(test_epoch.epoch_id()).await;
test_repo.write_to_storage(snapshot.clone()).await.unwrap();
// Make sure the memory cache cleared
assert!(test_repo.pending_commit.inserts.is_empty());
assert!(test_repo.pending_commit.updates.is_empty());
// Make sure the storage was written #[cfg(feature = "std")] let storage = test_repo.storage.inner.lock().unwrap(); #[cfg(not(feature = "std"))] let storage = test_repo.storage.inner.lock();
// Make sure you can access an epoch pending update let psk_id = ResumptionPsk {
psk_epoch: 0,
psk_group_id: PskGroupId(test_repo.group_id.clone()),
usage: ResumptionPSKUsage::Application,
};
let owned = test_repo.resumption_secret(&psk_id).await.unwrap();
assert_eq!(owned.as_ref(), Some(&to_update.secrets.resumption_secret));
// Write the update to storage let snapshot = test_snapshot(1).await;
test_repo.write_to_storage(snapshot.clone()).await.unwrap();
// Make sure the storage was written #[cfg(feature = "std")] let storage = test_repo.storage.inner.lock().unwrap(); #[cfg(not(feature = "std"))] let storage = test_repo.storage.inner.lock();
// Update the stored epoch let to_update = test_repo.get_epoch_mut(0).await.unwrap().unwrap(); let new_sender_secret = random_bytes(32);
to_update.secrets.sender_data_secret = SenderDataSecret::from(new_sender_secret); let to_update = to_update.clone();
// Insert another epoch let test_epoch_1 = test_epoch(1);
test_repo.insert(test_epoch_1.clone()).await.unwrap();
// Make sure the storage was written #[cfg(feature = "std")] let storage = test_repo.storage.inner.lock().unwrap(); #[cfg(not(feature = "std"))] let storage = test_repo.storage.inner.lock();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.