minor fix for closed group message sending

This commit is contained in:
Ryan ZHAO 2021-02-18 14:40:26 +11:00
parent 9d0831b874
commit 8e5e2fdc49
2 changed files with 34 additions and 27 deletions

View File

@ -16,6 +16,7 @@ import org.session.libsession.messaging.threads.Address;
import org.session.libsession.utilities.GroupUtil; import org.session.libsession.utilities.GroupUtil;
import org.session.libsession.utilities.TextSecurePreferences; import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsignal.service.internal.push.SignalServiceProtos;
import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil; import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
@ -28,6 +29,7 @@ import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.jobmanager.JobManager; import org.thoughtcrime.securesms.jobmanager.JobManager;
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint; import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.session.libsignal.utilities.logging.Log; import org.session.libsignal.utilities.logging.Log;
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocolV2;
import org.thoughtcrime.securesms.mms.MmsException; import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage; import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage; import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
@ -158,7 +160,7 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
if (filterAddress != null) targets = Collections.singletonList(Address.fromSerialized(filterAddress)); if (filterAddress != null) targets = Collections.singletonList(Address.fromSerialized(filterAddress));
else if (!existingNetworkFailures.isEmpty()) targets = Stream.of(existingNetworkFailures).map(NetworkFailure::getAddress).toList(); else if (!existingNetworkFailures.isEmpty()) targets = Stream.of(existingNetworkFailures).map(NetworkFailure::getAddress).toList();
else targets = Collections.singletonList(Address.fromSerialized(message.getRecipient().getAddress().toGroupString())); else targets = ClosedGroupsProtocolV2.getMessageDestinations(context, message.getRecipient().getAddress().toGroupString());
List<SendMessageResult> results = deliver(message, targets); List<SendMessageResult> results = deliver(message, targets);
List<NetworkFailure> networkFailures = Stream.of(results).filter(SendMessageResult::isNetworkFailure).map(result -> new NetworkFailure(Address.fromSerialized(result.getAddress().getNumber()))).toList(); List<NetworkFailure> networkFailures = Stream.of(results).filter(SendMessageResult::isNetworkFailure).map(result -> new NetworkFailure(Address.fromSerialized(result.getAddress().getNumber()))).toList();

View File

