Separate and kotlinize websockets.

This commit is contained in:
Cody Henthorne
2025-03-05 15:33:15 -05:00
committed by Michelle Tang
parent 6c9acf4657
commit 93d18c1763
26 changed files with 662 additions and 679 deletions

View File

@@ -42,7 +42,6 @@ import org.whispersystems.signalservice.api.SignalServiceAccountManager
import org.whispersystems.signalservice.api.SignalServiceDataStore
import org.whispersystems.signalservice.api.SignalServiceMessageReceiver
import org.whispersystems.signalservice.api.SignalServiceMessageSender
import org.whispersystems.signalservice.api.SignalWebSocket
import org.whispersystems.signalservice.api.archive.ArchiveApi
import org.whispersystems.signalservice.api.attachment.AttachmentApi
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations
@@ -53,6 +52,7 @@ import org.whispersystems.signalservice.api.services.CallLinksService
import org.whispersystems.signalservice.api.services.DonationsService
import org.whispersystems.signalservice.api.services.ProfileService
import org.whispersystems.signalservice.api.storage.StorageServiceApi
import org.whispersystems.signalservice.api.websocket.SignalWebSocket
import org.whispersystems.signalservice.api.websocket.WebSocketConnectionState
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration
import org.whispersystems.signalservice.internal.push.PushServiceSocket
@@ -214,7 +214,7 @@ object AppDependencies {
/**
* An observable that emits the current state of the WebSocket connection across the various lifecycles
* of the [signalWebSocket].
* of the [authWebSocket].
*/
@JvmStatic
val webSocketObserver: LatestValueObservable<WebSocketConnectionState> = LatestValueObservable(_webSocketObserver)
@@ -253,8 +253,12 @@ object AppDependencies {
get() = networkModule.libsignalNetwork
@JvmStatic
val signalWebSocket: SignalWebSocket
get() = networkModule.signalWebSocket
val authWebSocket: SignalWebSocket.AuthenticatedWebSocket
get() = networkModule.authWebSocket
@JvmStatic
val unauthWebSocket: SignalWebSocket.UnauthenticatedWebSocket
get() = networkModule.unauthWebSocket
@JvmStatic
val groupsV2Authorization: GroupsV2Authorization
@@ -326,11 +330,16 @@ object AppDependencies {
_networkModule.reset()
}
@JvmStatic
fun startNetwork() {
networkModule.openConnections()
}
interface Provider {
fun providePushServiceSocket(signalServiceConfiguration: SignalServiceConfiguration, groupsV2Operations: GroupsV2Operations): PushServiceSocket
fun provideGroupsV2Operations(signalServiceConfiguration: SignalServiceConfiguration): GroupsV2Operations
fun provideSignalServiceAccountManager(pushServiceSocket: PushServiceSocket, groupsV2Operations: GroupsV2Operations): SignalServiceAccountManager
fun provideSignalServiceMessageSender(signalWebSocket: SignalWebSocket, protocolStore: SignalServiceDataStore, pushServiceSocket: PushServiceSocket): SignalServiceMessageSender
fun provideSignalServiceMessageSender(authWebSocket: SignalWebSocket.AuthenticatedWebSocket, unauthWebSocket: SignalWebSocket.UnauthenticatedWebSocket, protocolStore: SignalServiceDataStore, pushServiceSocket: PushServiceSocket): SignalServiceMessageSender
fun provideSignalServiceMessageReceiver(pushServiceSocket: PushServiceSocket): SignalServiceMessageReceiver
fun provideSignalServiceNetworkAccess(): SignalServiceNetworkAccess
fun provideRecipientCache(): LiveRecipientCache
@@ -339,7 +348,7 @@ object AppDependencies {
fun provideMegaphoneRepository(): MegaphoneRepository
fun provideEarlyMessageCache(): EarlyMessageCache
fun provideMessageNotifier(): MessageNotifier
fun provideIncomingMessageObserver(signalWebSocket: SignalWebSocket): IncomingMessageObserver
fun provideIncomingMessageObserver(webSocket: SignalWebSocket.AuthenticatedWebSocket): IncomingMessageObserver
fun provideTrimThreadsByDateManager(): TrimThreadsByDateManager
fun provideViewOnceMessageManager(): ViewOnceMessageManager
fun provideExpiringStoriesManager(): ExpiringStoriesManager
@@ -353,14 +362,13 @@ object AppDependencies {
fun provideSignalCallManager(): SignalCallManager
fun providePendingRetryReceiptManager(): PendingRetryReceiptManager
fun providePendingRetryReceiptCache(): PendingRetryReceiptCache
fun provideSignalWebSocket(signalServiceConfigurationSupplier: Supplier<SignalServiceConfiguration>, libSignalNetworkSupplier: Supplier<Network>): SignalWebSocket
fun provideProtocolStore(): SignalServiceDataStoreImpl
fun provideGiphyMp4Cache(): GiphyMp4Cache
fun provideExoPlayerPool(): SimpleExoPlayerPool
fun provideAndroidCallAudioManager(): AudioManagerCompat
fun provideDonationsService(pushServiceSocket: PushServiceSocket): DonationsService
fun provideCallLinksService(pushServiceSocket: PushServiceSocket): CallLinksService
fun provideProfileService(profileOperations: ClientZkProfileOperations, signalServiceMessageReceiver: SignalServiceMessageReceiver, signalWebSocket: SignalWebSocket): ProfileService
fun provideProfileService(profileOperations: ClientZkProfileOperations, signalServiceMessageReceiver: SignalServiceMessageReceiver, authWebSocket: SignalWebSocket.AuthenticatedWebSocket, unauthWebSocket: SignalWebSocket.UnauthenticatedWebSocket): ProfileService
fun provideDeadlockDetector(): DeadlockDetector
fun provideClientZkReceiptOperations(signalServiceConfiguration: SignalServiceConfiguration): ClientZkReceiptOperations
fun provideScheduledMessageManager(): ScheduledMessageManager
@@ -368,9 +376,11 @@ object AppDependencies {
fun provideBillingApi(): BillingApi
fun provideArchiveApi(pushServiceSocket: PushServiceSocket): ArchiveApi
fun provideKeysApi(pushServiceSocket: PushServiceSocket): KeysApi
fun provideAttachmentApi(signalWebSocket: SignalWebSocket, pushServiceSocket: PushServiceSocket): AttachmentApi
fun provideAttachmentApi(authWebSocket: SignalWebSocket.AuthenticatedWebSocket, pushServiceSocket: PushServiceSocket): AttachmentApi
fun provideLinkDeviceApi(pushServiceSocket: PushServiceSocket): LinkDeviceApi
fun provideRegistrationApi(pushServiceSocket: PushServiceSocket): RegistrationApi
fun provideStorageServiceApi(pushServiceSocket: PushServiceSocket): StorageServiceApi
fun provideAuthWebSocket(signalServiceConfigurationSupplier: Supplier<SignalServiceConfiguration>, libSignalNetworkSupplier: Supplier<Network>): SignalWebSocket.AuthenticatedWebSocket
fun provideUnauthWebSocket(signalServiceConfigurationSupplier: Supplier<SignalServiceConfiguration>, libSignalNetworkSupplier: Supplier<Network>): SignalWebSocket.UnauthenticatedWebSocket
}
}

View File

@@ -81,7 +81,6 @@ import org.whispersystems.signalservice.api.SignalServiceAccountManager;
import org.whispersystems.signalservice.api.SignalServiceDataStore;
import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
import org.whispersystems.signalservice.api.SignalWebSocket;
import org.whispersystems.signalservice.api.archive.ArchiveApi;
import org.whispersystems.signalservice.api.attachment.AttachmentApi;
import org.whispersystems.signalservice.api.groupsv2.ClientZkOperations;
@@ -98,6 +97,8 @@ import org.whispersystems.signalservice.api.storage.StorageServiceApi;
import org.whispersystems.signalservice.api.util.CredentialsProvider;
import org.whispersystems.signalservice.api.util.SleepTimer;
import org.whispersystems.signalservice.api.util.UptimeSleepTimer;
import org.whispersystems.signalservice.api.websocket.HealthMonitor;
import org.whispersystems.signalservice.api.websocket.SignalWebSocket;
import org.whispersystems.signalservice.api.websocket.WebSocketFactory;
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
import org.whispersystems.signalservice.internal.push.PushServiceSocket;
@@ -147,11 +148,12 @@ public class ApplicationDependencyProvider implements AppDependencies.Provider {
}
@Override
public @NonNull SignalServiceMessageSender provideSignalServiceMessageSender(@NonNull SignalWebSocket signalWebSocket, @NonNull SignalServiceDataStore protocolStore, @NonNull PushServiceSocket pushServiceSocket) {
public @NonNull SignalServiceMessageSender provideSignalServiceMessageSender(@NonNull SignalWebSocket.AuthenticatedWebSocket authWebSocket, @NonNull SignalWebSocket.UnauthenticatedWebSocket unauthWebSocket, @NonNull SignalServiceDataStore protocolStore, @NonNull PushServiceSocket pushServiceSocket) {
return new SignalServiceMessageSender(pushServiceSocket,
protocolStore,
ReentrantSessionLock.INSTANCE,
signalWebSocket,
authWebSocket,
unauthWebSocket,
Optional.of(new SecurityEventListener(context)),
SignalExecutors.newCachedBoundedExecutor("signal-messages", ThreadUtil.PRIORITY_IMPORTANT_BACKGROUND_THREAD, 1, 16, 30),
ByteUnit.KILOBYTES.toBytes(256));
@@ -207,8 +209,8 @@ public class ApplicationDependencyProvider implements AppDependencies.Provider {
}
@Override
public @NonNull IncomingMessageObserver provideIncomingMessageObserver(@NonNull SignalWebSocket signalWebSocket) {
return new IncomingMessageObserver(context, signalWebSocket);
public @NonNull IncomingMessageObserver provideIncomingMessageObserver(@NonNull SignalWebSocket.AuthenticatedWebSocket webSocket) {
return new IncomingMessageObserver(context, webSocket);
}
@Override
@@ -297,15 +299,29 @@ public class ApplicationDependencyProvider implements AppDependencies.Provider {
}
@Override
public @NonNull SignalWebSocket provideSignalWebSocket(@NonNull Supplier<SignalServiceConfiguration> signalServiceConfigurationSupplier, @NonNull Supplier<Network> libSignalNetworkSupplier) {
SleepTimer sleepTimer = !SignalStore.account().isFcmEnabled() || SignalStore.internal().isWebsocketModeForced() ? new AlarmSleepTimer(context) : new UptimeSleepTimer();
SignalWebSocketHealthMonitor healthMonitor = new SignalWebSocketHealthMonitor(context, sleepTimer);
WebSocketShadowingBridge bridge = new DefaultWebSocketShadowingBridge(context);
SignalWebSocket signalWebSocket = new SignalWebSocket(provideWebSocketFactory(signalServiceConfigurationSupplier, healthMonitor, libSignalNetworkSupplier, bridge));
public @NonNull SignalWebSocket.AuthenticatedWebSocket provideAuthWebSocket(@NonNull Supplier<SignalServiceConfiguration> signalServiceConfigurationSupplier, @NonNull Supplier<Network> libSignalNetworkSupplier) {
SleepTimer sleepTimer = !SignalStore.account().isFcmEnabled() || SignalStore.internal().isWebsocketModeForced() ? new AlarmSleepTimer(context) : new UptimeSleepTimer();
SignalWebSocketHealthMonitor healthMonitor = new SignalWebSocketHealthMonitor(sleepTimer);
WebSocketShadowingBridge bridge = new DefaultWebSocketShadowingBridge(context);
WebSocketFactory webSocketFactory = provideWebSocketFactory(signalServiceConfigurationSupplier, healthMonitor, libSignalNetworkSupplier, bridge);
SignalWebSocket.AuthenticatedWebSocket webSocket = new SignalWebSocket.AuthenticatedWebSocket(webSocketFactory::createWebSocket);
healthMonitor.monitor(signalWebSocket);
healthMonitor.monitor(webSocket);
return signalWebSocket;
return webSocket;
}
@Override
public @NonNull SignalWebSocket.UnauthenticatedWebSocket provideUnauthWebSocket(@NonNull Supplier<SignalServiceConfiguration> signalServiceConfigurationSupplier, @NonNull Supplier<Network> libSignalNetworkSupplier) {
SleepTimer sleepTimer = !SignalStore.account().isFcmEnabled() || SignalStore.internal().isWebsocketModeForced() ? new AlarmSleepTimer(context) : new UptimeSleepTimer();
SignalWebSocketHealthMonitor healthMonitor = new SignalWebSocketHealthMonitor(sleepTimer);
WebSocketShadowingBridge bridge = new DefaultWebSocketShadowingBridge(context);
WebSocketFactory webSocketFactory = provideWebSocketFactory(signalServiceConfigurationSupplier, healthMonitor, libSignalNetworkSupplier, bridge);
SignalWebSocket.UnauthenticatedWebSocket webSocket = new SignalWebSocket.UnauthenticatedWebSocket(webSocketFactory::createUnidentifiedWebSocket);
healthMonitor.monitor(webSocket);
return webSocket;
}
@Override
@@ -383,9 +399,10 @@ public class ApplicationDependencyProvider implements AppDependencies.Provider {
@Override
public @NonNull ProfileService provideProfileService(@NonNull ClientZkProfileOperations clientZkProfileOperations,
@NonNull SignalServiceMessageReceiver receiver,
@NonNull SignalWebSocket signalWebSocket)
@NonNull SignalWebSocket.AuthenticatedWebSocket authWebSocket,
@NonNull SignalWebSocket.UnauthenticatedWebSocket unauthWebSocket)
{
return new ProfileService(clientZkProfileOperations, receiver, signalWebSocket);
return new ProfileService(clientZkProfileOperations, receiver, authWebSocket, unauthWebSocket);
}
@Override
@@ -401,7 +418,7 @@ public class ApplicationDependencyProvider implements AppDependencies.Provider {
}
@NonNull WebSocketFactory provideWebSocketFactory(@NonNull Supplier<SignalServiceConfiguration> signalServiceConfigurationSupplier,
@NonNull SignalWebSocketHealthMonitor healthMonitor,
@NonNull HealthMonitor healthMonitor,
@NonNull Supplier<Network> libSignalNetworkSupplier,
@NonNull WebSocketShadowingBridge bridge)
{
@@ -479,8 +496,8 @@ public class ApplicationDependencyProvider implements AppDependencies.Provider {
}
@Override
public @NonNull AttachmentApi provideAttachmentApi(@NonNull SignalWebSocket signalWebSocket, @NonNull PushServiceSocket pushServiceSocket) {
return new AttachmentApi(signalWebSocket, pushServiceSocket);
public @NonNull AttachmentApi provideAttachmentApi(@NonNull SignalWebSocket.AuthenticatedWebSocket authWebSocket, @NonNull PushServiceSocket pushServiceSocket) {
return new AttachmentApi(authWebSocket, pushServiceSocket);
}
@Override

View File

@@ -26,7 +26,6 @@ import org.thoughtcrime.securesms.push.SignalServiceTrustStore
import org.whispersystems.signalservice.api.SignalServiceAccountManager
import org.whispersystems.signalservice.api.SignalServiceMessageReceiver
import org.whispersystems.signalservice.api.SignalServiceMessageSender
import org.whispersystems.signalservice.api.SignalWebSocket
import org.whispersystems.signalservice.api.archive.ArchiveApi
import org.whispersystems.signalservice.api.attachment.AttachmentApi
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations
@@ -39,6 +38,7 @@ import org.whispersystems.signalservice.api.services.DonationsService
import org.whispersystems.signalservice.api.services.ProfileService
import org.whispersystems.signalservice.api.storage.StorageServiceApi
import org.whispersystems.signalservice.api.util.Tls12SocketFactory
import org.whispersystems.signalservice.api.websocket.SignalWebSocket
import org.whispersystems.signalservice.api.websocket.WebSocketConnectionState
import org.whispersystems.signalservice.internal.push.PushServiceSocket
import org.whispersystems.signalservice.internal.util.BlacklistingTrustManager
@@ -70,12 +70,12 @@ class NetworkDependenciesModule(
val protocolStore: SignalServiceDataStoreImpl by _protocolStore
private val _signalServiceMessageSender = resettableLazy {
provider.provideSignalServiceMessageSender(signalWebSocket, protocolStore, pushServiceSocket)
provider.provideSignalServiceMessageSender(authWebSocket, unauthWebSocket, protocolStore, pushServiceSocket)
}
val signalServiceMessageSender: SignalServiceMessageSender by _signalServiceMessageSender
val incomingMessageObserver: IncomingMessageObserver by lazy {
provider.provideIncomingMessageObserver(signalWebSocket)
provider.provideIncomingMessageObserver(authWebSocket)
}
val pushServiceSocket: PushServiceSocket by lazy {
@@ -90,12 +90,16 @@ class NetworkDependenciesModule(
provider.provideLibsignalNetwork(signalServiceNetworkAccess.getConfiguration())
}
val signalWebSocket: SignalWebSocket by lazy {
provider.provideSignalWebSocket({ signalServiceNetworkAccess.getConfiguration() }, { libsignalNetwork }).also {
disposables += it.webSocketState.subscribe { webSocketStateSubject.onNext(it) }
val authWebSocket: SignalWebSocket.AuthenticatedWebSocket by lazy {
provider.provideAuthWebSocket({ signalServiceNetworkAccess.getConfiguration() }, { libsignalNetwork }).also {
disposables += it.state.subscribe { s -> webSocketStateSubject.onNext(s) }
}
}
val unauthWebSocket: SignalWebSocket.UnauthenticatedWebSocket by lazy {
provider.provideUnauthWebSocket({ signalServiceNetworkAccess.getConfiguration() }, { libsignalNetwork })
}
val groupsV2Authorization: GroupsV2Authorization by lazy {
val authCache: GroupsV2Authorization.ValueCache = GroupsV2AuthorizationMemoryValueCache(SignalStore.groupsV2AciAuthorizationCache)
GroupsV2Authorization(signalServiceAccountManager.groupsV2Api, authCache)
@@ -122,7 +126,7 @@ class NetworkDependenciesModule(
}
val profileService: ProfileService by lazy {
provider.provideProfileService(groupsV2Operations.profileOperations, signalServiceMessageReceiver, signalWebSocket)
provider.provideProfileService(groupsV2Operations.profileOperations, signalServiceMessageReceiver, authWebSocket, unauthWebSocket)
}
val donationsService: DonationsService by lazy {
@@ -138,7 +142,7 @@ class NetworkDependenciesModule(
}
val attachmentApi: AttachmentApi by lazy {
provider.provideAttachmentApi(signalWebSocket, pushServiceSocket)
provider.provideAttachmentApi(authWebSocket, pushServiceSocket)
}
val linkDeviceApi: LinkDeviceApi by lazy {
@@ -185,9 +189,15 @@ class NetworkDependenciesModule(
if (_signalServiceMessageSender.isInitialized()) {
signalServiceMessageSender.cancelInFlightRequests()
}
unauthWebSocket.disconnect()
disposables.clear()
}
fun openConnections() {
incomingMessageObserver
unauthWebSocket.connect()
}
fun resetProtocolStores() {
_protocolStore.reset()
_signalServiceMessageSender.reset()