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