]> nmode's Git Repositories - signal-cli/blobdiff - lib/src/main/java/org/asamk/signal/manager/SignalDependencies.java
Update libsignal-service-java
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / SignalDependencies.java
index fef8351f9f13782c7e0347e196363f45bbff4133..244a110f7ccb8d17cb67a07611a7885194ea8c6d 100644 (file)
@@ -18,133 +18,202 @@ 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.CredentialsProvider;
 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 CredentialsProvider 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;
 
-    public SignalDependencies(
-            final SignalServiceAddress selfAddress,
+    private SignalWebSocket signalWebSocket;
+    private SignalServiceMessageReceiver messageReceiver;
+    private SignalServiceMessageSender messageSender;
+
+    private KeyBackupService keyBackupService;
+    private ProfileService profileService;
+    private SignalServiceCipher cipher;
+
+    SignalDependencies(
             final ServiceEnvironmentConfig serviceEnvironmentConfig,
             final String userAgent,
-            final DynamicCredentialsProvider credentialsProvider,
+            final CredentialsProvider credentialsProvider,
             final SignalServiceDataStore dataStore,
             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);
+        this.serviceEnvironmentConfig = serviceEnvironmentConfig;
+        this.userAgent = userAgent;
+        this.credentialsProvider = credentialsProvider;
+        this.dataStore = dataStore;
+        this.executor = executor;
+        this.sessionLock = sessionLock;
+    }
 
-        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);
-            }
+    public void resetAfterAddressChange() {
+        this.messageSender = null;
+        this.cipher = null;
+    }
 
-            @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);
+    public ServiceEnvironmentConfig getServiceEnvironmentConfig() {
+        return serviceEnvironmentConfig;
     }
 
     public SignalServiceAccountManager getAccountManager() {
-        return accountManager;
+        return getOrCreate(() -> accountManager,
+                () -> accountManager = new SignalServiceAccountManager(serviceEnvironmentConfig.getSignalServiceConfiguration(),
+                        credentialsProvider,
+                        userAgent,
+                        getGroupsV2Operations(),
+                        ServiceConfig.AUTOMATIC_NETWORK_RETRY));
+    }
+
+    public SignalServiceAccountManager createUnauthenticatedAccountManager(String number, String password) {
+        return new SignalServiceAccountManager(getServiceEnvironmentConfig().getSignalServiceConfiguration(),
+                null,
+                null,
+                number,
+                SignalServiceAddress.DEFAULT_DEVICE_ID,
+                password,
+                userAgent,
+                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);
+    }
+
+    private ClientZkProfileOperations getClientZkProfileOperations() {
+        final var clientZkOperations = getClientZkOperations();
+        return clientZkOperations == null ? null : clientZkOperations.getProfileOperations();
     }
 
     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,
+                        getClientZkProfileOperations(),
+                        ServiceConfig.AUTOMATIC_NETWORK_RETRY));
     }
 
     public SignalServiceMessageSender getMessageSender() {
-        return messageSender;
+        return getOrCreate(() -> messageSender,
+                () -> messageSender = new SignalServiceMessageSender(serviceEnvironmentConfig.getSignalServiceConfiguration(),
+                        credentialsProvider,
+                        dataStore,
+                        sessionLock,
+                        userAgent,
+                        getSignalWebSocket(),
+                        Optional.absent(),
+                        getClientZkProfileOperations(),
+                        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(getClientZkProfileOperations(),
+                        getMessageReceiver(),
+                        getSignalWebSocket()));
     }
 
     public SignalServiceCipher getCipher() {
-        return cipher;
+        return getOrCreate(() -> cipher, () -> {
+            final var certificateValidator = new CertificateValidator(serviceEnvironmentConfig.getUnidentifiedSenderTrustRoot());
+            final var address = new SignalServiceAddress(credentialsProvider.getAci(), credentialsProvider.getE164());
+            final var deviceId = credentialsProvider.getDeviceId();
+            cipher = new SignalServiceCipher(address, deviceId, dataStore.aci(), 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();
     }
 }