diff --git a/matrix_sdk/src/client.rs b/matrix_sdk/src/client.rs index 5daaeade..eb7c0ff9 100644 --- a/matrix_sdk/src/client.rs +++ b/matrix_sdk/src/client.rs @@ -36,7 +36,7 @@ use tracing::{error, info, instrument}; use matrix_sdk_base::{BaseClient, BaseClientConfig, Room, Session, StateStore}; #[cfg(feature = "encryption")] -use matrix_sdk_base::{CryptoStoreError, OutgoingRequests}; +use matrix_sdk_base::{CryptoStoreError, OutgoingRequests, ToDeviceRequest}; use matrix_sdk_common::{ api::r0::{ @@ -72,8 +72,7 @@ use matrix_sdk_common::{ api::r0::{ keys::{claim_keys, get_keys, upload_keys}, to_device::send_event_to_device::{ - IncomingRequest as OwnedToDeviceRequest, Request as ToDeviceRequest, - Response as ToDeviceResponse, + Request as RumaToDeviceRequest, Response as ToDeviceResponse, }, }, locks::Mutex, @@ -1101,11 +1100,12 @@ impl Client { } #[cfg(feature = "encryption")] - async fn send_to_device(&self, request: &OwnedToDeviceRequest) -> Result { - let request = ToDeviceRequest { - event_type: request.event_type.clone(), - txn_id: &request.txn_id, - messages: request.messages.clone(), + async fn send_to_device(&self, request: ToDeviceRequest) -> Result { + let txn_id_string = request.txn_id_string(); + let request = RumaToDeviceRequest { + event_type: request.event_type, + txn_id: &txn_id_string, + messages: request.messages, }; self.send(request).await @@ -1230,14 +1230,13 @@ impl Client { warn!("Error while querying device keys {:?}", e); } } - OutgoingRequests::KeysUpload(request) => { if let Err(e) = self.keys_upload(&r.request_id(), request).await { warn!("Error while querying device keys {:?}", e); } } OutgoingRequests::ToDeviceRequest(request) => { - if let Ok(resp) = self.send_to_device(request).await { + if let Ok(resp) = self.send_to_device(request.clone()).await { self.base_client .mark_request_as_sent(&r.request_id(), &resp) .await @@ -1320,7 +1319,7 @@ impl Client { .expect("Keys don't need to be uploaded"); for request in requests.drain(..) { - self.send_to_device(&request).await?; + self.send_to_device(request).await?; } Ok(()) diff --git a/matrix_sdk/src/device.rs b/matrix_sdk/src/device.rs index 49dfd5ab..7173e266 100644 --- a/matrix_sdk/src/device.rs +++ b/matrix_sdk/src/device.rs @@ -64,7 +64,7 @@ impl Device { let (sas, request) = self.inner.start_verification().await?; let request = ToDeviceRequest { event_type: request.event_type, - txn_id: &request.txn_id, + txn_id: &request.txn_id.to_string(), messages: request.messages, }; diff --git a/matrix_sdk/src/sas.rs b/matrix_sdk/src/sas.rs index cadaddd1..2a8e8708 100644 --- a/matrix_sdk/src/sas.rs +++ b/matrix_sdk/src/sas.rs @@ -30,7 +30,7 @@ impl Sas { if let Some(req) = self.inner.accept() { let request = ToDeviceRequest { event_type: req.event_type, - txn_id: &req.txn_id, + txn_id: &req.txn_id.to_string(), messages: req.messages, }; @@ -44,7 +44,7 @@ impl Sas { if let Some(req) = self.inner.confirm().await? { let request = ToDeviceRequest { event_type: req.event_type, - txn_id: &req.txn_id, + txn_id: &req.txn_id.to_string(), messages: req.messages, }; @@ -56,10 +56,10 @@ impl Sas { /// Cancel the interactive verification flow. pub async fn cancel(&self) -> Result<()> { - if let Some((_, req)) = self.inner.cancel() { + if let Some(req) = self.inner.cancel() { let request = ToDeviceRequest { event_type: req.event_type, - txn_id: &req.txn_id, + txn_id: &req.txn_id.to_string(), messages: req.messages, }; diff --git a/matrix_sdk_base/src/client.rs b/matrix_sdk_base/src/client.rs index 5f2e14ea..07ef1795 100644 --- a/matrix_sdk_base/src/client.rs +++ b/matrix_sdk_base/src/client.rs @@ -39,7 +39,6 @@ use matrix_sdk_common::{ #[cfg(feature = "encryption")] use matrix_sdk_common::{ api::r0::keys::claim_keys::Request as KeysClaimRequest, - api::r0::to_device::send_event_to_device::IncomingRequest as OwnedToDeviceRequest, events::{room::encrypted::EncryptedEventContent, AnyMessageEventContent}, identifiers::DeviceId, uuid::Uuid, @@ -47,7 +46,7 @@ use matrix_sdk_common::{ #[cfg(feature = "encryption")] use matrix_sdk_crypto::{ CryptoStore, CryptoStoreError, Device, IncomingResponse, OlmError, OlmMachine, OutgoingRequest, - Sas, UserDevices, + Sas, ToDeviceRequest, UserDevices, }; use zeroize::Zeroizing; @@ -1304,7 +1303,7 @@ impl BaseClient { /// Get a to-device request that will share a group session for a room. #[cfg(feature = "encryption")] #[cfg_attr(feature = "docs", doc(cfg(encryption)))] - pub async fn share_group_session(&self, room_id: &RoomId) -> Result> { + pub async fn share_group_session(&self, room_id: &RoomId) -> Result> { let room = self.get_joined_room(room_id).await.expect("No room found"); let olm = self.olm.lock().await; diff --git a/matrix_sdk_base/src/lib.rs b/matrix_sdk_base/src/lib.rs index f96d1728..abfaf827 100644 --- a/matrix_sdk_base/src/lib.rs +++ b/matrix_sdk_base/src/lib.rs @@ -58,7 +58,7 @@ pub use state::{AllRooms, ClientState}; #[cfg_attr(feature = "docs", doc(cfg(encryption)))] pub use matrix_sdk_crypto::{ CryptoStoreError, Device, IncomingResponse, LocalTrust, OutgoingRequest, OutgoingRequests, - ReadOnlyDevice, Sas, UserDevices, + ReadOnlyDevice, Sas, ToDeviceRequest, UserDevices, }; #[cfg(feature = "messages")] diff --git a/matrix_sdk_crypto/src/device.rs b/matrix_sdk_crypto/src/device.rs index 687401aa..0e1087eb 100644 --- a/matrix_sdk_crypto/src/device.rs +++ b/matrix_sdk_crypto/src/device.rs @@ -24,9 +24,7 @@ use std::{ use atomic::Atomic; use matrix_sdk_common::{ - api::r0::{ - keys::SignedKey, to_device::send_event_to_device::IncomingRequest as OwnedToDeviceRequest, - }, + api::r0::keys::SignedKey, encryption::DeviceKeys, events::{room::encrypted::EncryptedEventContent, EventType}, identifiers::{DeviceId, DeviceKeyAlgorithm, DeviceKeyId, EventEncryptionAlgorithm, UserId}, @@ -43,7 +41,7 @@ use crate::{ store::Result as StoreResult, user_identity::{OwnUserIdentity, UserIdentities}, verification::VerificationMachine, - verify_json, ReadOnlyUserDevices, Sas, + verify_json, ReadOnlyUserDevices, Sas, ToDeviceRequest, }; /// A read-only version of a `Device`. @@ -80,7 +78,7 @@ impl Device { /// Start a interactive verification with this `Device` /// /// Returns a `Sas` object and to-device request that needs to be sent out. - pub async fn start_verification(&self) -> StoreResult<(Sas, OwnedToDeviceRequest)> { + pub async fn start_verification(&self) -> StoreResult<(Sas, ToDeviceRequest)> { self.verification_machine .start_sas(self.inner.clone()) .await diff --git a/matrix_sdk_crypto/src/lib.rs b/matrix_sdk_crypto/src/lib.rs index 451d5f4a..af63b034 100644 --- a/matrix_sdk_crypto/src/lib.rs +++ b/matrix_sdk_crypto/src/lib.rs @@ -44,7 +44,7 @@ pub use machine::OlmMachine; pub use memory_stores::ReadOnlyUserDevices; pub(crate) use olm::Account; pub use olm::EncryptionSettings; -pub use requests::{IncomingResponse, OutgoingRequest, OutgoingRequests}; +pub use requests::{IncomingResponse, OutgoingRequest, OutgoingRequests, ToDeviceRequest}; #[cfg(feature = "sqlite_cryptostore")] pub use store::sqlite::SqliteStore; pub use store::{CryptoStore, CryptoStoreError}; diff --git a/matrix_sdk_crypto/src/machine.rs b/matrix_sdk_crypto/src/machine.rs index 77fbd492..baf36789 100644 --- a/matrix_sdk_crypto/src/machine.rs +++ b/matrix_sdk_crypto/src/machine.rs @@ -34,9 +34,7 @@ use matrix_sdk_common::{ upload_keys, }, sync::sync_events::Response as SyncResponse, - to_device::{ - send_event_to_device::IncomingRequest as OwnedToDeviceRequest, DeviceIdOrAllDevices, - }, + to_device::DeviceIdOrAllDevices, }, encryption::DeviceKeys, events::{ @@ -59,7 +57,7 @@ use super::{ Account, EncryptionSettings, GroupSessionKey, IdentityKeys, InboundGroupSession, OlmMessage, OutboundGroupSession, }, - requests::{IncomingResponse, OutgoingRequest}, + requests::{IncomingResponse, OutgoingRequest, ToDeviceRequest}, store::{memorystore::MemoryStore, Result as StoreResult}, user_identity::{ MasterPubkey, OwnUserIdentity, SelfSigningPubkey, UserIdentities, UserIdentity, @@ -1127,7 +1125,7 @@ impl OlmMachine { room_id: &RoomId, users: impl Iterator, encryption_settings: impl Into, - ) -> OlmResult> { + ) -> OlmResult> { self.create_outbound_group_session(room_id, encryption_settings.into()) .await?; let session = self.outbound_group_sessions.get(room_id).unwrap(); @@ -1181,9 +1179,9 @@ impl OlmMachine { ); } - requests.push(OwnedToDeviceRequest { + requests.push(ToDeviceRequest { event_type: EventType::RoomEncrypted, - txn_id: Uuid::new_v4().to_string(), + txn_id: Uuid::new_v4(), messages, }); } @@ -1555,14 +1553,11 @@ pub(crate) mod test { use crate::{ machine::OlmMachine, verification::test::{outgoing_request_to_event, request_to_event}, - verify_json, EncryptionSettings, ReadOnlyDevice, + verify_json, EncryptionSettings, ReadOnlyDevice, ToDeviceRequest, }; use matrix_sdk_common::{ - api::r0::{ - keys::{claim_keys, get_keys, upload_keys, OneTimeKey}, - to_device::send_event_to_device::IncomingRequest as OwnedToDeviceRequest, - }, + api::r0::keys::{claim_keys, get_keys, upload_keys, OneTimeKey}, events::{ room::{ encrypted::EncryptedEventContent, @@ -1612,7 +1607,7 @@ pub(crate) mod test { get_keys::Response::try_from(data).expect("Can't parse the keys upload response") } - fn to_device_requests_to_content(requests: Vec) -> EncryptedEventContent { + fn to_device_requests_to_content(requests: Vec) -> EncryptedEventContent { let to_device_request = &requests[0]; let content: Raw = serde_json::from_str( diff --git a/matrix_sdk_crypto/src/requests.rs b/matrix_sdk_crypto/src/requests.rs index a63d86a0..342f0b32 100644 --- a/matrix_sdk_crypto/src/requests.rs +++ b/matrix_sdk_crypto/src/requests.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::sync::Arc; +use std::{collections::BTreeMap, sync::Arc}; use matrix_sdk_common::{ api::r0::{ @@ -21,13 +21,41 @@ use matrix_sdk_common::{ get_keys::{IncomingRequest as KeysQueryRequest, Response as KeysQueryResponse}, upload_keys::{Request as KeysUploadRequest, Response as KeysUploadResponse}, }, - to_device::send_event_to_device::{ - IncomingRequest as ToDeviceRequest, Response as ToDeviceResponse, - }, + to_device::{send_event_to_device::Response as ToDeviceResponse, DeviceIdOrAllDevices}, }, + events::EventType, + identifiers::UserId, uuid::Uuid, }; +use serde_json::value::RawValue as RawJsonValue; + +/// Customized version of `ruma_client_api::r0::to_device::send_event_to_device::Request`, using a +/// UUID for the transaction ID. +#[derive(Clone, Debug)] +pub struct ToDeviceRequest { + /// Type of event being sent to each device. + pub event_type: EventType, + + /// A request identifier unique to the access token used to send the request. + pub txn_id: Uuid, + + /// A map of users to devices to a content for a message event to be + /// sent to the user's device. Individual message events can be sent + /// to devices, but all events must be of the same type. + /// The content's type for this field will be updated in a future + /// release, until then you can create a value using + /// `serde_json::value::to_raw_value`. + pub messages: BTreeMap>>, +} + +impl ToDeviceRequest { + /// Gets the transaction ID as a string. + pub fn txn_id_string(&self) -> String { + self.txn_id.to_string() + } +} + /// Enum over the different outgoing requests we can have. #[derive(Debug)] pub enum OutgoingRequests { diff --git a/matrix_sdk_crypto/src/verification/machine.rs b/matrix_sdk_crypto/src/verification/machine.rs index 898c5830..0728a7b6 100644 --- a/matrix_sdk_crypto/src/verification/machine.rs +++ b/matrix_sdk_crypto/src/verification/machine.rs @@ -19,14 +19,16 @@ use dashmap::DashMap; use tracing::{trace, warn}; use matrix_sdk_common::{ - api::r0::to_device::send_event_to_device::IncomingRequest as OwnedToDeviceRequest, events::{AnyToDeviceEvent, AnyToDeviceEventContent}, identifiers::{DeviceId, UserId}, uuid::Uuid, }; use super::sas::{content_to_request, Sas}; -use crate::{requests::OutgoingRequest, Account, CryptoStore, CryptoStoreError, ReadOnlyDevice}; +use crate::{ + requests::OutgoingRequest, Account, CryptoStore, CryptoStoreError, ReadOnlyDevice, + ToDeviceRequest, +}; #[derive(Clone, Debug)] pub struct VerificationMachine { @@ -49,7 +51,7 @@ impl VerificationMachine { pub async fn start_sas( &self, device: ReadOnlyDevice, - ) -> Result<(Sas, OwnedToDeviceRequest), CryptoStoreError> { + ) -> Result<(Sas, ToDeviceRequest), CryptoStoreError> { let identity = self.store.get_user_identity(device.user_id()).await?; let (sas, content) = Sas::start( @@ -59,7 +61,7 @@ impl VerificationMachine { identity, ); - let (_, request) = content_to_request( + let request = content_to_request( device.user_id(), device.device_id(), AnyToDeviceEventContent::KeyVerificationStart(content), @@ -82,7 +84,8 @@ impl VerificationMachine { recipient_device: &DeviceId, content: AnyToDeviceEventContent, ) { - let (request_id, request) = content_to_request(recipient, recipient_device, content); + let request = content_to_request(recipient, recipient_device, content); + let request_id = request.txn_id; let request = OutgoingRequest { request_id, @@ -117,10 +120,10 @@ impl VerificationMachine { for sas in self.verifications.iter() { if let Some(r) = sas.cancel_if_timed_out() { self.outgoing_to_device_messages.insert( - r.0, + r.txn_id, OutgoingRequest { - request_id: r.0, - request: Arc::new(r.1.into()), + request_id: r.txn_id, + request: Arc::new(r.into()), }, ); } @@ -193,10 +196,10 @@ impl VerificationMachine { if !s.mark_device_as_verified().await? { if let Some(r) = s.cancel() { self.outgoing_to_device_messages.insert( - r.0, + r.txn_id, OutgoingRequest { - request_id: r.0, - request: Arc::new(r.1.into()), + request_id: r.txn_id, + request: Arc::new(r.into()), }, ); } diff --git a/matrix_sdk_crypto/src/verification/mod.rs b/matrix_sdk_crypto/src/verification/mod.rs index ab79c0f7..7083c760 100644 --- a/matrix_sdk_crypto/src/verification/mod.rs +++ b/matrix_sdk_crypto/src/verification/mod.rs @@ -20,19 +20,15 @@ pub use sas::Sas; #[cfg(test)] pub(crate) mod test { - use crate::requests::{OutgoingRequest, OutgoingRequests}; + use crate::requests::{OutgoingRequest, OutgoingRequests, ToDeviceRequest}; use serde_json::Value; use matrix_sdk_common::{ - api::r0::to_device::send_event_to_device::IncomingRequest as OwnedToDeviceRequest, events::{AnyToDeviceEvent, AnyToDeviceEventContent, EventType, ToDeviceEvent}, identifiers::UserId, }; - pub(crate) fn request_to_event( - sender: &UserId, - request: &OwnedToDeviceRequest, - ) -> AnyToDeviceEvent { + pub(crate) fn request_to_event(sender: &UserId, request: &ToDeviceRequest) -> AnyToDeviceEvent { let content = get_content_from_request(request); wrap_any_to_device_content(sender, content) } @@ -81,9 +77,7 @@ pub(crate) mod test { } } - pub(crate) fn get_content_from_request( - request: &OwnedToDeviceRequest, - ) -> AnyToDeviceEventContent { + pub(crate) fn get_content_from_request(request: &ToDeviceRequest) -> AnyToDeviceEventContent { let json: Value = serde_json::from_str( request .messages diff --git a/matrix_sdk_crypto/src/verification/sas/helpers.rs b/matrix_sdk_crypto/src/verification/sas/helpers.rs index 259248e1..262b4bac 100644 --- a/matrix_sdk_crypto/src/verification/sas/helpers.rs +++ b/matrix_sdk_crypto/src/verification/sas/helpers.rs @@ -19,9 +19,7 @@ use tracing::{trace, warn}; use olm_rs::sas::OlmSas; use matrix_sdk_common::{ - api::r0::to_device::{ - send_event_to_device::IncomingRequest as OwnedToDeviceRequest, DeviceIdOrAllDevices, - }, + api::r0::to_device::DeviceIdOrAllDevices, events::{ key::verification::{cancel::CancelCode, mac::MacEventContent}, AnyToDeviceEventContent, EventType, ToDeviceEvent, @@ -30,7 +28,7 @@ use matrix_sdk_common::{ uuid::Uuid, }; -use crate::{user_identity::UserIdentities, Account, ReadOnlyDevice}; +use crate::{user_identity::UserIdentities, Account, ReadOnlyDevice, ToDeviceRequest}; #[derive(Clone, Debug)] pub struct SasIds { @@ -464,7 +462,7 @@ pub fn content_to_request( recipient: &UserId, recipient_device: &DeviceId, content: AnyToDeviceEventContent, -) -> (Uuid, OwnedToDeviceRequest) { +) -> ToDeviceRequest { let mut messages = BTreeMap::new(); let mut user_messages = BTreeMap::new(); @@ -483,16 +481,11 @@ pub fn content_to_request( _ => unreachable!(), }; - let request_id = Uuid::new_v4(); - - ( - request_id, - OwnedToDeviceRequest { - txn_id: request_id.to_string(), - event_type, - messages, - }, - ) + ToDeviceRequest { + txn_id: Uuid::new_v4(), + event_type, + messages, + } } #[cfg(test)] diff --git a/matrix_sdk_crypto/src/verification/sas/mod.rs b/matrix_sdk_crypto/src/verification/sas/mod.rs index 3e4db5e3..aaf8ef86 100644 --- a/matrix_sdk_crypto/src/verification/sas/mod.rs +++ b/matrix_sdk_crypto/src/verification/sas/mod.rs @@ -22,7 +22,6 @@ use std::sync::{Arc, Mutex}; use tracing::{info, trace, warn}; use matrix_sdk_common::{ - api::r0::to_device::send_event_to_device::IncomingRequest as OwnedToDeviceRequest, events::{ key::verification::{ accept::AcceptEventContent, cancel::CancelCode, mac::MacEventContent, @@ -31,12 +30,11 @@ use matrix_sdk_common::{ AnyToDeviceEvent, AnyToDeviceEventContent, ToDeviceEvent, }, identifiers::{DeviceId, UserId}, - uuid::Uuid, }; use crate::{ user_identity::UserIdentities, Account, CryptoStore, CryptoStoreError, LocalTrust, - ReadOnlyDevice, + ReadOnlyDevice, ToDeviceRequest, }; pub use helpers::content_to_request; @@ -166,10 +164,10 @@ impl Sas { /// /// This does nothing if the verification was already accepted, otherwise it /// returns an `AcceptEventContent` that needs to be sent out. - pub fn accept(&self) -> Option { + pub fn accept(&self) -> Option { self.inner.lock().unwrap().accept().map(|c| { let content = AnyToDeviceEventContent::KeyVerificationAccept(c); - self.content_to_request(content).1 + self.content_to_request(content) }) } @@ -180,7 +178,7 @@ impl Sas { /// Does nothing if we're not in a state where we can confirm the short auth /// string, otherwise returns a `MacEventContent` that needs to be sent to /// the server. - pub async fn confirm(&self) -> Result, CryptoStoreError> { + pub async fn confirm(&self) -> Result, CryptoStoreError> { let (content, done) = { let mut guard = self.inner.lock().unwrap(); let sas: InnerSas = (*guard).clone(); @@ -195,7 +193,7 @@ impl Sas { // else branch and only after the identity was verified as well. We // dont' want to verify one without the other. if !self.mark_device_as_verified().await? { - return Ok(self.cancel().map(|r| r.1)); + return Ok(self.cancel()); } else { self.mark_identity_as_verified().await?; } @@ -203,7 +201,7 @@ impl Sas { Ok(content.map(|c| { let content = AnyToDeviceEventContent::KeyVerificationMac(c); - self.content_to_request(content).1 + self.content_to_request(content) })) } @@ -328,7 +326,7 @@ impl Sas { /// /// Returns None if the `Sas` object is already in a canceled state, /// otherwise it returns a request that needs to be sent out. - pub fn cancel(&self) -> Option<(Uuid, OwnedToDeviceRequest)> { + pub fn cancel(&self) -> Option { let mut guard = self.inner.lock().unwrap(); let sas: InnerSas = (*guard).clone(); let (sas, content) = sas.cancel(CancelCode::User); @@ -337,7 +335,7 @@ impl Sas { content.map(|c| self.content_to_request(c)) } - pub(crate) fn cancel_if_timed_out(&self) -> Option<(Uuid, OwnedToDeviceRequest)> { + pub(crate) fn cancel_if_timed_out(&self) -> Option { if self.is_canceled() || self.is_done() { None } else if self.timed_out() { @@ -408,10 +406,7 @@ impl Sas { self.inner.lock().unwrap().verified_identities() } - pub(crate) fn content_to_request( - &self, - content: AnyToDeviceEventContent, - ) -> (Uuid, OwnedToDeviceRequest) { + pub(crate) fn content_to_request(&self, content: AnyToDeviceEventContent) -> ToDeviceRequest { content_to_request(self.other_user_id(), self.other_device_id(), content) } }