Skip to content

Commit c36d512

Browse files
committed
be conservative and take also potentially pending to-device requests into account
1 parent 33bdfca commit c36d512

File tree

2 files changed

+37
-10
lines changed

2 files changed

+37
-10
lines changed

crates/matrix-sdk-crypto/src/olm/group_sessions/outbound.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ pub struct OutboundGroupSession {
160160
pub(crate) shared_with_set:
161161
Arc<StdRwLock<BTreeMap<OwnedUserId, BTreeMap<OwnedDeviceId, ShareInfo>>>>,
162162
#[allow(clippy::type_complexity)]
163-
to_share_with_set:
163+
pub(crate) to_share_with_set:
164164
Arc<StdRwLock<BTreeMap<OwnedTransactionId, (Arc<ToDeviceRequest>, ShareInfoSet)>>>,
165165
}
166166

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

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -427,22 +427,49 @@ fn is_session_overshared_for_user(
427427
let recipient_device_ids: BTreeSet<&DeviceId> =
428428
recipient_devices.iter().map(|d| d.device_id()).collect();
429429

430+
let mut shared: Vec<&DeviceId> = Vec::new();
431+
432+
// This duplicates a conservative subset of the logic in OutbundGroupSession::is_shared_with,
433+
// because we don't have corresponding DeviceData at hand
434+
fn is_actually_shared(info: &ShareInfo) -> bool {
435+
match info {
436+
ShareInfo::Shared(_) => true,
437+
ShareInfo::Withheld(_) => false,
438+
}
439+
}
440+
441+
// Collect the devices that have definitely received the session already
430442
let guard = outbound_session.shared_with_set.read();
443+
if let Some(for_user) = guard.get(user_id) {
444+
shared.extend(for_user.iter().filter_map(|(d, info)| if is_actually_shared(info) {
445+
Some(AsRef::<DeviceId>::as_ref(d))
446+
} else {
447+
None
448+
}));
449+
}
431450

432-
let Some(shared) = guard.get(user_id) else {
451+
// To be conservative, also collect the devices that would still receive the session
452+
// from a pending to-device request if we don't rotate beforehand
453+
let guard = outbound_session.to_share_with_set.read();
454+
for (_txid, share_infos) in guard.values() {
455+
if let Some(for_user) = share_infos.get(user_id) {
456+
shared.extend(for_user.iter().filter_map(|(d, info)| if is_actually_shared(info) {
457+
Some(AsRef::<DeviceId>::as_ref(d))
458+
} else {
459+
None
460+
}));
461+
}
462+
}
463+
464+
if shared.is_empty() {
433465
return false;
434-
};
466+
}
435467

436-
// Devices that received this session
437-
let shared: BTreeSet<&DeviceId> = shared
438-
.iter()
439-
.filter(|(_, info)| matches!(info, ShareInfo::Shared(_)))
440-
.map(|(d, _)| d.as_ref())
441-
.collect();
468+
let shared: BTreeSet<&DeviceId> = shared.into_iter().collect();
442469

443470
// The set difference between
444471
//
445-
// 1. Devices that had previously received the session, and
472+
// 1. Devices that had previously received (or are queued to receive) the session, and
446473
// 2. Devices that would now receive the session
447474
//
448475
// Represents newly deleted or blacklisted devices. If this

0 commit comments

Comments
 (0)