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