@ -65,7 +65,7 @@ object ClosedGroupsProtocolV2 {
// Generate the key pair that'll be used for encryption and decryption // Generate the key pair that'll be used for encryption and decryption
val encryptionKeyPair = Curve.generateKeyPair() val encryptionKeyPair = Curve.generateKeyPair()
// Create the group // Create the group
val groupID = doubleEncodeGroupID(groupPublicKey) val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey)
val admins = setOf( userPublicKey ) val admins = setOf( userPublicKey )
val adminsAsData = admins.map { Hex.fromStringCondensed(it) } val adminsAsData = admins.map { Hex.fromStringCondensed(it) }
DatabaseFactory.getGroupDatabase(context).create(groupID, name, LinkedList(members.map { Address.fromSerialized(it) }), DatabaseFactory.getGroupDatabase(context).create(groupID, name, LinkedList(members.map { Address.fromSerialized(it) }),
@ -102,7 +102,7 @@ object ClosedGroupsProtocolV2 {
val userPublicKey = TextSecurePreferences.getLocalNumber(context)!! val userPublicKey = TextSecurePreferences.getLocalNumber(context)!!
val apiDB = DatabaseFactory.getLokiAPIDatabase(context) val apiDB = DatabaseFactory.getLokiAPIDatabase(context)
val groupDB = DatabaseFactory.getGroupDatabase(context) val groupDB = DatabaseFactory.getGroupDatabase(context)
val groupID = doubleEncodeGroupID(groupPublicKey) val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey)
val group = groupDB.getGroup(groupID).orNull() val group = groupDB.getGroup(groupID).orNull()
val updatedMembers = group.members.map { it.serialize() }.toSet() - userPublicKey val updatedMembers = group.members.map { it.serialize() }.toSet() - userPublicKey
val admins = group.admins.map { it.serialize() } val admins = group.admins.map { it.serialize() }
@ -133,7 +133,7 @@ object ClosedGroupsProtocolV2 {
return task { return task {
val apiDB = DatabaseFactory.getLokiAPIDatabase(context) val apiDB = DatabaseFactory.getLokiAPIDatabase(context)
val groupDB = DatabaseFactory.getGroupDatabase(context) val groupDB = DatabaseFactory.getGroupDatabase(context)
val groupID = doubleEncodeGroupID(groupPublicKey) val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey)
val group = groupDB.getGroup(groupID).orNull() val group = groupDB.getGroup(groupID).orNull()
if (group == null) { if (group == null) {
Log.d("Loki", "Can't leave nonexistent closed group.") Log.d("Loki", "Can't leave nonexistent closed group.")
@ -181,7 +181,7 @@ object ClosedGroupsProtocolV2 {
val userPublicKey = TextSecurePreferences.getLocalNumber(context) val userPublicKey = TextSecurePreferences.getLocalNumber(context)
val apiDB = DatabaseFactory.getLokiAPIDatabase(context) val apiDB = DatabaseFactory.getLokiAPIDatabase(context)
val groupDB = DatabaseFactory.getGroupDatabase(context) val groupDB = DatabaseFactory.getGroupDatabase(context)
val groupID = doubleEncodeGroupID(groupPublicKey) val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey)
val group = groupDB.getGroup(groupID).orNull() val group = groupDB.getGroup(groupID).orNull()
if (group == null) { if (group == null) {
Log.d("Loki", "Can't leave nonexistent closed group.") Log.d("Loki", "Can't leave nonexistent closed group.")
@ -225,7 +225,7 @@ object ClosedGroupsProtocolV2 {
val deferred = deferred<Unit, Exception>() val deferred = deferred<Unit, Exception>()
ThreadUtils.queue { ThreadUtils.queue {
val groupDB = DatabaseFactory.getGroupDatabase(context) val groupDB = DatabaseFactory.getGroupDatabase(context)
val groupID = doubleEncodeGroupID(groupPublicKey) val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey)
val group = groupDB.getGroup(groupID).orNull() val group = groupDB.getGroup(groupID).orNull()
val members = group.members.map { it.serialize() }.toSet() val members = group.members.map { it.serialize() }.toSet()
val admins = group.admins.map { it.serialize() } val admins = group.admins.map { it.serialize() }
@ -254,7 +254,7 @@ object ClosedGroupsProtocolV2 {
fun leave(context: Context, groupPublicKey: String): Promise<Unit, Exception> { fun leave(context: Context, groupPublicKey: String): Promise<Unit, Exception> {
val userPublicKey = TextSecurePreferences.getLocalNumber(context)!! val userPublicKey = TextSecurePreferences.getLocalNumber(context)!!
val groupDB = DatabaseFactory.getGroupDatabase(context) val groupDB = DatabaseFactory.getGroupDatabase(context)
val groupID = doubleEncodeGroupID(groupPublicKey) val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey)
val group = groupDB.getGroup(groupID).orNull() val group = groupDB.getGroup(groupID).orNull()
if (group == null) { if (group == null) {
Log.d("Loki", "Can't leave nonexistent closed group.") Log.d("Loki", "Can't leave nonexistent closed group.")
@ -278,7 +278,7 @@ object ClosedGroupsProtocolV2 {
val userPublicKey = TextSecurePreferences.getLocalNumber(context)!! val userPublicKey = TextSecurePreferences.getLocalNumber(context)!!
val apiDB = DatabaseFactory.getLokiAPIDatabase(context) val apiDB = DatabaseFactory.getLokiAPIDatabase(context)
val groupDB = DatabaseFactory.getGroupDatabase(context) val groupDB = DatabaseFactory.getGroupDatabase(context)
val groupID = doubleEncodeGroupID(groupPublicKey) val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey)
val group = groupDB.getGroup(groupID).orNull() val group = groupDB.getGroup(groupID).orNull()
if (group == null) { if (group == null) {
Log.d("Loki", "Can't update nonexistent closed group.") Log.d("Loki", "Can't update nonexistent closed group.")
@ -359,7 +359,7 @@ object ClosedGroupsProtocolV2 {
val userPublicKey = TextSecurePreferences.getLocalNumber(context) val userPublicKey = TextSecurePreferences.getLocalNumber(context)
val apiDB = DatabaseFactory.getLokiAPIDatabase(context) val apiDB = DatabaseFactory.getLokiAPIDatabase(context)
val groupDB = DatabaseFactory.getGroupDatabase(context) val groupDB = DatabaseFactory.getGroupDatabase(context)
val groupID = doubleEncodeGroupID(groupPublicKey) val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey)
val group = groupDB.getGroup(groupID).orNull() val group = groupDB.getGroup(groupID).orNull()
if (group == null) { if (group == null) {
Log.d("Loki", "Can't update nonexistent closed group.") Log.d("Loki", "Can't update nonexistent closed group.")
@ -454,7 +454,7 @@ object ClosedGroupsProtocolV2 {
val members = closedGroupUpdate.membersList.map { it.toByteArray().toHexString() } val members = closedGroupUpdate.membersList.map { it.toByteArray().toHexString() }
val admins = closedGroupUpdate.adminsList.map { it.toByteArray().toHexString() } val admins = closedGroupUpdate.adminsList.map { it.toByteArray().toHexString() }
// Create the group // Create the group
val groupID = doubleEncodeGroupID(groupPublicKey) val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey)
val groupDB = DatabaseFactory.getGroupDatabase(context) val groupDB = DatabaseFactory.getGroupDatabase(context)
val prevGroup = groupDB.getGroup(groupID).orNull() val prevGroup = groupDB.getGroup(groupID).orNull()
if (prevGroup != null) { if (prevGroup != null) {
@ -486,7 +486,7 @@ object ClosedGroupsProtocolV2 {
fun handleClosedGroupMembersRemoved(context: Context, closedGroupUpdate: SignalServiceProtos.ClosedGroupUpdateV2, sentTimestamp: Long, groupPublicKey: String, senderPublicKey: String) { fun handleClosedGroupMembersRemoved(context: Context, closedGroupUpdate: SignalServiceProtos.ClosedGroupUpdateV2, sentTimestamp: Long, groupPublicKey: String, senderPublicKey: String) {
val apiDB = DatabaseFactory.getLokiAPIDatabase(context) val apiDB = DatabaseFactory.getLokiAPIDatabase(context)
val groupDB = DatabaseFactory.getGroupDatabase(context) val groupDB = DatabaseFactory.getGroupDatabase(context)
val groupID = doubleEncodeGroupID(groupPublicKey) val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey)
val group = groupDB.getGroup(groupID).orNull() val group = groupDB.getGroup(groupID).orNull()
if (group == null || !group.isActive) { if (group == null || !group.isActive) {
Log.d("Loki", "Ignoring closed group info message for nonexistent or inactive group.") Log.d("Loki", "Ignoring closed group info message for nonexistent or inactive group.")
@ -540,7 +540,7 @@ object ClosedGroupsProtocolV2 {
val userPublicKey = TextSecurePreferences.getLocalNumber(context) val userPublicKey = TextSecurePreferences.getLocalNumber(context)
val apiDB = DatabaseFactory.getLokiAPIDatabase(context) val apiDB = DatabaseFactory.getLokiAPIDatabase(context)
val groupDB = DatabaseFactory.getGroupDatabase(context) val groupDB = DatabaseFactory.getGroupDatabase(context)
val groupID = doubleEncodeGroupID(groupPublicKey) val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey)
val group = groupDB.getGroup(groupID).orNull() val group = groupDB.getGroup(groupID).orNull()
if (group == null || !group.isActive) { if (group == null || !group.isActive) {
Log.d("Loki", "Ignoring closed group info message for nonexistent or inactive group.") Log.d("Loki", "Ignoring closed group info message for nonexistent or inactive group.")
@ -582,7 +582,7 @@ object ClosedGroupsProtocolV2 {
// Check that the sender is a member of the group (before the update) // Check that the sender is a member of the group (before the update)
val userPublicKey = TextSecurePreferences.getLocalNumber(context) val userPublicKey = TextSecurePreferences.getLocalNumber(context)
val groupDB = DatabaseFactory.getGroupDatabase(context) val groupDB = DatabaseFactory.getGroupDatabase(context)
val groupID = doubleEncodeGroupID(groupPublicKey) val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey)
val group = groupDB.getGroup(groupID).orNull() val group = groupDB.getGroup(groupID).orNull()
if (group == null || !group.isActive) { if (group == null || !group.isActive) {
Log.d("Loki", "Ignoring closed group info message for nonexistent or inactive group.") Log.d("Loki", "Ignoring closed group info message for nonexistent or inactive group.")
@ -610,7 +610,7 @@ object ClosedGroupsProtocolV2 {
val userPublicKey = TextSecurePreferences.getLocalNumber(context)!! val userPublicKey = TextSecurePreferences.getLocalNumber(context)!!
val apiDB = DatabaseFactory.getLokiAPIDatabase(context) val apiDB = DatabaseFactory.getLokiAPIDatabase(context)
val groupDB = DatabaseFactory.getGroupDatabase(context) val groupDB = DatabaseFactory.getGroupDatabase(context)
val groupID = doubleEncodeGroupID(groupPublicKey) val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey)
val group = groupDB.getGroup(groupID).orNull() val group = groupDB.getGroup(groupID).orNull()
if (group == null || !group.isActive) { if (group == null || !group.isActive) {
Log.d("Loki", "Ignoring closed group info message for nonexistent or inactive group.") Log.d("Loki", "Ignoring closed group info message for nonexistent or inactive group.")
@ -654,7 +654,7 @@ object ClosedGroupsProtocolV2 {
val name = closedGroupUpdate.name val name = closedGroupUpdate.name
val members = closedGroupUpdate.membersList.map { it.toByteArray().toHexString() } val members = closedGroupUpdate.membersList.map { it.toByteArray().toHexString() }
val groupDB = DatabaseFactory.getGroupDatabase(context) val groupDB = DatabaseFactory.getGroupDatabase(context)
val groupID = doubleEncodeGroupID(groupPublicKey) val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey)
val group = groupDB.getGroup(groupID).orNull() val group = groupDB.getGroup(groupID).orNull()
if (group == null || !group.isActive) { if (group == null || !group.isActive) {
Log.d("Loki", "Ignoring closed group info message for nonexistent or inactive group.") Log.d("Loki", "Ignoring closed group info message for nonexistent or inactive group.")
@ -735,7 +735,7 @@ object ClosedGroupsProtocolV2 {
val userKeyPair = apiDB.getUserX25519KeyPair() val userKeyPair = apiDB.getUserX25519KeyPair()
// Unwrap the message // Unwrap the message
val groupDB = DatabaseFactory.getGroupDatabase(context) val groupDB = DatabaseFactory.getGroupDatabase(context)
val groupID = doubleEncodeGroupID(groupPublicKey) val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey)
val group = groupDB.getGroup(groupID).orNull() val group = groupDB.getGroup(groupID).orNull()
if (group == null) { if (group == null) {
Log.d("Loki", "Ignoring closed group encryption key pair message for nonexistent group.") Log.d("Loki", "Ignoring closed group encryption key pair message for nonexistent group.")
@ -791,17 +791,22 @@ object ClosedGroupsProtocolV2 {
mmsDB.markAsSent(infoMessageID, true) mmsDB.markAsSent(infoMessageID, true)
} }
// NOTE: Signal group ID handling is weird. The ID is double encoded in the database, but not in a `GroupContext`.
@JvmStatic @JvmStatic
@Throws(IOException::class) fun getMessageDestinations(context: Context, groupID: String): List<Address> {
public fun doubleEncodeGroupID(groupPublicKey: String): String { return if (GroupUtil.isOpenGroup(groupID)) {
return GroupUtil.getEncodedClosedGroupID(GroupUtil.getEncodedClosedGroupID(Hex.fromStringCondensed(groupPublicKey)).toByteArray()) listOf(Address.fromSerialized(groupID))
} else {
var groupPublicKey: String? = null
try {
groupPublicKey = GroupUtil.doubleDecodeGroupID(groupID).toHexString()
} catch (exception: Exception) {
// Do nothing
}
if (groupPublicKey != null && DatabaseFactory.getLokiAPIDatabase(context).isClosedGroup(groupPublicKey)) {
listOf(Address.fromSerialized(groupPublicKey))
} else {
DatabaseFactory.getGroupDatabase(context).getGroupMembers(groupID, false).map { it.address }
}
} }
@JvmStatic
@Throws(IOException::class)
public fun doubleDecodeGroupID(groupID: String): ByteArray {
return GroupUtil.getDecodedGroupIDAsData(GroupUtil.getDecodedGroupID(groupID))
} }
} }