mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-27 12:05:22 +00:00
Merge pull request #101 from loki-project/closed-group-sync
Closed group sync
This commit is contained in:
commit
b6d22ae2dc
@ -186,7 +186,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
if (setUpStorageAPIIfNeeded()) {
|
||||
String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||
if (userHexEncodedPublicKey != null) {
|
||||
LokiFileServerAPI.Companion.getShared().getDeviceLinks(userHexEncodedPublicKey, true);
|
||||
if (TextSecurePreferences.getNeedsIsRevokedSlaveDeviceCheck(this)) {
|
||||
MultiDeviceUtilities.checkIsRevokedSlaveDevice(this);
|
||||
}
|
||||
|
@ -206,14 +206,11 @@ public class GroupMessageProcessor {
|
||||
@NonNull GroupRecord record)
|
||||
{
|
||||
String hexEncodedPublicKey = getMasterHexEncodedPublicKey(context, content.getSender());
|
||||
String ourPublicKey = getMasterHexEncodedPublicKey(context, TextSecurePreferences.getLocalNumber(context));
|
||||
// If the requester is a group member and we are admin then we should send them the group update
|
||||
if (record.getMembers().contains(Address.fromSerialized(hexEncodedPublicKey)) && record.getAdmins().contains(Address.fromSerialized(ourPublicKey))) {
|
||||
if (record.getMembers().contains(Address.fromSerialized(hexEncodedPublicKey))) {
|
||||
ApplicationContext.getInstance(context)
|
||||
.getJobManager()
|
||||
.add(new PushGroupUpdateJob(content.getSender(), group.getGroupId()));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -85,18 +85,23 @@ public class MultiDeviceGroupUpdateJob extends BaseJob implements InjectableType
|
||||
reader = DatabaseFactory.getGroupDatabase(context).getGroups();
|
||||
|
||||
while ((record = reader.getNext()) != null) {
|
||||
if (!record.isMms() && !record.isPublicChat() && !record.isRSSFeed()) {
|
||||
if (record.isSignalGroup()) {
|
||||
List<String> members = new LinkedList<>();
|
||||
List<String> admins = new LinkedList<>();
|
||||
|
||||
for (Address member : record.getMembers()) {
|
||||
members.add(member.serialize());
|
||||
}
|
||||
|
||||
for (Address admin : record.getAdmins()) {
|
||||
admins.add(admin.serialize());
|
||||
}
|
||||
|
||||
Recipient recipient = Recipient.from(context, Address.fromSerialized(GroupUtil.getEncodedId(record.getId(), record.isMms())), false);
|
||||
Optional<Integer> expirationTimer = recipient.getExpireMessages() > 0 ? Optional.of(recipient.getExpireMessages()) : Optional.absent();
|
||||
|
||||
out.write(new DeviceGroup(record.getId(), Optional.fromNullable(record.getTitle()),
|
||||
members, getAvatar(record.getAvatar()),
|
||||
members, admins, getAvatar(record.getAvatar()),
|
||||
record.isActive(), expirationTimer,
|
||||
Optional.of(recipient.getColor().serialize()),
|
||||
recipient.isBlocked()));
|
||||
@ -120,7 +125,8 @@ public class MultiDeviceGroupUpdateJob extends BaseJob implements InjectableType
|
||||
|
||||
@Override
|
||||
public boolean onShouldRetry(@NonNull Exception exception) {
|
||||
if (exception instanceof PushNetworkException) return true;
|
||||
// Loki - Disabled because we have our own retrying
|
||||
// if (exception instanceof PushNetworkException) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -139,7 +145,6 @@ public class MultiDeviceGroupUpdateJob extends BaseJob implements InjectableType
|
||||
.withLength(contactsFile.length())
|
||||
.build();
|
||||
|
||||
// TODO: Message ID
|
||||
messageSender.sendMessage(0, SignalServiceSyncMessage.forGroups(attachmentStream),
|
||||
UnidentifiedAccessUtil.getAccessForSync(context));
|
||||
}
|
||||
|
@ -107,6 +107,7 @@ import org.whispersystems.libsignal.state.PreKeyBundle;
|
||||
import org.whispersystems.libsignal.state.SignalProtocolStore;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceContent;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage.Preview;
|
||||
@ -123,6 +124,8 @@ import org.whispersystems.signalservice.api.messages.calls.SignalServiceCallMess
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.ContactsMessage;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.DeviceContact;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.DeviceContactsInputStream;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.DeviceGroup;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.DeviceGroupsInputStream;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.ReadMessage;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.RequestMessage;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.SentTranscriptMessage;
|
||||
@ -389,6 +392,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
else if (syncMessage.getVerified().isPresent()) handleSynchronizeVerifiedMessage(syncMessage.getVerified().get());
|
||||
else if (syncMessage.getStickerPackOperations().isPresent()) handleSynchronizeStickerPackOperation(syncMessage.getStickerPackOperations().get());
|
||||
else if (syncMessage.getContacts().isPresent()) handleContactSyncMessage(syncMessage.getContacts().get());
|
||||
else if (syncMessage.getGroups().isPresent()) handleGroupSyncMessage(content, syncMessage.getGroups().get());
|
||||
else Log.w(TAG, "Contains no known sync types...");
|
||||
} else if (content.getCallMessage().isPresent()) {
|
||||
Log.i(TAG, "Got call message...");
|
||||
@ -719,6 +723,32 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
}
|
||||
}
|
||||
|
||||
private void handleGroupSyncMessage(@NonNull SignalServiceContent content, @NonNull SignalServiceAttachment groupMessage) {
|
||||
if (groupMessage.isStream()) {
|
||||
Log.d("Loki", "Received a group sync message.");
|
||||
try {
|
||||
InputStream in = groupMessage.asStream().getInputStream();
|
||||
DeviceGroupsInputStream groupsInputStream = new DeviceGroupsInputStream(in);
|
||||
List<DeviceGroup> groups = groupsInputStream.readAll();
|
||||
for (DeviceGroup group : groups) {
|
||||
SignalServiceGroup serviceGroup = new SignalServiceGroup(
|
||||
SignalServiceGroup.Type.UPDATE,
|
||||
group.getId(),
|
||||
SignalServiceGroup.GroupType.SIGNAL,
|
||||
group.getName().orNull(),
|
||||
group.getMembers(),
|
||||
group.getAvatar().orNull(),
|
||||
group.getAdmins()
|
||||
);
|
||||
SignalServiceDataMessage dataMessage = new SignalServiceDataMessage(content.getTimestamp(), serviceGroup, null, null);
|
||||
GroupMessageProcessor.process(context, content, dataMessage, false);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.d("Loki", "Failed to sync group due to error: " + e + ".");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleSynchronizeSentMessage(@NonNull SignalServiceContent content,
|
||||
@NonNull SentTranscriptMessage message)
|
||||
throws StorageFailedException
|
||||
|
@ -128,7 +128,7 @@ fun sendDeviceLinkMessage(context: Context, hexEncodedPublicKey: String, deviceL
|
||||
}
|
||||
Promise.ofSuccess(Unit)
|
||||
} catch (e: Exception) {
|
||||
Log.d("Loki", "Failed to send device link message to: $hexEncodedPublicKey.")
|
||||
Log.d("Loki", "Failed to send device link message to: $hexEncodedPublicKey due to error: $e.")
|
||||
Promise.ofFail(e)
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,6 @@ import org.thoughtcrime.securesms.loki.redesign.dialogs.*
|
||||
import org.thoughtcrime.securesms.loki.signAndSendDeviceLinkMessage
|
||||
import org.thoughtcrime.securesms.sms.MessageSender
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.thoughtcrime.securesms.util.Util
|
||||
import org.whispersystems.signalservice.loki.api.DeviceLink
|
||||
import org.whispersystems.signalservice.loki.api.LokiFileServerAPI
|
||||
import java.util.*
|
||||
@ -145,20 +144,19 @@ class LinkedDevicesActivity : PassphraseRequiredActionBarActivity, LoaderManager
|
||||
|
||||
override fun onDeviceLinkRequestAuthorized(deviceLink: DeviceLink) {
|
||||
LokiFileServerAPI.shared.addDeviceLink(deviceLink).success {
|
||||
signAndSendDeviceLinkMessage(this, deviceLink).success {
|
||||
signAndSendDeviceLinkMessage(this, deviceLink).successUi {
|
||||
LoaderManager.getInstance(this).restartLoader(0, null, this)
|
||||
}.success {
|
||||
TextSecurePreferences.setMultiDevice(this, true)
|
||||
Util.runOnMain {
|
||||
LoaderManager.getInstance(this).restartLoader(0, null, this)
|
||||
}
|
||||
Timer().schedule(4000) {
|
||||
MessageSender.syncAllGroups(this@LinkedDevicesActivity)
|
||||
MessageSender.syncAllContacts(this@LinkedDevicesActivity, Address.fromSerialized(deviceLink.slaveHexEncodedPublicKey))
|
||||
}
|
||||
}.failUi {
|
||||
Toast.makeText(this, "Couldn't link device", Toast.LENGTH_LONG).show()
|
||||
}.fail {
|
||||
LokiFileServerAPI.shared.removeDeviceLink(deviceLink) // If this fails we have a problem
|
||||
DatabaseFactory.getLokiPreKeyBundleDatabase(this).removePreKeyBundle(deviceLink.slaveHexEncodedPublicKey)
|
||||
Util.runOnMain {
|
||||
Toast.makeText(this, "Couldn't link device", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
}.failUi {
|
||||
DatabaseFactory.getLokiPreKeyBundleDatabase(this).removePreKeyBundle(deviceLink.slaveHexEncodedPublicKey)
|
||||
|
@ -16,6 +16,7 @@ import org.thoughtcrime.securesms.loki.redesign.utilities.insertOrUpdate
|
||||
import org.thoughtcrime.securesms.util.Base64
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.libsignal.IdentityKey
|
||||
import org.whispersystems.libsignal.InvalidKeyException
|
||||
import org.whispersystems.libsignal.ecc.Curve
|
||||
import org.whispersystems.libsignal.state.PreKeyBundle
|
||||
import org.whispersystems.libsignal.util.KeyHelper
|
||||
@ -41,6 +42,25 @@ class LokiPreKeyBundleDatabase(context: Context, helper: SQLCipherOpenHelper) :
|
||||
}
|
||||
|
||||
fun generatePreKeyBundle(hexEncodedPublicKey: String): PreKeyBundle? {
|
||||
var failureCount = 0
|
||||
while (failureCount < 3) {
|
||||
try {
|
||||
val preKey = generatePreKeyBundle(hexEncodedPublicKey, failureCount > 0) ?: return null
|
||||
// Verify the bundle is correct
|
||||
if (!Curve.verifySignature(preKey.identityKey.publicKey, preKey.signedPreKey.serialize(), preKey.signedPreKeySignature)) {
|
||||
throw InvalidKeyException()
|
||||
}
|
||||
return preKey;
|
||||
} catch (e: InvalidKeyException) {
|
||||
failureCount += 1
|
||||
}
|
||||
}
|
||||
Log.w("Loki", "Failed to generate a valid pre key bundle for: $hexEncodedPublicKey.")
|
||||
return null
|
||||
}
|
||||
|
||||
private fun generatePreKeyBundle(hexEncodedPublicKey: String, forceClean: Boolean): PreKeyBundle? {
|
||||
if (hexEncodedPublicKey.isEmpty()) return null
|
||||
var registrationID = TextSecurePreferences.getLocalRegistrationId(context)
|
||||
if (registrationID == 0) {
|
||||
registrationID = KeyHelper.generateRegistrationId(false)
|
||||
@ -49,7 +69,7 @@ class LokiPreKeyBundleDatabase(context: Context, helper: SQLCipherOpenHelper) :
|
||||
val deviceID = SignalServiceAddress.DEFAULT_DEVICE_ID
|
||||
val preKeyRecord = DatabaseFactory.getLokiPreKeyRecordDatabase(context).getOrCreatePreKeyRecord(hexEncodedPublicKey)
|
||||
val identityKeyPair = IdentityKeyUtil.getIdentityKeyPair(context)
|
||||
if (TextSecurePreferences.isSignedPreKeyRegistered(context)) {
|
||||
if (!forceClean && TextSecurePreferences.isSignedPreKeyRegistered(context)) {
|
||||
Log.d("Loki", "A signed pre key has already been registered.")
|
||||
} else {
|
||||
Log.d("Loki", "Registering a new signed pre key.")
|
||||
|
@ -37,6 +37,7 @@ import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
import org.thoughtcrime.securesms.jobmanager.JobManager;
|
||||
import org.thoughtcrime.securesms.jobs.MmsSendJob;
|
||||
import org.thoughtcrime.securesms.jobs.MultiDeviceContactUpdateJob;
|
||||
import org.thoughtcrime.securesms.jobs.MultiDeviceGroupUpdateJob;
|
||||
import org.thoughtcrime.securesms.jobs.PushGroupSendJob;
|
||||
import org.thoughtcrime.securesms.jobs.PushMediaSendJob;
|
||||
import org.thoughtcrime.securesms.jobs.PushTextSendJob;
|
||||
@ -81,6 +82,10 @@ public class MessageSender {
|
||||
ApplicationContext.getInstance(context).getJobManager().add(new MultiDeviceContactUpdateJob(context, recipient, true));
|
||||
}
|
||||
|
||||
public static void syncAllGroups(Context context) {
|
||||
ApplicationContext.getInstance(context).getJobManager().add(new MultiDeviceGroupUpdateJob());
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a contact sync message to all our devices telling them that we want to sync `contact`
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user