UNPKG

rtp.js

Version:

RTP stack for Node.js and browser written in TypeScript

146 lines (145 loc) 5.39 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.GenericExtendedReport = void 0; const ExtendedReport_1 = require("./ExtendedReport"); /** * Generic Extended Report. * * ```text * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | BT=??? | type-specific | block length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | body | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * : ... : * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * ``` * * @category RTCP Extended Reports * * @see * - [RFC 3611 section 3](https://datatracker.ietf.org/doc/html/rfc3611#section-3) */ class GenericExtendedReport extends ExtendedReport_1.ExtendedReport { // Buffer view holding the report body. #bodyView; /** * @param view - If given it will be parsed. Otherwise an empty generic * Extended Report will be created. * @param reportType - If `view` is not given, this parameter must be given. * * @throws * - If given `view` does not contain a valid generic Extended Report. */ constructor(view, reportType) { super(view ? (0, ExtendedReport_1.getExtendedReportType)(view) : reportType, view); if (!view && !reportType) { throw new TypeError('view or reportType must be given'); } if (!this.view) { this.view = new DataView(new ArrayBuffer(ExtendedReport_1.COMMON_HEADER_LENGTH)); // Write report type. this.writeCommonHeader(); // Set empty body. this.#bodyView = new DataView(this.view.buffer, this.view.byteOffset + ExtendedReport_1.COMMON_HEADER_LENGTH, 0); return; } // Position relative to the DataView byte offset. let pos = 0; // Move to body. pos += ExtendedReport_1.COMMON_HEADER_LENGTH; // Get body. const bodyLength = this.view.byteLength - pos; this.#bodyView = new DataView(this.view.buffer, this.view.byteOffset + pos, bodyLength); pos += bodyLength; // Ensure that view length and parsed length match. if (pos !== this.view.byteLength) { throw new RangeError(`parsed length (${pos} bytes) does not match view length (${this.view.byteLength} bytes)`); } } /** * Dump generic Extended Report info. */ dump() { return super.dump(); } /** * @inheritDoc */ getByteLength() { if (!this.needsSerialization()) { return this.view.byteLength; } const packetLength = ExtendedReport_1.COMMON_HEADER_LENGTH + this.#bodyView.byteLength; return packetLength; } /** * @inheritDoc */ serialize(buffer, byteOffset) { const view = this.serializeBase(buffer, byteOffset); const uint8Array = new Uint8Array(view.buffer, view.byteOffset, view.byteLength); // Position relative to the DataView byte offset. let pos = 0; // Move to body. pos += ExtendedReport_1.COMMON_HEADER_LENGTH; // Copy the body into the new buffer. uint8Array.set(new Uint8Array(this.#bodyView.buffer, this.#bodyView.byteOffset, this.#bodyView.byteLength), pos); // Create new body DataView. const bodyView = new DataView(view.buffer, view.byteOffset + pos, this.#bodyView.byteLength); pos += bodyView.byteLength; if (pos !== view.byteLength) { throw new RangeError(`filled length (${pos} bytes) does not match the available buffer size (${view.byteLength} bytes)`); } // Update DataView. this.view = view; // Update body DataView. this.#bodyView = bodyView; this.setSerializationNeeded(false); } /** * @inheritDoc */ clone(buffer, byteOffset, serializationBuffer, serializationByteOffset) { const view = this.cloneInternal(buffer, byteOffset, serializationBuffer, serializationByteOffset); return new GenericExtendedReport(view); } /** * Get the value of the type specific field (second byte in the Extended * Report common header). */ getTypeSpecific() { return this.view.getUint8(1); } /** * Set the value of the type specific field (second byte in the Extended * Report common header). */ setTypeSpecific(typeSpecific) { this.view.setUint8(1, typeSpecific); this.setSerializationNeeded(true); } /** * Get the report body. */ getBody() { return this.#bodyView; } /** * Set the report body. * * @remarks * - Given `view` must have a byte length multiple of 4 bytes. */ setBody(view) { this.#bodyView = view; // Ensure body is padded to 4 bytes. if (view.byteLength % 4 !== 0) { throw new TypeError('body byte length must be multiple of 4 bytes'); } this.setSerializationNeeded(true); } } exports.GenericExtendedReport = GenericExtendedReport;