From a3e3f0047ac53dd12b4433729d2f19c726729931 Mon Sep 17 00:00:00 2001 From: Ryan ZHAO Date: Thu, 11 Mar 2021 10:23:16 +1100 Subject: [PATCH] fix closed group message sending & expiration mistakenly disabled --- .../libsession/messaging/messages/Message.kt | 10 ++++++++ .../control/ClosedGroupControlMessage.kt | 24 +++++++++++-------- .../messages/control/ExpirationTimerUpdate.kt | 12 ++++++++++ .../messages/visible/VisibleMessage.kt | 22 ++++++++++++++++- 4 files changed, 57 insertions(+), 11 deletions(-) diff --git a/libsession/src/main/java/org/session/libsession/messaging/messages/Message.kt b/libsession/src/main/java/org/session/libsession/messaging/messages/Message.kt index 9944e53cec..6f2a916351 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/messages/Message.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/messages/Message.kt @@ -1,5 +1,7 @@ package org.session.libsession.messaging.messages +import com.google.protobuf.ByteString +import org.session.libsession.utilities.GroupUtil import org.session.libsignal.service.internal.push.SignalServiceProtos abstract class Message { @@ -29,4 +31,12 @@ abstract class Message { abstract fun toProto(): SignalServiceProtos.Content? + fun setGroupContext(dataMessage: SignalServiceProtos.DataMessage.Builder) { + val groupProto = SignalServiceProtos.GroupContext.newBuilder() + val groupID = GroupUtil.doubleEncodeGroupID(recipient!!) + groupProto.id = ByteString.copyFrom(GroupUtil.getDecodedGroupIDAsData(groupID)) + groupProto.type = SignalServiceProtos.GroupContext.Type.DELIVER + dataMessage.group = groupProto.build() + } + } \ No newline at end of file diff --git a/libsession/src/main/java/org/session/libsession/messaging/messages/control/ClosedGroupControlMessage.kt b/libsession/src/main/java/org/session/libsession/messaging/messages/control/ClosedGroupControlMessage.kt index 4affd25f2f..bad3ad566f 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/messages/control/ClosedGroupControlMessage.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/messages/control/ClosedGroupControlMessage.kt @@ -1,12 +1,17 @@ package org.session.libsession.messaging.messages.control import com.google.protobuf.ByteString +import org.session.libsession.messaging.MessagingConfiguration +import org.session.libsession.messaging.threads.Address +import org.session.libsession.messaging.threads.recipients.Recipient +import org.session.libsession.utilities.GroupUtil import org.session.libsignal.libsignal.ecc.DjbECPrivateKey import org.session.libsignal.libsignal.ecc.DjbECPublicKey import org.session.libsignal.libsignal.ecc.ECKeyPair import org.session.libsignal.utilities.logging.Log import org.session.libsignal.service.internal.push.SignalServiceProtos import org.session.libsignal.service.internal.push.SignalServiceProtos.DataMessage +import org.session.libsignal.service.loki.utilities.removing05PrefixIfNeeded import org.session.libsignal.service.loki.utilities.toHexString import org.session.libsignal.utilities.Hex @@ -139,16 +144,10 @@ class ClosedGroupControlMessage() : ControlMessage() { closedGroupControlMessage.type = DataMessage.ClosedGroupControlMessage.Type.NEW closedGroupControlMessage.publicKey = kind.publicKey closedGroupControlMessage.name = kind.name - val encryptionKeyPairAsProto = SignalServiceProtos.KeyPair.newBuilder() - encryptionKeyPairAsProto.publicKey = ByteString.copyFrom(kind.encryptionKeyPair.publicKey.serialize()) - encryptionKeyPairAsProto.privateKey = ByteString.copyFrom(kind.encryptionKeyPair.privateKey.serialize()) - - try { - closedGroupControlMessage.encryptionKeyPair = encryptionKeyPairAsProto.build() - } catch (e: Exception) { - Log.w(TAG, "Couldn't construct closed group update proto from: $this") - return null - } + val encryptionKeyPair = SignalServiceProtos.KeyPair.newBuilder() + encryptionKeyPair.publicKey = ByteString.copyFrom(kind.encryptionKeyPair.publicKey.serialize().removing05PrefixIfNeeded()) + encryptionKeyPair.privateKey = ByteString.copyFrom(kind.encryptionKeyPair.privateKey.serialize()) + closedGroupControlMessage.encryptionKeyPair = encryptionKeyPair.build() closedGroupControlMessage.addAllMembers(kind.members) closedGroupControlMessage.addAllAdmins(kind.admins) } @@ -185,6 +184,11 @@ class ClosedGroupControlMessage() : ControlMessage() { val dataMessageProto = DataMessage.newBuilder() dataMessageProto.closedGroupControlMessage = closedGroupControlMessage.build() // Group context + setGroupContext(dataMessageProto) + // Expiration timer + // TODO: We * want * expiration timer updates to be explicit. But currently Android will disable the expiration timer for a conversation + // if it receives a message without the current expiration timer value attached to it... + dataMessageProto.expireTimer = Recipient.from(MessagingConfiguration.shared.context, Address.fromSerialized(GroupUtil.doubleEncodeGroupID(recipient!!)), false).expireMessages contentProto.dataMessage = dataMessageProto.build() return contentProto.build() } catch (e: Exception) { diff --git a/libsession/src/main/java/org/session/libsession/messaging/messages/control/ExpirationTimerUpdate.kt b/libsession/src/main/java/org/session/libsession/messaging/messages/control/ExpirationTimerUpdate.kt index a1c8e6b775..2571b103d4 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/messages/control/ExpirationTimerUpdate.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/messages/control/ExpirationTimerUpdate.kt @@ -1,5 +1,7 @@ package org.session.libsession.messaging.messages.control +import org.session.libsession.messaging.MessagingConfiguration +import org.session.libsession.messaging.messages.visible.VisibleMessage import org.session.libsignal.utilities.logging.Log import org.session.libsignal.service.internal.push.SignalServiceProtos @@ -40,6 +42,16 @@ class ExpirationTimerUpdate() : ControlMessage() { val dataMessageProto = SignalServiceProtos.DataMessage.newBuilder() dataMessageProto.flags = SignalServiceProtos.DataMessage.Flags.EXPIRATION_TIMER_UPDATE_VALUE dataMessageProto.expireTimer = duration + syncTarget?.let { dataMessageProto.syncTarget = it } + // Group context + if (MessagingConfiguration.shared.storage.isClosedGroup(recipient!!)) { + try { + setGroupContext(dataMessageProto) + } catch(e: Exception) { + Log.w(VisibleMessage.TAG, "Couldn't construct visible message proto from: $this") + return null + } + } val contentProto = SignalServiceProtos.Content.newBuilder() try { contentProto.dataMessage = dataMessageProto.build() diff --git a/libsession/src/main/java/org/session/libsession/messaging/messages/visible/VisibleMessage.kt b/libsession/src/main/java/org/session/libsession/messaging/messages/visible/VisibleMessage.kt index d353886eec..edb908e35c 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/messages/visible/VisibleMessage.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/messages/visible/VisibleMessage.kt @@ -4,6 +4,9 @@ import com.goterl.lazycode.lazysodium.BuildConfig import org.session.libsession.messaging.MessagingConfiguration import org.session.libsession.messaging.messages.Message import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment +import org.session.libsession.messaging.threads.Address +import org.session.libsession.messaging.threads.recipients.Recipient +import org.session.libsession.utilities.GroupUtil import org.session.libsignal.service.internal.push.SignalServiceProtos import org.session.libsignal.utilities.logging.Log import org.session.libsession.messaging.sending_receiving.attachments.Attachment as SignalAttachment @@ -102,11 +105,28 @@ class VisibleMessage : Message() { } val attachmentPointers = attachments.mapNotNull { Attachment.createAttachmentPointer(it) } dataMessage.addAllAttachments(attachmentPointers) + // TODO Contact + // Expiration timer + // TODO: We * want * expiration timer updates to be explicit. But currently Android will disable the expiration timer for a conversation + // if it receives a message without the current expiration timer value attached to it... + val storage = MessagingConfiguration.shared.storage + val context = MessagingConfiguration.shared.context + val expiration = if (storage.isClosedGroup(recipient!!)) Recipient.from(context, Address.fromSerialized(GroupUtil.doubleEncodeGroupID(recipient!!)), false).expireMessages + else Recipient.from(context, Address.fromSerialized(recipient!!), false).expireMessages + dataMessage.expireTimer = expiration + // Group context + if (storage.isClosedGroup(recipient!!)) { + try { + setGroupContext(dataMessage) + } catch(e: Exception) { + Log.w(TAG, "Couldn't construct visible message proto from: $this") + return null + } + } // Sync target if (syncTarget != null) { dataMessage.syncTarget = syncTarget } - // TODO Contact // Build try { proto.dataMessage = dataMessage.build()