]> nmode's Git Repositories - signal-cli/commitdiff
Create libsignal dependencies only when required
authorAsamK <asamk@gmx.de>
Mon, 30 Aug 2021 13:07:12 +0000 (15:07 +0200)
committerAsamK <asamk@gmx.de>
Mon, 30 Aug 2021 13:07:12 +0000 (15:07 +0200)
lib/src/main/java/org/asamk/signal/manager/Manager.java
lib/src/main/java/org/asamk/signal/manager/SignalDependencies.java
lib/src/main/java/org/asamk/signal/manager/helper/MessageReceiverProvider.java [deleted file]
lib/src/main/java/org/asamk/signal/manager/helper/ProfileHelper.java
lib/src/main/java/org/asamk/signal/manager/helper/ProfileServiceProvider.java [deleted file]
lib/src/main/java/org/asamk/signal/manager/jobs/Context.java
lib/src/main/java/org/asamk/signal/manager/jobs/RetrieveStickerPackJob.java

index 6d91ba11330d58bec80443c5952a6fd024db3571..c40fa7cdb2c2800f5f9d55323e5a30f9056d8521 100644 (file)
@@ -164,8 +164,7 @@ public class Manager implements Closeable {
                 return LEGACY_LOCK::unlock;
             }
         };
-        this.dependencies = new SignalDependencies(account.getSelfAddress(),
-                serviceEnvironmentConfig,
+        this.dependencies = new SignalDependencies(serviceEnvironmentConfig,
                 userAgent,
                 credentialsProvider,
                 account.getSignalProtocolStore(),
@@ -186,8 +185,6 @@ public class Manager implements Closeable {
                 avatarStore,
                 account.getProfileStore()::getProfileKey,
                 unidentifiedAccessHelper::getAccessFor,
-                dependencies::getProfileService,
-                dependencies::getMessageReceiver,
                 this::resolveSignalServiceAddress);
         final GroupV2Helper groupV2Helper = new GroupV2Helper(profileHelper::getRecipientProfileKeyCredential,
                 this::getRecipientProfile,
@@ -220,8 +217,7 @@ public class Manager implements Closeable {
                 this::resolveSignalServiceAddress);
 
         this.context = new Context(account,
-                dependencies.getAccountManager(),
-                dependencies.getMessageReceiver(),
+                dependencies,
                 stickerPackStore,
                 sendHelper,
                 groupHelper,
@@ -1149,10 +1145,6 @@ public class Manager implements Closeable {
     }
 
     public SignalServiceAddress resolveSignalServiceAddress(SignalServiceAddress address) {
-        if (address.matches(account.getSelfAddress())) {
-            return account.getSelfAddress();
-        }
-
         return resolveSignalServiceAddress(resolveRecipient(address));
     }
 
index fef8351f9f13782c7e0347e196363f45bbff4133..970a67415923131f8ae61cf0a6efd936a6bb37c3 100644 (file)
@@ -3,7 +3,6 @@ package org.asamk.signal.manager;
 import org.asamk.signal.manager.config.ServiceConfig;
 import org.asamk.signal.manager.config.ServiceEnvironmentConfig;
 import org.signal.libsignal.metadata.certificate.CertificateValidator;
-import org.signal.zkgroup.profiles.ClientZkProfileOperations;
 import org.whispersystems.libsignal.util.guava.Optional;
 import org.whispersystems.signalservice.api.KeyBackupService;
 import org.whispersystems.signalservice.api.SignalServiceAccountManager;
@@ -18,32 +17,41 @@ import org.whispersystems.signalservice.api.groupsv2.GroupsV2Api;
 import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
 import org.whispersystems.signalservice.api.push.SignalServiceAddress;
 import org.whispersystems.signalservice.api.services.ProfileService;
-import org.whispersystems.signalservice.api.util.SleepTimer;
 import org.whispersystems.signalservice.api.util.UptimeSleepTimer;
 import org.whispersystems.signalservice.api.websocket.WebSocketFactory;
 import org.whispersystems.signalservice.internal.util.DynamicCredentialsProvider;
 import org.whispersystems.signalservice.internal.websocket.WebSocketConnection;
 
 import java.util.concurrent.ExecutorService;
+import java.util.function.Supplier;
 
 import static org.asamk.signal.manager.config.ServiceConfig.capabilities;
 
 public class SignalDependencies {
 
-    private final SignalServiceAccountManager accountManager;
-    private final GroupsV2Api groupsV2Api;
-    private final GroupsV2Operations groupsV2Operations;
+    private final Object LOCK = new Object();
 
-    private final SignalWebSocket signalWebSocket;
-    private final SignalServiceMessageReceiver messageReceiver;
-    private final SignalServiceMessageSender messageSender;
+    private final ServiceEnvironmentConfig serviceEnvironmentConfig;
+    private final String userAgent;
+    private final DynamicCredentialsProvider credentialsProvider;
+    private final SignalServiceDataStore dataStore;
+    private final ExecutorService executor;
+    private final SignalSessionLock sessionLock;
 
-    private final KeyBackupService keyBackupService;
-    private final ProfileService profileService;
-    private final SignalServiceCipher cipher;
+    private SignalServiceAccountManager accountManager;
+    private GroupsV2Api groupsV2Api;
+    private GroupsV2Operations groupsV2Operations;
+    private ClientZkOperations clientZkOperations;
+
+    private SignalWebSocket signalWebSocket;
+    private SignalServiceMessageReceiver messageReceiver;
+    private SignalServiceMessageSender messageSender;
+
+    private KeyBackupService keyBackupService;
+    private ProfileService profileService;
+    private SignalServiceCipher cipher;
 
     public SignalDependencies(
-            final SignalServiceAddress selfAddress,
             final ServiceEnvironmentConfig serviceEnvironmentConfig,
             final String userAgent,
             final DynamicCredentialsProvider credentialsProvider,
@@ -51,100 +59,134 @@ public class SignalDependencies {
             final ExecutorService executor,
             final SignalSessionLock sessionLock
     ) {
-        this.groupsV2Operations = capabilities.isGv2() ? new GroupsV2Operations(ClientZkOperations.create(
-                serviceEnvironmentConfig.getSignalServiceConfiguration())) : null;
-        final SleepTimer timer = new UptimeSleepTimer();
-        this.accountManager = new SignalServiceAccountManager(serviceEnvironmentConfig.getSignalServiceConfiguration(),
-                credentialsProvider,
-                userAgent,
-                groupsV2Operations,
-                ServiceConfig.AUTOMATIC_NETWORK_RETRY);
-        this.groupsV2Api = accountManager.getGroupsV2Api();
-        this.keyBackupService = accountManager.getKeyBackupService(ServiceConfig.getIasKeyStore(),
-                serviceEnvironmentConfig.getKeyBackupConfig().getEnclaveName(),
-                serviceEnvironmentConfig.getKeyBackupConfig().getServiceId(),
-                serviceEnvironmentConfig.getKeyBackupConfig().getMrenclave(),
-                10);
-        final ClientZkProfileOperations clientZkProfileOperations = capabilities.isGv2() ? ClientZkOperations.create(
-                serviceEnvironmentConfig.getSignalServiceConfiguration()).getProfileOperations() : null;
-        this.messageReceiver = new SignalServiceMessageReceiver(serviceEnvironmentConfig.getSignalServiceConfiguration(),
-                credentialsProvider,
-                userAgent,
-                clientZkProfileOperations,
-                ServiceConfig.AUTOMATIC_NETWORK_RETRY);
-
-        final var healthMonitor = new SignalWebSocketHealthMonitor(timer);
-        final WebSocketFactory webSocketFactory = new WebSocketFactory() {
-            @Override
-            public WebSocketConnection createWebSocket() {
-                return new WebSocketConnection("normal",
-                        serviceEnvironmentConfig.getSignalServiceConfiguration(),
-                        Optional.of(credentialsProvider),
-                        userAgent,
-                        healthMonitor);
-            }
-
-            @Override
-            public WebSocketConnection createUnidentifiedWebSocket() {
-                return new WebSocketConnection("unidentified",
-                        serviceEnvironmentConfig.getSignalServiceConfiguration(),
-                        Optional.absent(),
-                        userAgent,
-                        healthMonitor);
-            }
-        };
-        this.signalWebSocket = new SignalWebSocket(webSocketFactory);
-        healthMonitor.monitor(signalWebSocket);
-        this.profileService = new ProfileService(clientZkProfileOperations, messageReceiver, signalWebSocket);
-
-        final var certificateValidator = new CertificateValidator(serviceEnvironmentConfig.getUnidentifiedSenderTrustRoot());
-        this.cipher = new SignalServiceCipher(selfAddress, dataStore, sessionLock, certificateValidator);
-        this.messageSender = new SignalServiceMessageSender(serviceEnvironmentConfig.getSignalServiceConfiguration(),
-                credentialsProvider,
-                dataStore,
-                sessionLock,
-                userAgent,
-                signalWebSocket,
-                Optional.absent(),
-                clientZkProfileOperations,
-                executor,
-                ServiceConfig.MAX_ENVELOPE_SIZE,
-                ServiceConfig.AUTOMATIC_NETWORK_RETRY);
+        this.serviceEnvironmentConfig = serviceEnvironmentConfig;
+        this.userAgent = userAgent;
+        this.credentialsProvider = credentialsProvider;
+        this.dataStore = dataStore;
+        this.executor = executor;
+        this.sessionLock = sessionLock;
     }
 
     public SignalServiceAccountManager getAccountManager() {
-        return accountManager;
+        return getOrCreate(() -> accountManager,
+                () -> accountManager = new SignalServiceAccountManager(serviceEnvironmentConfig.getSignalServiceConfiguration(),
+                        credentialsProvider,
+                        userAgent,
+                        getGroupsV2Operations(),
+                        ServiceConfig.AUTOMATIC_NETWORK_RETRY));
     }
 
     public GroupsV2Api getGroupsV2Api() {
-        return groupsV2Api;
+        return getOrCreate(() -> groupsV2Api, () -> groupsV2Api = getAccountManager().getGroupsV2Api());
     }
 
     public GroupsV2Operations getGroupsV2Operations() {
-        return groupsV2Operations;
+        return getOrCreate(() -> groupsV2Operations,
+                () -> groupsV2Operations = capabilities.isGv2() ? new GroupsV2Operations(ClientZkOperations.create(
+                        serviceEnvironmentConfig.getSignalServiceConfiguration())) : null);
+    }
+
+    private ClientZkOperations getClientZkOperations() {
+        return getOrCreate(() -> clientZkOperations,
+                () -> clientZkOperations = capabilities.isGv2()
+                        ? ClientZkOperations.create(serviceEnvironmentConfig.getSignalServiceConfiguration())
+                        : null);
     }
 
     public SignalWebSocket getSignalWebSocket() {
-        return signalWebSocket;
+        return getOrCreate(() -> signalWebSocket, () -> {
+            final var timer = new UptimeSleepTimer();
+            final var healthMonitor = new SignalWebSocketHealthMonitor(timer);
+            final var webSocketFactory = new WebSocketFactory() {
+                @Override
+                public WebSocketConnection createWebSocket() {
+                    return new WebSocketConnection("normal",
+                            serviceEnvironmentConfig.getSignalServiceConfiguration(),
+                            Optional.of(credentialsProvider),
+                            userAgent,
+                            healthMonitor);
+                }
+
+                @Override
+                public WebSocketConnection createUnidentifiedWebSocket() {
+                    return new WebSocketConnection("unidentified",
+                            serviceEnvironmentConfig.getSignalServiceConfiguration(),
+                            Optional.absent(),
+                            userAgent,
+                            healthMonitor);
+                }
+            };
+            signalWebSocket = new SignalWebSocket(webSocketFactory);
+            healthMonitor.monitor(signalWebSocket);
+        });
     }
 
     public SignalServiceMessageReceiver getMessageReceiver() {
-        return messageReceiver;
+        return getOrCreate(() -> messageReceiver,
+                () -> messageReceiver = new SignalServiceMessageReceiver(serviceEnvironmentConfig.getSignalServiceConfiguration(),
+                        credentialsProvider,
+                        userAgent,
+                        getClientZkOperations().getProfileOperations(),
+                        ServiceConfig.AUTOMATIC_NETWORK_RETRY));
     }
 
     public SignalServiceMessageSender getMessageSender() {
-        return messageSender;
+        return getOrCreate(() -> messageSender,
+                () -> messageSender = new SignalServiceMessageSender(serviceEnvironmentConfig.getSignalServiceConfiguration(),
+                        credentialsProvider,
+                        dataStore,
+                        sessionLock,
+                        userAgent,
+                        getSignalWebSocket(),
+                        Optional.absent(),
+                        getClientZkOperations().getProfileOperations(),
+                        executor,
+                        ServiceConfig.MAX_ENVELOPE_SIZE,
+                        ServiceConfig.AUTOMATIC_NETWORK_RETRY));
     }
 
     public KeyBackupService getKeyBackupService() {
-        return keyBackupService;
+        return getOrCreate(() -> keyBackupService,
+                () -> keyBackupService = getAccountManager().getKeyBackupService(ServiceConfig.getIasKeyStore(),
+                        serviceEnvironmentConfig.getKeyBackupConfig().getEnclaveName(),
+                        serviceEnvironmentConfig.getKeyBackupConfig().getServiceId(),
+                        serviceEnvironmentConfig.getKeyBackupConfig().getMrenclave(),
+                        10));
     }
 
     public ProfileService getProfileService() {
-        return profileService;
+        return getOrCreate(() -> profileService,
+                () -> profileService = new ProfileService(getClientZkOperations().getProfileOperations(),
+                        getMessageReceiver(),
+                        getSignalWebSocket()));
     }
 
     public SignalServiceCipher getCipher() {
-        return cipher;
+        return getOrCreate(() -> cipher, () -> {
+            final var certificateValidator = new CertificateValidator(serviceEnvironmentConfig.getUnidentifiedSenderTrustRoot());
+            final var address = new SignalServiceAddress(credentialsProvider.getUuid(), credentialsProvider.getE164());
+            cipher = new SignalServiceCipher(address, dataStore, sessionLock, certificateValidator);
+        });
+    }
+
+    private <T> T getOrCreate(Supplier<T> supplier, Callable creator) {
+        var value = supplier.get();
+        if (value != null) {
+            return value;
+        }
+
+        synchronized (LOCK) {
+            value = supplier.get();
+            if (value != null) {
+                return value;
+            }
+            creator.call();
+            return supplier.get();
+        }
+    }
+
+    private interface Callable {
+
+        void call();
     }
 }
diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/MessageReceiverProvider.java b/lib/src/main/java/org/asamk/signal/manager/helper/MessageReceiverProvider.java
deleted file mode 100644 (file)
index 9a18a5e..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.asamk.signal.manager.helper;
-
-import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
-
-public interface MessageReceiverProvider {
-
-    SignalServiceMessageReceiver getMessageReceiver();
-}
index 52154798ab85dc358f39bcd575a908807af4eebd..d4f8ae5db739a81d37f44b502c50ca1e9eae95ae 100644 (file)
@@ -45,8 +45,6 @@ public final class ProfileHelper {
     private final AvatarStore avatarStore;
     private final ProfileKeyProvider profileKeyProvider;
     private final UnidentifiedAccessProvider unidentifiedAccessProvider;
-    private final ProfileServiceProvider profileServiceProvider;
-    private final MessageReceiverProvider messageReceiverProvider;
     private final SignalServiceAddressResolver addressResolver;
 
     public ProfileHelper(
@@ -55,8 +53,6 @@ public final class ProfileHelper {
             final AvatarStore avatarStore,
             final ProfileKeyProvider profileKeyProvider,
             final UnidentifiedAccessProvider unidentifiedAccessProvider,
-            final ProfileServiceProvider profileServiceProvider,
-            final MessageReceiverProvider messageReceiverProvider,
             final SignalServiceAddressResolver addressResolver
     ) {
         this.account = account;
@@ -64,8 +60,6 @@ public final class ProfileHelper {
         this.avatarStore = avatarStore;
         this.profileKeyProvider = profileKeyProvider;
         this.unidentifiedAccessProvider = unidentifiedAccessProvider;
-        this.profileServiceProvider = profileServiceProvider;
-        this.messageReceiverProvider = messageReceiverProvider;
         this.addressResolver = addressResolver;
     }
 
@@ -218,7 +212,7 @@ public final class ProfileHelper {
     }
 
     private SignalServiceProfile retrieveProfileSync(String username) throws IOException {
-        return messageReceiverProvider.getMessageReceiver().retrieveProfileByUsername(username, Optional.absent());
+        return dependencies.getMessageReceiver().retrieveProfileByUsername(username, Optional.absent());
     }
 
     private ProfileAndCredential retrieveProfileAndCredential(
@@ -287,7 +281,7 @@ public final class ProfileHelper {
             Optional<UnidentifiedAccess> unidentifiedAccess,
             SignalServiceProfile.RequestType requestType
     ) {
-        var profileService = profileServiceProvider.getProfileService();
+        var profileService = dependencies.getProfileService();
 
         Single<ServiceResponse<ProfileAndCredential>> responseSingle;
         try {
diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/ProfileServiceProvider.java b/lib/src/main/java/org/asamk/signal/manager/helper/ProfileServiceProvider.java
deleted file mode 100644 (file)
index 4fffb15..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.asamk.signal.manager.helper;
-
-import org.whispersystems.signalservice.api.services.ProfileService;
-
-public interface ProfileServiceProvider {
-
-    ProfileService getProfileService();
-}
index 82c3bf16ddc23d312623ea7d11259fdb54c8aa1a..142c148aef5453494d5c280267a0f9372b4c0cc7 100644 (file)
@@ -1,19 +1,17 @@
 package org.asamk.signal.manager.jobs;
 
+import org.asamk.signal.manager.SignalDependencies;
 import org.asamk.signal.manager.StickerPackStore;
 import org.asamk.signal.manager.helper.GroupHelper;
 import org.asamk.signal.manager.helper.ProfileHelper;
 import org.asamk.signal.manager.helper.SendHelper;
 import org.asamk.signal.manager.helper.SyncHelper;
 import org.asamk.signal.manager.storage.SignalAccount;
-import org.whispersystems.signalservice.api.SignalServiceAccountManager;
-import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
 
 public class Context {
 
     private final SignalAccount account;
-    private final SignalServiceAccountManager accountManager;
-    private final SignalServiceMessageReceiver messageReceiver;
+    private final SignalDependencies dependencies;
     private final StickerPackStore stickerPackStore;
     private final SendHelper sendHelper;
     private final GroupHelper groupHelper;
@@ -22,8 +20,7 @@ public class Context {
 
     public Context(
             final SignalAccount account,
-            final SignalServiceAccountManager accountManager,
-            final SignalServiceMessageReceiver messageReceiver,
+            final SignalDependencies dependencies,
             final StickerPackStore stickerPackStore,
             final SendHelper sendHelper,
             final GroupHelper groupHelper,
@@ -31,8 +28,7 @@ public class Context {
             final ProfileHelper profileHelper
     ) {
         this.account = account;
-        this.accountManager = accountManager;
-        this.messageReceiver = messageReceiver;
+        this.dependencies = dependencies;
         this.stickerPackStore = stickerPackStore;
         this.sendHelper = sendHelper;
         this.groupHelper = groupHelper;
@@ -44,12 +40,8 @@ public class Context {
         return account;
     }
 
-    public SignalServiceAccountManager getAccountManager() {
-        return accountManager;
-    }
-
-    public SignalServiceMessageReceiver getMessageReceiver() {
-        return messageReceiver;
+    public SignalDependencies getDependencies() {
+        return dependencies;
     }
 
     public StickerPackStore getStickerPackStore() {
index 20042451e5e76a2d8fb7f09c104c93db57bccc77..c27bcafcb745f9612be848cf277df548f17a75d5 100644 (file)
@@ -32,7 +32,9 @@ public class RetrieveStickerPackJob implements Job {
         }
         logger.debug("Retrieving sticker pack {}.", Hex.toStringCondensed(packId.serialize()));
         try {
-            final var manifest = context.getMessageReceiver().retrieveStickerManifest(packId.serialize(), packKey);
+            final var manifest = context.getDependencies()
+                    .getMessageReceiver()
+                    .retrieveStickerManifest(packId.serialize(), packKey);
 
             final var stickerIds = new HashSet<Integer>();
             if (manifest.getCover().isPresent()) {
@@ -43,7 +45,9 @@ public class RetrieveStickerPackJob implements Job {
             }
 
             for (var id : stickerIds) {
-                final var inputStream = context.getMessageReceiver().retrieveSticker(packId.serialize(), packKey, id);
+                final var inputStream = context.getDependencies()
+                        .getMessageReceiver()
+                        .retrieveSticker(packId.serialize(), packKey, id);
                 context.getStickerPackStore().storeSticker(packId, id, o -> IOUtils.copyStream(inputStream, o));
             }