detritus-client-socket
Version:
A TypeScript NodeJS library to interact with Discord's Gateway
236 lines (235 loc) • 7.41 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RTPNonce = exports.RTPHeader = exports.isValidRTPHeader = exports.ValidRTPVersion = void 0;
const constants_1 = require("../constants");
const rtpcrypto_1 = require("./rtpcrypto");
exports.ValidRTPVersion = 2;
function isValidRTPHeader(buffer) {
return ((buffer.readUIntBE(0, 1) >> 6) === 2);
}
exports.isValidRTPHeader = isValidRTPHeader;
;
class RTPHeader {
constructor(options = {}) {
if (options.buffer) {
this.buffer = options.buffer;
}
else {
this.buffer = Buffer.alloc(12);
}
Object.defineProperty(this, 'buffer', { enumerable: false, writable: false });
if (!options.buffer && options.version === undefined) {
options.version = exports.ValidRTPVersion;
}
if (options.version !== undefined) {
this.setVersion(options.version);
}
if (options.marker !== undefined) {
this.setMarker(options.marker);
}
if (options.payloadType !== undefined) {
this.setPayloadType(options.payloadType);
}
if (options.ssrc !== undefined) {
this.setSSRC(options.ssrc);
}
if (options.randomize) {
this.randomizeSequence();
this.randomizeTimestamp();
}
}
get length() {
return this.buffer.length;
}
get valid() {
return isValidRTPHeader(this.buffer);
}
get firstByte() {
return this.buffer.readUIntBE(0, 1);
}
get secondByte() {
return this.buffer.readUIntBE(1, 1);
}
get version() {
return this.firstByte >> 6;
}
get padding() {
return (this.firstByte >> 5) & 1;
}
get extension() {
return (this.firstByte >> 4) & 1;
}
get csrcCount() {
return this.firstByte & 0x0F;
}
get marker() {
return this.secondByte >> 7;
}
get payloadType() {
return this.secondByte & 0x7F;
}
/* header[2, 3] = sequence*/
get sequence() {
return this.buffer.readUIntBE(2, 2);
}
/* header[4, 5, 6, 7] = timestamp*/
get timestamp() {
return this.buffer.readUIntBE(4, 4);
}
/* header[8, 9, 10, 11] = ssrc*/
get ssrc() {
return this.buffer.readUIntBE(8, 4);
}
get nonceNumber() {
if (this.nonce) {
return this.nonce.readUIntBE(0, 4);
}
return 0;
}
randomizeSequence() {
this.setSequence(Math.round(Math.random() * constants_1.MaxNumbers.UINT16));
}
randomizeTimestamp() {
this.setTimestamp(Math.round(Math.random() * constants_1.MaxNumbers.UINT32));
}
randomizeNonce() {
this.setNonce(Math.round(Math.random() * constants_1.MaxNumbers.UINT32));
}
setVersion(version) {
this.buffer.writeUIntBE((version << 6 | this.padding << 5 | this.extension << 4 | this.csrcCount), 0, 1);
}
setPadding(padding) {
this.buffer.writeUIntBE((this.version << 6 | Number(!!padding) << 5 | this.extension << 4 | this.csrcCount), 0, 1);
}
setExtension(extension) {
this.buffer.writeUIntBE((this.version << 6 | this.padding << 5 | Number(!!extension) << 4 | this.csrcCount), 0, 1);
}
setCSRCCount(csrcCount) {
this.buffer.writeUIntBE((this.version << 6 | this.padding << 5 | this.extension << 4 | csrcCount), 0, 1);
}
setMarker(marker) {
this.buffer.writeUIntBE((Number(!!marker) << 7 | this.payloadType), 1, 1);
}
setPayloadType(payloadType) {
this.buffer.writeUIntBE((this.marker << 7 | payloadType), 1, 1);
}
setSequence(sequence, increment = false) {
if (sequence === undefined) {
sequence = 1;
increment = true;
}
if (increment) {
sequence = this.sequence + 1;
}
sequence %= constants_1.MaxNumbers.UINT16;
this.buffer.writeUIntBE(sequence, 2, 2);
}
setTimestamp(timestamp, increment = false) {
if (timestamp === undefined) {
timestamp = Date.now();
increment = false;
}
if (increment) {
timestamp += this.timestamp;
}
timestamp %= constants_1.MaxNumbers.UINT32;
this.buffer.writeUIntBE(timestamp, 4, 4);
}
setSSRC(ssrc) {
if (!Number.isInteger(ssrc)) {
throw new Error('SSRC must be an integer!');
}
if (constants_1.MaxNumbers.UINT32 < ssrc) {
throw new Error(`SSRC must not be over ${constants_1.MaxNumbers.UINT32}`);
}
this.buffer.writeUIntBE(ssrc, 8, 4);
}
setPayload(payload, replace = false) {
if (replace) {
this.payload = payload;
}
else {
if (!this.payload) {
throw new Error('Cannot overwrite a non-existant payload on this packet');
}
this.payload.fill(0);
payload.copy(this.payload);
}
}
setNonce(nonce, increment = false) {
if (Buffer.isBuffer(nonce)) {
if (this.nonce) {
this.nonce.fill(0);
nonce.copy(this.nonce);
}
else {
this.nonce = nonce;
}
}
else {
if (!this.nonce) {
this.nonce = Buffer.alloc(24);
this.randomizeNonce();
}
if (nonce === undefined) {
nonce = 1;
increment = true;
}
if (increment) {
nonce += this.nonceNumber;
}
nonce %= constants_1.MaxNumbers.UINT32;
this.nonce.writeUIntBE(nonce, 0, 4);
}
}
reset() {
const firstByte = this.firstByte;
const secondByte = this.secondByte;
this.buffer.fill(0);
this.buffer.writeUIntBE(firstByte, 0, 1);
this.buffer.writeUIntBE(secondByte, 1, 1);
if (this.payload) {
this.payload.fill(0);
}
this.randomizeSequence();
this.randomizeTimestamp();
}
copy(target, targetStart, sourceStart, sourceEnd) {
return this.buffer.copy(target, targetStart, sourceStart, sourceEnd);
}
}
exports.RTPHeader = RTPHeader;
class RTPNonce {
constructor(options = {}) {
this.buffer = Buffer.alloc(24);
Object.defineProperty(this, 'buffer', { enumerable: false, writable: false });
if (options.randomize || options.randomize === undefined) {
this.randomize();
}
}
get number() {
return this.buffer.readUIntBE(0, 4);
}
copy(target, targetStart, sourceStart, sourceEnd) {
return this.buffer.copy(target, targetStart, sourceStart, sourceEnd);
}
generate() {
return rtpcrypto_1.default.generateNonce(this.buffer);
}
randomize() {
return this.set(Math.round(Math.random() * constants_1.MaxNumbers.UINT32));
}
set(nonce, increment = false) {
if (nonce === undefined) {
nonce = 1;
increment = true;
}
if (increment) {
nonce = this.number + nonce;
}
nonce %= constants_1.MaxNumbers.UINT32;
this.buffer.writeUIntBE(nonce, 0, 4);
return this.buffer;
}
}
exports.RTPNonce = RTPNonce;