diff --git a/package.json b/package.json index 74647c68a..aba9f77b2 100644 --- a/package.json +++ b/package.json @@ -219,7 +219,7 @@ "@indutny/parallel-prettier": "3.0.0", "@indutny/rezip-electron": "2.0.1", "@napi-rs/canvas": "0.1.61", - "@signalapp/mock-server": "10.5.0", + "@signalapp/mock-server": "11.0.0", "@storybook/addon-a11y": "8.4.4", "@storybook/addon-actions": "8.4.4", "@storybook/addon-controls": "8.4.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 06bc21af5..5a95b009d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -432,8 +432,8 @@ importers: specifier: 0.1.61 version: 0.1.61 '@signalapp/mock-server': - specifier: 10.5.0 - version: 10.5.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + specifier: 11.0.0 + version: 11.0.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) '@storybook/addon-a11y': specifier: 8.4.4 version: 8.4.4(storybook@8.4.4(bufferutil@4.0.9)(prettier@3.3.3)(utf-8-validate@5.0.10)) @@ -2530,8 +2530,8 @@ packages: '@signalapp/libsignal-client@0.66.2': resolution: {integrity: sha512-zwgU0LXIJjJNVBxJWnjbJN1+gIUJ+eY+BnqIP1d0751Sq1zy5VMHs+/5nmEyVGNn6ptD0qseYXkxtr/XLs07Lw==} - '@signalapp/mock-server@10.5.0': - resolution: {integrity: sha512-w7KXcWYRPXhAxYWzeBNesu+A9DO6FYJUhg52md3M9yQkPR2Yr/YBvc9zBhFo5fafZmkaRoxDoz9y29Ivd5ZykQ==} + '@signalapp/mock-server@11.0.0': + resolution: {integrity: sha512-JHEqdjXvWcXyLJ90OtaTIQVtizH/w+rmnPplNmHuUiDZIQIEvE3lRyZFyIvgVTNg29lQWs/Gw/o+hICerdOChQ==} '@signalapp/parchment-cjs@3.0.1': resolution: {integrity: sha512-hSBMQ1M7wE4GcC8ZeNtvpJF+DAJg3eIRRf1SiHS3I3Algav/sgJJNm6HIYm6muHuK7IJmuEjkL3ILSXgmu0RfQ==} @@ -6802,9 +6802,6 @@ packages: resolution: {integrity: sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==} engines: {node: '>= 0.6.0'} - long@4.0.0: - resolution: {integrity: sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==} - long@5.2.3: resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} @@ -12262,7 +12259,7 @@ snapshots: type-fest: 4.26.1 uuid: 8.3.2 - '@signalapp/mock-server@10.5.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)': + '@signalapp/mock-server@11.0.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)': dependencies: '@indutny/parallel-prettier': 3.0.0(prettier@3.3.3) '@signalapp/libsignal-client': 0.60.2 @@ -12270,7 +12267,7 @@ snapshots: '@tus/server': 1.10.2 debug: 4.3.7(supports-color@8.1.1) is-plain-obj: 3.0.0 - long: 4.0.0 + long: 5.2.3 micro: 9.4.1 microrouter: 3.1.3 prettier: 3.3.3 @@ -17566,8 +17563,6 @@ snapshots: loglevel@1.9.2: {} - long@4.0.0: {} - long@5.2.3: {} longest-streak@2.0.4: {} diff --git a/ts/CI.ts b/ts/CI.ts index 3d9d5dd9c..96d5ec513 100644 --- a/ts/CI.ts +++ b/ts/CI.ts @@ -17,6 +17,7 @@ import { SECOND } from './util/durations'; import { isSignalRoute } from './util/signalRoutes'; import { strictAssert } from './util/assert'; import { MessageModel } from './models/messages'; +import type { SocketStatuses } from './textsecure/SocketManager'; type ResolveType = (data: unknown) => void; @@ -28,6 +29,7 @@ export type CIType = { sentAt: number ): Promise>; getPendingEventCount: (event: string) => number; + getSocketStatus: () => SocketStatuses; handleEvent: (event: string, data: unknown) => unknown; setProvisioningURL: (url: string) => unknown; solveChallenge: (response: ChallengeResponseType) => unknown; @@ -202,6 +204,10 @@ export function getCI({ handleEvent('print', format(...args)); } + function getSocketStatus() { + return window.getSocketStatus(); + } + async function resetReleaseNotesFetcher() { await Promise.all([ window.textsecure.storage.put( @@ -218,6 +224,7 @@ export function getCI({ getConversationId, createNotificationToken, getMessagesBySentAt, + getSocketStatus, handleEvent, setProvisioningURL, solveChallenge, diff --git a/ts/background.ts b/ts/background.ts index 5c7e958d2..b2d542891 100644 --- a/ts/background.ts +++ b/ts/background.ts @@ -398,7 +398,10 @@ export async function startApp(): Promise { window.getSocketStatus = () => { if (server === undefined) { - return SocketStatus.CLOSED; + return { + authenticated: { status: SocketStatus.CLOSED }, + unauthenticated: { status: SocketStatus.CLOSED }, + }; } return server.getSocketStatus(); }; @@ -1141,7 +1144,8 @@ export async function startApp(): Promise { setupAppState(); drop(start()); window.Signal.Services.initializeNetworkObserver( - window.reduxActions.network + window.reduxActions.network, + () => window.getSocketStatus().authenticated.status ); window.Signal.Services.initializeUpdateListener( window.reduxActions.updates @@ -1947,7 +1951,7 @@ export async function startApp(): Promise { window.addEventListener('offline', onNavigatorOffline); window.Whisper.events.on('socketStatusChange', () => { - if (window.getSocketStatus() === SocketStatus.OPEN) { + if (window.getSocketStatus().authenticated.status === SocketStatus.OPEN) { pauseQueuesAndNotificationsOnSocketConnect(); } }); @@ -1976,7 +1980,7 @@ export async function startApp(): Promise { } function isSocketOnline() { - const socketStatus = window.getSocketStatus(); + const socketStatus = window.getSocketStatus().authenticated.status; return ( socketStatus === SocketStatus.CONNECTING || socketStatus === SocketStatus.OPEN diff --git a/ts/components/Inbox.tsx b/ts/components/Inbox.tsx index faf16deb3..d12d1565a 100644 --- a/ts/components/Inbox.tsx +++ b/ts/components/Inbox.tsx @@ -61,7 +61,7 @@ export function Inbox({ } const interval = setInterval(() => { - const status = window.getSocketStatus(); + const { status } = window.getSocketStatus().authenticated; switch (status) { case 'CONNECTING': break; diff --git a/ts/services/networkObserver.ts b/ts/services/networkObserver.ts index 4166deed0..a2b0d6630 100644 --- a/ts/services/networkObserver.ts +++ b/ts/services/networkObserver.ts @@ -5,7 +5,6 @@ import type { SetNetworkStatusPayloadType, NetworkActionType, } from '../state/ducks/network'; -import { getSocketStatus } from '../shims/socketStatus'; import * as log from '../logging/log'; import { SECOND } from '../util/durations'; import { electronLookup } from '../util/dns'; @@ -31,14 +30,15 @@ type NetworkActions = { }; export function initializeNetworkObserver( - networkActions: NetworkActions + networkActions: NetworkActions, + getAuthSocketStatus: () => SocketStatus ): void { log.info('Initializing network observer'); let onlineStatus = OnlineStatus.Online; const refresh = () => { - const socketStatus = getSocketStatus(); + const socketStatus = getAuthSocketStatus(); networkActions.setNetworkStatus({ isOnline: onlineStatus !== OnlineStatus.Offline, diff --git a/ts/shims/socketStatus.ts b/ts/shims/socketStatus.ts deleted file mode 100644 index 8353a3bac..000000000 --- a/ts/shims/socketStatus.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2020 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import type { SocketStatus } from '../types/SocketStatus'; - -export function getSocketStatus(): SocketStatus { - const { getSocketStatus: getMessageReceiverStatus } = window; - - return getMessageReceiverStatus(); -} diff --git a/ts/test-mock/bootstrap.ts b/ts/test-mock/bootstrap.ts index b018036a2..81f0c37aa 100644 --- a/ts/test-mock/bootstrap.ts +++ b/ts/test-mock/bootstrap.ts @@ -142,6 +142,15 @@ function sanitizePathComponent(component: string): string { return normalizePath(component.replace(/[^a-z]+/gi, '-')); } +const DEFAULT_REMOTE_CONFIG = [ + ['desktop.backup.credentialFetch', { enabled: true }], + ['desktop.internalUser', { enabled: true }], + ['desktop.releaseNotes', { enabled: true }], + ['desktop.senderKey.retry', { enabled: true }], + ['global.groupsv2.groupSizeHardLimit', { enabled: true, value: '64' }], + ['global.groupsv2.maxGroupSize', { enabled: true, value: '32' }], +] as const; + // // Bootstrap is a class that prepares mock server and desktop for running // tests/benchmarks. @@ -266,6 +275,10 @@ export class Bootstrap { path.join(os.tmpdir(), 'mock-signal-') ); + DEFAULT_REMOTE_CONFIG.forEach(([key, value]) => + this.server.setRemoteConfig(key, value) + ); + debug('setting storage path=%j', this.#storagePath); } @@ -725,7 +738,7 @@ export class Bootstrap { storagePath: this.#storagePath, storageProfile: 'mock', serverUrl: url, - storageUrl: url, + storageUrl: `${url}/storageService`, resourcesUrl: `${url}/updates2`, sfuUrl: url, cdn: { diff --git a/ts/test-mock/network/libsignal_test.ts b/ts/test-mock/network/libsignal_test.ts new file mode 100644 index 000000000..45d05e9b9 --- /dev/null +++ b/ts/test-mock/network/libsignal_test.ts @@ -0,0 +1,95 @@ +// Copyright 2025 Signal Messenger, LLC +// SPDX-License-Identifier: AGPL-3.0-only +import createDebug from 'debug'; +import { assert } from 'chai'; +import { type PrimaryDevice, StorageState } from '@signalapp/mock-server'; + +import type { App } from '../playwright'; +import { Bootstrap } from '../bootstrap'; +import { typeIntoInput, waitForEnabledComposer } from '../helpers'; +import { MINUTE } from '../../util/durations'; + +export const debug = createDebug('mock:test:libsignal'); + +describe('Libsignal-net', function (this: Mocha.Suite) { + this.timeout(MINUTE); + let bootstrap: Bootstrap; + let app: App; + let contact: PrimaryDevice; + + beforeEach(async () => { + bootstrap = new Bootstrap(); + await bootstrap.init(); + [contact] = bootstrap.contacts; + + let state = StorageState.getEmpty(); + + state = state.addContact(contact, { + identityKey: contact.publicKey.serialize(), + profileKey: contact.profileKey.serialize(), + whitelisted: true, + }); + + await bootstrap.phone.setStorageState(state); + + bootstrap.server.setRemoteConfig( + 'desktop.experimentalTransportEnabled.alpha', + { enabled: true } + ); + + bootstrap.server.setRemoteConfig( + 'desktop.experimentalTransport.enableAuth', + { enabled: true } + ); + + // Link & close so that app can get remote config first over non-libsignal websocket, + // and then on next app start it will connect via libsignal + await bootstrap.linkAndClose(); + app = await bootstrap.startApp(); + }); + + afterEach(async function (this: Mocha.Context) { + if (!bootstrap) { + return; + } + + await bootstrap.maybeSaveLogs(this.currentTest, app); + await app.close(); + await bootstrap.teardown(); + }); + + it('can send and receive messages', async () => { + const window = await app.getWindow(); + const { desktop } = bootstrap; + + debug('receiving incoming message'); + await contact.sendText(bootstrap.desktop, 'incoming message'); + + debug('ensuring app received message, opening conversation'); + { + const leftPane = window.locator('#LeftPane'); + const item = leftPane + .getByTestId(contact.toContact().aci) + .getByText('incoming message'); + await item.click(); + } + + debug('sending outgoing message'); + const input = await waitForEnabledComposer(window); + await typeIntoInput(input, 'outgoing message'); + await input.press('Enter'); + + debug('waiting for message on server side'); + const { body, source } = await contact.waitForMessage(); + assert.strictEqual(body, 'outgoing message'); + assert.strictEqual(source, desktop); + + debug('confirming app successfully sent message'); + await app.waitForMessageSend(); + + debug('confirming that app was actually using libsignal'); + const { authenticated, unauthenticated } = await app.getSocketStatus(); + assert.strictEqual(authenticated.lastConnectionTransport, 'libsignal'); + assert.strictEqual(unauthenticated.lastConnectionTransport, 'libsignal'); + }); +}); diff --git a/ts/test-mock/playwright.ts b/ts/test-mock/playwright.ts index 8374d3777..257572c18 100644 --- a/ts/test-mock/playwright.ts +++ b/ts/test-mock/playwright.ts @@ -14,6 +14,7 @@ import type { ReceiptType } from '../types/Receipt'; import { SECOND } from '../util/durations'; import { drop } from '../util/drop'; import type { MessageAttributesType } from '../model-types'; +import type { SocketStatuses } from '../textsecure/SocketManager'; export type AppLoadedInfoType = Readonly<{ loadTime: number; @@ -187,6 +188,11 @@ export class App extends EventEmitter { ); } + public async getSocketStatus(): Promise { + const window = await this.getWindow(); + return window.evaluate('window.SignalCI.getSocketStatus()'); + } + public async getMessagesBySentAt( timestamp: number ): Promise> { diff --git a/ts/test-mock/release-notes/release_notes_test.ts b/ts/test-mock/release-notes/release_notes_test.ts index e7fd0020e..2dcb2e511 100644 --- a/ts/test-mock/release-notes/release_notes_test.ts +++ b/ts/test-mock/release-notes/release_notes_test.ts @@ -27,6 +27,10 @@ describe('release notes', function (this: Mocha.Suite) { bootstrap = new Bootstrap(); await bootstrap.init(); + bootstrap.server.setRemoteConfig('desktop.releaseNotes', { + enabled: true, + }); + app = await bootstrap.link(); }); diff --git a/ts/textsecure/SocketManager.ts b/ts/textsecure/SocketManager.ts index 2dac616a3..5659a2684 100644 --- a/ts/textsecure/SocketManager.ts +++ b/ts/textsecure/SocketManager.ts @@ -26,7 +26,7 @@ import { sleep } from '../util/sleep'; import { drop } from '../util/drop'; import type { ProxyAgent } from '../util/createProxyAgent'; import { createProxyAgent } from '../util/createProxyAgent'; -import { SocketStatus } from '../types/SocketStatus'; +import { type SocketInfo, SocketStatus } from '../types/SocketStatus'; import * as Errors from '../types/errors'; import * as Bytes from '../Bytes'; import * as log from '../logging/log'; @@ -39,6 +39,7 @@ import type { import WebSocketResource, { connectAuthenticatedLibsignal, connectUnauthenticatedLibsignal, + LibsignalWebSocketResource, ServerRequestType, TransportOption, WebSocketResourceWithShadowing, @@ -48,6 +49,7 @@ import type { IRequestHandler, WebAPICredentials } from './Types.d'; import { connect as connectWebSocket } from './WebSocket'; import { isNightly, isBeta, isStaging } from '../util/version'; import { getBasicAuth } from '../util/getBasicAuth'; +import { isTestOrMockEnvironment } from '../environment'; const FIVE_MINUTES = 5 * durations.MINUTE; @@ -68,6 +70,20 @@ export type SocketManagerOptions = Readonly<{ hasStoriesDisabled: boolean; }>; +type SocketStatusUpdate = + | { + status: SocketStatus.OPEN; + transportOption: TransportOption.Libsignal | TransportOption.Original; + } + | { + status: Exclude; + }; + +export type SocketStatuses = Record< + 'authenticated' | 'unauthenticated', + SocketInfo +>; + // This class manages two websocket resources: // // - Authenticated IWebSocketResource which uses supplied WebAPICredentials and @@ -92,7 +108,12 @@ export class SocketManager extends EventListener { #unauthenticatedExpirationTimer?: NodeJS.Timeout; #credentials?: WebAPICredentials; #lazyProxyAgent?: Promise; - #status = SocketStatus.CLOSED; + #authenticatedStatus: SocketInfo = { + status: SocketStatus.CLOSED, + }; + #unathenticatedStatus: SocketInfo = { + status: SocketStatus.CLOSED, + }; #requestHandlers = new Set(); #incomingRequestQueue = new Array(); #isNavigatorOffline = false; @@ -111,8 +132,11 @@ export class SocketManager extends EventListener { this.#hasStoriesDisabled = options.hasStoriesDisabled; } - public getStatus(): SocketStatus { - return this.#status; + public getStatus(): SocketStatuses { + return { + authenticated: this.#authenticatedStatus, + unauthenticated: this.#unathenticatedStatus, + }; } #markOffline() { @@ -163,7 +187,7 @@ export class SocketManager extends EventListener { `(hasStoriesDisabled=${this.#hasStoriesDisabled})` ); - this.#setStatus(SocketStatus.CONNECTING); + this.#setAuthenticatedStatus({ status: SocketStatus.CONNECTING }); const proxyAgent = await this.#getProxyAgent(); const useLibsignalTransport = @@ -252,7 +276,14 @@ export class SocketManager extends EventListener { let authenticated: IWebSocketResource; try { authenticated = await process.getResult(); - this.#setStatus(SocketStatus.OPEN); + + this.#setAuthenticatedStatus({ + status: SocketStatus.OPEN, + transportOption: + authenticated instanceof LibsignalWebSocketResource + ? TransportOption.Libsignal + : TransportOption.Original, + }); } catch (error) { log.warn( 'SocketManager: authenticated socket connection failed with ' + @@ -290,6 +321,11 @@ export class SocketManager extends EventListener { ) { this.emit('authError'); return; + } else if ( + error instanceof LibSignalErrorBase && + error.code === ErrorCode.IoError + ) { + this.#markOffline(); } else if ( error instanceof LibSignalErrorBase && error.code === ErrorCode.AppExpired @@ -566,21 +602,44 @@ export class SocketManager extends EventListener { // Private // - #setStatus(status: SocketStatus): void { - if (this.#status === status) { + #setAuthenticatedStatus(newStatus: SocketStatusUpdate): void { + if (this.#authenticatedStatus.status === newStatus.status) { return; } - this.#status = status; + this.#authenticatedStatus.status = newStatus.status; this.emit('statusChange'); - if (this.#status === SocketStatus.OPEN && !this.#privIsOnline) { - this.#privIsOnline = true; - this.emit('online'); + if (newStatus.status === SocketStatus.OPEN) { + this.#authenticatedStatus.lastConnectionTimestamp = Date.now(); + this.#authenticatedStatus.lastConnectionTransport = + newStatus.transportOption; + + if (!this.#privIsOnline) { + this.#privIsOnline = true; + this.emit('online'); + } + } + } + + #setUnauthenticatedStatus(newStatus: SocketStatusUpdate): void { + this.#unathenticatedStatus.status = newStatus.status; + + if (newStatus.status === SocketStatus.OPEN) { + this.#unathenticatedStatus.lastConnectionTimestamp = Date.now(); + this.#unathenticatedStatus.lastConnectionTransport = + newStatus.transportOption; } } #transportOption(): TransportOption { + if (isTestOrMockEnvironment()) { + const configValue = window.Signal.RemoteConfig.isEnabled( + 'desktop.experimentalTransportEnabled.alpha' + ); + return configValue ? TransportOption.Libsignal : TransportOption.Original; + } + // in staging, switch to using libsignal transport if (isStaging(this.options.version)) { return TransportOption.Libsignal; @@ -641,6 +700,10 @@ export class SocketManager extends EventListener { `SocketManager: connecting unauthenticated socket, transport option [${transportOption}]` ); + this.#setUnauthenticatedStatus({ + status: SocketStatus.CONNECTING, + }); + let process: AbortableProcess; if (transportOption === TransportOption.Libsignal) { @@ -667,6 +730,13 @@ export class SocketManager extends EventListener { let unauthenticated: IWebSocketResource; try { unauthenticated = await this.#unauthenticated.getResult(); + this.#setUnauthenticatedStatus({ + status: SocketStatus.OPEN, + transportOption: + unauthenticated instanceof LibsignalWebSocketResource + ? TransportOption.Libsignal + : TransportOption.Original, + }); } catch (error) { log.info( 'SocketManager: failed to connect unauthenticated socket ' + @@ -824,7 +894,7 @@ export class SocketManager extends EventListener { this.#incomingRequestQueue = []; this.#authenticated = undefined; - this.#setStatus(SocketStatus.CLOSED); + this.#setAuthenticatedStatus({ status: SocketStatus.CLOSED }); } #dropUnauthenticated(process: AbortableProcess): void { @@ -833,6 +903,7 @@ export class SocketManager extends EventListener { } this.#unauthenticated = undefined; + this.#setUnauthenticatedStatus({ status: SocketStatus.CLOSED }); if (!this.#unauthenticatedExpirationTimer) { return; } diff --git a/ts/textsecure/WebAPI.ts b/ts/textsecure/WebAPI.ts index 09f271bb9..985851189 100644 --- a/ts/textsecure/WebAPI.ts +++ b/ts/textsecure/WebAPI.ts @@ -30,7 +30,6 @@ import { createHTTPSAgent } from '../util/createHTTPSAgent'; import { createProxyAgent } from '../util/createProxyAgent'; import type { ProxyAgent } from '../util/createProxyAgent'; import type { FetchFunctionType } from '../util/uploads/tusProtocol'; -import type { SocketStatus } from '../types/SocketStatus'; import { VerificationTransport } from '../types/VerificationTransport'; import { toLogFormat } from '../types/errors'; import { isPackIdValid, redactPackId } from '../types/Stickers'; @@ -52,7 +51,7 @@ import { randomInt } from '../Crypto'; import * as linkPreviewFetch from '../linkPreviews/linkPreviewFetch'; import { isBadgeImageFileUrlValid } from '../badges/isBadgeImageFileUrlValid'; -import { SocketManager } from './SocketManager'; +import { SocketManager, type SocketStatuses } from './SocketManager'; import type { CDSAuthType, CDSResponseType } from './cds/Types.d'; import { CDSI } from './cds/CDSI'; import { SignalService as Proto } from '../protobuf'; @@ -1578,7 +1577,7 @@ export type WebAPIType = { getConfig: () => Promise; authenticate: (credentials: WebAPICredentials) => Promise; logout: () => Promise; - getSocketStatus: () => SocketStatus; + getSocketStatus: () => SocketStatuses; registerRequestHandler: (handler: IRequestHandler) => void; unregisterRequestHandler: (handler: IRequestHandler) => void; onHasStoriesDisabledChange: (newValue: boolean) => void; @@ -2106,7 +2105,7 @@ export function initialize({ } } - function getSocketStatus(): SocketStatus { + function getSocketStatus(): SocketStatuses { return socketManager.getStatus(); } diff --git a/ts/types/SocketStatus.ts b/ts/types/SocketStatus.ts index 90407a1ed..40c3435aa 100644 --- a/ts/types/SocketStatus.ts +++ b/ts/types/SocketStatus.ts @@ -1,6 +1,8 @@ // Copyright 2020 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only +import type { TransportOption } from '../textsecure/WebsocketResources'; + // Maps to values found here: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState // which are returned by libtextsecure's MessageReceiver export enum SocketStatus { @@ -9,3 +11,11 @@ export enum SocketStatus { CLOSING = 'CLOSING', CLOSED = 'CLOSED', } + +export type SocketInfo = { + status: SocketStatus; + lastConnectionTimestamp?: number; + lastConnectionTransport?: + | TransportOption.Libsignal + | TransportOption.Original; +}; diff --git a/ts/window.d.ts b/ts/window.d.ts index 18fc6ca3f..caefe62fc 100644 --- a/ts/window.d.ts +++ b/ts/window.d.ts @@ -51,6 +51,7 @@ import type { RetryPlaceholders } from './util/retryPlaceholders'; import type { PropsPreloadType as PreferencesPropsType } from './components/Preferences'; import type { WindowsNotificationData } from './services/notifications'; import type { QueryStatsOptions } from './sql/main'; +import type { SocketStatuses } from './textsecure/SocketManager'; export { Long } from 'long'; @@ -146,7 +147,10 @@ export type SignalCoreType = { calling: CallingClass; backups: BackupsService; initializeGroupCredentialFetcher: () => Promise; - initializeNetworkObserver: (network: ReduxActions['network']) => void; + initializeNetworkObserver: ( + network: ReduxActions['network'], + getAuthSocketStatus: () => SocketStatus + ) => void; initializeUpdateListener: (updates: ReduxActions['updates']) => void; retryPlaceholders?: RetryPlaceholders; lightSessionResetQueue?: PQueue; @@ -201,7 +205,7 @@ declare global { getBackupServerPublicParams: () => string; getSfuUrl: () => string; getIceServerOverride: () => string; - getSocketStatus: () => SocketStatus; + getSocketStatus: () => SocketStatuses; getTitle: () => string; waitForEmptyEventQueue: () => Promise; getVersion: () => string; diff --git a/ts/windows/main/start.ts b/ts/windows/main/start.ts index fb8ef74d4..2e48ebb62 100644 --- a/ts/windows/main/start.ts +++ b/ts/windows/main/start.ts @@ -78,6 +78,7 @@ if ( getSfuUrl: () => window.Signal.Services.calling._sfuUrl, getIceServerOverride: () => window.Signal.Services.calling._iceServerOverride, + getSocketStatus: () => window.textsecure.server?.getSocketStatus(), getStorageItem: (name: keyof StorageAccessType) => window.storage.get(name), putStorageItem: ( name: K,