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