fix duplicated closed group info message

This commit is contained in:
Ryan ZHAO 2021-03-11 15:31:14 +11:00
parent d7124c3b7e
commit 2859da01a7
4 changed files with 38 additions and 21 deletions

View File

@ -391,7 +391,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
DatabaseFactory.getGroupDatabase(context).updateMembers(groupID, members) DatabaseFactory.getGroupDatabase(context).updateMembers(groupID, members)
} }
override fun insertIncomingInfoMessage(context: Context, senderPublicKey: String, groupID: String, type0: SignalServiceProtos.GroupContext.Type, type1: SignalServiceGroup.Type, name: String, members: Collection<String>, admins: Collection<String>) { override fun insertIncomingInfoMessage(context: Context, senderPublicKey: String, groupID: String, type0: SignalServiceProtos.GroupContext.Type, type1: SignalServiceGroup.Type, name: String, members: Collection<String>, admins: Collection<String>, sentTimestamp: Long) {
val groupContextBuilder = SignalServiceProtos.GroupContext.newBuilder() val groupContextBuilder = SignalServiceProtos.GroupContext.newBuilder()
.setId(ByteString.copyFrom(GroupUtil.getDecodedGroupIDAsData(groupID))) .setId(ByteString.copyFrom(GroupUtil.getDecodedGroupIDAsData(groupID)))
.setType(type0) .setType(type0)
@ -399,13 +399,14 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
.addAllMembers(members) .addAllMembers(members)
.addAllAdmins(admins) .addAllAdmins(admins)
val group = SignalServiceGroup(type1, GroupUtil.getDecodedGroupIDAsData(groupID), SignalServiceGroup.GroupType.SIGNAL, name, members.toList(), null, admins.toList()) val group = SignalServiceGroup(type1, GroupUtil.getDecodedGroupIDAsData(groupID), SignalServiceGroup.GroupType.SIGNAL, name, members.toList(), null, admins.toList())
val m = IncomingTextMessage(Address.fromSerialized(senderPublicKey), 1, System.currentTimeMillis(), "", Optional.of(group), 0, true) val m = IncomingTextMessage(Address.fromSerialized(senderPublicKey), 1, sentTimestamp, "", Optional.of(group), 0, true)
val infoMessage = IncomingGroupMessage(m, groupContextBuilder.build(), "") val infoMessage = IncomingGroupMessage(m, groupContextBuilder.build(), "")
val smsDB = DatabaseFactory.getSmsDatabase(context) val smsDB = DatabaseFactory.getSmsDatabase(context)
smsDB.insertMessageInbox(infoMessage) smsDB.insertMessageInbox(infoMessage)
} }
override fun insertOutgoingInfoMessage(context: Context, groupID: String, type: SignalServiceProtos.GroupContext.Type, name: String, members: Collection<String>, admins: Collection<String>, threadID: Long) { override fun insertOutgoingInfoMessage(context: Context, groupID: String, type: SignalServiceProtos.GroupContext.Type, name: String, members: Collection<String>, admins: Collection<String>, threadID: Long, sentTimestamp: Long) {
val userPublicKey = getUserPublicKey()
val recipient = Recipient.from(context, Address.fromSerialized(groupID), false) val recipient = Recipient.from(context, Address.fromSerialized(groupID), false)
val groupContextBuilder = SignalServiceProtos.GroupContext.newBuilder() val groupContextBuilder = SignalServiceProtos.GroupContext.newBuilder()
.setId(ByteString.copyFrom(GroupUtil.getDecodedGroupIDAsData(groupID))) .setId(ByteString.copyFrom(GroupUtil.getDecodedGroupIDAsData(groupID)))
@ -413,8 +414,10 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
.setName(name) .setName(name)
.addAllMembers(members) .addAllMembers(members)
.addAllAdmins(admins) .addAllAdmins(admins)
val infoMessage = OutgoingGroupMediaMessage(recipient, groupContextBuilder.build(), null, 0, null, listOf(), listOf()) val infoMessage = OutgoingGroupMediaMessage(recipient, groupContextBuilder.build(), null, sentTimestamp, 0, null, listOf(), listOf())
val mmsDB = DatabaseFactory.getMmsDatabase(context) val mmsDB = DatabaseFactory.getMmsDatabase(context)
val mmsSmsDB = DatabaseFactory.getMmsSmsDatabase(context)
if (mmsSmsDB.getMessageFor(sentTimestamp,userPublicKey) != null) return
val infoMessageID = mmsDB.insertMessageOutbox(infoMessage, threadID, false, null) val infoMessageID = mmsDB.insertMessageOutbox(infoMessage, threadID, false, null)
mmsDB.markAsSent(infoMessageID, true) mmsDB.markAsSent(infoMessageID, true)
} }

