Skip to content

Commit

Permalink
Add ECNExtendedReport
Browse files Browse the repository at this point in the history
  • Loading branch information
ibc committed Aug 23, 2023
1 parent 21f1b70 commit a251a69
Show file tree
Hide file tree
Showing 4 changed files with 320 additions and 1 deletion.
297 changes: 297 additions & 0 deletions src/packets/RTCP/ExtendedReports/ECNExtendedReport.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,297 @@
import {
ExtendedReport,
ExtendedReportType,
ExtendedReportDump,
COMMON_HEADER_LENGTH
} from './ExtendedReport';

const ECN_EXTENDED_REPORT_LENGTH = COMMON_HEADER_LENGTH + 20;

/**
* ECN Summary Extended Report dump.
*
* @category RTCP Extended Reports
*/
export type ECNExtendedReportDump = ExtendedReportDump &
{
ssrc: number;
ect0Counter: number;
ect1Counter: number;
ecnCeCounter: number;
nonEctCounter: number;
lostPacketsCounter: number;
duplicationCounter: number;
};

/**
* ECN 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=13 | reserved | block length = 5 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | SSRC of Media Sender |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | ECT (0) Counter |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | ECT (1) Counter |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | ECN-CE Counter | not-ECT Counter |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Lost Packets Counter | Duplication Counter |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* ```
*
* @category RTCP Extended Reports
*
* @see
* - [RFC 6679 section 5.2](https://datatracker.ietf.org/doc/html/rfc6679#section-5.2)
*/
export class ECNExtendedReport extends ExtendedReport
{
// Chunks (2 bytes numbers, unparsed).
#chunks: number[] = [];

/**
* @param view - If given it will be parsed. Otherwise an empty ECN Summary
* Extended Report will be created.
*/
constructor(view?: DataView)
{
super(ExtendedReportType.ECN, view);

if (!this.view)
{
this.view = new DataView(new ArrayBuffer(ECN_EXTENDED_REPORT_LENGTH));

// Write report type.
this.writeCommonHeader();

return;
}

if (this.view.byteLength !== ECN_EXTENDED_REPORT_LENGTH)
{
throw new TypeError(
'wrong byte length for a ECN Summary Extended Report'
);
}
}

/**
* Dump ECN Summary Extended Report info.
*/
dump(): ECNExtendedReportDump
{
return {
...super.dump(),
ssrc : this.getSsrc(),
ect0Counter : this.getEct0Counter(),
ect1Counter : this.getEct1Counter(),
ecnCeCounter : this.getEcnCeCounter(),
nonEctCounter : this.getNonEctCounter(),
lostPacketsCounter : this.getLostPacketsCounter(),
duplicationCounter : this.getDuplicationCounter()
};
}

/**
* @inheritDoc
*/
getByteLength(): number
{
return ECN_EXTENDED_REPORT_LENGTH;
}

/**
* @inheritDoc
*/
serialize(buffer?: ArrayBuffer, byteOffset?: number): void
{
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 += 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,
ECN_EXTENDED_REPORT_LENGTH - COMMON_HEADER_LENGTH
),
pos
);

// Move to the end.
pos += ECN_EXTENDED_REPORT_LENGTH - 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?: ArrayBuffer,
byteOffset?: number,
serializationBuffer?: ArrayBuffer,
serializationByteOffset?: number
): ECNExtendedReport
{
const view = this.cloneInternal(
buffer,
byteOffset,
serializationBuffer,
serializationByteOffset
);

return new ECNExtendedReport(view);
}

/**
* Get SSRC of media sender.
*/
getSsrc(): number
{
return this.view.getUint32(4);
}

/**
* Set SSRC of media sender.
*/
setSsrc(ssrc: number): void
{
this.view.setUint32(4, ssrc);

this.setSerializationNeeded(true);
}

/**
* Get ECT (0) Counter.
*/
getEct0Counter(): number
{
return this.view.getUint32(8);
}

/**
* Set ECT (0) Counter.
*/
setEct0Counter(counter: number): void
{
this.view.setUint32(8, counter);

this.setSerializationNeeded(true);
}

/**
* Get ECT (1) Counter.
*/
getEct1Counter(): number
{
return this.view.getUint32(12);
}

/**
* Set ECT (1) Counter.
*/
setEct1Counter(counter: number): void
{
this.view.setUint32(12, counter);

this.setSerializationNeeded(true);
}

/**
* Get ECN-CE Counter.
*/
getEcnCeCounter(): number
{
return this.view.getUint16(16);
}

/**
* Set ECN-CE Counter.
*/
setEcnCeCounter(counter: number): void
{
this.view.setUint16(16, counter);

this.setSerializationNeeded(true);
}

/**
* Get not-ECT Counter.
*/
getNonEctCounter(): number
{
return this.view.getUint16(18);
}

/**
* Set not-ECT Counter.
*/
setNonEctCounter(counter: number): void
{
this.view.setUint16(18, counter);

this.setSerializationNeeded(true);
}

/**
* Get Lost Packets Counter.
*/
getLostPacketsCounter(): number
{
return this.view.getUint16(20);
}

/**
* Set Lost Packets Counter.
*/
setLostPacketsCounter(counter: number): void
{
this.view.setUint16(20, counter);

this.setSerializationNeeded(true);
}

/**
* Get Duplication Counter.
*/
getDuplicationCounter(): number
{
return this.view.getUint16(22);
}

/**
* Set Duplication Counter.
*/
setDuplicationCounter(counter: number): void
{
this.view.setUint16(22, counter);

this.setSerializationNeeded(true);
}
}
11 changes: 10 additions & 1 deletion src/packets/RTCP/ExtendedReports/ExtendedReport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ export enum ExtendedReportType
/**
* VoIP Metrics Report.
*/
VM = 7
VM = 7,
/**
* ECN Summary Report.
*/
ECN = 13
}

/**
Expand Down Expand Up @@ -142,6 +146,11 @@ export function reportTypeToString(reportType: ExtendedReportType): string
return 'VoIP Metrics';
}

case ExtendedReportType.ECN:
{
return 'ECN Summary';
}

default:
{
assertUnreachable(reportType);
Expand Down
8 changes: 8 additions & 0 deletions src/packets/RTCP/XrPacket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { RRTExtendedReport } from './ExtendedReports/RRTExtendedReport';
import { DLRRExtendedReport } from './ExtendedReports/DLRRExtendedReport';
import { SSExtendedReport } from './ExtendedReports/SSExtendedReport';
import { VMExtendedReport } from './ExtendedReports/VMExtendedReport';
import { ECNExtendedReport } from './ExtendedReports/ECNExtendedReport';
import { GenericExtendedReport } from './ExtendedReports/GenericExtendedReport';
import {
RtcpPacket,
Expand Down Expand Up @@ -156,6 +157,13 @@ export class XrPacket extends RtcpPacket
break;
}

case ExtendedReportType.ECN:
{
report = new ECNExtendedReport(reportView);

break;
}

default:
{
report = new GenericExtendedReport(reportView);
Expand Down
5 changes: 5 additions & 0 deletions src/packets/public.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,11 @@ export {
VMExtendedReportDump
} from './RTCP/ExtendedReports/VMExtendedReport';

export {
ECNExtendedReport,
ECNExtendedReportDump
} from './RTCP/ExtendedReports/ECNExtendedReport';

export {
GenericExtendedReport,
GenericExtendedReportDump
Expand Down

0 comments on commit a251a69

Please sign in to comment.