]> nmode's Git Repositories - signal-cli/blob - lib/src/main/java/org/asamk/signal/manager/internal/SignalDependencies.java
Update libsignal-service
[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.zkgroup.profiles.ClientZkProfileOperations;
9 import org.slf4j.Logger;
10 import org.slf4j.LoggerFactory;
11 import org.whispersystems.signalservice.api.SignalServiceAccountManager;
12 import org.whispersystems.signalservice.api.SignalServiceDataStore;
13 import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
14 import org.whispersystems.signalservice.api.SignalServiceMessageSender;
15 import org.whispersystems.signalservice.api.SignalSessionLock;
16 import org.whispersystems.signalservice.api.account.AccountApi;
17 import org.whispersystems.signalservice.api.attachment.AttachmentApi;
18 import org.whispersystems.signalservice.api.cds.CdsApi;
19 import org.whispersystems.signalservice.api.certificate.CertificateApi;
20 import org.whispersystems.signalservice.api.crypto.SignalServiceCipher;
21 import org.whispersystems.signalservice.api.groupsv2.ClientZkOperations;
22 import org.whispersystems.signalservice.api.groupsv2.GroupsV2Api;
23 import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
24 import org.whispersystems.signalservice.api.keys.KeysApi;
25 import org.whispersystems.signalservice.api.link.LinkDeviceApi;
26 import org.whispersystems.signalservice.api.message.MessageApi;
27 import org.whispersystems.signalservice.api.profiles.ProfileApi;
28 import org.whispersystems.signalservice.api.push.ServiceIdType;
29 import org.whispersystems.signalservice.api.push.SignalServiceAddress;
30 import org.whispersystems.signalservice.api.ratelimit.RateLimitChallengeApi;
31 import org.whispersystems.signalservice.api.registration.RegistrationApi;
32 import org.whispersystems.signalservice.api.services.ProfileService;
33 import org.whispersystems.signalservice.api.storage.StorageServiceApi;
34 import org.whispersystems.signalservice.api.storage.StorageServiceRepository;
35 import org.whispersystems.signalservice.api.svr.SecureValueRecovery;
36 import org.whispersystems.signalservice.api.username.UsernameApi;
37 import org.whispersystems.signalservice.api.util.CredentialsProvider;
38 import org.whispersystems.signalservice.api.util.UptimeSleepTimer;
39 import org.whispersystems.signalservice.api.websocket.SignalWebSocket;
40 import org.whispersystems.signalservice.internal.push.PushServiceSocket;
41 import org.whispersystems.signalservice.internal.websocket.OkHttpWebSocketConnection;
42
43 import java.io.IOException;
44 import java.net.InetSocketAddress;
45 import java.net.Proxy;
46 import java.util.List;
47 import java.util.Optional;
48 import java.util.concurrent.ExecutorService;
49 import java.util.concurrent.TimeUnit;
50 import java.util.function.Supplier;
51
52 public class SignalDependencies {
53
54 private static final Logger logger = LoggerFactory.getLogger(SignalDependencies.class);
55
56 private final Object LOCK = new Object();
57
58 private final ServiceEnvironmentConfig serviceEnvironmentConfig;
59 private final String userAgent;
60 private final CredentialsProvider credentialsProvider;
61 private final SignalServiceDataStore dataStore;
62 private final ExecutorService executor;
63 private final SignalSessionLock sessionLock;
64
65 private boolean allowStories = true;
66
67 private SignalServiceAccountManager accountManager;
68 private AccountApi accountApi;
69 private RateLimitChallengeApi rateLimitChallengeApi;
70 private CdsApi cdsApi;
71 private UsernameApi usernameApi;
72 private GroupsV2Api groupsV2Api;
73 private RegistrationApi registrationApi;
74 private LinkDeviceApi linkDeviceApi;
75 private StorageServiceApi storageServiceApi;
76 private CertificateApi certificateApi;
77 private AttachmentApi attachmentApi;
78 private MessageApi messageApi;
79 private KeysApi keysApi;
80 private GroupsV2Operations groupsV2Operations;
81 private ClientZkOperations clientZkOperations;
82
83 private PushServiceSocket pushServiceSocket;
84 private Network libSignalNetwork;
85 private SignalWebSocket.AuthenticatedWebSocket authenticatedSignalWebSocket;
86 private SignalWebSocket.UnauthenticatedWebSocket unauthenticatedSignalWebSocket;
87 private SignalServiceMessageReceiver messageReceiver;
88 private SignalServiceMessageSender messageSender;
89
90 private List<SecureValueRecovery> secureValueRecovery;
91 private ProfileService profileService;
92 private ProfileApi profileApi;
93
94 SignalDependencies(
95 final ServiceEnvironmentConfig serviceEnvironmentConfig,
96 final String userAgent,
97 final CredentialsProvider credentialsProvider,
98 final SignalServiceDataStore dataStore,
99 final ExecutorService executor,
100 final SignalSessionLock sessionLock
101 ) {
102 this.serviceEnvironmentConfig = serviceEnvironmentConfig;
103 this.userAgent = userAgent;
104 this.credentialsProvider = credentialsProvider;
105 this.dataStore = dataStore;
106 this.executor = executor;
107 this.sessionLock = sessionLock;
108 }
109
110 public void resetAfterAddressChange() {
111 if (this.pushServiceSocket != null) {
112 this.pushServiceSocket.close();
113 this.pushServiceSocket = null;
114 this.accountManager = null;
115 this.messageReceiver = null;
116 this.messageSender = null;
117 this.profileService = null;
118 this.groupsV2Api = null;
119 this.registrationApi = null;
120 this.secureValueRecovery = null;
121 }
122 if (this.authenticatedSignalWebSocket != null) {
123 this.authenticatedSignalWebSocket.forceNewWebSocket();
124 }
125 if (this.unauthenticatedSignalWebSocket != null) {
126 this.unauthenticatedSignalWebSocket.forceNewWebSocket();
127 }
128 }
129
130 /**
131 * This method needs to be called before the first websocket is created
132 */
133 public void setAllowStories(final boolean allowStories) {
134 this.allowStories = allowStories;
135 }
136
137 public ServiceEnvironmentConfig getServiceEnvironmentConfig() {
138 return serviceEnvironmentConfig;
139 }
140
141 public SignalSessionLock getSessionLock() {
142 return sessionLock;
143 }
144
145 public PushServiceSocket getPushServiceSocket() {
146 return getOrCreate(() -> pushServiceSocket,
147 () -> pushServiceSocket = new PushServiceSocket(serviceEnvironmentConfig.signalServiceConfiguration(),
148 credentialsProvider,
149 userAgent,
150 getClientZkProfileOperations(),
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), 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), 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 }
331
332 public List<SecureValueRecovery> getSecureValueRecovery() {
333 return getOrCreate(() -> secureValueRecovery,
334 () -> secureValueRecovery = serviceEnvironmentConfig.svr2Mrenclaves()
335 .stream()
336 .map(mr -> (SecureValueRecovery) getAccountManager().getSecureValueRecoveryV2(mr))
337 .toList());
338 }
339
340 public ProfileApi getProfileApi() {
341 return getOrCreate(() -> profileApi,
342 () -> profileApi = new ProfileApi(getAuthenticatedSignalWebSocket(), getPushServiceSocket()));
343 }
344
345 public ProfileService getProfileService() {
346 return getOrCreate(() -> profileService,
347 () -> profileService = new ProfileService(getClientZkProfileOperations(),
348 getAuthenticatedSignalWebSocket(),
349 getUnauthenticatedSignalWebSocket()));
350 }
351
352 public SignalServiceCipher getCipher(ServiceIdType serviceIdType) {
353 final var certificateValidator = new CertificateValidator(serviceEnvironmentConfig.unidentifiedSenderTrustRoot());
354 final var address = new SignalServiceAddress(credentialsProvider.getAci(), credentialsProvider.getE164());
355 final var deviceId = credentialsProvider.getDeviceId();
356 return new SignalServiceCipher(address,
357 deviceId,
358 serviceIdType == ServiceIdType.ACI ? dataStore.aci() : dataStore.pni(),
359 sessionLock,
360 certificateValidator);
361 }
362
363 private <T> T getOrCreate(Supplier<T> supplier, Callable creator) {
364 var value = supplier.get();
365 if (value != null) {
366 return value;
367 }
368
369 synchronized (LOCK) {
370 value = supplier.get();
371 if (value != null) {
372 return value;
373 }
374 creator.call();
375 return supplier.get();
376 }
377 }
378
379 private interface Callable {
380
381 void call();
382 }
383 }