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