Merge pull request #1824 from famedly/td/fireNewPifJoined

preShareKey improvements
This commit is contained in:
td 2024-05-22 22:21:42 +05:30 committed by GitHub
commit 763bb0ba00
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 63 additions and 36 deletions

View File

@ -73,6 +73,8 @@ abstract class CallBackend {
List<CallParticipant> anyLeft, List<CallParticipant> anyLeft,
); );
Future<void> preShareKey(GroupCallSession groupCall);
Future<void> requestEncrytionKey( Future<void> requestEncrytionKey(
GroupCallSession groupCall, GroupCallSession groupCall,
List<CallParticipant> remoteParticipants, List<CallParticipant> remoteParticipants,

View File

@ -52,9 +52,10 @@ class LiveKitBackend extends CallBackend {
return newIndex; return newIndex;
} }
@override
Future<void> preShareKey(GroupCallSession groupCall) async { Future<void> preShareKey(GroupCallSession groupCall) async {
await groupCall.onMemberStateChanged(); await groupCall.onMemberStateChanged();
await _makeNewSenderKey(groupCall, false); await _changeEncryptionKey(groupCall, groupCall.participants, false);
} }
/// makes a new e2ee key for local user and sets it with a delay if specified /// makes a new e2ee key for local user and sets it with a delay if specified
@ -120,6 +121,19 @@ class LiveKitBackend extends CallBackend {
); );
} }
Future<void> _changeEncryptionKey(
GroupCallSession groupCall,
List<CallParticipant> anyJoined,
bool delayBeforeUsingKeyOurself,
) async {
if (!e2eeEnabled) return;
if (groupCall.voip.enableSFUE2EEKeyRatcheting) {
await _ratchetLocalParticipantKey(groupCall, anyJoined);
} else {
await _makeNewSenderKey(groupCall, delayBeforeUsingKeyOurself);
}
}
/// sets incoming keys and also sends the key if it was for the local user /// sets incoming keys and also sends the key if it was for the local user
/// if sendTo is null, its sent to all _participants, see `_sendEncryptionKeysEvent` /// if sendTo is null, its sent to all _participants, see `_sendEncryptionKeysEvent`
Future<void> _setEncryptionKey( Future<void> _setEncryptionKey(
@ -180,8 +194,6 @@ class LiveKitBackend extends CallBackend {
int keyIndex, { int keyIndex, {
List<CallParticipant>? sendTo, List<CallParticipant>? sendTo,
}) async { }) async {
Logs().i('Sending encryption keys event');
final myKeys = _getKeysForParticipant(groupCall.localParticipant!); final myKeys = _getKeysForParticipant(groupCall.localParticipant!);
final myLatestKey = myKeys?[keyIndex]; final myLatestKey = myKeys?[keyIndex];
@ -235,6 +247,7 @@ class LiveKitBackend extends CallBackend {
Map<String, Object> data, Map<String, Object> data,
String eventType, String eventType,
) async { ) async {
if (remoteParticipants.isEmpty) return;
Logs().v( Logs().v(
'[VOIP] _sendToDeviceEvent: sending ${data.toString()} to ${remoteParticipants.map((e) => e.id)} '); '[VOIP] _sendToDeviceEvent: sending ${data.toString()} to ${remoteParticipants.map((e) => e.id)} ');
final txid = final txid =
@ -392,14 +405,8 @@ class LiveKitBackend extends CallBackend {
Future<void> onNewParticipant( Future<void> onNewParticipant(
GroupCallSession groupCall, GroupCallSession groupCall,
List<CallParticipant> anyJoined, List<CallParticipant> anyJoined,
) async { ) =>
if (!e2eeEnabled) return; _changeEncryptionKey(groupCall, anyJoined, true);
if (groupCall.voip.enableSFUE2EEKeyRatcheting) {
await _ratchetLocalParticipantKey(groupCall, anyJoined);
} else {
await _makeNewSenderKey(groupCall, true);
}
}
@override @override
Future<void> onLeftParticipant( Future<void> onLeftParticipant(

View File

@ -877,4 +877,9 @@ class MeshBackend extends CallBackend {
List<CallParticipant> remoteParticipants) async { List<CallParticipant> remoteParticipants) async {
return; return;
} }
@override
Future<void> preShareKey(GroupCallSession groupCall) async {
return;
}
} }

View File

@ -48,7 +48,7 @@ class GroupCallSession {
CallParticipant? get localParticipant => voip.localParticipant; CallParticipant? get localParticipant => voip.localParticipant;
List<CallParticipant> get participants => List.unmodifiable(_participants); List<CallParticipant> get participants => List.unmodifiable(_participants);
final List<CallParticipant> _participants = []; final Set<CallParticipant> _participants = {};
String groupCallId; String groupCallId;
@ -218,7 +218,7 @@ class GroupCallSession {
'[VOIP] Ignored ${mem.userId}\'s mem event ${mem.toJson()} while updating _participants list for callId: $groupCallId, expiry status: ${mem.isExpired}'); '[VOIP] Ignored ${mem.userId}\'s mem event ${mem.toJson()} while updating _participants list for callId: $groupCallId, expiry status: ${mem.isExpired}');
} }
final List<CallParticipant> newP = []; final Set<CallParticipant> newP = {};
for (final mem in memsForCurrentGroupCall) { for (final mem in memsForCurrentGroupCall) {
final rp = CallParticipant( final rp = CallParticipant(
@ -239,23 +239,29 @@ class GroupCallSession {
await backend.setupP2PCallWithNewMember(this, rp, mem); await backend.setupP2PCallWithNewMember(this, rp, mem);
} }
final newPcopy = List<CallParticipant>.from(newP); final newPcopy = Set<CallParticipant>.from(newP);
final oldPcopy = List<CallParticipant>.from(_participants); final oldPcopy = Set<CallParticipant>.from(_participants);
final anyJoined = newPcopy.where((element) => !oldPcopy.contains(element)); final anyJoined = newPcopy.difference(oldPcopy);
final anyLeft = oldPcopy.where((element) => !newPcopy.contains(element)); final anyLeft = oldPcopy.difference(newPcopy);
if (anyJoined.isNotEmpty || anyLeft.isNotEmpty) { if (anyJoined.isNotEmpty || anyLeft.isNotEmpty) {
if (anyJoined.isNotEmpty) { if (anyJoined.isNotEmpty) {
Logs().d('anyJoined: ${anyJoined.map((e) => e.id).toString()}'); final nonLocalAnyJoined = anyJoined..remove(localParticipant);
if (nonLocalAnyJoined.isNotEmpty && state == GroupCallState.entered) {
Logs().v(
'nonLocalAnyJoined: ${nonLocalAnyJoined.map((e) => e.id).toString()} roomId: ${room.id} groupCallId: $groupCallId');
await backend.onNewParticipant(this, nonLocalAnyJoined.toList());
}
_participants.addAll(anyJoined); _participants.addAll(anyJoined);
await backend.onNewParticipant(this, anyJoined.toList());
} }
if (anyLeft.isNotEmpty) { if (anyLeft.isNotEmpty) {
Logs().d('anyLeft: ${anyLeft.map((e) => e.id).toString()}'); final nonLocalAnyLeft = anyLeft..remove(localParticipant);
for (final leftp in anyLeft) { if (nonLocalAnyLeft.isNotEmpty && state == GroupCallState.entered) {
_participants.remove(leftp); Logs().v(
'nonLocalAnyLeft: ${nonLocalAnyLeft.map((e) => e.id).toString()} roomId: ${room.id} groupCallId: $groupCallId');
await backend.onLeftParticipant(this, nonLocalAnyLeft.toList());
} }
await backend.onLeftParticipant(this, anyLeft.toList()); _participants.removeAll(anyLeft);
} }
onGroupCallEvent.add(GroupCallStateChange.participantsChanged); onGroupCallEvent.add(GroupCallStateChange.participantsChanged);

View File

@ -756,37 +756,44 @@ class VoIP {
/// [application] normal group call, thrirdroom, etc /// [application] normal group call, thrirdroom, etc
/// ///
/// [scope] room, between specifc users, etc. /// [scope] room, between specifc users, etc.
///
/// [preShareKey] for livekit calls it creates and shares a key with other
/// participants in the call without entering, useful on onboarding screens.
/// does not do anything in mesh calls
Future<GroupCallSession> fetchOrCreateGroupCall( Future<GroupCallSession> fetchOrCreateGroupCall(
String groupCallId, String groupCallId,
Room room, Room room,
CallBackend backend, CallBackend backend,
String? application, String? application,
String? scope, String? scope, {
) async { bool preShareKey = true,
}) async {
if (!room.groupCallsEnabledForEveryone) { if (!room.groupCallsEnabledForEveryone) {
await room.enableGroupCalls(); await room.enableGroupCalls();
} }
final groupCall = getGroupCallById(room.id, groupCallId); if (!room.canJoinGroupCall) {
throw MatrixSDKVoipException(
if (groupCall != null) { 'User ${client.userID}:${client.deviceID} is not allowed to join famedly calls in room ${room.id}, canJoinGroupCall: ${room.canJoinGroupCall}, room.canJoinGroupCall: ${room.groupCallsEnabledForEveryone}',
if (!room.canJoinGroupCall) { );
throw MatrixSDKVoipException(
'User ${client.userID}:${client.deviceID} is not allowed to join famedly calls in room ${room.id}, canJoinGroupCall: ${room.canJoinGroupCall}, room.canJoinGroupCall: ${room.groupCallsEnabledForEveryone}',
);
}
return groupCall;
} }
// The call doesn't exist, but we can create it GroupCallSession? groupCall = getGroupCallById(room.id, groupCallId);
return await _newGroupCall(
groupCall ??= await _newGroupCall(
groupCallId, groupCallId,
room, room,
backend, backend,
application, application,
scope, scope,
); );
if (preShareKey) {
await groupCall.backend.preShareKey(groupCall);
}
return groupCall;
} }
GroupCallSession? getGroupCallById(String roomId, String groupCallId) { GroupCallSession? getGroupCallById(String roomId, String groupCallId) {