]> nmode's Git Repositories - signal-cli/blobdiff - lib/src/main/java/org/asamk/signal/manager/helper/PreKeyHelper.java
Update libsignal-service
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / helper / PreKeyHelper.java
index f81623e473294d9913ec2435728d974bf366fa5d..bf7ad580bafde15e6668b5abfe7f2d066e0548dc 100644 (file)
@@ -11,16 +11,19 @@ import org.signal.libsignal.protocol.state.PreKeyRecord;
 import org.signal.libsignal.protocol.state.SignedPreKeyRecord;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.whispersystems.signalservice.api.NetworkResultUtil;
 import org.whispersystems.signalservice.api.account.PreKeyUpload;
+import org.whispersystems.signalservice.api.keys.OneTimePreKeyCounts;
 import org.whispersystems.signalservice.api.push.ServiceIdType;
 import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException;
-import org.whispersystems.signalservice.internal.push.OneTimePreKeyCounts;
+import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
 
 import java.io.IOException;
 import java.util.List;
 
 import static org.asamk.signal.manager.config.ServiceConfig.PREKEY_STALE_AGE;
 import static org.asamk.signal.manager.config.ServiceConfig.SIGNED_PREKEY_ROTATE_AGE;
+import static org.asamk.signal.manager.util.Utils.handleResponseException;
 
 public class PreKeyHelper {
 
@@ -29,9 +32,7 @@ public class PreKeyHelper {
     private final SignalAccount account;
     private final SignalDependencies dependencies;
 
-    public PreKeyHelper(
-            final SignalAccount account, final SignalDependencies dependencies
-    ) {
+    public PreKeyHelper(final SignalAccount account, final SignalDependencies dependencies) {
         this.account = account;
         this.dependencies = dependencies;
     }
@@ -41,6 +42,11 @@ public class PreKeyHelper {
         refreshPreKeysIfNecessary(ServiceIdType.PNI);
     }
 
+    public void forceRefreshPreKeys() throws IOException {
+        forceRefreshPreKeys(ServiceIdType.ACI);
+        forceRefreshPreKeys(ServiceIdType.PNI);
+    }
+
     public void refreshPreKeysIfNecessary(ServiceIdType serviceIdType) throws IOException {
         final var identityKeyPair = account.getIdentityKeyPair(serviceIdType);
         if (identityKeyPair == null) {
@@ -56,19 +62,45 @@ public class PreKeyHelper {
         }
     }
 
+    public void forceRefreshPreKeys(ServiceIdType serviceIdType) throws IOException {
+        final var identityKeyPair = account.getIdentityKeyPair(serviceIdType);
+        if (identityKeyPair == null) {
+            return;
+        }
+        final var accountId = account.getAccountId(serviceIdType);
+        if (accountId == null) {
+            return;
+        }
+
+        final var counts = new OneTimePreKeyCounts(0, 0);
+        if (refreshPreKeysIfNecessary(serviceIdType, identityKeyPair, counts, true)) {
+            refreshPreKeysIfNecessary(serviceIdType, identityKeyPair, counts, true);
+        }
+    }
+
     private boolean refreshPreKeysIfNecessary(
-            final ServiceIdType serviceIdType, final IdentityKeyPair identityKeyPair
+            final ServiceIdType serviceIdType,
+            final IdentityKeyPair identityKeyPair
     ) throws IOException {
         OneTimePreKeyCounts preKeyCounts;
         try {
-            preKeyCounts = dependencies.getAccountManager().getPreKeyCounts(serviceIdType);
+            preKeyCounts = handleResponseException(dependencies.getKeysApi().getAvailablePreKeyCounts(serviceIdType));
         } catch (AuthorizationFailedException e) {
             logger.debug("Failed to get pre key count, ignoring: " + e.getClass().getSimpleName());
             preKeyCounts = new OneTimePreKeyCounts(0, 0);
         }
 
+        return refreshPreKeysIfNecessary(serviceIdType, identityKeyPair, preKeyCounts, false);
+    }
+
+    private boolean refreshPreKeysIfNecessary(
+            final ServiceIdType serviceIdType,
+            final IdentityKeyPair identityKeyPair,
+            final OneTimePreKeyCounts preKeyCounts,
+            final boolean force
+    ) throws IOException {
         List<PreKeyRecord> preKeyRecords = null;
-        if (preKeyCounts.getEcCount() < ServiceConfig.PREKEY_MINIMUM_COUNT) {
+        if (force || preKeyCounts.getEcCount() < ServiceConfig.PREKEY_MINIMUM_COUNT) {
             logger.debug("Refreshing {} ec pre keys, because only {} of min {} pre keys remain",
                     serviceIdType,
                     preKeyCounts.getEcCount(),
@@ -77,13 +109,13 @@ public class PreKeyHelper {
         }
 
         SignedPreKeyRecord signedPreKeyRecord = null;
-        if (signedPreKeyNeedsRefresh(serviceIdType)) {
+        if (force || signedPreKeyNeedsRefresh(serviceIdType)) {
             logger.debug("Refreshing {} signed pre key.", serviceIdType);
             signedPreKeyRecord = generateSignedPreKey(serviceIdType, identityKeyPair);
         }
 
         List<KyberPreKeyRecord> kyberPreKeyRecords = null;
-        if (preKeyCounts.getKyberCount() < ServiceConfig.PREKEY_MINIMUM_COUNT) {
+        if (force || preKeyCounts.getKyberCount() < ServiceConfig.PREKEY_MINIMUM_COUNT) {
             logger.debug("Refreshing {} kyber pre keys, because only {} of min {} pre keys remain",
                     serviceIdType,
                     preKeyCounts.getKyberCount(),
@@ -92,9 +124,11 @@ public class PreKeyHelper {
         }
 
         KyberPreKeyRecord lastResortKyberPreKeyRecord = null;
-        if (lastResortKyberPreKeyNeedsRefresh(serviceIdType)) {
+        if (force || lastResortKyberPreKeyNeedsRefresh(serviceIdType)) {
             logger.debug("Refreshing {} last resort kyber pre key.", serviceIdType);
-            lastResortKyberPreKeyRecord = generateLastResortKyberPreKey(serviceIdType, identityKeyPair);
+            lastResortKyberPreKeyRecord = generateLastResortKyberPreKey(serviceIdType,
+                    identityKeyPair,
+                    kyberPreKeyRecords == null ? 0 : kyberPreKeyRecords.size());
         }
 
         if (signedPreKeyRecord == null
@@ -111,7 +145,7 @@ public class PreKeyHelper {
                 kyberPreKeyRecords);
         var needsReset = false;
         try {
-            dependencies.getAccountManager().setPreKeys(preKeyUpload);
+            NetworkResultUtil.toPreKeysLegacy(dependencies.getKeysApi().setPreKeys(preKeyUpload));
             try {
                 if (preKeyRecords != null) {
                     account.addPreKeys(serviceIdType, preKeyRecords);
@@ -139,6 +173,11 @@ public class PreKeyHelper {
         } catch (AuthorizationFailedException e) {
             // This can happen when the primary device has changed phone number
             logger.warn("Failed to updated pre keys: {}", e.getMessage());
+        } catch (NonSuccessfulResponseCodeException e) {
+            if (serviceIdType != ServiceIdType.PNI || e.code != 422) {
+                throw e;
+            }
+            logger.warn("Failed to set PNI pre keys, ignoring for now. Account needs to be reregistered to fix this.");
         }
         return needsReset;
     }
@@ -157,9 +196,7 @@ public class PreKeyHelper {
         final var accountData = account.getAccountData(serviceIdType);
         final var offset = accountData.getPreKeyMetadata().getNextPreKeyId();
 
-        var records = KeyUtils.generatePreKeyRecords(offset);
-
-        return records;
+        return KeyUtils.generatePreKeyRecords(offset);
     }
 
     private boolean signedPreKeyNeedsRefresh(ServiceIdType serviceIdType) {
@@ -185,7 +222,8 @@ public class PreKeyHelper {
     }
 
     private List<KyberPreKeyRecord> generateKyberPreKeys(
-            ServiceIdType serviceIdType, final IdentityKeyPair identityKeyPair
+            ServiceIdType serviceIdType,
+            final IdentityKeyPair identityKeyPair
     ) {
         final var accountData = account.getAccountData(serviceIdType);
         final var offset = accountData.getPreKeyMetadata().getNextKyberPreKeyId();
@@ -210,10 +248,12 @@ public class PreKeyHelper {
     }
 
     private KyberPreKeyRecord generateLastResortKyberPreKey(
-            ServiceIdType serviceIdType, IdentityKeyPair identityKeyPair
+            ServiceIdType serviceIdType,
+            IdentityKeyPair identityKeyPair,
+            final int offset
     ) {
         final var accountData = account.getAccountData(serviceIdType);
-        final var signedPreKeyId = accountData.getPreKeyMetadata().getNextKyberPreKeyId();
+        final var signedPreKeyId = accountData.getPreKeyMetadata().getNextKyberPreKeyId() + offset;
 
         return KeyUtils.generateKyberPreKeyRecord(signedPreKeyId, identityKeyPair.getPrivateKey());
     }