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