From 3285975b1a91847e24daf14a645a7e8ee1967d63 Mon Sep 17 00:00:00 2001 From: Ryan ZHAO Date: Wed, 17 Feb 2021 10:51:02 +1100 Subject: [PATCH] WIP: clean up V1 multi device --- .../loki/activities/EditClosedGroupLoader.kt | 1 - .../securesms/loki/activities/HomeActivity.kt | 12 -- .../securesms/loki/api/PublicChatPoller.kt | 26 +-- .../loki/database/LokiAPIDatabase.kt | 43 ----- .../protocol/SessionManagementProtocol.kt | 8 +- .../messaging/fileserver/FileServerAPI.kt | 182 ------------------ .../threads/recipients/Recipient.java | 8 +- .../api/SignalServiceMessageSender.java | 33 +--- .../api/crypto/SignalServiceCipher.java | 30 +-- .../api/messages/SignalServiceContent.java | 43 +---- .../messages/SignalServiceDataMessage.java | 36 +--- .../loki/api/fileserver/FileServerAPI.kt | 181 ----------------- .../loki/database/LokiAPIDatabaseProtocol.kt | 8 - .../loki/protocol/meta/SessionMetaProtocol.kt | 1 - .../shelved/multidevice/DeviceLink.kt | 72 ------- .../multidevice/DeviceLinkingSession.kt | 37 ---- .../DeviceLinkingSessionListener.kt | 7 - .../multidevice/MultiDeviceProtocol.kt | 46 ----- .../syncmessages/SyncMessagesProtocol.kt | 36 ---- 19 files changed, 19 insertions(+), 791 deletions(-) delete mode 100644 libsignal/src/main/java/org/session/libsignal/service/loki/protocol/shelved/multidevice/DeviceLink.kt delete mode 100644 libsignal/src/main/java/org/session/libsignal/service/loki/protocol/shelved/multidevice/DeviceLinkingSession.kt delete mode 100644 libsignal/src/main/java/org/session/libsignal/service/loki/protocol/shelved/multidevice/DeviceLinkingSessionListener.kt delete mode 100644 libsignal/src/main/java/org/session/libsignal/service/loki/protocol/shelved/multidevice/MultiDeviceProtocol.kt delete mode 100644 libsignal/src/main/java/org/session/libsignal/service/loki/protocol/shelved/syncmessages/SyncMessagesProtocol.kt diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/EditClosedGroupLoader.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/EditClosedGroupLoader.kt index d3479658cb..4f49501fc6 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/EditClosedGroupLoader.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/EditClosedGroupLoader.kt @@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.loki.activities import android.content.Context import org.thoughtcrime.securesms.database.DatabaseFactory -import org.thoughtcrime.securesms.loki.utilities.ContactUtilities import org.thoughtcrime.securesms.util.AsyncLoader class EditClosedGroupLoader(context: Context, val groupID: String) : AsyncLoader>(context) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/HomeActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/HomeActivity.kt index 88c5eea005..9291808fc3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/HomeActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/HomeActivity.kt @@ -44,12 +44,9 @@ import org.session.libsession.utilities.TextSecurePreferences import org.session.libsession.utilities.TextSecurePreferences.getBooleanPreference import org.session.libsession.utilities.TextSecurePreferences.setBooleanPreference import org.session.libsession.utilities.Util -import org.session.libsignal.service.loki.api.fileserver.FileServerAPI import org.session.libsignal.service.loki.protocol.mentions.MentionsManager import org.session.libsignal.service.loki.protocol.meta.SessionMetaProtocol import org.session.libsignal.service.loki.protocol.sessionmanagement.SessionManagementProtocol -import org.session.libsignal.service.loki.protocol.shelved.multidevice.MultiDeviceProtocol -import org.session.libsignal.service.loki.protocol.shelved.syncmessages.SyncMessagesProtocol import org.session.libsignal.utilities.ThreadUtils import org.session.libsignal.service.loki.utilities.toHexString import org.thoughtcrime.securesms.loki.dialogs.* @@ -177,20 +174,11 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe if (userPublicKey != null) { MentionsManager.configureIfNeeded(userPublicKey, threadDB, userDB) SessionMetaProtocol.configureIfNeeded(apiDB, userPublicKey) - SyncMessagesProtocol.configureIfNeeded(apiDB, userPublicKey) application.publicChatManager.startPollersIfNeeded() } SessionManagementProtocol.configureIfNeeded(sessionResetImpl, sskDatabase, application) - MultiDeviceProtocol.configureIfNeeded(apiDB) IP2Country.configureIfNeeded(this) application.registerForFCMIfNeeded(false) - // Preload device links to make message sending quicker - val publicKeys = ContactUtilities.getAllContacts(this).filter { contact -> - !contact.recipient.isGroupRecipient && !contact.isOurDevice && !contact.isSlave - }.map { - it.recipient.address.toString() - }.toSet() - FileServerAPI.shared.getDeviceLinks(publicKeys) // Observe blocked contacts changed events val broadcastReceiver = object : BroadcastReceiver() { diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/api/PublicChatPoller.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/api/PublicChatPoller.kt index 3303515794..3ffbc83f5c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/api/PublicChatPoller.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/api/PublicChatPoller.kt @@ -27,7 +27,6 @@ import org.session.libsignal.service.loki.api.fileserver.FileServerAPI import org.session.libsignal.service.loki.api.opengroups.PublicChat import org.session.libsignal.service.loki.api.opengroups.PublicChatAPI import org.session.libsignal.service.loki.api.opengroups.PublicChatMessage -import org.session.libsignal.service.loki.protocol.shelved.multidevice.MultiDeviceProtocol import java.security.MessageDigest import java.util.* @@ -161,14 +160,11 @@ class PublicChatPoller(private val context: Context, private val group: PublicCh fun pollForNewMessages(): Promise { fun processIncomingMessage(message: PublicChatMessage) { // If the sender of the current message is not a slave device, set the display name in the database - val masterHexEncodedPublicKey = MultiDeviceProtocol.shared.getMasterDevice(message.senderPublicKey) - if (masterHexEncodedPublicKey == null) { - val senderDisplayName = "${message.displayName} (...${message.senderPublicKey.takeLast(8)})" - DatabaseFactory.getLokiUserDatabase(context).setServerDisplayName(group.id, message.senderPublicKey, senderDisplayName) - } - val senderHexEncodedPublicKey = masterHexEncodedPublicKey ?: message.senderPublicKey + val senderDisplayName = "${message.displayName} (...${message.senderPublicKey.takeLast(8)})" + DatabaseFactory.getLokiUserDatabase(context).setServerDisplayName(group.id, message.senderPublicKey, senderDisplayName) + val senderHexEncodedPublicKey = message.senderPublicKey val serviceDataMessage = getDataMessage(message) - val serviceContent = SignalServiceContent(serviceDataMessage, senderHexEncodedPublicKey, SignalServiceAddress.DEFAULT_DEVICE_ID, message.serverTimestamp, false, false) + val serviceContent = SignalServiceContent(serviceDataMessage, senderHexEncodedPublicKey, SignalServiceAddress.DEFAULT_DEVICE_ID, message.serverTimestamp, false) if (serviceDataMessage.quote.isPresent || (serviceDataMessage.attachments.isPresent && serviceDataMessage.attachments.get().size > 0) || serviceDataMessage.previews.isPresent) { PushDecryptJob(context).handleMediaMessage(serviceContent, serviceDataMessage, Optional.absent(), Optional.of(message.serverID)) } else { @@ -221,8 +217,6 @@ class PublicChatPoller(private val context: Context, private val group: PublicCh } if (isPollOngoing) { return Promise.of(Unit) } isPollOngoing = true - val userDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(userHexEncodedPublicKey) - var uniqueDevices = setOf() val userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(context).privateKey.serialize() val apiDB = DatabaseFactory.getLokiAPIDatabase(context) FileServerAPI.configure(userHexEncodedPublicKey, userPrivateKey, apiDB) @@ -240,20 +234,10 @@ class PublicChatPoller(private val context: Context, private val group: PublicCh */ Promise.of(messages) } - promise.successBackground { - /* - val newDisplayNameUpdatees = uniqueDevices.mapNotNull { - // This will return null if the current device is a master device - MultiDeviceProtocol.shared.getMasterDevice(it) - }.toSet() - // Fetch the display names of the master devices - displayNameUpdatees = displayNameUpdatees.union(newDisplayNameUpdatees) - */ - } promise.successBackground { messages -> // Process messages in the background messages.forEach { message -> - if (userDevices.contains(message.senderPublicKey)) { + if (message.senderPublicKey == userHexEncodedPublicKey) { processOutgoingMessage(message) } else { processIncomingMessage(message) diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/database/LokiAPIDatabase.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/database/LokiAPIDatabase.kt index 5e7183ac6c..d426d200f0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/database/LokiAPIDatabase.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/database/LokiAPIDatabase.kt @@ -11,7 +11,6 @@ import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper import org.thoughtcrime.securesms.loki.utilities.* import org.session.libsignal.service.loki.api.Snode import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol -import org.session.libsignal.service.loki.protocol.shelved.multidevice.DeviceLink import org.session.libsignal.service.loki.utilities.removing05PrefixIfNeeded import org.session.libsignal.service.loki.utilities.toHexString import org.thoughtcrime.securesms.crypto.IdentityKeyUtil @@ -459,48 +458,6 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database( val database = databaseHelper.writableDatabase database.delete(closedGroupPublicKeysTable, "${Companion.groupPublicKey} = ?", wrap(groupPublicKey)) } - - // region Deprecated - override fun getDeviceLinks(publicKey: String): Set { - return setOf() - /* - val database = databaseHelper.readableDatabase - return database.getAll(deviceLinkCache, "$masterPublicKey = ? OR $slavePublicKey = ?", arrayOf( publicKey, publicKey )) { cursor -> - val masterHexEncodedPublicKey = cursor.getString(masterPublicKey) - val slaveHexEncodedPublicKey = cursor.getString(slavePublicKey) - val requestSignature: ByteArray? = if (cursor.isNull(cursor.getColumnIndexOrThrow(requestSignature))) null else cursor.getBase64EncodedData(requestSignature) - val authorizationSignature: ByteArray? = if (cursor.isNull(cursor.getColumnIndexOrThrow(authorizationSignature))) null else cursor.getBase64EncodedData(authorizationSignature) - DeviceLink(masterHexEncodedPublicKey, slaveHexEncodedPublicKey, requestSignature, authorizationSignature) - }.toSet() - */ - } - - override fun clearDeviceLinks(publicKey: String) { - /* - val database = databaseHelper.writableDatabase - database.delete(deviceLinkCache, "$masterPublicKey = ? OR $slavePublicKey = ?", arrayOf( publicKey, publicKey )) - */ - } - - override fun addDeviceLink(deviceLink: DeviceLink) { - /* - val database = databaseHelper.writableDatabase - val values = ContentValues() - values.put(masterPublicKey, deviceLink.masterPublicKey) - values.put(slavePublicKey, deviceLink.slavePublicKey) - if (deviceLink.requestSignature != null) { values.put(requestSignature, Base64.encodeBytes(deviceLink.requestSignature)) } - if (deviceLink.authorizationSignature != null) { values.put(authorizationSignature, Base64.encodeBytes(deviceLink.authorizationSignature)) } - database.insertOrUpdate(deviceLinkCache, values, "$masterPublicKey = ? AND $slavePublicKey = ?", arrayOf( deviceLink.masterPublicKey, deviceLink.slavePublicKey )) - */ - } - - override fun removeDeviceLink(deviceLink: DeviceLink) { - /* - val database = databaseHelper.writableDatabase - database.delete(deviceLinkCache, "$masterPublicKey = ? OR $slavePublicKey = ?", arrayOf( deviceLink.masterPublicKey, deviceLink.slavePublicKey )) - */ - } - // endregion } // region Convenience diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/SessionManagementProtocol.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/SessionManagementProtocol.kt index c305852eb1..87881d5456 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/SessionManagementProtocol.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/SessionManagementProtocol.kt @@ -13,7 +13,6 @@ import org.thoughtcrime.securesms.sms.OutgoingTextMessage import org.session.libsession.utilities.TextSecurePreferences import org.session.libsignal.libsignal.loki.SessionResetStatus import org.session.libsignal.service.api.messages.SignalServiceContent -import org.session.libsignal.service.loki.protocol.shelved.multidevice.MultiDeviceProtocol import java.util.* object SessionManagementProtocol { @@ -95,13 +94,12 @@ object SessionManagementProtocol { @JvmStatic fun triggerSessionRestorationUI(context: Context, publicKey: String, errorTimestamp: Long) { - val masterDevicePublicKey = MultiDeviceProtocol.shared.getMasterDevice(publicKey) ?: publicKey - val masterDeviceAsRecipient = recipient(context, masterDevicePublicKey) - if (masterDeviceAsRecipient.isGroupRecipient) { return } + val recipient = recipient(context, publicKey) + if (recipient.isGroupRecipient) { return } if (TextSecurePreferences.getRestorationTime(context) > errorTimestamp) { return ApplicationContext.getInstance(context).sendSessionRequestIfNeeded(publicKey) } - val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(masterDeviceAsRecipient) + val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient) DatabaseFactory.getLokiThreadDatabase(context).addSessionRestoreDevice(threadID, publicKey) } } \ No newline at end of file diff --git a/libsession/src/main/java/org/session/libsession/messaging/fileserver/FileServerAPI.kt b/libsession/src/main/java/org/session/libsession/messaging/fileserver/FileServerAPI.kt index 6f04c5db5b..e72e0c0a33 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/fileserver/FileServerAPI.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/fileserver/FileServerAPI.kt @@ -9,7 +9,6 @@ import org.session.libsignal.utilities.Base64 import org.session.libsignal.utilities.JsonUtil import org.session.libsignal.service.loki.api.onionrequests.OnionRequestAPI import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol -import org.session.libsignal.service.loki.protocol.shelved.multidevice.DeviceLink import org.session.libsignal.service.loki.utilities.* import java.net.URL import java.util.concurrent.ConcurrentHashMap @@ -17,21 +16,6 @@ import java.util.concurrent.ConcurrentHashMap class FileServerAPI(public val server: String, userPublicKey: String, userPrivateKey: ByteArray, private val database: LokiAPIDatabaseProtocol) : DotNetAPI() { companion object { - // region Settings - /** - * Deprecated. - */ - private val deviceLinkType = "network.loki.messenger.devicemapping" - /** - * Deprecated. - */ - private val deviceLinkRequestCache = ConcurrentHashMap, Exception>>() - /** - * Deprecated. - */ - private val deviceLinkUpdateInterval = 60 * 1000 - private val lastDeviceLinkUpdate = ConcurrentHashMap() - internal val fileServerPublicKey = "62509D59BDEEC404DD0D489C1E15BA8F94FD3D619B01C1BF48A9922BFCB7311C" internal val maxRetryCount = 4 @@ -63,172 +47,6 @@ class FileServerAPI(public val server: String, userPublicKey: String, userPrivat // endregion } - // region Device Link Update Result - sealed class DeviceLinkUpdateResult { - class Success(val publicKey: String, val deviceLinks: Set) : DeviceLinkUpdateResult() - class Failure(val publicKey: String, val error: Exception) : DeviceLinkUpdateResult() - } - // endregion - - // region API - public fun hasDeviceLinkCacheExpired(referenceTime: Long = System.currentTimeMillis(), publicKey: String): Boolean { - return !lastDeviceLinkUpdate.containsKey(publicKey) || (referenceTime - lastDeviceLinkUpdate[publicKey]!! > deviceLinkUpdateInterval) - } - - fun getDeviceLinks(publicKey: String, isForcedUpdate: Boolean = false): Promise, Exception> { - return Promise.of(setOf()) - /* - if (deviceLinkRequestCache.containsKey(publicKey) && !isForcedUpdate) { - val result = deviceLinkRequestCache[publicKey] - if (result != null) { return result } // A request was already pending - } - val promise = getDeviceLinks(setOf(publicKey), isForcedUpdate) - deviceLinkRequestCache[publicKey] = promise - promise.always { - deviceLinkRequestCache.remove(publicKey) - } - return promise - */ - } - - fun getDeviceLinks(publicKeys: Set, isForcedUpdate: Boolean = false): Promise, Exception> { - return Promise.of(setOf()) - /* - val validPublicKeys = publicKeys.filter { PublicKeyValidation.isValid(it) } - val now = System.currentTimeMillis() - // IMPORTANT: Don't fetch device links for the current user (i.e. don't remove the it != userHexEncodedPublicKey) check below - val updatees = validPublicKeys.filter { it != userPublicKey && (hasDeviceLinkCacheExpired(now, it) || isForcedUpdate) }.toSet() - val cachedDeviceLinks = validPublicKeys.minus(updatees).flatMap { database.getDeviceLinks(it) }.toSet() - if (updatees.isEmpty()) { - return Promise.of(cachedDeviceLinks) - } else { - return getUserProfiles(updatees, server, true).map(SnodeAPI.sharedContext) { data -> - data.map dataMap@ { node -> - val publicKey = node["username"] as String - val annotations = node["annotations"] as List> - val deviceLinksAnnotation = annotations.find { - annotation -> (annotation["type"] as String) == deviceLinkType - } ?: return@dataMap DeviceLinkUpdateResult.Success(publicKey, setOf()) - val value = deviceLinksAnnotation["value"] as Map<*, *> - val deviceLinksAsJSON = value["authorisations"] as List> - val deviceLinks = deviceLinksAsJSON.mapNotNull { deviceLinkAsJSON -> - try { - val masterPublicKey = deviceLinkAsJSON["primaryDevicePubKey"] as String - val slavePublicKey = deviceLinkAsJSON["secondaryDevicePubKey"] as String - var requestSignature: ByteArray? = null - var authorizationSignature: ByteArray? = null - if (deviceLinkAsJSON["requestSignature"] != null) { - val base64EncodedSignature = deviceLinkAsJSON["requestSignature"] as String - requestSignature = Base64.decode(base64EncodedSignature) - } - if (deviceLinkAsJSON["grantSignature"] != null) { - val base64EncodedSignature = deviceLinkAsJSON["grantSignature"] as String - authorizationSignature = Base64.decode(base64EncodedSignature) - } - val deviceLink = DeviceLink(masterPublicKey, slavePublicKey, requestSignature, authorizationSignature) - val isValid = deviceLink.verify() - if (!isValid) { - Log.d("Loki", "Ignoring invalid device link: $deviceLinkAsJSON.") - return@mapNotNull null - } - deviceLink - } catch (e: Exception) { - Log.d("Loki", "Failed to parse device links for $publicKey from $deviceLinkAsJSON due to error: $e.") - null - } - }.toSet() - DeviceLinkUpdateResult.Success(publicKey, deviceLinks) - } - }.recover { e -> - publicKeys.map { DeviceLinkUpdateResult.Failure(it, e) } - }.success { updateResults -> - for (updateResult in updateResults) { - if (updateResult is DeviceLinkUpdateResult.Success) { - database.clearDeviceLinks(updateResult.publicKey) - updateResult.deviceLinks.forEach { database.addDeviceLink(it) } - } else { - // Do nothing - } - } - }.map(SnodeAPI.sharedContext) { updateResults -> - val deviceLinks = mutableListOf() - for (updateResult in updateResults) { - when (updateResult) { - is DeviceLinkUpdateResult.Success -> { - lastDeviceLinkUpdate[updateResult.publicKey] = now - deviceLinks.addAll(updateResult.deviceLinks) - } - is DeviceLinkUpdateResult.Failure -> { - if (updateResult.error is SnodeAPI.Error.ParsingFailed) { - lastDeviceLinkUpdate[updateResult.publicKey] = now // Don't infinitely update in case of a parsing failure - } - deviceLinks.addAll(database.getDeviceLinks(updateResult.publicKey)) // Fall back on cached device links in case of a failure - } - } - } - // Updatees that didn't show up in the response provided by the file server are assumed to not have any device links - val excludedUpdatees = updatees.filter { updatee -> - updateResults.find { updateResult -> - when (updateResult) { - is DeviceLinkUpdateResult.Success -> updateResult.publicKey == updatee - is DeviceLinkUpdateResult.Failure -> updateResult.publicKey == updatee - } - } == null - } - excludedUpdatees.forEach { - lastDeviceLinkUpdate[it] = now - } - deviceLinks.union(cachedDeviceLinks) - }.recover { - publicKeys.flatMap { database.getDeviceLinks(it) }.toSet() - } - } - */ - } - - fun setDeviceLinks(deviceLinks: Set): Promise { - return Promise.of(Unit) - /* - val isMaster = deviceLinks.find { it.masterPublicKey == userPublicKey } != null - val deviceLinksAsJSON = deviceLinks.map { it.toJSON() } - val value = if (deviceLinks.isNotEmpty()) mapOf( "isPrimary" to isMaster, "authorisations" to deviceLinksAsJSON ) else null - val annotation = mapOf( "type" to deviceLinkType, "value" to value ) - val parameters = mapOf( "annotations" to listOf( annotation ) ) - return retryIfNeeded(maxRetryCount) { - execute(HTTPVerb.PATCH, server, "/users/me", parameters = parameters) - }.map { Unit } - */ - } - - fun addDeviceLink(deviceLink: DeviceLink): Promise { - return Promise.of(Unit) - /* - Log.d("Loki", "Updating device links.") - return getDeviceLinks(userPublicKey, true).bind { deviceLinks -> - val mutableDeviceLinks = deviceLinks.toMutableSet() - mutableDeviceLinks.add(deviceLink) - setDeviceLinks(mutableDeviceLinks) - }.success { - database.addDeviceLink(deviceLink) - }.map { Unit } - */ - } - - fun removeDeviceLink(deviceLink: DeviceLink): Promise { - return Promise.of(Unit) - /* - Log.d("Loki", "Updating device links.") - return getDeviceLinks(userPublicKey, true).bind { deviceLinks -> - val mutableDeviceLinks = deviceLinks.toMutableSet() - mutableDeviceLinks.remove(deviceLink) - setDeviceLinks(mutableDeviceLinks) - }.success { - database.removeDeviceLink(deviceLink) - }.map { Unit } - */ - } - // endregion - // region Open Group Server Public Key fun getPublicKeyForOpenGroupServer(openGroupServer: String): Promise { val publicKey = database.getOpenGroupPublicKey(openGroupServer) diff --git a/libsession/src/main/java/org/session/libsession/messaging/threads/recipients/Recipient.java b/libsession/src/main/java/org/session/libsession/messaging/threads/recipients/Recipient.java index 1c9b48d775..0b385556a1 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/threads/recipients/Recipient.java +++ b/libsession/src/main/java/org/session/libsession/messaging/threads/recipients/Recipient.java @@ -38,7 +38,6 @@ import org.session.libsession.utilities.Util; import org.session.libsession.utilities.color.MaterialColor; import org.session.libsignal.utilities.logging.Log; import org.session.libsignal.libsignal.util.guava.Optional; -import org.session.libsignal.service.loki.protocol.shelved.multidevice.MultiDeviceProtocol; import org.session.libsession.messaging.avatars.ContactColors; import org.session.libsession.messaging.avatars.ContactPhoto; import org.session.libsession.messaging.avatars.GroupRecordContactPhoto; @@ -550,12 +549,7 @@ public class Recipient implements RecipientModifiedListener { } public synchronized boolean isBlocked() { - String masterPublicKey = MultiDeviceProtocol.shared.getMasterDevice(this.address.serialize()); - if (masterPublicKey != null) { - return Recipient.from(context, Address.Companion.fromSerialized(masterPublicKey), false).blocked; - } else { - return blocked; - } + return blocked; } public void setBlocked(boolean blocked) { diff --git a/libsignal/src/main/java/org/session/libsignal/service/api/SignalServiceMessageSender.java b/libsignal/src/main/java/org/session/libsignal/service/api/SignalServiceMessageSender.java index ab402c93ca..6afe4075e7 100644 --- a/libsignal/src/main/java/org/session/libsignal/service/api/SignalServiceMessageSender.java +++ b/libsignal/src/main/java/org/session/libsignal/service/api/SignalServiceMessageSender.java @@ -78,8 +78,6 @@ import org.session.libsignal.service.loki.database.LokiUserDatabaseProtocol; import org.session.libsignal.service.loki.protocol.closedgroups.SharedSenderKeysDatabaseProtocol; import org.session.libsignal.service.loki.protocol.meta.TTLUtilities; import org.session.libsignal.service.loki.protocol.sessionmanagement.SessionManagementProtocol; -import org.session.libsignal.service.loki.protocol.shelved.multidevice.MultiDeviceProtocol; -import org.session.libsignal.service.loki.protocol.shelved.syncmessages.SyncMessagesProtocol; import org.session.libsignal.service.loki.utilities.Broadcaster; import org.session.libsignal.service.loki.utilities.HexEncodingKt; import org.session.libsignal.service.loki.utilities.PlaintextOutputStreamFactory; @@ -248,7 +246,7 @@ public class SignalServiceMessageSender { long timestamp = message.getTimestamp(); boolean useFallbackEncryption = SessionManagementProtocol.shared.shouldMessageUseFallbackEncryption(message, recipient.getNumber(), store); boolean isClosedGroup = message.group.isPresent() && message.group.get().getGroupType() == SignalServiceGroup.GroupType.SIGNAL; - SendMessageResult result = sendMessage(messageID, recipient, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, content, false, message.getTTL(), message.getDeviceLink().isPresent(), useFallbackEncryption, isClosedGroup, message.hasVisibleContent(), message.getSyncTarget()); + SendMessageResult result = sendMessage(messageID, recipient, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, content, false, message.getTTL(), useFallbackEncryption, isClosedGroup, message.hasVisibleContent(), message.getSyncTarget()); // // Loki - This shouldn't get invoked for note to self // boolean wouldSignalSendSyncMessage = (result.getSuccess() != null && result.getSuccess().isNeedsSync()) || unidentifiedAccess.isPresent(); @@ -298,18 +296,6 @@ public class SignalServiceMessageSender { } } - // Loki - This shouldn't get invoked for note to self - if (needsSyncInResults && SyncMessagesProtocol.shared.shouldSyncMessage(message)) { - byte[] syncMessage = createMultiDeviceSentTranscriptContent(content, Optional.absent(), timestamp, results); - // Loki - Customize multi device logic - Set linkedDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(userPublicKey); - for (String device : linkedDevices) { - SignalServiceAddress deviceAsAddress = new SignalServiceAddress(device); - boolean useFallbackEncryption = SessionManagementProtocol.shared.shouldMessageUseFallbackEncryption(syncMessage, device, store); - sendMessage(deviceAsAddress, Optional.absent(), timestamp, syncMessage, false, message.getTTL(), useFallbackEncryption); - } - } - return results; } @@ -341,14 +327,6 @@ public class SignalServiceMessageSender { } else { throw new IOException("Unsupported sync message!"); } - - // Loki - Customize multi device logic - Set linkedDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(userPublicKey); - for (String device : linkedDevices) { - SignalServiceAddress deviceAsAddress = new SignalServiceAddress(device); - boolean useFallbackEncryption = SessionManagementProtocol.shared.shouldMessageUseFallbackEncryption(message, device, store); - sendMessageToPrivateChat(0, deviceAsAddress, Optional.absent(), timestamp, content, false, message.getTTL(), useFallbackEncryption, false, false, Optional.absent()); - } } public void setMessagePipe(SignalServiceMessagePipe pipe, SignalServiceMessagePipe unidentifiedPipe) { @@ -462,10 +440,6 @@ public class SignalServiceMessageSender { builder.setFlags(DataMessage.Flags.PROFILE_KEY_UPDATE_VALUE); } - if (message.isDeviceUnlinkingRequest()) { - builder.setFlags(DataMessage.Flags.DEVICE_UNLINKING_REQUEST_VALUE); - } - if (message.getExpiresInSeconds() > 0) { builder.setExpireTimer(message.getExpiresInSeconds()); } @@ -881,7 +855,7 @@ public class SignalServiceMessageSender { try { boolean useFallbackEncryption = SessionManagementProtocol.shared.shouldMessageUseFallbackEncryption(content, recipient.getNumber(), store); - SendMessageResult result = sendMessage(messageID, recipient, unidentifiedAccessIterator.next(), timestamp, content, online, ttl, false, useFallbackEncryption, isClosedGroup, notifyPNServer, Optional.absent()); + SendMessageResult result = sendMessage(messageID, recipient, unidentifiedAccessIterator.next(), timestamp, content, online, ttl, useFallbackEncryption, isClosedGroup, notifyPNServer, Optional.absent()); results.add(result); } catch (UnregisteredUserException e) { Log.w(TAG, e); @@ -905,7 +879,7 @@ public class SignalServiceMessageSender { throws IOException { // Loki - This method is only invoked for various types of control messages - return sendMessage(0, recipient, unidentifiedAccess, timestamp, content, online, ttl, false, false, useFallbackEncryption, false,Optional.absent()); + return sendMessage(0, recipient, unidentifiedAccess, timestamp, content, online, ttl, false, useFallbackEncryption, false,Optional.absent()); } public SendMessageResult sendMessage(final long messageID, @@ -915,7 +889,6 @@ public class SignalServiceMessageSender { byte[] content, boolean online, int ttl, - boolean isDeviceLinkMessage, boolean useFallbackEncryption, boolean isClosedGroup, boolean notifyPNServer, diff --git a/libsignal/src/main/java/org/session/libsignal/service/api/crypto/SignalServiceCipher.java b/libsignal/src/main/java/org/session/libsignal/service/api/crypto/SignalServiceCipher.java index 51ca336605..153353c2c0 100644 --- a/libsignal/src/main/java/org/session/libsignal/service/api/crypto/SignalServiceCipher.java +++ b/libsignal/src/main/java/org/session/libsignal/service/api/crypto/SignalServiceCipher.java @@ -91,7 +91,6 @@ import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol; import org.session.libsignal.service.loki.protocol.closedgroups.ClosedGroupUtilities; import org.session.libsignal.service.loki.protocol.closedgroups.SharedSenderKeysDatabaseProtocol; import org.session.libsignal.service.loki.protocol.sessionmanagement.PreKeyBundleMessage; -import org.session.libsignal.service.loki.protocol.shelved.multidevice.DeviceLink; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -226,30 +225,6 @@ public class SignalServiceCipher { content.setDataMessage(signalServiceDataMessage); } - return content; - } else if (message.hasDeviceLinkMessage()) { - SignalServiceProtos.DeviceLinkMessage protoDeviceLinkMessage = message.getDeviceLinkMessage(); - String masterPublicKey = protoDeviceLinkMessage.getPrimaryPublicKey(); - String slavePublicKey = protoDeviceLinkMessage.getSecondaryPublicKey(); - byte[] requestSignature = protoDeviceLinkMessage.hasRequestSignature() ? protoDeviceLinkMessage.getRequestSignature().toByteArray() : null; - byte[] authorizationSignature = protoDeviceLinkMessage.hasAuthorizationSignature() ? protoDeviceLinkMessage.getAuthorizationSignature().toByteArray() : null; - DeviceLink deviceLink = new DeviceLink(masterPublicKey, slavePublicKey, requestSignature, authorizationSignature); - SignalServiceCipher.Metadata metadata = plaintext.getMetadata(); - SignalServiceContent content = new SignalServiceContent(deviceLink, metadata.getSender(), metadata.getSenderDevice(), metadata.getTimestamp()); - - content.setPreKeyBundleMessage(preKeyBundleMessage); - - if (message.hasSyncMessage() && message.getSyncMessage().hasContacts()) { - SignalServiceSyncMessage syncMessage = createSynchronizeMessage(metadata, message.getSyncMessage()); - content.setSyncMessage(syncMessage); - } - - if (message.hasDataMessage()) { - setProfile(message.getDataMessage(), content); - SignalServiceDataMessage signalServiceDataMessage = createSignalServiceMessage(metadata, message.getDataMessage()); - content.setDataMessage(signalServiceDataMessage); - } - return content; } else if (message.hasDataMessage()) { DataMessage dataMessage = message.getDataMessage(); @@ -259,8 +234,7 @@ public class SignalServiceCipher { plaintext.getMetadata().getSender(), plaintext.getMetadata().getSenderDevice(), plaintext.getMetadata().getTimestamp(), - plaintext.getMetadata().isNeedsReceipt(), - signalServiceDataMessage.isDeviceUnlinkingRequest()); + plaintext.getMetadata().isNeedsReceipt()); content.setPreKeyBundleMessage(preKeyBundleMessage); @@ -425,10 +399,8 @@ public class SignalServiceCipher { previews, sticker, null, - null, closedGroupUpdate, closedGroupUpdateV2, - isDeviceUnlinkingRequest, syncTarget); } diff --git a/libsignal/src/main/java/org/session/libsignal/service/api/messages/SignalServiceContent.java b/libsignal/src/main/java/org/session/libsignal/service/api/messages/SignalServiceContent.java index 0e978e5954..35d87c99be 100644 --- a/libsignal/src/main/java/org/session/libsignal/service/api/messages/SignalServiceContent.java +++ b/libsignal/src/main/java/org/session/libsignal/service/api/messages/SignalServiceContent.java @@ -7,15 +7,9 @@ package org.session.libsignal.service.api.messages; import org.session.libsignal.libsignal.util.guava.Optional; -import org.session.libsignal.service.api.messages.SignalServiceDataMessage; -import org.session.libsignal.service.api.messages.SignalServiceNullMessage; -import org.session.libsignal.service.api.messages.SignalServiceReceiptMessage; -import org.session.libsignal.service.api.messages.SignalServiceTypingMessage; import org.session.libsignal.service.api.messages.calls.SignalServiceCallMessage; -import org.session.libsignal.service.api.messages.multidevice.ConfigurationMessage; import org.session.libsignal.service.api.messages.multidevice.SignalServiceSyncMessage; import org.session.libsignal.service.internal.push.SignalServiceProtos; -import org.session.libsignal.service.loki.protocol.shelved.multidevice.DeviceLink; import org.session.libsignal.service.loki.protocol.sessionmanagement.PreKeyBundleMessage; public class SignalServiceContent { @@ -25,8 +19,6 @@ public class SignalServiceContent { private final boolean needsReceipt; // Loki - private final boolean isDeviceUnlinkingRequest; - private Optional message; private Optional synchronizeMessage; private final Optional callMessage; @@ -35,13 +27,12 @@ public class SignalServiceContent { private final Optional typingMessage; // Loki - private final Optional deviceLink; public Optional configurationMessageProto = Optional.absent(); public Optional preKeyBundleMessage = Optional.absent(); public Optional senderDisplayName = Optional.absent(); public Optional senderProfilePictureURL = Optional.absent(); - public SignalServiceContent(SignalServiceDataMessage message, String sender, int senderDevice, long timestamp, boolean needsReceipt, boolean isDeviceUnlinkingRequest) { + public SignalServiceContent(SignalServiceDataMessage message, String sender, int senderDevice, long timestamp, boolean needsReceipt) { this.sender = sender; this.senderDevice = senderDevice; this.timestamp = timestamp; @@ -52,8 +43,6 @@ public class SignalServiceContent { this.nullMessage = Optional.absent(); this.readMessage = Optional.absent(); this.typingMessage = Optional.absent(); - this.deviceLink = Optional.absent(); - this.isDeviceUnlinkingRequest = isDeviceUnlinkingRequest; } public SignalServiceContent(SignalServiceSyncMessage synchronizeMessage, String sender, int senderDevice, long timestamp) { @@ -67,8 +56,6 @@ public class SignalServiceContent { this.nullMessage = Optional.absent(); this.readMessage = Optional.absent(); this.typingMessage = Optional.absent(); - this.deviceLink = Optional.absent(); - this.isDeviceUnlinkingRequest = false; } public SignalServiceContent(SignalServiceCallMessage callMessage, String sender, int senderDevice, long timestamp) { @@ -82,8 +69,6 @@ public class SignalServiceContent { this.nullMessage = Optional.absent(); this.readMessage = Optional.absent(); this.typingMessage = Optional.absent(); - this.deviceLink = Optional.absent(); - this.isDeviceUnlinkingRequest = false; } public SignalServiceContent(SignalServiceReceiptMessage receiptMessage, String sender, int senderDevice, long timestamp) { @@ -97,8 +82,6 @@ public class SignalServiceContent { this.nullMessage = Optional.absent(); this.readMessage = Optional.of(receiptMessage); this.typingMessage = Optional.absent(); - this.deviceLink = Optional.absent(); - this.isDeviceUnlinkingRequest = false; } public SignalServiceContent(SignalServiceTypingMessage typingMessage, String sender, int senderDevice, long timestamp) { @@ -112,23 +95,6 @@ public class SignalServiceContent { this.nullMessage = Optional.absent(); this.readMessage = Optional.absent(); this.typingMessage = Optional.of(typingMessage); - this.deviceLink = Optional.absent(); - this.isDeviceUnlinkingRequest = false; - } - - public SignalServiceContent(DeviceLink deviceLink, String sender, int senderDevice, long timestamp) { - this.sender = sender; - this.senderDevice = senderDevice; - this.timestamp = timestamp; - this.needsReceipt = false; - this.message = Optional.absent(); - this.synchronizeMessage = Optional.absent(); - this.callMessage = Optional.absent(); - this.nullMessage = Optional.absent(); - this.readMessage = Optional.absent(); - this.typingMessage = Optional.absent(); - this.deviceLink = Optional.fromNullable(deviceLink); - this.isDeviceUnlinkingRequest = false; } public SignalServiceContent(SignalServiceProtos.Content configurationMessageProto, String sender, int senderDevice, long timestamp) { @@ -142,9 +108,7 @@ public class SignalServiceContent { this.nullMessage = Optional.absent(); this.readMessage = Optional.absent(); this.typingMessage = Optional.absent(); - this.deviceLink = Optional.absent(); this.configurationMessageProto = Optional.fromNullable(configurationMessageProto); - this.isDeviceUnlinkingRequest = false; } public SignalServiceContent(SignalServiceNullMessage nullMessage, String sender, int senderDevice, long timestamp) { @@ -158,8 +122,6 @@ public class SignalServiceContent { this.nullMessage = Optional.of(nullMessage); this.readMessage = Optional.absent(); this.typingMessage = Optional.absent(); - this.deviceLink = Optional.absent(); - this.isDeviceUnlinkingRequest = false; } public Optional getDataMessage() { @@ -203,9 +165,6 @@ public class SignalServiceContent { public Optional getNullMessage() { return nullMessage; } // Loki - public boolean isDeviceUnlinkingRequest() { return isDeviceUnlinkingRequest; } - - public Optional getDeviceLink() { return deviceLink; } public void setPreKeyBundleMessage(PreKeyBundleMessage preKeyBundleMessage) { this.preKeyBundleMessage = Optional.fromNullable(preKeyBundleMessage); } diff --git a/libsignal/src/main/java/org/session/libsignal/service/api/messages/SignalServiceDataMessage.java b/libsignal/src/main/java/org/session/libsignal/service/api/messages/SignalServiceDataMessage.java index 151eac5696..9262a707b7 100644 --- a/libsignal/src/main/java/org/session/libsignal/service/api/messages/SignalServiceDataMessage.java +++ b/libsignal/src/main/java/org/session/libsignal/service/api/messages/SignalServiceDataMessage.java @@ -13,7 +13,6 @@ import org.session.libsignal.service.api.push.SignalServiceAddress; import org.session.libsignal.service.internal.push.SignalServiceProtos.ClosedGroupUpdateV2; import org.session.libsignal.service.internal.push.SignalServiceProtos.ClosedGroupUpdate; import org.session.libsignal.service.loki.protocol.meta.TTLUtilities; -import org.session.libsignal.service.loki.protocol.shelved.multidevice.DeviceLink; import java.util.LinkedList; import java.util.List; @@ -37,10 +36,8 @@ public class SignalServiceDataMessage { private final Optional sticker; // Loki private final Optional preKeyBundle; - private final Optional deviceLink; private final Optional closedGroupUpdate; private final Optional closedGroupUpdateV2; - private final boolean isDeviceUnlinkingRequest; private final Optional syncTarget; /** @@ -135,7 +132,7 @@ public class SignalServiceDataMessage { Quote quote, List sharedContacts, List previews, Sticker sticker) { - this(timestamp, group, attachments, body, endSession, expiresInSeconds, expirationUpdate, profileKey, profileKeyUpdate, quote, sharedContacts, previews, sticker, null, null, null, null, false, null); + this(timestamp, group, attachments, body, endSession, expiresInSeconds, expirationUpdate, profileKey, profileKeyUpdate, quote, sharedContacts, previews, sticker, null, null, null, null); } /** @@ -154,9 +151,9 @@ public class SignalServiceDataMessage { String body, boolean endSession, int expiresInSeconds, boolean expirationUpdate, byte[] profileKey, boolean profileKeyUpdate, Quote quote, List sharedContacts, List previews, - Sticker sticker, PreKeyBundle preKeyBundle, DeviceLink deviceLink, + Sticker sticker, PreKeyBundle preKeyBundle, ClosedGroupUpdate closedGroupUpdate, ClosedGroupUpdateV2 closedGroupUpdateV2, - boolean isDeviceUnlinkingRequest, String syncTarget) + String syncTarget) { this.timestamp = timestamp; this.body = Optional.fromNullable(body); @@ -169,10 +166,8 @@ public class SignalServiceDataMessage { this.quote = Optional.fromNullable(quote); this.sticker = Optional.fromNullable(sticker); this.preKeyBundle = Optional.fromNullable(preKeyBundle); - this.deviceLink = Optional.fromNullable(deviceLink); this.closedGroupUpdate = Optional.fromNullable(closedGroupUpdate); this.closedGroupUpdateV2 = Optional.fromNullable(closedGroupUpdateV2); - this.isDeviceUnlinkingRequest = isDeviceUnlinkingRequest; this.syncTarget = Optional.fromNullable(syncTarget); if (attachments != null && !attachments.isEmpty()) { @@ -273,26 +268,18 @@ public class SignalServiceDataMessage { } // Loki - public boolean isDeviceUnlinkingRequest() { - return isDeviceUnlinkingRequest; - } - public Optional getClosedGroupUpdate() { return closedGroupUpdate; } public Optional getClosedGroupUpdateV2() { return closedGroupUpdateV2; } public Optional getPreKeyBundle() { return preKeyBundle; } - public Optional getDeviceLink() { return deviceLink; } - public boolean hasVisibleContent() { return (body.isPresent() && !body.get().isEmpty()) || (attachments.isPresent() && !attachments.get().isEmpty()); } public int getTTL() { - if (deviceLink.isPresent()) { return TTLUtilities.getTTL(TTLUtilities.MessageType.DeviceLink); } - else if (isDeviceUnlinkingRequest) { return TTLUtilities.getTTL(TTLUtilities.MessageType.DeviceUnlinkingRequest); } return TTLUtilities.getTTL(TTLUtilities.MessageType.Regular); } @@ -312,9 +299,7 @@ public class SignalServiceDataMessage { private Quote quote; private Sticker sticker; private PreKeyBundle preKeyBundle; - private DeviceLink deviceLink; private String syncTarget; - private boolean isDeviceUnlinkingRequest; private Builder() {} @@ -411,25 +396,14 @@ public class SignalServiceDataMessage { return this; } - public Builder withDeviceLink(DeviceLink deviceLink) { - this.deviceLink = deviceLink; - return this; - } - - public Builder asDeviceUnlinkingRequest(boolean isDeviceUnlinkingRequest) { - this.isDeviceUnlinkingRequest = isDeviceUnlinkingRequest; - return this; - } - public SignalServiceDataMessage build() { if (timestamp == 0) timestamp = System.currentTimeMillis(); // closedGroupUpdate is always null because we don't use SignalServiceDataMessage to send them (we use ClosedGroupUpdateMessageSendJob) return new SignalServiceDataMessage(timestamp, group, attachments, body, endSession, expiresInSeconds, expirationUpdate, profileKey, profileKeyUpdate, quote, sharedContacts, previews, - sticker, preKeyBundle, deviceLink, - null, null, - isDeviceUnlinkingRequest, syncTarget); + sticker, preKeyBundle, null, null, + syncTarget); } } diff --git a/libsignal/src/main/java/org/session/libsignal/service/loki/api/fileserver/FileServerAPI.kt b/libsignal/src/main/java/org/session/libsignal/service/loki/api/fileserver/FileServerAPI.kt index 82e04e5a84..2e63a76564 100644 --- a/libsignal/src/main/java/org/session/libsignal/service/loki/api/fileserver/FileServerAPI.kt +++ b/libsignal/src/main/java/org/session/libsignal/service/loki/api/fileserver/FileServerAPI.kt @@ -9,7 +9,6 @@ import org.session.libsignal.utilities.JsonUtil import org.session.libsignal.service.loki.api.LokiDotNetAPI import org.session.libsignal.service.loki.api.onionrequests.OnionRequestAPI import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol -import org.session.libsignal.service.loki.protocol.shelved.multidevice.DeviceLink import org.session.libsignal.service.loki.utilities.* import java.net.URL import java.util.concurrent.ConcurrentHashMap @@ -18,20 +17,6 @@ class FileServerAPI(public val server: String, userPublicKey: String, userPrivat companion object { // region Settings - /** - * Deprecated. - */ - private val deviceLinkType = "network.loki.messenger.devicemapping" - /** - * Deprecated. - */ - private val deviceLinkRequestCache = ConcurrentHashMap, Exception>>() - /** - * Deprecated. - */ - private val deviceLinkUpdateInterval = 60 * 1000 - private val lastDeviceLinkUpdate = ConcurrentHashMap() - internal val fileServerPublicKey = "62509D59BDEEC404DD0D489C1E15BA8F94FD3D619B01C1BF48A9922BFCB7311C" internal val maxRetryCount = 4 @@ -62,172 +47,6 @@ class FileServerAPI(public val server: String, userPublicKey: String, userPrivat // endregion } - // region Device Link Update Result - sealed class DeviceLinkUpdateResult { - class Success(val publicKey: String, val deviceLinks: Set) : DeviceLinkUpdateResult() - class Failure(val publicKey: String, val error: Exception) : DeviceLinkUpdateResult() - } - // endregion - - // region API - public fun hasDeviceLinkCacheExpired(referenceTime: Long = System.currentTimeMillis(), publicKey: String): Boolean { - return !lastDeviceLinkUpdate.containsKey(publicKey) || (referenceTime - lastDeviceLinkUpdate[publicKey]!! > deviceLinkUpdateInterval) - } - - fun getDeviceLinks(publicKey: String, isForcedUpdate: Boolean = false): Promise, Exception> { - return Promise.of(setOf()) - /* - if (deviceLinkRequestCache.containsKey(publicKey) && !isForcedUpdate) { - val result = deviceLinkRequestCache[publicKey] - if (result != null) { return result } // A request was already pending - } - val promise = getDeviceLinks(setOf(publicKey), isForcedUpdate) - deviceLinkRequestCache[publicKey] = promise - promise.always { - deviceLinkRequestCache.remove(publicKey) - } - return promise - */ - } - - fun getDeviceLinks(publicKeys: Set, isForcedUpdate: Boolean = false): Promise, Exception> { - return Promise.of(setOf()) - /* - val validPublicKeys = publicKeys.filter { PublicKeyValidation.isValid(it) } - val now = System.currentTimeMillis() - // IMPORTANT: Don't fetch device links for the current user (i.e. don't remove the it != userHexEncodedPublicKey) check below - val updatees = validPublicKeys.filter { it != userPublicKey && (hasDeviceLinkCacheExpired(now, it) || isForcedUpdate) }.toSet() - val cachedDeviceLinks = validPublicKeys.minus(updatees).flatMap { database.getDeviceLinks(it) }.toSet() - if (updatees.isEmpty()) { - return Promise.of(cachedDeviceLinks) - } else { - return getUserProfiles(updatees, server, true).map(SnodeAPI.sharedContext) { data -> - data.map dataMap@ { node -> - val publicKey = node["username"] as String - val annotations = node["annotations"] as List> - val deviceLinksAnnotation = annotations.find { - annotation -> (annotation["type"] as String) == deviceLinkType - } ?: return@dataMap DeviceLinkUpdateResult.Success(publicKey, setOf()) - val value = deviceLinksAnnotation["value"] as Map<*, *> - val deviceLinksAsJSON = value["authorisations"] as List> - val deviceLinks = deviceLinksAsJSON.mapNotNull { deviceLinkAsJSON -> - try { - val masterPublicKey = deviceLinkAsJSON["primaryDevicePubKey"] as String - val slavePublicKey = deviceLinkAsJSON["secondaryDevicePubKey"] as String - var requestSignature: ByteArray? = null - var authorizationSignature: ByteArray? = null - if (deviceLinkAsJSON["requestSignature"] != null) { - val base64EncodedSignature = deviceLinkAsJSON["requestSignature"] as String - requestSignature = Base64.decode(base64EncodedSignature) - } - if (deviceLinkAsJSON["grantSignature"] != null) { - val base64EncodedSignature = deviceLinkAsJSON["grantSignature"] as String - authorizationSignature = Base64.decode(base64EncodedSignature) - } - val deviceLink = DeviceLink(masterPublicKey, slavePublicKey, requestSignature, authorizationSignature) - val isValid = deviceLink.verify() - if (!isValid) { - Log.d("Loki", "Ignoring invalid device link: $deviceLinkAsJSON.") - return@mapNotNull null - } - deviceLink - } catch (e: Exception) { - Log.d("Loki", "Failed to parse device links for $publicKey from $deviceLinkAsJSON due to error: $e.") - null - } - }.toSet() - DeviceLinkUpdateResult.Success(publicKey, deviceLinks) - } - }.recover { e -> - publicKeys.map { DeviceLinkUpdateResult.Failure(it, e) } - }.success { updateResults -> - for (updateResult in updateResults) { - if (updateResult is DeviceLinkUpdateResult.Success) { - database.clearDeviceLinks(updateResult.publicKey) - updateResult.deviceLinks.forEach { database.addDeviceLink(it) } - } else { - // Do nothing - } - } - }.map(SnodeAPI.sharedContext) { updateResults -> - val deviceLinks = mutableListOf() - for (updateResult in updateResults) { - when (updateResult) { - is DeviceLinkUpdateResult.Success -> { - lastDeviceLinkUpdate[updateResult.publicKey] = now - deviceLinks.addAll(updateResult.deviceLinks) - } - is DeviceLinkUpdateResult.Failure -> { - if (updateResult.error is SnodeAPI.Error.ParsingFailed) { - lastDeviceLinkUpdate[updateResult.publicKey] = now // Don't infinitely update in case of a parsing failure - } - deviceLinks.addAll(database.getDeviceLinks(updateResult.publicKey)) // Fall back on cached device links in case of a failure - } - } - } - // Updatees that didn't show up in the response provided by the file server are assumed to not have any device links - val excludedUpdatees = updatees.filter { updatee -> - updateResults.find { updateResult -> - when (updateResult) { - is DeviceLinkUpdateResult.Success -> updateResult.publicKey == updatee - is DeviceLinkUpdateResult.Failure -> updateResult.publicKey == updatee - } - } == null - } - excludedUpdatees.forEach { - lastDeviceLinkUpdate[it] = now - } - deviceLinks.union(cachedDeviceLinks) - }.recover { - publicKeys.flatMap { database.getDeviceLinks(it) }.toSet() - } - } - */ - } - - fun setDeviceLinks(deviceLinks: Set): Promise { - return Promise.of(Unit) - /* - val isMaster = deviceLinks.find { it.masterPublicKey == userPublicKey } != null - val deviceLinksAsJSON = deviceLinks.map { it.toJSON() } - val value = if (deviceLinks.isNotEmpty()) mapOf( "isPrimary" to isMaster, "authorisations" to deviceLinksAsJSON ) else null - val annotation = mapOf( "type" to deviceLinkType, "value" to value ) - val parameters = mapOf( "annotations" to listOf( annotation ) ) - return retryIfNeeded(maxRetryCount) { - execute(HTTPVerb.PATCH, server, "/users/me", parameters = parameters) - }.map { Unit } - */ - } - - fun addDeviceLink(deviceLink: DeviceLink): Promise { - return Promise.of(Unit) - /* - Log.d("Loki", "Updating device links.") - return getDeviceLinks(userPublicKey, true).bind { deviceLinks -> - val mutableDeviceLinks = deviceLinks.toMutableSet() - mutableDeviceLinks.add(deviceLink) - setDeviceLinks(mutableDeviceLinks) - }.success { - database.addDeviceLink(deviceLink) - }.map { Unit } - */ - } - - fun removeDeviceLink(deviceLink: DeviceLink): Promise { - return Promise.of(Unit) - /* - Log.d("Loki", "Updating device links.") - return getDeviceLinks(userPublicKey, true).bind { deviceLinks -> - val mutableDeviceLinks = deviceLinks.toMutableSet() - mutableDeviceLinks.remove(deviceLink) - setDeviceLinks(mutableDeviceLinks) - }.success { - database.removeDeviceLink(deviceLink) - }.map { Unit } - */ - } - // endregion - // region Open Group Server Public Key fun getPublicKeyForOpenGroupServer(openGroupServer: String): Promise { val publicKey = database.getOpenGroupPublicKey(openGroupServer) diff --git a/libsignal/src/main/java/org/session/libsignal/service/loki/database/LokiAPIDatabaseProtocol.kt b/libsignal/src/main/java/org/session/libsignal/service/loki/database/LokiAPIDatabaseProtocol.kt index 4b5d651e94..07caf9d0d9 100644 --- a/libsignal/src/main/java/org/session/libsignal/service/loki/database/LokiAPIDatabaseProtocol.kt +++ b/libsignal/src/main/java/org/session/libsignal/service/loki/database/LokiAPIDatabaseProtocol.kt @@ -2,7 +2,6 @@ package org.session.libsignal.service.loki.database import org.session.libsignal.libsignal.ecc.ECKeyPair import org.session.libsignal.service.loki.api.Snode -import org.session.libsignal.service.loki.protocol.shelved.multidevice.DeviceLink import java.util.* interface LokiAPIDatabaseProtocol { @@ -38,11 +37,4 @@ interface LokiAPIDatabaseProtocol { fun getUserX25519KeyPair(): ECKeyPair fun getClosedGroupEncryptionKeyPairs(groupPublicKey: String): List fun getLatestClosedGroupEncryptionKeyPair(groupPublicKey: String): ECKeyPair? - - // region Deprecated - fun getDeviceLinks(publicKey: String): Set - fun clearDeviceLinks(publicKey: String) - fun addDeviceLink(deviceLink: DeviceLink) - fun removeDeviceLink(deviceLink: DeviceLink) - // endregion } diff --git a/libsignal/src/main/java/org/session/libsignal/service/loki/protocol/meta/SessionMetaProtocol.kt b/libsignal/src/main/java/org/session/libsignal/service/loki/protocol/meta/SessionMetaProtocol.kt index ecda929f56..5250964973 100644 --- a/libsignal/src/main/java/org/session/libsignal/service/loki/protocol/meta/SessionMetaProtocol.kt +++ b/libsignal/src/main/java/org/session/libsignal/service/loki/protocol/meta/SessionMetaProtocol.kt @@ -1,7 +1,6 @@ package org.session.libsignal.service.loki.protocol.meta import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol -import org.session.libsignal.service.loki.protocol.shelved.multidevice.MultiDeviceProtocol public class SessionMetaProtocol(private val apiDatabase: LokiAPIDatabaseProtocol, private val userPublicKey: String) { diff --git a/libsignal/src/main/java/org/session/libsignal/service/loki/protocol/shelved/multidevice/DeviceLink.kt b/libsignal/src/main/java/org/session/libsignal/service/loki/protocol/shelved/multidevice/DeviceLink.kt deleted file mode 100644 index f14deef4a6..0000000000 --- a/libsignal/src/main/java/org/session/libsignal/service/loki/protocol/shelved/multidevice/DeviceLink.kt +++ /dev/null @@ -1,72 +0,0 @@ -package org.session.libsignal.service.loki.protocol.shelved.multidevice - -import org.whispersystems.curve25519.Curve25519 -import org.session.libsignal.utilities.logging.Log -import org.session.libsignal.utilities.Base64 -import org.session.libsignal.utilities.Hex -import org.session.libsignal.service.loki.utilities.removing05PrefixIfNeeded -import java.util.* - -data class DeviceLink(val masterPublicKey: String, val slavePublicKey: String, val requestSignature: ByteArray?, val authorizationSignature: ByteArray?) { - private val curve = Curve25519.getInstance(Curve25519.BEST) - - val type: Type - get() = when (authorizationSignature) { - null -> Type.REQUEST - else -> Type.AUTHORIZATION - } - - enum class Type(val rawValue: Int) { REQUEST(1), AUTHORIZATION(2) } - - constructor(masterPublicKey: String, slavePublicKey: String) : this(masterPublicKey, slavePublicKey, null, null) - - fun sign(type: Type, privateKey: ByteArray): DeviceLink? { - val target = if (type == Type.REQUEST) masterPublicKey else slavePublicKey - val data = Hex.fromStringCondensed(target) + ByteArray(1) { type.rawValue.toByte() } - try { - val signature = curve.calculateSignature(privateKey, data) - return if (type == Type.REQUEST) copy(requestSignature = signature) else copy(authorizationSignature = signature) - } catch (e: Exception) { - return null - } - } - - fun verify(): Boolean { - if (requestSignature == null && authorizationSignature == null) { return false } - val signature = if (type == Type.REQUEST) requestSignature else authorizationSignature - val issuer = if (type == Type.REQUEST) slavePublicKey else masterPublicKey - val target = if (type == Type.REQUEST) masterPublicKey else slavePublicKey - return try { - val data = Hex.fromStringCondensed(target) + ByteArray(1) { type.rawValue.toByte() } - val issuerPublicKey = Hex.fromStringCondensed(issuer.removing05PrefixIfNeeded()) - curve.verifySignature(issuerPublicKey, data, signature) - } catch (e: Exception) { - Log.w("LOKI", e.message) - false - } - } - - fun toJSON(): Map { - val result = mutableMapOf( "primaryDevicePubKey" to masterPublicKey, "secondaryDevicePubKey" to slavePublicKey ) - if (requestSignature != null) { result["requestSignature"] = Base64.encodeBytes(requestSignature) } - if (authorizationSignature != null) { result["grantSignature"] = Base64.encodeBytes(authorizationSignature) } - return result - } - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other is DeviceLink) { - return (masterPublicKey == other.masterPublicKey && slavePublicKey == other.slavePublicKey - && Arrays.equals(requestSignature, other.requestSignature) && Arrays.equals(authorizationSignature, other.authorizationSignature)) - } else { - return false - } - } - - override fun hashCode(): Int { - var hash = masterPublicKey.hashCode() xor slavePublicKey.hashCode() - if (requestSignature != null) { hash = hash xor Arrays.hashCode(requestSignature) } - if (authorizationSignature != null) { hash = hash xor Arrays.hashCode(authorizationSignature) } - return hash - } -} diff --git a/libsignal/src/main/java/org/session/libsignal/service/loki/protocol/shelved/multidevice/DeviceLinkingSession.kt b/libsignal/src/main/java/org/session/libsignal/service/loki/protocol/shelved/multidevice/DeviceLinkingSession.kt deleted file mode 100644 index 9315c6df48..0000000000 --- a/libsignal/src/main/java/org/session/libsignal/service/loki/protocol/shelved/multidevice/DeviceLinkingSession.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.session.libsignal.service.loki.protocol.shelved.multidevice - -class DeviceLinkingSession { - private val listeners = mutableListOf() - var isListeningForLinkingRequests: Boolean = false - private set - - companion object { - val shared = DeviceLinkingSession() - } - - fun addListener(listener: DeviceLinkingSessionListener) { - listeners.add(listener) - } - - fun removeListener(listener: DeviceLinkingSessionListener) { - listeners.remove(listener) - } - - fun startListeningForLinkingRequests() { - isListeningForLinkingRequests = true - } - - fun stopListeningForLinkingRequests() { - isListeningForLinkingRequests = false - } - - fun processLinkingRequest(deviceLink: DeviceLink) { - if (!isListeningForLinkingRequests || !deviceLink.verify()) { return } - listeners.forEach { it.requestUserAuthorization(deviceLink) } - } - - fun processLinkingAuthorization(deviceLink: DeviceLink) { - if (!isListeningForLinkingRequests || !deviceLink.verify()) { return } - listeners.forEach { it.onDeviceLinkRequestAuthorized(deviceLink) } - } -} diff --git a/libsignal/src/main/java/org/session/libsignal/service/loki/protocol/shelved/multidevice/DeviceLinkingSessionListener.kt b/libsignal/src/main/java/org/session/libsignal/service/loki/protocol/shelved/multidevice/DeviceLinkingSessionListener.kt deleted file mode 100644 index 295af113ea..0000000000 --- a/libsignal/src/main/java/org/session/libsignal/service/loki/protocol/shelved/multidevice/DeviceLinkingSessionListener.kt +++ /dev/null @@ -1,7 +0,0 @@ -package org.session.libsignal.service.loki.protocol.shelved.multidevice - -interface DeviceLinkingSessionListener { - - fun requestUserAuthorization(deviceLink: DeviceLink) { } - fun onDeviceLinkRequestAuthorized(deviceLink: DeviceLink) { } -} diff --git a/libsignal/src/main/java/org/session/libsignal/service/loki/protocol/shelved/multidevice/MultiDeviceProtocol.kt b/libsignal/src/main/java/org/session/libsignal/service/loki/protocol/shelved/multidevice/MultiDeviceProtocol.kt deleted file mode 100644 index 47be30d500..0000000000 --- a/libsignal/src/main/java/org/session/libsignal/service/loki/protocol/shelved/multidevice/MultiDeviceProtocol.kt +++ /dev/null @@ -1,46 +0,0 @@ -package org.session.libsignal.service.loki.protocol.shelved.multidevice - -import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol - -public class MultiDeviceProtocol(private val apiDatabase: LokiAPIDatabaseProtocol) { - - // region Initialization - companion object { - - public lateinit var shared: MultiDeviceProtocol - - public fun configureIfNeeded(apiDatabase: LokiAPIDatabaseProtocol) { - if (Companion::shared.isInitialized) { return; } - shared = MultiDeviceProtocol(apiDatabase) - } - } - // endregion - - // region Utilities - public fun getMasterDevice(publicKey: String): String? { - return null - /* - val deviceLinks = apiDatabase.getDeviceLinks(publicKey) - return deviceLinks.firstOrNull { it.slavePublicKey == publicKey }?.masterPublicKey - */ - } - - public fun getSlaveDevices(publicKey: String): Set { - return setOf() - /* - val deviceLinks = apiDatabase.getDeviceLinks(publicKey) - if (deviceLinks.isEmpty()) { return setOf() } - return deviceLinks.map { it.slavePublicKey }.toSet() - */ - } - - public fun getAllLinkedDevices(publicKey: String): Set { - return setOf( publicKey ) - /* - val deviceLinks = apiDatabase.getDeviceLinks(publicKey) - if (deviceLinks.isEmpty()) { return setOf( publicKey ) } - return deviceLinks.flatMap { listOf( it.masterPublicKey, it.slavePublicKey ) }.toSet() - */ - } - // endregion -} diff --git a/libsignal/src/main/java/org/session/libsignal/service/loki/protocol/shelved/syncmessages/SyncMessagesProtocol.kt b/libsignal/src/main/java/org/session/libsignal/service/loki/protocol/shelved/syncmessages/SyncMessagesProtocol.kt deleted file mode 100644 index f0f0c54865..0000000000 --- a/libsignal/src/main/java/org/session/libsignal/service/loki/protocol/shelved/syncmessages/SyncMessagesProtocol.kt +++ /dev/null @@ -1,36 +0,0 @@ -package org.session.libsignal.service.loki.protocol.shelved.syncmessages - -import org.session.libsignal.service.api.messages.SignalServiceDataMessage -import org.session.libsignal.service.api.messages.SignalServiceGroup -import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol - -public class SyncMessagesProtocol(private val apiDatabase: LokiAPIDatabaseProtocol, private val userPublicKey: String) { - - // region Initialization - companion object { - - public lateinit var shared: SyncMessagesProtocol - - public fun configureIfNeeded(apiDatabase: LokiAPIDatabaseProtocol, userPublicKey: String) { - if (Companion::shared.isInitialized) { return; } - shared = SyncMessagesProtocol(apiDatabase, userPublicKey) - } - } - // endregion - - // region Sending - /** - * Note: This is called only if based on Signal's logic we'd want to send a sync message. - */ - public fun shouldSyncMessage(message: SignalServiceDataMessage): Boolean { - return false - /* - if (message.deviceLink.isPresent) { return false } - val isOpenGroupMessage = message.group.isPresent && message.group.get().groupType == SignalServiceGroup.GroupType.PUBLIC_CHAT - if (isOpenGroupMessage) { return false } - val usesMultiDevice = apiDatabase.getDeviceLinks(userPublicKey).isNotEmpty() - return usesMultiDevice - */ - } - // endregion -}