request method

Future<void> request(
  1. Room room,
  2. String sessionId,
  3. String? senderKey, {
  4. bool tryOnlineBackup = true,
  5. bool onlineKeyBackupOnly = false,
})

Request a certain key from another device

Implementation

Future<void> request(
  Room room,
  String sessionId,
  String? senderKey, {
  bool tryOnlineBackup = true,
  bool onlineKeyBackupOnly = false,
}) async {
  Logs().i(
    '[KeyManager] Requesting session key for $sessionId for room ${room.id}',
  );
  if (tryOnlineBackup && await isCached()) {
    // let's first check our online key backup store thingy...
    final hadSessionBefore =
        getInboundGroupSession(room.id, sessionId) != null;
    try {
      await loadSingleKey(room.id, sessionId);
    } catch (err, stacktrace) {
      if (err is MatrixException && err.errcode == 'M_NOT_FOUND') {
        Logs().i(
          '[KeyManager] Key not in online key backup, requesting it from other devices...',
        );
      } else {
        Logs().e(
          '[KeyManager] Failed to access online key backup',
          err,
          stacktrace,
        );
      }
    }

    final storedSession = getInboundGroupSession(room.id, sessionId);
    // We loaded *something* from backup we didn't have before — peers are
    // unlikely to do better, so don't spam to-device requests.
    final loadedFreshFromBackup = !hadSessionBefore && storedSession != null;
    // We have the session from its very first index; peers literally cannot
    // give us anything better.
    final hasFullSession =
        storedSession?.inboundGroupSession?.firstKnownIndex == 0;
    if (loadedFreshFromBackup || hasFullSession) {
      return;
    }
  }
  if (onlineKeyBackupOnly) {
    return; // we only want to do the online key backup
  }
  try {
    // while we just send the to-device event to '*', we still need to save the
    // devices themself to know where to send the cancel to after receiving a reply
    final devices = await room.getUserDeviceKeys();
    final requestId = client.generateUniqueTransactionId();
    final request = KeyManagerKeyShareRequest(
      requestId: requestId,
      devices: devices,
      room: room,
      sessionId: sessionId,
    );
    final userList = await room.requestParticipants();
    await client.sendToDevicesOfUserIds(
      userList.map<String>((u) => u.id).toSet(),
      EventTypes.RoomKeyRequest,
      {
        'action': 'request',
        'body': {
          'algorithm': AlgorithmTypes.megolmV1AesSha2,
          'room_id': room.id,
          'session_id': sessionId,
          'sender_key': ?senderKey,
        },
        'request_id': requestId,
        'requesting_device_id': client.deviceID,
      },
    );
    outgoingShareRequests[request.requestId] = request;
  } catch (e, s) {
    Logs().e('[Key Manager] Sending key verification request failed', e, s);
  }
}