Skip to content

Commit da14cef

Browse files
committed
crypto: Factor out a EncryptForDevicesResultBuilder
We want to re-use all this logic, so putting it in a separate type will help. Plus I think it's cleaner.
1 parent f1ea3e6 commit da14cef

File tree

1 file changed

+73
-34
lines changed
  • crates/matrix-sdk-crypto/src/session_manager/group_sessions

1 file changed

+73
-34
lines changed

crates/matrix-sdk-crypto/src/session_manager/group_sessions/mod.rs

Lines changed: 73 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use matrix_sdk_common::{
2626
deserialized_responses::WithheldCode, executor::spawn, locks::RwLock as StdRwLock,
2727
};
2828
use ruma::{
29-
events::{AnyMessageLikeEventContent, ToDeviceEventType},
29+
events::{AnyMessageLikeEventContent, AnyToDeviceEventContent, ToDeviceEventType},
3030
serde::Raw,
3131
to_device::DeviceIdOrAllDevices,
3232
OwnedDeviceId, OwnedRoomId, OwnedTransactionId, OwnedUserId, RoomId, TransactionId, UserId,
@@ -270,10 +270,8 @@ impl GroupSessionManager {
270270
maybe_encrypted_room_key: MaybeEncryptedRoomKey,
271271
}
272272

273-
let mut messages = BTreeMap::new();
274-
let mut changed_sessions = Vec::new();
273+
let mut result_builder = EncryptForDevicesResultBuilder::default();
275274
let mut share_infos = BTreeMap::new();
276-
let mut withheld_devices = Vec::new();
277275

278276
// XXX is there a way to do this that doesn't involve cloning the
279277
// `Arc<CryptoStoreWrapper>` for each device?
@@ -297,48 +295,22 @@ impl GroupSessionManager {
297295

298296
match result.maybe_encrypted_room_key {
299297
MaybeEncryptedRoomKey::Encrypted { used_session, share_info, message } => {
300-
changed_sessions.push(used_session);
298+
result_builder.on_successful_encryption(&result.device, used_session, message);
301299

302300
let user_id = result.device.user_id().to_owned();
303301
let device_id = result.device.device_id().to_owned();
304-
305-
messages
306-
.entry(user_id.to_owned())
307-
.or_insert_with(BTreeMap::new)
308-
.insert(DeviceIdOrAllDevices::DeviceId(device_id.to_owned()), message);
309-
310302
share_infos
311303
.entry(user_id)
312304
.or_insert_with(BTreeMap::new)
313305
.insert(device_id, share_info);
314306
}
315-
MaybeEncryptedRoomKey::Withheld { code } => {
316-
withheld_devices.push((result.device, code));
307+
MaybeEncryptedRoomKey::Withheld { .. } => {
308+
result_builder.on_missing_session(result.device);
317309
}
318310
}
319311
}
320312

321-
let mut encrypt_for_devices_result = EncryptForDevicesResult {
322-
to_device_request: None,
323-
updated_olm_sessions: changed_sessions,
324-
no_olm_devices: withheld_devices,
325-
};
326-
327-
if !messages.is_empty() {
328-
let request = ToDeviceRequest {
329-
event_type: ToDeviceEventType::RoomEncrypted,
330-
txn_id: TransactionId::new(),
331-
messages,
332-
};
333-
trace!(
334-
recipient_count = request.message_count(),
335-
transaction_id = ?request.txn_id,
336-
"Created a to-device request carrying room keys",
337-
);
338-
encrypt_for_devices_result.to_device_request = Some(request);
339-
};
340-
341-
Ok((encrypt_for_devices_result, share_infos))
313+
Ok((result_builder.into_result(), share_infos))
342314
}
343315

344316
/// Given a list of user and an outbound session, return the list of users
@@ -791,6 +763,73 @@ struct EncryptForDevicesResult {
791763
updated_olm_sessions: Vec<Session>,
792764
}
793765

766+
/// A helper for building [`EncryptForDevicesResult`]
767+
#[derive(Debug, Default)]
768+
struct EncryptForDevicesResultBuilder {
769+
/// The payloads of the to-device messages
770+
messages: BTreeMap<OwnedUserId, BTreeMap<DeviceIdOrAllDevices, Raw<AnyToDeviceEventContent>>>,
771+
772+
/// The devices which lack an Olm session and therefore need a withheld code
773+
no_olm_devices: Vec<(DeviceData, WithheldCode)>,
774+
775+
/// The Olm sessions which were used to encrypt the requests and now need
776+
/// persisting to the store.
777+
updated_olm_sessions: Vec<Session>,
778+
}
779+
780+
impl EncryptForDevicesResultBuilder {
781+
/// Record a successful encryption. The encrypted message is added to the
782+
/// list to be sent, and the olm session is added to the list of those
783+
/// that have been modified.
784+
pub fn on_successful_encryption(
785+
&mut self,
786+
device: &DeviceData,
787+
used_session: Session,
788+
message: Raw<AnyToDeviceEventContent>,
789+
) {
790+
self.updated_olm_sessions.push(used_session);
791+
792+
self.messages
793+
.entry(device.user_id().to_owned())
794+
.or_default()
795+
.insert(DeviceIdOrAllDevices::DeviceId(device.device_id().to_owned()), message);
796+
}
797+
798+
/// Record a device which didn't have an active Olm session.
799+
pub fn on_missing_session(&mut self, device: DeviceData) {
800+
self.no_olm_devices.push((device, WithheldCode::NoOlm));
801+
}
802+
803+
/// Transform the accumulated results into an [`EncryptForDevicesResult`],
804+
/// wrapping the messages, if any, into a `ToDeviceRequest`.
805+
pub fn into_result(self) -> EncryptForDevicesResult {
806+
let EncryptForDevicesResultBuilder { updated_olm_sessions, no_olm_devices, messages } =
807+
self;
808+
809+
let mut encrypt_for_devices_result = EncryptForDevicesResult {
810+
to_device_request: None,
811+
updated_olm_sessions,
812+
no_olm_devices,
813+
};
814+
815+
if !messages.is_empty() {
816+
let request = ToDeviceRequest {
817+
event_type: ToDeviceEventType::RoomEncrypted,
818+
txn_id: TransactionId::new(),
819+
messages,
820+
};
821+
trace!(
822+
recipient_count = request.message_count(),
823+
transaction_id = ?request.txn_id,
824+
"Created a to-device request carrying room keys",
825+
);
826+
encrypt_for_devices_result.to_device_request = Some(request);
827+
};
828+
829+
encrypt_for_devices_result
830+
}
831+
}
832+
794833
#[cfg(test)]
795834
mod tests {
796835
use std::{

0 commit comments

Comments
 (0)