]> nmode's Git Repositories - signal-cli/blobdiff - src/main/java/org/asamk/signal/Manager.java
Handle received sync messages
[signal-cli] / src / main / java / org / asamk / signal / Manager.java
index 94bb555af37c0b8e191a9b0b6dfdf6ec181e41e3..2fc54504ad4121ad450346a7ae08a33dc030eec9 100644 (file)
@@ -37,10 +37,13 @@ import org.whispersystems.signalservice.api.SignalServiceAccountManager;
 import org.whispersystems.signalservice.api.SignalServiceMessagePipe;
 import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
 import org.whispersystems.signalservice.api.SignalServiceMessageSender;
-import org.whispersystems.signalservice.api.crypto.SignalServiceCipher;
+import org.whispersystems.signalservice.api.crypto.*;
+import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
 import org.whispersystems.signalservice.api.messages.*;
+import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
 import org.whispersystems.signalservice.api.push.SignalServiceAddress;
 import org.whispersystems.signalservice.api.push.TrustStore;
+import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException;
 import org.whispersystems.signalservice.api.push.exceptions.EncapsulatedExceptions;
 import org.whispersystems.signalservice.api.util.InvalidNumberException;
 import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
@@ -58,7 +61,10 @@ class Manager implements Signal {
 
     public final static String PROJECT_NAME = Manager.class.getPackage().getImplementationTitle();
     public final static String PROJECT_VERSION = Manager.class.getPackage().getImplementationVersion();
-    private final static String USER_AGENT = PROJECT_NAME + " " + PROJECT_VERSION;
+    private final static String USER_AGENT = PROJECT_NAME == null ? null : PROJECT_NAME + " " + PROJECT_VERSION;
+
+    private final static int PREKEY_MINIMUM_COUNT = 20;
+    private static final int PREKEY_BATCH_SIZE = 100;
 
     private final String settingsPath;
     private final String dataPath;
@@ -140,6 +146,14 @@ class Manager implements Signal {
             groupStore = new JsonGroupStore();
         }
         accountManager = new SignalServiceAccountManager(URL, TRUST_STORE, username, password, USER_AGENT);
+        try {
+            if (registered && accountManager.getPreKeysCount() < PREKEY_MINIMUM_COUNT) {
+                refreshPreKeys();
+                save();
+            }
+        } catch (AuthorizationFailedException e) {
+            System.err.println("Authorization failed, was the number registered elsewhere?");
+        }
     }
 
     private void save() {
@@ -187,12 +201,10 @@ class Manager implements Signal {
         save();
     }
 
-    private static final int BATCH_SIZE = 100;
-
     private List<PreKeyRecord> generatePreKeys() {
         List<PreKeyRecord> records = new LinkedList<>();
 
-        for (int i = 0; i < BATCH_SIZE; i++) {
+        for (int i = 0; i < PREKEY_BATCH_SIZE; i++) {
             int preKeyId = (preKeyIdOffset + i) % Medium.MAX_VALUE;
             ECKeyPair keyPair = Curve.generateKeyPair();
             PreKeyRecord record = new PreKeyRecord(preKeyId, keyPair);
@@ -201,13 +213,13 @@ class Manager implements Signal {
             records.add(record);
         }
 
-        preKeyIdOffset = (preKeyIdOffset + BATCH_SIZE + 1) % Medium.MAX_VALUE;
+        preKeyIdOffset = (preKeyIdOffset + PREKEY_BATCH_SIZE + 1) % Medium.MAX_VALUE;
         save();
 
         return records;
     }
 
-    private PreKeyRecord generateLastResortPreKey() {
+    private PreKeyRecord getOrGenerateLastResortPreKey() {
         if (signalProtocolStore.containsPreKey(Medium.MAX_VALUE)) {
             try {
                 return signalProtocolStore.loadPreKey(Medium.MAX_VALUE);
@@ -249,14 +261,16 @@ class Manager implements Signal {
         //accountManager.setGcmId(Optional.of(GoogleCloudMessaging.getInstance(this).register(REGISTRATION_ID)));
         registered = true;
 
-        List<PreKeyRecord> oneTimePreKeys = generatePreKeys();
-
-        PreKeyRecord lastResortKey = generateLastResortPreKey();
+        refreshPreKeys();
+        save();
+    }
 
+    private void refreshPreKeys() throws IOException {
+        List<PreKeyRecord> oneTimePreKeys = generatePreKeys();
+        PreKeyRecord lastResortKey = getOrGenerateLastResortPreKey();
         SignedPreKeyRecord signedPreKeyRecord = generateSignedPreKey(signalProtocolStore.getIdentityKeyPair());
 
         accountManager.setPreKeys(signalProtocolStore.getIdentityKeyPair().getPublicKey(), lastResortKey, signedPreKeyRecord, oneTimePreKeys);
-        save();
     }
 
 
@@ -441,6 +455,73 @@ class Manager implements Signal {
         void handleMessage(SignalServiceEnvelope envelope, SignalServiceContent decryptedContent, GroupInfo group);
     }
 
+    private GroupInfo handleSignalServiceDataMessage(SignalServiceDataMessage message, boolean isSync, String source, String destination) {
+        GroupInfo group = null;
+        if (message.getGroupInfo().isPresent()) {
+            SignalServiceGroup groupInfo = message.getGroupInfo().get();
+            switch (groupInfo.getType()) {
+                case UPDATE:
+                    try {
+                        group = groupStore.getGroup(groupInfo.getGroupId());
+                    } catch (GroupNotFoundException e) {
+                        group = new GroupInfo(groupInfo.getGroupId());
+                    }
+
+                    if (groupInfo.getAvatar().isPresent()) {
+                        SignalServiceAttachment avatar = groupInfo.getAvatar().get();
+                        if (avatar.isPointer()) {
+                            long avatarId = avatar.asPointer().getId();
+                            try {
+                                retrieveAttachment(avatar.asPointer());
+                                group.avatarId = avatarId;
+                            } catch (IOException | InvalidMessageException e) {
+                                System.err.println("Failed to retrieve group avatar (" + avatarId + "): " + e.getMessage());
+                            }
+                        }
+                    }
+
+                    if (groupInfo.getName().isPresent()) {
+                        group.name = groupInfo.getName().get();
+                    }
+
+                    if (groupInfo.getMembers().isPresent()) {
+                        group.members.addAll(groupInfo.getMembers().get());
+                    }
+
+                    groupStore.updateGroup(group);
+                    break;
+                case DELIVER:
+                    try {
+                        group = groupStore.getGroup(groupInfo.getGroupId());
+                    } catch (GroupNotFoundException e) {
+                    }
+                    break;
+                case QUIT:
+                    try {
+                        group = groupStore.getGroup(groupInfo.getGroupId());
+                        group.members.remove(source);
+                    } catch (GroupNotFoundException e) {
+                    }
+                    break;
+            }
+        }
+        if (message.isEndSession()) {
+            handleEndSession(isSync ? destination : source);
+        }
+        if (message.getAttachments().isPresent()) {
+            for (SignalServiceAttachment attachment : message.getAttachments().get()) {
+                if (attachment.isPointer()) {
+                    try {
+                        retrieveAttachment(attachment.asPointer());
+                    } catch (IOException | InvalidMessageException e) {
+                        System.err.println("Failed to retrieve attachment (" + attachment.asPointer().getId() + "): " + e.getMessage());
+                    }
+                }
+            }
+        }
+        return group;
+    }
+
     public void receiveMessages(int timeoutSeconds, boolean returnOnTimeout, ReceiveMessageHandler handler) throws IOException {
         final SignalServiceMessageReceiver messageReceiver = new SignalServiceMessageReceiver(URL, TRUST_STORE, username, password, signalingKey, USER_AGENT);
         SignalServiceMessagePipe messagePipe = null;
@@ -459,67 +540,19 @@ class Manager implements Signal {
                         if (content != null) {
                             if (content.getDataMessage().isPresent()) {
                                 SignalServiceDataMessage message = content.getDataMessage().get();
-                                if (message.getGroupInfo().isPresent()) {
-                                    SignalServiceGroup groupInfo = message.getGroupInfo().get();
-                                    switch (groupInfo.getType()) {
-                                        case UPDATE:
-                                            try {
-                                                group = groupStore.getGroup(groupInfo.getGroupId());
-                                            } catch (GroupNotFoundException e) {
-                                                group = new GroupInfo(groupInfo.getGroupId());
-                                            }
-
-                                            if (groupInfo.getAvatar().isPresent()) {
-                                                SignalServiceAttachment avatar = groupInfo.getAvatar().get();
-                                                if (avatar.isPointer()) {
-                                                    long avatarId = avatar.asPointer().getId();
-                                                    try {
-                                                        retrieveAttachment(avatar.asPointer());
-                                                        group.avatarId = avatarId;
-                                                    } catch (IOException | InvalidMessageException e) {
-                                                        System.err.println("Failed to retrieve group avatar (" + avatarId + "): " + e.getMessage());
-                                                    }
-                                                }
-                                            }
-
-                                            if (groupInfo.getName().isPresent()) {
-                                                group.name = groupInfo.getName().get();
-                                            }
-
-                                            if (groupInfo.getMembers().isPresent()) {
-                                                group.members.addAll(groupInfo.getMembers().get());
-                                            }
-
-                                            groupStore.updateGroup(group);
-                                            break;
-                                        case DELIVER:
-                                            try {
-                                                group = groupStore.getGroup(groupInfo.getGroupId());
-                                            } catch (GroupNotFoundException e) {
-                                            }
-                                            break;
-                                        case QUIT:
-                                            try {
-                                                group = groupStore.getGroup(groupInfo.getGroupId());
-                                                group.members.remove(envelope.getSource());
-                                            } catch (GroupNotFoundException e) {
-                                            }
-                                            break;
-                                    }
+                                group = handleSignalServiceDataMessage(message, false, envelope.getSource(), username);
+                            }
+                            if (content.getSyncMessage().isPresent()) {
+                                SignalServiceSyncMessage syncMessage = content.getSyncMessage().get();
+                                if (syncMessage.getSent().isPresent()) {
+                                    SignalServiceDataMessage message = syncMessage.getSent().get().getMessage();
+                                    group = handleSignalServiceDataMessage(message, true, envelope.getSource(), syncMessage.getSent().get().getDestination().get());
                                 }
-                                if (message.isEndSession()) {
-                                    handleEndSession(envelope.getSource());
+                                if (syncMessage.getRequest().isPresent()) {
+                                    // TODO
                                 }
-                                if (message.getAttachments().isPresent()) {
-                                    for (SignalServiceAttachment attachment : message.getAttachments().get()) {
-                                        if (attachment.isPointer()) {
-                                            try {
-                                                retrieveAttachment(attachment.asPointer());
-                                            } catch (IOException | InvalidMessageException e) {
-                                                System.err.println("Failed to retrieve attachment (" + attachment.asPointer().getId() + "): " + e.getMessage());
-                                            }
-                                        }
-                                    }
+                                if (syncMessage.getGroups().isPresent()) {
+                                    // TODO
                                 }
                             }
                         }