Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 60 additions & 17 deletions index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,16 @@ It uses an additional API on {{RTCRtpSender}} and {{RTCRtpReceiver}} to
insert the processing into the pipeline.

<pre class="idl">
typedef (SFrameTransform or RTCRtpScriptTransform) RTCRtpTransform;
typedef (SFrameSenderTransform or RTCRtpScriptTransform) RTCRtpSenderTransform;
typedef (SFrameReceiverTransform or RTCRtpScriptTransform) RTCRtpReceiverTransform;

// New methods for RTCRtpSender and RTCRtpReceiver
partial interface RTCRtpSender {
attribute RTCRtpTransform? transform;
attribute RTCRtpSenderTransform? transform;
};

partial interface RTCRtpReceiver {
attribute RTCRtpTransform? transform;
attribute RTCRtpReceiverTransform? transform;
};
</pre>

Expand Down Expand Up @@ -214,7 +215,7 @@ There is no guarantee on which frame will happen the switch from the previous tr
If a web application sets the transform synchronously at creation of the {{RTCRtpSender}} (for instance when calling addTrack), the transform will receive the first frame generated by the {{RTCRtpSender}}'s encoder.
Similarly, if a web application sets the transform synchronously at creation of the {{RTCRtpReceiver}} (for instance when calling addTrack, or at track event handler), the transform will receive the first full frame generated by the {{RTCRtpReceiver}}'s packetizer.

# SFrameTransform # {#sframe}
# SFrame transforms # {#sframe}

