Local Peer-to-Peer API

Draft Community Group Report,

This version:
https://WICG.github.io/local-peer-to-peer/
Issue Tracking:
GitHub
Inline In Spec
Editors:
(Intel)
(Intel)
(Twintag)
(Intel)
Tests:
web-platform-tests local-peer-to-peer/ (ongoing work)

Abstract

Local Peer-to-Peer is a Web platform API proposal for local communication between browsers without the aid of a server.

Status of this document

This specification was published by the Web Platform Incubator Community Group. It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. Learn more about W3C Community and Business Groups.

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.

1. Introduction

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.

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. See also Use Cases.

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. While not described here, the API is expected to be implementable on top of other transports when technically feasible.

2. Terminology

The term local communication medium refers to a communication medium that provides a local, direct communication channel between the communicating devices. This is a purposefully broad term that covers any medium that can be used to establish a an authenticated, streams-based transport between the devices. Examples may include but are not limited to: a wired or wireless local area network, a Thread network, Bluetooth Low Energy or Wi-Fi Direct. This spec will not mandate which underlying technologies must be supported.

The term local communication refers to data communication over the local communication medium.

The term communication medium topology refers to the composition of the local communication medium which may include sensitive information such as IP or other address information or the number of devices connected to the medium.

3. 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):

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 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:

<iframe src="https://third-party.com" allow="local-peer-to-peer"/></iframe>

Alternatively, the Local Peer-to-Peer API can be disabled completely by specifying the permissions policy in a HTTP response header:

Permissions-Policy: local-peer-to-peer=()

See [PERMISSIONS-POLICY] for more details.

4. 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 peer is an equal participant in the local communication. These nodes can communicate without the need for a central coordination by a server.

A user agent has an associated local peer-to-peer manager 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 the communication medium topology.

4.1. 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 known peers map, an ordered map of known peers. Each known peer is a peer that has an associated authentication state and peer grant state. 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.

