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