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