View File

@ -113,9 +113,9 @@ interface StorageProtocol {
fun addClosedGroupEncryptionKeyPair(encryptionKeyPair: ECKeyPair, groupPublicKey: String) fun addClosedGroupEncryptionKeyPair(encryptionKeyPair: ECKeyPair, groupPublicKey: String)
fun removeAllClosedGroupEncryptionKeyPairs(groupPublicKey: String) fun removeAllClosedGroupEncryptionKeyPairs(groupPublicKey: String)
fun insertIncomingInfoMessage(context: Context, senderPublicKey: String, groupID: String, type0: SignalServiceProtos.GroupContext.Type, type1: SignalServiceGroup.Type, fun insertIncomingInfoMessage(context: Context, senderPublicKey: String, groupID: String, type0: SignalServiceProtos.GroupContext.Type, type1: SignalServiceGroup.Type,
name: String, members: Collection<String>, admins: Collection<String>) name: String, members: Collection<String>, admins: Collection<String>, sentTimestamp: Long)
fun insertOutgoingInfoMessage(context: Context, groupID: String, type: SignalServiceProtos.GroupContext.Type, name: String, fun insertOutgoingInfoMessage(context: Context, groupID: String, type: SignalServiceProtos.GroupContext.Type, name: String,
members: Collection<String>, admins: Collection<String>, threadID: Long) members: Collection<String>, admins: Collection<String>, threadID: Long, sentTimestamp: Long)
fun isClosedGroup(publicKey: String): Boolean fun isClosedGroup(publicKey: String): Boolean
fun getClosedGroupEncryptionKeyPairs(groupPublicKey: String): MutableList<ECKeyPair> fun getClosedGroupEncryptionKeyPairs(groupPublicKey: String): MutableList<ECKeyPair>
fun getLatestClosedGroupEncryptionKeyPair(groupPublicKey: String): ECKeyPair? fun getLatestClosedGroupEncryptionKeyPair(groupPublicKey: String): ECKeyPair?

View File

@ -110,7 +110,7 @@ private fun MessageReceiver.handleConfigurationMessage(message: ConfigurationMes
val allClosedGroupPublicKeys = storage.getAllClosedGroupPublicKeys() val allClosedGroupPublicKeys = storage.getAllClosedGroupPublicKeys()
for (closeGroup in message.closedGroups) { for (closeGroup in message.closedGroups) {
if (allClosedGroupPublicKeys.contains(closeGroup.publicKey)) continue if (allClosedGroupPublicKeys.contains(closeGroup.publicKey)) continue
handleNewClosedGroup(message.sender!!, closeGroup.publicKey, closeGroup.name, closeGroup.encryptionKeyPair, closeGroup.members, closeGroup.admins, message.sentTimestamp!!) handleNewClosedGroup(message.sender!!, message.sentTimestamp!!, closeGroup.publicKey, closeGroup.name, closeGroup.encryptionKeyPair, closeGroup.members, closeGroup.admins, message.sentTimestamp!!)
} }
val allOpenGroups = storage.getAllOpenGroups().map { it.value.server } val allOpenGroups = storage.getAllOpenGroups().map { it.value.server }
for (openGroup in message.openGroups) { for (openGroup in message.openGroups) {
@ -222,11 +222,11 @@ private fun MessageReceiver.handleNewClosedGroup(message: ClosedGroupControlMess
val groupPublicKey = kind.publicKey.toByteArray().toHexString() val groupPublicKey = kind.publicKey.toByteArray().toHexString()
val members = kind.members.map { it.toByteArray().toHexString() } val members = kind.members.map { it.toByteArray().toHexString() }
val admins = kind.admins.map { it.toByteArray().toHexString() } val admins = kind.admins.map { it.toByteArray().toHexString() }
handleNewClosedGroup(message.sender!!, groupPublicKey, kind.name, kind.encryptionKeyPair, members, admins, message.sentTimestamp!!) handleNewClosedGroup(message.sender!!, message.sentTimestamp!!, groupPublicKey, kind.name, kind.encryptionKeyPair, members, admins, message.sentTimestamp!!)
} }
// Parameter @sender:String is just for inserting incoming info message // Parameter @sender:String is just for inserting incoming info message
private fun handleNewClosedGroup(sender: String, groupPublicKey: String, name: String, encryptionKeyPair: ECKeyPair, members: List<String>, admins: List<String>, formationTimestamp: Long) { private fun handleNewClosedGroup(sender: String, sentTimestamp: Long, groupPublicKey: String, name: String, encryptionKeyPair: ECKeyPair, members: List<String>, admins: List<String>, formationTimestamp: Long) {
val context = MessagingConfiguration.shared.context val context = MessagingConfiguration.shared.context
val storage = MessagingConfiguration.shared.storage val storage = MessagingConfiguration.shared.storage
// Create the group // Create the group
@ -239,7 +239,7 @@ private fun handleNewClosedGroup(sender: String, groupPublicKey: String, name: S
storage.createGroup(groupID, name, LinkedList(members.map { Address.fromSerialized(it) }), storage.createGroup(groupID, name, LinkedList(members.map { Address.fromSerialized(it) }),
null, null, LinkedList(admins.map { Address.fromSerialized(it) }), formationTimestamp) null, null, LinkedList(admins.map { Address.fromSerialized(it) }), formationTimestamp)
// Notify the user // Notify the user
storage.insertIncomingInfoMessage(context, sender, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, SignalServiceGroup.Type.UPDATE, name, members, admins) storage.insertIncomingInfoMessage(context, sender, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, SignalServiceGroup.Type.UPDATE, name, members, admins, sentTimestamp)
} }
storage.setProfileSharing(Address.fromSerialized(groupID), true) storage.setProfileSharing(Address.fromSerialized(groupID), true)
// Add the group to the user's set of public keys to poll for // Add the group to the user's set of public keys to poll for
@ -297,7 +297,7 @@ private fun MessageReceiver.handleClosedGroupUpdated(message: ClosedGroupControl
val wasSenderRemoved = !members.contains(senderPublicKey) val wasSenderRemoved = !members.contains(senderPublicKey)
val type0 = if (wasSenderRemoved) SignalServiceProtos.GroupContext.Type.QUIT else SignalServiceProtos.GroupContext.Type.UPDATE val type0 = if (wasSenderRemoved) SignalServiceProtos.GroupContext.Type.QUIT else SignalServiceProtos.GroupContext.Type.UPDATE
val type1 = if (wasSenderRemoved) SignalServiceGroup.Type.QUIT else SignalServiceGroup.Type.UPDATE val type1 = if (wasSenderRemoved) SignalServiceGroup.Type.QUIT else SignalServiceGroup.Type.UPDATE
storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, type0, type1, name, members, group.admins.map { it.toString() }) storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, type0, type1, name, members, group.admins.map { it.toString() }, message.sentTimestamp!!)
} }
private fun MessageReceiver.handleClosedGroupEncryptionKeyPair(message: ClosedGroupControlMessage) { private fun MessageReceiver.handleClosedGroupEncryptionKeyPair(message: ClosedGroupControlMessage) {
@ -356,7 +356,7 @@ private fun MessageReceiver.handleClosedGroupNameChanged(message: ClosedGroupCon
val name = kind.name val name = kind.name
storage.updateTitle(groupID, name) storage.updateTitle(groupID, name)
storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, SignalServiceGroup.Type.UPDATE, name, members, admins) storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, SignalServiceGroup.Type.UPDATE, name, members, admins, message.sentTimestamp!!)
} }
private fun MessageReceiver.handleClosedGroupMembersAdded(message: ClosedGroupControlMessage) { private fun MessageReceiver.handleClosedGroupMembersAdded(message: ClosedGroupControlMessage) {
@ -388,7 +388,7 @@ private fun MessageReceiver.handleClosedGroupMembersAdded(message: ClosedGroupCo
MessageSender.sendLatestEncryptionKeyPair(member, groupPublicKey) MessageSender.sendLatestEncryptionKeyPair(member, groupPublicKey)
} }
} }
storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, SignalServiceGroup.Type.UPDATE, name, members, admins) storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, SignalServiceGroup.Type.UPDATE, name, members, admins, message.sentTimestamp!!)
} }
private fun MessageReceiver.handleClosedGroupMembersRemoved(message: ClosedGroupControlMessage) { private fun MessageReceiver.handleClosedGroupMembersRemoved(message: ClosedGroupControlMessage) {
@ -437,7 +437,7 @@ private fun MessageReceiver.handleClosedGroupMembersRemoved(message: ClosedGroup
if (senderLeft) SignalServiceProtos.GroupContext.Type.QUIT to SignalServiceGroup.Type.QUIT if (senderLeft) SignalServiceProtos.GroupContext.Type.QUIT to SignalServiceGroup.Type.QUIT
else SignalServiceProtos.GroupContext.Type.UPDATE to SignalServiceGroup.Type.UPDATE else SignalServiceProtos.GroupContext.Type.UPDATE to SignalServiceGroup.Type.UPDATE
storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, contextType, signalType, name, members, admins) storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, contextType, signalType, name, members, admins, message.sentTimestamp!!)
} }
private fun MessageReceiver.handleClosedGroupMemberLeft(message: ClosedGroupControlMessage) { private fun MessageReceiver.handleClosedGroupMemberLeft(message: ClosedGroupControlMessage) {
@ -472,7 +472,7 @@ private fun MessageReceiver.handleClosedGroupMemberLeft(message: ClosedGroupCont
MessageSender.generateAndSendNewEncryptionKeyPair(groupPublicKey, updatedMemberList) MessageSender.generateAndSendNewEncryptionKeyPair(groupPublicKey, updatedMemberList)
} }
} }
storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceProtos.GroupContext.Type.QUIT, SignalServiceGroup.Type.QUIT, name, members, admins) storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceProtos.GroupContext.Type.QUIT, SignalServiceGroup.Type.QUIT, name, members, admins, message.sentTimestamp!!)
} }
private fun MessageReceiver.handleClosedGroupEncryptionKeyPairRequest(message: ClosedGroupControlMessage) { private fun MessageReceiver.handleClosedGroupEncryptionKeyPairRequest(message: ClosedGroupControlMessage) {

View File

@ -62,7 +62,7 @@ fun MessageSender.create(name: String, members: Collection<String>): Promise<Str
storage.addClosedGroupEncryptionKeyPair(encryptionKeyPair, groupPublicKey) storage.addClosedGroupEncryptionKeyPair(encryptionKeyPair, groupPublicKey)
// Notify the user // Notify the user
val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID)) val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID))
storage.insertOutgoingInfoMessage(context, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, name, members, admins, threadID) storage.insertOutgoingInfoMessage(context, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, name, members, admins, threadID, sentTime)
// Notify the PN server // Notify the PN server
PushNotificationAPI.performOperation(PushNotificationAPI.ClosedGroupOperation.Subscribe, groupPublicKey, userPublicKey) PushNotificationAPI.performOperation(PushNotificationAPI.ClosedGroupOperation.Subscribe, groupPublicKey, userPublicKey)
// Fulfill the promise // Fulfill the promise
@ -102,14 +102,16 @@ fun MessageSender.setName(groupPublicKey: String, newName: String) {
val admins = group.admins.map { it.serialize() } val admins = group.admins.map { it.serialize() }
// Send the update to the group // Send the update to the group
val kind = ClosedGroupControlMessage.Kind.NameChange(newName) val kind = ClosedGroupControlMessage.Kind.NameChange(newName)
val sentTime = System.currentTimeMillis()
val closedGroupControlMessage = ClosedGroupControlMessage(kind) val closedGroupControlMessage = ClosedGroupControlMessage(kind)
closedGroupControlMessage.sentTimestamp = sentTime
send(closedGroupControlMessage, Address.fromSerialized(groupID)) send(closedGroupControlMessage, Address.fromSerialized(groupID))
// Update the group // Update the group
storage.updateTitle(groupID, newName) storage.updateTitle(groupID, newName)
// Notify the user // Notify the user
val infoType = SignalServiceProtos.GroupContext.Type.UPDATE val infoType = SignalServiceProtos.GroupContext.Type.UPDATE
val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID)) val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID))
storage.insertOutgoingInfoMessage(context, groupID, infoType, newName, members, admins, threadID) storage.insertOutgoingInfoMessage(context, groupID, infoType, newName, members, admins, threadID, sentTime)
} }
fun MessageSender.addMembers(groupPublicKey: String, membersToAdd: List<String>) { fun MessageSender.addMembers(groupPublicKey: String, membersToAdd: List<String>) {
@ -138,18 +140,21 @@ fun MessageSender.addMembers(groupPublicKey: String, membersToAdd: List<String>)
val name = group.title val name = group.title
// Send the update to the group // Send the update to the group
val memberUpdateKind = ClosedGroupControlMessage.Kind.MembersAdded(newMembersAsData) val memberUpdateKind = ClosedGroupControlMessage.Kind.MembersAdded(newMembersAsData)
val sentTime = System.currentTimeMillis()
val closedGroupControlMessage = ClosedGroupControlMessage(memberUpdateKind) val closedGroupControlMessage = ClosedGroupControlMessage(memberUpdateKind)
closedGroupControlMessage.sentTimestamp = sentTime
send(closedGroupControlMessage, Address.fromSerialized(groupID)) send(closedGroupControlMessage, Address.fromSerialized(groupID))
// Send closed group update messages to any new members individually // Send closed group update messages to any new members individually
for (member in membersToAdd) { for (member in membersToAdd) {
val closedGroupNewKind = ClosedGroupControlMessage.Kind.New(ByteString.copyFrom(Hex.fromStringCondensed(groupPublicKey)), name, encryptionKeyPair, membersAsData, adminsAsData) val closedGroupNewKind = ClosedGroupControlMessage.Kind.New(ByteString.copyFrom(Hex.fromStringCondensed(groupPublicKey)), name, encryptionKeyPair, membersAsData, adminsAsData)
val closedGroupControlMessage = ClosedGroupControlMessage(closedGroupNewKind) val closedGroupControlMessage = ClosedGroupControlMessage(closedGroupNewKind)
closedGroupControlMessage.sentTimestamp = sentTime
send(closedGroupControlMessage, Address.fromSerialized(member)) send(closedGroupControlMessage, Address.fromSerialized(member))
} }
// Notify the user // Notify the user
val infoType = SignalServiceProtos.GroupContext.Type.UPDATE val infoType = SignalServiceProtos.GroupContext.Type.UPDATE
val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID)) val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID))
storage.insertOutgoingInfoMessage(context, groupID, infoType, name, updatedMembers, admins, threadID) storage.insertOutgoingInfoMessage(context, groupID, infoType, name, updatedMembers, admins, threadID, sentTime)
} }
fun MessageSender.removeMembers(groupPublicKey: String, membersToRemove: List<String>) { fun MessageSender.removeMembers(groupPublicKey: String, membersToRemove: List<String>) {
@ -177,7 +182,9 @@ fun MessageSender.removeMembers(groupPublicKey: String, membersToRemove: List<St
val name = group.title val name = group.title
// Send the update to the group // Send the update to the group
val memberUpdateKind = ClosedGroupControlMessage.Kind.MembersRemoved(removeMembersAsData) val memberUpdateKind = ClosedGroupControlMessage.Kind.MembersRemoved(removeMembersAsData)
val sentTime = System.currentTimeMillis()
val closedGroupControlMessage = ClosedGroupControlMessage(memberUpdateKind) val closedGroupControlMessage = ClosedGroupControlMessage(memberUpdateKind)
closedGroupControlMessage.sentTimestamp = sentTime
send(closedGroupControlMessage, Address.fromSerialized(groupID)) send(closedGroupControlMessage, Address.fromSerialized(groupID))
val isCurrentUserAdmin = admins.contains(userPublicKey) val isCurrentUserAdmin = admins.contains(userPublicKey)
if (isCurrentUserAdmin) { if (isCurrentUserAdmin) {
@ -186,7 +193,7 @@ fun MessageSender.removeMembers(groupPublicKey: String, membersToRemove: List<St
// Notify the user // Notify the user
val infoType = SignalServiceProtos.GroupContext.Type.UPDATE val infoType = SignalServiceProtos.GroupContext.Type.UPDATE
val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID)) val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID))
storage.insertOutgoingInfoMessage(context, groupID, infoType, name, updatedMembers, admins, threadID) storage.insertOutgoingInfoMessage(context, groupID, infoType, name, updatedMembers, admins, threadID, sentTime)
} }
fun MessageSender.leave(groupPublicKey: String, notifyUser: Boolean = true): Promise<Unit, Exception> { fun MessageSender.leave(groupPublicKey: String, notifyUser: Boolean = true): Promise<Unit, Exception> {
@ -202,13 +209,14 @@ fun MessageSender.leave(groupPublicKey: String, notifyUser: Boolean = true): Pro
val name = group.title val name = group.title
// Send the update to the group // Send the update to the group
val closedGroupControlMessage = ClosedGroupControlMessage(ClosedGroupControlMessage.Kind.MemberLeft()) val closedGroupControlMessage = ClosedGroupControlMessage(ClosedGroupControlMessage.Kind.MemberLeft())
closedGroupControlMessage.sentTimestamp = System.currentTimeMillis() val sentTime = System.currentTimeMillis()
closedGroupControlMessage.sentTimestamp = sentTime
sendNonDurably(closedGroupControlMessage, Address.fromSerialized(groupID)).success { sendNonDurably(closedGroupControlMessage, Address.fromSerialized(groupID)).success {
// Notify the user // Notify the user
val infoType = SignalServiceProtos.GroupContext.Type.QUIT val infoType = SignalServiceProtos.GroupContext.Type.QUIT
val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID)) val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID))
if (notifyUser) { if (notifyUser) {
storage.insertOutgoingInfoMessage(context, groupID, infoType, name, updatedMembers, admins, threadID) storage.insertOutgoingInfoMessage(context, groupID, infoType, name, updatedMembers, admins, threadID, sentTime)
} }
// Remove the group private key and unsubscribe from PNs // Remove the group private key and unsubscribe from PNs
MessageReceiver.disableLocalGroupAndUnsubscribe(groupPublicKey, groupID, userPublicKey) MessageReceiver.disableLocalGroupAndUnsubscribe(groupPublicKey, groupID, userPublicKey)
@ -248,7 +256,9 @@ fun MessageSender.generateAndSendNewEncryptionKeyPair(groupPublicKey: String, ta
ClosedGroupControlMessage.KeyPairWrapper(publicKey, ByteString.copyFrom(ciphertext)) ClosedGroupControlMessage.KeyPairWrapper(publicKey, ByteString.copyFrom(ciphertext))
} }
val kind = ClosedGroupControlMessage.Kind.EncryptionKeyPair(null, wrappers) val kind = ClosedGroupControlMessage.Kind.EncryptionKeyPair(null, wrappers)
val sentTime = System.currentTimeMillis()
val closedGroupControlMessage = ClosedGroupControlMessage(kind) val closedGroupControlMessage = ClosedGroupControlMessage(kind)
closedGroupControlMessage.sentTimestamp = sentTime
sendNonDurably(closedGroupControlMessage, Address.fromSerialized(groupID)).success { sendNonDurably(closedGroupControlMessage, Address.fromSerialized(groupID)).success {
// Store it * after * having sent out the message to the group // Store it * after * having sent out the message to the group
storage.addClosedGroupEncryptionKeyPair(newKeyPair, groupPublicKey) storage.addClosedGroupEncryptionKeyPair(newKeyPair, groupPublicKey)
@ -267,7 +277,9 @@ fun MessageSender.requestEncryptionKeyPair(groupPublicKey: String) {
val members = group.members.map { it.serialize() }.toSet() val members = group.members.map { it.serialize() }.toSet()
if (!members.contains(storage.getUserPublicKey()!!)) return if (!members.contains(storage.getUserPublicKey()!!)) return
// Send the request to the group // Send the request to the group
val sentTime = System.currentTimeMillis()
val closedGroupControlMessage = ClosedGroupControlMessage(ClosedGroupControlMessage.Kind.EncryptionKeyPairRequest()) val closedGroupControlMessage = ClosedGroupControlMessage(ClosedGroupControlMessage.Kind.EncryptionKeyPairRequest())
closedGroupControlMessage.sentTimestamp = sentTime
send(closedGroupControlMessage, Address.fromSerialized(groupID)) send(closedGroupControlMessage, Address.fromSerialized(groupID))
} }
@ -295,6 +307,8 @@ fun MessageSender.sendLatestEncryptionKeyPair(publicKey: String, groupPublicKey:
Log.d("Loki", "Sending latest encryption key pair to: $publicKey.") Log.d("Loki", "Sending latest encryption key pair to: $publicKey.")
val wrapper = ClosedGroupControlMessage.KeyPairWrapper(publicKey, ByteString.copyFrom(ciphertext)) val wrapper = ClosedGroupControlMessage.KeyPairWrapper(publicKey, ByteString.copyFrom(ciphertext))
val kind = ClosedGroupControlMessage.Kind.EncryptionKeyPair(ByteString.copyFrom(Hex.fromStringCondensed(groupPublicKey)), listOf(wrapper)) val kind = ClosedGroupControlMessage.Kind.EncryptionKeyPair(ByteString.copyFrom(Hex.fromStringCondensed(groupPublicKey)), listOf(wrapper))
val sentTime = System.currentTimeMillis()
val closedGroupControlMessage = ClosedGroupControlMessage(kind) val closedGroupControlMessage = ClosedGroupControlMessage(kind)
closedGroupControlMessage.sentTimestamp = sentTime
MessageSender.send(closedGroupControlMessage, Address.fromSerialized(publicKey)) MessageSender.send(closedGroupControlMessage, Address.fromSerialized(publicKey))
} }