Handle received contact sync message

This commit is contained in:
Mikunj 2019-11-04 16:16:56 +11:00
parent 6f2a6f7f94
commit ce265f29fd
4 changed files with 63 additions and 7 deletions

View File

@ -116,6 +116,9 @@ import org.whispersystems.signalservice.api.messages.calls.HangupMessage;
import org.whispersystems.signalservice.api.messages.calls.IceUpdateMessage; import org.whispersystems.signalservice.api.messages.calls.IceUpdateMessage;
import org.whispersystems.signalservice.api.messages.calls.OfferMessage; import org.whispersystems.signalservice.api.messages.calls.OfferMessage;
import org.whispersystems.signalservice.api.messages.calls.SignalServiceCallMessage; import org.whispersystems.signalservice.api.messages.calls.SignalServiceCallMessage;
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.ReadMessage; import org.whispersystems.signalservice.api.messages.multidevice.ReadMessage;
import org.whispersystems.signalservice.api.messages.multidevice.RequestMessage; import org.whispersystems.signalservice.api.messages.multidevice.RequestMessage;
import org.whispersystems.signalservice.api.messages.multidevice.SentTranscriptMessage; import org.whispersystems.signalservice.api.messages.multidevice.SentTranscriptMessage;
@ -135,6 +138,7 @@ import org.whispersystems.signalservice.loki.messaging.LokiThreadFriendRequestSt
import org.whispersystems.signalservice.loki.messaging.LokiThreadSessionResetStatus; import org.whispersystems.signalservice.loki.messaging.LokiThreadSessionResetStatus;
import org.whispersystems.signalservice.loki.utilities.PromiseUtil; import org.whispersystems.signalservice.loki.utilities.PromiseUtil;
import java.io.IOException;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.util.ArrayList; import java.util.ArrayList;
@ -352,6 +356,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
else if (syncMessage.getRead().isPresent()) handleSynchronizeReadMessage(syncMessage.getRead().get(), content.getTimestamp()); else if (syncMessage.getRead().isPresent()) handleSynchronizeReadMessage(syncMessage.getRead().get(), content.getTimestamp());
else if (syncMessage.getVerified().isPresent()) handleSynchronizeVerifiedMessage(syncMessage.getVerified().get()); else if (syncMessage.getVerified().isPresent()) handleSynchronizeVerifiedMessage(syncMessage.getVerified().get());
else if (syncMessage.getStickerPackOperations().isPresent()) handleSynchronizeStickerPackOperation(syncMessage.getStickerPackOperations().get()); else if (syncMessage.getStickerPackOperations().isPresent()) handleSynchronizeStickerPackOperation(syncMessage.getStickerPackOperations().get());
else if (syncMessage.getContacts().isPresent()) handleSynchronizeContactMessage(syncMessage.getContacts().get());
else Log.w(TAG, "Contains no known sync types..."); else Log.w(TAG, "Contains no known sync types...");
} else if (content.getCallMessage().isPresent()) { } else if (content.getCallMessage().isPresent()) {
Log.i(TAG, "Got call message..."); Log.i(TAG, "Got call message...");
@ -641,6 +646,46 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
} }
} }
private void handleSynchronizeContactMessage(@NonNull ContactsMessage contactsMessage) {
if (contactsMessage.getContactsStream().isStream()) {
try {
DeviceContactsInputStream contactsInputStream = new DeviceContactsInputStream(contactsMessage.getContactsStream().asStream().getInputStream());
DeviceContact deviceContact = contactsInputStream.read();
while (deviceContact != null) {
// Check if we have the contact as a friend
Address address = Address.fromSerialized(deviceContact.getNumber());
if (!address.isPhone()) { continue; }
/*
If we're not friends with the contact we received or our friend request expired then we should send them a friend request
otherwise if we have received a friend request with from them then we should automatically accept the friend request
*/
Recipient recipient = Recipient.from(context, address, false);
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient);
LokiThreadFriendRequestStatus status = DatabaseFactory.getLokiThreadDatabase(context).getFriendRequestStatus(threadId);
if (status == LokiThreadFriendRequestStatus.NONE || status == LokiThreadFriendRequestStatus.REQUEST_EXPIRED) {
MessageSender.sendBackgroundFriendRequest(context, deviceContact.getNumber(), "This is an automated friend request. Still under testing!");
} else if (status == LokiThreadFriendRequestStatus.REQUEST_RECEIVED) {
// Accept the incoming friend request
becomeFriendsWithContact(deviceContact.getNumber());
}
// TODO: Handle blocked - If user is not blocked then we should do the friend request logic otherwise add them to our block list
// TODO: Handle expiration timer - Update expiration timer?
// TODO: Handle avatar - Download and set avatar?
// Read the next contact
deviceContact = contactsInputStream.read();
}
} catch (IOException e) {
// Exception is thrown when we don't have any more contacts to read from
} catch (Exception e) {
Log.d("Loki", "Failed to sync contact: " + e.getMessage());
}
}
}
private void handleSynchronizeSentMessage(@NonNull SignalServiceContent content, private void handleSynchronizeSentMessage(@NonNull SignalServiceContent content,
@NonNull SentTranscriptMessage message) @NonNull SentTranscriptMessage message)
throws StorageFailedException throws StorageFailedException

