Merge pull request #13 from poljar/fga/feature/handle_request_failing

Fga/feature/handle request failing
This commit is contained in:
ganfra 2022-06-13 17:16:14 +02:00 committed by GitHub
commit bda031496a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 138 additions and 100 deletions

View File

@ -24,6 +24,7 @@ import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel
import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
import org.matrix.android.sdk.api.session.crypto.model.UnsignedDeviceInfo import org.matrix.android.sdk.api.session.crypto.model.UnsignedDeviceInfo
import org.matrix.android.sdk.api.session.crypto.verification.CancelCode
import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod
import org.matrix.android.sdk.internal.crypto.network.RequestSender import org.matrix.android.sdk.internal.crypto.network.RequestSender
import org.matrix.android.sdk.internal.crypto.verification.SasVerification import org.matrix.android.sdk.internal.crypto.verification.SasVerification
@ -83,8 +84,13 @@ internal class Device @AssistedInject constructor(
innerMachine.requestVerificationWithDevice(innerDevice.userId, innerDevice.deviceId, stringMethods) innerMachine.requestVerificationWithDevice(innerDevice.userId, innerDevice.deviceId, stringMethods)
} }
return if (result != null) { return if (result != null) {
requestSender.sendVerificationRequest(result.request) try {
verificationRequestFactory.create(result.verification) requestSender.sendVerificationRequest(result.request)
verificationRequestFactory.create(result.verification)
} catch (failure: Throwable) {
innerMachine.cancelVerification(result.verification.otherUserId, result.verification.flowId, CancelCode.UserError.value)
null
}
} else { } else {
null null
} }
@ -104,10 +110,14 @@ internal class Device @AssistedInject constructor(
val result = withContext(coroutineDispatchers.io) { val result = withContext(coroutineDispatchers.io) {
innerMachine.startSasWithDevice(innerDevice.userId, innerDevice.deviceId) innerMachine.startSasWithDevice(innerDevice.userId, innerDevice.deviceId)
} }
return if (result != null) { return if (result != null) {
requestSender.sendVerificationRequest(result.request) try {
sasVerificationFactory.create(result.sas) requestSender.sendVerificationRequest(result.request)
sasVerificationFactory.create(result.sas)
} catch (failure: Throwable) {
innerMachine.cancelVerification(result.sas.otherUserId, result.sas.flowId, CancelCode.UserError.value)
null
}
} else { } else {
null null
} }
@ -140,9 +150,7 @@ internal class Device @AssistedInject constructor(
val request = withContext(coroutineDispatchers.io) { val request = withContext(coroutineDispatchers.io) {
innerMachine.verifyDevice(innerDevice.userId, innerDevice.deviceId) innerMachine.verifyDevice(innerDevice.userId, innerDevice.deviceId)
} }
requestSender.sendSignatureUpload(request) requestSender.sendSignatureUpload(request)
return true return true
} }

View File

