mirror of
https://github.com/danbulant/discord.js
synced 2026-05-27 14:02:02 +00:00
58 lines
1.7 KiB
JavaScript
58 lines
1.7 KiB
JavaScript
const nonce = Buffer.alloc(24);
|
|
const secretbox = require('../util/Secretbox');
|
|
|
|
class Readable extends require('stream').Readable { _read() {} } // eslint-disable-line no-empty-function
|
|
|
|
class PacketHandler {
|
|
constructor(receiver) {
|
|
this.receiver = receiver;
|
|
this.streams = new Map();
|
|
}
|
|
|
|
makeStream(user) {
|
|
if (this.streams.has(user)) return this.streams.get(user);
|
|
const stream = new Readable();
|
|
this.streams.set(user, stream);
|
|
return stream;
|
|
}
|
|
|
|
parseBuffer(buffer) {
|
|
// Reuse nonce buffer
|
|
buffer.copy(nonce, 0, 0, 12);
|
|
|
|
let packet = secretbox.methods.open(buffer.slice(12), nonce, this.receiver.connection.authentication.secretKey);
|
|
if (!packet) return Error('Failed to decrypt voice packet');
|
|
packet = Buffer.from(packet);
|
|
|
|
// Strip RTP Header Extensions (one-byte only)
|
|
if (packet[0] === 0xBE && packet[1] === 0xDE && packet.length > 4) {
|
|
const headerExtensionLength = packet.readUInt16BE(2);
|
|
let offset = 4;
|
|
for (let i = 0; i < headerExtensionLength; i++) {
|
|
const byte = packet[offset];
|
|
offset++;
|
|
if (byte === 0) continue;
|
|
offset += 1 + (0b1111 & (byte >> 4));
|
|
}
|
|
while (packet[offset] === 0) offset++;
|
|
packet = packet.slice(offset);
|
|
}
|
|
|
|
return packet;
|
|
}
|
|
|
|
userFromSSRC(ssrc) { return this.receiver.connection.ssrcMap.get(ssrc); }
|
|
|
|
push(buffer) {
|
|
const ssrc = buffer.readUInt32BE(8);
|
|
const user = this.userFromSSRC(ssrc);
|
|
if (!user) return;
|
|
const stream = this.streams.get(user.id);
|
|
if (!stream) return;
|
|
const opusPacket = this.parseBuffer(buffer);
|
|
if (opusPacket instanceof Error) return;
|
|
stream.push(opusPacket);
|
|
}
|
|
}
|
|
|
|
module.exports = PacketHandler;
|