Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .idea/dictionaries/bmarty.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright 2021 The Matrix.org Foundation C.I.C.
*
* 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.api.session

interface EventStreamService {

fun addEventStreamListener(streamListener: LiveEventListener)

fun removeEventStreamListener(streamListener: LiveEventListener)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright 2021 The Matrix.org Foundation C.I.C.
*
* 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.api.session

import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.util.JsonDict

interface LiveEventListener {

fun onLiveEvent(roomId: String, event: Event)

fun onPaginatedEvent(roomId: String, event: Event)

fun onEventDecrypted(eventId: String, roomId: String, clearEvent: JsonDict)

fun onEventDecryptionError(eventId: String, roomId: String, throwable: Throwable)

fun onLiveToDeviceEvent(event: Event)

// Maybe later add more, like onJoin, onLeave..
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ interface Session :
SyncStatusService,
HomeServerCapabilitiesService,
SecureStorageService,
AccountService {
AccountService,
ToDeviceService,
EventStreamService {

val coroutineDispatchers: MatrixCoroutineDispatchers

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright 2021 The Matrix.org Foundation C.I.C.
*
* 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.api.session

import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap
import java.util.UUID

interface ToDeviceService {

/**
* Send an event to a specific list of devices
*/
suspend fun sendToDevice(eventType: String, contentMap: MXUsersDevicesMap<Any>, txnId: String? = UUID.randomUUID().toString())

suspend fun sendToDevice(eventType: String, userId: String, deviceId: String, content: Content, txnId: String? = UUID.randomUUID().toString()) {
sendToDevice(eventType, mapOf(userId to listOf(deviceId)), content, txnId)
}

suspend fun sendToDevice(eventType: String, targets: Map<String, List<String>>, content: Content, txnId: String? = UUID.randomUUID().toString())

suspend fun sendEncryptedToDevice(eventType: String, targets: Map<String, List<String>>, content: Content, txnId: String? = UUID.randomUUID().toString())
}
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ import org.matrix.android.sdk.internal.di.MoshiProvider
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.StreamEventsManager
import org.matrix.android.sdk.internal.session.room.membership.LoadRoomMembersTask
import org.matrix.android.sdk.internal.task.TaskExecutor
import org.matrix.android.sdk.internal.task.TaskThread
Expand Down Expand Up @@ -168,7 +169,8 @@ internal class DefaultCryptoService @Inject constructor(
private val coroutineDispatchers: MatrixCoroutineDispatchers,
private val taskExecutor: TaskExecutor,
private val cryptoCoroutineScope: CoroutineScope,
private val eventDecryptor: EventDecryptor
private val eventDecryptor: EventDecryptor,
private val liveEventManager: Lazy<StreamEventsManager>
) : CryptoService {

private val isStarting = AtomicBoolean(false)
Expand Down Expand Up @@ -782,6 +784,7 @@ internal class DefaultCryptoService @Inject constructor(
}
}
}
liveEventManager.get().dispatchOnLiveToDevice(event)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package org.matrix.android.sdk.internal.crypto.algorithms.megolm

import dagger.Lazy
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
Expand Down Expand Up @@ -43,6 +44,7 @@ import org.matrix.android.sdk.internal.crypto.model.rest.ForwardedRoomKeyContent
import org.matrix.android.sdk.internal.crypto.model.rest.RoomKeyRequestBody
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask
import org.matrix.android.sdk.internal.session.StreamEventsManager
import timber.log.Timber

private val loggerTag = LoggerTag("MXMegolmDecryption", LoggerTag.CRYPTO)
Expand All @@ -56,7 +58,8 @@ internal class MXMegolmDecryption(private val userId: String,
private val cryptoStore: IMXCryptoStore,
private val sendToDeviceTask: SendToDeviceTask,
private val coroutineDispatchers: MatrixCoroutineDispatchers,
private val cryptoCoroutineScope: CoroutineScope
private val cryptoCoroutineScope: CoroutineScope,
private val liveEventManager: Lazy<StreamEventsManager>
) : IMXDecrypting, IMXWithHeldExtension {

var newSessionListener: NewSessionListener? = null
Expand Down Expand Up @@ -108,12 +111,15 @@ internal class MXMegolmDecryption(private val userId: String,
claimedEd25519Key = olmDecryptionResult.keysClaimed?.get("ed25519"),
forwardingCurve25519KeyChain = olmDecryptionResult.forwardingCurve25519KeyChain
.orEmpty()
)
).also {
liveEventManager.get().dispatchLiveEventDecrypted(event, it)
}
} else {
throw MXCryptoError.Base(MXCryptoError.ErrorType.MISSING_FIELDS, MXCryptoError.MISSING_FIELDS_REASON)
}
},
{ throwable ->
liveEventManager.get().dispatchLiveEventDecryptionFailed(event, throwable)
if (throwable is MXCryptoError.OlmError) {
// TODO Check the value of .message
if (throwable.olmException.message == "UNKNOWN_MESSAGE_INDEX") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package org.matrix.android.sdk.internal.crypto.algorithms.megolm

import dagger.Lazy
import kotlinx.coroutines.CoroutineScope
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
import org.matrix.android.sdk.internal.crypto.DeviceListManager
Expand All @@ -26,6 +27,7 @@ import org.matrix.android.sdk.internal.crypto.actions.MessageEncrypter
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask
import org.matrix.android.sdk.internal.di.UserId
import org.matrix.android.sdk.internal.session.StreamEventsManager
import javax.inject.Inject

internal class MXMegolmDecryptionFactory @Inject constructor(
Expand All @@ -38,7 +40,8 @@ internal class MXMegolmDecryptionFactory @Inject constructor(
private val cryptoStore: IMXCryptoStore,
private val sendToDeviceTask: SendToDeviceTask,
private val coroutineDispatchers: MatrixCoroutineDispatchers,
private val cryptoCoroutineScope: CoroutineScope
private val cryptoCoroutineScope: CoroutineScope,
private val eventsManager: Lazy<StreamEventsManager>
) {

fun create(): MXMegolmDecryption {
Expand All @@ -52,6 +55,7 @@ internal class MXMegolmDecryptionFactory @Inject constructor(
cryptoStore,
sendToDeviceTask,
coroutineDispatchers,
cryptoCoroutineScope)
cryptoCoroutineScope,
eventsManager)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright 2021 The Matrix.org Foundation C.I.C.
*
* 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.session

import org.matrix.android.sdk.api.session.EventStreamService
import org.matrix.android.sdk.api.session.LiveEventListener
import javax.inject.Inject

internal class DefaultEventStreamService @Inject constructor(
private val streamEventsManager: StreamEventsManager
) : EventStreamService {

override fun addEventStreamListener(streamListener: LiveEventListener) {
streamEventsManager.addLiveEventListener(streamListener)
}

override fun removeEventStreamListener(streamListener: LiveEventListener) {
streamEventsManager.removeLiveEventListener(streamListener)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ import org.matrix.android.sdk.api.auth.data.SessionParams
import org.matrix.android.sdk.api.failure.GlobalError
import org.matrix.android.sdk.api.federation.FederationService
import org.matrix.android.sdk.api.pushrules.PushRuleService
import org.matrix.android.sdk.api.session.EventStreamService
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.SessionLifecycleObserver
import org.matrix.android.sdk.api.session.ToDeviceService
import org.matrix.android.sdk.api.session.account.AccountService
import org.matrix.android.sdk.api.session.accountdata.SessionAccountDataService
import org.matrix.android.sdk.api.session.cache.CacheService
Expand Down Expand Up @@ -133,6 +135,8 @@ internal class DefaultSession @Inject constructor(
private val spaceService: Lazy<SpaceService>,
private val openIdService: Lazy<OpenIdService>,
private val presenceService: Lazy<PresenceService>,
private val toDeviceService: Lazy<ToDeviceService>,
private val eventStreamService: Lazy<EventStreamService>,
@UnauthenticatedWithCertificate
private val unauthenticatedWithCertificateOkHttpClient: Lazy<OkHttpClient>
) : Session,
Expand All @@ -152,7 +156,9 @@ internal class DefaultSession @Inject constructor(
HomeServerCapabilitiesService by homeServerCapabilitiesService.get(),
ProfileService by profileService.get(),
PresenceService by presenceService.get(),
AccountService by accountService.get() {
AccountService by accountService.get(),
ToDeviceService by toDeviceService.get(),
EventStreamService by eventStreamService.get() {

override val sharedSecretStorageService: SharedSecretStorageService
get() = _sharedSecretStorageService.get()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright 2021 The Matrix.org Foundation C.I.C.
*
* 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.session

import org.matrix.android.sdk.api.session.ToDeviceService
import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.internal.crypto.actions.MessageEncrypter
import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask
import javax.inject.Inject

internal class DefaultToDeviceService @Inject constructor(
private val sendToDeviceTask: SendToDeviceTask,
private val messageEncrypter: MessageEncrypter,
private val cryptoStore: IMXCryptoStore
) : ToDeviceService {

override suspend fun sendToDevice(eventType: String, targets: Map<String, List<String>>, content: Content, txnId: String?) {
val sendToDeviceMap = MXUsersDevicesMap<Any>()
targets.forEach { (userId, deviceIdList) ->
deviceIdList.forEach { deviceId ->
sendToDeviceMap.setObject(userId, deviceId, content)
}
}
sendToDevice(eventType, sendToDeviceMap, txnId)
}

override suspend fun sendToDevice(eventType: String, contentMap: MXUsersDevicesMap<Any>, txnId: String?) {
sendToDeviceTask.executeRetry(
SendToDeviceTask.Params(
eventType = eventType,
contentMap = contentMap,
transactionId = txnId
),
3
)
}

override suspend fun sendEncryptedToDevice(eventType: String, targets: Map<String, List<String>>, content: Content, txnId: String?) {
val payloadJson = mapOf(
"type" to eventType,
"content" to content
)
val sendToDeviceMap = MXUsersDevicesMap<Any>()

// Should I do an ensure olm session?
targets.forEach { (userId, deviceIdList) ->
deviceIdList.forEach { deviceId ->
cryptoStore.getUserDevice(userId, deviceId)?.let { deviceInfo ->
sendToDeviceMap.setObject(userId, deviceId, messageEncrypter.encryptMessage(payloadJson, listOf(deviceInfo)))
}
}
}

sendToDevice(EventType.ENCRYPTED, sendToDeviceMap, txnId)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
import org.matrix.android.sdk.api.auth.data.SessionParams
import org.matrix.android.sdk.api.auth.data.sessionId
import org.matrix.android.sdk.api.crypto.MXCryptoConfig
import org.matrix.android.sdk.api.session.EventStreamService
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.SessionLifecycleObserver
import org.matrix.android.sdk.api.session.ToDeviceService
import org.matrix.android.sdk.api.session.accountdata.SessionAccountDataService
import org.matrix.android.sdk.api.session.events.EventService
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilitiesService
Expand Down Expand Up @@ -374,6 +376,12 @@ internal abstract class SessionModule {
@Binds
abstract fun bindOpenIdTokenService(service: DefaultOpenIdService): OpenIdService

@Binds
abstract fun bindToDeviceService(service: DefaultToDeviceService): ToDeviceService

@Binds
abstract fun bindEventStreamService(service: DefaultEventStreamService): EventStreamService

@Binds
abstract fun bindTypingUsersTracker(tracker: DefaultTypingUsersTracker): TypingUsersTracker

Expand Down
Loading