-
Notifications
You must be signed in to change notification settings - Fork 7
/
index.bs
703 lines (537 loc) · 27.5 KB
/
index.bs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
<pre class='metadata'>
Title: Local Peer-to-Peer API
Shortname: local-peer-to-peer
Level: 1
Status: CG-DRAFT
Group: WICG
Repository: WICG/local-peer-to-peer
URL: https://WICG.github.io/local-peer-to-peer/
Editor: Anssi Kostiainen, Intel https://intel.com, [email protected]
Editor: Belem Zhang, Intel https://intel.com, [email protected]
Editor: Michiel De Backker, Twintag https://twintag.com, [email protected]
Editor: Wei Wang, Intel https://intel.com, [email protected]
!Tests: <a href=https://github.com/w3c/web-platform-tests/tree/master/local-peer-to-peer>web-platform-tests local-peer-to-peer/</a> (<a href=https://github.com/w3c/web-platform-tests/labels/local-peer-to-peer>ongoing work</a>)
Abstract: Local Peer-to-Peer is a Web platform API proposal for local communication between browsers without the aid of a server.
Markup Shorthands: markdown yes, dfn yes, idl yes, markup yes
</pre>
Note: This specification is under active development and therefore incomplete. If you're looking for an overview of the proposal, please refer to the [Explainer](https://github.com/WICG/local-peer-to-peer/blob/main/EXPLAINER.md).
Introduction {#intro}
=====================
*This section is non-normative.*
The Local Peer-to-Peer API aims to give browsers the means to communicate directly, without the aid of a server in the middle. It is designed to enable this communication within the confines of a local communication medium such as the Local Area Network.
Many modern Web security measures rely on the presence of naming, signaling and certificate authorities. Local use-cases where these authorities are not readily available have started lagging behind in user experience or are not supported altogether. The Local Peer-to-Peer API aims to bring back first-class support for local communication use-cases while working within the same strict user-friendliness, security and privacy requirements.
Examples of potential uses of this API include: Collaboration tools that work during an internet outage or emergency situations, connecting to your NAS, your home security system, your robotic assistant doing the dishes or your GPU farm in the basement that's running your personalized virtual assistant.
This specification aims to strike a balance between creating a powerful new building block for developers and providing a seamless, secure and privacy preserving experience for browser users. As an example: while the API doesn't provide raw socket access, it does aim to give developers the flexibility to innovate on top by providing a persistent, two-way communication channel with little overhead.
The API is designed to be backed by an authenticated, streams-based transport. As a commitment to an open standards-based implementation path, this specification describes how the API can be implemented on top of the [Open Screen Protocol](https://w3c.github.io/openscreenprotocol/). While not described here, the API is expected to be implementable on top of other transports when technically feasible.
Permission Policy Integration {#permission-policy-integration}
======================================================
The Local Peer-to-Peer API defines a [=policy-controlled feature=] identified by the token "local-peer-to-peer". Its [=default allowlist=] is `"self"`.
Workers (dedicated and shared) adhere to the permission policy set by their owning document(s):
<ul>
<li>
Dedicated workers can be created from other workers, in which case the permission policy of the first owning document (in case of a dedicated worker) or owning documents (in case of a shared worker) up the owner chain will be used.
</li>
<li>
Shared workers often have multiple owning documents as they can be obtained by other documents with the [=same origin=]. In this case, all owning documents must be [=allowed to use=] the [=policy-controlled feature=] defined by this specification.
</li>
</ul>
Note: There has been discussion on allowing setting permission policy directly on a worker on creation, in which case that would have to be consulted as well.
The [=policy-controlled feature/default allowlist=] of `"self"` allows usage in same-origin nested frames but prevents third-party content from using the feature. Third-party content usage can be selectively enabled by adding `allow="local-peer-to-peer"` attribute to the frame container element:
<pre class="example" title= "Enabling Local Peer-to-Peer API on third-party content" highlight='js'>
<iframe src="https://third-party.com" allow="local-peer-to-peer"/></iframe>
</pre>
Alternatively, the Local Peer-to-Peer API can be disabled completely by specifying the permissions policy in a HTTP response header:
<pre class="example" title="Permission Policy over HTTP" highlight='js'>
Permissions-Policy: local-peer-to-peer=()
</pre>
See [[!PERMISSIONS-POLICY]] for more details.
Peer Management {#peer-management}
==================================
Note: This section and its subsections use RFC 2119 terminology in a relaxed manner. These sections will be converted into well-defined algorithmic normative prose informed by further implementation experience. For now, this relaxed description better allows for rapid prototyping.
The user agent is in charge of managing peers.
A <dfn>peer</dfn> is an equal participants in the network that forms a peer-to-peer network of nodes. These nodes can communicate without the need for a central coordination by a server.
A user agent has an associated <dfn>local peer-to-peer manager</dfn> in charge of managing [=peers=]. Its responsibility is to [=start local peer discovery=], [=establish local peer connections=] and [=acquire a local peer grant=] on a per-origin basis. This is done to avoid exposing information about a user's local network topology.
Known peers {#known-peers}
--------------------------
The user agent should maintain a list of peers that it has knowledge of.
The [=local peer-to-peer manager=] has an associated <dfn>known peers map</dfn>, an [=/ordered map=] of [=known peers=]. Each <dfn>known peer</dfn> is a [=peer=] that has an associated <dfn>authentication state</dfn> and <dfn>peer grant state</dfn>. The user agent keeps track of the [=authentication state=] per peer and the [=peer grant state=] per peer, per origin. Unless [=persisted=], both the states are initially false.
Note: The [=peer grant state=] is origin-level while the [=authentication state=] is peer-level. The rationale is to not require the user to undergo authentication multiple times between the same peers. This design may change informed by security and privacy considerations.
Issue(wicg/local-peer-to-peer#24): See also related
The user agent may persist known peers, their [=authentication states=] and/or [=peer grant states=]. If the user agent chooses to do so, it must do so in accordance with the [[!openscreenprotocol|Open Screen Protocol]] Persistent State rules. Such a peer or its state is said to be <dfn>persisted</dfn>.
Peer advertisement {#peer-advertisement}
----------------------------------------
The user agent can make itself discoverable by advertising using the [=session/advertise agent=] capability.
Note: The user agent must get the user's explicit consent in order to start advertising.
When advertising, the user agent must listen for incoming peer connections. In case a connection is received, the peer is added to the [=known peers map=]. The user agent must not directly provide access to the incoming peer connection to any origin. Instead, the user agent must prompt to [grant peer](#peer-grant) access to the origin that initiated peer advertisement.
Peer discovery {#peer-discovery}
--------------------------------
The user agent can discover local peers using the [=session/discover agents=] capability.
When asked to <dfn>start local peer discovery</dfn>, the user agent discovers local peers using the [=session/discover agents=] capability.
If a peer is discovered, the user agent should add it to the [=known peers map=]. The user agent must never expose the full result of peer discovery with an origin. Instead, the user agent must [=acquire a local peer grant=] to grant access to a peer for the origin that initiated the peer request.
Peer authentication {#peer-authentication}
------------------------------------------
The user agent can initiate authentication with a peer using the [=session/authenticate an agent=] capability.
When asked to <dfn>authenticate a local peer</dfn>, the user agent must initiate authentication with a local peer using the [=session/authenticate an agent=] capability. The peer's [=authentication state=] must be set to true if authentication succeeds, otherwise false.
A peer is said to be <dfn>authenticated</dfn> when its [=authentication state=] is true.
Peer grant {#peer-grant}
------------------------------------
The user agent, with the user's consent, must [=acquire a local peer grant=] for an origin to get access to a peer.
Note: The user agent must get the user's explicit consent in order to grant an origin access to a peer. For enhanced privacy protection, the user agent must provide means to dismiss any related user interface and this action must not be detectable by script or have script-observable side-effects. The user interface may provide means to revoke the grant or to make the grant [=persisted=].
When asked to <dfn>acquire a local peer grant</dfn>, the user agent displays the [=known peers=] to the user through its native user interface. When the user selects a peer from the user interface, the user agent must check the selected peer is [=authenticated=], and run the [=authenticate a local peer=] algorithm otherwise, and set the [=peer grant state=] according to the user's explicit selection.
Protocol concepts {#protocol-concepts}
======================================
When asked to <dfn>establish local peer connection</dfn>, the user agent ...
A <dfn for="protocol">Local Peer-to-Peer session</dfn> represents an authenticated [[!RFC9000|QUIC]] connection as defined in [[!openscreenprotocol|Open Screen Protocol]] or OSP.
A [=Local Peer-to-Peer session=] has the following capabilities:
<table class="data" dfn-for="session">
<thead>
<tr>
<th>capability
<th>definition
</tr>
</thead>
<tbody>
<tr>
<td><dfn>advertise agent</dfn>
<td>[[!openscreenprotocol]]
[discovery](https://www.w3.org/TR/openscreenprotocol/#discovery)
</tr>
<tr>
<td><dfn>discover agents</dfn>
<td>[[!openscreenprotocol]]
[discovery](https://www.w3.org/TR/openscreenprotocol/#discovery)
</tr>
<tr>
<td><dfn>discover metadata</dfn>
<td>[[!openscreenprotocol]]
[transport](https://www.w3.org/TR/openscreenprotocol/#transport)
</tr>
<tr>
<td><dfn>authenticate an agent</dfn>
<td>[[!openscreenprotocol]]
[authentication](https://www.w3.org/TR/openscreenprotocol/#authentication)
</tr>
<tr>
<td>[=open a data channel=]
<td>[[#data-channel-extension]]
</tr>
<tr>
<td>[=send data on a channel=]
<td>[[#data-channel-extension]]
</tr>
<tr>
<td>[=open a WebTransport session=]
<td>[[#webtransport-extension]]
</tr>
</tbody>
</table>
Part of these capabilities are defined below as [protocol extensions](https://www.w3.org/TR/openscreenprotocol/#protocol-extensions) to the [[!openscreenprotocol|Open Screen Protocol]].
Data channel extension {#data-channel-extension}
------------------------------------------------
In order to signal support for this protocol extension, the agent should include the [=data-channels=] [=agent-capability=] as part of the [agent-info-response](https://www.w3.org/TR/openscreenprotocol/#agent-info-response) message exchanged during [=discover metadata=].
To <dfn>open a data channel</dfn> an agent may send a [=data-channel-open-request=] message on a new [[!RFC9000|QUIC]] stream. The [=Local Peer-to-Peer session=] must be authenticated. The message must contain the following values:
: channel-id
:: An ID number (between 0 and 65,534) which uniquely identifies the data channel. Must not be empty.
: label
:: a string that contains a name describing the data channel. These labels are not required to be unique.
: protocol
:: a string containing the name of the subprotocol in use. If no protocol was specified when the data channel was created, then this property's value is the empty string ("").
When the receiver receives the [=data-channel-open-request=], it should send back a [=data-channel-open-response=] message. The response must include the following:
: result
:: a code indicating success or failure, and the reason for the failure.
If the [=data-channel-open-response=] message indicates success, the data channel is considered open. Agents can now <dfn>send data on a channel</dfn> by sending [=data-frame=] messages on the same [[!RFC9000|QUIC]] stream the data channel was opened. The message must include the following:
: encoding-id
:: Determines the encoding of the data being sent. The values are specified as [=data-channel-encoding-id=]:
0: [=encoding-id-blob|Blob=];
1: [=encoding-id-string|String=];
2: [=encoding-id-array-buffer|ArrayBuffer=].
: payload
:: The binary representation of the data being sent.
WebTransport extension {#webtransport-extension}
------------------------------------------------
The protocol extension to [=send data on a channel=] provides an ergonomic way to send simple messages. An agent can [=open a WebTransport session=] for communication that requires low overhead and more granular streams control.
In order to signal support for this protocol extension, the agent should include the [=quick-transport=] [=agent-capability=] as part of the [agent-info-response](https://www.w3.org/TR/openscreenprotocol/#agent-info-response) message exchanged during [=discover metadata=].
An agent can <dfn>open a WebTransport session</dfn> by dialing a new [[!RFC9000|QUIC]] connection using the agent certificates established during [=authenticate an agent=]. During connection establishment, the ALPN token "q2q" must be used in the TLS handshake.
The capabilities of the Local WebTransport session are defined in [[!webtransport]].
Note: The WebTransport-over-QUIC protocol is yet to be defined. Potentially considering earlier work such as [draft-vvv-webtransport-quic](https://datatracker.ietf.org/doc/html/draft-vvv-webtransport-quic-02).
LP2PReceiver Interface {#lp2p-receiver}
================================================
<section algorithm="LP2PReceiver">
The <dfn interface>LP2PReceiver</dfn> interface allows advertising on the local network, enabling other peers to discover and connect.
<pre class="idl">
[Exposed=(Window,Worker), SecureContext]
interface LP2PReceiver : EventTarget {
constructor(optional LP2PReceiverOptions options = {});
attribute EventHandler onconnection;
Promise<undefined> start();
};
</pre>
LP2PReceiverOptions {#lp2p-receiver-options}
---------------------------------
<pre class="idl">
[Exposed=(Window,Worker), SecureContext]
dictionary LP2PReceiverOptions {
DOMString nickname;
};
</pre>
LP2PConnectionEvent {#lp2p-receiver-connection-event}
----------------------------------------------------
Issue: In general, when defining a new interface that inherits from Event please always ask feedback from the WHATWG or the W3C WebApps WG community. See [defining event interfaces](https://dom.spec.whatwg.org/#defining-event-interfaces).
<pre class="idl">
[Exposed=(Window,Worker), SecureContext]
interface LP2PConnectionEvent : Event {
constructor(DOMString type, LP2PConnectionEventInit connectionEventInitDict);
readonly attribute LP2PConnection connection;
};
dictionary LP2PConnectionEventInit : EventInit {
required LP2PConnection connection;
};
</pre>
Examples {#lp2p-receiver-examples}
---------------------------------
Example: Setting up a receiver to listen for connections:
<pre class='example' highlight='js'>
const receiver = new LP2PReceiver({
nickname: "example-receiver",
});
receiver.onconnection = e => {
console.log("Connection established!");
const conn = e.connection;
};
// Blocks until permission is received.
await receiver.start();
</pre>
Events {#lp2p-receiver-events}
------------------------------
The following event is [=fire an event|fired=] at the {{LP2PReceiver}} object:
<table class="data">
<thead>
<tr>
<th>Event name</th>
<th>Interface</th>
<th>Fired when…</th>
</tr>
</thead>
<tbody>
<tr>
<td><dfn event for="LP2PReceiver"><code>connection</code></dfn></td>
<td>{{LP2PConnectionEvent}}</td>
<td>An incoming connection is received.</td>
</tr>
</tbody>
</table>
Event handlers {#lp2p-receiver-event-handlers}
----------------------------------------------
The following are the <a>event handlers</a> (and their corresponding <a>event handler event types</a>) that must be supported, as <a>event handler IDL attributes</a>, by all objects implementing the [[#lp2p-receiver|LP2PReceiver]] interface:
<table class="data">
<thead>
<tr>
<th><a>event handler</a></th>
<th><a>event handler event type</a></th>
</tr>
</thead>
<tbody>
<tr>
<td><dfn attribute for="LP2PReceiver"><code>onconnection</code></dfn></td>
<td>{{LP2PReceiver/connection}}</td>
</tr>
</tbody>
</table>
</section>
<section algorithm="LP2PRequest">
The LP2PRequest Interface {#lp2p-request}
================================================
The <dfn interface>LP2PRequest</dfn> interface represents a request for a connection to another local peer.
<pre class="idl">
[Exposed=(Window,Worker), SecureContext]
interface LP2PRequest {
constructor(optional LP2PRequestOptions options = {});
Promise<LP2PConnection> start();
};
</pre>
LP2PRequestOptions {#lp2p-request-options}
---------------------------------
<pre class="idl">
[Exposed=(Window,Worker), SecureContext]
dictionary LP2PRequestOptions {
DOMString nickname;
};
</pre>
Examples {#lp2p-request-examples}
---------------------------------
Example: Setting up a request for a connection:
<pre class='example' highlight='js'>
const request = new LP2PRequest({
nickname: "example-request",
});
// Blocks until connection is received.
const conn = await request.start();
console.log("Connection established!");
</pre>
</section>
<section algorithm="LP2PConnection">
The LP2PConnection Interface {#lp2p-connection}
===============================================
The <dfn interface>LP2PConnection</dfn> interface represents a connection with another local peer.
<pre class="idl">
[Exposed=(Window,Worker), SecureContext]
interface LP2PConnection : EventTarget {
};
</pre>
</section>
<section algorithm="LP2PDataChannel">
The LP2PDataChannel Interface {#lp2p-data-channel}
==========================================
The LP2PDataChannel interface represents a bi-directional data channel between two peers. An LP2PDataChannel is created via a [factory method](#lp2p-data-channel-extensions) on a LP2PConnection object.
Note: The LP2PDataChannel interface is purposefully kept as close as possible to the [RTCDataChannel](https://www.w3.org/TR/webrtc/#rtcdatachannel) interface defined in [[!webrtc]]. The aim is to allow seamless transition of developers that are familiar with WebRTC as well as allowing libraries to easily work with both the [[!webrtc]] and LP2P API.
<pre class="idl">
[Exposed=(Window,Worker), SecureContext]
interface LP2PDataChannel : EventTarget {
constructor(USVString label,
optional LP2PDataChannelInit dataChannelDict = {});
readonly attribute USVString label;
readonly attribute USVString protocol;
readonly attribute unsigned short? id;
attribute EventHandler onopen;
attribute EventHandler onerror;
attribute EventHandler onclosing;
attribute EventHandler onclose;
undefined close();
attribute EventHandler onmessage;
attribute BinaryType binaryType;
undefined send((USVString or Blob or ArrayBuffer or ArrayBufferView) data);
};
</pre>
LP2PDataChannelInit {#lp2p-data-channel-init}
----------------------------------------------
<pre class="idl">
[Exposed=(Window,Worker), SecureContext]
dictionary LP2PDataChannelInit {
USVString protocol = "";
[EnforceRange] unsigned short id;
};
</pre>
Events {#lp2p-data-channel-events}
---------------------------------
The following event is [=fire an event|fired=] at the {{LP2PDataChannel}} object:
<table class="data">
<thead>
<tr>
<th>Event name</th>
<th>Interface</th>
<th>Fired when…</th>
</tr>
</thead>
<tbody>
<tr>
<td><dfn event for="LP2PDataChannel"><code>open</code></dfn></td>
<td>{{Event}}</td>
<td>The data channel is opened.</td>
</tr>
<tr>
<td><dfn event for="LP2PDataChannel"><code>message</code></dfn></td>
<td>{{MessageEvent}}[[html]]</td>
<td>An incoming message is received.</td>
</tr>
<tr>
<td><dfn event for="LP2PDataChannel"><code>error</code></dfn></td>
<td>{{Event}}</td>
<td>An error occurred.</td>
</tr>
<tr>
<td><dfn event for="LP2PDataChannel"><code>closing</code></dfn></td>
<td>{{Event}}</td>
<td>The data channel is closing.</td>
</tr>
<tr>
<td><dfn event for="LP2PDataChannel"><code>close</code></dfn></td>
<td>{{Event}}</td>
<td>The data channel is closed.</td>
</tr>
</tbody>
</table>
Data Channel Event handlers {#lp2p-data-channel-event-handlers}
---------------------------------------------------------------
The following are the <a>event handlers</a> (and their corresponding <a>event handler event types</a>) that must be supported, as <a>event handler IDL attributes</a>, by all objects implementing the [[#lp2p-connection|LP2PConnection]] interface:
<table class="data">
<thead>
<tr>
<th><a>event handler</a></th>
<th><a>event handler event type</a></th>
</tr>
</thead>
<tbody>
<tr>
<td><dfn attribute for="LP2PDataChannel"><code>onopen</code></dfn></td>
<td>{{LP2PDataChannel/open}}</td>
</tr>
<tr>
<td><dfn attribute for="LP2PDataChannel"><code>onmessage</code></dfn></td>
<td>{{LP2PDataChannel/message}}</td>
</tr>
<tr>
<td><dfn attribute for="LP2PDataChannel"><code>onerror</code></dfn></td>
<td>{{LP2PDataChannel/error}}</td>
</tr>
<tr>
<td><dfn attribute for="LP2PDataChannel"><code>onclosing</code></dfn></td>
<td>{{LP2PDataChannel/closing}}</td>
</tr>
<tr>
<td><dfn attribute for="LP2PDataChannel"><code>onclose</code></dfn></td>
<td>{{LP2PDataChannel/close}}</td>
</tr>
</table>
LP2PConnection Interface Extensions {#lp2p-data-channel-extensions}
-------------------------------------------------------------------
<pre class="idl">
[Exposed=(Window,Worker), SecureContext]
partial interface LP2PConnection {
LP2PDataChannel createDataChannel(USVString label,
optional LP2PDataChannelInit dataChannelDict = {});
attribute EventHandler ondatachannel;
};
</pre>
LP2PDataChannelEvent {#lp2p-data-channel-event}
------------------------------------------------
Issue: In general, when defining a new interface that inherits from Event please always ask feedback from the WHATWG or the W3C WebApps WG community. See [defining event interfaces](https://dom.spec.whatwg.org/#defining-event-interfaces).
<pre class="idl">
[Exposed=(Window,Worker), SecureContext]
interface LP2PDataChannelEvent : Event {
constructor(DOMString type, LP2PDataChannelEventInit DataChannelEventInitDict);
readonly attribute LP2PDataChannel channel;
};
dictionary LP2PDataChannelEventInit : EventInit {
required LP2PDataChannel channel;
};
</pre>
Extensions Events {#lp2p-data-channel-extensions-events}
------------------------------
The following event is [=fire an event|fired=] at the {{LP2PConnection}} object:
<table class="data">
<thead>
<tr>
<th>Event name</th>
<th>Interface</th>
<th>Fired when…</th>
</tr>
</thead>
<tbody>
<tr>
<td><dfn event for="LP2PConnection"><code>datachannel</code></dfn></td>
<td>{{LP2PDataChannelEvent}}</td>
<td>An incoming data channel is received.</td>
</tr>
</tbody>
</table>
Extensions Event handlers {#lp2p-data-channel-extensions-event-handlers}
------------------------------------------------------------------------
The following are the <a>event handlers</a> (and their corresponding <a>event handler event types</a>) that must be supported, as <a>event handler IDL attributes</a>, by all objects implementing the {{LP2PConnection}} interface:
<table class="data">
<thead>
<tr>
<th><a>event handler</a></th>
<th><a>event handler event type</a></th>
</tr>
</thead>
<tbody>
<tr>
<td><dfn attribute for="LP2PConnection"><code>ondatachannel</code></dfn></td>
<td>{{LP2PConnection/datachannel}}</td>
</tr>
</tbody>
</table>
</section>
<section algorithm="LP2PQuicTransport">
The LP2PQuicTransport Interface {#lp2p-quic-transport}
======================================================
<pre class="idl">
[Exposed=(Window,Worker), SecureContext]
interface LP2PQuicTransport : WebTransport {
constructor(LP2PConnection transport);
Promise<undefined> start();
};
</pre>
Examples {#lp2p-quic-transport-examples}
----------------------------------------
Example: Setting up a request for a connections:
<pre class='example' highlight='js'>
const request = new LP2PRequest({
nickname: "example-request",
});
const conn = await request.start();
const transport = new LP2PQuicTransport(conn);
// Blocks until transport is opened.
await transport.start();
</pre>
Refer to the [WebTransport examples](https://www.w3.org/TR/webtransport/#examples) for usage of a [[!webtransport]] object.
</section>
Examples {#examples}
====================
Data Channel Communication {#examples-data-channel}
---------------------------------------------------
<pre class='example' highlight='js'>
// Peer A
const receiver = new LP2PReceiver({
nickname: "Peer A",
});
receiver.onconnection = e => {
const conn = e.connection;
console.log("Receiver: Got a connection!");
conn.ondatachannel = e => {
const channel = e.channel;
channel.onmessage = e => {
const message = e.message;
console.log(\`Receiver: Received message: ${message}\`);
};
channel.send("Good day to you, requester!");
};
};
await receiver.start();
// Peer B
const request = new LP2PRequest({
nickname: "Peer B",
});
const conn = await request.start();
console.log("Requester: Got a connection!");
const channel = conn.createDataChannel("My Channel");
channel.onopen = e => {
channel.onmessage = e => {
const message = e.data;
console.log(\`Requester: Received message: ${message}\`);
};
channel.send("Good day to you, receiver!");
};
</pre>
Appendix A: OSP Extension Messages {#appendix-a}
================================================
The following messages are defined according to and as an extension to the [[!openscreenprotocol|Open Screen Protocol]] [Messages](https://www.w3.org/TR/openscreenprotocol/#appendix-a).
Note: The type keys and capability IDs for these extensions are not officially registered yet. They will be registered as this specification matures.
<pre class="data" highlight='cddl'>
<dfn>agent-capability</dfn> = &(
<dfn>data-channels</dfn>: 11OO
<dfn>quick-transport</dfn>: 12OO
)
<dfn>data-channel-encoding-id</dfn> = &(
<dfn>encoding-id-blob</dfn>: 0
<dfn>encoding-id-string</dfn>: 1
<dfn>encoding-id-array-buffer</dfn>: 2
)
; type key 24
<dfn>data-frame</dfn> = {
0: data-channel-encoding-id ; encoding-id
4: bytes ; payload
}
; type key 1101
<dfn>data-channel-open-request</dfn> = {
request
1: uint ; channel-id
2: text ; label
3: text ; protocol
}
; type key 1102
<dfn>data-channel-open-response</dfn> = {
response
1: &result ; result
}
</pre>