feat(crypto-nodejs) Implement OlmMachine.close

feat(crypto-nodejs) Implement `OlmMachine.close`
This commit is contained in:
Ivan Enderlin
2023-02-15 12:48:45 +01:00
committed by GitHub
2 changed files with 60 additions and 5 deletions

View File

@@ -2,6 +2,7 @@
use std::{
collections::{BTreeMap, HashMap},
ops::Deref,
sync::Arc,
};
@@ -16,11 +17,38 @@ use crate::{
sync_events, types, vodozemac,
};
/// The value used by the `OlmMachine` JS class.
///
/// It has 2 states: `Opened` and `Closed`. Why maintaining the state here?
/// Because NodeJS has no way to drop an object explicitly, and we want to be
/// able to “close” the `OlmMachine` to free all associated data. More over,
/// `napi-rs` doesn't allow a function to take the ownership of the type itself
/// (`fn close(self) { … }`). So we manage the state ourselves.
///
/// Using the `OlmMachine` when its state is `Closed` will panic.
enum OlmMachineInner {
Opened(matrix_sdk_crypto::OlmMachine),
Closed,
}
impl Deref for OlmMachineInner {
type Target = matrix_sdk_crypto::OlmMachine;
#[inline]
fn deref(&self) -> &Self::Target {
match self {
Self::Opened(machine) => machine,
Self::Closed => panic!("The `OlmMachine` has been closed, cannot use it anymore"),
}
}
}
/// State machine implementation of the Olm/Megolm encryption protocol
/// used for Matrix end to end encryption.
// #[napi(custom_finalize)]
#[napi]
pub struct OlmMachine {
inner: matrix_sdk_crypto::OlmMachine,
inner: OlmMachineInner,
}
#[napi]
@@ -77,7 +105,7 @@ impl OlmMachine {
store_passphrase.zeroize();
Ok(OlmMachine {
inner: match store {
inner: OlmMachineInner::Opened(match store {
Some(store) => matrix_sdk_crypto::OlmMachine::with_store(
user_id.inner.as_ref(),
device_id.inner.as_ref(),
@@ -92,7 +120,7 @@ impl OlmMachine {
)
.await
}
},
}),
})
}
@@ -409,4 +437,21 @@ impl OlmMachine {
pub async fn sign(&self, message: String) -> types::Signatures {
self.inner.sign(message.as_str()).await.into()
}
/// Shut down the `OlmMachine`.
///
/// The `OlmMachine` cannot be used after this method has been called,
/// otherwise it will panic.
///
/// All associated resources will be closed too, like the crypto storage
/// connections.
///
/// # Safety
///
/// The caller is responsible to **not** use any objects that came from this
/// `OlmMachine` after this `close` method has been called.
#[napi(strict)]
pub fn close(&mut self) {
self.inner = OlmMachineInner::Closed;
}
}

View File

@@ -25,7 +25,7 @@ describe(OlmMachine.name, () => {
expect(await OlmMachine.initialize(new UserId('@foo:bar.org'), new DeviceId('baz'), temp_directory, 'hello')).toBeInstanceOf(OlmMachine);
});
});
const user = new UserId('@alice:example.org');
const device = new DeviceId('foobar');
const room = new RoomId('!baz:matrix.org');
@@ -34,6 +34,16 @@ describe(OlmMachine.name, () => {
return OlmMachine.initialize(new_user || user, new_device || device);
}
test('can drop/close, and then re-open', async () => {
const temp_directory = await fs.mkdtemp(path.join(os.tmpdir(), 'matrix-sdk-crypto--'));
let m1 = await OlmMachine.initialize(new UserId('@test:bar.org'), new DeviceId('device'), temp_directory, 'hello')
m1.close();
let m2 = await OlmMachine.initialize(new UserId('@test:bar.org'), new DeviceId('device'), temp_directory, 'hello')
m2.close();
});
test('can read user ID', async () => {
expect((await machine()).userId.toString()).toStrictEqual(user.toString());
});
@@ -179,7 +189,7 @@ describe(OlmMachine.name, () => {
beforeAll(async () => {
m = await machine(user, device);
});
test('can pass keysquery and keysclaim requests directly', async () => {
{
// derived from https://github.com/matrix-org/matrix-rust-sdk/blob/7f49618d350fab66b7e1dc4eaf64ec25ceafd658/benchmarks/benches/crypto_bench/keys_query.json