Fix control messages

This commit is contained in:
andrew
2023-11-28 12:47:27 +10:30
parent 8cc26b8fb6
commit 7bd43b1b3c
18 changed files with 110 additions and 192 deletions

View File

@@ -64,13 +64,11 @@ abstract class Message {
}
expirationTimer = config.expiryMode.expirySeconds.toInt()
lastDisappearingMessageChangeTimestamp = config.updatedTimestampMs
if (ExpirationConfiguration.isNewConfigEnabled) {
config.expiryMode.let { expiryMode ->
when (expiryMode) {
is ExpiryMode.AfterSend -> expirationType = ExpirationType.DELETE_AFTER_SEND
is ExpiryMode.AfterRead -> expirationType = ExpirationType.DELETE_AFTER_READ
is ExpiryMode.Legacy, ExpiryMode.NONE -> { /* do nothing */ }
}
config.expiryMode.let { expiryMode ->
expirationType = when (expiryMode) {
is ExpiryMode.Legacy, is ExpiryMode.AfterSend -> ExpirationType.DELETE_AFTER_SEND
is ExpiryMode.AfterRead -> ExpirationType.DELETE_AFTER_READ
ExpiryMode.NONE -> ExpirationType.UNKNOWN
}
}
return this

View File

@@ -1,5 +1,6 @@
package org.session.libsession.messaging.messages.control
import network.loki.messenger.libsession_util.util.ExpiryMode
import org.session.libsession.messaging.MessagingModuleConfiguration
import org.session.libsession.messaging.messages.ExpirationConfiguration
import org.session.libsession.messaging.messages.visible.VisibleMessage
@@ -10,15 +11,10 @@ import org.session.libsignal.utilities.Log
*
* **Note:** `nil` if this isn't a sync message.
*/
data class ExpirationTimerUpdate(var duration: Int? = 0, var syncTarget: String? = null) : ControlMessage() {
data class ExpirationTimerUpdate(var expiryMode: ExpiryMode, var syncTarget: String? = null) : ControlMessage() {
override val isSelfSendValid: Boolean = true
override fun isValid(): Boolean {
if (!super.isValid()) return false
return duration != null || ExpirationConfiguration.isNewConfigEnabled
}
companion object {
const val TAG = "ExpirationTimerUpdate"
@@ -29,15 +25,22 @@ data class ExpirationTimerUpdate(var duration: Int? = 0, var syncTarget: String?
) != 0
if (!isExpirationTimerUpdate) return null
val syncTarget = dataMessageProto.syncTarget
val duration = if (proto.hasExpirationTimer()) proto.expirationTimer else dataMessageProto.expireTimer
return ExpirationTimerUpdate(duration, syncTarget)
val duration: Int = if (proto.hasExpirationTimer()) proto.expirationTimer else dataMessageProto.expireTimer
val type = proto.expirationType.takeIf { duration > 0 }
val expiryMode = when (type) {
SignalServiceProtos.Content.ExpirationType.DELETE_AFTER_SEND -> ExpiryMode.AfterSend(duration.toLong())
SignalServiceProtos.Content.ExpirationType.DELETE_AFTER_READ -> ExpiryMode.AfterRead(duration.toLong())
else -> ExpiryMode.NONE
}
return ExpirationTimerUpdate(expiryMode, syncTarget)
}
}
override fun toProto(): SignalServiceProtos.Content? {
val dataMessageProto = SignalServiceProtos.DataMessage.newBuilder()
dataMessageProto.flags = SignalServiceProtos.DataMessage.Flags.EXPIRATION_TIMER_UPDATE_VALUE
duration?.let { dataMessageProto.expireTimer = it }
dataMessageProto.expireTimer = expiryMode.expirySeconds.toInt()
// Sync target
if (syncTarget != null) {
dataMessageProto.syncTarget = syncTarget
@@ -53,6 +56,8 @@ data class ExpirationTimerUpdate(var duration: Int? = 0, var syncTarget: String?
}
return try {
SignalServiceProtos.Content.newBuilder().apply {
expirationType
expirationTimer
dataMessage = dataMessageProto.build()
setExpirationConfigurationIfNeeded(threadID)
}.build()

View File

@@ -148,12 +148,14 @@ object MessageReceiver {
VisibleMessage.fromProto(proto) ?: run {
throw Error.UnknownMessage
}
val isUserBlindedSender = sender == openGroupPublicKey?.let { SodiumUtilities.blindedKeyPair(it, MessagingModuleConfiguration.shared.getUserED25519KeyPair()!!) }?.let { SessionId(IdPrefix.BLINDED, it.publicKey.asBytes).hexString }
val isUserSender = sender == userPublicKey
// Ignore self send if needed
if (!message.isSelfSendValid && (sender == userPublicKey || isUserBlindedSender)) {
if (!message.isSelfSendValid && (isUserSender || isUserBlindedSender)) {
throw Error.SelfSend
}
if (sender == userPublicKey || isUserBlindedSender) {
if (isUserSender || isUserBlindedSender) {
message.isSenderSelf = true
}
// Guard against control messages in open groups

View File

@@ -40,7 +40,6 @@ import org.session.libsession.utilities.GroupUtil.doubleEncodeGroupID
import org.session.libsession.utilities.ProfileKeyUtil
import org.session.libsession.utilities.SSKEnvironment
import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsession.utilities.expiryMode
import org.session.libsession.utilities.recipients.Recipient
import org.session.libsignal.crypto.ecc.DjbECPrivateKey
import org.session.libsignal.crypto.ecc.DjbECPublicKey
@@ -156,28 +155,21 @@ fun MessageReceiver.cancelTypingIndicatorsIfNeeded(senderPublicKey: String) {
private fun MessageReceiver.handleExpirationTimerUpdate(message: ExpirationTimerUpdate) {
if (ExpirationConfiguration.isNewConfigEnabled) return
val module = MessagingModuleConfiguration.shared
val recipient = Recipient.from(module.context, Address.fromSerialized(message.sender!!), false)
val type = when {
recipient.isContactRecipient -> ExpiryMode.AfterRead(message.duration!!.toLong())
recipient.isGroupRecipient -> ExpiryMode.AfterSend(message.duration!!.toLong())
else -> ExpiryMode.NONE
}
try {
var threadId: Long = module.storage.getOrCreateThreadIdFor(fromSerialized(message.sender!!))
if (message.groupPublicKey != null) {
threadId = module.storage.getOrCreateThreadIdFor(fromSerialized(doubleEncodeGroupID(message.groupPublicKey!!)))
}
val threadId = fromSerialized(message.groupPublicKey?.let(::doubleEncodeGroupID) ?: message.sender!!)
.let(module.storage::getOrCreateThreadIdFor)
module.storage.setExpirationConfiguration(
ExpirationConfiguration(
threadId,
type,
message.expiryMode,
message.sentTimestamp!!
)
)
} catch (e: Exception) {
Log.e("Loki", "Failed to update expiration configuration.")
}
SSKEnvironment.shared.messageExpirationManager.setExpirationTimer(message, type)
SSKEnvironment.shared.messageExpirationManager.setExpirationTimer(message, message.expiryMode)
}
private fun MessageReceiver.handleDataExtractionNotification(message: DataExtractionNotification) {
@@ -317,10 +309,18 @@ fun MessageReceiver.updateExpiryIfNeeded(
if (message is ExpirationTimerUpdate) {
SSKEnvironment.shared.messageExpirationManager.setExpirationTimer(message, type?.expiryMode(durationSeconds.toLong()))
SSKEnvironment.shared.messageExpirationManager.setExpirationTimer(message, expiryMode)
}
}
private fun SignalServiceProtos.Content.ExpirationType.expiryMode(durationSeconds: Long) = takeIf { durationSeconds > 0 }?.let {
when (it) {
SignalServiceProtos.Content.ExpirationType.DELETE_AFTER_READ -> ExpiryMode.AfterRead(durationSeconds)
SignalServiceProtos.Content.ExpirationType.DELETE_AFTER_SEND, SignalServiceProtos.Content.ExpirationType.UNKNOWN -> ExpiryMode.AfterSend(durationSeconds)
else -> ExpiryMode.NONE
}
} ?: ExpiryMode.NONE
fun MessageReceiver.handleVisibleMessage(
message: VisibleMessage,
proto: SignalServiceProtos.Content,
@@ -583,8 +583,8 @@ private fun MessageReceiver.handleNewClosedGroup(message: ClosedGroupControlMess
val groupPublicKey = kind.publicKey.toByteArray().toHexString()
val members = kind.members.map { it.toByteArray().toHexString() }
val admins = kind.admins.map { it.toByteArray().toHexString() }
val expireTimer = kind.expirationTimer
handleNewClosedGroup(message.sender!!, message.sentTimestamp!!, groupPublicKey, kind.name, kind.encryptionKeyPair!!, members, admins, message.sentTimestamp!!, expireTimer)
val expirationTimer = kind.expirationTimer
handleNewClosedGroup(message.sender!!, message.sentTimestamp!!, groupPublicKey, kind.name, kind.encryptionKeyPair!!, members, admins, message.sentTimestamp!!, expirationTimer)
}
private fun handleNewClosedGroup(sender: String, sentTimestamp: Long, groupPublicKey: String, name: String, encryptionKeyPair: ECKeyPair, members: List<String>, admins: List<String>, formationTimestamp: Long, expireTimer: Int) {

View File

@@ -1,31 +0,0 @@
package org.session.libsession.utilities
import network.loki.messenger.libsession_util.util.ExpiryMode
import org.session.libsignal.protos.SignalServiceProtos
import kotlin.reflect.KClass
fun ExpiryMode?.typeRadioIndex(): Int {
return when (this) {
is ExpiryMode.AfterRead -> SignalServiceProtos.Content.ExpirationType.DELETE_AFTER_READ_VALUE
is ExpiryMode.AfterSend -> SignalServiceProtos.Content.ExpirationType.DELETE_AFTER_SEND_VALUE
is ExpiryMode.Legacy -> SignalServiceProtos.Content.ExpirationType.UNKNOWN_VALUE
else -> -1
}
}
fun SignalServiceProtos.Content.ExpirationType?.expiryMode(durationSeconds: Long): ExpiryMode? = when (this) {
null -> null
SignalServiceProtos.Content.ExpirationType.DELETE_AFTER_READ -> ExpiryMode.AfterRead(durationSeconds)
SignalServiceProtos.Content.ExpirationType.DELETE_AFTER_SEND -> ExpiryMode.AfterSend(durationSeconds)
SignalServiceProtos.Content.ExpirationType.UNKNOWN -> ExpiryMode.Legacy(durationSeconds)
}
fun Int.expiryType(): KClass<out ExpiryMode>? {
if (this == -1) return null
return when (this) {
SignalServiceProtos.Content.ExpirationType.DELETE_AFTER_READ_VALUE -> ExpiryMode.AfterSend::class
SignalServiceProtos.Content.ExpirationType.DELETE_AFTER_SEND_VALUE -> ExpiryMode.AfterRead::class
SignalServiceProtos.Content.ExpirationType.UNKNOWN_VALUE -> ExpiryMode.Legacy::class
else -> ExpiryMode.NONE::class
}
}