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 97532ada..9ecf24ca 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,8 @@ use matrix_sdk_common::{ #[cfg(feature = "encryption")] use matrix_sdk_crypto::{ store::{CryptoStore, CryptoStoreError}, - Device, IncomingResponse, OlmError, OlmMachine, OutgoingRequest, Sas, UserDevices, + Device, IncomingResponse, OlmError, OlmMachine, OutgoingRequest, Sas, ToDeviceRequest, + UserDevices, }; use zeroize::Zeroizing; @@ -1304,7 +1304,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 c1002046..9ba33445 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::{ store::CryptoStoreError, Device, IncomingResponse, LocalTrust, OutgoingRequest, - OutgoingRequests, ReadOnlyDevice, Sas, UserDevices, + OutgoingRequests, ReadOnlyDevice, Sas, ToDeviceRequest, UserDevices, }; #[cfg(feature = "messages")] diff --git a/matrix_sdk_crypto/src/identities/device.rs b/matrix_sdk_crypto/src/identities/device.rs index 60b87925..55fe5594 100644 --- a/matrix_sdk_crypto/src/identities/device.rs +++ b/matrix_sdk_crypto/src/identities/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::{ identities::{OwnUserIdentity, UserIdentities}, store::{caches::ReadOnlyUserDevices, Result as StoreResult}, verification::VerificationMachine, - verify_json, Sas, + verify_json, 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 0280d408..1ede88bb 100644 --- a/matrix_sdk_crypto/src/lib.rs +++ b/matrix_sdk_crypto/src/lib.rs @@ -42,7 +42,7 @@ pub use identities::{ pub use machine::OlmMachine; pub(crate) use olm::Account; pub use olm::EncryptionSettings; -pub use requests::{IncomingResponse, OutgoingRequest, OutgoingRequests}; +pub use requests::{IncomingResponse, OutgoingRequest, OutgoingRequests, ToDeviceRequest}; pub use verification::Sas; use error::SignatureError; diff --git a/matrix_sdk_crypto/src/machine.rs b/matrix_sdk_crypto/src/machine.rs index 363c920c..6a06acbe 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::{ @@ -62,7 +60,7 @@ use super::{ Account, EncryptionSettings, GroupSessionKey, IdentityKeys, InboundGroupSession, OlmMessage, OutboundGroupSession, }, - requests::{IncomingResponse, OutgoingRequest}, + requests::{IncomingResponse, OutgoingRequest, ToDeviceRequest}, store::{CryptoStore, MemoryStore, Result as StoreResult}, verification::{Sas, VerificationMachine}, }; @@ -1125,7 +1123,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(); @@ -1179,9 +1177,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, }); } @@ -1551,14 +1549,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, @@ -1608,7 +1603,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 65050ff2..9dbaca6c 100644 --- a/matrix_sdk_crypto/src/verification/machine.rs +++ b/matrix_sdk_crypto/src/verification/machine.rs @@ -19,7 +19,6 @@ 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, @@ -27,7 +26,7 @@ use matrix_sdk_common::{ use super::sas::{content_to_request, Sas}; use crate::{ - requests::OutgoingRequest, + requests::{OutgoingRequest, ToDeviceRequest}, store::{CryptoStore, CryptoStoreError}, Account, ReadOnlyDevice, }; @@ -53,7 +52,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( @@ -63,7 +62,7 @@ impl VerificationMachine { identity, ); - let (_, request) = content_to_request( + let request = content_to_request( device.user_id(), device.device_id(), AnyToDeviceEventContent::KeyVerificationStart(content), @@ -86,7 +85,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, @@ -121,10 +121,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()), }, ); } @@ -197,10 +197,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 848d37ef..d7abf88d 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, @@ -32,7 +30,7 @@ use matrix_sdk_common::{ use crate::{ identities::{ReadOnlyDevice, UserIdentities}, - Account, + Account, ToDeviceRequest, }; #[derive(Clone, Debug)] @@ -467,7 +465,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(); @@ -486,16 +484,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 1be3a236..61724ed5 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,13 +30,12 @@ use matrix_sdk_common::{ AnyToDeviceEvent, AnyToDeviceEventContent, ToDeviceEvent, }, identifiers::{DeviceId, UserId}, - uuid::Uuid, }; use crate::{ identities::{LocalTrust, ReadOnlyDevice, UserIdentities}, store::{CryptoStore, CryptoStoreError}, - Account, + Account, ToDeviceRequest, }; pub use helpers::content_to_request; @@ -167,10 +165,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) }) } @@ -181,7 +179,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(); @@ -196,7 +194,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?; } @@ -204,7 +202,7 @@ impl Sas { Ok(content.map(|c| { let content = AnyToDeviceEventContent::KeyVerificationMac(c); - self.content_to_request(content).1 + self.content_to_request(content) })) } @@ -329,7 +327,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); @@ -338,7 +336,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() { @@ -409,10 +407,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) } }