]> nmode's Git Repositories - signal-cli/blob - lib/src/main/java/org/asamk/signal/manager/internal/SignalDependencies.java
90e3b1595e0ad4389b3b6c72cf04a6238a6e5c1f
[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.signal.libsignal.metadata.certificate.CertificateValidator;
6 import org.signal.libsignal.net.Network;
7 import org.signal.libsignal.zkgroup.profiles.ClientZkProfileOperations;
8 import org.whispersystems.signalservice.api.SignalServiceAccountManager;
9 import org.whispersystems.signalservice.api.SignalServiceDataStore;
10 import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
11 import org.whispersystems.signalservice.api.SignalServiceMessageSender;
12 import org.whispersystems.signalservice.api.SignalSessionLock;
13 import org.whispersystems.signalservice.api.SignalWebSocket;
14 import org.whispersystems.signalservice.api.crypto.SignalServiceCipher;
15 import org.whispersystems.signalservice.api.groupsv2.ClientZkOperations;
16 import org.whispersystems.signalservice.api.groupsv2.GroupsV2Api;
17 import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
18 import org.whispersystems.signalservice.api.link.LinkDeviceApi;
19 import org.whispersystems.signalservice.api.push.ServiceIdType;
20 import org.whispersystems.signalservice.api.push.SignalServiceAddress;
21 import org.whispersystems.signalservice.api.registration.RegistrationApi;
22 import org.whispersystems.signalservice.api.services.ProfileService;
23 import org.whispersystems.signalservice.api.storage.StorageServiceApi;
24 import org.whispersystems.signalservice.api.storage.StorageServiceRepository;
25 import org.whispersystems.signalservice.api.svr.SecureValueRecovery;
26 import org.whispersystems.signalservice.api.util.CredentialsProvider;
27 import org.whispersystems.signalservice.api.util.UptimeSleepTimer;
28 import org.whispersystems.signalservice.api.websocket.WebSocketFactory;
29 import org.whispersystems.signalservice.internal.push.ProvisioningSocket;
30 import org.whispersystems.signalservice.internal.push.PushServiceSocket;
31 import org.whispersystems.signalservice.internal.websocket.OkHttpWebSocketConnection;
32 import org.whispersystems.signalservice.internal.websocket.WebSocketConnection;
33
34 import java.util.List;
35 import java.util.Optional;
36 import java.util.concurrent.ExecutorService;
37 import java.util.function.Supplier;
38
39 public class SignalDependencies {
40
41 private final Object LOCK = new Object();
42
43 private final ServiceEnvironmentConfig serviceEnvironmentConfig;
44 private final String userAgent;
45 private final CredentialsProvider credentialsProvider;
46 private final SignalServiceDataStore dataStore;
47 private final ExecutorService executor;
48 private final SignalSessionLock sessionLock;
49
50 private boolean allowStories = true;
51
52 private SignalServiceAccountManager accountManager;
53 private GroupsV2Api groupsV2Api;
54 private RegistrationApi registrationApi;
55 private LinkDeviceApi linkDeviceApi;
56 private StorageServiceApi storageServiceApi;
57 private GroupsV2Operations groupsV2Operations;
58 private ClientZkOperations clientZkOperations;
59
60 private PushServiceSocket pushServiceSocket;
61 private ProvisioningSocket provisioningSocket;
62 private Network libSignalNetwork;
63 private SignalWebSocket signalWebSocket;
64 private SignalServiceMessageReceiver messageReceiver;
65 private SignalServiceMessageSender messageSender;
66
67 private List<SecureValueRecovery> secureValueRecovery;
68 private ProfileService profileService;
69
70 SignalDependencies(
71 final ServiceEnvironmentConfig serviceEnvironmentConfig,
72 final String userAgent,
73 final CredentialsProvider credentialsProvider,
74 final SignalServiceDataStore dataStore,
75 final ExecutorService executor,
76 final SignalSessionLock sessionLock
77 ) {
78 this.serviceEnvironmentConfig = serviceEnvironmentConfig;
79 this.userAgent = userAgent;
80 this.credentialsProvider = credentialsProvider;
81 this.dataStore = dataStore;
82 this.executor = executor;
83 this.sessionLock = sessionLock;
84 }
85
86 public void resetAfterAddressChange() {
87 if (this.pushServiceSocket != null) {
88 this.pushServiceSocket.close();
89 this.pushServiceSocket = null;
90 this.accountManager = null;
91 this.messageReceiver = null;
92 this.messageSender = null;
93 this.profileService = null;
94 this.groupsV2Api = null;
95 this.registrationApi = null;
96 this.secureValueRecovery = null;
97 }
98 getSignalWebSocket().forceNewWebSockets();
99 }
100
101 /**
102 * This method needs to be called before the first websocket is created
103 */
104 public void setAllowStories(final boolean allowStories) {
105 this.allowStories = allowStories;
106 }
107
108 public ServiceEnvironmentConfig getServiceEnvironmentConfig() {
109 return serviceEnvironmentConfig;
110 }
111
112 public SignalSessionLock getSessionLock() {
113 return sessionLock;
114 }
115
116 public PushServiceSocket getPushServiceSocket() {
117 return getOrCreate(() -> pushServiceSocket,
118 () -> pushServiceSocket = new PushServiceSocket(serviceEnvironmentConfig.signalServiceConfiguration(),
119 credentialsProvider,
120 userAgent,
121 getClientZkProfileOperations(),
122 ServiceConfig.AUTOMATIC_NETWORK_RETRY));
123 }
124
125 public ProvisioningSocket getProvisioningSocket() {
126 return getOrCreate(() -> provisioningSocket,
127 () -> provisioningSocket = new ProvisioningSocket(getServiceEnvironmentConfig().signalServiceConfiguration(),
128 userAgent));
129 }
130
131 public Network getLibSignalNetwork() {
132 return getOrCreate(() -> libSignalNetwork,
133 () -> libSignalNetwork = new Network(serviceEnvironmentConfig.netEnvironment(), userAgent));
134 }
135
136 public SignalServiceAccountManager getAccountManager() {
137 return getOrCreate(() -> accountManager,
138 () -> accountManager = new SignalServiceAccountManager(getPushServiceSocket(),
139 getProvisioningSocket(),
140 getGroupsV2Operations()));
141 }
142
143 public SignalServiceAccountManager createUnauthenticatedAccountManager(String number, String password) {
144 return SignalServiceAccountManager.createWithStaticCredentials(getServiceEnvironmentConfig().signalServiceConfiguration(),
145 null,
146 null,
147 number,
148 SignalServiceAddress.DEFAULT_DEVICE_ID,
149 password,
150 userAgent,
151 ServiceConfig.AUTOMATIC_NETWORK_RETRY,
152 ServiceConfig.GROUP_MAX_SIZE);
153 }
154
155 public GroupsV2Api getGroupsV2Api() {
156 return getOrCreate(() -> groupsV2Api, () -> groupsV2Api = getAccountManager().getGroupsV2Api());
157 }
158
159 public RegistrationApi getRegistrationApi() {
160 return getOrCreate(() -> registrationApi, () -> registrationApi = getAccountManager().getRegistrationApi());
161 }
162
163 public LinkDeviceApi getLinkDeviceApi() {
164 return getOrCreate(() -> linkDeviceApi, () -> linkDeviceApi = new LinkDeviceApi(getPushServiceSocket()));
165 }
166
167 private StorageServiceApi getStorageServiceApi() {
168 return getOrCreate(() -> storageServiceApi,
169 () -> storageServiceApi = new StorageServiceApi(getPushServiceSocket()));
170 }
171
172 public StorageServiceRepository getStorageServiceRepository() {
173 return new StorageServiceRepository(getStorageServiceApi());
174 }
175
176 public GroupsV2Operations getGroupsV2Operations() {
177 return getOrCreate(() -> groupsV2Operations,
178 () -> groupsV2Operations = new GroupsV2Operations(ClientZkOperations.create(serviceEnvironmentConfig.signalServiceConfiguration()),
179 ServiceConfig.GROUP_MAX_SIZE));
180 }
181
182 private ClientZkOperations getClientZkOperations() {
183 return getOrCreate(() -> clientZkOperations,
184 () -> clientZkOperations = ClientZkOperations.create(serviceEnvironmentConfig.signalServiceConfiguration()));
185 }
186
187 private ClientZkProfileOperations getClientZkProfileOperations() {
188 final var clientZkOperations = getClientZkOperations();
189 return clientZkOperations.getProfileOperations();
190 }
191
192 public SignalWebSocket getSignalWebSocket() {
193 return getOrCreate(() -> signalWebSocket, () -> {
194 final var timer = new UptimeSleepTimer();
195 final var healthMonitor = new SignalWebSocketHealthMonitor(timer);
196 final var webSocketFactory = new WebSocketFactory() {
197 @Override
198 public WebSocketConnection createWebSocket() {
199 return new OkHttpWebSocketConnection("normal",
200 serviceEnvironmentConfig.signalServiceConfiguration(),
201 Optional.of(credentialsProvider),
202 userAgent,
203 healthMonitor,
204 allowStories);
205 }
206
207 @Override
208 public WebSocketConnection createUnidentifiedWebSocket() {
209 return new OkHttpWebSocketConnection("unidentified",
210 serviceEnvironmentConfig.signalServiceConfiguration(),
211 Optional.empty(),
212 userAgent,
213 healthMonitor,
214 allowStories);
215 }
216 };
217 signalWebSocket = new SignalWebSocket(webSocketFactory);
218 healthMonitor.monitor(signalWebSocket);
219 });
220 }
221
222 public SignalServiceMessageReceiver getMessageReceiver() {
223 return getOrCreate(() -> messageReceiver,
224 () -> messageReceiver = new SignalServiceMessageReceiver(getPushServiceSocket()));
225 }
226
227 public SignalServiceMessageSender getMessageSender() {
228 return getOrCreate(() -> messageSender,
229 () -> messageSender = new SignalServiceMessageSender(getPushServiceSocket(),
230 dataStore,
231 sessionLock,
232 getSignalWebSocket(),
233 Optional.empty(),
234 executor,
235 ServiceConfig.MAX_ENVELOPE_SIZE));
236 }
237
238 public List<SecureValueRecovery> getSecureValueRecovery() {
239 return getOrCreate(() -> secureValueRecovery,
240 () -> secureValueRecovery = serviceEnvironmentConfig.svr2Mrenclaves()
241 .stream()
242 .map(mr -> (SecureValueRecovery) getAccountManager().getSecureValueRecoveryV2(mr))
243 .toList());
244 }
245
246 public ProfileService getProfileService() {
247 return getOrCreate(() -> profileService,
248 () -> profileService = new ProfileService(getClientZkProfileOperations(),
249 getMessageReceiver(),
250 getSignalWebSocket()));
251 }
252
253 public SignalServiceCipher getCipher(ServiceIdType serviceIdType) {
254 final var certificateValidator = new CertificateValidator(serviceEnvironmentConfig.unidentifiedSenderTrustRoot());
255 final var address = new SignalServiceAddress(credentialsProvider.getAci(), credentialsProvider.getE164());
256 final var deviceId = credentialsProvider.getDeviceId();
257 return new SignalServiceCipher(address,
258 deviceId,
259 serviceIdType == ServiceIdType.ACI ? dataStore.aci() : dataStore.pni(),
260 sessionLock,
261 certificateValidator);
262 }
263
264 private <T> T getOrCreate(Supplier<T> supplier, Callable creator) {
265 var value = supplier.get();
266 if (value != null) {
267 return value;
268 }
269
270 synchronized (LOCK) {
271 value = supplier.get();
272 if (value != null) {
273 return value;
274 }
275 creator.call();
276 return supplier.get();
277 }
278 }
279
280 private interface Callable {
281
282 void call();
283 }
284 }