Implement unauthenticated chat web socket connection via libsignal-net.

This commit is contained in:
moiseev-signal
2024-04-24 12:19:40 -07:00
committed by Greyson Parrelli
parent 00a91e32fc
commit 95fbd7a31c
13 changed files with 604 additions and 45 deletions

View File

@@ -573,7 +573,7 @@ public class ApplicationDependencies {
if (signalWebSocket == null) {
synchronized (LOCK) {
if (signalWebSocket == null) {
signalWebSocket = provider.provideSignalWebSocket(() -> getSignalServiceNetworkAccess().getConfiguration());
signalWebSocket = provider.provideSignalWebSocket(() -> getSignalServiceNetworkAccess().getConfiguration(), ApplicationDependencies::getLibsignalNetwork);
}
}
}
@@ -726,7 +726,7 @@ public class ApplicationDependencies {
@NonNull SignalCallManager provideSignalCallManager();
@NonNull PendingRetryReceiptManager providePendingRetryReceiptManager();
@NonNull PendingRetryReceiptCache providePendingRetryReceiptCache();
@NonNull SignalWebSocket provideSignalWebSocket(@NonNull Supplier<SignalServiceConfiguration> signalServiceConfigurationSupplier);
@NonNull SignalWebSocket provideSignalWebSocket(@NonNull Supplier<SignalServiceConfiguration> signalServiceConfigurationSupplier, @NonNull Supplier<Network> libSignalNetworkSupplier);
@NonNull SignalServiceDataStoreImpl provideProtocolStore();
@NonNull GiphyMp4Cache provideGiphyMp4Cache();
@NonNull SimpleExoPlayerPool provideExoPlayerPool();

View File

@@ -90,7 +90,10 @@ import org.whispersystems.signalservice.api.util.SleepTimer;
import org.whispersystems.signalservice.api.util.UptimeSleepTimer;
import org.whispersystems.signalservice.api.websocket.WebSocketFactory;
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
import org.whispersystems.signalservice.internal.websocket.LibSignalNetwork;
import org.whispersystems.signalservice.internal.websocket.WebSocketConnection;
import org.whispersystems.signalservice.internal.websocket.LibSignalChatConnection;
import org.whispersystems.signalservice.internal.websocket.OkHttpWebSocketConnection;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
@@ -287,10 +290,10 @@ public class ApplicationDependencyProvider implements ApplicationDependencies.Pr
}
@Override
public @NonNull SignalWebSocket provideSignalWebSocket(@NonNull Supplier<SignalServiceConfiguration> signalServiceConfigurationSupplier) {
public @NonNull SignalWebSocket provideSignalWebSocket(@NonNull Supplier<SignalServiceConfiguration> signalServiceConfigurationSupplier, @NonNull Supplier<Network> libSignalNetworkSupplier) {
SleepTimer sleepTimer = !SignalStore.account().isFcmEnabled() || SignalStore.internalValues().isWebsocketModeForced() ? new AlarmSleepTimer(context) : new UptimeSleepTimer() ;
SignalWebSocketHealthMonitor healthMonitor = new SignalWebSocketHealthMonitor(context, sleepTimer);
SignalWebSocket signalWebSocket = new SignalWebSocket(provideWebSocketFactory(signalServiceConfigurationSupplier, healthMonitor));
SignalWebSocket signalWebSocket = new SignalWebSocket(provideWebSocketFactory(signalServiceConfigurationSupplier, healthMonitor, libSignalNetworkSupplier));
healthMonitor.monitor(signalWebSocket);
@@ -397,26 +400,35 @@ public class ApplicationDependencyProvider implements ApplicationDependencies.Pr
return provideClientZkOperations(signalServiceConfiguration).getReceiptOperations();
}
@NonNull WebSocketFactory provideWebSocketFactory(@NonNull Supplier<SignalServiceConfiguration> signalServiceConfigurationSupplier, @NonNull SignalWebSocketHealthMonitor healthMonitor) {
@NonNull WebSocketFactory provideWebSocketFactory(@NonNull Supplier<SignalServiceConfiguration> signalServiceConfigurationSupplier, @NonNull SignalWebSocketHealthMonitor healthMonitor, @NonNull Supplier<Network> libSignalNetworkSupplier) {
return new WebSocketFactory() {
@Override
public WebSocketConnection createWebSocket() {
return new WebSocketConnection("normal",
signalServiceConfigurationSupplier.get(),
Optional.of(new DynamicCredentialsProvider()),
BuildConfig.SIGNAL_AGENT,
healthMonitor,
Stories.isFeatureEnabled());
return new OkHttpWebSocketConnection("normal",
signalServiceConfigurationSupplier.get(),
Optional.of(new DynamicCredentialsProvider()),
BuildConfig.SIGNAL_AGENT,
healthMonitor,
Stories.isFeatureEnabled());
}
@Override
public WebSocketConnection createUnidentifiedWebSocket() {
return new WebSocketConnection("unidentified",
signalServiceConfigurationSupplier.get(),
Optional.empty(),
BuildConfig.SIGNAL_AGENT,
healthMonitor,
Stories.isFeatureEnabled());
if (FeatureFlags.libSignalWebSocketEnabled()) {
var network = new LibSignalNetwork(libSignalNetworkSupplier.get());
return new LibSignalChatConnection(
"libsignal-unauth",
network.createChatService(null),
healthMonitor,
false);
} else {
return new OkHttpWebSocketConnection("unidentified",
signalServiceConfigurationSupplier.get(),
Optional.empty(),
BuildConfig.SIGNAL_AGENT,
healthMonitor,
Stories.isFeatureEnabled());
}
}
};
}

View File

@@ -9,7 +9,7 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.stories.Stories
import org.whispersystems.signalservice.api.websocket.WebSocketConnectionState
import org.whispersystems.signalservice.internal.util.StaticCredentialsProvider
import org.whispersystems.signalservice.internal.websocket.WebSocketConnection
import org.whispersystems.signalservice.internal.websocket.OkHttpWebSocketConnection
import java.util.Optional
import java.util.concurrent.TimeUnit
@@ -64,7 +64,7 @@ class CheckServiceReachabilityJob private constructor(params: Parameters) : Base
SignalStore.misc().lastCensorshipServiceReachabilityCheckTime = System.currentTimeMillis()
val uncensoredWebsocket = WebSocketConnection(
val uncensoredWebsocket = OkHttpWebSocketConnection(
"uncensored-test",
ApplicationDependencies.getSignalServiceNetworkAccess().uncensoredConfiguration,
Optional.of(

View File

@@ -11,7 +11,7 @@ import org.whispersystems.signalservice.api.util.Preconditions;
import org.whispersystems.signalservice.api.util.SleepTimer;
import org.whispersystems.signalservice.api.websocket.HealthMonitor;
import org.whispersystems.signalservice.api.websocket.WebSocketConnectionState;
import org.whispersystems.signalservice.internal.websocket.WebSocketConnection;
import org.whispersystems.signalservice.internal.websocket.OkHttpWebSocketConnection;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@@ -33,7 +33,7 @@ public final class SignalWebSocketHealthMonitor implements HealthMonitor {
/**
* This is the amount of time in between sent keep alives. Must be greater than {@link SignalWebSocketHealthMonitor#KEEP_ALIVE_TIMEOUT}
*/
private static final long KEEP_ALIVE_SEND_CADENCE = TimeUnit.SECONDS.toMillis(WebSocketConnection.KEEPALIVE_FREQUENCY_SECONDS);
private static final long KEEP_ALIVE_SEND_CADENCE = TimeUnit.SECONDS.toMillis(OkHttpWebSocketConnection.KEEPALIVE_FREQUENCY_SECONDS);
/**
* This is the amount of time we will wait for a response to the keep alive before we consider the websockets dead.

View File

@@ -129,6 +129,7 @@ public final class FeatureFlags {
private static final String MESSAGE_BACKUPS = "android.messageBackups";
private static final String CAMERAX_CUSTOM_CONTROLLER = "android.cameraXCustomController";
private static final String REGISTRATION_V2 = "android.registration.v2";
private static final String LIBSIGNAL_WEB_SOCKET_ENABLED = "android.libsignalWebSocketEnabled";
/**
* We will only store remote values for flags in this set. If you want a flag to be controllable
@@ -208,7 +209,8 @@ public final class FeatureFlags {
CDSI_LIBSIGNAL_NET,
RX_MESSAGE_SEND,
LINKED_DEVICE_LIFESPAN_SECONDS,
CAMERAX_CUSTOM_CONTROLLER
CAMERAX_CUSTOM_CONTROLLER,
LIBSIGNAL_WEB_SOCKET_ENABLED
);
@VisibleForTesting
@@ -754,6 +756,9 @@ public final class FeatureFlags {
return getBoolean(REGISTRATION_V2, false);
}
/** Whether unauthenticated chat web socket is backed by libsignal-net */
public static boolean libSignalWebSocketEnabled() { return getBoolean(LIBSIGNAL_WEB_SOCKET_ENABLED, false); }
/** Only for rendering debug info. */
public static synchronized @NonNull Map<String, Object> getMemoryValues() {
return new TreeMap<>(REMOTE_VALUES);