]> nmode's Git Repositories - signal-cli/blob - lib/src/main/java/org/asamk/signal/manager/internal/SignalDependencies.java
Convert classes to records
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / internal / SignalDependencies.java
1 package org.asamk.signal.manager.internal;
2
3 import org.asamk.signal.manager.config.ServiceConfig;
4 import org.asamk.signal.manager.config.ServiceEnvironmentConfig;
5 import org.signal.libsignal.metadata.certificate.CertificateValidator;
6 import org.signal.libsignal.zkgroup.profiles.ClientZkProfileOperations;
7 import org.whispersystems.signalservice.api.KeyBackupService;
8 import org.whispersystems.signalservice.api.SignalServiceAccountManager;
9 import org.whispersystems.signalservice.api.SignalServiceDataStore;
10 import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
11 import org.whispersystems.signalservice.api.SignalServiceMessageSender;
12 import org.whispersystems.signalservice.api.SignalSessionLock;
13 import org.whispersystems.signalservice.api.SignalWebSocket;
14 import org.whispersystems.signalservice.api.crypto.SignalServiceCipher;
15 import org.whispersystems.signalservice.api.groupsv2.ClientZkOperations;
16 import org.whispersystems.signalservice.api.groupsv2.GroupsV2Api;
17 import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
18 import org.whispersystems.signalservice.api.push.SignalServiceAddress;
19 import org.whispersystems.signalservice.api.services.ProfileService;
20 import org.whispersystems.signalservice.api.svr.SecureValueRecoveryV2;
21 import org.whispersystems.signalservice.api.util.CredentialsProvider;
22 import org.whispersystems.signalservice.api.util.UptimeSleepTimer;
23 import org.whispersystems.signalservice.api.websocket.WebSocketFactory;
24 import org.whispersystems.signalservice.internal.websocket.WebSocketConnection;
25
26 import java.util.Collection;
27 import java.util.Optional;
28 import java.util.concurrent.ExecutorService;
29 import java.util.function.Supplier;
30
31 public class SignalDependencies {
32
33 private final Object LOCK = new Object();
34
35 private final ServiceEnvironmentConfig serviceEnvironmentConfig;
36 private final String userAgent;
37 private final CredentialsProvider credentialsProvider;
38 private final SignalServiceDataStore dataStore;
39 private final ExecutorService executor;
40 private final SignalSessionLock sessionLock;
41
42 private boolean allowStories = true;
43
44 private SignalServiceAccountManager accountManager;
45 private GroupsV2Api groupsV2Api;
46 private GroupsV2Operations groupsV2Operations;
47 private ClientZkOperations clientZkOperations;
48
49 private SignalWebSocket signalWebSocket;
50 private SignalServiceMessageReceiver messageReceiver;
51 private SignalServiceMessageSender messageSender;
52
53 private KeyBackupService keyBackupService;
54 private SecureValueRecoveryV2 secureValueRecoveryV2;
55 private ProfileService profileService;
56 private SignalServiceCipher cipher;
57
58 SignalDependencies(
59 final ServiceEnvironmentConfig serviceEnvironmentConfig,
60 final String userAgent,
61 final CredentialsProvider credentialsProvider,
62 final SignalServiceDataStore dataStore,
63 final ExecutorService executor,
64 final SignalSessionLock sessionLock
65 ) {
66 this.serviceEnvironmentConfig = serviceEnvironmentConfig;
67 this.userAgent = userAgent;
68 this.credentialsProvider = credentialsProvider;
69 this.dataStore = dataStore;
70 this.executor = executor;
71 this.sessionLock = sessionLock;
72 }
73
74 public void resetAfterAddressChange() {
75 this.messageSender = null;
76 this.cipher = null;
77 getSignalWebSocket().forceNewWebSockets();
78 }
79
80 /**
81 * This method needs to be called before the first websocket is created
82 */
83 public void setAllowStories(final boolean allowStories) {
84 this.allowStories = allowStories;
85 }
86
87 public ServiceEnvironmentConfig getServiceEnvironmentConfig() {
88 return serviceEnvironmentConfig;
89 }
90
91 public SignalSessionLock getSessionLock() {
92 return sessionLock;
93 }
94
95 public SignalServiceAccountManager getAccountManager() {
96 return getOrCreate(() -> accountManager,
97 () -> accountManager = new SignalServiceAccountManager(serviceEnvironmentConfig.signalServiceConfiguration(),
98 credentialsProvider,
99 userAgent,
100 getGroupsV2Operations(),
101 ServiceConfig.AUTOMATIC_NETWORK_RETRY));
102 }
103
104 public SignalServiceAccountManager createUnauthenticatedAccountManager(String number, String password) {
105 return new SignalServiceAccountManager(getServiceEnvironmentConfig().signalServiceConfiguration(),
106 null,
107 null,
108 number,
109 SignalServiceAddress.DEFAULT_DEVICE_ID,
110 password,
111 userAgent,
112 ServiceConfig.AUTOMATIC_NETWORK_RETRY,
113 ServiceConfig.GROUP_MAX_SIZE);
114 }
115
116 public GroupsV2Api getGroupsV2Api() {
117 return getOrCreate(() -> groupsV2Api, () -> groupsV2Api = getAccountManager().getGroupsV2Api());
118 }
119
120 public GroupsV2Operations getGroupsV2Operations() {
121 return getOrCreate(() -> groupsV2Operations,
122 () -> groupsV2Operations = new GroupsV2Operations(ClientZkOperations.create(serviceEnvironmentConfig.signalServiceConfiguration()),
123 ServiceConfig.GROUP_MAX_SIZE));
124 }
125
126 private ClientZkOperations getClientZkOperations() {
127 return getOrCreate(() -> clientZkOperations,
128 () -> clientZkOperations = ClientZkOperations.create(serviceEnvironmentConfig.signalServiceConfiguration()));
129 }
130
131 private ClientZkProfileOperations getClientZkProfileOperations() {
132 final var clientZkOperations = getClientZkOperations();
133 return clientZkOperations == null ? null : clientZkOperations.getProfileOperations();
134 }
135
136 public SignalWebSocket getSignalWebSocket() {
137 return getOrCreate(() -> signalWebSocket, () -> {
138 final var timer = new UptimeSleepTimer();
139 final var healthMonitor = new SignalWebSocketHealthMonitor(timer);
140 final var webSocketFactory = new WebSocketFactory() {
141 @Override
142 public WebSocketConnection createWebSocket() {
143 return new WebSocketConnection("normal",
144 serviceEnvironmentConfig.signalServiceConfiguration(),
145 Optional.of(credentialsProvider),
146 userAgent,
147 healthMonitor,
148 allowStories);
149 }
150
151 @Override
152 public WebSocketConnection createUnidentifiedWebSocket() {
153 return new WebSocketConnection("unidentified",
154 serviceEnvironmentConfig.signalServiceConfiguration(),
155 Optional.empty(),
156 userAgent,
157 healthMonitor,
158 allowStories);
159 }
160 };
161 signalWebSocket = new SignalWebSocket(webSocketFactory);
162 healthMonitor.monitor(signalWebSocket);
163 });
164 }
165
166 public SignalServiceMessageReceiver getMessageReceiver() {
167 return getOrCreate(() -> messageReceiver,
168 () -> messageReceiver = new SignalServiceMessageReceiver(serviceEnvironmentConfig.signalServiceConfiguration(),
169 credentialsProvider,
170 userAgent,
171 getClientZkProfileOperations(),
172 ServiceConfig.AUTOMATIC_NETWORK_RETRY));
173 }
174
175 public SignalServiceMessageSender getMessageSender() {
176 return getOrCreate(() -> messageSender,
177 () -> messageSender = new SignalServiceMessageSender(serviceEnvironmentConfig.signalServiceConfiguration(),
178 credentialsProvider,
179 dataStore,
180 sessionLock,
181 userAgent,
182 getSignalWebSocket(),
183 Optional.empty(),
184 getClientZkProfileOperations(),
185 executor,
186 ServiceConfig.MAX_ENVELOPE_SIZE,
187 ServiceConfig.AUTOMATIC_NETWORK_RETRY));
188 }
189
190 public KeyBackupService getKeyBackupService() {
191 return getOrCreate(() -> keyBackupService,
192 () -> keyBackupService = getAccountManager().getKeyBackupService(ServiceConfig.getIasKeyStore(),
193 serviceEnvironmentConfig.keyBackupConfig().enclaveName(),
194 serviceEnvironmentConfig.keyBackupConfig().serviceId(),
195 serviceEnvironmentConfig.keyBackupConfig().mrenclave(),
196 10));
197 }
198
199 public SecureValueRecoveryV2 getSecureValueRecoveryV2() {
200 return getOrCreate(() -> secureValueRecoveryV2,
201 () -> secureValueRecoveryV2 = getAccountManager().getSecureValueRecoveryV2(serviceEnvironmentConfig.svr2Mrenclave()));
202 }
203
204 public Collection<KeyBackupService> getFallbackKeyBackupServices() {
205 return serviceEnvironmentConfig.fallbackKeyBackupConfigs()
206 .stream()
207 .map(config -> getAccountManager().getKeyBackupService(ServiceConfig.getIasKeyStore(),
208 config.enclaveName(),
209 config.serviceId(),
210 config.mrenclave(),
211 10))
212 .toList();
213 }
214
215 public ProfileService getProfileService() {
216 return getOrCreate(() -> profileService,
217 () -> profileService = new ProfileService(getClientZkProfileOperations(),
218 getMessageReceiver(),
219 getSignalWebSocket()));
220 }
221
222 public SignalServiceCipher getCipher() {
223 return getOrCreate(() -> cipher, () -> {
224 final var certificateValidator = new CertificateValidator(serviceEnvironmentConfig.unidentifiedSenderTrustRoot());
225 final var address = new SignalServiceAddress(credentialsProvider.getAci(), credentialsProvider.getE164());
226 final var deviceId = credentialsProvider.getDeviceId();
227 cipher = new SignalServiceCipher(address, deviceId, dataStore.aci(), sessionLock, certificateValidator);
228 });
229 }
230
231 private <T> T getOrCreate(Supplier<T> supplier, Callable creator) {
232 var value = supplier.get();
233 if (value != null) {
234 return value;
235 }
236
237 synchronized (LOCK) {
238 value = supplier.get();
239 if (value != null) {
240 return value;
241 }
242 creator.call();
243 return supplier.get();
244 }
245 }
246
247 private interface Callable {
248
249 void call();
250 }
251 }