setInboundGroupSession method
Future<void>
setInboundGroupSession(
- String roomId,
- String sessionId,
- String senderKey,
- Map<String, dynamic> content, {
- bool forwarded = false,
- Map<String, String>? senderClaimedKeys,
- bool uploaded = false,
- Map<String, Map<String, int>>? allowedAtIndex,
})
Implementation
Future<void> setInboundGroupSession(
String roomId,
String sessionId,
String senderKey,
Map<String, dynamic> content, {
bool forwarded = false,
Map<String, String>? senderClaimedKeys,
bool uploaded = false,
Map<String, Map<String, int>>? allowedAtIndex,
}) async {
final senderClaimedKeys_ = senderClaimedKeys ?? <String, String>{};
final allowedAtIndex_ = allowedAtIndex ?? <String, Map<String, int>>{};
final userId = client.userID;
if (userId == null) return Future.value();
if (!senderClaimedKeys_.containsKey('ed25519')) {
final device = client.getUserDeviceKeysByCurve25519Key(senderKey);
if (device != null && device.ed25519Key != null) {
senderClaimedKeys_['ed25519'] = device.ed25519Key!;
}
}
final oldSession = getInboundGroupSession(
roomId,
sessionId,
);
if (content['algorithm'] != AlgorithmTypes.megolmV1AesSha2) {
return;
}
late olm.InboundGroupSession inboundGroupSession;
try {
inboundGroupSession = olm.InboundGroupSession();
if (forwarded) {
inboundGroupSession.import_session(content['session_key']);
} else {
inboundGroupSession.create(content['session_key']);
}
} catch (e, s) {
inboundGroupSession.free();
Logs().e('[LibOlm] Could not create new InboundGroupSession', e, s);
return Future.value();
}
final newSession = SessionKey(
content: content,
inboundGroupSession: inboundGroupSession,
indexes: {},
roomId: roomId,
sessionId: sessionId,
key: userId,
senderKey: senderKey,
senderClaimedKeys: senderClaimedKeys_,
allowedAtIndex: allowedAtIndex_,
);
final oldFirstIndex =
oldSession?.inboundGroupSession?.first_known_index() ?? 0;
final newFirstIndex = newSession.inboundGroupSession!.first_known_index();
if (oldSession == null ||
newFirstIndex < oldFirstIndex ||
(oldFirstIndex == newFirstIndex &&
newSession.forwardingCurve25519KeyChain.length <
oldSession.forwardingCurve25519KeyChain.length)) {
// use new session
oldSession?.dispose();
} else {
// we are gonna keep our old session
newSession.dispose();
return;
}
final roomInboundGroupSessions =
_inboundGroupSessions[roomId] ??= <String, SessionKey>{};
roomInboundGroupSessions[sessionId] = newSession;
if (!client.isLogged() || client.encryption == null) {
return;
}
final storeFuture = client.database
?.storeInboundGroupSession(
roomId,
sessionId,
inboundGroupSession.pickle(userId),
json.encode(content),
json.encode({}),
json.encode(allowedAtIndex_),
senderKey,
json.encode(senderClaimedKeys_),
)
.then((_) async {
if (!client.isLogged() || client.encryption == null) {
return;
}
if (uploaded) {
await client.database
?.markInboundGroupSessionAsUploaded(roomId, sessionId);
}
});
final room = client.getRoomById(roomId);
if (room != null) {
// attempt to decrypt the last event
final event = room.lastEvent;
if (event != null &&
event.type == EventTypes.Encrypted &&
event.content['session_id'] == sessionId) {
final decrypted = encryption.decryptRoomEventSync(roomId, event);
if (decrypted.type != EventTypes.Encrypted) {
// Update the last event in memory first
room.lastEvent = decrypted;
// To persist it in database and trigger UI updates:
await client.database?.transaction(() async {
await client.handleSync(
SyncUpdate(
nextBatch: '',
rooms: switch (room.membership) {
Membership.join =>
RoomsUpdate(join: {room.id: JoinedRoomUpdate()}),
Membership.ban ||
Membership.leave =>
RoomsUpdate(leave: {room.id: LeftRoomUpdate()}),
Membership.invite =>
RoomsUpdate(invite: {room.id: InvitedRoomUpdate()}),
Membership.knock =>
RoomsUpdate(knock: {room.id: KnockRoomUpdate()}),
},
),
);
});
}
}
// and finally broadcast the new session
room.onSessionKeyReceived.add(sessionId);
}
return storeFuture ?? Future.value();
}