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