UNPKG

rtp.js

Version:

RTP stack for Node.js and browser written in TypeScript

490 lines (489 loc) 14.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SsExtendedReport = void 0; const ExtendedReport_1 = require("./ExtendedReport"); const bitOps_1 = require("../../../utils/bitOps"); const SS_EXTENDED_REPORT_LENGTH = ExtendedReport_1.COMMON_HEADER_LENGTH + 36; /** * Statistics Summary 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=6 |L|D|J|ToH|rsvd.| block length = 9 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | SSRC of source | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | begin_seq | end_seq | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | lost_packets | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | dup_packets | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | min_jitter | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | max_jitter | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | mean_jitter | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | dev_jitter | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | min_ttl_or_hl | max_ttl_or_hl |mean_ttl_or_hl | dev_ttl_or_hl | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * ``` * * @category RTCP Extended Reports * * @see * - [RFC 3611 section 4.6](https://datatracker.ietf.org/doc/html/rfc3611#section-4.6) */ class SsExtendedReport extends ExtendedReport_1.ExtendedReport { /** * @param view - If given it will be parsed. Otherwise an empty Statistics * Summary Extended Report will be created. */ constructor(view) { super(ExtendedReport_1.ExtendedReportType.SS, view); if (!this.view) { this.view = new DataView(new ArrayBuffer(SS_EXTENDED_REPORT_LENGTH)); // Write report type. this.writeCommonHeader(); return; } if (this.view.byteLength !== SS_EXTENDED_REPORT_LENGTH) { throw new TypeError('wrong byte length for a Statistics Summary Extended Report'); } } /** * Dump Statistics Summary Extended Report info. */ dump() { return { ...super.dump(), ssrc: this.getSsrc(), beginSeq: this.getBeginSeq(), endSeq: this.getEndSeq(), lostPackets: this.getLostPackets(), duplicatePackets: this.getDuplicatePackets(), minJitter: this.getMinJitter(), maxJitter: this.getMaxJitter(), meanJitter: this.getMeanJitter(), devJitter: this.getDevJitter(), minTtlOrHl: this.getMinTtlOrHopLimit(), maxTtlOrHl: this.getMaxTtlOrHopLimit(), meanTtlOrHl: this.getMeanTtlOrHopLimit(), devTtlOrHl: this.getDevTtlOrHopLimit(), ttlOrHlMode: this.getTtlOrHopLimitMode(), }; } /** * @inheritDoc */ getByteLength() { return SS_EXTENDED_REPORT_LENGTH; } /** * @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 the fixed header fields after the common header. pos += ExtendedReport_1.COMMON_HEADER_LENGTH; // Copy the rest of the Extended Report into the new buffer. uint8Array.set(new Uint8Array(this.view.buffer, this.view.byteOffset + pos, SS_EXTENDED_REPORT_LENGTH - ExtendedReport_1.COMMON_HEADER_LENGTH), pos); // Move to the end. pos += SS_EXTENDED_REPORT_LENGTH - ExtendedReport_1.COMMON_HEADER_LENGTH; 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; this.setSerializationNeeded(false); } /** * @inheritDoc */ clone(buffer, byteOffset, serializationBuffer, serializationByteOffset) { const view = this.cloneInternal(buffer, byteOffset, serializationBuffer, serializationByteOffset); return new SsExtendedReport(view); } /** * Get SSRC of source. */ getSsrc() { return this.view.getUint32(4); } /** * Set SSRC of source. */ setSsrc(ssrc) { this.view.setUint32(4, ssrc); this.setSerializationNeeded(true); } /** * Get begin sequence number. */ getBeginSeq() { return this.view.getUint16(8); } /** * Set begin sequence number. */ setBeginSeq(seq) { this.view.setUint16(8, seq); this.setSerializationNeeded(true); } /** * Get end sequence number. */ getEndSeq() { return this.view.getUint16(10); } /** * Set end sequence number. */ setEndSeq(seq) { this.view.setUint16(10, seq); this.setSerializationNeeded(true); } /** * Get number of lost packets. * * @remarks * - It could be `undefined` if the field is unset in the report. */ getLostPackets() { if (!this.hasLostPacketsBit()) { return undefined; } return this.view.getUint32(12); } /** * Set number of lost packets. */ setLostPackets(lostPackets) { if (lostPackets !== undefined) { this.setLostPacketsBit(true); this.view.setUint32(12, lostPackets); } else { this.setLostPacketsBit(false); } this.setSerializationNeeded(true); } /** * Get number of duplicate packets. * * @remarks * - It could be `undefined` if the field is unset in the report. */ getDuplicatePackets() { if (!this.hasDuplicatePacketsBit()) { return undefined; } return this.view.getUint32(16); } /** * Set number of duplicate packets. */ setDuplicatePackets(duplicatePackets) { if (duplicatePackets !== undefined) { this.setDuplicatePacketsBit(true); this.view.setUint32(16, duplicatePackets); } else { this.setDuplicatePacketsBit(false); } this.setSerializationNeeded(true); } /** * Get minimum jitter. * * @remarks * - It could be `undefined` if the field is unset in the report. */ getMinJitter() { if (!this.hasJitterBit()) { return undefined; } return this.view.getUint32(20); } /** * Set minimum jitter. */ setMinJitter(minJitter) { if (minJitter !== undefined) { this.setJitterBit(true); this.view.setUint32(20, minJitter); } else { this.setJitterBit(false); } this.setSerializationNeeded(true); } /** * Get maximum jitter. * * @remarks * - It could be `undefined` if the field is unset in the report. */ getMaxJitter() { if (!this.hasJitterBit()) { return undefined; } return this.view.getUint32(24); } /** * Set maximum jitter. */ setMaxJitter(maxJitter) { if (maxJitter !== undefined) { this.setJitterBit(true); this.view.setUint32(24, maxJitter); } else { this.setJitterBit(false); } this.setSerializationNeeded(true); } /** * Get mean jitter. * * @remarks * - It could be `undefined` if the field is unset in the report. */ getMeanJitter() { if (!this.hasJitterBit()) { return undefined; } return this.view.getUint32(28); } /** * Set mean jitter. */ setMeanJitter(meanJitter) { if (meanJitter !== undefined) { this.setJitterBit(true); this.view.setUint32(28, meanJitter); } else { this.setJitterBit(false); } this.setSerializationNeeded(true); } /** * Get dev jitter. * * @remarks * - It could be `undefined` if the field is unset in the report. */ getDevJitter() { if (!this.hasJitterBit()) { return undefined; } return this.view.getUint32(32); } /** * Set dev jitter. */ setDevJitter(devJitter) { if (devJitter !== undefined) { this.setJitterBit(true); this.view.setUint32(32, devJitter); } else { this.setJitterBit(false); } this.setSerializationNeeded(true); } /** * Get minimum TTL or Hop Limit value. * * @remarks * - It could be `undefined` if the field is unset in the report. */ getMinTtlOrHopLimit() { if (!this.getTtlOrHopLimitMode()) { return undefined; } return this.view.getUint8(36); } /** * Set minimum TTL or Hop Limit value. */ setMinTtlOrHl(minTtlOrHl) { if (minTtlOrHl !== undefined) { if (!this.getTtlOrHopLimitMode()) { this.setTtlOrHlMode('ipv4-ttl'); } this.view.setUint8(36, minTtlOrHl); } else { this.setTtlOrHlMode(undefined); } this.setSerializationNeeded(true); } /** * Get maximum TTL or Hop Limit value. * * @remarks * - It could be `undefined` if the field is unset in the report. */ getMaxTtlOrHopLimit() { if (!this.getTtlOrHopLimitMode()) { return undefined; } return this.view.getUint8(37); } /** * Set maximum TTL or Hop Limit value. */ setMaxTtlOrHl(maxTtlOrHl) { if (maxTtlOrHl !== undefined) { if (!this.getTtlOrHopLimitMode()) { this.setTtlOrHlMode('ipv4-ttl'); } this.view.setUint8(37, maxTtlOrHl); } else { this.setTtlOrHlMode(undefined); } this.setSerializationNeeded(true); } /** * Get mean TTL or Hop Limit value. * * @remarks * - It could be `undefined` if the field is unset in the report. */ getMeanTtlOrHopLimit() { if (!this.getTtlOrHopLimitMode()) { return undefined; } return this.view.getUint8(38); } /** * Set mean TTL or Hop Limit value. */ setMeanTtlOrHl(meanTtlOrHl) { if (meanTtlOrHl !== undefined) { if (!this.getTtlOrHopLimitMode()) { this.setTtlOrHlMode('ipv4-ttl'); } this.view.setUint8(38, meanTtlOrHl); } else { this.setTtlOrHlMode(undefined); } this.setSerializationNeeded(true); } /** * Get dev TTL or Hop Limit value. * * @remarks * - It could be `undefined` if the field is unset in the report. */ getDevTtlOrHopLimit() { if (!this.getTtlOrHopLimitMode()) { return undefined; } return this.view.getUint8(39); } /** * Set dev TTL or Hop Limit value. */ setDevTtlOrHl(devTtlOrHl) { if (devTtlOrHl !== undefined) { if (!this.getTtlOrHopLimitMode()) { this.setTtlOrHlMode('ipv4-ttl'); } this.view.setUint8(39, devTtlOrHl); } else { this.setTtlOrHlMode(undefined); } this.setSerializationNeeded(true); } getTtlOrHopLimitMode() { const value = (0, bitOps_1.readBitsInDataView)({ view: this.view, pos: 1, mask: 0b00011000, }); if (value === 1) { return 'ipv4-ttl'; } else if (value === 2) { return 'ipv6-hop-limit'; } else { return undefined; } } setTtlOrHlMode(mode) { if (mode === 'ipv4-ttl') { (0, bitOps_1.writeBitsInDataView)({ view: this.view, pos: 1, mask: 0b00011000, value: 1, }); } else if (mode === 'ipv6-hop-limit') { (0, bitOps_1.writeBitsInDataView)({ view: this.view, pos: 1, mask: 0b00011000, value: 2, }); } else { (0, bitOps_1.writeBitsInDataView)({ view: this.view, pos: 1, mask: 0b00011000, value: 0, }); this.view.setUint8(36, 0); this.view.setUint8(37, 0); this.view.setUint8(38, 0); this.view.setUint8(39, 0); } this.setSerializationNeeded(true); } hasLostPacketsBit() { return (0, bitOps_1.readBitInDataView)({ view: this.view, pos: 1, bit: 7 }); } setLostPacketsBit(flag) { (0, bitOps_1.writeBitInDataView)({ view: this.view, pos: 1, bit: 1, flag }); if (!flag) { this.view.setUint32(12, 0); } } hasDuplicatePacketsBit() { return (0, bitOps_1.readBitInDataView)({ view: this.view, pos: 1, bit: 6 }); } setDuplicatePacketsBit(flag) { (0, bitOps_1.writeBitInDataView)({ view: this.view, pos: 1, bit: 6, flag }); if (!flag) { this.view.setUint32(16, 0); } } hasJitterBit() { return (0, bitOps_1.readBitInDataView)({ view: this.view, pos: 1, bit: 5 }); } setJitterBit(flag) { (0, bitOps_1.writeBitInDataView)({ view: this.view, pos: 1, bit: 5, flag }); if (!flag) { this.view.setUint32(20, 0); this.view.setUint32(24, 0); this.view.setUint32(28, 0); this.view.setUint32(32, 0); } } } exports.SsExtendedReport = SsExtendedReport;