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