View File

@ -82,7 +82,7 @@ fun shouldAutomaticallyBecomeFriendsWithDevice(publicKey: String, context: Conte
fun sendPairingAuthorisationMessage(context: Context, contactHexEncodedPublicKey: String, authorisation: PairingAuthorisation): Promise<Unit, Exception> { fun sendPairingAuthorisationMessage(context: Context, contactHexEncodedPublicKey: String, authorisation: PairingAuthorisation): Promise<Unit, Exception> {
val messageSender = ApplicationContext.getInstance(context).communicationModule.provideSignalMessageSender() val messageSender = ApplicationContext.getInstance(context).communicationModule.provideSignalMessageSender()
val address = SignalServiceAddress(contactHexEncodedPublicKey) val address = SignalServiceAddress(contactHexEncodedPublicKey)
val message = SignalServiceDataMessage.newBuilder().withBody("").withPairingAuthorisation(authorisation) val message = SignalServiceDataMessage.newBuilder().withBody(null).withPairingAuthorisation(authorisation)
// A REQUEST should always act as a friend request. A GRANT should always be replying back as a normal message. // A REQUEST should always act as a friend request. A GRANT should always be replying back as a normal message.
if (authorisation.type == PairingAuthorisation.Type.REQUEST) { if (authorisation.type == PairingAuthorisation.Type.REQUEST) {
val preKeyBundle = DatabaseFactory.getLokiPreKeyBundleDatabase(context).generatePreKeyBundle(address.number) val preKeyBundle = DatabaseFactory.getLokiPreKeyBundleDatabase(context).generatePreKeyBundle(address.number)

View File

@ -26,7 +26,7 @@ public class MessageSenderEventListener implements SignalServiceMessageSender.Ev
@Override @Override
public void onSyncEvent(long messageID, long timestamp, byte[] message, int ttl) { public void onSyncEvent(long messageID, long timestamp, byte[] message, int ttl) {
if (messageID > 0 && timestamp > 0 && message != null && ttl > 0) { if (messageID >= 0 && timestamp > 0 && message != null && ttl > 0) {
MessageSender.sendSyncMessageToOurDevices(context, messageID, timestamp, message, ttl); MessageSender.sendSyncMessageToOurDevices(context, messageID, timestamp, message, ttl);
} }
} }

View File

@ -55,6 +55,7 @@ import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.service.ExpiringMessageManager; import org.thoughtcrime.securesms.service.ExpiringMessageManager;
import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.libsignal.state.PreKeyBundle;
import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.SignalServiceAccountManager; import org.whispersystems.signalservice.api.SignalServiceAccountManager;
import org.whispersystems.signalservice.api.SignalServiceMessageSender; import org.whispersystems.signalservice.api.SignalServiceMessageSender;
@ -120,18 +121,28 @@ public class MessageSender {
} }
public static void sendBackgroundMessage(Context context, String contactHexEncodedPublicKey) { public static void sendBackgroundMessage(Context context, String contactHexEncodedPublicKey) {
sendMessageWithBody(context, contactHexEncodedPublicKey, null); SignalServiceDataMessage message = new SignalServiceDataMessage(System.currentTimeMillis(), null);
sendMessage(context, contactHexEncodedPublicKey, message);
} }
public static void sendMessageWithBody(Context context, String contactHexEncodedPublicKey, @Nullable String messageBody) { public static void sendBackgroundFriendRequest(Context context, String contactHexEncodedPublicKey, String messageBody) {
PreKeyBundle bundle = DatabaseFactory.getLokiPreKeyBundleDatabase(context).generatePreKeyBundle(contactHexEncodedPublicKey);
SignalServiceDataMessage message = SignalServiceDataMessage.newBuilder()
.withTimestamp(System.currentTimeMillis())
.withBody(messageBody)
.asFriendRequest(true)
.withPreKeyBundle(bundle)
.build();
sendMessage(context, contactHexEncodedPublicKey, message);
}
private static void sendMessage(Context context, String contactHexEncodedPublicKey, SignalServiceDataMessage message) {
Util.runOnMain(() -> { Util.runOnMain(() -> {
SignalServiceMessageSender messageSender = ApplicationContext.getInstance(context).communicationModule.provideSignalMessageSender(); SignalServiceMessageSender messageSender = ApplicationContext.getInstance(context).communicationModule.provideSignalMessageSender();
SignalServiceAddress address = new SignalServiceAddress(contactHexEncodedPublicKey); SignalServiceAddress address = new SignalServiceAddress(contactHexEncodedPublicKey);
String body = (messageBody == null || messageBody.isEmpty()) ? null : messageBody;
SignalServiceDataMessage message = new SignalServiceDataMessage(System.currentTimeMillis(), body);
try { try {
// Try send to the original person // Try send to the original person
messageSender.sendMessage(0, address, Optional.absent(), message); // The message ID doesn't matter messageSender.sendMessage(-1, address, Optional.absent(), message); // The message ID doesn't matter
} catch (Exception e) { } catch (Exception e) {
Log.d("Loki", "Failed to send background message to: " + contactHexEncodedPublicKey + "."); Log.d("Loki", "Failed to send background message to: " + contactHexEncodedPublicKey + ".");
} }