See also related [Issue #wicg/local-peer-to-peer#24]

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 Open Screen Protocol Persistent State rules. Such a peer or its state is said to be persisted.

4.2. Peer advertisement

The user agent can make itself discoverable by advertising using the 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 access to the origin that initiated peer advertisement.

4.3. Peer discovery

The user agent can discover local peers using the discover agents capability.

When asked to start local peer discovery, the user agent discovers local peers using the 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.

4.4. Peer authentication

The user agent can initiate authentication with a peer using the authenticate an agent capability.

When asked to authenticate a local peer, the user agent must initiate authentication with a local peer using the 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 authenticated when its authentication state is true.

4.5. 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 acquire a local peer grant, 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.

5. Protocol concepts

When asked to establish local peer connection, the user agent ...

A Local Peer-to-Peer session represents an authenticated QUIC connection as defined in Open Screen Protocol or OSP.

A Local Peer-to-Peer session has the following capabilities:

capability definition
advertise agent [openscreenprotocol] discovery
discover agents [openscreenprotocol] discovery
discover metadata [openscreenprotocol] transport
authenticate an agent [openscreenprotocol] authentication
open a data channel § 5.1 Data channel extension
send data on a channel § 5.1 Data channel extension
open a WebTransport session § 5.2 WebTransport extension

Part of these capabilities are defined below as protocol extensions to the Open Screen Protocol.

5.1. 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 message exchanged during discover metadata.

To open a data channel an agent may send a data-channel-open-request message on a new 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 send data on a channel by sending data-frame messages on the same 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: Blob; 1: String; 2: ArrayBuffer.

payload

The binary representation of the data being sent.

5.2. 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 message exchanged during discover metadata.

An agent can open a WebTransport session by dialing a new 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.

6. Local HTTPS

Authentication establishes a mutual trust anchor between peers on the local communication medium. This trust anchor can also be used to validate certificates used by HTTP servers on the local communication medium. An Open Screen Protocol agent certificate can be identified by the common name of its subject ending in "._openscreen._udp". When a user agent loads a webpage and finds an agent certificate in the certificate chain, it can use it as a trust anchor for authentication of the server. If the corresponding agent is not authenticated, the user agent should prompt the user to authenticate the agent before proceeding with certificate validation.

6.1. Endpoint discovery

If a peer is authenticated, it may advertize one or more HTTPS endpoints it provides. A user agent may display these to the user to connect to servers on the local communication medium without knowledge of the corresponding hostname and/or IP address.

define endpoint-info messages

7. LP2PReceiver Interface

The LP2PReceiver interface allows advertising on the local communication medium, enabling other peers to discover and connect.

[Exposed=(Window,Worker), SecureContext]
interface LP2PReceiver : EventTarget {
  constructor(optional LP2PReceiverOptions options = {});
  attribute EventHandler onconnection;
  Promise<undefined> start();
};

7.1. LP2PReceiverOptions

[Exposed=(Window,Worker), SecureContext]
dictionary LP2PReceiverOptions {
    DOMString nickname;
};

7.2. LP2PConnectionEvent

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.

[Exposed=(Window,Worker), SecureContext]
interface LP2PConnectionEvent : Event {
    constructor(DOMString type, LP2PConnectionEventInit connectionEventInitDict);
    readonly attribute LP2PConnection connection;
};

dictionary LP2PConnectionEventInit : EventInit {
    required LP2PConnection connection;
};

7.3. Events

The following event is fired at the LP2PReceiver object:

Event name Interface Fired when…
connection LP2PConnectionEvent An incoming connection is received.

7.4. Event handlers

The following are the event handlers (and their corresponding event handler event types) that must be supported, as event handler IDL attributes, by all objects implementing the LP2PReceiver interface:

event handler event handler event type
onconnection connection

7.5. Examples

Example: Setting up a receiver to listen for connections:

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();

8. The LP2PRequest Interface

The LP2PRequest interface represents a request for a connection to another local peer.

[Exposed=(Window,Worker), SecureContext]
interface LP2PRequest {
    constructor(optional LP2PRequestOptions options = {});
    Promise<LP2PConnection> start();
};

8.1. LP2PRequestOptions

[Exposed=(Window,Worker), SecureContext]
dictionary LP2PRequestOptions {
    DOMString nickname;
};

8.2. Examples

Example: Setting up a request for a connection:

const request = new LP2PRequest({
    nickname: "example-request",
});

// Blocks until connection is received.
const conn = await request.start();
console.log("Connection established!");

9. The LP2PConnection Interface

The LP2PConnection interface represents a connection with another local peer.

[Exposed=(Window,Worker), SecureContext]
interface LP2PConnection : EventTarget {
};

9.1. LP2PQuicTransport Interface Extensions

This LP2PQuicTransport extension allows opening a QuicTransport using an existing connection. In this case, the already established permission and grants should be used.

[Exposed=(Window,Worker), SecureContext]
partial interface LP2PQuicTransport {
  constructor(LP2PConnection connection,
              optional LP2PQuicTransportInit quicTransportDict = {});
};

9.2. Examples

Example: Open a LP2PQuicTransport using an existing connection as receiver:

const receiver = new LP2PReceiver({
    nickname: "example-receiver",
});
receiver.onconnection = async e => {
    const conn = e.connection;
    
    const transport = new LP2PQuicTransport(conn);

    // Blocks until transport is ready.
    await transport.ready;
};

// Blocks until permission is received.
await receiver.start();

Example: Open a LP2PQuicTransport using an existing connection as requester:

const request = new LP2PRequest({
    nickname: "example-request",
});

// Blocks until connection is received.
const conn = await request.start();

const transport = new LP2PQuicTransport(conn);

// Blocks until transport is ready.
await transport.ready;

10. The LP2PDataChannel Interface

The LP2PDataChannel interface represents a bi-directional data channel between two peers. An LP2PDataChannel is created via a factory method on a LP2PConnection object.

Note: The LP2PDataChannel interface is purposefully kept as close as possible to the 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.

[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);
};

10.1. LP2PDataChannelInit

