fix olm session proliferation

This commit is contained in:
Valere 2022-07-13 11:47:48 +02:00
parent c7b54b8d3d
commit e8bd7ea967
3 changed files with 30 additions and 14 deletions

1
changelog.d/6534.bugfix Normal file
View file

@ -0,0 +1 @@
Unwedging could cause the SDK to force creating a new olm session every hour

View file

@ -60,7 +60,6 @@ import kotlin.coroutines.resume
*/ */
@RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.JVM) @FixMethodOrder(MethodSorters.JVM)
@Ignore
class UnwedgingTest : InstrumentedTest { class UnwedgingTest : InstrumentedTest {
private lateinit var messagesReceivedByBob: List<TimelineEvent> private lateinit var messagesReceivedByBob: List<TimelineEvent>

View file

@ -18,6 +18,8 @@ package org.matrix.android.sdk.internal.crypto
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
@ -68,6 +70,7 @@ internal class EventDecryptor @Inject constructor(
val senderKey: String? val senderKey: String?
) )
private val wedgedMutex = Mutex()
private val wedgedDevices = mutableListOf<WedgedDeviceInfo>() private val wedgedDevices = mutableListOf<WedgedDeviceInfo>()
/** /**
@ -151,13 +154,15 @@ internal class EventDecryptor @Inject constructor(
} }
} }
private fun markOlmSessionForUnwedging(senderId: String, senderKey: String) { private suspend fun markOlmSessionForUnwedging(senderId: String, senderKey: String) {
wedgedMutex.withLock {
val info = WedgedDeviceInfo(senderId, senderKey) val info = WedgedDeviceInfo(senderId, senderKey)
if (!wedgedDevices.contains(info)) { if (!wedgedDevices.contains(info)) {
Timber.tag(loggerTag.value).d("Marking device from $senderId key:$senderKey as wedged") Timber.tag(loggerTag.value).d("Marking device from $senderId key:$senderKey as wedged")
wedgedDevices.add(info) wedgedDevices.add(info)
} }
} }
}
// coroutineDispatchers.crypto scope // coroutineDispatchers.crypto scope
suspend fun unwedgeDevicesIfNeeded() { suspend fun unwedgeDevicesIfNeeded() {
@ -167,7 +172,8 @@ internal class EventDecryptor @Inject constructor(
Timber.tag(loggerTag.value).v("Unwedging: ${wedgedDevices.size} are wedged") Timber.tag(loggerTag.value).v("Unwedging: ${wedgedDevices.size} are wedged")
// get the one that should be retried according to rate limit // get the one that should be retried according to rate limit
val now = clock.epochMillis() val now = clock.epochMillis()
val toUnwedge = wedgedDevices.filter { val toUnwedge = wedgedMutex.withLock {
wedgedDevices.filter {
val lastForcedDate = lastNewSessionForcedDates[it] ?: 0 val lastForcedDate = lastNewSessionForcedDates[it] ?: 0
if (now - lastForcedDate < DefaultCryptoService.CRYPTO_MIN_FORCE_SESSION_PERIOD_MILLIS) { if (now - lastForcedDate < DefaultCryptoService.CRYPTO_MIN_FORCE_SESSION_PERIOD_MILLIS) {
Timber.tag(loggerTag.value).d("Unwedging, New session for $it already forced with device at $lastForcedDate") Timber.tag(loggerTag.value).d("Unwedging, New session for $it already forced with device at $lastForcedDate")
@ -177,6 +183,7 @@ internal class EventDecryptor @Inject constructor(
lastNewSessionForcedDates[it] = now lastNewSessionForcedDates[it] = now
true true
} }
}
if (toUnwedge.isEmpty()) { if (toUnwedge.isEmpty()) {
Timber.tag(loggerTag.value).v("Nothing to unwedge") Timber.tag(loggerTag.value).v("Nothing to unwedge")
@ -230,6 +237,15 @@ internal class EventDecryptor @Inject constructor(
withContext(coroutineDispatchers.io) { withContext(coroutineDispatchers.io) {
sendToDeviceTask.executeRetry(sendToDeviceParams, remainingRetry = SEND_TO_DEVICE_RETRY_COUNT) sendToDeviceTask.executeRetry(sendToDeviceParams, remainingRetry = SEND_TO_DEVICE_RETRY_COUNT)
} }
deviceList.values.flatten().forEach { deviceInfo ->
wedgedMutex.withLock {
wedgedDevices.removeAll {
it.senderKey == deviceInfo.identityKey() &&
it.userId == deviceInfo.userId
}
}
}
} catch (failure: Throwable) { } catch (failure: Throwable) {
deviceList.flatMap { it.value }.joinToString { it.shortDebugString() }.let { deviceList.flatMap { it.value }.joinToString { it.shortDebugString() }.let {
Timber.tag(loggerTag.value).e(failure, "## Failed to unwedge devices: $it}") Timber.tag(loggerTag.value).e(failure, "## Failed to unwedge devices: $it}")