From 626406a43c169105c3485749249ffbfd715e3441 Mon Sep 17 00:00:00 2001 From: AsamK Date: Mon, 30 Aug 2021 15:07:12 +0200 Subject: [PATCH] Create libsignal dependencies only when required --- .../org/asamk/signal/manager/Manager.java | 12 +- .../signal/manager/SignalDependencies.java | 202 +++++++++++------- .../helper/MessageReceiverProvider.java | 8 - .../signal/manager/helper/ProfileHelper.java | 10 +- .../helper/ProfileServiceProvider.java | 8 - .../asamk/signal/manager/jobs/Context.java | 20 +- .../manager/jobs/RetrieveStickerPackJob.java | 8 +- 7 files changed, 138 insertions(+), 130 deletions(-) delete mode 100644 lib/src/main/java/org/asamk/signal/manager/helper/MessageReceiverProvider.java delete mode 100644 lib/src/main/java/org/asamk/signal/manager/helper/ProfileServiceProvider.java diff --git a/lib/src/main/java/org/asamk/signal/manager/Manager.java b/lib/src/main/java/org/asamk/signal/manager/Manager.java index 6d91ba11..c40fa7cd 100644 --- a/lib/src/main/java/org/asamk/signal/manager/Manager.java +++ b/lib/src/main/java/org/asamk/signal/manager/Manager.java @@ -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)); } diff --git a/lib/src/main/java/org/asamk/signal/manager/SignalDependencies.java b/lib/src/main/java/org/asamk/signal/manager/SignalDependencies.java index fef8351f..970a6741 100644 --- a/lib/src/main/java/org/asamk/signal/manager/SignalDependencies.java +++ b/lib/src/main/java/org/asamk/signal/manager/SignalDependencies.java @@ -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 getOrCreate(Supplier 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 index 9a18a5e4..00000000 --- a/lib/src/main/java/org/asamk/signal/manager/helper/MessageReceiverProvider.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.asamk.signal.manager.helper; - -import org.whispersystems.signalservice.api.SignalServiceMessageReceiver; - -public interface MessageReceiverProvider { - - SignalServiceMessageReceiver getMessageReceiver(); -} diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/ProfileHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/ProfileHelper.java index 52154798..d4f8ae5d 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/ProfileHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/ProfileHelper.java @@ -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, SignalServiceProfile.RequestType requestType ) { - var profileService = profileServiceProvider.getProfileService(); + var profileService = dependencies.getProfileService(); Single> 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 index 4fffb15c..00000000 --- a/lib/src/main/java/org/asamk/signal/manager/helper/ProfileServiceProvider.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.asamk.signal.manager.helper; - -import org.whispersystems.signalservice.api.services.ProfileService; - -public interface ProfileServiceProvider { - - ProfileService getProfileService(); -} diff --git a/lib/src/main/java/org/asamk/signal/manager/jobs/Context.java b/lib/src/main/java/org/asamk/signal/manager/jobs/Context.java index 82c3bf16..142c148a 100644 --- a/lib/src/main/java/org/asamk/signal/manager/jobs/Context.java +++ b/lib/src/main/java/org/asamk/signal/manager/jobs/Context.java @@ -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() { diff --git a/lib/src/main/java/org/asamk/signal/manager/jobs/RetrieveStickerPackJob.java b/lib/src/main/java/org/asamk/signal/manager/jobs/RetrieveStickerPackJob.java index 20042451..c27bcafc 100644 --- a/lib/src/main/java/org/asamk/signal/manager/jobs/RetrieveStickerPackJob.java +++ b/lib/src/main/java/org/asamk/signal/manager/jobs/RetrieveStickerPackJob.java @@ -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(); 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)); } -- 2.50.1