Browse files

[giow] (0) Completely revamp how peer-to-peer networking works (and s…

…ome minor typo fixes in other parts of the spec). This is only a second draft, and therefore this feature will likely evolve a lot over the coming months. Detailed responses to feedback on the topic will be sent out soon.

git-svn-id: http://svn.whatwg.org/webapps@5945 340c8d12-0b0e-0410-8428-c7bf67bfef74
  • Loading branch information...
1 parent 432682d commit 76d736eab54686f44e1ad44457583bc9c5a344a6 @Hixie Hixie committed Mar 14, 2011
Showing with 5,723 additions and 1,763 deletions.
  1. +2,061 −818 complete.html
  2. +1,926 −689 index
  3. +1,736 −256 source
View
2,879 complete.html
2,061 additions, 818 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
2,615 index
1,926 additions, 689 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
1,992 source
@@ -74,7 +74,7 @@
of HTML5) currently consist of:</p>
<ul class="brief">
- <li>The <code>device</code> element.</li> <!--DEVICE-->
+ <li>The <code>PeerConnection</code> API and related video-conferencing features.</li> <!--DEVICE-->
<li>The <code title="attr-hyperlink-ping">ping</code> attribute and related <span>hyperlink auditing</span> features.</li> <!--PING-->
<li>The <span>WebVTT</span> format and some <span>text track</span> API features.</li> <!--TT--> <!--TTVTT-->
<li>Rules for <a href="#atom">converting HTML to Atom</a>.</li> <!--MD-->
@@ -26631,7 +26631,7 @@ href="?audio">audio&lt;/a> test instead.)&lt;/p></pre>
zero or more <code>track</code> elements, then
<!--KEEP-START w3c-html--><!--TT-->
<span>transparent</span>, but with no <span>media element</span> descendants.</dd>
- <dd>If the element does not have a <code title="attr-media-src">src</code> attribute: one or more <code>source</code> elements, then
+ <dd>If the element does not have a <code title="attr-media-src">src</code> attribute: zero or more <code>source</code> elements, then
<!--KEEP-END w3c-html--><!--TT-->
zero or more <code>track</code> elements, then
<!--KEEP-START w3c-html--><!--TT-->
@@ -29593,8 +29593,8 @@ interface <dfn>HTMLAudioElement</dfn> : <span>HTMLMediaElement</span> {};</pre>
<span>queue a task</span> to <span>fire a simple event</span>
named <code title="event-media-playing">playing</code>.</p>
- <p class="note">User agents are not required to autoplay, and it
- is suggested that user agents honor user preferences on the
+ <p class="note">User agents do not need to support autoplay,
+ and it is suggested that user agents honor user preferences on the
matter. Authors are urged to use the <code
title="attr-media-autoplay">autoplay</code> attribute rather than
using script to force the video to play, so as to allow the user
@@ -57097,254 +57097,6 @@ fur
</div>
-<!--END w3c-html--><!--DEVICE-->
-<div data-component="other Hixie drafts (editor: Ian Hickson)">
-<!--START html-device-->
-
- <h4 id="devices">The <dfn><code>device</code></dfn> element</h4>
-
- <dl class="element">
- <dt>Categories</dt>
- <dd><span>Flow content</span>.</dd>
- <dd><span>Phrasing content</span>.</dd>
- <dd><span>Interactive content</span>.</dd>
- <dt>Contexts in which this element can be used:</dt>
- <dd>Where <span>phrasing content</span> is expected.</dd>
- <dt>Content model:</dt>
- <dd>Empty.</dd>
- <dt>Content attributes:</dt>
- <dd><span>Global attributes</span></dd>
- <dd><code title="attr-device-type">type</code></dd>
- <dt>DOM interface:</dt>
- <dd>
-<pre class="idl">interface <dfn>HTMLDeviceElement</dfn> : <span>HTMLElement</span> {
- attribute DOMString <span title="dom-device-type">type</span>;
- readonly attribute any <span title="dom-device-data">data</span>;
-};</pre>
- </dl>
-
- <p>The <code>device</code> element represents a device selector, to
- allow the user to give the page access to a device, for example a
- video camera.</p>
-
- <p>The <dfn title="attr-device-type"><code>type</code></dfn>
- attribute allows the author to specify which kind of device the page
- would like access to. The attribute is an <span>enumerated
- attribute</span> with the keywords given in the first column of the
- following table, and their corresponding states given in the cell in
- second column of the same row.</p>
-
- <p class="XXX">RS232 and USB are only included below to give an idea
- of where we could go with this. <strong>Should we instead just make
- this only useful for audiovisual streams?</strong> Unless there are
- compelling reasons, we probably should not be this generic. So far,
- the reasons for RS232 aren't that compelling. For USB, slightly more
- so.</p>
-
- <table>
- <thead>
- <tr>
- <th>Keyword
- <th>State
- <th>Device description
- <th>Examples
- <tbody>
- <tr>
- <td><dfn title="attr-device-type-keyword-media"><code>media</code></dfn>
- <td><span title="attr-device-type-media">Media</span>
- <td>Stream of audio and/or video data.
- <td>A webcam.
- <tr>
- <td><dfn title="attr-device-type-keyword-fs"><code>fs</code></dfn>
- <td><span title="attr-device-type-fs">File system</span>
- <td>File system.
- <td>A USB-connected media player.
- <tr>
- <td><dfn title="attr-device-type-keyword-rs232"><code>rs232</code></dfn>
- <td><span title="attr-device-type-rs232">RS232</span>
- <td>RS232 device.
- <td>A serial port.
- <tr>
- <td><dfn title="attr-device-type-keyword-usb"><code>usb</code></dfn>
- <td><span title="attr-device-type-usb">USB</span>
- <td>USB device.
- <td>A scanner, a music player, a disk jockey, a fish tank.
- </table>
-
- <p class="XXX">processing model: 'change' event fires once user
- selects a new device; .data is set to new Stream, LocalFS, USB, or
- RS232 object as appropriate.</p>
-
- <div class="example">
-
- <pre>&lt;p>To start chatting, select a video camera: &lt;device type=media onchange="update(this.data)">&lt;/p>
-&lt;video autoplay>&lt;/video>
-&lt;script>
- function update(stream) {
- document.getElementsByTagName('video')[0].src = stream.url;
- }
-&lt;/script></pre>
-
- </div>
-
- <p class="XXX">The <code>device</code> element is intended to be a
- void element, but the parser spec hasn't yet been updated. This
- section of the spec is very much awaiting implementation
- experience.</p>
-
-
- <h5>Stream API</h5>
-
- <p>The <code>Stream</code> interface is used to represent
- streams.</p>
-
- <pre class="idl">interface <dfn>Stream</dfn> {
- readonly attribute DOMString <span title="dom-stream-url">url</span>;
- <span>StreamRecorder</span> <span title="dom-stream-record">record</span>();
-};</pre>
-
- <p>The <dfn title="dom-stream-url"><code>url</code></dfn> attribute
- must return a <span title="fileURN">File URN</span> representing the
- stream. <a href="#refsFILEAPI">[FILEAPI]</a></p>
-
- <p>For audio and video streams, the stream must be in a format
- supported by the user agent for use in <code>audio</code> and
- <code>video</code> elements.</p>
-
- <p class="XXX">This will be pinned down to a specific codec.</p>
-
- <p>When the <dfn
- title="dom-stream-record"><code>record()</code></dfn> method is
- invoked, the user agent must return a new
- <code>StreamRecorder</code> object associated with the stream.</p>
-
- <pre class="idl">interface <dfn>StreamRecorder</dfn> {
- <span>File</span> <span title="dom-StreamRecorder-stop">stop</span>();
-};</pre>
-
- <p>The <dfn
- title="dom-StreamRecorder-stop"><code>stop()</code></dfn> method
- must return a new <code>File</code> object representing the data
- that was streamed between the creation of the
- <code>StreamRecorder</code> object and the invocation of the <code
- title="dom-StreamRecorder-stop">stop()</code> method. <a
- href="#refsFILEAPI">[FILEAPI]</a></p>
-
- <p>For audio and video streams, the file must be in a format
- supported by the user agent for use in <code>audio</code> and
- <code>video</code> elements.</p>
-
- <p class="XXX">This again will be pinned down to a specific codec.</p>
-
-
- <h5>Peer-to-peer connections</h5>
-
- <p class="XXX">This section will be moved to a more appropriate
- location in due course; it is here currently to keep it near the
- <code>device</code> element to allow reviewers to look at it.</p>
-
- <pre class="idl">[Constructor(in DOMString serverConfiguration)]
-interface <dfn>ConnectionPeer</dfn> {
- void sendText(in DOMString text, in optional boolean unimportant); // if second arg is true, then use unreliable low-latency transport (UDP-like), otherwise guarantee delivery (TCP-like)
- attribute <span>Function</span> ontext; // receiving
-
- void sendBitmap(in HTMLImageElement image);
- attribute <span>Function</span> onbitmap; // receiving
-
- void sendFile(in File file);
- attribute <span>Function</span> onfile; // receiving
-
- void addStream(in Stream stream);
- void removeStream(in Stream stream);
- readonly attribute Stream[] localStreams;
- readonly attribute Stream[] remoteStreams;
- attribute <span>Function</span> onstream; // receiving
-
- void <span title="dom-ConnectionPeer-getLocalConfiguration">getLocalConfiguration</span>(in <span>ConnectionPeerConfigurationCallback</span> callback); // maybe this should be in the constructor, or be an event
- void <span title="dom-ConnectionPeer-addRemoteConfiguration">addRemoteConfiguration</span>(in DOMString configuration, in optional DOMString remoteOrigin); // remote origin is assumed to be same-origin if not specified. If specified, has to match remote origin (checked in handshake). Should support leading "*." to mean "any subdomain of".
- void close(); // disconnects and stops listening
-
- attribute <span>Function</span> onconnect;
- attribute <span>Function</span> onerror;
- attribute <span>Function</span> ondisconnect;
-};
-<span>ConnectionPeer</span> implements <span>EventTarget</span>;
-
-[Callback=FunctionOnly, NoInterfaceObject]
-interface <dfn>ConnectionPeerConfigurationCallback</dfn> {
- void <span title="dom-ConnectionPeerConfigurationCallback-handleEvent">handleEvent</span>(in <span>ConnectionPeer</span> server, in DOMString configuration);
-};</pre>
-
- <p class="XXX">...</p>
-
- <div class="XXX">
-
- <p>This relies on some currently hypothetical other standard to
- define:</p>
-
- <ul>
- <li>The format of server configuration strings.
- <li>The format of client configuration strings.
- <li>The protocols that clients use to talk to third-party servers mentioned in the server configuration strings.
- <li>The protocols that clients use to talk to each other.
- </ul>
-
- </div>
-
- <div class="example">
-
- <p>When two peers decide they are going to set up a connection to
- each other, they both go through these steps. The serverConfig
- comes from a third-party server they can use to get things like
- their public IP address or to set up NAT traversal. They also have
- to send their respective configuration to each other using the same
- out-of-band mechanism they used to establish that they were going
- to communicate in the first place.</p>
-
- <pre>var serverConfig = ...; // configuration string obtained from server
-// contains details such as the IP address of a server that can speak some
-// protocol to help the client determine its public IP address, route packets
-// if necessary, etc.
-
-var local = new ConnectionPeer(serverConfig);
-local.getLocalConfiguration(function (configuration) {
- if (configuration != '') {
- ...; // send configuration to other peer using out-of-band mechanism
- } else {
- // we've exhausted our options; wait for connection
- }
-});
-
-function ... (configuration) {
- // called whenever we get configuration information out-of-band
- local.addRemoteConfiguration(configuration);
-}
-
-local.onconnect = function (event) {
- // we are connected!
- local.sendText('Hello');
- local.addStream(...); // send video
- local.onstream = function (event) {
- // receive video
- // (videoElement is some &lt;video> element)
- if (local.remoteStreams.length > 0)
- videoElement.src = local.remoteStreams[0].url;
- };
-};</pre>
-
- </div>
-
- <p class="warning">To prevent network sniffing from allowing a
- fourth party to establish a connection to a peer using the
- information sent out-of-band to the other peer and thus spoofing the
- client, the configuration information should always be transmitted
- using an encrypted connection.</p>
-
-<!--END html-device-->
-</div>
-<!--START w3c-html--><!--DEVICE-->
-
-
<h3 id="links">Links</h3>
@@ -75962,7 +75714,6 @@ interface <dfn>NavigatorStorageUtils</dfn> {
-
<h2 id="editing"><dfn>User interaction</dfn></h2>
@@ -81193,8 +80944,1710 @@ v2 (well, really v0):
"justifycenter", "justifyright", "justifyfull", "indent", "outdent"
-->
+<!--END w3c-html-->
+<div data-component="other Hixie drafts (editor: Ian Hickson)">
+
+ <h2>Video conferencing and peer-to-peer communication</h2>
+
+ <h3>Introduction</h3>
+
+ <!--END dev-html--><p><i>This section is non-normative.</i></p><!--START dev-html-->
+
+ <p>There are a number of facets to video-conferencing in HTML:</p>
+
+ <ul>
+
+ <li>Getting a multimedia stream (video, audio, or both) from local
+ devices (video cameras, microphones, Web cams) or from prerecorded
+ files provided by the user.</li>
+
+ <li>Recording such streams locally.</li>
+
+ <li>Connecting to remote peers using NAT-traversal technologies
+ such as ICE, STUN, and TURN.</li>
+
+ <li>Sending the locally-produced streams to remote peers and
+ receiving streams from remote peers.</li>
+
+ <li>Displaying such streams (both the locally-produced ones and the
+ remotely-obtained ones) locally using the <code>video</code> or
+ <code>audio</code> elements.</li>
+
+ <li>Sending arbitrary data to remote peers.</li>
+
+ </ul>
+
+ <p>This section defines the APIs used for these features.</p>
+
+
+ <h4>Obtaining local multimedia content</h4>
+
+ <pre class="idl">[Supplemental, NoInterfaceObject]
+interface <dfn>NavigatorUserMedia</dfn> {
+ void <span title="dom-navigator-getUserMedia">getUserMedia</span>(in DOMString options, in <span>NavigatorUserMediaSuccessCallback</span> successCallback, in optional <span>NavigatorUserMediaErrorCallback</span> errorCallback);
+};
+<span>Navigator</span> implements <span>NavigatorUserMedia</span>;
+
+[Callback=FunctionOnly, NoInterfaceObject]
+interface <dfn>NavigatorUserMediaSuccessCallback</dfn> {
+ void <span title="dom-NavigatorUserMediaSuccessCallback-handleEvent">handleEvent</span>(in <span>GeneratedStream</span> stream);
+};
+
+[NoInterfaceObject]<!-- this is based on PositionError in geolocation -->
+interface <dfn>NavigatorUserMediaError</dfn> {
+ const unsigned short <span title="dom-NavigatorUserMediaError-PERMISSION_DENIED">PERMISSION_DENIED</span> = 1;<!--
+ const unsigned short <span title="dom-NavigatorUserMediaError-UNAVAILABLE">UNAVAILABLE</span> = 2;
+ const unsigned short <span title="dom-NavigatorUserMediaError-TIMEOUT">TIMEOUT</span> = 3;-->
+ readonly attribute unsigned short <span title="dom-NavigatorUserMediaError-code">code</span>;<!--
+ readonly attribute DOMString <span title="dom-NavigatorUserMediaError-message">message</span>;-->
+};
+
+[Callback=FunctionOnly, NoInterfaceObject]
+interface <dfn>NavigatorUserMediaErrorCallback</dfn> {
+ void <span title="dom-NavigatorUserMediaSuccessCallback-handleEvent">handleEvent</span>(in <span>NavigatorUserMediaError</span> error);
+};</pre>
+
+ <dl class="domintro">
+
+ <dt><var title="">window</var> . <code title="dom-navigator">navigator</code> . <code title="dom-navigator-getUserMedia">getUserMedia</code>(<var title="">options</var>, <var title="">successCallback</var> [, <var title="">errorCallback</var> ] )</dt>
+
+ <dd>
+
+ <p>Prompts the user for permission to use their Web cam or other
+ video or audio input.</p>
+
+ <p>The <var title="">options</var> argument is a string of
+ comma-separated values from the following list:</p>
+
+ <dl>
+
+
+ <dt>"<code title="">audio</code>"</dt>
+
+ <dd>The provided media needs to include audio data.</dd>
+
+
+ <dt>"<code title="">video</code>"</dt>
+
+ <dd>The provided media needs to include video data.</dd>
+
+
+ </dl>
+
+ <p>If the user accepts, the <var title="">successCallback</var> is
+ invoked, with a suitable <code>GeneratedStream</code> object as
+ its argument.</p>
+
+ <p>If the user declines, the <var title="">errorCallback</var> (if
+ any) is invoked.</p>
+
+ </dd>
+
+
+ <dt><var title="">error</var> . <code title="dom-NavigatorUserMediaError-code">code</code></dt>
+
+ <dd>
+
+ <p>Returns the current error's error code. At this time, this will
+ always be 1, for which the constant <code
+ title="dom-NavigatorUserMediaError-PERMISSION_DENIED">PERMISSION_DENIED</code>
+ is defined.</p>
+
+ </dd>
+
+ </dl>
+
+ <div class="impl">
+
+ <p>When the <dfn
+ title="dom-navigator-getUserMedia"><code>getUserMedia()</code></dfn>
+ method is called, the user agent must run the following steps:</p>
+
+ <ol>
+
+ <li><p>Let <var title="">options</var> be the method's first
+ argument.</p></li>
+
+ <li><p>Let <var title="">successCallback</var> be the callback
+ indicated by the method's second argument.</p></li>
+
+ <li><p>Let <var title="">errorCallback</var> be the callback
+ indicated by the method's third argument, if any, or null
+ otherwise.</p></li>
+
+ <li><p>If <var title="">successCallback</var> is null, abort these
+ steps.</p></li> <!-- we could throw an exception instead (that's
+ why the method doesn't return until later: so that we can add an
+ exception here, or for /options/ below, without changing the
+ algorithm) -->
+
+ <li><p><span title="split a string on spaces">Split <var
+ title="">options</var> on spaces</span> to obtain <var
+ title="">list of options</var>.</p></li>
+
+ <li><p>If one of the tokens in <var title="">list of options</var>
+ is a <span>case-sensitive</span> match for the string "<code
+ title="">audio</code>", let <var title="">audio</var> be true.
+ Otherwise, let it be false.</p></li>
+
+ <li><p>If one of the tokens in <var title="">list of options</var>
+ is a <span>case-sensitive</span> match for the string "<code
+ title="">video</code>", let <var title="">video</var> be true.
+ Otherwise, let it be false.</p></li>
+
+ <!-- any error handling for /options/ should be done here (that's
+ why the method doesn't return until the next step: so we can add
+ exception throwing here) -->
+
+ <li><p>Return, and run the remaining steps asynchronously.</p></li>
+
+ <li><p>Optionally, e.g. based on a previously-established user
+ preference, for security reasons, or due to platform limitations,
+ jump to the step labeled <i>failure</i> below.</p></li>
+
+ <li>
+
+ <p>Prompt the user in a user-agent-specific manner for permission
+ to provide the <span>entry script</span>'s <span>origin</span>
+ with a <code>GeneratedStream</code> object representing a media
+ stream.</p>
+
+ <p>If <var title="">audio</var> is true, then the provided media
+ should include an audio component. If <var title="">audio</var>
+ is false, then the provided media must not include an audio
+ component.</p>
+
+ <p>If <var title="">video</var> is true, then the provided media
+ should include a video component. If <var title="">video</var> is
+ false, then the provided media must not include a video
+ component.</p>
+
+ <p>User agents are encouraged to default to using the user's
+ primary or system default camera and/or microphone (as
+ appropriate) to generate the media stream. User agents may allow
+ users to use any media source, including pre-recorded media
+ files.</p>
+
+ <p>If the user grants permission to use local recording devices,
+ user agents are encouraged to include a prominent indicator that
+ the devices are "hot" (i.e. an "on-air" or "recording"
+ indicator).</p>
+
+ <p>If the user denies permission, jump to the step labeled
+ <i>failure</i> below. If the user never responds, this algorithm
+ stalls on this step.</p>
+
+ </li>
+
+ <li><p>Let <var title="">stream</var> be the
+ <code>GeneratedStream</code> object for which the user granted
+ permission.</p></li>
+
+ <li><p><span>Queue a task</span> to invoke <var
+ title="">successCallback</var> with <var title="">stream</var> as
+ its argument.</p></li>
+
+ <li><p>Abort these steps.</p></li>
+
+ <li><p><i>Failure</i>: If <var title="">errorCallback</var> is
+ null, abort these steps.</p></li>
+
+ <li><p>Let <var title="">error</var> be a new
+ <code>NavigatorUserMediaError</code> object whose <code
+ title="dom-NavigatorUserMediaError-code">code</code> attribute has
+ the numeric value 1 (<code
+ title="dom-NavigatorUserMediaError-PERMISSION_DENIED">PERMISSION_DENIED</code>).</p></li>
+
+ <li><p><span>Queue a task</span> to invoke <var
+ title="">errorCallback</var> with <var title="">error</var> as its
+ argument.</p></li>
+
+ </ol>
+
+ <p>The <span>task source</span> for these <span
+ title="concept-task">tasks</span> is the <span>user interaction task
+ source</span>.</p>
+
+ <hr>
+
+ <p>The <dfn title="dom-NavigatorUserMediaError-code"><code>code</code></dfn>
+ attribute of a <code>NavigatorUserMediaError</code> object must return the code
+ for the error, which must be <!--one of--> the following:</p>
+
+ <dl>
+
+ <dt><dfn title="dom-NavigatorUserMediaError-PERMISSION_DENIED"><code>PERMISSION_DENIED</code></dfn> (numeric value 1)</dt>
+
+ <dd>The user denied the page permission to use the user's media devices.</dd>
+
+ </dl>
+
+ </div>
+
+ <div class="example">
+
+ <p>A voice chat feature in a game could attempt to get access to
+ the user's microphone by calling the API as follows:</p>
+
+ <pre>&lt;script>
+ navigator.getUserMedia('audio', gotAudio);
+ function gotAudio(stream) {
+ // ... use 'stream' ...
+ }
+&lt;/script></pre>
+
+ </div>
+
+ <div class="example">
+
+ <p>A video-conferencing system would ask for both audio and video:</p>
+
+ <pre>&lt;script>
+ function beginCall() {
+ navigator.getUserMedia('audio,video', gotStream);
+ }
+ function gotStream(stream) {
+ // ... use 'stream' ...
+ }
+&lt;/script></pre>
+
+ </div>
+
+
+
+ <h4>Stream API</h4>
+
+ <p>The <code>Stream</code> interface is used to represent streams,
+ typically (but not necessarily) of audio and/or video content, e.g.
+ from a local camera or a remote site.</p>
+
+ <p>The <code>GeneratedStream</code> interface is used when the user
+ agent is generating the stream's data (e.g. from a camera or
+ streaming it from a local video file). It allows authors to pause
+ the generation of the content, e.g. to allow the user to temporarily
+ disable a local camera during a video-conference chat.</p>
+
+ <p>When a <code>GeneratedStream</code> object is being generated
+ from a local file (as opposed to a live audio/video source), the
+ user agent should stream the data from the file in real time, not
+ all at once. This reduces the ease with which pages can distinguish
+ live video from pre-recorded video, which can help protect the
+ user's privacy.</p>
+
+ <!-- v2: support reading the bits from the stream directly, for use
+ with streaming over WebSocket? Or do we rely on FileReader for that? -->
+
+ <pre class="idl">interface <dfn>Stream</dfn> {
+ readonly attribute DOMString <span title="dom-stream-label">label</span>;
+ <span>StreamRecorder</span> <span title="dom-stream-record">record</span>();
+<!--
+ const unsigned short <span title="dom-stream-LOADING">LOADING</span> = 0; -->
+ const unsigned short <span title="dom-stream-LIVE">LIVE</span> = 1;
+ const unsigned short <span title="dom-stream-ENDED">ENDED</span> = 2;
+ readonly attribute unsigned short <span title="dom-stream-readyState">readyState</span>;
+ attribute <span>Function</span> <span title="handler-stream-onreadystatechange">onreadystatechange</span>;
+ attribute <span>Function</span> <span title="handler-stream-onended">onended</span>;
+};
+<span>Stream</span> implements <span>EventTarget</span>;
+
+interface <dfn>GeneratedStream</dfn> {
+ void <span title="dom-stream-stop">stop</span>();
+
+ // temporarily pausing the stream
+ const unsigned short <span title="dom-stream-PAUSED">PAUSED</span> = 3;
+ void <span title="dom-stream-pause">pause</span>();
+ void <span title="dom-stream-resume">resume</span>();
+ attribute <span>Function</span> <span title="handler-stream-onpause">onpause</span>;
+ attribute <span>Function</span> <span title="handler-stream-onplay">onplay</span>;
+};</pre>
+
+ <dl class="domintro">
+
+ <dt><var title="">stream</var> . <code title="dom-stream-label">label</code></dt>
+
+ <dd>
+
+ <p>Returns a label that is unique to this stream, so that streams
+ can be recognised after they are sent through the
+ <code>PeerConnection</code> API.</p>
+
+ </dd>
+
+
+ <dt><var title="">recorder</var> = <var title="">stream</var> . <code title="dom-stream-record">record</code>()</dt>
+
+ <dd>
+
+ <p>Begins recording the stream. The returned
+ <code>StreamRecorder</code> object provides access to the recorded
+ data.</p>
+
+ </dd>
+
+
+ <dt><var title="">stream</var> . <code title="dom-stream-stop">stop</code>()</dt>
+
+ <dd>
+
+ <p>Permanently stops the generation of media data for the stream.</p>
+
+ </dd>
+
+
+ <dt><var title="">stream</var> . <code title="dom-stream-paused">paused</code></dt>
+
+ <dd>
+
+ <p>Returns false if the stream is generating data; true if it is pause.</p>
+
+ </dd>
+
+
+ <dt><var title="">stream</var> . <code title="dom-stream-pause">pause</code>()</dt>
+
+ <dd>
+
+ <p>Temporarily stops the generation of media data for the stream.</p>
+
+ </dd>
+
+
+ <dt><var title="">stream</var> . <code title="dom-stream-resume">resume</code>()</dt>
+
+ <dd>
+
+ <p>Resumes the generation of media data for the stream if it was temporarily stopped.</p>
+
+ </dd>
+
+ </dl>
+
+ <div class="impl">
+
+ <p>The <dfn
+ title="dom-stream-readyState"><code>readyState</code></dfn>
+ attribute represents the state of the stream. It must return the
+ value to which the user agent last set it (as defined below). It can
+ have the following values:</p>
+
+ <dl>
+
+ <dt><dfn title="dom-stream-LIVE"><code>LIVE</code></dfn> (numeric value 1)</dt>
+
+ <dd>The stream is active (the user agent is making a best-effort
+ attempt to receive or generate data in real time).</dd>
+
+ <dt><dfn title="dom-stream-ENDED"><code>ENDED</code></dfn> (numeric value 2)</dt>
+
+ <dd>The stream has finished (the user agent is no longer receiving
+ or generating data, and will never receive or generate more data
+ for this stream).</dd>
+
+ <dt><dfn title="dom-stream-PAUSED"><code>PAUSED</code></dfn> (numeric value 3)</dt>
+
+ <dd>The stream is not generating data at this time, but could still
+ be resumed. Only <code>GeneratedStream</code> objects can be in
+ this state.</dd>
+
+ </dl>
+
+ <p>When a <code>Stream</code> object is created, its <code
+ title="dom-stream-readyState">readyState</code> attribute must be
+ set to <code title="dom-stream-LIVE">LIVE</code> (1).</p>
+
+ <p>When a <code>Stream</code> object ends for any reason other than
+ the <code title="dom-stream-stop">stop()</code> method being invoke
+ (e.g. because the user rescinds the permission for the page to use
+ the local camera, or because the data comes from a finite file and
+ the file's end has been reached and the user has not requested that
+ it be looped, or because the stream comes from a remote peer and the
+ remote peer has permanently stopped sending data), the user agent
+ must <span>queue a task</span> that runs the following steps:</p>
+
+ <ol>
+
+ <li><p>If the object's <code
+ title="dom-stream-readyState">readyState</code> attribute has the
+ value <code title="dom-stream-ENDED">ENDED</code> (2) already, then
+ abort these steps. (The <code title="dom-stream-stop">stop()</code>
+ method was probably called just before the stream stopped for other
+ reasons, e.g. the user clicked an in-page stop button and then the
+ user-agent-provided stop button.)</p></li>
+
+ <li><p>Set the object's <code
+ title="dom-stream-readyState">readyState</code> attribute to <code
+ title="dom-stream-ENDED">ENDED</code> (2).</p></li>
+
+ <li><p><span>Fire a simple event</span> named <code
+ title="event-readystatechange">readystatechange</code> at the
+ object.</p></li>
+
+ <li><p><span>Fire a simple event</span> named <code
+ title="event-stream-ended">ended</code> at the object.</p></li>
+
+ </ol>
+
+ <p>If the end of the stream was reached due to a user request, the
+ <span>task source</span> for this <span
+ title="concept-task">task</span> is the <span>user interaction task
+ source</span>. Otherwise the <span>task source</span> for this <span
+ title="concept-task">task</span> is the <span>networking task
+ source</span>.</p>
+
+ <hr>
+
+ <p>When a <code>GeneratedStream</code> object is created, the user
+ agent must generate a globally unique identifier string, and must
+ initialize the object's <code title="dom-stream-label">label</code>
+ attribute to that string. Such strings must only use characters in
+ the ranges U+0021, U+0023 to U+0027, U+002A to U+002B, U+002D to
+ U+002E, U+0030 to U+0039, U+0041 to U+005A, U+005E to U+007E, and
+ must be 36 characters long.</p> <!-- UUIDs have 36 characters
+ including hyphens; the ranges above comes from RFC4574 (the a=label:
+ thing in SDP) -->
+
+ <p>When a <code>Stream</code> is created to represent a stream
+ obtained from a remote peer, the <code
+ title="dom-stream-label">label</code> attribute is initialized from
+ information provided by the remote source.</p> <!-- described below
+ -->
+
+ <p>The <dfn title="dom-stream-label"><code>label</code></dfn>
+ attribute must return the value to which it was initialized when the
+ object was created.</p>
+
+ <hr>
+
+ <p>When the <dfn
+ title="dom-stream-record"><code>record()</code></dfn> method is
+ invoked, the user agent must return a new
+ <code>StreamRecorder</code> object associated with the stream.</p>
+
+ <hr>
+
+ <p>When a <code>GeneratedStream</code> object's <dfn
+ title="dom-stream-stop"><code>stop()</code></dfn> method is invoked,
+ the user agent must <span>queue a task</span> that runs the
+ following steps:</p>
+
+ <ol>
+
+ <li><p>If the object's <code
+ title="dom-stream-readyState">readyState</code> attribute is in the
+ <code title="dom-stream-ENDED">ENDED</code> (2) state, then abort
+ these steps.</p></li>
+
+ <li><p>Permanently stop the generation of data for the stream. If
+ the data is being generated from a live source (e.g. a microphone
+ or camera), and no other stream is being generated from a live
+ source, then the user agent should remove any active "on-air"
+ indicator. If the data is being generated from a prerecorded source
+ (e.g. a video file), any remaining content in the file is
+ ignored.</p></li>
+
+ <li><p>Set the object's <code
+ title="dom-stream-readyState">readyState</code> attribute to <code
+ title="dom-stream-ENDED">ENDED</code> (2).</p></li>
+
+ <li><p><span>Fire a simple event</span> named <code
+ title="event-readystatechange">readystatechange</code> at the
+ object.</p></li>
+
+ <li><p><span>Fire a simple event</span> named <code
+ title="event-stream-ended">ended</code> at the object.</p></li>
+
+ </ol>
+
+ <hr>
+
+ <p>When a <code>GeneratedStream</code> object's <dfn
+ title="dom-stream-pause"><code>pause()</code></dfn> method is
+ invoked, the user agent must <span>queue a task</span> that runs the
+ following steps:</p>
+
+ <ol>
+
+ <li><p>If the object's <code
+ title="dom-stream-readyState">readyState</code> attribute is not in
+ the <code title="dom-stream-LIVE">LIVE</code> (1) state, then abort
+ these steps.</p></li>
+
+ <li><p>Pause the generation of data for the stream. If the data is
+ being generated from a live source (e.g. a microphone or camera),
+ then data collected for this stream while the stream is paused must
+ be discarded. If the data is being generated from a prerecorded
+ source (e.g. a video file), the user agent should follow user
+ preferences for handling a pause (either skipping over data in real
+ time or resuming from the same point when the stream is later
+ resumed).</p></li>
+
+ <li><p>Set the object's <code
+ title="dom-stream-readyState">readyState</code> attribute to <code
+ title="dom-stream-PAUSED">PAUSED</code> (3).</p></li>
+
+ <li><p><span>Fire a simple event</span> named <code
+ title="event-readystatechange">readystatechange</code> at the
+ object.</p></li>
+
+ <li><p><span>Fire a simple event</span> named <code
+ title="event-stream-pause">pause</code> at the object.</p></li>
+
+ </ol>
+
+ <p>When a <code>GeneratedStream</code> object's <dfn
+ title="dom-stream-resume"><code>resume()</code></dfn> method is
+ invoked, the user agent must <span>queue a task</span> that runs the
+ following steps:</p>
+
+ <ol>
+
+ <li><p>If the object's <code
+ title="dom-stream-readyState">readyState</code> attribute is not in
+ the <code title="dom-stream-PAUSED">PAUSED</code> (3) state, then
+ abort these steps.</p></li>
+
+ <li><p>Resume the generation of data for the stream.</p></li>
+
+ <li><p>Set the object's <code
+ title="dom-stream-readyState">readyState</code> attribute to <code
+ title="dom-stream-LIVE">LIVE</code> (1).</p></li>
+
+ <li><p><span>Fire a simple event</span> named <code
+ title="event-readystatechange">readystatechange</code> at the
+ object.</p></li>
+
+ <li><p><span>Fire a simple event</span> named <code
+ title="event-stream-play">play</code> at the object.</p></li>
+
+ </ol>
+
+ <hr>
+
+ <p>The <span>task source</span> for the <span
+ title="concept-task">tasks</span> queued for the <code
+ title="dom-stream-stop">stop()</code>, <code
+ title="dom-stream-pause">pause()</code>, and <code
+ title="dom-stream-resume">resume()</code> methods is the <span>DOM
+ manipulation task source</span>.</p>
+
+ <hr>
+
+ <p>The following are the <span>event handlers</span> (and their
+ corresponding <span title="event handler event type">event handler
+ event types</span>) that must be supported, as IDL attributes, by
+ all objects implementing the <code>Stream</code> interface:</p>
+
+ <table>
+ <thead>
+ <tr><th><span title="event handlers">Event handler</span> <th><span>Event handler event type</span>
+ <tbody>
+ <tr><td><dfn title="handler-stream-onreadystatechange"><code>onreadystatechange</code></dfn> <td> <code title="event-stream-readystatechange">readystatechange</code>
+ <tr><td><dfn title="handler-stream-onended"><code>onended</code></dfn> <td> <code title="event-stream-ended">ended</code>
+ </table>
+
+ <p>The following are the additional <span>event handlers</span> (and
+ their corresponding <span title="event handler event type">event
+ handler event types</span>) that must be supported, as IDL
+ attributes, by all objects implementing the
+ <code>GeneratedStream</code> interface:</p>
+
+ <table>
+ <thead>
+ <tr><th><span title="event handlers">Event handler</span> <th><span>Event handler event type</span>
+ <tbody>
+ <tr><td><dfn title="handler-stream-onpause"><code>onpause</code></dfn> <td> <code title="event-stream-pause">pause</code>
+ <tr><td><dfn title="handler-stream-onplay"><code>onplay</code></dfn> <td> <code title="event-stream-play">play</code>
+ </table>
+
+ </div>
+
+ <div class="example">
+
+ <p>This sample code exposes a button. When clicked, the button is
+ disabled and the user is prompted to offer a stream. The user can
+ cause the button to be re-enabled by providing a stream (e.g.
+ giving the page access to the local camera) and then disabling the
+ stream (e.g. revoking that access).</p>
+
+ <pre>
+&lt;input type="button" value="Start" onclick="start()" id="startBtn">
+&lt;script>
+ var startBtn = document.getElementById('startBtn');
+ function start() {
+ navigator.getUserMedia('audio,video', gotStream);
+ startBtn.disabled = true;
+ }
+ function gotStream(stream) {
+ stream.onended = function () {
+ startBtn.disabled = false;
+ }
+ }
+&lt;/script></pre>
+
+ </div>
+
+ <pre class="idl">interface <dfn>StreamRecorder</dfn> {
+ <span>Blob</span> <span title="dom-StreamRecorder-getRecordedData">getRecordedData</span>(in <span>BlobCallback</span> callback);
+};
+
+[Callback=FunctionOnly, NoInterfaceObject]
+interface <dfn>BlobCallback</dfn> {
+ void <span title="dom-BlobCallback-handleEvent">handleEvent</span>(in <span>Blob</span> blob);
+};</pre>
+
+ <dl class="domintro">
+
+ <dt><var title="">recorder</var> . <code title="dom-StreamRecorder-getRecordedData">getRecordedData</code>(<var title="">callback</var>)</dt>
+
+ <dd>
+
+ <p>Creates a <code>Blob</code> of the recorded data, and invokes
+ the provided callback with that <code>Blob</code>.</p>
+
+ </dd>
+
+ </dl>
+
+ <div class="impl">
+
+ <p>When the <dfn
+ title="dom-StreamRecorder-getRecordedData"><code>getRecordedData()</code></dfn>
+ method is called, the user agent must run the following steps:</p>
+
+ <ol>
+
+ <li><p>Let <var title="">callback</var> be the callback
+ indicated by the method's first argument.</p></li>
+
+ <li><p>If <var title="">callback</var> is null, abort these
+ steps.</p></li> <!-- we could throw an exception instead (that's
+ why the method doesn't return until later: so that we can add an
+ exception here without changing the algorithm) -->
+
+ <li><p>Let <var title="">data</var> be the data that was streamed
+ by the <code>Stream</code> object from which the
+ <code>StreamRecorder</code> was created since the creation of the
+ <code>StreamRecorder</code> object.</li>
+
+ <li><p>Return, and run the remaining steps asynchronously.</p></li>
+
+ <li><p>Generate a file that containing <var title="">data</var> in
+ a format supported by the user agent for use in <code>audio</code>
+ and <code>video</code> elements.</p></li>
+
+ <li><p>Let <var title="">blob</var> be a <code>Blob</code> object
+ representing the contents of the file generated in the previous
+ step. <a href="#refsFILEAPI">[FILEAPI]</a></p>
+
+ <li><p><span>Queue a task</span> to invoke <var
+ title="">callback</var> with <var title="">blob</var> as its
+ argument.</p></li>
+
+ </ol>
+
+ <p class="note">The <code
+ title="dom-StreamRecorder-getRecordedData">getRecordedData()</code>
+ method can be called multiple times on one
+ <code>StreamRecorder</code> object; each time, it will create a new
+ file as if this was the first time the method was being called. In
+ particular, the method does not stop or reset the recording when the
+ method is called.</p>
+
+ </div>
+
+ <div class="example">
+
+ <p>This example allows people to record a short audio message and
+ upload it to the server. This example even shows rudimentary error
+ handling.</p>
+
+ <pre>&lt;input type="button" value="&#x26AB;" onclick="msgRecord()" id="recBtn">
+&lt;input type="button" value="&#x25FC;" onclick="msgStop()" id="stopBtn" disabled>
+&lt;p id="status">To start recording, press the &#x26AB; button.&lt;/p>
+&lt;script>
+ var recBtn = document.getElementById('recBtn');
+ var stopBtn = document.getElementById('stopBtn');
+ function report(s) {
+ document.getElementById('status').textContent = s;
+ }
+ function msgRecord() {
+ report('Attempting to access microphone...');
+ navigator.getUserMedia('audio', gotStream, noStream);
+ recBtn.disabled = true;
+ }
+ var msgStream;
+ function gotStream(stream) {
+ report('Recording... To stop, press to &#x25FC; button.');
+ msgStream = stream;
+ stopBtn.disabled = false;
+ stream.onended = function () {
+ msgStop();
+ }
+ }
+ function msgStop() {
+ report('Creating file...');
+ stopBtn.disabled = true;
+ stream.onended = null;
+ stream.stop();
+ stream.getRecordedData(msgSave);
+ }
+ function msgSave(blob) {
+ report('Uploading file...');
+ var x = new XMLHttpRequest();
+ x.open('POST', 'uploadMessage');
+ x.send(blob);
+ x.onload = function () {
+ report('Done! To record a new message, press the &#x26AB; button.');
+ recBtn.disabled = false;
+ };
+ x.onerror = function () {
+ report('Failed to upload message. To try recording a message again, press the &#x26AB; button.');
+ recBtn.disabled = false;
+ };
+ }
+ funciton noStream() {
+ report('Could not obtain access to your microphone. To try again, press the &#x26AB; button.');
+ recBtn.disabled = false;
+ }
+&lt;/script></pre>
+
+ </div>
+
+ <pre class="idl">[Supplemental]
+interface <dfn title="dom-URL">URL</dfn> {
+ static DOMString <span title="dom-URL-createObjectURL">createObjectURL</span>(in <span>Stream</span> stream);
+};</pre>
+
+ <dl class="domintro">
+
+ <dt><var title="">window</var> . <code title="dom-URL">URL</code> . <code title="dom-URL-createObjectURL">createObjectURL</code>(<var title="">stream</var>)</dt>
+
+ <dd>
+
+ <p>Mints a <span>Blob URL</span> to refer to the given <code>Stream</code>.</p>
+
+ </dd>
+
+ </dl>
+
+ <div class="impl">
+
+ <p>When the <dfn
+ title="dom-URL-createObjectURL"><code>createObjectURL()</code></dfn>
+ method is called with a <code>Stream</code> argument, the user agent
+ must return a unique <span>Blob URL</span> for the given
+ <code>Stream</code>. <a href="#refsFILEAPI">[FILEAPI]</a></p>
+
+ <p>For audio and video streams, the data exposed on that stream must
+ be in a format supported by the user agent for use in
+ <code>audio</code> and <code>video</code> elements.</p>
+
+ <p class="bookkeeping">A <dfn>Blob URL</dfn> is the same as what the
+ File API specification calls a <span>Blob URI</span>, except that
+ anything in the definition of that feature that refers to
+ <code>File</code> and <code>Blob</code> objects is hereby extended
+ to also apply to <code>Stream</code> and
+ <code>GeneratedStream</code> objects.</p>
+
+ </div>
+
+ <div class="example">
+
+ <p>This example allows people to take photos of themselves from the
+ local video camera.</p>
+
+ <pre>&lt;article>
+ &lt;style scoped>
+ video { transform: scaleX(-1); }
+ p { text-align: center; }
+ &lt;/style>
+ &lt;h1>Snapshot Kiosk&lt;/h1>
+ &lt;section id="splash">
+ &lt;p id="errorMessage">Loading...&lt;/p>
+ &lt;/section>
+ &lt;section id="app" hidden>
+ &lt;p>&lt;video id="monitor">&lt;/video> &lt;canvas id="photo">&lt;/canvas>
+ &lt;p>&lt;input type=button value="&amp;#x1F4F7;" onclick="snapshot()">
+ &lt;/section>
+ &lt;script>
+ navigator.getUserMedia('video', gotStream, noStream);
+ var video = document.getElementById('monitor');
+ var canvas = document.getElementById('photo');
+ function gotStream(stream) {
+ video.src = URL.getObjectURL(stream);
+ video.onerror = function () {
+ stream.stop();
+ noStream();
+ }
+ video.onloadedmetadata = function () {
+ canvas.width = video.videoWidth;
+ canvas.height = video.videoHeight;
+ document.getElementById('splash').hidden = true;
+ document.getElementById('app').hidden = false;
+ }
+ }
+ function noStream() {
+ document.getElementById('errorMessage').textContent = 'No camera available.';
+ }
+ function snapshot() {
+ canvas.getContext('2d').drawImage(video, 0, 0);
+ }
+ &lt;/script>
+&lt;/article></pre>
+
+ </div>
+
+
+
+ <h4>Peer-to-peer connections</h4>
+
+ <pre class="idl">[<span title="dom-PeerConnection">Constructor</span>(in DOMString configuration, in <span>SignalingCallback</span> signalingCallback)]
+interface <dfn>PeerConnection</dfn> {
+ void <span title="dom-PeerConnection-signalingMessage">signalingMessage</span>(in DOMString message);
+
+ // <span class="XXX">readyState, etc</span>
+
+ void <span title="dom-PeerConnection-send">send</span>(in DOMString text);
+ void <span title="dom-PeerConnection-addStream">addStream</span>(in <span>Stream</span> stream);
+ void <span title="dom-PeerConnection-removeStream">removeStream</span>(in <span>Stream</span> stream);
+ readonly attribute <span>Stream</span>[] <span title="dom-PeerConnection-localStreams">localStreams</span>;
+ readonly attribute <span>Stream</span>[] <span title="dom-PeerConnection-remoteStreams">remoteStreams</span>;
+
+ // <span class="XXX">connection quality information</span>
+
+ attribute <span>Function</span> <span title="handler-PeerConnection-ontext">ontext</span>;
+ attribute <span>Function</span> <span title="handler-PeerConnection-onaddstream">onaddstream</span>;
+ attribute <span>Function</span> <span title="handler-PeerConnection-onremovestream">onremovestream</span>;
+};
+<span>PeerConnection</span> implements <span>EventTarget</span>;
+
+[Callback=FunctionOnly, NoInterfaceObject]
+interface <dfn>SignalingCallback</dfn> {
+ void <span title="dom-SignalingCallback-handleEvent">handleEvent</span>(in <span>PeerConnection</span> source, in DOMString message);
+};</pre>
+
+ <p>A <code>PeerConnection</code> allows two users to communicate
+ directly, browser-to-browser. Communications are coordinated via a
+ signaling channel provided by script in the page via the server,
+ e.g. using <code>XMLHttpRequest</code>.</p>
+
+ <dl class="domintro">
+
+ <dt><var title="">connection</var> = new <code title="dom-PeerConnection">PeerConnection</code>(<var title="">configuration</var>, <var title="">signalingCallback</var>)</dt>
+
+ <dd>
+
+ <p>Creates a <code>PeerConnection</code> object.</p>
+
+ <p>The <var title="">configuration</var> string gives the address
+ of a STUN or TURN server to use to establish the connection. <a
+ href="#refsSTUN">[STUN]</a> <a href="#refsTURN">[TURN]</a></p>
+
+ <p>The allowed formats for this string are:</p>
+
+ <dl>
+
+ <dt>"<code title=""><var title="">TYPE</var> 203.0.113.2:3478</code>"
+ <dd>
+ <p>Indicates a specific IP address and port for the server.</p>
+ </dd>
+
+ <dt>"<code title=""><var title="">TYPE</var> relay.example.net:3478</code>"
+ <dd>
+ <p>Indicates a specific host and port for the server; the user agent will look up the IP address in DNS.</p>
+ </dd>
+
+ <dt>"<code title=""><var title="">TYPE</var> example.net</code>"
+ <dd>
+ <p>Indicates a specific domain for the server; the user agent will look up the IP address and port in DNS.</p>
+ </dd>
+
+ </dl>
+
+ <p>The "<code title=""><var title="">TYPE</var></code>" is one of:</p>
+
+ <dl>
+
+ <dt><code title="">STUN</code></dt>
+ <dd>Indicates a STUN server
+
+ <dt><code title="">STUNS</code></dt>
+ <dd>Indicates a STUN server that is to be contacted using a TLS session.
+
+ <dt><code title="">TURN</code></dt>
+ <dd>Indicates a TURN server
+
+ <dt><code title="">TURNS</code></dt>
+ <dd>Indicates a TURN server that is to be contacted using a TLS session.
+
+ </dl>
+
+ <p>The <var title="">signalingCallback</var> argument is a method
+ that will be invoked when the user agent needs to send a message
+ to the other host over the signaling channel. When the callback
+ is invoked, convey its argument (a string) to the other peer using
+ whatever method is being used by the Web application to relay
+ signaling messages. (Messages returned from the other peer are
+ provided back to the user agent using the <code
+ title="dom-PeerConnection-signalingMessage">signalingMessage()</code>
+ method.)</p>
+
+ </dd>
+
+
+ <dt><var title="">connection</var> . <code title="dom-PeerConnection-signalingMessage">signalingMessage</code>(<var title="">message</var>)</dt>
+
+ <dd>
+
+ <p>When a message is relayed from the remote peer over the
+ signaling channel is received by the Web application, pass it to
+ the user agent by calling the <code
+ title="dom-PeerConnection-signalingMessage">signalingMessage()</code>
+ method.</p>
+
+ <p>The order of messages is important. Passing messages to the
+ user agent in a different order than they were generated by the
+ remote peer's user agent can prevent a successful connection from
+ being established or degrade the connection's quality if one is
+ established.</p>
+
+ </dd>
+
+ <dt><var title="">connection</var> . <code title="dom-PeerConnection-send">send</code>(<var title="">text</var>)</dt>
+
+ <dd>
+
+ <p>Attempts to send the given text to the remote peer. This uses
+ UDP, which is inherently unreliable; there is no guarantee that
+ every message will be received.</p>
+
+ <p>When a message sent in this manner from the other peer is
+ received, a <code title="event-PeerConnection-text">text</code>
+ event is dispatched at the <code>PeerConnection</code> object.</p>
+
+ </dd>
+
+ <dt><var title="">connection</var> . <code title="dom-PeerConnection-addStream">addStream</code>(<var title="">stream</var>)</dt>
+
+ <dd>
+
+ <p>Attempts to starting sending the given stream to the remote
+ peer.</p>
+
+ <p>When the other peer starts sending a stream in this manner, an
+ <code title="event-PeerConnection-addstream">addstream</code>
+ event is dispatched at the <code>PeerConnection</code> object.</p>
+
+ </dd>
+
+ <dt><var title="">connection</var> . <code title="dom-PeerConnection-removeStream">removeStream</code>(<var title="">stream</var>)</dt>
+
+ <dd>
+
+ <p>Steps sending the given stream to the remote peer.</p>
+
+ <p>When the other peer stops sending a stream in this manner, a
+ <code
+ title="event-PeerConnection-removestream">removestream</code>
+ event is dispatched at the <code>PeerConnection</code> object.</p>
+
+ </dd>
+
+ <dt><var title="">connection</var> . <code title="dom-PeerConnection-localStreams">localStreams</code></dt>
+
+ <dd>
+
+ <p>Returns a live array containing the streams that the user agent
+ is currently attempting to transmit to the remote peer (those that
+ were added with <code
+ title="dom-PeerConnection-addStream">addStream()</code>).</p>
+
+ </dd>
+
+ <dt><var title="">connection</var> . <code title="dom-PeerConnection-remoteStreams">remoteStreams</code></dt>
+
+ <dd>
+
+ <p>Returns a live array containing the streams that the user agent
+ is currently receiving from the remote peer.</p>
+
+ <p>This array is updated when <code
+ title="event-PeerConnection-addstream">addstream</code> and <code
+ title="event-PeerConnection-removestream">removestream</code>
+ events are fired.</p>
+
+ </dd>
+
+ </dl>
+
+ <div class="impl">
+
+ <p>A <code>PeerConnection</code> object has an associated
+ <dfn><code>PeerConnection</code> signaling callback</dfn>, a
+ <dfn><code>PeerConnection</code> ICE Agent</dfn>, a
+ <dfn><code>PeerConnection</code> data UDP media stream</dfn> and an
+ <dfn>ICE started flag</dfn>. These are initialized when the object
+ is created.</p>
+
+ <p>When the <dfn
+ title="dom-PeerConnection"><code>PeerConnection()</code></dfn>
+ constructor is invoked, the user agent must run the following steps.
+ This algorithm has a <span>synchronous section</span> (which is
+ triggered as part of the <span>event loop</span> algorithm). Steps
+ in the <span>synchronous section</span> are marked with
+ &#x231B;.</p>
+
+ <ol>
+
+ <li><p>Let <var title="">serverConfiguration</var> be the constructor's
+ first argument.</p></li>
+
+ <li><p>Let <var title="">signalingCallback</var> be the
+ constructor's second argument.</p></li>
+
+ <li><p>If <var title="">signalingCallback</var> is null, throw a
+ <code>TypeError</code> exception and abort these steps.</p></li>
+
+ <li><p>Let <var title="">connection</var> be a newly created
+ <code>PeerConnection</code> object.</p></li>
+
+ <li><p>Create an ICE Agent and let <var title="">connection</var>'s
+ <span><code>PeerConnection</code> ICE Agent</span> be that ICE
+ Agent. <a href="#refsICE">[ICE]</a></p></li>
+
+ <li><p>If <var title="">serverConfiguration</var> contains a U+000A LINE
+ FEED (LF) character or a U+000D CARRIAGE RETURN (CR) character (or
+ both), remove all characters from <var title="">serverConfiguration</var>
+ after the first such character.</p></li>
+
+ <li><p><span title="split a string on spaces">Split <var
+ title="">serverConfiguration</var> on spaces</span> to obtain <var
+ title="">configuration components</var>.</p></li>
+
+ <li>
+
+ <p>If <var title="">configuration components</var> has two or more
+ components, and the first component is a
+ <span>case-sensitive</span> match for one of the following
+ strings:</p>
+
+ <ul class="brief">
+ <li>"<code title="">STUN</code>"
+ <li>"<code title="">STUNS</code>"
+ <li>"<code title="">TURN</code>"
+ <li>"<code title="">TURNS</code>"
+ </ul>
+
+ <p>...then run the following substeps:</p>
+
+ <ol>
+
+ <li><p>Let <var title="">server type</var> be STUN if the first
+ component of <var title="">configuration components</var> is
+ "<code title="">STUN</code>" or "<code title="">STUNS</code>",
+ and TURN otherwise (the first component of <var
+ title="">configuration components</var> is "<code
+ title="">TURN</code>" or "<code title="">TURNS</code>").</p>
+
+ <li><p>Let <var title="">secure</var> be true if the first
+ component of <var title="">configuration components</var> is
+ "<code title="">STUNS</code>" or "<code title="">TURNS</code>",
+ and false otherwise.</p>
+
+ <li><p>Let <var title="">host</var> be the contents of the second
+ component of <var title="">configuration components</var> up to
+ the character before the first U+003A COLON character (:), if
+ any, or the entire string otherwise.</p></li>
+
+ <li><p>Let <var title="">port</var> be the contents of the second
+ component of <var title="">configuration components</var> from
+ the character after the first U+003A COLON character (:) up to
+ the end, if any, or the empty string otherwise.</p></li>
+
+ <li>
+
+ <p>Configure the <span><code>PeerConnection</code> ICE
+ Agent</span>'s STUN or TURN server as follows:</p>
+
+ <ul>
+
+ <li>If <var title="">server type</var> is STUN, the server is a
+ STUN server. Otherwise, <var title="">server type</var> is TURN
+ and the server is a TURN server.</li>
+
+ <li>If <var title="">secure</var> is true, the server is to be
+ contacted using TLS-over-TCP, otherwise, it is to be contacted
+ using UDP.</li>
+
+ <li>The IP address, host name, or domain name of the server is
+ <var title="">host</var>.</li>
+
+ <li>The port to use is <var title="">port</var>. If this is the
+ empty string, then only a domain name is configured (and the
+ ICE Agent will use DNS SRV requests to determine the IP address
+ and port).</li>
+
+ <li>The long-term username for the the STUN or TURN server is
+ the <span title="ASCII serialization of an origin">ASCII
+ serialization</span> of the <span>entry script</span>'s
+ <span>origin</span>; the long-term password is the empty
+ string.</li>
+
+ </ul>
+
+ <p>If the given IP address, host name, domain name, or port are
+ invalid, then the user agent must act as if no STUN or TURN
+ server is configured.</p>
+
+ </li>
+
+ </ol>
+
+ </li>
+
+ <li><p>Let the <var title="">connection</var>'s
+ <span><code>PeerConnection</code> signaling callback</span> be
+ <var title="">signalingCallback</var>.</p></li>
+
+ <li><p>Set <var title="">connection</var>'s <span>ICE started
+ flag</span> to false.</p></li>
+
+ <li><p>Let <var title="">connection</var>'s
+ <span><code>PeerConnection</code> data UDP media stream</span> be a
+ new <span>data UDP media stream</span>.</p></li>
+
+ <li><p>Let <var title="">connection</var>'s <code
+ title="dom-PeerConnection-localStreams">localStreams</code>
+ attribute be an empty read-only <code>Stream</code> array. <a
+ href="#refsWEBIDL">[WEBIDL]</a></p></li>
+
+ <li><p>Let <var title="">connection</var>'s <code
+ title="dom-PeerConnection-remoteStreams">remoteStreams</code>
+ attribute be an empty read-only <code>Stream</code> array. <a
+ href="#refsWEBIDL">[WEBIDL]</a></p></li>
+
+ <li><p>Return <var title="">connection</var>, but continue these
+ steps asynchronously.</p></li>
+
+ <li><p><span>Await a stable state</span>. The <span>synchronous
+ section</span> consists of the remaining steps of this
+ algorithm. (Steps in <span title="synchronous section">synchronous
+ sections</span> are marked with &#x231B;.)</p></li>
+
+ <li><p>&#x231B; If <var title="">connection</var>'s <span>ICE
+ started flag</span> is still false, start the
+ <span><code>PeerConnection</code> ICE Agent</span> and send the
+ initial offer. The initial offer must include a media description
+ for the <span><code>PeerConnection</code> data UDP media
+ stream</span> and for all the streams in <code
+ title="dom-PeerConnection-localStreams">localStreams</code>. <a
+ href="#refsICE">[ICE]</a></p></li>
+
+ <li><p>&#x231B; Let <var title="">connection</var>'s <span>ICE
+ started flag</span> be true.</p></li>
+
+ </ol>
+
+ <p>When a <span><code>PeerConnection</code> ICE Agent</span> is
+ required to send SDP offers or answers, the user agent must follow
+ these steps:</p>
+
+ <ol>
+
+ <li><p>Let <var title="">sdp</var> be the SDP offer or answer to be
+ sent. <a href="#refsSDPOFFERANSWER">[SDPOFFERANSWER]</a></p></li>
+
+ <li><p>Let <var title="">message</var> be the concatenation of the
+ string "<code title="">SDP</code>", a U+000A LINE FEED (LF)
+ character, and <var title="">sdp</var>, in that order.</p></li>
+
+ <li><p><span>Queue a task</span> to invoke that
+ <span><code>PeerConnection</code> ICE Agent</span>'s
+ <span><code>PeerConnection</code> signaling callback</span> with
+ <var title="">message</var> as its argument.</p></li>
+
+ </ol>
+
+ <p>All SDP media descriptions for streams represented by
+ <code>Stream</code> objects must include a label attribute ("<code
+ title="">a=label:</code>") whose value is the value of the
+ <code>Stream</code> object's <code
+ title="dom-stream-label">label</code> attribute. <a
+ href="#refsSDP">[SDP]</a> <a href="#refsSDPLABEL">[SDPLABEL]</a></p>
+
+ <p><span title="PeerConnection ICE
+ Agent"><code>PeerConnection</code> ICE Agents</span> must not
+ generate any candidates for media streams whose media descriptions
+ do not have a label attribute ("<code title="">a=label:</code>"). <a
+ href="#refsICE">[ICE]</a> <a href="#refsSDP">[SDP]</a> <a
+ href="#refsSDPLABEL">[SDPLABEL]</a></p>
+
+ <p>When a user agent starts receiving media for a component an a
+ candidate provided for that component by a
+ <span><code>PeerConnection</code> ICE Agent</span>, the user agent
+ must follow these steps:</p>
+
+ <ol>
+
+ <li><p>Let <var title="">connection</var> be the
+ <code>PeerConnection</code> whose ICE Agent is expecting this
+ media.</p></li>
+
+ <li><p>If there is already a <code>Stream</code> object for the
+ media stream to which this component belongs, then associate the
+ component with that media stream and abort these steps. (Some media
+ streams have multiple components; this API does not expose the
+ role of these individual components in ICE.)</p></li>
+
+ <li><p>Create a <code>Stream</code> object to represent the media
+ stream. Set its <code title="attr-stream-label">label</code>
+ attribute to the value of the SDP Label attribute for that
+ component's media stream.</p></li>
+
+ <li><p><span>Queue a task</span> to add the newly created
+ <code>Stream</code> object to the end of <var
+ title="">connection</var>'s <code
+ title="dom-PeerConnection-remoteStreams">remoteStreams</code>
+ array, then <span>fire a stream event</span> named <code
+ title="event-stream-addstream">addstream</code> with the newly
+ created <code>Stream</code> object at the <var
+ title="">connection</var> object.</p></li>
+
+ </ol>
+
+ <p>When a <span><code>PeerConnection</code> ICE Agent</span> finds
+ that a stream from the remote peer has been removed (its port has
+ been set to zero in a media description sent on the signaling
+ channel), the user agent must follow these steps:</p>
+
+ <ol>
+
+ <li><p>Let <var title="">connection</var> be the
+ <code>PeerConnection</code> whose <span><code>PeerConnection</code>
+ ICE Agent</span> has determined that a stream is being removed.</p></li>
+
+ <li><p>Let <var title="">stream</var> be the <code>Stream</code>
+ object that represents the media stream being removed, if any. If
+ there isn't one, then abort these steps.</p></li>
+
+ <li><p><span>Queue a task</span> to remove <var
+ title="">stream</var> from <var title="">connection</var>'s <code
+ title="dom-PeerConnection-remoteStreams">remoteStreams</code>
+ array, then <span>fire a stream event</span> named <code
+ title="event-stream-removestream">removestream</code> with <var
+ title="">stream</var> at the <var title="">connection</var>
+ object.</p></li>
+
+ </ol>
+
+ <p>When the <dfn title="dom-PeerConnection-signalingMessage"><code
+ title="">signalingMessage()</code></dfn> method is invoked, the
+ user agent must run the following steps:</p>
+
+ <ol>
+
+ <li><p>Let <var title="">message</var> be the method's
+ argument.</p></li>
+
+ <li>
+
+ <p>If the first four characters of <var title="">message</var> are
+ not "<code title="">SDP</code>" followed by a U+000A LINE FEED
+ (LF) character, then abort these steps. (This indicates an error
+ in the signaling channel implementation. User agents may report
+ such errors to their developer consoles to aid debugging.)</p>
+
+ <p class="note">Future extensions to the
+ <code>PeerConnection</code> interface might use other prefix
+ values to implement additional features.</p>
+
+ </li>
+
+ <li><p>Let <var title="">sdp</var> be the string consisting of all
+ but the first four characters of <var
+ title="">message</var>.</p></li>
+
+ <li>
+
+ <p>If <var title="">connection</var>'s <span>ICE started
+ flag</span> is still false, start the
+ <span><code>PeerConnection</code> ICE Agent</span> and pass it
+ <var title="">sdp</var> as the initial offer from the other peer;
+ the ICE Agent will then (asynchronously) construct the initial
+ answer and transmit it as described above. The initial answer must
+ include a media description for the
+ <span><code>PeerConnection</code> data UDP media stream</span> and
+ for all the streams in <code
+ title="dom-PeerConnection-localStreams">localStreams</code>. <a
+ href="#refsICE">[ICE]</a></p>
+
+ <p>If <var title="">connection</var>'s <span>ICE started
+ flag</span> is true, then pass <var title="">sdp</var> to the
+ <span><code>PeerConnection</code> ICE Agent</span> as a subsequent
+ offer or answer, to be interpreted as appropriate given the
+ current state of the ICE Agent. <a href="#refsICE">[ICE]</a></p>
+
+ </li>
+
+ <li><p>Let <var title="">connection</var>'s <span>ICE started
+ flag</span> be true.</p></li>
+
+ </ol>
+
+ <p>When the <dfn title="dom-PeerConnection-send"><code
+ title="">send()</code></dfn> method is invoked, the
+ user agent must run the following steps:</p>
+
+ <ol>
+
+ <li><p>Let <var title="">message</var> be the method's first
+ argument.</p></li>
+
+ <li><p>Let <var title="">data</var> be <var title="">message</var>
+ encoded as UTF-8. <a href="#refsRFC3629">[RFC3629]</a></p></li>
+
+ <li><p>If <var title="">data</var> is longer than 65470 bytes,
+ throw an <code>INVALID_ACCESS_ERR</code> exception and abort these
+ steps.</p></li>
+ <!-- 65470 = 65535 (64K, max IP size) - 40 (IP header) - 8 (UDP header) - 16 (nonce) - 1 (payload type byte) -->
+
+ <li><p>If the <code>PeerConnection</code>'s
+ <span><code>PeerConnection</code> data UDP media stream</span> is
+ not an <span>active data UDP media stream</span>, abort these
+ steps. No message is sent.</p></li>
+
+ <li><p><span>Transmit a data packet to a peer</span> using the
+ <code>PeerConnection</code>'s <span><code>PeerConnection</code>
+ data UDP media stream</span> with <var title="">data</var> as the
+ message.</p></li>
+
+ </ol>
+
+ <p>When the <dfn title="dom-PeerConnection-addStream"><code
+ title="">addStream()</code></dfn> method is invoked, the user agent
+ must run the following steps:</p>
+
+ <ol>
+
+ <li><p>Let <var title="">stream</var> be the method's
+ argument.</p></li>
+
+ <li><p>If <var title="">stream</var> is null, throw a
+ <code>TypeError</code> exception and abort these steps.</p></li>
+
+ <li><p>If <var title="">stream</var> is already in the
+ <code>PeerConnection</code> object's <code
+ title="dom-PeerConnection-localStreams">localStreams</code> object,
+ then abort these steps.</p></li>
+
+ <li><p>Add <var title="">stream</var> to the end of the
+ <code>PeerConnection</code> object's <code
+ title="dom-PeerConnection-localStreams">localStreams</code>
+ object.</p></li>
+
+ <li><p>If the <code>PeerConnection</code>'s <span>ICE
+ started flag</span> is false, then abort these steps.</p></li>
+
+ <li><p>Have the <code>PeerConnection</code>'s
+ <span><code>PeerConnection</code> ICE Agent</span> add a media
+ stream for <var title="">stream</var>. <a
+ href="#refsICE">[ICE]</a></p></li> <!-- section 9.1.1.3 -->
+
+ </ol>
+
+ <p>When the <dfn title="dom-PeerConnection-removeStream"><code
+ title="">removeStream()</code></dfn> method is invoked, the user agent
+ must run the following steps:</p>
+
+ <ol>
+
+ <li><p>Let <var title="">stream</var> be the method's
+ argument.</p></li>
+
+ <li><p>If <var title="">stream</var> is null, throw a
+ <code>TypeError</code> exception and abort these steps.</p></li>
+
+ <li><p>If <var title="">stream</var> is not in the
+ <code>PeerConnection</code> object's <code
+ title="dom-PeerConnection-localStreams">localStreams</code> object,
+ then abort these steps.</p></li>
+
+ <li><p>Remove <var title="">stream</var> from the
+ <code>PeerConnection</code> object's <code
+ title="dom-PeerConnection-localStreams">localStreams</code>
+ object.</p></li>
+
+ <li><p>If the <code>PeerConnection</code>'s <span>ICE
+ started flag</span> is false, then abort these steps.</p></li>
+
+ <li><p>Have the <code>PeerConnection</code>'s
+ <span><code>PeerConnection</code> ICE Agent</span> remove the media
+ stream for <var title="">stream</var>. <a
+ href="#refsICE">[ICE]</a></p></li> <!-- section 9.1.1.2 -->
+
+ </ol>
+
+ <p>The <dfn
+ title="dom-PeerConnection-localStreams"><code>localStreams</code></dfn>
+ and <dfn
+ title="dom-PeerConnection-remoteStreams"><code>remoteStreams</code></dfn>
+ attributes must return the read-only <code>Stream</code> arrays that
+ the attributes were respectively set to when the
+ <code>PeerConnection</code>'s constructor ran.</p>
+
+ <hr>
+
+ <p>The following are the <span>event handlers</span> (and their
+ corresponding <span title="event handler event type">event handler
+ event types</span>) that must be supported, as IDL attributes, by
+ all objects implementing the <code>PeerConnection</code>
+ interface:</p>
+
+ <table>
+ <thead>
+ <tr><th><span title="event handlers">Event handler</span> <th><span>Event handler event type</span>
+ <tbody>
+ <tr><td><dfn title="handler-PeerConnection-ontext"><code>ontext</code></dfn> <td> <code title="event-stream-text">text</code>
+ <tr><td><dfn title="handler-PeerConnection-onaddstream"><code>onaddstream</code></dfn> <td> <code title="event-stream-addstream">addstream</code>
+ <tr><td><dfn title="handler-PeerConnection-onremovestream"><code>onremovestream</code></dfn> <td> <code title="event-stream-removestream">removestream</code>
+ </table>
+
+ <hr>
+
+ <p>The <span>task source</span> for the <span
+ title="concept-task">tasks</span> listed in this section is the
+ <span>networking task source</span>.</p>
+
+ </div>
+
+ <div class="example">
+
+ <p>When two peers decide they are going to set up a connection to
+ each other, they both go through these steps. The STUN/TURN server
+ configuration describes a server they can use to get things like
+ their public IP address or to set up NAT traversal. They also have
+ to send data for the signaling channel to each other using the same
+ out-of-band mechanism they used to establish that they were going
+ to communicate in the first place.</p>
+
+ <pre>// the first argument describes the STUN/TURN server configuration
+var local = new PeerConnection('TURNS example.net', sendSignalingChannel);
+local.signalingChannel(...); // if we have a message from the other side, pass it along here
+
+// (aLocalStream is some GeneratedStream object)
+local.addStream(aLocalStream); // start sending video
+
+function sendSignalingChannel(message) {
+ ... // send message to the other side via the signaling channel
+}
+
+function receiveSignalingChannel (message) {
+ // call this whenever we get a message on the signaling channel
+ local.signalingChannel(message);
+}
+
+local.onaddstream = function (event) {
+ // (videoElement is some &lt;video> element)
+ videoElement.src = URL.getObjectURL(event.stream);
+};</pre>
+
+ </div>
+
+ <p class="warning">To prevent network sniffing from allowing a
+ fourth party to establish a connection to a peer using the
+ information sent out-of-band to the other peer and thus spoofing the
+ client, the configuration information should always be transmitted
+ using an encrypted connection.</p>
+
+
+
+ <h4>The data stream</h4>
+
+ <p>All <code>PeerConnection</code> connections include a <dfn>data
+ UDP media stream</dfn>, which is used to send data packets
+ peer-to-peer, for instance game control packets. This data channel
+ is unreliable (packets are not guaranteed to be delivered, and are
+ not guaranteed to be delivered in the right order).</p>
+
+ <p>All SDP media descriptions for <span title="data UDP media
+ stream">data UDP media streams</span> must include a label attribute
+ ("<code title="">a=label:</code>") whose value is the string "<code
+ title="">data</code>". <a href="#refsSDP">[SDP]</a> <a
+ href="#refsSDPLABEL">[SDPLABEL]</a></p>
+
+ <p>All SDP media descriptions for <span title="data UDP media
+ stream">data UDP media streams</span> must also include a key field
+ ("<code title="">k=</code>"), with the value being a base64-encoded
+ representation of 16 cryptographically random bytes determined on a
+ per-ICE-Agent basis. <a href="#refsSDP">[SDP]</a></p>
+
+ <p><span title="PeerConnection ICE
+ Agent"><code>PeerConnection</code> ICE Agents</span> must attempt to
+ establish a connection for their <span><code>PeerConnection</code>
+ data UDP media stream</span> during the initial offer/answer
+ exchange, and must maintain that UDP media stream for the ICE
+ Agents' whole lifetime.</p>
+
+ <p>A <span>data UDP media stream</span> is an <dfn>active data UDP
+ media stream</dfn> if the <span><code>PeerConnection</code> ICE
+ Agent</span> has selected a destination for it. A <span>data UDP
+ media stream</span> can change active status many times during the
+ lifetime of its <code>PeerConnection</code> object (e.g. any time
+ the network topology changes and the ICE Agent performs an ICE
+ Restart). <a href="#refsICE">[ICE]</a></p>
+
+ <p>Bytes transmitted on a <span>data UDP media stream</span> are
+ masked so as to prevent cross-protocol attacks (<span>data UDP media
+ stream</span> always appear to contain random noise to other
+ protocols). For the purposes of masking, the <dfn>data UDP media
+ stream salt</dfn> is defined to be the following 16 bytes, described
+ here as hexadecimal numbers: DB 68 B5 FD 17 0E 15 77 56 AF 7A 3A 1A
+ 57 75 02</p> <!-- obtained thusly: head -c 16 /dev/urandom |
+ hexdump -C -->
+
+ <p>When the user agent is to <dfn>transmit a data packet to a
+ peer</dfn> using a <span>data UDP media stream</span> and with a
+ byte string payload <var title="">data</var>, the user agent must
+ run the following steps:</p>
+
+ <ol>
+
+ <li><p>Let <var title="">nonce</var> be 16 cryptographically random
+ bytes.</p></li>
+
+ <li><p>Let <var title="">ice-key</var> be the 16 bytes given as the
+ encryption key for the <span>data UDP media stream</span> in its
+ media description, as defined above.</p></li>
+
+ <li><p>Let <var title="">key</var> be the first 16 bytes of the
+ HMAC-SHA1 of the 16 <var title="">nonce</var> bytes concatenated
+ with the 16 <var title="">ice-key</var> bytes concatenated with the
+ 16 <span>data UDP media stream salt</span> bytes. <a
+ href="#refsHMAC">[HMAC]</a> <a href="#refsSHA1">[SHA1]</a></p></li>
+
+ <li><p>Let <var title="">message</var> be a 0x01 byte followed by
+ <var title="">data</var>.</p></li>
+
+ <li><p>Let <var title="">masked message</var> be the result of
+ encrypting <var title="">message</var> using AES-128-CTR keyed with
+ <var title="">key</var>. <a
+ href="#refsAES128CTR">[AES128CTR]</a></p></li>
+
+ <li><p>Send the concatenation of <var title="">nonce</var> and <var
+ title="">masked message</var> in a UDP packet to the destination
+ that the relevant <span><code>PeerConnection</code> ICE
+ Agent</span> has selected a destination for the <span>data UDP
+ media stream</span>.</p></li>
+
+ </ol>
+
+ <p>A <dfn>remote data UDP media stream</dfn> is the first UDP media
+ stream whose sender is the remote peer, whose label attribute
+ ("<code title="">a=label:</code>") has the value "<code
+ title="">data</code>", and for which a
+ <span><code>PeerConnection</code> ICE Agent</span> has selected a
+ destination, if that media stream has an encryption key advertised
+ in its media description, and if that encryption key is 16 bytes
+ long. A <span>remote data UDP media stream</span> is associated with
+ the <code>PeerConnection</code> object for which the
+ <span><code>PeerConnection</code> ICE Agent</span> in question is
+ operating.</p>
+
+ <p>When a packet from a <span>remote data UDP media stream</span> is
+ received, the user agent must run the following steps:</p>
+
+ <ol>
+
+ <li><p>Let <var title="">data</var> be the UDP packet's data.</p></li>
+
+ <li><p>If <var title="">data</var> is shorter than 17 bytes, then
+ abort these steps.</p></li>
+
+ <li><p>Let <var title="">nonce</var> be the first 16 bytes of the
+ <var title="">data</var>.</p></li>
+
+ <li><p>Let <var title="">ice-key</var> be the 16 bytes given as the
+ encryption key for the <span>remote data UDP media stream</span> in
+ the media description for this media stream. <a
+ href="#refsSDP">[SDP]</a></p></li>
+
+ <li><p>Let <var title="">key</var> be the first 16 bytes of the
+ HMAC-SHA1 of the 16 <var title="">nonce</var> bytes concatenated
+ with the 16 <var title="">ice-key</var> bytes concatenated with the
+ 16 <span>data UDP media stream salt</span> bytes. <a
+ href="#refsHMAC">[HMAC]</a> <a href="#refsSHA1">[SHA1]</a></li>
+
+ <li><p>Let <var title="">unmasked data</var> be the result of
+ decrypting <var title="">message</var> using AES-128-CTR keyed with
+ <var title="">key</var>. <a
+ href="#refsAES128CTR">[AES128CTR]</a></p></li>
+
+ <li><p>If the first byte of <var title="">unmasked data</var> is
+ not 0x01, then abort these steps.</p></li>
+
+ <li><p>Let <var title="">raw message</var> be the string consisting
+ of all but the first character of <var title="">unmasked
+ message</var>.</p></li>
+
+ <li><p>Let <var title="">message</var> be <var title="">raw
+ message</var> <span>decoded as UTF-8, with error
+ handling</span>.</p></li>
+
+ <li><p>Create an event that uses the <code>MessageEvent</code>
+ interface, with the name <code title="event-text">text</code>,
+ which does not bubble, is not cancelable, has no default action,
+ and has a <code title="dom-MessageEvent-data">data</code> attribute
+ whose value is <var title="">message</var>, and <span>queue a
+ task</span> to dispatch the event at the
+ <code>PeerConnection</code> object that the <span>remote data UDP
+ media stream</span> is associated with.</p></li>
+
+ </ol>
+
+
+ <h4>Event definitions</h4>
+
+ <p>The <code title="event-stream-addstream">addstream</code> and
+ <code title="event-stream-removestream">removestream</code> events
+ use the <code>StreamEvent</code> interface:</p>
+
+ <pre class="idl">interface <dfn>StreamEvent</dfn> : <span>Event</span> {
+ readonly attribute <span>Stream</span> <span title="dom-StreamEvent-stream">stream</span>;
+ void <span title="dom-CloseEvent-initCloseEvent">initCloseEvent</span>(in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in <span>Stream</span> streamArg);
+};</pre>
+
+ <p>The <dfn
+ title="dom-StreamEvent-initStreamEvent"><code>initStreamEvent()</code></dfn>
+ method must initialize the event in a manner analogous to the
+ similarly-named method in the DOM Events interfaces. <a
+ href="#refsDOMEVENTS">[DOMEVENTS]</a></p>
+
+ <p>The <dfn title="dom-StreamEvent-stream"><code>stream</code></dfn>
+ attribute represents the <code>Stream</code> object associated with
+ the event.</p>
+
+ <p><dfn title="fire a stream event">Firing a stream event named <var
+ title="">e</var></dfn> with a <code>Stream</code> <var
+ title="">stream</var> means that an event with the name <var
+ title="">e</var>, which does not bubble (except where otherwise
+ stated) and is not cancelable (except where otherwise stated), and
+ which uses the <code>StreamEvent</code> interface with the <code
+ title="dom-StreamEvent-stream">stream</code> attribute set to <var
+ title="">stream</var>, must be dispatched at the given target.</p>
+
+
+ <h4>Event Summary</h4>
+
+ <p class="XXX">...will add event summary for streams here...</p>
+
+</div>
+
+<!--END html--><!--END dev-html-->
+
+
+
+
-<!--END html--><!--END dev-html--><!--END w3c-html-->
<div data-component="Web Workers (editor: Ian Hickson)">
@@ -81261,7 +82714,7 @@ v2 (well, really v0):
<p>The bulk of this code is simply an unoptimized search for a prime
number. To send a message back to the page, the <code
- title="dom-DedicatedWorkerGlobalScope-postMessage">postMessage()</code>
+ title="dom-DedicatedWorkerGlobalScope-send">send()</code>
method is used to post a message when a prime is found.</p>
<p><a href="http://www.whatwg.org/demos/workers/primes/page.html">View this example online</a>.</p>
@@ -99096,7 +100549,7 @@ iframe:not([seamless]) { border: 2px inset; }
<hr>
<p>All animated images with the same <span>absolute URL</span> and
- the same image data are expected to be rendered synchronised to the
+ the same image data are expected to be rendered synchronized to the
same timeline as a group, with the timeline starting at the time of
the most recent addition to the group.</p>
@@ -106877,6 +108330,9 @@ interface <span>HTMLDocument</span> {
href="http://tools.ietf.org/html/draft-holsten-about-uri-scheme">The
'about' URI scheme</a></cite>, J. Holsten, L. Hunt. IETF.</dd>
+ <dt id="refsAES128CTR">[AES128CTR]</dt>
+ <dd><cite><a href="http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf">Advanced Encryption Standard (AES)</a></cite>. NIST.</dd>
+
<dt id="refsARIA">[ARIA]</dt>
<dd><cite><a href="http://www.w3.org/WAI/PF/aria/">Accessible Rich
Internet Applications (WAI-ARIA)</a></cite>, J. Craig, M. Cooper, L. Pappas,
@@ -107110,6 +108566,9 @@ interface <span>HTMLDocument</span> {
href="http://microformats.org/wiki/hatom">hAtom</a></cite>, D
Janes. Microformats.</dd>
+ <dt id="refsHMAC">[HMAC]</dt>
+ <dd><cite><a href="http://csrc.nist.gov/publications/fips/fips198/fips-198a.pdf">The Keyed-Hash Message Authentication Code (HMAC)</a></cite>. NIST.</dd>
+
<dt id="refsHTML4">[HTML4]</dt>
<dd>(Non-normative) <cite><a
href="http://www.w3.org/TR/html4/">HTML 4.01
@@ -107158,6 +108617,9 @@ interface <span>HTMLDocument</span> {
href="http://www.iana.org/assignments/message-headers/perm-headers.html">Permanent
Message Header Field Names</a></cite>. IANA.</dd>
+ <dt id="refsICE">[ICE]</dt>
+ <dd><cite><a href="http://tools.ietf.org/html/rfc5245">Interactive Connectivity Establishment (ICE): A Protocol for Network Address Translator (NAT) Traversal for Offer/Answer Protocols</a></cite>, J. Rosenberg. IETF.</dd>
+
<dt id="refsIEEE754">[IEEE754]</dt>
<dd><cite><a
href="http://ieeexplore.ieee.org/servlet/opac?punumber=4610933">IEEE
@@ -107463,12 +108925,24 @@ interface <span>HTMLDocument</span> {
Compression Scheme For Unicode</a></cite>, M. Wolf, K. Whistler,
C. Wicksteed, M. Davis, A. Freytag, M. Scherer. Unicode Consortium.</dd>
+ <dt id="refsSDP">[SDP]</dt>
+ <dd><cite><a href="http://tools.ietf.org/html/rfc4566">SDP: Session Description Protocol</a></cite>, M. Handley, V. Jacobson, C. Perkins. IETF.</dd>
+
+ <dt id="refsSDPLABEL">[SDPLABEL]</dt>
+ <dd><cite><a href="http://tools.ietf.org/html/rfc4574">The Session Description Protocol (SDP) Label Attribute</a></cite>, O. Levin, G. Camarillo. IETF.</dd>
+
+ <dt id="refsSDPOFFERANSWER">[SDPOFFERANSWER]</dt>
+ <dd><cite><a href="http://tools.ietf.org/html/rfc3264">An Offer/Answer Model with the Session Description Protocol (SDP)</a></cite>, J. Rosenberg, H. Schulzrinne. IETF.</dd>
+
<dt id="refsSELECTORS">[SELECTORS]</dt>
<dd><cite><a
href="http://www.w3.org/TR/css3-selectors">Selectors</a></cite>,
T. &Ccedil;elik, E. Etemad, D. Glazman, I. Hickson, P. Linss,
J. Williams. W3C.</dd>
+ <dt id="refsSHA1">[SHA1]</dt>
+ <dd><cite><a href="http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf">Secure Hash Standard</a></cite>. NIST.</dd>
+
<dt id="refsSHIFTJIS">[SHIFTJIS]</dt>
<dd><cite>JIS X0208: 7-bit and 8-bit double byte coded KANJI sets
for information interchange</cite>. Japanese Industrial Standards Committee.</dd>
@@ -107480,6 +108954,9 @@ interface <span>HTMLDocument</span> {
and management &mdash; Part 2-1: Colour management &mdash; Default RGB colour
space &mdash; sRGB</a></cite>. IEC.</dd>
+ <dt id="refsSTUN">[STUN]</dt>
+ <dd><cite><a href="http://tools.ietf.org/html/rfc5389">Session Traversal Utilities for NAT (STUN)</a></cite>, J. Rosenberg, R. Mahy, P. Matthews, D. Wing. IETF.</dd>
+
<dt id="refsSVG">[SVG]</dt>
<dd><cite><a href="http://www.w3.org/TR/SVGTiny12/">Scalable Vector
Graphics (SVG) Tiny 1.2 Specification</a></cite>, O. Andersson,
@@ -107495,6 +108972,9 @@ interface <span>HTMLDocument</span> {
Ministry of Industry, Royal Thai Government. ISBN
974-606-153-4.</dd>
+ <dt id="refsTURN">[TURN]</dt>
+ <dd><cite><a href="http://tools.ietf.org/html/rfc5766">Traversal Using Relays around NAT (TURN): Relay Extensions to Session Traversal Utilities for NAT (STUN)</a></cite>, R. Mahy, P. Matthews, J. Rosenberg. IETF.</dd>
+
<dt id="refsUAAG">[UAAG]</dt>
<dd>(Non-normative) <cite><a
href="http://www.w3.org/TR/UAAG20/">Web Content Accessibility

0 comments on commit 76d736e

Please sign in to comment.