]> nmode's Git Repositories - signal-cli/blob - lib/src/main/java/org/asamk/signal/manager/SignalDependencies.java
Implement receive handling for story messages
[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.Optional;
26 import java.util.concurrent.ExecutorService;
27 import java.util.function.Supplier;
28
29 import static org.asamk.signal.manager.config.ServiceConfig.capabilities;
30
31 public class SignalDependencies {
32
33 private final Object LOCK = new Object();
34
35 private final ServiceEnvironmentConfig serviceEnvironmentConfig;
36 private final String userAgent;
37 private final CredentialsProvider credentialsProvider;
38 private final SignalServiceDataStore dataStore;
39 private final ExecutorService executor;
40 private final SignalSessionLock sessionLock;
41
42 private SignalServiceAccountManager accountManager;
43 private GroupsV2Api groupsV2Api;
44 private GroupsV2Operations groupsV2Operations;
45 private ClientZkOperations clientZkOperations;
46
47 private SignalWebSocket signalWebSocket;
48 private SignalServiceMessageReceiver messageReceiver;
49 private SignalServiceMessageSender messageSender;
50
51 private KeyBackupService keyBackupService;
52 private ProfileService profileService;
53 private SignalServiceCipher cipher;
54
55 SignalDependencies(
56 final ServiceEnvironmentConfig serviceEnvironmentConfig,
57 final String userAgent,
58 final CredentialsProvider credentialsProvider,
59 final SignalServiceDataStore dataStore,
60 final ExecutorService executor,
61 final SignalSessionLock sessionLock
62 ) {
63 this.serviceEnvironmentConfig = serviceEnvironmentConfig;
64 this.userAgent = userAgent;
65 this.credentialsProvider = credentialsProvider;
66 this.dataStore = dataStore;
67 this.executor = executor;
68 this.sessionLock = sessionLock;
69 }
70
71 public void resetAfterAddressChange() {
72 this.messageSender = null;
73 this.cipher = null;
74 }
75
76 public ServiceEnvironmentConfig getServiceEnvironmentConfig() {
77 return serviceEnvironmentConfig;
78 }
79
80 public SignalServiceAccountManager getAccountManager() {
81 return getOrCreate(() -> accountManager,
82 () -> accountManager = new SignalServiceAccountManager(serviceEnvironmentConfig.getSignalServiceConfiguration(),
83 credentialsProvider,
84 userAgent,
85 getGroupsV2Operations(),
86 ServiceConfig.AUTOMATIC_NETWORK_RETRY));
87 }
88
89 public SignalServiceAccountManager createUnauthenticatedAccountManager(String number, String password) {
90 return new SignalServiceAccountManager(getServiceEnvironmentConfig().getSignalServiceConfiguration(),
91 null,
92 null,
93 number,
94 SignalServiceAddress.DEFAULT_DEVICE_ID,
95 password,
96 userAgent,
97 ServiceConfig.AUTOMATIC_NETWORK_RETRY,
98 ServiceConfig.GROUP_MAX_SIZE);
99 }
100
101 public GroupsV2Api getGroupsV2Api() {
102 return getOrCreate(() -> groupsV2Api, () -> groupsV2Api = getAccountManager().getGroupsV2Api());
103 }
104
105 public GroupsV2Operations getGroupsV2Operations() {
106 return getOrCreate(() -> groupsV2Operations,
107 () -> groupsV2Operations = capabilities.isGv2()
108 ? new GroupsV2Operations(ClientZkOperations.create(serviceEnvironmentConfig.getSignalServiceConfiguration()),
109 ServiceConfig.GROUP_MAX_SIZE)
110 : null);
111 }
112
113 private ClientZkOperations getClientZkOperations() {
114 return getOrCreate(() -> clientZkOperations,
115 () -> clientZkOperations = capabilities.isGv2()
116 ? ClientZkOperations.create(serviceEnvironmentConfig.getSignalServiceConfiguration())
117 : null);
118 }
119
120 private ClientZkProfileOperations getClientZkProfileOperations() {
121 final var clientZkOperations = getClientZkOperations();
122 return clientZkOperations == null ? null : clientZkOperations.getProfileOperations();
123 }
124
125 public SignalWebSocket getSignalWebSocket() {
126 return getOrCreate(() -> signalWebSocket, () -> {
127 final var timer = new UptimeSleepTimer();
128 final var healthMonitor = new SignalWebSocketHealthMonitor(timer);
129 final var webSocketFactory = new WebSocketFactory() {
130 @Override
131 public WebSocketConnection createWebSocket() {
132 return new WebSocketConnection("normal",
133 serviceEnvironmentConfig.getSignalServiceConfiguration(),
134 Optional.of(credentialsProvider),
135 userAgent,
136 healthMonitor);
137 }
138
139 @Override
140 public WebSocketConnection createUnidentifiedWebSocket() {
141 return new WebSocketConnection("unidentified",
142 serviceEnvironmentConfig.getSignalServiceConfiguration(),
143 Optional.empty(),
144 userAgent,
145 healthMonitor);
146 }
147 };
148 signalWebSocket = new SignalWebSocket(webSocketFactory);
149 healthMonitor.monitor(signalWebSocket);
150 });
151 }
152
153 public SignalServiceMessageReceiver getMessageReceiver() {
154 return getOrCreate(() -> messageReceiver,
155 () -> messageReceiver = new SignalServiceMessageReceiver(serviceEnvironmentConfig.getSignalServiceConfiguration(),
156 credentialsProvider,
157 userAgent,
158 getClientZkProfileOperations(),
159 ServiceConfig.AUTOMATIC_NETWORK_RETRY));
160 }
161
162 public SignalServiceMessageSender getMessageSender() {
163 return getOrCreate(() -> messageSender,
164 () -> messageSender = new SignalServiceMessageSender(serviceEnvironmentConfig.getSignalServiceConfiguration(),
165 credentialsProvider,
166 dataStore,
167 sessionLock,
168 userAgent,
169 getSignalWebSocket(),
170 Optional.empty(),
171 getClientZkProfileOperations(),
172 executor,
173 ServiceConfig.MAX_ENVELOPE_SIZE,
174 ServiceConfig.AUTOMATIC_NETWORK_RETRY));
175 }
176
177 public KeyBackupService getKeyBackupService() {
178 return getOrCreate(() -> keyBackupService,
179 () -> keyBackupService = getAccountManager().getKeyBackupService(ServiceConfig.getIasKeyStore(),
180 serviceEnvironmentConfig.getKeyBackupConfig().getEnclaveName(),
181 serviceEnvironmentConfig.getKeyBackupConfig().getServiceId(),
182 serviceEnvironmentConfig.getKeyBackupConfig().getMrenclave(),
183 10));
184 }
185
186 public ProfileService getProfileService() {
187 return getOrCreate(() -> profileService,
188 () -> profileService = new ProfileService(getClientZkProfileOperations(),
189 getMessageReceiver(),
190 getSignalWebSocket()));
191 }
192
193 public SignalServiceCipher getCipher() {
194 return getOrCreate(() -> cipher, () -> {
195 final var certificateValidator = new CertificateValidator(serviceEnvironmentConfig.getUnidentifiedSenderTrustRoot());
196 final var address = new SignalServiceAddress(credentialsProvider.getAci(), credentialsProvider.getE164());
197 final var deviceId = credentialsProvider.getDeviceId();
198 cipher = new SignalServiceCipher(address, deviceId, dataStore.aci(), sessionLock, certificateValidator);
199 });
200 }
201
202 private <T> T getOrCreate(Supplier<T> supplier, Callable creator) {
203 var value = supplier.get();
204 if (value != null) {
205 return value;
206 }
207
208 synchronized (LOCK) {
209 value = supplier.get();
210 if (value != null) {
211 return value;
212 }
213 creator.call();
214 return supplier.get();
215 }
216 }
217
218 private interface Callable {
219
220 void call();
221 }
222 }