<p>
The APIs presented in this section allow applications to process SFrame data using specific cipher suites defined in [[RFC9605]].
Expand All @@ -237,30 +238,42 @@ dictionary SFrameTransformOptions {
typedef [EnforceRange] unsigned long long SmallCryptoKeyID;
typedef (SmallCryptoKeyID or bigint) CryptoKeyID;

interface mixin SFrameKeyManagement {
interface mixin SFrameEncrypterManagement {
Promise<undefined> setEncryptionKey(CryptoKey key, optional CryptoKeyID keyID);
attribute EventHandler onerror;
};

interface mixin SFrameDecrypterManagement {
Promise<undefined> addDecryptionKey(CryptoKey key, CryptoKeyID keyID);
Promise<undefined> removeDecryptionKey(CryptoKeyID keyID);
attribute EventHandler onerror;
};

[Exposed=Window]
interface SFrameSenderTransform {
constructor(optional SFrameTransformOptions options = {});
};
SFrameSenderTransform includes SFrameEncrypterKeyManagement;

[Exposed=Window]
interface SFrameTransform : EventTarget {
interface SFrameReceiverTransform : EventTarget {
constructor(optional SFrameTransformOptions options = {});
};
SFrameTransform includes SFrameKeyManagement;
SFrameReceiverTransform includes SFrameDecrypterKeyManagement;

[Exposed=(Window,DedicatedWorker)]
interface SFrameEncrypterStream : EventTarget {
constructor(optional SFrameTransformOptions options = {});
};
SFrameEncrypterStream includes GenericTransformStream;
SFrameEncrypterStream includes SFrameKeyManagement;
SFrameEncrypterStream includes SFrameEncrypterManagement;

[Exposed=(Window,DedicatedWorker)]
interface SFrameDecrypterStream : EventTarget {
constructor(optional SFrameTransformOptions options = {});
};
SFrameDecrypterStream includes GenericTransformStream;
SFrameDecrypterStream includes SFrameKeyManagement;
SFrameDecrypterStream includes SFrameDecrypterManagement;

enum SFrameTransformErrorEventType {
"authentication",
Expand All @@ -284,9 +297,15 @@ dictionary SFrameTransformErrorEventInit : EventInit {
};
</xmp>

The <dfn constructor for="SFrameTransform" lt="SFrameTransform(options)"><code>new SFrameTransform(<var>options</var>)</code></dfn> constructor steps are:
The <dfn constructor for="SFrameSenderTransform" lt="SFrameSenderTransform(options)"><code>new SFrameSenderTransform(<var>options</var>)</code></dfn> constructor steps are:
1. Let |options| be the method's first argument.
1. Run the [=SFrame initialization algorithm=] with |this| and |options|.
1. Set |this|.`[[role]]` to 'encrypt'.

The <dfn constructor for="SFrameReceiverTransform" lt="SFrameReceiverTransform(options)"><code>new SFrameReceiverTransform(<var>options</var>)</code></dfn> constructor steps are:
1. Let |options| be the method's first argument.
1. Run the [=SFrame initialization algorithm=] with |this| and |options|.
1. Set |this|.`[[role]]` to 'decrypt'.

The <dfn constructor for="SFrameEncrypterStream" lt="SFrameEncrypterStream(options)"><code>new SFrameEncrypterStream(<var>options</var>)</code></dfn> constructor steps are:
1. Let |options| be the method's first argument.
Expand Down Expand Up @@ -335,14 +354,38 @@ The <dfn>SFrame transform algorithm</dfn>, given |this| and |frame|, runs these
1. [=ReadableStream/Enqueue=] |frame| in |this|.`[[transform]]`.

## Methods ## {#sframe-transform-methods}
The <dfn method for="SFrameTransform">setEncryptionKey(|key|, |keyID|)</dfn> method steps are:
The <dfn method for="SFrameEncrypterKeyManager">setEncryptionKey(|key|, |keyID|)</dfn> method steps are:
1. Let |promise| be [=a new promise=].
2. If |keyID| is a {{bigint}} which cannot be represented as a integer between 0 and 2<sup>64</sup>-1 inclusive, [=reject=] |promise| with a {{RangeError}} exception.
3. Otherwise, [=in parallel=], run the following steps:
1. Set |key| with its optional |keyID| as key material to use for the SFrame transform algorithm, as defined by [[RFC9605]].
2. If setting the key material fails, [=reject=] |promise| with an {{InvalidModificationError}} exception and abort these steps.
3. [=Resolve=] |promise| with undefined.
4. Return |promise|.
1. If |keyId| is <code>undefined</code>, run the following steps:
1. Let |currentKeyId| be |this|.`[[currentKeyId]]` if not undefined or 0 otherwise.
1. If |currentKeyId| is greater or equal to 2<sup>64</sup>-1, [=reject=] |promise| with a {{RangeError}} exception and abort these steps.
1. Set |keyId| to |currentKeyId| incremented by 1.
1. If |keyID| is a {{bigint}} which cannot be represented as a integer between 0 and 2<sup>64</sup>-1 inclusive, [=reject=] |promise| with a {{RangeError}} exception and abort these steps.
1. Set |this|.`[[currentKeyId]]` to |keyId|.
1. [=In parallel=], run the following steps:
1. Set |key| and |keyID| as key material to use for the SFrame transform encryption algorithm, as defined by [[RFC9605]].
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: "Set as" is a bit confusing to me. It's the reverse of (yet similar looking to) "set a to b" which usually means a = b, not b = a... How about:

Suggested change
1. Set |key| and |keyID| as key material to use for the SFrame transform encryption algorithm, as defined by [[RFC9605]].
1. Set the SFrame transform encryption algorithm's key material to |key| and |keyID|, as defined by [[RFC9605]].

1. If setting the key material fails, [=queue a task=] to [=reject=] |promise| with an {{InvalidModificationError}} exception and abort these steps.
1. [=Queue a task=] to [=resolve=] |promise| with undefined.
1. Return |promise|.

The <dfn method for="SFrameDecrypterKeyManager">addEncryptionKey(|key|, |keyID|)</dfn> method steps are:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The <dfn method for="SFrameDecrypterKeyManager">addEncryptionKey(|key|, |keyID|)</dfn> method steps are:
The <dfn method for="SFrameDecrypterKeyManager">addDecryptionKey(|key|, |keyID|)</dfn> method steps are:

1. Let |promise| be [=a new promise=].
1. If |keyID| is a {{bigint}} which cannot be represented as a integer between 0 and 2<sup>64</sup>-1 inclusive, [=reject=] |promise| with a {{RangeError}} exception, and abort these steps..
1. [=In parallel=], run the following steps:
1. Let |keyStore| be the key store used for the SFrame transform algorithm, as defined by [[RFC9605]].
1. Set an entry to |keyStore| with |keyId| as key and |keyValue| as value. This overrides any existing entry to |keyId|.
Comment on lines +375 to +376
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see "key store" matches language in RFC9605, which is nice.

But I also wonder if we could use infra here. Is it an https://infra.spec.whatwg.org/#ordered-map ?

1. If setting the key material fails, [=queue a task=] to [=reject=] |promise| with an {{InvalidModificationError}} exception and abort these steps.
1. [=Resolve=] |promise| with undefined.
1. Return |promise|.

The <dfn method for="SFrameDecrypterKeyManager">removeEncryptionKey(|key|, |keyID|)</dfn> method steps are:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The <dfn method for="SFrameDecrypterKeyManager">removeEncryptionKey(|key|, |keyID|)</dfn> method steps are:
The <dfn method for="SFrameDecrypterKeyManager">removeDecryptionKey(|key|, |keyID|)</dfn> method steps are:

1. Let |promise| be [=a new promise=].
1. If |keyID| is a {{bigint}} which cannot be represented as a integer between 0 and 2<sup>64</sup>-1 inclusive, [=reject=] |promise| with a {{RangeError}} exception, and abort these steps.
1. [=In parallel=], run the following steps:
1. Let |keyStore| be the key store used for the SFrame transform algorithm, as defined by [[RFC9605]].
1. Remove the entry of |keyStore| at |keyId| if it exits.
1. [=Resolve=] |promise| with undefined.
1. Return |promise|.


# RTCRtpScriptTransform # {#scriptTransform}
Expand Down
Loading