Adopt libsignal-net version with no auto-reconnect
Co-authored-by: Jordan Rose <jrose@signal.org>
This commit is contained in:
parent
00e6071b1d
commit
30a419bb2a
7 changed files with 139 additions and 71 deletions
|
@ -4733,7 +4733,7 @@ For more information on this, and how to apply and follow the GNU AGPL, see
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## attest 0.1.0, libsignal-ffi 0.54.0, libsignal-jni 0.54.0, libsignal-jni-testing 0.54.0, libsignal-node 0.54.0, signal-neon-futures 0.1.0, signal-neon-futures-tests 0.1.0, libsignal-bridge 0.1.0, libsignal-bridge-macros 0.1.0, libsignal-bridge-testing 0.1.0, libsignal-bridge-types 0.1.0, libsignal-core 0.1.0, signal-crypto 0.1.0, device-transfer 0.1.0, signal-media 0.1.0, libsignal-message-backup 0.1.0, libsignal-message-backup-macros 0.1.0, libsignal-net 0.1.0, signal-pin 0.1.0, poksho 0.7.0, libsignal-protocol 0.1.0, libsignal-svr3 0.1.0, usernames 0.1.0, zkcredential 0.1.0, zkgroup 0.9.0
|
## attest 0.1.0, libsignal-ffi 0.55.0, libsignal-jni 0.55.0, libsignal-jni-testing 0.55.0, libsignal-node 0.55.0, signal-neon-futures 0.1.0, signal-neon-futures-tests 0.1.0, libsignal-bridge 0.1.0, libsignal-bridge-macros 0.1.0, libsignal-bridge-testing 0.1.0, libsignal-bridge-types 0.1.0, libsignal-core 0.1.0, signal-crypto 0.1.0, device-transfer 0.1.0, signal-media 0.1.0, libsignal-message-backup 0.1.0, libsignal-message-backup-macros 0.1.0, libsignal-net 0.1.0, signal-pin 0.1.0, poksho 0.7.0, libsignal-protocol 0.1.0, libsignal-svr3 0.1.0, usernames 0.1.0, zkcredential 0.1.0, zkgroup 0.9.0
|
||||||
|
|
||||||
```
|
```
|
||||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||||
|
@ -5986,7 +5986,7 @@ limitations under the License.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## boring 4.6.0
|
## boring 4.9.0
|
||||||
|
|
||||||
```
|
```
|
||||||
Copyright 2011-2017 Google Inc.
|
Copyright 2011-2017 Google Inc.
|
||||||
|
@ -6421,7 +6421,7 @@ express Statement of Purpose.
|
||||||
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
```
|
```
|
||||||
|
|
||||||
## boring-sys 4.6.0
|
## boring-sys 4.9.0
|
||||||
|
|
||||||
```
|
```
|
||||||
/* Copyright (c) 2015, Google Inc.
|
/* Copyright (c) 2015, Google Inc.
|
||||||
|
@ -6792,7 +6792,7 @@ DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## boring-sys 4.6.0
|
## boring-sys 4.9.0
|
||||||
|
|
||||||
```
|
```
|
||||||
Copyright (c) 2014 Alex Crichton
|
Copyright (c) 2014 Alex Crichton
|
||||||
|
@ -7113,7 +7113,7 @@ THE SOFTWARE.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## anstyle-wincon 3.0.4
|
## anstyle-wincon 3.0.3
|
||||||
|
|
||||||
```
|
```
|
||||||
Copyright (c) 2015 Josh Triplett, 2022 The rust-cli Developers
|
Copyright (c) 2015 Josh Triplett, 2022 The rust-cli Developers
|
||||||
|
@ -7200,7 +7200,7 @@ DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## gimli 0.29.0, heck 0.5.0, peeking_take_while 0.1.2, unicode-bidi 0.3.15, unicode-normalization 0.1.23
|
## gimli 0.29.0, heck 0.4.1, heck 0.5.0, peeking_take_while 0.1.2, unicode-bidi 0.3.15, unicode-normalization 0.1.23
|
||||||
|
|
||||||
```
|
```
|
||||||
Copyright (c) 2015 The Rust Project Developers
|
Copyright (c) 2015 The Rust Project Developers
|
||||||
|
@ -7351,7 +7351,7 @@ DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## boring-sys 4.6.0
|
## boring-sys 4.9.0
|
||||||
|
|
||||||
```
|
```
|
||||||
Copyright (c) 2015-2016 the fiat-crypto authors (see
|
Copyright (c) 2015-2016 the fiat-crypto authors (see
|
||||||
|
@ -7579,7 +7579,7 @@ DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## hashbrown 0.14.5
|
## hashbrown 0.12.3, hashbrown 0.14.5
|
||||||
|
|
||||||
```
|
```
|
||||||
Copyright (c) 2016 Amanieu d'Antras
|
Copyright (c) 2016 Amanieu d'Antras
|
||||||
|
@ -7641,7 +7641,7 @@ DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## anstyle-parse 0.2.5
|
## anstyle-parse 0.2.4
|
||||||
|
|
||||||
```
|
```
|
||||||
Copyright (c) 2016 Joe Wilm and individual contributors
|
Copyright (c) 2016 Joe Wilm and individual contributors
|
||||||
|
@ -7822,7 +7822,7 @@ SOFTWARE.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## tokio-boring 4.6.0
|
## tokio-boring 4.9.0
|
||||||
|
|
||||||
```
|
```
|
||||||
Copyright (c) 2016 Tokio contributors
|
Copyright (c) 2016 Tokio contributors
|
||||||
|
@ -7885,7 +7885,7 @@ DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## indexmap 2.2.6
|
## indexmap 1.9.3, indexmap 2.2.6
|
||||||
|
|
||||||
```
|
```
|
||||||
Copyright (c) 2016--2017
|
Copyright (c) 2016--2017
|
||||||
|
@ -8757,7 +8757,7 @@ DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## protobuf-codegen 3.5.0, protobuf-json-mapping 3.5.0, protobuf-support 3.5.0, protobuf 3.5.0
|
## protobuf-codegen 3.4.0, protobuf-json-mapping 3.4.0, protobuf-parse 3.4.0, protobuf-support 3.4.0, protobuf 3.4.0
|
||||||
|
|
||||||
```
|
```
|
||||||
Copyright (c) 2019 Stepan Koltsov
|
Copyright (c) 2019 Stepan Koltsov
|
||||||
|
@ -8779,7 +8779,6 @@ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||||
OR OTHER DEALINGS IN THE SOFTWARE.
|
OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## ppv-lite86 0.2.17
|
## ppv-lite86 0.2.17
|
||||||
|
@ -9306,7 +9305,7 @@ DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## anstyle 1.0.8
|
## anstyle 1.0.7
|
||||||
|
|
||||||
```
|
```
|
||||||
Copyright (c) 2022 The rust-cli Developers
|
Copyright (c) 2022 The rust-cli Developers
|
||||||
|
@ -9518,7 +9517,7 @@ SOFTWARE.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## anstream 0.6.15, anstyle-query 1.1.1, clap 4.5.11, colorchoice 1.0.2, env_filter 0.1.2, env_logger 0.11.5, is_terminal_polyfill 1.70.1, toml_datetime 0.6.7, toml_edit 0.21.1
|
## anstream 0.6.14, anstyle-query 1.1.0, clap 4.4.18, colorchoice 1.0.1, env_filter 0.1.1, env_logger 0.11.4, is_terminal_polyfill 1.70.0, toml_datetime 0.6.6, toml_edit 0.21.1
|
||||||
|
|
||||||
```
|
```
|
||||||
Copyright (c) Individual contributors
|
Copyright (c) Individual contributors
|
||||||
|
@ -10248,7 +10247,7 @@ SOFTWARE.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## cesu8 1.1.0, half 2.4.1, pqcrypto-internals 0.2.5, pqcrypto-kyber 0.7.9, pqcrypto-kyber 0.8.1, pqcrypto-traits 0.3.5, protobuf-parse 3.5.0
|
## cesu8 1.1.0, half 2.4.1, pqcrypto-internals 0.2.5, pqcrypto-kyber 0.7.9, pqcrypto-kyber 0.8.1, pqcrypto-traits 0.3.5
|
||||||
|
|
||||||
```
|
```
|
||||||
MIT License
|
MIT License
|
||||||
|
@ -10597,7 +10596,7 @@ THE SOFTWARE.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## strsim 0.10.0, strsim 0.11.1
|
## strsim 0.10.0
|
||||||
|
|
||||||
```
|
```
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
@ -10735,7 +10734,7 @@ SOFTWARE.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## clap_builder 4.5.11, clap_derive 4.5.11, clap_lex 0.7.2
|
## clap_builder 4.4.18, clap_derive 4.4.7, clap_lex 0.6.0
|
||||||
|
|
||||||
```
|
```
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
@ -11018,7 +11017,7 @@ SOFTWARE.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## version_check 0.9.5
|
## version_check 0.9.4
|
||||||
|
|
||||||
```
|
```
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
@ -11096,7 +11095,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
```
|
```
|
||||||
|
|
||||||
## boring-sys 4.6.0, ring 0.17.8
|
## boring-sys 4.9.0, ring 0.17.8
|
||||||
|
|
||||||
```
|
```
|
||||||
/* ====================================================================
|
/* ====================================================================
|
||||||
|
|
8
package-lock.json
generated
8
package-lock.json
generated
|
@ -22,7 +22,7 @@
|
||||||
"@react-aria/utils": "3.16.0",
|
"@react-aria/utils": "3.16.0",
|
||||||
"@react-spring/web": "9.5.5",
|
"@react-spring/web": "9.5.5",
|
||||||
"@signalapp/better-sqlite3": "8.7.1",
|
"@signalapp/better-sqlite3": "8.7.1",
|
||||||
"@signalapp/libsignal-client": "0.54.0",
|
"@signalapp/libsignal-client": "0.55.0",
|
||||||
"@signalapp/ringrtc": "2.46.0",
|
"@signalapp/ringrtc": "2.46.0",
|
||||||
"@signalapp/windows-dummy-keystroke": "1.0.0",
|
"@signalapp/windows-dummy-keystroke": "1.0.0",
|
||||||
"@types/fabric": "4.5.3",
|
"@types/fabric": "4.5.3",
|
||||||
|
@ -7223,9 +7223,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@signalapp/libsignal-client": {
|
"node_modules/@signalapp/libsignal-client": {
|
||||||
"version": "0.54.0",
|
"version": "0.55.0",
|
||||||
"resolved": "https://registry.npmjs.org/@signalapp/libsignal-client/-/libsignal-client-0.54.0.tgz",
|
"resolved": "https://registry.npmjs.org/@signalapp/libsignal-client/-/libsignal-client-0.55.0.tgz",
|
||||||
"integrity": "sha512-bkdw3r39UU0W0UaFAJJVhLC5AEiMkgCgtdtabI64c1KuT7oeIx4XvegfqtBwF7vKj29ZHz4lODCh3tFyqbrNLw==",
|
"integrity": "sha512-SwsBLUlHsUU6ae6cWsvok2maaRqIoACi0LgW0uGtTrNDeSUdja3j2Dnt/M5InQ+LaU5DQg8xMyUq8KKRp2RmpQ==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"node-gyp-build": "^4.2.3",
|
"node-gyp-build": "^4.2.3",
|
||||||
|
|
|
@ -104,7 +104,7 @@
|
||||||
"@react-aria/utils": "3.16.0",
|
"@react-aria/utils": "3.16.0",
|
||||||
"@react-spring/web": "9.5.5",
|
"@react-spring/web": "9.5.5",
|
||||||
"@signalapp/better-sqlite3": "8.7.1",
|
"@signalapp/better-sqlite3": "8.7.1",
|
||||||
"@signalapp/libsignal-client": "0.54.0",
|
"@signalapp/libsignal-client": "0.55.0",
|
||||||
"@signalapp/ringrtc": "2.46.0",
|
"@signalapp/ringrtc": "2.46.0",
|
||||||
"@signalapp/windows-dummy-keystroke": "1.0.0",
|
"@signalapp/windows-dummy-keystroke": "1.0.0",
|
||||||
"@types/fabric": "4.5.3",
|
"@types/fabric": "4.5.3",
|
||||||
|
|
|
@ -10,6 +10,7 @@ import { getRandomBytes } from '../../Crypto';
|
||||||
import * as Bytes from '../../Bytes';
|
import * as Bytes from '../../Bytes';
|
||||||
import { SignalService as Proto, Backups } from '../../protobuf';
|
import { SignalService as Proto, Backups } from '../../protobuf';
|
||||||
import { DataWriter } from '../../sql/Client';
|
import { DataWriter } from '../../sql/Client';
|
||||||
|
import { APPLICATION_OCTET_STREAM } from '../../types/MIME';
|
||||||
import { generateAci } from '../../types/ServiceId';
|
import { generateAci } from '../../types/ServiceId';
|
||||||
import { PaymentEventKind } from '../../types/Payment';
|
import { PaymentEventKind } from '../../types/Payment';
|
||||||
import { ContactFormType } from '../../types/EmbeddedContact';
|
import { ContactFormType } from '../../types/EmbeddedContact';
|
||||||
|
@ -372,6 +373,11 @@ describe('backup/non-bubble messages', () => {
|
||||||
packId: Bytes.toHex(getRandomBytes(16)),
|
packId: Bytes.toHex(getRandomBytes(16)),
|
||||||
stickerId: 1,
|
stickerId: 1,
|
||||||
packKey: Bytes.toBase64(getRandomBytes(32)),
|
packKey: Bytes.toBase64(getRandomBytes(32)),
|
||||||
|
data: {
|
||||||
|
contentType: APPLICATION_OCTET_STREAM,
|
||||||
|
error: true,
|
||||||
|
size: 0,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
reactions: [
|
reactions: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -591,14 +591,12 @@ export class SocketManager extends EventListener {
|
||||||
: TransportOption.Original;
|
: TransportOption.Original;
|
||||||
}
|
}
|
||||||
|
|
||||||
private connectLibsignalUnauthenticated(): AbortableProcess<IWebSocketResource> {
|
|
||||||
return connectUnauthenticatedLibsignal({
|
|
||||||
libsignalNet: this.libsignalNet,
|
|
||||||
name: UNAUTHENTICATED_CHANNEL_NAME,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private async getUnauthenticatedResource(): Promise<IWebSocketResource> {
|
private async getUnauthenticatedResource(): Promise<IWebSocketResource> {
|
||||||
|
// awaiting on `this.getProxyAgent()` needs to happen here
|
||||||
|
// so that there are no calls to `await` between checking
|
||||||
|
// the value of `this.unauthenticated` and assigning it later in this function
|
||||||
|
const proxyAgent = await this.getProxyAgent();
|
||||||
|
|
||||||
if (this.unauthenticated) {
|
if (this.unauthenticated) {
|
||||||
return this.unauthenticated.getResult();
|
return this.unauthenticated.getResult();
|
||||||
}
|
}
|
||||||
|
@ -613,8 +611,6 @@ export class SocketManager extends EventListener {
|
||||||
|
|
||||||
log.info('SocketManager: connecting unauthenticated socket');
|
log.info('SocketManager: connecting unauthenticated socket');
|
||||||
|
|
||||||
const proxyAgent = await this.getProxyAgent();
|
|
||||||
|
|
||||||
const transportOption = this.transportOption(proxyAgent);
|
const transportOption = this.transportOption(proxyAgent);
|
||||||
log.info(
|
log.info(
|
||||||
`SocketManager: connecting unauthenticated socket, transport option [${transportOption}]`
|
`SocketManager: connecting unauthenticated socket, transport option [${transportOption}]`
|
||||||
|
@ -623,7 +619,10 @@ export class SocketManager extends EventListener {
|
||||||
let process: AbortableProcess<IWebSocketResource>;
|
let process: AbortableProcess<IWebSocketResource>;
|
||||||
|
|
||||||
if (transportOption === TransportOption.Libsignal) {
|
if (transportOption === TransportOption.Libsignal) {
|
||||||
process = this.connectLibsignalUnauthenticated();
|
process = connectUnauthenticatedLibsignal({
|
||||||
|
libsignalNet: this.libsignalNet,
|
||||||
|
name: UNAUTHENTICATED_CHANNEL_NAME,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
process = this.connectResource({
|
process = this.connectResource({
|
||||||
name: UNAUTHENTICATED_CHANNEL_NAME,
|
name: UNAUTHENTICATED_CHANNEL_NAME,
|
||||||
|
|
|
@ -38,7 +38,11 @@ import type { ChatServiceDebugInfo } from '@signalapp/libsignal-client/Native';
|
||||||
|
|
||||||
import type { Net } from '@signalapp/libsignal-client';
|
import type { Net } from '@signalapp/libsignal-client';
|
||||||
import { Buffer } from 'node:buffer';
|
import { Buffer } from 'node:buffer';
|
||||||
import type { ChatServerMessageAck } from '@signalapp/libsignal-client/dist/net';
|
import type {
|
||||||
|
ChatServerMessageAck,
|
||||||
|
ChatServiceListener,
|
||||||
|
ConnectionEventsListener,
|
||||||
|
} from '@signalapp/libsignal-client/dist/net';
|
||||||
import type { EventHandler } from './EventTarget';
|
import type { EventHandler } from './EventTarget';
|
||||||
import EventTarget from './EventTarget';
|
import EventTarget from './EventTarget';
|
||||||
|
|
||||||
|
@ -88,7 +92,6 @@ const AggregatedStatsSchema = z.object({
|
||||||
connectionFailures: z.number(),
|
connectionFailures: z.number(),
|
||||||
requestsCompared: z.number(),
|
requestsCompared: z.number(),
|
||||||
ipVersionMismatches: z.number(),
|
ipVersionMismatches: z.number(),
|
||||||
unexpectedReconnects: z.number(),
|
|
||||||
healthcheckFailures: z.number(),
|
healthcheckFailures: z.number(),
|
||||||
healthcheckBadStatus: z.number(),
|
healthcheckBadStatus: z.number(),
|
||||||
lastToastTimestamp: z.number(),
|
lastToastTimestamp: z.number(),
|
||||||
|
@ -133,7 +136,6 @@ export namespace AggregatedStats {
|
||||||
connectionFailures: a.connectionFailures + b.connectionFailures,
|
connectionFailures: a.connectionFailures + b.connectionFailures,
|
||||||
healthcheckFailures: a.healthcheckFailures + b.healthcheckFailures,
|
healthcheckFailures: a.healthcheckFailures + b.healthcheckFailures,
|
||||||
ipVersionMismatches: a.ipVersionMismatches + b.ipVersionMismatches,
|
ipVersionMismatches: a.ipVersionMismatches + b.ipVersionMismatches,
|
||||||
unexpectedReconnects: a.unexpectedReconnects + b.unexpectedReconnects,
|
|
||||||
healthcheckBadStatus: a.healthcheckBadStatus + b.healthcheckBadStatus,
|
healthcheckBadStatus: a.healthcheckBadStatus + b.healthcheckBadStatus,
|
||||||
lastToastTimestamp: Math.max(a.lastToastTimestamp, b.lastToastTimestamp),
|
lastToastTimestamp: Math.max(a.lastToastTimestamp, b.lastToastTimestamp),
|
||||||
};
|
};
|
||||||
|
@ -144,7 +146,6 @@ export namespace AggregatedStats {
|
||||||
requestsCompared: 0,
|
requestsCompared: 0,
|
||||||
connectionFailures: 0,
|
connectionFailures: 0,
|
||||||
ipVersionMismatches: 0,
|
ipVersionMismatches: 0,
|
||||||
unexpectedReconnects: 0,
|
|
||||||
healthcheckFailures: 0,
|
healthcheckFailures: 0,
|
||||||
healthcheckBadStatus: 0,
|
healthcheckBadStatus: 0,
|
||||||
lastToastTimestamp: 0,
|
lastToastTimestamp: 0,
|
||||||
|
@ -156,12 +157,11 @@ export namespace AggregatedStats {
|
||||||
if (timeSinceLastToast < durations.DAY || stats.requestsCompared < 1000) {
|
if (timeSinceLastToast < durations.DAY || stats.requestsCompared < 1000) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return (
|
const totalFailuresSinceLastToast =
|
||||||
stats.healthcheckBadStatus +
|
stats.healthcheckBadStatus +
|
||||||
stats.healthcheckFailures +
|
stats.healthcheckFailures +
|
||||||
stats.connectionFailures >
|
stats.connectionFailures;
|
||||||
20 || stats.unexpectedReconnects > 50
|
return totalFailuresSinceLastToast > 20;
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function localStorageKey(name: string): string {
|
export function localStorageKey(name: string): string {
|
||||||
|
@ -330,6 +330,10 @@ export interface IWebSocketResource extends IResource {
|
||||||
localPort(): number | undefined;
|
localPort(): number | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type LibsignalWebSocketResourceHolder = {
|
||||||
|
resource: LibsignalWebSocketResource | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
export function connectUnauthenticatedLibsignal({
|
export function connectUnauthenticatedLibsignal({
|
||||||
libsignalNet,
|
libsignalNet,
|
||||||
name,
|
name,
|
||||||
|
@ -337,7 +341,24 @@ export function connectUnauthenticatedLibsignal({
|
||||||
libsignalNet: Net.Net;
|
libsignalNet: Net.Net;
|
||||||
name: string;
|
name: string;
|
||||||
}): AbortableProcess<LibsignalWebSocketResource> {
|
}): AbortableProcess<LibsignalWebSocketResource> {
|
||||||
return connectLibsignal(libsignalNet.newUnauthenticatedChatService(), name);
|
const logId = `LibsignalWebSocketResource(${name})`;
|
||||||
|
const listener: LibsignalWebSocketResourceHolder & ConnectionEventsListener =
|
||||||
|
{
|
||||||
|
resource: undefined,
|
||||||
|
onConnectionInterrupted(): void {
|
||||||
|
if (!this.resource) {
|
||||||
|
logDisconnectedListenerWarn(logId, 'onConnectionInterrupted');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.resource.onConnectionInterrupted();
|
||||||
|
this.resource = undefined;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return connectLibsignal(
|
||||||
|
libsignalNet.newUnauthenticatedChatService(listener),
|
||||||
|
listener,
|
||||||
|
logId
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function connectAuthenticatedLibsignal({
|
export function connectAuthenticatedLibsignal({
|
||||||
|
@ -353,12 +374,15 @@ export function connectAuthenticatedLibsignal({
|
||||||
handler: (request: IncomingWebSocketRequest) => void;
|
handler: (request: IncomingWebSocketRequest) => void;
|
||||||
receiveStories: boolean;
|
receiveStories: boolean;
|
||||||
}): AbortableProcess<LibsignalWebSocketResource> {
|
}): AbortableProcess<LibsignalWebSocketResource> {
|
||||||
const listener = {
|
const logId = `LibsignalWebSocketResource(${name})`;
|
||||||
|
const listener: LibsignalWebSocketResourceHolder & ChatServiceListener = {
|
||||||
|
resource: undefined,
|
||||||
onIncomingMessage(
|
onIncomingMessage(
|
||||||
envelope: Buffer,
|
envelope: Buffer,
|
||||||
timestamp: number,
|
timestamp: number,
|
||||||
ack: ChatServerMessageAck
|
ack: ChatServerMessageAck
|
||||||
): void {
|
): void {
|
||||||
|
// Handle incoming messages even if we've disconnected.
|
||||||
const request = new IncomingWebSocketRequestLibsignal(
|
const request = new IncomingWebSocketRequestLibsignal(
|
||||||
ServerRequestType.ApiMessage,
|
ServerRequestType.ApiMessage,
|
||||||
envelope,
|
envelope,
|
||||||
|
@ -368,6 +392,10 @@ export function connectAuthenticatedLibsignal({
|
||||||
handler(request);
|
handler(request);
|
||||||
},
|
},
|
||||||
onQueueEmpty(): void {
|
onQueueEmpty(): void {
|
||||||
|
if (!this.resource) {
|
||||||
|
logDisconnectedListenerWarn(logId, 'onQueueEmpty');
|
||||||
|
return;
|
||||||
|
}
|
||||||
const request = new IncomingWebSocketRequestLibsignal(
|
const request = new IncomingWebSocketRequestLibsignal(
|
||||||
ServerRequestType.ApiEmptyQueue,
|
ServerRequestType.ApiEmptyQueue,
|
||||||
undefined,
|
undefined,
|
||||||
|
@ -377,7 +405,12 @@ export function connectAuthenticatedLibsignal({
|
||||||
handler(request);
|
handler(request);
|
||||||
},
|
},
|
||||||
onConnectionInterrupted(): void {
|
onConnectionInterrupted(): void {
|
||||||
log.warn(`LibsignalWebSocketResource(${name}): connection interrupted`);
|
if (!this.resource) {
|
||||||
|
logDisconnectedListenerWarn(logId, 'onConnectionInterrupted');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.resource.onConnectionInterrupted();
|
||||||
|
this.resource = undefined;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
return connectLibsignal(
|
return connectLibsignal(
|
||||||
|
@ -387,33 +420,40 @@ export function connectAuthenticatedLibsignal({
|
||||||
receiveStories,
|
receiveStories,
|
||||||
listener
|
listener
|
||||||
),
|
),
|
||||||
name
|
listener,
|
||||||
|
logId
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function logDisconnectedListenerWarn(logId: string, method: string): void {
|
||||||
|
log.warn(`${logId} received ${method}, but listener already disconnected`);
|
||||||
|
}
|
||||||
|
|
||||||
function connectLibsignal(
|
function connectLibsignal(
|
||||||
chatService: Net.ChatService,
|
chatService: Net.ChatService,
|
||||||
name: string
|
resourceHolder: LibsignalWebSocketResourceHolder,
|
||||||
|
logId: string
|
||||||
): AbortableProcess<LibsignalWebSocketResource> {
|
): AbortableProcess<LibsignalWebSocketResource> {
|
||||||
const connectAsync = async () => {
|
const connectAsync = async () => {
|
||||||
try {
|
try {
|
||||||
const debugInfo = await chatService.connect();
|
const debugInfo = await chatService.connect();
|
||||||
log.info(`LibsignalWebSocketResource(${name}) connected`, debugInfo);
|
log.info(`${logId} connected`, debugInfo);
|
||||||
return new LibsignalWebSocketResource(
|
const resource = new LibsignalWebSocketResource(
|
||||||
chatService,
|
chatService,
|
||||||
IpVersion.fromDebugInfoCode(debugInfo.ipType)
|
IpVersion.fromDebugInfoCode(debugInfo.ipType),
|
||||||
|
logId
|
||||||
);
|
);
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
resourceHolder.resource = resource;
|
||||||
|
return resource;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Handle any errors that occur during connection
|
// Handle any errors that occur during connection
|
||||||
log.error(
|
log.error(`${logId} connection failed`, Errors.toLogFormat(error));
|
||||||
`LibsignalWebSocketResource(${name}) connection failed`,
|
|
||||||
Errors.toLogFormat(error)
|
|
||||||
);
|
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return new AbortableProcess<LibsignalWebSocketResource>(
|
return new AbortableProcess<LibsignalWebSocketResource>(
|
||||||
`LibsignalWebSocketResource.connect(${name})`,
|
`${logId}.connect`,
|
||||||
{
|
{
|
||||||
abort() {
|
abort() {
|
||||||
// if interrupted, trying to disconnect
|
// if interrupted, trying to disconnect
|
||||||
|
@ -428,9 +468,12 @@ export class LibsignalWebSocketResource
|
||||||
extends EventTarget
|
extends EventTarget
|
||||||
implements IWebSocketResource
|
implements IWebSocketResource
|
||||||
{
|
{
|
||||||
|
closed = false;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly chatService: Net.ChatService,
|
private readonly chatService: Net.ChatService,
|
||||||
private readonly socketIpVersion: IpVersion | undefined
|
private readonly socketIpVersion: IpVersion | undefined,
|
||||||
|
private readonly logId: string
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
@ -452,12 +495,39 @@ export class LibsignalWebSocketResource
|
||||||
return super.addEventListener(name, handler);
|
return super.addEventListener(name, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
public close(_code?: number, _reason?: string): void {
|
public close(code = 3000, reason?: string): void {
|
||||||
|
if (this.closed) {
|
||||||
|
log.info(`${this.logId}.close: Already closed! ${code}/${reason}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
drop(this.chatService.disconnect());
|
drop(this.chatService.disconnect());
|
||||||
|
|
||||||
|
// On linux the socket can wait a long time to emit its close event if we've
|
||||||
|
// lost the internet connection. On the order of minutes. This speeds that
|
||||||
|
// process up.
|
||||||
|
Timers.setTimeout(
|
||||||
|
() => this.onConnectionInterrupted(),
|
||||||
|
5 * durations.SECOND
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public shutdown(): void {
|
public shutdown(): void {
|
||||||
drop(this.chatService.disconnect());
|
this.close(3000, 'Shutdown');
|
||||||
|
}
|
||||||
|
|
||||||
|
onConnectionInterrupted(): void {
|
||||||
|
if (this.closed) {
|
||||||
|
log.warn(
|
||||||
|
`${this.logId}.onConnectionInterrupted called after resource is closed`
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.closed = true;
|
||||||
|
log.warn(`${this.logId}: connection closed`);
|
||||||
|
// TODO: DESKTOP-7519. `reason` should be eventually resolved from the
|
||||||
|
// disconnect reason error object coming from libsignal.
|
||||||
|
const reason = undefined;
|
||||||
|
this.dispatchEvent(new CloseEvent(3000, reason || 'normal'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public forceKeepAlive(): void {
|
public forceKeepAlive(): void {
|
||||||
|
@ -627,12 +697,11 @@ export class WebSocketResourceWithShadowing implements IWebSocketResource {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const [healthCheckResult, debugInfo] =
|
const healthCheckResult = await this.shadowing.sendRequest({
|
||||||
await this.shadowing.sendRequestGetDebugInfo({
|
verb: 'GET',
|
||||||
verb: 'GET',
|
path: '/v1/keepalive',
|
||||||
path: '/v1/keepalive',
|
timeout: KEEPALIVE_TIMEOUT_MS,
|
||||||
timeout: KEEPALIVE_TIMEOUT_MS,
|
});
|
||||||
});
|
|
||||||
this.stats.requestsCompared += 1;
|
this.stats.requestsCompared += 1;
|
||||||
if (!isSuccessfulStatusCode(healthCheckResult.status)) {
|
if (!isSuccessfulStatusCode(healthCheckResult.status)) {
|
||||||
this.stats.healthcheckBadStatus += 1;
|
this.stats.healthcheckBadStatus += 1;
|
||||||
|
@ -640,7 +709,6 @@ export class WebSocketResourceWithShadowing implements IWebSocketResource {
|
||||||
`${this.logId}: keepalive via libsignal responded with status [${healthCheckResult.status}]`
|
`${this.logId}: keepalive via libsignal responded with status [${healthCheckResult.status}]`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.stats.unexpectedReconnects = debugInfo.reconnectCount;
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.stats.healthcheckFailures += 1;
|
this.stats.healthcheckFailures += 1;
|
||||||
log.warn(
|
log.warn(
|
||||||
|
|
|
@ -180,7 +180,6 @@ type NetworkStatistics = {
|
||||||
unauthorizedRequestsCompared?: string;
|
unauthorizedRequestsCompared?: string;
|
||||||
unauthorizedHealthcheckFailures?: string;
|
unauthorizedHealthcheckFailures?: string;
|
||||||
unauthorizedHealthcheckBadStatus?: string;
|
unauthorizedHealthcheckBadStatus?: string;
|
||||||
unauthorizedUnexpectedReconnects?: string;
|
|
||||||
unauthorizedIpVersionMismatches?: string;
|
unauthorizedIpVersionMismatches?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -220,9 +219,6 @@ ipc.on('additional-log-data-request', async event => {
|
||||||
unauthorizedHealthcheckBadStatus: formatCountForLogging(
|
unauthorizedHealthcheckBadStatus: formatCountForLogging(
|
||||||
unauthorizedStats.healthcheckBadStatus
|
unauthorizedStats.healthcheckBadStatus
|
||||||
),
|
),
|
||||||
unauthorizedUnexpectedReconnects: formatCountForLogging(
|
|
||||||
unauthorizedStats.unexpectedReconnects
|
|
||||||
),
|
|
||||||
unauthorizedIpVersionMismatches: formatCountForLogging(
|
unauthorizedIpVersionMismatches: formatCountForLogging(
|
||||||
unauthorizedStats.ipVersionMismatches
|
unauthorizedStats.ipVersionMismatches
|
||||||
),
|
),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue