]> nmode's Git Repositories - signal-cli/blob - lib/src/main/java/org/asamk/signal/manager/SignalDependencies.java
Filter null from db result
[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 SignalSessionLock getSessionLock() {
92 return sessionLock;
93 }
94
95 public SignalServiceAccountManager getAccountManager() {
96 return getOrCreate(() -> accountManager,
97 () -> accountManager = new SignalServiceAccountManager(serviceEnvironmentConfig.getSignalServiceConfiguration(),
98 credentialsProvider,
99 userAgent,
100 getGroupsV2Operations(),
101 ServiceConfig.AUTOMATIC_NETWORK_RETRY));
102 }
103
104 public SignalServiceAccountManager createUnauthenticatedAccountManager(String number, String password) {
105 return new SignalServiceAccountManager(getServiceEnvironmentConfig().getSignalServiceConfiguration(),
106 null,
107 null,
108 number,
109 SignalServiceAddress.DEFAULT_DEVICE_ID,
110 password,
111 userAgent,
112 ServiceConfig.AUTOMATIC_NETWORK_RETRY,
113 ServiceConfig.GROUP_MAX_SIZE);
114 }
115
116 public GroupsV2Api getGroupsV2Api() {
117 return getOrCreate(() -> groupsV2Api, () -> groupsV2Api = getAccountManager().getGroupsV2Api());
118 }
119
120 public GroupsV2Operations getGroupsV2Operations() {
121 return getOrCreate(() -> groupsV2Operations,
122 () -> groupsV2Operations = capabilities.getGv2()
123 ? new GroupsV2Operations(ClientZkOperations.create(serviceEnvironmentConfig.getSignalServiceConfiguration()),
124 ServiceConfig.GROUP_MAX_SIZE)
125 : null);
126 }
127
128 private ClientZkOperations getClientZkOperations() {
129 return getOrCreate(() -> clientZkOperations,
130 () -> clientZkOperations = capabilities.getGv2()
131 ? ClientZkOperations.create(serviceEnvironmentConfig.getSignalServiceConfiguration())
132 : null);
133 }
134
135 private ClientZkProfileOperations getClientZkProfileOperations() {
136 final var clientZkOperations = getClientZkOperations();
137 return clientZkOperations == null ? null : clientZkOperations.getProfileOperations();
138 }
139
140 public SignalWebSocket getSignalWebSocket() {
141 return getOrCreate(() -> signalWebSocket, () -> {
142 final var timer = new UptimeSleepTimer();
143 final var healthMonitor = new SignalWebSocketHealthMonitor(timer);
144 final var webSocketFactory = new WebSocketFactory() {
145 @Override
146 public WebSocketConnection createWebSocket() {
147 return new WebSocketConnection("normal",
148 serviceEnvironmentConfig.getSignalServiceConfiguration(),
149 Optional.of(credentialsProvider),
150 userAgent,
151 healthMonitor,
152 allowStories);
153 }
154
155 @Override
156 public WebSocketConnection createUnidentifiedWebSocket() {
157 return new WebSocketConnection("unidentified",
158 serviceEnvironmentConfig.getSignalServiceConfiguration(),
159 Optional.empty(),
160 userAgent,
161 healthMonitor,
162 allowStories);
163 }
164 };
165 signalWebSocket = new SignalWebSocket(webSocketFactory);
166 healthMonitor.monitor(signalWebSocket);
167 });
168 }
169
170 public SignalServiceMessageReceiver getMessageReceiver() {
171 return getOrCreate(() -> messageReceiver,
172 () -> messageReceiver = new SignalServiceMessageReceiver(serviceEnvironmentConfig.getSignalServiceConfiguration(),
173 credentialsProvider,
174 userAgent,
175 getClientZkProfileOperations(),
176 ServiceConfig.AUTOMATIC_NETWORK_RETRY));
177 }
178
179 public SignalServiceMessageSender getMessageSender() {
180 return getOrCreate(() -> messageSender,
181 () -> messageSender = new SignalServiceMessageSender(serviceEnvironmentConfig.getSignalServiceConfiguration(),
182 credentialsProvider,
183 dataStore,
184 sessionLock,
185 userAgent,
186 getSignalWebSocket(),
187 Optional.empty(),
188 getClientZkProfileOperations(),
189 executor,
190 ServiceConfig.MAX_ENVELOPE_SIZE,
191 ServiceConfig.AUTOMATIC_NETWORK_RETRY));
192 }
193
194 public KeyBackupService getKeyBackupService() {
195 return getOrCreate(() -> keyBackupService,
196 () -> keyBackupService = getAccountManager().getKeyBackupService(ServiceConfig.getIasKeyStore(),
197 serviceEnvironmentConfig.getKeyBackupConfig().getEnclaveName(),
198 serviceEnvironmentConfig.getKeyBackupConfig().getServiceId(),
199 serviceEnvironmentConfig.getKeyBackupConfig().getMrenclave(),
200 10));
201 }
202
203 public Collection<KeyBackupService> getFallbackKeyBackupServices() {
204 return serviceEnvironmentConfig.getFallbackKeyBackupConfigs()
205 .stream()
206 .map(config -> getAccountManager().getKeyBackupService(ServiceConfig.getIasKeyStore(),
207 config.getEnclaveName(),
208 config.getServiceId(),
209 config.getMrenclave(),
210 10))
211 .toList();
212 }
213
214 public ProfileService getProfileService() {
215 return getOrCreate(() -> profileService,
216 () -> profileService = new ProfileService(getClientZkProfileOperations(),
217 getMessageReceiver(),
218 getSignalWebSocket()));
219 }
220
221 public SignalServiceCipher getCipher() {
222 return getOrCreate(() -> cipher, () -> {
223 final var certificateValidator = new CertificateValidator(serviceEnvironmentConfig.getUnidentifiedSenderTrustRoot());
224 final var address = new SignalServiceAddress(credentialsProvider.getAci(), credentialsProvider.getE164());
225 final var deviceId = credentialsProvider.getDeviceId();
226 cipher = new SignalServiceCipher(address, deviceId, dataStore.aci(), sessionLock, certificateValidator);
227 });
228 }
229
230 private <T> T getOrCreate(Supplier<T> supplier, Callable creator) {
231 var value = supplier.get();
232 if (value != null) {
233 return value;
234 }
235
236 synchronized (LOCK) {
237 value = supplier.get();
238 if (value != null) {
239 return value;
240 }
241 creator.call();
242 return supplier.get();
243 }
244 }
245
246 private interface Callable {
247
248 void call();
249 }
250 }