rtp.js
Version:
RTP stack for Node.js and browser written in TypeScript
122 lines (121 loc) • 5.4 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Serializable = void 0;
const helpers_1 = require("../utils/helpers");
/**
* Class holding a serializable buffer view. All RTP and RTCP packets inherit
* from this class, and also items in some RTCP packets.
*/
class Serializable {
// Buffer view holding the packet or item content.
// @ts-expect-error --- 'view' has not initializer and is not assigned in
// constructor.
view;
// Whether serialization is needed due to recent modifications.
#serializationNeeded = false;
constructor(view) {
if (view) {
this.view = view;
}
}
/**
* Serializable dump.
*/
dump() {
return {
byteLength: this.getByteLength(),
};
}
/**
* Get a buffer view containing the serialized content of the packet or item.
*
* @param serializationBuffer - Buffer in which the content will be serialized
* in case serialization is needed. If not given, a new one will internally
* allocated.
* @param serializationByteOffset - Byte offset of the given `serializationBuffer`
* where serialization (if needed) will start.
*
* @remarks
* - The internal buffer is serialized if needed (to apply pending
* modifications) by internally calling {@link serialize}.
*
* @throws
* - If buffer serialization is needed and it fails due to invalid
* content.
*/
getView(serializationBuffer, serializationByteOffset) {
if (this.needsSerialization()) {
this.serialize(serializationBuffer, serializationByteOffset);
}
return this.view;
}
/**
* Whether serialization is needed, meaning that the current buffer view
* doesn't represent the current content of the packet or item (due to
* modifications not applied yet). Calling {@link serialize} or {@link getView}
* will serialize the packet or the item.
*/
needsSerialization() {
return this.#serializationNeeded;
}
setSerializationNeeded(flag) {
this.#serializationNeeded = flag;
}
/**
* This method returns a buffer (plus byte offset) for the child to serialize.
* If a buffer (and optionally a byte offset) is given, this method will verify
* whether the serialized content can fit into it and will throw otherwise.
*/
getSerializationBuffer(buffer, byteOffset = 0) {
const byteLength = this.getByteLength();
if (buffer) {
if (buffer.byteLength - byteOffset < byteLength) {
throw new RangeError(`given buffer available space (${buffer.byteLength - byteOffset} bytes) is less than length required for serialization (${byteLength} bytes)`);
}
// If the given buffer is the same as the one internally used by the view
// of this packet, we must assert that the new serialization would not
// happen in bytes where the packet currently exists.
// Here we must take into account the given byte offset and the byte
// offset of the view, the current packet length and the expected packet
// length after the serialization.
if (buffer === this.view.buffer &&
((byteOffset >= this.view.byteOffset &&
byteOffset <= this.view.byteOffset + this.view.byteLength - 1) ||
(byteOffset + byteLength - 1 >= this.view.byteOffset &&
byteOffset + byteLength <=
this.view.byteOffset + this.view.byteLength - 1))) {
throw new RangeError('given buffer is the same as the internal buffer of the packet and given byteLength would make serialization override existing packet data');
}
const uint8Array = new Uint8Array(buffer, byteOffset, byteLength);
// If a buffer is given, ensure the required length is filled with zeroes.
uint8Array.fill(0);
}
else {
// The buffer is guaranteed to be filled with zeros.
buffer = new ArrayBuffer(byteLength);
}
return { buffer, byteOffset, byteLength };
}
cloneInternal(buffer, byteOffset = 0, serializationBuffer, serializationByteOffset) {
if (this.needsSerialization()) {
this.serialize(serializationBuffer, serializationByteOffset);
}
let view;
// If buffer is given, let's check whether it holds enough space for the
// content.
if (buffer) {
if (buffer.byteLength - byteOffset < this.view.byteLength) {
throw new RangeError(`given buffer available space (${buffer.byteLength - byteOffset} bytes) is less than length required for clonation (${this.view.byteLength} bytes)`);
}
// Copy the content into the given buffer.
const uint8Array = new Uint8Array(buffer, byteOffset, this.view.byteLength);
uint8Array.set(new Uint8Array(this.view.buffer, this.view.byteOffset, this.view.byteLength), 0);
view = new DataView(uint8Array.buffer, uint8Array.byteOffset, uint8Array.byteLength);
}
else {
view = (0, helpers_1.clone)(this.view);
}
return view;
}
}
exports.Serializable = Serializable;