signal-desktop/ts/textsecure/CDSSocketManager.ts

81 lines
2.4 KiB
TypeScript
Raw Normal View History

2021-11-08 23:32:31 +00:00
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import ProxyAgent from 'proxy-agent';
import { HsmEnclaveClient, PublicKey } from '@signalapp/signal-client';
import type { connection as WebSocket } from 'websocket';
import * as Bytes from '../Bytes';
2021-11-12 20:45:30 +00:00
import { prefixPublicKey } from '../Curve';
2021-11-08 23:32:31 +00:00
import type { AbortableProcess } from '../util/AbortableProcess';
import * as log from '../logging/log';
import type { UUIDStringType } from '../types/UUID';
import { CDSSocket } from './CDSSocket';
2021-11-12 20:45:30 +00:00
import type { CDSRequestOptionsType } from './CDSSocket';
2021-11-08 23:32:31 +00:00
import { connect as connectWebSocket } from './WebSocket';
export type CDSSocketManagerOptionsType = Readonly<{
url: string;
publicKey: string;
codeHash: string;
certificateAuthority: string;
proxyUrl?: string;
version: string;
}>;
export class CDSSocketManager {
private readonly publicKey: PublicKey;
private readonly codeHash: Buffer;
private readonly proxyAgent?: ReturnType<typeof ProxyAgent>;
constructor(private readonly options: CDSSocketManagerOptionsType) {
this.publicKey = PublicKey.deserialize(
2021-11-12 20:45:30 +00:00
Buffer.from(prefixPublicKey(Bytes.fromHex(options.publicKey)))
2021-11-08 23:32:31 +00:00
);
this.codeHash = Buffer.from(Bytes.fromHex(options.codeHash));
if (options.proxyUrl) {
this.proxyAgent = new ProxyAgent(options.proxyUrl);
}
}
2021-11-12 20:45:30 +00:00
public async request(
options: CDSRequestOptionsType
): Promise<ReadonlyArray<UUIDStringType | null>> {
2021-11-08 23:32:31 +00:00
log.info('CDSSocketManager: connecting socket');
const socket = await this.connect().getResult();
log.info('CDSSocketManager: connected socket');
try {
2021-11-12 20:45:30 +00:00
return await socket.request(options);
2021-11-08 23:32:31 +00:00
} finally {
log.info('CDSSocketManager: closing socket');
socket.close(3000, 'Normal');
}
}
private connect(): AbortableProcess<CDSSocket> {
const enclaveClient = HsmEnclaveClient.new(this.publicKey, [this.codeHash]);
const {
publicKey: publicKeyHex,
codeHash: codeHashHex,
version,
} = this.options;
const url = `${this.options.url}/discovery/${publicKeyHex}/${codeHashHex}`;
return connectWebSocket<CDSSocket>({
url,
version,
proxyAgent: this.proxyAgent,
certificateAuthority: this.options.certificateAuthority,
createResource: (socket: WebSocket): CDSSocket => {
return new CDSSocket(socket, enclaveClient);
},
});
}
}