[Exposed=(Window,Worker), SecureContext]
dictionary LP2PDataChannelInit {
  USVString protocol = "";
  [EnforceRange] unsigned short id;
};

10.2. Events

The following event is fired at the LP2PDataChannel object:

Event name Interface Fired when…
open Event The data channel is opened.
message MessageEvent[html] An incoming message is received.
error Event An error occurred.
closing Event The data channel is closing.
close Event The data channel is closed.

10.3. Event handlers

The following are the event handlers (and their corresponding event handler event types) that must be supported, as event handler IDL attributes, by all objects implementing the LP2PDataChannel interface:

event handler event handler event type
onopen open
onmessage message
onerror error
onclosing closing
onclose close

10.4. LP2PConnection Interface Extensions

[Exposed=(Window,Worker), SecureContext]
partial interface LP2PConnection {
  LP2PDataChannel createDataChannel(USVString label,
                                    optional LP2PDataChannelInit dataChannelDict = {});
  attribute EventHandler ondatachannel;
};

10.5. LP2PDataChannelEvent

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.

[Exposed=(Window,Worker), SecureContext]
interface LP2PDataChannelEvent : Event {
  constructor(DOMString type, LP2PDataChannelEventInit DataChannelEventInitDict);
  readonly attribute LP2PDataChannel channel;
};

dictionary LP2PDataChannelEventInit : EventInit {
    required LP2PDataChannel channel;
};

10.6. Extensions Events

The following event is fired at the LP2PConnection object:

Event name Interface Fired when…
datachannel LP2PDataChannelEvent An incoming data channel is received.

10.7. Extensions Event handlers

The following are the event handlers (and their corresponding event handler event types) that must be supported, as event handler IDL attributes, by all objects implementing the LP2PConnection interface:

event handler event handler event type
ondatachannel datachannel

10.8. Examples

Example: Receive a LP2PDataChannel on an existing connection as receiver:

const receiver = new LP2PReceiver({
    nickname: "example-receiver",
});

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.data;
            console.log(`Receiver: Received message: ${message}`);
        };

        channel.send("Good day to you, requester!");
    };
};

await receiver.start();

Example: Create a LP2PDataChannel on an existing connection as requester:

const request = new LP2PRequest({
    nickname: "example-request",
});

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!");
};

11. The LP2PQuicTransport Interface

The LP2PQuicTransport Interface allows opening a [webtransport] between peers. If the LP2PRequest or LP2PReceiver is not yet started, it must be started when the LP2PQuicTransport is constructed.

[Exposed=(Window,Worker), SecureContext]
interface LP2PQuicTransport : WebTransport {
  constructor((LP2PRequest or LP2PReceiver) source,
              optional LP2PQuicTransportInit quicTransportDict = {});
};

[Exposed=(Window,Worker), SecureContext]
dictionary LP2PQuicTransportInit {
};

Define LP2PQuicTransportInit as needed using WebTransportOptions as reference.

11.1. LP2PQuicTransportListener Interface

The LP2PQuicTransportListener Interface allows listening for incoming [webtransport] transports. If the LP2PRequest or LP2PReceiver is not yet started, it must be started when the LP2PQuicTransport is constructed.

[Exposed=(Window,Worker), SecureContext]
partial interface LP2PQuicTransportListener {
  constructor((LP2PRequest or LP2PReceiver) source,
              optional LP2PQuicTransportListenerInit quicTransportListenerDict = {});
  readonly attribute Promise<undefined> ready;
  /* a ReadableStream of LP2PQuicTransport objects */
  readonly attribute ReadableStream incomingTransports;
};

[Exposed=(Window,Worker), SecureContext]
dictionary LP2PQuicTransportListenerInit {
};

Define LP2PQuicTransportListenerInit as needed using WebTransportOptions as reference.

11.2. Examples

Example: Setting up a request for a LP2PQuicTransport:

const request = new LP2PRequest({
    nickname: "example-request",
});

const transport = new LP2PQuicTransport(request);

