setInboundGroupSession method

Future<void> setInboundGroupSession(
  1. String roomId,
  2. String sessionId,
  3. String senderKey,
  4. Map<String, dynamic> content, {
  5. bool forwarded = false,
  6. Map<String, String>? senderClaimedKeys,
  7. bool uploaded = false,
  8. 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();
}