fix: Don't re-play m.dummy to_device events

If both ends had m.dummy events queued as last messages an an olm
session corrupted, then the clients landed in an infinite game of
ping-pong. It was so stable, that the clients could have won the
ping-pong world championships!
This commit is contained in:
Sorunome 2021-09-21 09:58:11 +02:00
parent 7a3553839c
commit b41c7b1bc6
No known key found for this signature in database
GPG Key ID: B19471D07FC9BE9C
2 changed files with 32 additions and 3 deletions

View File

@ -667,9 +667,14 @@ class OlmManager {
return;
}
final lastSentMessage = json.decode(lastSentMessageRes.first);
// okay, time to send the message!
await client.sendToDeviceEncrypted(
[device], lastSentMessage['type'], lastSentMessage['content']);
// We do *not* want to re-play m.dummy events, as they hold no value except of saying
// what olm session is the most recent one. In fact, if we *do* replay them, then
// we can easily land in an infinite ping-pong trap!
if (lastSentMessage['type'] != EventTypes.Dummy) {
// okay, time to send the message!
await client.sendToDeviceEncrypted(
[device], lastSentMessage['type'], lastSentMessage['content']);
}
}
}

View File

@ -234,6 +234,30 @@ void main() {
FakeMatrixApi.calledEndpoints.keys.any(
(k) => k.startsWith('/client/r0/sendToDevice/m.room.encrypted')),
false);
// don't replay if the last event is m.dummy itself
FakeMatrixApi.calledEndpoints.clear();
await client.database.setLastSentMessageUserDeviceKey(
json.encode({
'type': 'm.dummy',
'content': {},
}),
client.id,
userId,
deviceId);
event = ToDeviceEvent(
sender: userId,
type: 'm.dummy',
content: {},
encryptedContent: {
'sender_key': senderKey,
},
);
await client.encryption.olmManager.handleToDeviceEvent(event);
expect(
FakeMatrixApi.calledEndpoints.keys.any(
(k) => k.startsWith('/client/r0/sendToDevice/m.room.encrypted')),
false);
});
test('dispose client', () async {