// Blocks until transport is ready.
await transport.ready;

Example: Receiving a LP2PQuicTransport:

const receiver = new LP2PReceiver({
    nickname: "example-receiver",
});

const listener = new LP2PQuicTransportListener(receiver);

for await (const transport of listener.incomingTransports) {
  // Blocks until transport is ready.
  await transport.ready;
}

Refer to the WebTransport examples for usage of a [webtransport] object.

12. Security and privacy considerations

12.1. Open Screen Protocol

The Local Peer-to-Peer API is meant to be implementable on the Open Screen Protocol. The Security and Privacy considerations of the Open Screen Protocol must therefore be considered when implementing this API.

12.2. Personally identifiable information

The peer attributes, such as the nickname and device model, are provided to give minimal context to a connected peer. This information could be used in conjunction with other information for fingerprinting the user. However, this information is only available to an origin after it has been authenticated and a user has given explicit consent to make the connection to the remote peer.

No information is exposed to the origin during service discovery. No IP information is exposed to an origin. This is fully managed by the user agent.

Refine peer attributes, related: [Issue #WICG/local-peer-to-peer#15]

12.3. User interface guidelines

When the user is asked to grant permission to connect to a peer, the user agent should make it clear what origin the request is coming from.

Define filtering to provide additional context, related: [Issue #WICG/local-peer-to-peer#15]

12.4. Impact on same-origin policy

This document extends the Web platform with the ability to set up real-time, direct communication between browsers and other devices, including other browsers, within a local communication medium.

This means that data and media can be shared between applications running in different browsers, or between an application running in the browser and another user agent that is not a browser such as a headless service provided by a smart TV or smart fridge. This extends the usual barriers in the Web’s security model that prevents sending data between entities with different origins.

12.5. Device Access

The Local Peer-to-Peer API requires user permission for a page to access any peers. The API uses purpose-fit protocols for data communication. It cannot be used to connect to raw sockets or unknowing HTTP servers. In addition, a user must acquire a local peer grant by explicitly providing consenting for an origin to connect to a peer. In addition, a user must authenticate a local peer before use.

12.6. Persistent State

The persisted state considerations of the Open Screen Protocol must be followed when implementing this API.

12.7. Secure Contexts

The Local Peer-to-Peer API must only be provided in a secure context.

Appendix A: OSP Extension Messages

The following messages are defined according to and as an extension to the Open Screen Protocol Messages.

Note: The type keys and capability IDs for these extensions are not officially registered yet. They will be registered as this specification matures.

agent-capability = &(
  data-channels: 11OO
  quick-transport: 12OO
)

data-channel-encoding-id = &(
  encoding-id-blob: 0
  encoding-id-string: 1
  encoding-id-array-buffer: 2
)

; type key 24
data-frame = {
  0: data-channel-encoding-id ; encoding-id
  4: bytes ; payload
}

; type key 1101
data-channel-open-request = {
  request
  1: uint ; channel-id
  2: text ; label
  3: text ; protocol
}

; type key 1102
data-channel-open-response = {
  response
  1: &result ; result
}

Conformance

Document conventions

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example", like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with class="note", like this:

Note, this is an informative note.

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[DOM]
Anne van Kesteren. DOM Standard. Living Standard. URL: https://dom.spec.whatwg.org/
[FileAPI]
Marijn Kruisselbrink. File API. URL: https://w3c.github.io/FileAPI/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. Living Standard. URL: https://infra.spec.whatwg.org/
[OPENSCREENPROTOCOL]
Mark Foltz. Open Screen Protocol. URL: https://w3c.github.io/openscreenprotocol/
[PERMISSIONS-POLICY]
Ian Clelland. Permissions Policy. URL: https://w3c.github.io/webappsec-permissions-policy/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[RFC9000]
J. Iyengar, Ed.; M. Thomson, Ed.. QUIC: A UDP-Based Multiplexed and Secure Transport. May 2021. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc9000
[STREAMS]
Adam Rice; et al. Streams Standard. Living Standard. URL: https://streams.spec.whatwg.org/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard. Living Standard. URL: https://webidl.spec.whatwg.org/
[WEBRTC]
Cullen Jennings; et al. WebRTC: Real-Time Communication in Browsers. URL: https://w3c.github.io/webrtc-pc/
[WEBSOCKETS]
Adam Rice. WebSockets Standard. Living Standard. URL: https://websockets.spec.whatwg.org/
[WEBTRANSPORT]
Bernard Aboba; Nidhi Jaju; Victor Vasiliev. WebTransport. URL: https://w3c.github.io/webtransport/

IDL Index

[Exposed=(Window,Worker), SecureContext]
interface LP2PReceiver : EventTarget {
  constructor(optional LP2PReceiverOptions options = {});
  attribute EventHandler onconnection;
  Promise<undefined> start();
};

[Exposed=(Window,Worker), SecureContext]
dictionary LP2PReceiverOptions {
    DOMString nickname;
};

[Exposed=(Window,Worker), SecureContext]
interface LP2PConnectionEvent : Event {
    constructor(DOMString type, LP2PConnectionEventInit connectionEventInitDict);
    readonly attribute LP2PConnection connection;
};

dictionary LP2PConnectionEventInit : EventInit {
    required LP2PConnection connection;
};

[Exposed=(Window,Worker), SecureContext]
interface LP2PRequest {
    constructor(optional LP2PRequestOptions options = {});
    Promise<LP2PConnection> start();
};

[Exposed=(Window,Worker), SecureContext]
dictionary LP2PRequestOptions {
    DOMString nickname;
};

[Exposed=(Window,Worker), SecureContext]
interface LP2PConnection : EventTarget {
};

[Exposed=(Window,Worker), SecureContext]
partial interface LP2PQuicTransport {
  constructor(LP2PConnection connection,
              optional LP2PQuicTransportInit quicTransportDict = {});
};

[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);
};

[Exposed=(Window,Worker), SecureContext]
dictionary LP2PDataChannelInit {
  USVString protocol = "";
  [EnforceRange] unsigned short id;
};

[Exposed=(Window,Worker), SecureContext]
partial interface LP2PConnection {
  LP2PDataChannel createDataChannel(USVString label,
                                    optional LP2PDataChannelInit dataChannelDict = {});
  attribute EventHandler ondatachannel;
};

[Exposed=(Window,Worker), SecureContext]
interface LP2PDataChannelEvent : Event {
  constructor(DOMString type, LP2PDataChannelEventInit DataChannelEventInitDict);
  readonly attribute LP2PDataChannel channel;
};

dictionary LP2PDataChannelEventInit : EventInit {
    required LP2PDataChannel channel;
};

[Exposed=(Window,Worker), SecureContext]
interface LP2PQuicTransport : WebTransport {
  constructor((LP2PRequest or LP2PReceiver) source,
              optional LP2PQuicTransportInit quicTransportDict = {});
};

[Exposed=(Window,Worker), SecureContext]
dictionary LP2PQuicTransportInit {
};

[Exposed=(Window,Worker), SecureContext]
partial interface LP2PQuicTransportListener {
  constructor((LP2PRequest or LP2PReceiver) source,
              optional LP2PQuicTransportListenerInit quicTransportListenerDict = {});
  readonly attribute Promise<undefined> ready;
  /* a ReadableStream of LP2PQuicTransport objects */
  readonly attribute ReadableStream incomingTransports;
};

[Exposed=(Window,Worker), SecureContext]
dictionary LP2PQuicTransportListenerInit {
};

Issues Index

See also related [Issue #wicg/local-peer-to-peer#24]
define endpoint-info messages
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.
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.
Define LP2PQuicTransportInit as needed using WebTransportOptions as reference.
Define LP2PQuicTransportListenerInit as needed using WebTransportOptions as reference.
Refine peer attributes, related: [Issue #WICG/local-peer-to-peer#15]
Define filtering to provide additional context, related: [Issue #WICG/local-peer-to-peer#15]