@ -241,7 +241,7 @@ internal class SecretShareManager @Inject constructor(
) )
try { try {
withContext(coroutineDispatchers.io) { withContext(coroutineDispatchers.io) {
sendToDeviceTask.executeRetry(params, 3) sendToDeviceTask.execute(params)
} }
Timber.tag(loggerTag.value) Timber.tag(loggerTag.value)
.d("Secret request sent for $secretName to ${cryptoDeviceInfo.shortDebugString()}") .d("Secret request sent for $secretName to ${cryptoDeviceInfo.shortDebugString()}")

View File

@ -33,7 +33,7 @@ internal class DefaultGetKeysBackupLastVersionTask @Inject constructor(
override suspend fun execute(params: Unit): KeysBackupLastVersionResult { override suspend fun execute(params: Unit): KeysBackupLastVersionResult {
return try { return try {
val keysVersionResult = executeRequest(globalErrorReceiver) { val keysVersionResult = executeRequest(globalErrorReceiver, canRetry = true) {
roomKeysApi.getKeysBackupLastVersion() roomKeysApi.getKeysBackupLastVersion()
} }
KeysBackupLastVersionResult.KeysBackup(keysVersionResult) KeysBackupLastVersionResult.KeysBackup(keysVersionResult)

View File

@ -31,7 +31,7 @@ internal class DefaultGetKeysBackupVersionTask @Inject constructor(
) : GetKeysBackupVersionTask { ) : GetKeysBackupVersionTask {
override suspend fun execute(params: String): KeysVersionResult { override suspend fun execute(params: String): KeysVersionResult {
return executeRequest(globalErrorReceiver) { return executeRequest(globalErrorReceiver, canRetry = true) {
roomKeysApi.getKeysBackupVersion(params) roomKeysApi.getKeysBackupVersion(params)
} }
} }

View File

@ -37,7 +37,7 @@ internal class DefaultStoreSessionsDataTask @Inject constructor(
) : StoreSessionsDataTask { ) : StoreSessionsDataTask {
override suspend fun execute(params: StoreSessionsDataTask.Params): BackupKeysResult { override suspend fun execute(params: StoreSessionsDataTask.Params): BackupKeysResult {
return executeRequest(globalErrorReceiver) { return executeRequest(globalErrorReceiver, canRetry = true) {
roomKeysApi.storeSessionsData( roomKeysApi.storeSessionsData(
params.version, params.version,
params.keysBackupData params.keysBackupData

View File

@ -36,7 +36,7 @@ internal class DefaultUpdateKeysBackupVersionTask @Inject constructor(
) : UpdateKeysBackupVersionTask { ) : UpdateKeysBackupVersionTask {
override suspend fun execute(params: UpdateKeysBackupVersionTask.Params) { override suspend fun execute(params: UpdateKeysBackupVersionTask.Params) {
return executeRequest(globalErrorReceiver) { return executeRequest(globalErrorReceiver, canRetry = true) {
roomKeysApi.updateKeysBackupVersion(params.version, params.keysBackupVersionBody) roomKeysApi.updateKeysBackupVersion(params.version, params.keysBackupVersionBody)
} }
} }

View File

@ -59,6 +59,7 @@ import org.matrix.android.sdk.internal.crypto.tasks.UploadKeysTask
import org.matrix.android.sdk.internal.crypto.tasks.UploadSignaturesTask import org.matrix.android.sdk.internal.crypto.tasks.UploadSignaturesTask
import org.matrix.android.sdk.internal.crypto.tasks.UploadSigningKeysTask import org.matrix.android.sdk.internal.crypto.tasks.UploadSigningKeysTask
import org.matrix.android.sdk.internal.di.MoshiProvider import org.matrix.android.sdk.internal.di.MoshiProvider
import org.matrix.android.sdk.internal.network.DEFAULT_REQUEST_RETRY_COUNT
import org.matrix.android.sdk.internal.network.parsing.CheckNumberType import org.matrix.android.sdk.internal.network.parsing.CheckNumberType
import org.matrix.android.sdk.internal.session.room.send.SendResponse import org.matrix.android.sdk.internal.session.room.send.SendResponse
import timber.log.Timber import timber.log.Timber
@ -87,13 +88,10 @@ internal class RequestSender @Inject constructor(
private val getRoomSessionDataTask: GetRoomSessionDataTask, private val getRoomSessionDataTask: GetRoomSessionDataTask,
private val moshi: Moshi, private val moshi: Moshi,
) { ) {
companion object {
const val REQUEST_RETRY_COUNT = 3
}
suspend fun claimKeys(request: Request.KeysClaim): String { suspend fun claimKeys(request: Request.KeysClaim): String {
val claimParams = ClaimOneTimeKeysForUsersDeviceTask.Params(request.oneTimeKeys) val claimParams = ClaimOneTimeKeysForUsersDeviceTask.Params(request.oneTimeKeys)
val response = oneTimeKeysForUsersDeviceTask.executeRetry(claimParams, REQUEST_RETRY_COUNT) val response = oneTimeKeysForUsersDeviceTask.execute(claimParams)
val adapter = MoshiProvider val adapter = MoshiProvider
.providesMoshi() .providesMoshi()
.adapter(KeysClaimResponse::class.java) .adapter(KeysClaimResponse::class.java)
@ -102,7 +100,7 @@ internal class RequestSender @Inject constructor(
suspend fun queryKeys(request: Request.KeysQuery): String { suspend fun queryKeys(request: Request.KeysQuery): String {
val params = DownloadKeysForUsersTask.Params(request.users, null) val params = DownloadKeysForUsersTask.Params(request.users, null)
val response = downloadKeysForUsersTask.executeRetry(params, REQUEST_RETRY_COUNT) val response = downloadKeysForUsersTask.execute(params)
val adapter = moshi.adapter(KeysQueryResponse::class.java) val adapter = moshi.adapter(KeysQueryResponse::class.java)
return adapter.toJson(response)!! return adapter.toJson(response)!!
} }
@ -111,35 +109,40 @@ internal class RequestSender @Inject constructor(
val body = moshi.adapter<JsonDict>(Map::class.java).fromJson(request.body)!! val body = moshi.adapter<JsonDict>(Map::class.java).fromJson(request.body)!!
val params = UploadKeysTask.Params(body) val params = UploadKeysTask.Params(body)
val response = uploadKeysTask.executeRetry(params, REQUEST_RETRY_COUNT) val response = uploadKeysTask.execute(params)
val adapter = moshi.adapter(KeysUploadResponse::class.java) val adapter = moshi.adapter(KeysUploadResponse::class.java)
return adapter.toJson(response)!! return adapter.toJson(response)!!
} }
suspend fun sendVerificationRequest(request: OutgoingVerificationRequest) { suspend fun sendVerificationRequest(request: OutgoingVerificationRequest, retryCount: Int = DEFAULT_REQUEST_RETRY_COUNT) {
when (request) { when (request) {
is OutgoingVerificationRequest.InRoom -> sendRoomMessage(request) is OutgoingVerificationRequest.InRoom -> sendRoomMessage(request, retryCount)
is OutgoingVerificationRequest.ToDevice -> sendToDevice(request) is OutgoingVerificationRequest.ToDevice -> sendToDevice(request, retryCount)
} }
} }
private suspend fun sendRoomMessage(request: OutgoingVerificationRequest.InRoom): SendResponse { private suspend fun sendRoomMessage(request: OutgoingVerificationRequest.InRoom, retryCount: Int): SendResponse {
return sendRoomMessage(request.eventType, request.roomId, request.content, request.requestId) return sendRoomMessage(request.eventType, request.roomId, request.content, request.requestId, retryCount)
} }
suspend fun sendRoomMessage(request: Request.RoomMessage): String { suspend fun sendRoomMessage(request: Request.RoomMessage, retryCount: Int = DEFAULT_REQUEST_RETRY_COUNT): String {
val sendResponse = sendRoomMessage(request.eventType, request.roomId, request.content, request.requestId) val sendResponse = sendRoomMessage(request.eventType, request.roomId, request.content, request.requestId, retryCount)
val responseAdapter = moshi.adapter(SendResponse::class.java) val responseAdapter = moshi.adapter(SendResponse::class.java)
return responseAdapter.toJson(sendResponse) return responseAdapter.toJson(sendResponse)
} }
suspend fun sendRoomMessage(eventType: String, roomId: String, content: String, transactionId: String): SendResponse { suspend fun sendRoomMessage(eventType: String,
roomId: String,
content: String,
transactionId: String,
retryCount: Int = DEFAULT_REQUEST_RETRY_COUNT
): SendResponse {
val paramsAdapter = moshi.adapter<Content>(Map::class.java) val paramsAdapter = moshi.adapter<Content>(Map::class.java)
val jsonContent = paramsAdapter.fromJson(content) val jsonContent = paramsAdapter.fromJson(content)
val event = Event(eventType, transactionId, jsonContent, roomId = roomId) val event = Event(eventType, transactionId, jsonContent, roomId = roomId)
val params = SendVerificationMessageTask.Params(event) val params = SendVerificationMessageTask.Params(event, retryCount)
return sendVerificationMessageTask.get().executeRetry(params, REQUEST_RETRY_COUNT) return sendVerificationMessageTask.get().execute(params)
} }
suspend fun sendSignatureUpload(request: Request.SignatureUpload): String { suspend fun sendSignatureUpload(request: Request.SignatureUpload): String {
@ -154,7 +157,7 @@ internal class RequestSender @Inject constructor(
val paramsAdapter = moshi.adapter<Map<String, Map<String, Any>>>(Map::class.java) val paramsAdapter = moshi.adapter<Map<String, Map<String, Any>>>(Map::class.java)
val signatures = paramsAdapter.fromJson(body)!! val signatures = paramsAdapter.fromJson(body)!!
val params = UploadSignaturesTask.Params(signatures) val params = UploadSignaturesTask.Params(signatures)
val response = signaturesUploadTask.executeRetry(params, REQUEST_RETRY_COUNT) val response = signaturesUploadTask.execute(params)
val responseAdapter = moshi.adapter(SignatureUploadResponse::class.java) val responseAdapter = moshi.adapter(SignatureUploadResponse::class.java)
return responseAdapter.toJson(response)!! return responseAdapter.toJson(response)!!
} }
@ -183,9 +186,8 @@ internal class RequestSender @Inject constructor(
failure = failure, failure = failure,
interceptor = interactiveAuthInterceptor, interceptor = interactiveAuthInterceptor,
retryBlock = { authUpdate -> retryBlock = { authUpdate ->
uploadSigningKeysTask.executeRetry( uploadSigningKeysTask.execute(
uploadSigningKeysParams.copy(userAuthParam = authUpdate), uploadSigningKeysParams.copy(userAuthParam = authUpdate)
REQUEST_RETRY_COUNT
) )
} }
) != UiaResult.SUCCESS ) != UiaResult.SUCCESS
@ -196,15 +198,15 @@ internal class RequestSender @Inject constructor(
} }
} }
suspend fun sendToDevice(request: Request.ToDevice) { suspend fun sendToDevice(request: Request.ToDevice, retryCount: Int = DEFAULT_REQUEST_RETRY_COUNT) {
sendToDevice(request.eventType, request.body, request.requestId) sendToDevice(request.eventType, request.body, request.requestId, retryCount)
} }
suspend fun sendToDevice(request: OutgoingVerificationRequest.ToDevice) { suspend fun sendToDevice(request: OutgoingVerificationRequest.ToDevice, retryCount: Int = DEFAULT_REQUEST_RETRY_COUNT) {
sendToDevice(request.eventType, request.body, request.requestId) sendToDevice(request.eventType, request.body, request.requestId, retryCount)
} }
suspend fun sendToDevice(eventType: String, body: String, transactionId: String) { private suspend fun sendToDevice(eventType: String, body: String, transactionId: String, retryCount: Int) {
val adapter = moshi val adapter = moshi
.newBuilder() .newBuilder()
.add(CheckNumberType.JSON_ADAPTER_FACTORY) .add(CheckNumberType.JSON_ADAPTER_FACTORY)
@ -215,16 +217,16 @@ internal class RequestSender @Inject constructor(
val userMap = MXUsersDevicesMap<Any>() val userMap = MXUsersDevicesMap<Any>()
userMap.join(jsonBody) userMap.join(jsonBody)
val sendToDeviceParams = SendToDeviceTask.Params(eventType, userMap, transactionId) val sendToDeviceParams = SendToDeviceTask.Params(eventType, userMap, transactionId, retryCount)
sendToDeviceTask.executeRetry(sendToDeviceParams, REQUEST_RETRY_COUNT) sendToDeviceTask.execute(sendToDeviceParams)
} }
suspend fun getKeyBackupVersion(version: String): KeysVersionResult? = getKeyBackupVersion { suspend fun getKeyBackupVersion(version: String): KeysVersionResult? = getKeyBackupVersion {
getKeysBackupVersionTask.executeRetry(version, 3) getKeysBackupVersionTask.execute(version)
} }
suspend fun getKeyBackupLastVersion(): KeysBackupLastVersionResult? = getKeyBackupVersion { suspend fun getKeyBackupLastVersion(): KeysBackupLastVersionResult? = getKeyBackupVersion {
getKeysBackupLastVersionTask.executeRetry(Unit, 3) getKeysBackupLastVersionTask.execute(Unit)
} }
private inline fun <reified T> getKeyBackupVersion(block: () -> T?): T? { private inline fun <reified T> getKeyBackupVersion(block: () -> T?): T? {
@ -261,27 +263,32 @@ internal class RequestSender @Inject constructor(
Map::class.java, Map::class.java,
String::class.java, String::class.java,
RoomKeysBackupData::class.java RoomKeysBackupData::class.java
)) )
)
val keys = adapter.fromJson(request.rooms)!! val keys = adapter.fromJson(request.rooms)!!
val params = StoreSessionsDataTask.Params(request.version, KeysBackupData(keys)) val params = StoreSessionsDataTask.Params(request.version, KeysBackupData(keys))
val response = backupRoomKeysTask.executeRetry(params, REQUEST_RETRY_COUNT) val response = backupRoomKeysTask.execute(params)
val responseAdapter = moshi.adapter(BackupKeysResult::class.java) val responseAdapter = moshi.adapter(BackupKeysResult::class.java)
return responseAdapter.toJson(response)!! return responseAdapter.toJson(response)!!
} }
suspend fun updateBackup(keysBackupVersion: KeysVersionResult, body: UpdateKeysBackupVersionBody) { suspend fun updateBackup(keysBackupVersion: KeysVersionResult, body: UpdateKeysBackupVersionBody) {
val params = UpdateKeysBackupVersionTask.Params(keysBackupVersion.version, body) val params = UpdateKeysBackupVersionTask.Params(keysBackupVersion.version, body)
updateKeysBackupVersionTask.executeRetry(params, REQUEST_RETRY_COUNT) updateKeysBackupVersionTask.execute(params)
} }
suspend fun downloadBackedUpKeys(version: String, roomId: String, sessionId: String): KeysBackupData { suspend fun downloadBackedUpKeys(version: String, roomId: String, sessionId: String): KeysBackupData {
val data = getRoomSessionDataTask.execute(GetRoomSessionDataTask.Params(roomId, sessionId, version)) val data = getRoomSessionDataTask.execute(GetRoomSessionDataTask.Params(roomId, sessionId, version))
return KeysBackupData(mutableMapOf( return KeysBackupData(
roomId to RoomKeysBackupData(mutableMapOf( mutableMapOf(
sessionId to data roomId to RoomKeysBackupData(
)) mutableMapOf(
)) sessionId to data
)
)
)
)
} }
suspend fun downloadBackedUpKeys(version: String, roomId: String): KeysBackupData { suspend fun downloadBackedUpKeys(version: String, roomId: String): KeysBackupData {

View File

@ -39,7 +39,7 @@ internal class DefaultClaimOneTimeKeysForUsersDevice @Inject constructor(
override suspend fun execute(params: ClaimOneTimeKeysForUsersDeviceTask.Params): KeysClaimResponse { override suspend fun execute(params: ClaimOneTimeKeysForUsersDeviceTask.Params): KeysClaimResponse {
val body = KeysClaimBody(oneTimeKeys = params.usersDevicesKeyTypesMap) val body = KeysClaimBody(oneTimeKeys = params.usersDevicesKeyTypesMap)
return executeRequest(globalErrorReceiver) { return executeRequest(globalErrorReceiver, canRetry = true) {
cryptoApi.claimOneTimeKeysForUsersDevices(body) cryptoApi.claimOneTimeKeysForUsersDevices(body)
} }
} }

View File

@ -97,7 +97,7 @@ internal class DefaultDownloadKeysForUsers @Inject constructor(
) )
} else { } else {
// No need to chunk, direct request // No need to chunk, direct request
executeRequest(globalErrorReceiver) { executeRequest(globalErrorReceiver, canRetry = true) {
cryptoApi.downloadKeysForUsers( cryptoApi.downloadKeysForUsers(
KeysQueryBody( KeysQueryBody(
deviceKeys = params.userIds.associateWith { emptyList() }, deviceKeys = params.userIds.associateWith { emptyList() },

View File

@ -19,6 +19,7 @@ package org.matrix.android.sdk.internal.crypto.tasks
import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap
import org.matrix.android.sdk.internal.crypto.api.CryptoApi import org.matrix.android.sdk.internal.crypto.api.CryptoApi
import org.matrix.android.sdk.internal.crypto.model.rest.SendToDeviceBody import org.matrix.android.sdk.internal.crypto.model.rest.SendToDeviceBody
import org.matrix.android.sdk.internal.network.DEFAULT_REQUEST_RETRY_COUNT
import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.GlobalErrorReceiver
import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.network.executeRequest
import org.matrix.android.sdk.internal.task.Task import org.matrix.android.sdk.internal.task.Task
@ -32,7 +33,9 @@ internal interface SendToDeviceTask : Task<SendToDeviceTask.Params, Unit> {
// the content to send. Map from user_id to device_id to content dictionary. // the content to send. Map from user_id to device_id to content dictionary.
val contentMap: MXUsersDevicesMap<Any>, val contentMap: MXUsersDevicesMap<Any>,
// the transactionId. If not provided, a transactionId will be created by the task // the transactionId. If not provided, a transactionId will be created by the task
val transactionId: String? = null val transactionId: String? = null,
// Number of retry before failing
val retryCount: Int = DEFAULT_REQUEST_RETRY_COUNT
) )
} }
@ -54,7 +57,7 @@ internal class DefaultSendToDeviceTask @Inject constructor(
return executeRequest( return executeRequest(
globalErrorReceiver, globalErrorReceiver,
canRetry = true, canRetry = true,
maxRetriesCount = 3 maxRetriesCount = params.retryCount
) { ) {
cryptoApi.sendToDevice( cryptoApi.sendToDevice(
eventType = params.eventType, eventType = params.eventType,

View File

@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.crypto.tasks
import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.room.send.SendState import org.matrix.android.sdk.api.session.room.send.SendState
import org.matrix.android.sdk.internal.crypto.CryptoSessionInfoProvider import org.matrix.android.sdk.internal.crypto.CryptoSessionInfoProvider
import org.matrix.android.sdk.internal.network.DEFAULT_REQUEST_RETRY_COUNT
import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.GlobalErrorReceiver
import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.network.executeRequest
import org.matrix.android.sdk.internal.session.room.RoomAPI import org.matrix.android.sdk.internal.session.room.RoomAPI
@ -29,7 +30,10 @@ import javax.inject.Inject
internal interface SendVerificationMessageTask : Task<SendVerificationMessageTask.Params, SendResponse> { internal interface SendVerificationMessageTask : Task<SendVerificationMessageTask.Params, SendResponse> {
data class Params( data class Params(
val event: Event // The event to sent
val event: Event,
// Number of retry before failing
val retryCount: Int = DEFAULT_REQUEST_RETRY_COUNT
) )
} }
@ -45,7 +49,7 @@ internal class DefaultSendVerificationMessageTask @Inject constructor(
val localId = event.eventId!! val localId = event.eventId!!
try { try {
localEchoRepository.updateSendState(localId, event.roomId, SendState.SENDING) localEchoRepository.updateSendState(localId, event.roomId, SendState.SENDING)
val response = executeRequest(globalErrorReceiver) { val response = executeRequest(globalErrorReceiver, canRetry = true, maxRetriesCount = params.retryCount) {
roomAPI.send( roomAPI.send(
txId = localId, txId = localId,
roomId = event.roomId ?: "", roomId = event.roomId ?: "",

View File

@ -38,7 +38,7 @@ internal class DefaultUploadKeysTask @Inject constructor(
override suspend fun execute(params: UploadKeysTask.Params): KeysUploadResponse { override suspend fun execute(params: UploadKeysTask.Params): KeysUploadResponse {
Timber.i("## Uploading device keys -> $params.body") Timber.i("## Uploading device keys -> $params.body")
return executeRequest(globalErrorReceiver) { return executeRequest(globalErrorReceiver, canRetry = true) {
cryptoApi.uploadKeys(params.body) cryptoApi.uploadKeys(params.body)
} }
} }

View File

@ -60,7 +60,7 @@ internal class DefaultUploadSigningKeysTask @Inject constructor(
} }
private suspend fun doRequest(uploadQuery: UploadSigningKeysBody) { private suspend fun doRequest(uploadQuery: UploadSigningKeysBody) {
val keysQueryResponse = executeRequest(globalErrorReceiver) { val keysQueryResponse = executeRequest(globalErrorReceiver, canRetry = true) {
cryptoApi.uploadSigningKeys(uploadQuery) cryptoApi.uploadSigningKeys(uploadQuery)
} }
if (keysQueryResponse.failures?.isNotEmpty() == true) { if (keysQueryResponse.failures?.isNotEmpty() == true) {

View File

@ -19,8 +19,10 @@ package org.matrix.android.sdk.internal.crypto.verification
import dagger.assisted.Assisted import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.crypto.verification.CancelCode import org.matrix.android.sdk.api.session.crypto.verification.CancelCode
import org.matrix.android.sdk.api.session.crypto.verification.EmojiRepresentation import org.matrix.android.sdk.api.session.crypto.verification.EmojiRepresentation
import org.matrix.android.sdk.api.session.crypto.verification.SasVerificationTransaction import org.matrix.android.sdk.api.session.crypto.verification.SasVerificationTransaction
@ -193,11 +195,12 @@ internal class SasVerification @AssistedInject constructor(
} }
internal suspend fun accept() { internal suspend fun accept() {
val request = innerMachine.acceptSasVerification(inner.otherUserId, inner.flowId) val request = innerMachine.acceptSasVerification(inner.otherUserId, inner.flowId) ?: return
dispatchTxUpdated()
if (request != null) { try {
sender.sendVerificationRequest(request) sender.sendVerificationRequest(request)
dispatchTxUpdated() } catch (failure: Throwable) {
cancelHelper(CancelCode.UserError)
} }
} }
@ -205,8 +208,10 @@ internal class SasVerification @AssistedInject constructor(
private suspend fun confirm() { private suspend fun confirm() {
val result = withContext(coroutineDispatchers.io) { val result = withContext(coroutineDispatchers.io) {
innerMachine.confirmVerification(inner.otherUserId, inner.flowId) innerMachine.confirmVerification(inner.otherUserId, inner.flowId)
} } ?: return
if (result != null) {
dispatchTxUpdated()
try {
for (verificationRequest in result.requests) { for (verificationRequest in result.requests) {
sender.sendVerificationRequest(verificationRequest) sender.sendVerificationRequest(verificationRequest)
} }
@ -214,16 +219,16 @@ internal class SasVerification @AssistedInject constructor(
if (signatureRequest != null) { if (signatureRequest != null) {
sender.sendSignatureUpload(signatureRequest) sender.sendSignatureUpload(signatureRequest)
} }
dispatchTxUpdated() } catch (failure: Throwable) {
cancelHelper(CancelCode.UserError)
} }
} }
private suspend fun cancelHelper(code: CancelCode) { private suspend fun cancelHelper(code: CancelCode) = withContext(NonCancellable) {
val request = innerMachine.cancelVerification(inner.otherUserId, inner.flowId, code.value) val request = innerMachine.cancelVerification(inner.otherUserId, inner.flowId, code.value) ?: return@withContext
dispatchTxUpdated()
if (request != null) { tryOrNull("Fail to send cancel request") {
sender.sendVerificationRequest(request) sender.sendVerificationRequest(request, retryCount = Int.MAX_VALUE)
dispatchTxUpdated()
} }
} }

View File

@ -19,8 +19,10 @@ package org.matrix.android.sdk.internal.crypto.verification
import dagger.assisted.Assisted import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.crypto.verification.CancelCode import org.matrix.android.sdk.api.session.crypto.verification.CancelCode
import org.matrix.android.sdk.api.session.crypto.verification.PendingVerificationRequest import org.matrix.android.sdk.api.session.crypto.verification.PendingVerificationRequest
import org.matrix.android.sdk.api.session.crypto.verification.ValidVerificationInfoReady import org.matrix.android.sdk.api.session.crypto.verification.ValidVerificationInfoReady
@ -140,11 +142,13 @@ internal class VerificationRequest @AssistedInject constructor(
innerVerificationRequest.otherUserId, innerVerificationRequest.otherUserId,
innerVerificationRequest.flowId, innerVerificationRequest.flowId,
stringMethods stringMethods
) ) ?: return
if (request != null) { try {
requestSender.sendVerificationRequest(request)
dispatchRequestUpdated() dispatchRequestUpdated()
requestSender.sendVerificationRequest(request)
} catch (failure: Throwable) {
cancel(CancelCode.UserError)
} }
} }
@ -163,12 +167,12 @@ internal class VerificationRequest @AssistedInject constructor(
*/ */
internal suspend fun startSasVerification(): SasVerification? { internal suspend fun startSasVerification(): SasVerification? {
return withContext(coroutineDispatchers.io) { return withContext(coroutineDispatchers.io) {
val result = innerOlmMachine.startSasVerification(innerVerificationRequest.otherUserId, innerVerificationRequest.flowId) val result = innerOlmMachine.startSasVerification(innerVerificationRequest.otherUserId, innerVerificationRequest.flowId) ?: return@withContext null
try {
if (result != null) {
requestSender.sendVerificationRequest(result.request) requestSender.sendVerificationRequest(result.request)
sasVerificationFactory.create(result.sas) sasVerificationFactory.create(result.sas)
} else { } catch (failure: Throwable) {
cancel(CancelCode.UserError)
null null
} }
} }
@ -192,8 +196,12 @@ internal class VerificationRequest @AssistedInject constructor(
val byteArray = data.toByteArray(Charsets.ISO_8859_1) val byteArray = data.toByteArray(Charsets.ISO_8859_1)
val encodedData = byteArray.toBase64NoPadding() val encodedData = byteArray.toBase64NoPadding()
val result = innerOlmMachine.scanQrCode(otherUser(), flowId(), encodedData) ?: return null val result = innerOlmMachine.scanQrCode(otherUser(), flowId(), encodedData) ?: return null
try {
requestSender.sendVerificationRequest(result.request) requestSender.sendVerificationRequest(result.request)
} catch (failure: Throwable) {
cancel(CancelCode.UserError)
return null
}
return qrCodeVerificationFactory.create(this, result.qr) return qrCodeVerificationFactory.create(this, result.qr)
} }
@ -233,16 +241,15 @@ internal class VerificationRequest @AssistedInject constructor(
* *
* The method turns into a noop, if the verification flow has already been cancelled. * The method turns into a noop, if the verification flow has already been cancelled.
*/ */
internal suspend fun cancel() { internal suspend fun cancel(cancelCode: CancelCode = CancelCode.User) = withContext(NonCancellable) {
val request = innerOlmMachine.cancelVerification( val request = innerOlmMachine.cancelVerification(
innerVerificationRequest.otherUserId, innerVerificationRequest.otherUserId,
innerVerificationRequest.flowId, innerVerificationRequest.flowId,
CancelCode.User.value cancelCode.value
) ) ?: return@withContext
dispatchRequestUpdated()
if (request != null) { tryOrNull("Fail to send cancel request") {
requestSender.sendVerificationRequest(request) requestSender.sendVerificationRequest(request, retryCount = Int.MAX_VALUE)
dispatchRequestUpdated()
} }
} }

View File

@ -19,8 +19,10 @@ package org.matrix.android.sdk.internal.crypto.verification.qrcode
import dagger.assisted.Assisted import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.crypto.verification.CancelCode import org.matrix.android.sdk.api.session.crypto.verification.CancelCode
import org.matrix.android.sdk.api.session.crypto.verification.QrCodeVerificationTransaction import org.matrix.android.sdk.api.session.crypto.verification.QrCodeVerificationTransaction
import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState
@ -184,9 +186,9 @@ internal class QrCodeVerification @AssistedInject constructor(
private suspend fun confirm() { private suspend fun confirm() {
val result = withContext(coroutineDispatchers.io) { val result = withContext(coroutineDispatchers.io) {
innerMachine.confirmVerification(request.otherUser(), request.flowId()) innerMachine.confirmVerification(request.otherUser(), request.flowId())
} } ?: return
dispatchTxUpdated()
if (result != null) { try {
for (verificationRequest in result.requests) { for (verificationRequest in result.requests) {
sender.sendVerificationRequest(verificationRequest) sender.sendVerificationRequest(verificationRequest)
} }
@ -194,16 +196,16 @@ internal class QrCodeVerification @AssistedInject constructor(
if (signatureRequest != null) { if (signatureRequest != null) {
sender.sendSignatureUpload(signatureRequest) sender.sendSignatureUpload(signatureRequest)
} }
dispatchTxUpdated() } catch (failure: Throwable) {
cancelHelper(CancelCode.UserError)
} }
} }
private suspend fun cancelHelper(code: CancelCode) { private suspend fun cancelHelper(code: CancelCode) = withContext(NonCancellable) {
val request = innerMachine.cancelVerification(request.otherUser(), request.flowId(), code.value) val request = innerMachine.cancelVerification(request.otherUser(), request.flowId(), code.value) ?: return@withContext
dispatchTxUpdated()
if (request != null) { tryOrNull("Fail to send cancel verification request") {
sender.sendVerificationRequest(request) sender.sendVerificationRequest(request, retryCount = Int.MAX_VALUE)
dispatchTxUpdated()
} }
} }

View File

@ -39,10 +39,13 @@ import java.io.IOException
* @param maxRetriesCount the max number of retries * @param maxRetriesCount the max number of retries
* @param requestBlock a suspend lambda to perform the network request * @param requestBlock a suspend lambda to perform the network request
*/ */
internal const val DEFAULT_REQUEST_RETRY_COUNT = 4
internal suspend inline fun <DATA> executeRequest(globalErrorReceiver: GlobalErrorReceiver?, internal suspend inline fun <DATA> executeRequest(globalErrorReceiver: GlobalErrorReceiver?,
canRetry: Boolean = false, canRetry: Boolean = false,
maxDelayBeforeRetry: Long = 32_000L, maxDelayBeforeRetry: Long = 32_000L,
maxRetriesCount: Int = 4, maxRetriesCount: Int = DEFAULT_REQUEST_RETRY_COUNT,
noinline requestBlock: suspend () -> DATA): DATA { noinline requestBlock: suspend () -> DATA): DATA {
var currentRetryCount = 0 var currentRetryCount = 0
var currentDelay = 1_000L var currentDelay = 1_000L

View File

@ -37,13 +37,12 @@ internal class DefaultToDeviceService @Inject constructor(
} }
override suspend fun sendToDevice(eventType: String, contentMap: MXUsersDevicesMap<Any>, txnId: String?) { override suspend fun sendToDevice(eventType: String, contentMap: MXUsersDevicesMap<Any>, txnId: String?) {
sendToDeviceTask.executeRetry( sendToDeviceTask.execute(
SendToDeviceTask.Params( SendToDeviceTask.Params(
eventType = eventType, eventType = eventType,
contentMap = contentMap, contentMap = contentMap,
transactionId = txnId transactionId = txnId
), )
3
) )
} }