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