]> nmode's Git Repositories - signal-cli/blob - lib/src/main/java/org/asamk/signal/manager/internal/SignalDependencies.java
Update libsignal-service-java
[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.asamk.signal.manager.util.Utils;
6 import org.signal.libsignal.metadata.certificate.CertificateValidator;
7 import org.signal.libsignal.net.Network;
8 import org.signal.libsignal.protocol.UsePqRatchet;
9 import org.signal.libsignal.zkgroup.profiles.ClientZkProfileOperations;
10 import org.slf4j.Logger;
11 import org.slf4j.LoggerFactory;
12 import org.whispersystems.signalservice.api.SignalServiceAccountManager;
13 import org.whispersystems.signalservice.api.SignalServiceDataStore;
14 import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
15 import org.whispersystems.signalservice.api.SignalServiceMessageSender;
16 import org.whispersystems.signalservice.api.SignalSessionLock;
17 import org.whispersystems.signalservice.api.account.AccountApi;
18 import org.whispersystems.signalservice.api.attachment.AttachmentApi;
19 import org.whispersystems.signalservice.api.cds.CdsApi;
20 import org.whispersystems.signalservice.api.certificate.CertificateApi;
21 import org.whispersystems.signalservice.api.crypto.SignalServiceCipher;
22 import org.whispersystems.signalservice.api.groupsv2.ClientZkOperations;
23 import org.whispersystems.signalservice.api.groupsv2.GroupsV2Api;
24 import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
25 import org.whispersystems.signalservice.api.keys.KeysApi;
26 import org.whispersystems.signalservice.api.link.LinkDeviceApi;
27 import org.whispersystems.signalservice.api.message.MessageApi;
28 import org.whispersystems.signalservice.api.profiles.ProfileApi;
29 import org.whispersystems.signalservice.api.push.ServiceIdType;
30 import org.whispersystems.signalservice.api.push.SignalServiceAddress;
31 import org.whispersystems.signalservice.api.ratelimit.RateLimitChallengeApi;
32 import org.whispersystems.signalservice.api.registration.RegistrationApi;
33 import org.whispersystems.signalservice.api.services.ProfileService;
34 import org.whispersystems.signalservice.api.storage.StorageServiceApi;
35 import org.whispersystems.signalservice.api.storage.StorageServiceRepository;
36 import org.whispersystems.signalservice.api.svr.SecureValueRecovery;
37 import org.whispersystems.signalservice.api.username.UsernameApi;
38 import org.whispersystems.signalservice.api.util.CredentialsProvider;
39 import org.whispersystems.signalservice.api.util.UptimeSleepTimer;
40 import org.whispersystems.signalservice.api.websocket.SignalWebSocket;
41 import org.whispersystems.signalservice.internal.push.PushServiceSocket;
42 import org.whispersystems.signalservice.internal.websocket.OkHttpWebSocketConnection;
43
44 import java.io.IOException;
45 import java.net.InetSocketAddress;
46 import java.net.Proxy;
47 import java.util.List;
48 import java.util.Optional;
49 import java.util.concurrent.ExecutorService;
50 import java.util.concurrent.TimeUnit;
51 import java.util.function.Supplier;
52
53 public class SignalDependencies {
54
55 private static final Logger logger = LoggerFactory.getLogger(SignalDependencies.class);
56
57 private final Object LOCK = new Object();
58
59 private final ServiceEnvironmentConfig serviceEnvironmentConfig;
60 private final String userAgent;
61 private final CredentialsProvider credentialsProvider;
62 private final SignalServiceDataStore dataStore;
63 private final ExecutorService executor;
64 private final SignalSessionLock sessionLock;
65
66 private boolean allowStories = true;
67
68 private SignalServiceAccountManager accountManager;
69 private AccountApi accountApi;
70 private RateLimitChallengeApi rateLimitChallengeApi;
71 private CdsApi cdsApi;
72 private UsernameApi usernameApi;
73 private GroupsV2Api groupsV2Api;
74 private RegistrationApi registrationApi;
75 private LinkDeviceApi linkDeviceApi;
76 private StorageServiceApi storageServiceApi;
77 private CertificateApi certificateApi;
78 private AttachmentApi attachmentApi;
79 private MessageApi messageApi;
80 private KeysApi keysApi;
81 private GroupsV2Operations groupsV2Operations;
82 private ClientZkOperations clientZkOperations;
83
84 private PushServiceSocket pushServiceSocket;
85 private Network libSignalNetwork;
86 private SignalWebSocket.AuthenticatedWebSocket authenticatedSignalWebSocket;
87 private SignalWebSocket.UnauthenticatedWebSocket unauthenticatedSignalWebSocket;
88 private SignalServiceMessageReceiver messageReceiver;
89 private SignalServiceMessageSender messageSender;
90
91 private List<SecureValueRecovery> secureValueRecovery;
92 private ProfileService profileService;
93 private ProfileApi profileApi;
94
95 SignalDependencies(
96 final ServiceEnvironmentConfig serviceEnvironmentConfig,
97 final String userAgent,
98 final CredentialsProvider credentialsProvider,
99 final SignalServiceDataStore dataStore,
100 final ExecutorService executor,
101 final SignalSessionLock sessionLock
102 ) {
103 this.serviceEnvironmentConfig = serviceEnvironmentConfig;
104 this.userAgent = userAgent;
105 this.credentialsProvider = credentialsProvider;
106 this.dataStore = dataStore;
107 this.executor = executor;
108 this.sessionLock = sessionLock;
109 }
110
111 public void resetAfterAddressChange() {
112 if (this.pushServiceSocket != null) {
113 this.pushServiceSocket.close();
114 this.pushServiceSocket = null;
115 this.accountManager = null;
116 this.messageReceiver = null;
117 this.messageSender = null;
118 this.profileService = null;
119 this.groupsV2Api = null;
120 this.registrationApi = null;
121 this.secureValueRecovery = null;
122 }
123 if (this.authenticatedSignalWebSocket != null) {
124 this.authenticatedSignalWebSocket.forceNewWebSocket();
125 }
126 if (this.unauthenticatedSignalWebSocket != null) {
127 this.unauthenticatedSignalWebSocket.forceNewWebSocket();
128 }
129 }
130
131 /**
132 * This method needs to be called before the first websocket is created
133 */
134 public void setAllowStories(final boolean allowStories) {
135 this.allowStories = allowStories;
136 }
137
138 public ServiceEnvironmentConfig getServiceEnvironmentConfig() {
139 return serviceEnvironmentConfig;
140 }
141
142 public SignalSessionLock getSessionLock() {
143 return sessionLock;
144 }
145
146 public PushServiceSocket getPushServiceSocket() {
147 return getOrCreate(() -> pushServiceSocket,
148 () -> pushServiceSocket = new PushServiceSocket(serviceEnvironmentConfig.signalServiceConfiguration(),
149 credentialsProvider,
150 userAgent,
151 ServiceConfig.AUTOMATIC_NETWORK_RETRY));
152 }
153
154 public Network getLibSignalNetwork() {
155 return getOrCreate(() -> libSignalNetwork, () -> {
156 libSignalNetwork = new Network(serviceEnvironmentConfig.netEnvironment(), userAgent);
157 setSignalNetworkProxy(libSignalNetwork);
158 });
159 }
160
161 private void setSignalNetworkProxy(Network libSignalNetwork) {
162 final var proxy = Utils.getHttpsProxy();
163 if (proxy.address() instanceof InetSocketAddress addr) {
164 switch (proxy.type()) {
165 case Proxy.Type.DIRECT -> {
166 }
167 case Proxy.Type.HTTP -> {
168 try {
169 libSignalNetwork.setProxy("http", addr.getHostName(), addr.getPort(), null, null);
170 } catch (IOException e) {
171 logger.warn("Failed to set http proxy", e);
172 }
173 }
174 case Proxy.Type.SOCKS -> {
175 try {
176 libSignalNetwork.setProxy("socks", addr.getHostName(), addr.getPort(), null, null);
177 } catch (IOException e) {
178 logger.warn("Failed to set socks proxy", e);
179 }
180 }
181 }
182 }
183 }
184
185 public SignalServiceAccountManager getAccountManager() {
186 return getOrCreate(() -> accountManager,
187 () -> accountManager = new SignalServiceAccountManager(getAuthenticatedSignalWebSocket(),
188 getAccountApi(),
189 getPushServiceSocket(),
190 getGroupsV2Operations()));
191 }
192
193 public SignalServiceAccountManager createUnauthenticatedAccountManager(String number, String password) {
194 return SignalServiceAccountManager.createWithStaticCredentials(getServiceEnvironmentConfig().signalServiceConfiguration(),
195 null,
196 null,
197 number,
198 SignalServiceAddress.DEFAULT_DEVICE_ID,
199 password,
200 userAgent,
201 ServiceConfig.AUTOMATIC_NETWORK_RETRY,
202 ServiceConfig.GROUP_MAX_SIZE);
203 }
204
205 public AccountApi getAccountApi() {
206 return getOrCreate(() -> accountApi, () -> accountApi = new AccountApi(getAuthenticatedSignalWebSocket()));
207 }
208
209 public RateLimitChallengeApi getRateLimitChallengeApi() {
210 return getOrCreate(() -> rateLimitChallengeApi,
211 () -> rateLimitChallengeApi = new RateLimitChallengeApi(getAuthenticatedSignalWebSocket()));
212 }
213
214 public CdsApi getCdsApi() {
215 return getOrCreate(() -> cdsApi, () -> cdsApi = new CdsApi(getAuthenticatedSignalWebSocket()));
216 }
217
218 public UsernameApi getUsernameApi() {
219 return getOrCreate(() -> usernameApi, () -> usernameApi = new UsernameApi(getUnauthenticatedSignalWebSocket()));
220 }
221
222 public GroupsV2Api getGroupsV2Api() {
223 return getOrCreate(() -> groupsV2Api, () -> groupsV2Api = getAccountManager().getGroupsV2Api());
224 }
225
226 public RegistrationApi getRegistrationApi() {
227 return getOrCreate(() -> registrationApi, () -> registrationApi = getAccountManager().getRegistrationApi());
228 }
229
230 public LinkDeviceApi getLinkDeviceApi() {
231 return getOrCreate(() -> linkDeviceApi,
232 () -> linkDeviceApi = new LinkDeviceApi(getAuthenticatedSignalWebSocket()));
233 }
234
235 private StorageServiceApi getStorageServiceApi() {
236 return getOrCreate(() -> storageServiceApi,
237 () -> storageServiceApi = new StorageServiceApi(getAuthenticatedSignalWebSocket(),
238 getPushServiceSocket()));
239 }
240
241 public StorageServiceRepository getStorageServiceRepository() {
242 return new StorageServiceRepository(getStorageServiceApi());
243 }
244
245 public CertificateApi getCertificateApi() {
246 return getOrCreate(() -> certificateApi,
247 () -> certificateApi = new CertificateApi(getAuthenticatedSignalWebSocket()));
248 }
249
250 public AttachmentApi getAttachmentApi() {
251 return getOrCreate(() -> attachmentApi,
252 () -> attachmentApi = new AttachmentApi(getAuthenticatedSignalWebSocket(), getPushServiceSocket()));
253 }
254
255 public MessageApi getMessageApi() {
256 return getOrCreate(() -> messageApi,
257 () -> messageApi = new MessageApi(getAuthenticatedSignalWebSocket(),
258 getUnauthenticatedSignalWebSocket()));
259 }
260
261 public KeysApi getKeysApi() {
262 return getOrCreate(() -> keysApi,
263 () -> keysApi = new KeysApi(getAuthenticatedSignalWebSocket(), getUnauthenticatedSignalWebSocket()));
264 }
265
266 public GroupsV2Operations getGroupsV2Operations() {
267 return getOrCreate(() -> groupsV2Operations,
268 () -> groupsV2Operations = new GroupsV2Operations(ClientZkOperations.create(serviceEnvironmentConfig.signalServiceConfiguration()),
269 ServiceConfig.GROUP_MAX_SIZE));
270 }
271
272 private ClientZkOperations getClientZkOperations() {
273 return getOrCreate(() -> clientZkOperations,
274 () -> clientZkOperations = ClientZkOperations.create(serviceEnvironmentConfig.signalServiceConfiguration()));
275 }
276
277 private ClientZkProfileOperations getClientZkProfileOperations() {
278 final var clientZkOperations = getClientZkOperations();
279 return clientZkOperations.getProfileOperations();
280 }
281
282 public SignalWebSocket.AuthenticatedWebSocket getAuthenticatedSignalWebSocket() {
283 return getOrCreate(() -> authenticatedSignalWebSocket, () -> {
284 final var timer = new UptimeSleepTimer();
285 final var healthMonitor = new SignalWebSocketHealthMonitor(timer);
286
287 authenticatedSignalWebSocket = new SignalWebSocket.AuthenticatedWebSocket(() -> new OkHttpWebSocketConnection(
288 "normal",
289 serviceEnvironmentConfig.signalServiceConfiguration(),
290 Optional.of(credentialsProvider),
291 userAgent,
292 healthMonitor,
293 allowStories), () -> true, timer, TimeUnit.SECONDS.toMillis(10));
294 healthMonitor.monitor(authenticatedSignalWebSocket);
295 });
296 }
297
298 public SignalWebSocket.UnauthenticatedWebSocket getUnauthenticatedSignalWebSocket() {
299 return getOrCreate(() -> unauthenticatedSignalWebSocket, () -> {
300 final var timer = new UptimeSleepTimer();
301 final var healthMonitor = new SignalWebSocketHealthMonitor(timer);
302
303 unauthenticatedSignalWebSocket = new SignalWebSocket.UnauthenticatedWebSocket(() -> new OkHttpWebSocketConnection(
304 "unidentified",
305 serviceEnvironmentConfig.signalServiceConfiguration(),
306 Optional.empty(),
307 userAgent,
308 healthMonitor,
309 allowStories), () -> true, timer, TimeUnit.SECONDS.toMillis(10));
310 healthMonitor.monitor(unauthenticatedSignalWebSocket);
311 });
312 }
313
314 public SignalServiceMessageReceiver getMessageReceiver() {
315 return getOrCreate(() -> messageReceiver,
316 () -> messageReceiver = new SignalServiceMessageReceiver(getPushServiceSocket()));
317 }
318
319 public SignalServiceMessageSender getMessageSender() {
320 return getOrCreate(() -> messageSender,
321 () -> messageSender = new SignalServiceMessageSender(getPushServiceSocket(),
322 dataStore,
323 sessionLock,
324 getAttachmentApi(),
325 getMessageApi(),
326 getKeysApi(),
327 Optional.empty(),
328 executor,
329 ServiceConfig.MAX_ENVELOPE_SIZE,
330 () -> true,
331 UsePqRatchet.NO));
332 }
333
334 public List<SecureValueRecovery> getSecureValueRecovery() {
335 return getOrCreate(() -> secureValueRecovery,
336 () -> secureValueRecovery = serviceEnvironmentConfig.svr2Mrenclaves()
337 .stream()
338 .map(mr -> (SecureValueRecovery) getAccountManager().getSecureValueRecoveryV2(mr))
339 .toList());
340 }
341
342 public ProfileApi getProfileApi() {
343 return getOrCreate(() -> profileApi,
344 () -> profileApi = new ProfileApi(getAuthenticatedSignalWebSocket(),
345 getUnauthenticatedSignalWebSocket(),
346 getPushServiceSocket(),
347 getClientZkProfileOperations()));
348 }
349
350 public ProfileService getProfileService() {
351 return getOrCreate(() -> profileService,
352 () -> profileService = new ProfileService(getClientZkProfileOperations(),
353 getAuthenticatedSignalWebSocket(),
354 getUnauthenticatedSignalWebSocket()));
355 }
356
357 public SignalServiceCipher getCipher(ServiceIdType serviceIdType) {
358 final var certificateValidator = new CertificateValidator(serviceEnvironmentConfig.unidentifiedSenderTrustRoot());
359 final var address = new SignalServiceAddress(credentialsProvider.getAci(), credentialsProvider.getE164());
360 final var deviceId = credentialsProvider.getDeviceId();
361 return new SignalServiceCipher(address,
362 deviceId,
363 serviceIdType == ServiceIdType.ACI ? dataStore.aci() : dataStore.pni(),
364 sessionLock,
365 certificateValidator);
366 }
367
368 private <T> T getOrCreate(Supplier<T> supplier, Callable creator) {
369 var value = supplier.get();
370 if (value != null) {
371 return value;
372 }
373
374 synchronized (LOCK) {
375 value = supplier.get();
376 if (value != null) {
377 return value;
378 }
379 creator.call();
380 return supplier.get();
381 }
382 }
383
384 private interface Callable {
385
386 void call();
387 }
388 }