sendToDeviceEncrypted method
Sends an encrypted message
of this eventType
to these deviceKeys
.
Implementation
Future<void> sendToDeviceEncrypted(
List<DeviceKeys> deviceKeys,
String eventType,
Map<String, dynamic> message, {
String? messageId,
bool onlyVerified = false,
}) async {
final encryption = this.encryption;
if (!encryptionEnabled || encryption == null) return;
// Don't send this message to blocked devices, and if specified onlyVerified
// then only send it to verified devices
if (deviceKeys.isNotEmpty) {
deviceKeys.removeWhere((DeviceKeys deviceKeys) =>
deviceKeys.blocked ||
(deviceKeys.userId == userID && deviceKeys.deviceId == deviceID) ||
(onlyVerified && !deviceKeys.verified));
if (deviceKeys.isEmpty) return;
}
// So that we can guarantee order of encrypted to_device messages to be preserved we
// must ensure that we don't attempt to encrypt multiple concurrent to_device messages
// to the same device at the same time.
// A failure to do so can result in edge-cases where encryption and sending order of
// said to_device messages does not match up, resulting in an olm session corruption.
// As we send to multiple devices at the same time, we may only proceed here if the lock for
// *all* of them is freed and lock *all* of them while sending.
try {
await _sendToDeviceEncryptedLock.lock(deviceKeys);
// Send with send-to-device messaging
final data = await encryption.encryptToDeviceMessage(
deviceKeys,
eventType,
message,
);
eventType = EventTypes.Encrypted;
await sendToDevice(
eventType, messageId ?? generateUniqueTransactionId(), data);
} finally {
_sendToDeviceEncryptedLock.unlock(deviceKeys);
}
}