@@ -26,7 +26,7 @@ use matrix_sdk_common::{
26
26
deserialized_responses:: WithheldCode , executor:: spawn, locks:: RwLock as StdRwLock ,
27
27
} ;
28
28
use ruma:: {
29
- events:: { AnyMessageLikeEventContent , ToDeviceEventType } ,
29
+ events:: { AnyMessageLikeEventContent , AnyToDeviceEventContent , ToDeviceEventType } ,
30
30
serde:: Raw ,
31
31
to_device:: DeviceIdOrAllDevices ,
32
32
OwnedDeviceId , OwnedRoomId , OwnedTransactionId , OwnedUserId , RoomId , TransactionId , UserId ,
@@ -270,10 +270,8 @@ impl GroupSessionManager {
270
270
maybe_encrypted_room_key : MaybeEncryptedRoomKey ,
271
271
}
272
272
273
- let mut messages = BTreeMap :: new ( ) ;
274
- let mut changed_sessions = Vec :: new ( ) ;
273
+ let mut result_builder = EncryptForDevicesResultBuilder :: default ( ) ;
275
274
let mut share_infos = BTreeMap :: new ( ) ;
276
- let mut withheld_devices = Vec :: new ( ) ;
277
275
278
276
// XXX is there a way to do this that doesn't involve cloning the
279
277
// `Arc<CryptoStoreWrapper>` for each device?
@@ -297,48 +295,22 @@ impl GroupSessionManager {
297
295
298
296
match result. maybe_encrypted_room_key {
299
297
MaybeEncryptedRoomKey :: Encrypted { used_session, share_info, message } => {
300
- changed_sessions . push ( used_session) ;
298
+ result_builder . on_successful_encryption ( & result . device , used_session, message ) ;
301
299
302
300
let user_id = result. device . user_id ( ) . to_owned ( ) ;
303
301
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
-
310
302
share_infos
311
303
. entry ( user_id)
312
304
. or_insert_with ( BTreeMap :: new)
313
305
. insert ( device_id, share_info) ;
314
306
}
315
- MaybeEncryptedRoomKey :: Withheld { code } => {
316
- withheld_devices . push ( ( result. device , code ) ) ;
307
+ MaybeEncryptedRoomKey :: Withheld { .. } => {
308
+ result_builder . on_missing_session ( result. device ) ;
317
309
}
318
310
}
319
311
}
320
312
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) )
342
314
}
343
315
344
316
/// Given a list of user and an outbound session, return the list of users
@@ -791,6 +763,73 @@ struct EncryptForDevicesResult {
791
763
updated_olm_sessions : Vec < Session > ,
792
764
}
793
765
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
+
794
833
#[ cfg( test) ]
795
834
mod tests {
796
835
use std:: {
0 commit comments