1 package org
.asamk
.signal
.manager
.internal
;
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
;
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
;
53 public class SignalDependencies
{
55 private static final Logger logger
= LoggerFactory
.getLogger(SignalDependencies
.class);
57 private final Object LOCK
= new Object();
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
;
66 private boolean allowStories
= true;
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
;
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
;
91 private List
<SecureValueRecovery
> secureValueRecovery
;
92 private ProfileService profileService
;
93 private ProfileApi profileApi
;
96 final ServiceEnvironmentConfig serviceEnvironmentConfig
,
97 final String userAgent
,
98 final CredentialsProvider credentialsProvider
,
99 final SignalServiceDataStore dataStore
,
100 final ExecutorService executor
,
101 final SignalSessionLock sessionLock
103 this.serviceEnvironmentConfig
= serviceEnvironmentConfig
;
104 this.userAgent
= userAgent
;
105 this.credentialsProvider
= credentialsProvider
;
106 this.dataStore
= dataStore
;
107 this.executor
= executor
;
108 this.sessionLock
= sessionLock
;
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;
123 if (this.authenticatedSignalWebSocket
!= null) {
124 this.authenticatedSignalWebSocket
.forceNewWebSocket();
126 if (this.unauthenticatedSignalWebSocket
!= null) {
127 this.unauthenticatedSignalWebSocket
.forceNewWebSocket();
132 * This method needs to be called before the first websocket is created
134 public void setAllowStories(final boolean allowStories
) {
135 this.allowStories
= allowStories
;
138 public ServiceEnvironmentConfig
getServiceEnvironmentConfig() {
139 return serviceEnvironmentConfig
;
142 public SignalSessionLock
getSessionLock() {
146 public PushServiceSocket
getPushServiceSocket() {
147 return getOrCreate(() -> pushServiceSocket
,
148 () -> pushServiceSocket
= new PushServiceSocket(serviceEnvironmentConfig
.signalServiceConfiguration(),
151 ServiceConfig
.AUTOMATIC_NETWORK_RETRY
));
154 public Network
getLibSignalNetwork() {
155 return getOrCreate(() -> libSignalNetwork
, () -> {
156 libSignalNetwork
= new Network(serviceEnvironmentConfig
.netEnvironment(), userAgent
);
157 setSignalNetworkProxy(libSignalNetwork
);
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
-> {
167 case Proxy
.Type
.HTTP
-> {
169 libSignalNetwork
.setProxy("http", addr
.getHostName(), addr
.getPort(), null, null);
170 } catch (IOException e
) {
171 logger
.warn("Failed to set http proxy", e
);
174 case Proxy
.Type
.SOCKS
-> {
176 libSignalNetwork
.setProxy("socks", addr
.getHostName(), addr
.getPort(), null, null);
177 } catch (IOException e
) {
178 logger
.warn("Failed to set socks proxy", e
);
185 public SignalServiceAccountManager
getAccountManager() {
186 return getOrCreate(() -> accountManager
,
187 () -> accountManager
= new SignalServiceAccountManager(getAuthenticatedSignalWebSocket(),
189 getPushServiceSocket(),
190 getGroupsV2Operations()));
193 public SignalServiceAccountManager
createUnauthenticatedAccountManager(String number
, String password
) {
194 return SignalServiceAccountManager
.createWithStaticCredentials(getServiceEnvironmentConfig().signalServiceConfiguration(),
198 SignalServiceAddress
.DEFAULT_DEVICE_ID
,
201 ServiceConfig
.AUTOMATIC_NETWORK_RETRY
,
202 ServiceConfig
.GROUP_MAX_SIZE
);
205 public AccountApi
getAccountApi() {
206 return getOrCreate(() -> accountApi
, () -> accountApi
= new AccountApi(getAuthenticatedSignalWebSocket()));
209 public RateLimitChallengeApi
getRateLimitChallengeApi() {
210 return getOrCreate(() -> rateLimitChallengeApi
,
211 () -> rateLimitChallengeApi
= new RateLimitChallengeApi(getAuthenticatedSignalWebSocket()));
214 public CdsApi
getCdsApi() {
215 return getOrCreate(() -> cdsApi
, () -> cdsApi
= new CdsApi(getAuthenticatedSignalWebSocket()));
218 public UsernameApi
getUsernameApi() {
219 return getOrCreate(() -> usernameApi
, () -> usernameApi
= new UsernameApi(getUnauthenticatedSignalWebSocket()));
222 public GroupsV2Api
getGroupsV2Api() {
223 return getOrCreate(() -> groupsV2Api
, () -> groupsV2Api
= getAccountManager().getGroupsV2Api());
226 public RegistrationApi
getRegistrationApi() {
227 return getOrCreate(() -> registrationApi
, () -> registrationApi
= getAccountManager().getRegistrationApi());
230 public LinkDeviceApi
getLinkDeviceApi() {
231 return getOrCreate(() -> linkDeviceApi
,
232 () -> linkDeviceApi
= new LinkDeviceApi(getAuthenticatedSignalWebSocket()));
235 private StorageServiceApi
getStorageServiceApi() {
236 return getOrCreate(() -> storageServiceApi
,
237 () -> storageServiceApi
= new StorageServiceApi(getAuthenticatedSignalWebSocket(),
238 getPushServiceSocket()));
241 public StorageServiceRepository
getStorageServiceRepository() {
242 return new StorageServiceRepository(getStorageServiceApi());
245 public CertificateApi
getCertificateApi() {
246 return getOrCreate(() -> certificateApi
,
247 () -> certificateApi
= new CertificateApi(getAuthenticatedSignalWebSocket()));
250 public AttachmentApi
getAttachmentApi() {
251 return getOrCreate(() -> attachmentApi
,
252 () -> attachmentApi
= new AttachmentApi(getAuthenticatedSignalWebSocket(), getPushServiceSocket()));
255 public MessageApi
getMessageApi() {
256 return getOrCreate(() -> messageApi
,
257 () -> messageApi
= new MessageApi(getAuthenticatedSignalWebSocket(),
258 getUnauthenticatedSignalWebSocket()));
261 public KeysApi
getKeysApi() {
262 return getOrCreate(() -> keysApi
,
263 () -> keysApi
= new KeysApi(getAuthenticatedSignalWebSocket(), getUnauthenticatedSignalWebSocket()));
266 public GroupsV2Operations
getGroupsV2Operations() {
267 return getOrCreate(() -> groupsV2Operations
,
268 () -> groupsV2Operations
= new GroupsV2Operations(ClientZkOperations
.create(serviceEnvironmentConfig
.signalServiceConfiguration()),
269 ServiceConfig
.GROUP_MAX_SIZE
));
272 private ClientZkOperations
getClientZkOperations() {
273 return getOrCreate(() -> clientZkOperations
,
274 () -> clientZkOperations
= ClientZkOperations
.create(serviceEnvironmentConfig
.signalServiceConfiguration()));
277 private ClientZkProfileOperations
getClientZkProfileOperations() {
278 final var clientZkOperations
= getClientZkOperations();
279 return clientZkOperations
.getProfileOperations();
282 public SignalWebSocket
.AuthenticatedWebSocket
getAuthenticatedSignalWebSocket() {
283 return getOrCreate(() -> authenticatedSignalWebSocket
, () -> {
284 final var timer
= new UptimeSleepTimer();
285 final var healthMonitor
= new SignalWebSocketHealthMonitor(timer
);
287 authenticatedSignalWebSocket
= new SignalWebSocket
.AuthenticatedWebSocket(() -> new OkHttpWebSocketConnection(
289 serviceEnvironmentConfig
.signalServiceConfiguration(),
290 Optional
.of(credentialsProvider
),
293 allowStories
), () -> true, timer
, TimeUnit
.SECONDS
.toMillis(10));
294 healthMonitor
.monitor(authenticatedSignalWebSocket
);
298 public SignalWebSocket
.UnauthenticatedWebSocket
getUnauthenticatedSignalWebSocket() {
299 return getOrCreate(() -> unauthenticatedSignalWebSocket
, () -> {
300 final var timer
= new UptimeSleepTimer();
301 final var healthMonitor
= new SignalWebSocketHealthMonitor(timer
);
303 unauthenticatedSignalWebSocket
= new SignalWebSocket
.UnauthenticatedWebSocket(() -> new OkHttpWebSocketConnection(
305 serviceEnvironmentConfig
.signalServiceConfiguration(),
309 allowStories
), () -> true, timer
, TimeUnit
.SECONDS
.toMillis(10));
310 healthMonitor
.monitor(unauthenticatedSignalWebSocket
);
314 public SignalServiceMessageReceiver
getMessageReceiver() {
315 return getOrCreate(() -> messageReceiver
,
316 () -> messageReceiver
= new SignalServiceMessageReceiver(getPushServiceSocket()));
319 public SignalServiceMessageSender
getMessageSender() {
320 return getOrCreate(() -> messageSender
,
321 () -> messageSender
= new SignalServiceMessageSender(getPushServiceSocket(),
329 ServiceConfig
.MAX_ENVELOPE_SIZE
,
334 public List
<SecureValueRecovery
> getSecureValueRecovery() {
335 return getOrCreate(() -> secureValueRecovery
,
336 () -> secureValueRecovery
= serviceEnvironmentConfig
.svr2Mrenclaves()
338 .map(mr
-> (SecureValueRecovery
) getAccountManager().getSecureValueRecoveryV2(mr
))
342 public ProfileApi
getProfileApi() {
343 return getOrCreate(() -> profileApi
,
344 () -> profileApi
= new ProfileApi(getAuthenticatedSignalWebSocket(),
345 getUnauthenticatedSignalWebSocket(),
346 getPushServiceSocket(),
347 getClientZkProfileOperations()));
350 public ProfileService
getProfileService() {
351 return getOrCreate(() -> profileService
,
352 () -> profileService
= new ProfileService(getClientZkProfileOperations(),
353 getAuthenticatedSignalWebSocket(),
354 getUnauthenticatedSignalWebSocket()));
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
,
363 serviceIdType
== ServiceIdType
.ACI ? dataStore
.aci() : dataStore
.pni(),
365 certificateValidator
);
368 private <T
> T
getOrCreate(Supplier
<T
> supplier
, Callable creator
) {
369 var value
= supplier
.get();
374 synchronized (LOCK
) {
375 value
= supplier
.get();
380 return supplier
.get();
384 private interface Callable
{