Reconnect within MessageReceiver
This commit is contained in:
parent
0ec23be91b
commit
a6394e0c8b
5 changed files with 40 additions and 24 deletions
|
@ -43,7 +43,7 @@ import { connectToServerWithStoredCredentials } from './util/connectToServerWith
|
||||||
import * as universalExpireTimer from './util/universalExpireTimer';
|
import * as universalExpireTimer from './util/universalExpireTimer';
|
||||||
import { isDirectConversation, isGroupV2 } from './util/whatTypeOfConversation';
|
import { isDirectConversation, isGroupV2 } from './util/whatTypeOfConversation';
|
||||||
import { getSendOptions } from './util/getSendOptions';
|
import { getSendOptions } from './util/getSendOptions';
|
||||||
import { BackOff } from './util/BackOff';
|
import { BackOff, FIBONACCI_TIMEOUTS } from './util/BackOff';
|
||||||
import { AppViewType } from './state/ducks/app';
|
import { AppViewType } from './state/ducks/app';
|
||||||
import { isIncoming } from './state/selectors/message';
|
import { isIncoming } from './state/selectors/message';
|
||||||
import { actionCreators } from './state/actions';
|
import { actionCreators } from './state/actions';
|
||||||
|
@ -113,14 +113,7 @@ export async function startApp(): Promise<void> {
|
||||||
resolveOnAppView = resolve;
|
resolveOnAppView = resolve;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Fibonacci timeouts
|
const reconnectBackOff = new BackOff(FIBONACCI_TIMEOUTS);
|
||||||
const reconnectBackOff = new BackOff([
|
|
||||||
5 * 1000,
|
|
||||||
10 * 1000,
|
|
||||||
15 * 1000,
|
|
||||||
25 * 1000,
|
|
||||||
40 * 1000,
|
|
||||||
]);
|
|
||||||
|
|
||||||
window.textsecure.protobuf.onLoad(() => {
|
window.textsecure.protobuf.onLoad(() => {
|
||||||
window.storage.onready(() => {
|
window.storage.onready(() => {
|
||||||
|
|
|
@ -186,3 +186,5 @@ export class UnregisteredUserError extends Error {
|
||||||
appendStack(this, httpError);
|
appendStack(this, httpError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class ConnectTimeoutError extends Error {}
|
||||||
|
|
|
@ -41,6 +41,7 @@ import {
|
||||||
Sessions,
|
Sessions,
|
||||||
SignedPreKeys,
|
SignedPreKeys,
|
||||||
} from '../LibSignalStores';
|
} from '../LibSignalStores';
|
||||||
|
import { BackOff, FIBONACCI_TIMEOUTS } from '../util/BackOff';
|
||||||
import { BatcherType, createBatcher } from '../util/batcher';
|
import { BatcherType, createBatcher } from '../util/batcher';
|
||||||
import { sleep } from '../util/sleep';
|
import { sleep } from '../util/sleep';
|
||||||
import { parseIntOrThrow } from '../util/parseIntOrThrow';
|
import { parseIntOrThrow } from '../util/parseIntOrThrow';
|
||||||
|
@ -51,6 +52,7 @@ import utils from './Helpers';
|
||||||
import WebSocketResource, {
|
import WebSocketResource, {
|
||||||
IncomingWebSocketRequest,
|
IncomingWebSocketRequest,
|
||||||
} from './WebsocketResources';
|
} from './WebsocketResources';
|
||||||
|
import { ConnectTimeoutError } from './Errors';
|
||||||
import * as Bytes from '../Bytes';
|
import * as Bytes from '../Bytes';
|
||||||
import Crypto from './Crypto';
|
import Crypto from './Crypto';
|
||||||
import { deriveMasterKeyFromGroupV1, typedArrayToArrayBuffer } from '../Crypto';
|
import { deriveMasterKeyFromGroupV1, typedArrayToArrayBuffer } from '../Crypto';
|
||||||
|
@ -80,7 +82,6 @@ const FIXMEU8 = Uint8Array;
|
||||||
const GROUPV1_ID_LENGTH = 16;
|
const GROUPV1_ID_LENGTH = 16;
|
||||||
const GROUPV2_ID_LENGTH = 32;
|
const GROUPV2_ID_LENGTH = 32;
|
||||||
const RETRY_TIMEOUT = 2 * 60 * 1000;
|
const RETRY_TIMEOUT = 2 * 60 * 1000;
|
||||||
const RECONNECT_DELAY = 1 * 1000;
|
|
||||||
|
|
||||||
const decryptionErrorTypeSchema = z
|
const decryptionErrorTypeSchema = z
|
||||||
.object({
|
.object({
|
||||||
|
@ -229,6 +230,8 @@ class MessageReceiverInner extends EventTarget {
|
||||||
|
|
||||||
wsr?: WebSocketResource;
|
wsr?: WebSocketResource;
|
||||||
|
|
||||||
|
private readonly reconnectBackOff = new BackOff(FIBONACCI_TIMEOUTS);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
oldUsername: string,
|
oldUsername: string,
|
||||||
username: string,
|
username: string,
|
||||||
|
@ -348,6 +351,11 @@ class MessageReceiverInner extends EventTarget {
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.socketStatus = SocketStatus.CLOSED;
|
this.socketStatus = SocketStatus.CLOSED;
|
||||||
|
|
||||||
|
if (error instanceof ConnectTimeoutError) {
|
||||||
|
await this.onclose(-1, 'Connection timed out');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const event = new Event('error');
|
const event = new Event('error');
|
||||||
event.error = error;
|
event.error = error;
|
||||||
await this.dispatchAndWait(event);
|
await this.dispatchAndWait(event);
|
||||||
|
@ -443,7 +451,7 @@ class MessageReceiverInner extends EventTarget {
|
||||||
|
|
||||||
async onclose(code: number, reason: string): Promise<void> {
|
async onclose(code: number, reason: string): Promise<void> {
|
||||||
window.log.info(
|
window.log.info(
|
||||||
'websocket closed',
|
'MessageReceiver: websocket closed',
|
||||||
code,
|
code,
|
||||||
reason || '',
|
reason || '',
|
||||||
'calledClose:',
|
'calledClose:',
|
||||||
|
@ -464,12 +472,18 @@ class MessageReceiverInner extends EventTarget {
|
||||||
this.onEmpty();
|
this.onEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
await sleep(RECONNECT_DELAY);
|
const timeout = this.reconnectBackOff.getAndIncrement();
|
||||||
|
|
||||||
// Try to reconnect (if there is an error - we'll get an
|
window.log.info(`MessageReceiver: reconnecting after ${timeout}ms`);
|
||||||
// `error` event from `connect()` and hit the retry backoff logic in
|
await sleep(timeout);
|
||||||
// `ts/background.ts`)
|
|
||||||
|
// Try to reconnect (if there is an HTTP error - we'll get an
|
||||||
|
// `error` event from `connect()` and hit the secondary retry backoff
|
||||||
|
// logic in `ts/background.ts`)
|
||||||
await this.connect();
|
await this.connect();
|
||||||
|
|
||||||
|
// Successfull reconnect, reset the backoff timeouts
|
||||||
|
this.reconnectBackOff.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
checkSocket(): void {
|
checkSocket(): void {
|
||||||
|
|
|
@ -59,6 +59,7 @@ import {
|
||||||
} from '../textsecure.d';
|
} from '../textsecure.d';
|
||||||
import { SignalService as Proto } from '../protobuf';
|
import { SignalService as Proto } from '../protobuf';
|
||||||
|
|
||||||
|
import { ConnectTimeoutError } from './Errors';
|
||||||
import MessageSender from './SendMessage';
|
import MessageSender from './SendMessage';
|
||||||
|
|
||||||
// TODO: remove once we move away from ArrayBuffers
|
// TODO: remove once we move away from ArrayBuffers
|
||||||
|
@ -305,15 +306,7 @@ async function _connectSocket(
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
reject(
|
reject(new ConnectTimeoutError('Connection timed out'));
|
||||||
makeHTTPError(
|
|
||||||
'_connectSocket: Connection timed out',
|
|
||||||
-1,
|
|
||||||
{},
|
|
||||||
'Connection timed out',
|
|
||||||
stack
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
client.abort();
|
client.abort();
|
||||||
}, timeout);
|
}, timeout);
|
||||||
|
|
|
@ -1,6 +1,20 @@
|
||||||
// Copyright 2021 Signal Messenger, LLC
|
// Copyright 2021 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
const SECOND = 1000;
|
||||||
|
|
||||||
|
export const FIBONACCI_TIMEOUTS: ReadonlyArray<number> = [
|
||||||
|
1 * SECOND,
|
||||||
|
2 * SECOND,
|
||||||
|
3 * SECOND,
|
||||||
|
5 * SECOND,
|
||||||
|
8 * SECOND,
|
||||||
|
13 * SECOND,
|
||||||
|
21 * SECOND,
|
||||||
|
34 * SECOND,
|
||||||
|
55 * SECOND,
|
||||||
|
];
|
||||||
|
|
||||||
export class BackOff {
|
export class BackOff {
|
||||||
private count = 0;
|
private count = 0;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue