fix(Voice): send keep alives without awaiting a response (#9202)

This commit is contained in:
Vlad Frangu
2023-03-09 13:12:02 +02:00
committed by GitHub
parent f65ac2ea78
commit c6d98fa0c5
2 changed files with 3 additions and 61 deletions

View File

@@ -121,23 +121,6 @@ describe('VoiceUDPSocket#performIPDiscovery', () => {
expect(closed).toEqual(false);
});
test('Emits an error when no response received to keep alive messages', async () => {
const fake = new FakeSocket();
fake.send = jest.fn();
createSocket.mockImplementation(() => fake as any);
socket = new VoiceUDPSocket({ ip: '1.2.3.4', port: 25_565 });
let closed = false;
socket.on('close', () => (closed = true));
for (let index = 0; index < 15; index++) {
jest.advanceTimersToNextTimer();
await wait();
}
expect(closed).toEqual(true);
});
test('Recovers from intermittent responses', async () => {
const fake = new FakeSocket();
const fakeSend = jest.fn();

View File

@@ -12,11 +12,6 @@ export interface SocketConfig {
port: number;
}
interface KeepAlive {
timestamp: number;
value: number;
}
/**
* Parses the response from Discord to aid with local IP discovery.
*
@@ -41,11 +36,6 @@ export function parseLocalPacket(message: Buffer): SocketConfig {
*/
const KEEP_ALIVE_INTERVAL = 5e3;
/**
* The maximum number of keep alive packets which can be missed.
*/
const KEEP_ALIVE_LIMIT = 12;
/**
* The maximum value of the keep alive counter.
*/
@@ -72,11 +62,6 @@ export class VoiceUDPSocket extends EventEmitter {
*/
private readonly remote: SocketConfig;
/**
* A list of keep alives that are waiting to be acknowledged.
*/
private readonly keepAlives: KeepAlive[];
/**
* The counter used in the keep alive mechanism.
*/
@@ -94,32 +79,26 @@ export class VoiceUDPSocket extends EventEmitter {
/**
* The time taken to receive a response to keep alive messages.
*
* @deprecated This field is no longer updated as keep alive messages are no longer tracked.
*/
public ping?: number;
/**
* The debug logger function, if debugging is enabled.
*/
private readonly debug: ((message: string) => void) | null;
/**
* Creates a new VoiceUDPSocket.
*
* @param remote - Details of the remote socket
*/
public constructor(remote: SocketConfig, debug = false) {
public constructor(remote: SocketConfig) {
super();
this.socket = createSocket('udp4');
this.socket.on('error', (error: Error) => this.emit('error', error));
this.socket.on('message', (buffer: Buffer) => this.onMessage(buffer));
this.socket.on('close', () => this.emit('close'));
this.remote = remote;
this.keepAlives = [];
this.keepAliveBuffer = Buffer.alloc(8);
this.keepAliveInterval = setInterval(() => this.keepAlive(), KEEP_ALIVE_INTERVAL);
setImmediate(() => this.keepAlive());
this.debug = debug ? (message: string) => this.emit('debug', message) : null;
}
/**
@@ -128,16 +107,6 @@ export class VoiceUDPSocket extends EventEmitter {
* @param buffer - The received buffer
*/
private onMessage(buffer: Buffer): void {
// Handle keep alive message
if (buffer.length === 8) {
const counter = buffer.readUInt32LE(0);
const index = this.keepAlives.findIndex(({ value }) => value === counter);
if (index === -1) return;
this.ping = Date.now() - this.keepAlives[index]!.timestamp;
// Delete all keep alives up to and including the received one
this.keepAlives.splice(0, index);
}
// Propagate the message
this.emit('message', buffer);
}
@@ -146,18 +115,8 @@ export class VoiceUDPSocket extends EventEmitter {
* Called at a regular interval to check whether we are still able to send datagrams to Discord.
*/
private keepAlive() {
if (this.keepAlives.length >= KEEP_ALIVE_LIMIT) {
this.debug?.('UDP socket has not received enough responses from Discord - closing socket');
this.destroy();
return;
}
this.keepAliveBuffer.writeUInt32LE(this.keepAliveCounter, 0);
this.send(this.keepAliveBuffer);
this.keepAlives.push({
value: this.keepAliveCounter,
timestamp: Date.now(),
});
this.keepAliveCounter++;
if (this.keepAliveCounter > MAX_COUNTER_VALUE) {
this.keepAliveCounter = 0;