From aad18ebec75c062607574c4b75d9e796c4118eb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Thu, 24 Jun 2021 13:58:59 +0200 Subject: [PATCH] crypto: Move the sendToDevice logic to a common class and use it for verifications --- .../internal/crypto/DefaultCryptoService.kt | 70 +++--- .../android/sdk/internal/crypto/OlmMachine.kt | 193 ++-------------- .../internal/crypto/RustSasVerification.kt | 208 +++++++++++++++++- .../verification/RustVerificationService.kt | 45 ++-- 4 files changed, 272 insertions(+), 244 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt index 37e1288525..c21aaed6a1 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt @@ -20,25 +20,16 @@ import android.content.Context import androidx.annotation.VisibleForTesting import androidx.lifecycle.LiveData import androidx.paging.PagedList -import com.squareup.moshi.Types -import dagger.Lazy -import java.io.File -import java.util.concurrent.atomic.AtomicBoolean -import java.util.concurrent.ConcurrentHashMap -import javax.inject.Inject -import kotlin.jvm.Throws -import kotlin.math.max -import kotlinx.coroutines.async import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.async import kotlinx.coroutines.cancelChildren +import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.joinAll import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock -import kotlinx.coroutines.withContext import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.NoOpMatrixCallback import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor @@ -59,14 +50,11 @@ import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibilityContent import org.matrix.android.sdk.api.session.room.model.RoomMemberContent import org.matrix.android.sdk.api.util.JsonDict -import org.matrix.android.sdk.internal.crypto.OlmMachine -import org.matrix.android.sdk.internal.crypto.setRustLogger import org.matrix.android.sdk.internal.crypto.crosssigning.DefaultCrossSigningService import org.matrix.android.sdk.internal.crypto.crosssigning.DeviceTrustLevel import org.matrix.android.sdk.internal.crypto.keysbackup.DefaultKeysBackupService import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult -import org.matrix.android.sdk.internal.crypto.model.MXDeviceInfo import org.matrix.android.sdk.internal.crypto.model.MXEncryptEventContentResult import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.internal.crypto.model.event.RoomKeyContent @@ -74,19 +62,19 @@ import org.matrix.android.sdk.internal.crypto.model.event.RoomKeyWithHeldContent import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo import org.matrix.android.sdk.internal.crypto.model.rest.DevicesListResponse import org.matrix.android.sdk.internal.crypto.model.rest.ForwardedRoomKeyContent -import org.matrix.android.sdk.internal.crypto.model.rest.KeysUploadResponse import org.matrix.android.sdk.internal.crypto.model.rest.KeysClaimResponse import org.matrix.android.sdk.internal.crypto.model.rest.KeysQueryResponse +import org.matrix.android.sdk.internal.crypto.model.rest.KeysUploadResponse import org.matrix.android.sdk.internal.crypto.repository.WarnOnUnknownDeviceRepository import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore +import org.matrix.android.sdk.internal.crypto.tasks.ClaimOneTimeKeysForUsersDeviceTask import org.matrix.android.sdk.internal.crypto.tasks.DeleteDeviceTask import org.matrix.android.sdk.internal.crypto.tasks.DownloadKeysForUsersTask import org.matrix.android.sdk.internal.crypto.tasks.GetDeviceInfoTask import org.matrix.android.sdk.internal.crypto.tasks.GetDevicesTask -import org.matrix.android.sdk.internal.crypto.tasks.UploadKeysTask -import org.matrix.android.sdk.internal.crypto.tasks.SetDeviceNameTask import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask -import org.matrix.android.sdk.internal.crypto.tasks.ClaimOneTimeKeysForUsersDeviceTask +import org.matrix.android.sdk.internal.crypto.tasks.SetDeviceNameTask +import org.matrix.android.sdk.internal.crypto.tasks.UploadKeysTask import org.matrix.android.sdk.internal.crypto.verification.RustVerificationService import org.matrix.android.sdk.internal.di.DeviceId import org.matrix.android.sdk.internal.di.MoshiProvider @@ -95,7 +83,6 @@ import org.matrix.android.sdk.internal.di.UserId import org.matrix.android.sdk.internal.extensions.foldToCallback import org.matrix.android.sdk.internal.session.SessionScope import org.matrix.android.sdk.internal.session.room.membership.LoadRoomMembersTask -import org.matrix.android.sdk.internal.session.sync.model.SyncResponse import org.matrix.android.sdk.internal.session.sync.model.DeviceListResponse import org.matrix.android.sdk.internal.session.sync.model.DeviceOneTimeKeysCountSyncResponse import org.matrix.android.sdk.internal.session.sync.model.ToDeviceSyncResponse @@ -107,6 +94,30 @@ import org.matrix.android.sdk.internal.util.MatrixCoroutineDispatchers import timber.log.Timber import uniffi.olm.Request import uniffi.olm.RequestType +import java.io.File +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.atomic.AtomicBoolean +import javax.inject.Inject +import kotlin.math.max + +internal class RequestSender( + private val sendToDeviceTask: SendToDeviceTask, +) { + suspend fun sendToDevice(eventType: String, body: String) { + // TODO this produces floats for the Olm type fields, which + // are integers originally. + val adapter = MoshiProvider + .providesMoshi() + .adapter>>(Map::class.java) + val jsonBody = adapter.fromJson(body)!! + + val userMap = MXUsersDevicesMap() + userMap.join(jsonBody) + + val sendToDeviceParams = SendToDeviceTask.Params(eventType, userMap) + sendToDeviceTask.execute(sendToDeviceParams) + } +} /** * A `CryptoService` class instance manages the end-to-end crypto for a session. @@ -153,6 +164,8 @@ internal class DefaultCryptoService @Inject constructor( private val isStarting = AtomicBoolean(false) private val isStarted = AtomicBoolean(false) + private val sender = RequestSender(this.sendToDeviceTask) + private var olmMachine: OlmMachine? = null // The verification service. private var verificationService: RustVerificationService? = null @@ -320,7 +333,7 @@ internal class DefaultCryptoService @Inject constructor( val machine = OlmMachine(userId, deviceId!!, dataDir, deviceObserver) this.olmMachine = machine this.verificationService = - RustVerificationService(this.taskExecutor, machine, this.sendToDeviceTask) + RustVerificationService(machine, this.sender) Timber.v( "## CRYPTO | Successfully started up an Olm machine for " + "${userId}, ${deviceId}, identity keys: ${this.olmMachine?.identityKeys()}") @@ -373,7 +386,7 @@ internal class DefaultCryptoService @Inject constructor( // `ActiveSessionHolder` class in the `setActiveSession()` method. In // the `setActiveSession()` method we call the `start()` method of the // handlers without first calling the `start()` method of the - // `DefaultCrytpoService`. + // `DefaultCryptoService`. // // The start method of the crypto service isn't part of the // `CryptoService` interface so it currently can't be called there. I'm @@ -666,7 +679,7 @@ internal class DefaultCryptoService @Inject constructor( } } - private fun notifyRoomKeyReceival( + private fun notifyRoomKeyReceived( roomId: String, sessionId: String, ) { @@ -791,18 +804,7 @@ internal class DefaultCryptoService @Inject constructor( } private suspend fun sendToDevice(request: Request.ToDevice) { - // TODO this produces floats for the Olm type fields, which - // are integers originally. - val adapter = MoshiProvider - .providesMoshi() - .adapter>>(Map::class.java) - val body = adapter.fromJson(request.body)!! - - val userMap = MXUsersDevicesMap() - userMap.join(body) - - val sendToDeviceParams = SendToDeviceTask.Params(request.eventType, userMap) - sendToDeviceTask.execute(sendToDeviceParams) + this.sender.sendToDevice(request.eventType, request.body) olmMachine!!.markRequestAsSent(request.requestId, RequestType.TO_DEVICE, "{}") } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OlmMachine.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OlmMachine.kt index 196eced925..4622960c3f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OlmMachine.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OlmMachine.kt @@ -27,13 +27,10 @@ import kotlinx.coroutines.withContext import org.matrix.android.sdk.api.listeners.ProgressListener import org.matrix.android.sdk.api.session.crypto.MXCryptoError 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.PendingVerificationRequest -import org.matrix.android.sdk.api.session.crypto.verification.SasVerificationTransaction import org.matrix.android.sdk.api.session.crypto.verification.ValidVerificationInfoReady import org.matrix.android.sdk.api.session.crypto.verification.ValidVerificationInfoRequest import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod -import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.util.JsonDict @@ -46,7 +43,6 @@ import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_QR_ import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_QR_CODE_SHOW import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_RECIPROCATE import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_SAS -import org.matrix.android.sdk.internal.crypto.verification.getEmojiForCode import org.matrix.android.sdk.internal.di.MoshiProvider import org.matrix.android.sdk.internal.session.sync.model.DeviceListResponse import org.matrix.android.sdk.internal.session.sync.model.DeviceOneTimeKeysCountSyncResponse @@ -64,7 +60,7 @@ import uniffi.olm.OutgoingVerificationRequest import uniffi.olm.ProgressListener as RustProgressListener import uniffi.olm.Request import uniffi.olm.RequestType -import uniffi.olm.Sas as InnerSas +import uniffi.olm.Sas import uniffi.olm.StartSasResult import uniffi.olm.VerificationRequest as InnerRequest import uniffi.olm.setLogger @@ -149,7 +145,7 @@ internal class VerificationRequest( return } - fun accept_with_methods(methods: List): OutgoingVerificationRequest? { + fun acceptWithMethods(methods: List): OutgoingVerificationRequest? { val stringMethods: MutableList = methods .map { @@ -185,17 +181,11 @@ internal class VerificationRequest( return this.inner.isReady } - suspend fun startSasVerification(): Pair? { + suspend fun startSasVerification(): StartSasResult? { refreshData() return withContext(Dispatchers.IO) { - val response = machine.startSasVerification(inner.otherUserId, inner.flowId) - - if (response != null) { - Pair(response.request, SasVerification(machine, response.sas)) - } else { - null - } + machine.startSasVerification(inner.otherUserId, inner.flowId) } } @@ -280,7 +270,7 @@ internal class VerificationRequest( } } -private fun toCancelCode(cancelCode: RustCancelCode): CancelCode { +internal fun toCancelCode(cancelCode: RustCancelCode): CancelCode { return when (cancelCode) { RustCancelCode.USER -> CancelCode.User RustCancelCode.TIMEOUT -> CancelCode.Timeout @@ -290,162 +280,11 @@ private fun toCancelCode(cancelCode: RustCancelCode): CancelCode { RustCancelCode.KEY_MISMATCH -> CancelCode.MismatchedKeys RustCancelCode.USER_MISMATCH -> CancelCode.MismatchedKeys RustCancelCode.INVALID_MESSAGE -> CancelCode.InvalidMessage - // TODO why don't the ruma codes match what's in EA? + // TODO why don't the Ruma codes match what's in EA? RustCancelCode.ACCEPTED -> CancelCode.User } } -public class SasVerification(private val machine: InnerMachine, private var inner: InnerSas) : - SasVerificationTransaction { - private var stateField: VerificationTxState = VerificationTxState.OnStarted - - private fun refreshData() { - val sas = this.machine.getVerification(this.inner.otherUserId, this.inner.flowId) - - if (sas != null) { - this.inner = sas - } - - return - } - - override val isIncoming: Boolean - get() { - return false - } - - override var otherDeviceId: String? - get() { - return this.inner.otherDeviceId - } - set(value) { - if (value != null) { - this.inner.otherDeviceId = value - } - } - - override val otherUserId: String - get() { - return this.inner.otherUserId - } - - override var state: VerificationTxState - get() { - refreshData() - return when { - this.inner.canBePresented -> { - VerificationTxState.ShortCodeReady - } - this.inner.isCancelled -> { - // TODO fetch the cancel code from the rust side - VerificationTxState.Cancelled(CancelCode.User, false) - } - this.inner.isDone -> { - VerificationTxState.Verified - } - else -> { - VerificationTxState.Started - } - } - } - set(v) { - this.stateField = v - } - - override val transactionId: String - get() { - return this.inner.flowId - } - - override fun cancel() { - TODO() - } - - override fun cancel(code: CancelCode) { - TODO() - } - - override fun shortCodeDoesNotMatch() { - TODO() - } - - override fun isToDeviceTransport(): Boolean { - return false - } - - override fun supportsDecimal(): Boolean { - // This is ignored anyways, throw it away? - // The spec also mandates that devices support - // at least decimal and the rust-sdk cancels if - // devices don't support it - return true - } - - override fun supportsEmoji(): Boolean { - refreshData() - return this.inner.supportsEmoji - } - - override fun userHasVerifiedShortCode() { - // This is confirm - TODO() - } - - fun isCanceled(): Boolean { - refreshData() - return this.inner.isCancelled - } - - fun isDone(): Boolean { - refreshData() - return this.inner.isDone - } - - fun timedOut(): Boolean { - refreshData() - return this.inner.timedOut - } - - fun canBePresented(): Boolean { - refreshData() - return this.inner.canBePresented - } - - fun accept(): OutgoingVerificationRequest? { - return this.machine.acceptSasVerification(this.inner.otherUserId, inner.flowId) - } - - @Throws(CryptoStoreErrorException::class) - suspend fun confirm(): OutgoingVerificationRequest? = - withContext(Dispatchers.IO) { - machine.confirmVerification(inner.otherUserId, inner.flowId) - } - - fun cancelHelper(): OutgoingVerificationRequest? { - return this.machine.cancelVerification(this.inner.otherUserId, inner.flowId) - } - - override fun getEmojiCodeRepresentation(): List { - val emojiIndex = this.machine.getEmojiIndex(this.inner.otherUserId, this.inner.flowId) - - return if (emojiIndex != null) { - emojiIndex.map { getEmojiForCode(it) } - } else { - listOf() - } - } - - override fun getDecimalCodeRepresentation(): String { - val decimals = this.machine.getDecimals(this.inner.otherUserId, this.inner.flowId) - - return if (decimals != null) { - decimals.joinToString(" ") - } else { - "" - } - } -} - internal class OlmMachine( user_id: String, device_id: String, @@ -470,6 +309,10 @@ internal class OlmMachine( return this.inner.identityKeys() } + fun inner(): InnerMachine { + return this.inner + } + fun ownDevice(): CryptoDeviceInfo { val deviceId = this.deviceId() @@ -528,7 +371,7 @@ internal class OlmMachine( * This needs to be called after every sync, ideally before processing any other sync changes. * * @param toDevice A serialized array of to-device events we received in the current sync - * resposne. + * response. * * @param deviceChanges The list of devices that have changed in some way since the previous * sync. @@ -613,7 +456,7 @@ internal class OlmMachine( * **Note**: A room key needs to be shared with the group of users that are members in the given * room. If this is not done this method will panic. * - * The usual flow to encrypt an evnet using this state machine is as follows: + * The usual flow to encrypt an event using this state machine is as follows: * * 1. Get the one-time key claim request to establish 1:1 Olm sessions for * ``` @@ -629,7 +472,7 @@ internal class OlmMachine( * * 4. Send the encrypted event to the server. * - * After the room key is shared steps 1 and 2 will become noops, unless there's some changes in + * After the room key is shared steps 1 and 2 will become no-ops, unless there's some changes in * the room membership or in the list of devices a member has. * * @param roomId the ID of the room where the encrypted event will be sent to @@ -865,13 +708,7 @@ internal class OlmMachine( } /** Get an active verification */ - fun getVerification(userId: String, flowId: String): SasVerification? { - val sas = this.inner.getVerification(userId, flowId) - - return if (sas == null) { - null - } else { - SasVerification(this.inner, sas) - } + fun getVerification(userId: String, flowId: String): Sas? { + return this.inner.getVerification(userId, flowId) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RustSasVerification.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RustSasVerification.kt index 4ae9ccbcc0..a4cb81150e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RustSasVerification.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RustSasVerification.kt @@ -1,2 +1,208 @@ -package org.matrix.android.sdk.internal.crypto +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.matrix.android.sdk.internal.crypto + +import android.os.Handler +import android.os.Looper +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withContext +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.SasVerificationTransaction +import org.matrix.android.sdk.api.session.crypto.verification.VerificationService +import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState +import org.matrix.android.sdk.internal.crypto.verification.getEmojiForCode +import timber.log.Timber +import uniffi.olm.CryptoStoreErrorException +import uniffi.olm.OlmMachine +import uniffi.olm.OutgoingVerificationRequest +import uniffi.olm.Sas + +internal class SasVerification( + private val machine: OlmMachine, + private var inner: Sas, + private val sender: RequestSender, + private val listeners: ArrayList, + ) : + SasVerificationTransaction { + private val uiHandler = Handler(Looper.getMainLooper()) + private var stateField: VerificationTxState = VerificationTxState.OnStarted + + private fun dispatchTxUpdated() { + uiHandler.post { + listeners.forEach { + try { + it.transactionUpdated(this) + } catch (e: Throwable) { + Timber.e(e, "## Error while notifying listeners") + } + } + } + } + + private fun refreshData() { + val sas = this.machine.getVerification(this.inner.otherUserId, this.inner.flowId) + + if (sas != null) { + this.inner = sas + } + + return + } + + override val isIncoming: Boolean + get() { + return false + } + + override var otherDeviceId: String? + get() { + return this.inner.otherDeviceId + } + set(value) { + if (value != null) { + this.inner.otherDeviceId = value + } + } + + override val otherUserId: String + get() { + return this.inner.otherUserId + } + + override var state: VerificationTxState + get() { + refreshData() + return when { + this.inner.isDone -> VerificationTxState.Verified + this.inner.haveWeConfirmed -> VerificationTxState.ShortCodeAccepted + this.inner.canBePresented -> VerificationTxState.ShortCodeReady + this.inner.isCancelled -> { + val rustCancelCode = this.inner.cancelCode + val cancelCode = + if (rustCancelCode != null) { + toCancelCode(rustCancelCode) + } else { + CancelCode.UnexpectedMessage + } + // TODO get byMe from the rust side + VerificationTxState.Cancelled(cancelCode, false) + } + else -> { + VerificationTxState.Started + } + } + } + set(v) { + this.stateField = v + } + + override val transactionId: String + get() { + return this.inner.flowId + } + + override fun cancel() { + TODO() + } + + override fun cancel(code: CancelCode) { + TODO() + } + + override fun shortCodeDoesNotMatch() { + TODO() + } + + override fun isToDeviceTransport(): Boolean { + return false + } + + override fun supportsDecimal(): Boolean { + // This is ignored anyways, throw it away? + // The spec also mandates that devices support + // at least decimal and the rust-sdk cancels if + // devices don't support it + return true + } + + override fun supportsEmoji(): Boolean { + refreshData() + return this.inner.supportsEmoji + } + + override fun userHasVerifiedShortCode() { + runBlocking { + when (val request = confirm()) { + is OutgoingVerificationRequest.ToDevice -> { + sender.sendToDevice(request.eventType, request.body) + } + + else -> {} + } + } + refreshData() + dispatchTxUpdated() + } + + fun isCanceled(): Boolean { + refreshData() + return this.inner.isCancelled + } + + fun isDone(): Boolean { + refreshData() + return this.inner.isDone + } + + fun timedOut(): Boolean { + refreshData() + return this.inner.timedOut + } + + fun canBePresented(): Boolean { + refreshData() + return this.inner.canBePresented + } + + fun accept(): OutgoingVerificationRequest? { + return this.machine.acceptSasVerification(this.inner.otherUserId, inner.flowId) + } + + @Throws(CryptoStoreErrorException::class) + suspend fun confirm(): OutgoingVerificationRequest? = + withContext(Dispatchers.IO) { + machine.confirmVerification(inner.otherUserId, inner.flowId) + } + + fun cancelHelper(): OutgoingVerificationRequest? { + return this.machine.cancelVerification(this.inner.otherUserId, inner.flowId) + } + + override fun getEmojiCodeRepresentation(): List { + val emojiIndex = this.machine.getEmojiIndex(this.inner.otherUserId, this.inner.flowId) + + return emojiIndex?.map { getEmojiForCode(it) } ?: listOf() + } + + override fun getDecimalCodeRepresentation(): String { + val decimals = this.machine.getDecimals(this.inner.otherUserId, this.inner.flowId) + + return decimals?.joinToString(" ") ?: "" + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/RustVerificationService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/RustVerificationService.kt index 91c68e18cf..0630830ce0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/RustVerificationService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/RustVerificationService.kt @@ -18,9 +18,7 @@ package org.matrix.android.sdk.internal.crypto.verification import android.os.Handler import android.os.Looper -import kotlinx.coroutines.flow.flow import javax.inject.Inject -import kotlin.collections.set import kotlinx.coroutines.runBlocking import org.matrix.android.sdk.api.session.crypto.verification.PendingVerificationRequest import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod @@ -31,14 +29,12 @@ import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.room.model.message.MessageType import org.matrix.android.sdk.internal.crypto.OlmMachine -import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap +import org.matrix.android.sdk.internal.crypto.RequestSender +import org.matrix.android.sdk.internal.crypto.SasVerification import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationDone import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationKey import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationRequest -import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask -import org.matrix.android.sdk.internal.di.MoshiProvider import org.matrix.android.sdk.internal.session.SessionScope -import org.matrix.android.sdk.internal.task.TaskExecutor import timber.log.Timber import uniffi.olm.OutgoingVerificationRequest @@ -46,9 +42,8 @@ import uniffi.olm.OutgoingVerificationRequest internal class RustVerificationService @Inject constructor( - private val taskExecutor: TaskExecutor, private val olmMachine: OlmMachine, - private val sendToDeviceTask: SendToDeviceTask, + private val requestSender: RequestSender, ) : DefaultVerificationTransaction.Listener, VerificationService { private val uiHandler = Handler(Looper.getMainLooper()) @@ -91,7 +86,7 @@ constructor( } private fun dispatchRequestAdded(tx: PendingVerificationRequest) { - Timber.v("## SAS dispatchRequestAdded txId:${tx.transactionId} ${tx}") + Timber.v("## SAS dispatchRequestAdded txId:${tx.transactionId} $tx") uiHandler.post { listeners.forEach { try { @@ -188,7 +183,9 @@ constructor( otherUserId: String, tid: String, ): VerificationTransaction? { - return this.olmMachine.getVerification(otherUserId, tid) + val verification = this.olmMachine.getVerification(otherUserId, tid) ?: return null + + return SasVerification(this.olmMachine.inner(), verification, this.requestSender, this.listeners) } override fun getExistingVerificationRequests( @@ -204,13 +201,7 @@ constructor( tid: String? ): PendingVerificationRequest? { return if (tid != null) { - val request = this.olmMachine.getVerificationRequest(otherUserId, tid) - - if (request != null) { - request.toPendingVerificationRequest() - } else { - null - } + olmMachine.getVerificationRequest(otherUserId, tid)?.toPendingVerificationRequest() } else { null } @@ -236,9 +227,10 @@ constructor( runBlocking { val response = request?.startSasVerification() if (response != null) { - sendRequest(response.first) - dispatchTxAdded(response.second) - response.second.transactionId + sendRequest(response.request) + val sas = SasVerification(olmMachine.inner(), response.sas, requestSender, listeners) + dispatchTxAdded(sas) + sas.transactionId } else { null } @@ -315,7 +307,7 @@ constructor( val request = this.olmMachine.getVerificationRequest(otherUserId, transactionId) return if (request != null) { - val outgoingRequest = request.accept_with_methods(methods) + val outgoingRequest = request.acceptWithMethods(methods) if (outgoingRequest != null) { runBlocking { sendRequest(outgoingRequest) } @@ -335,16 +327,7 @@ constructor( suspend fun sendRequest(request: OutgoingVerificationRequest) { when (request) { is OutgoingVerificationRequest.ToDevice -> { - val adapter = - MoshiProvider.providesMoshi() - .adapter>>(Map::class.java) - val body = adapter.fromJson(request.body)!! - - val userMap = MXUsersDevicesMap() - userMap.join(body) - - val sendToDeviceParams = SendToDeviceTask.Params(request.eventType, userMap) - sendToDeviceTask.execute(sendToDeviceParams) + this.requestSender.sendToDevice(request.eventType, request.body) } else -> {} }