UNPKG

detritus-client-socket

Version:

A TypeScript NodeJS library to interact with Discord's Gateway

236 lines (235 loc) 7.41 kB
"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;