This specification defines an abstraction for establishing and operating a direct peer-to-peer connection between two participants. It defines the offer-and-contract exchange, the connection lifecycle, application message transfer, media publication, media observation, failure conditions, and automatic renegotiation.
This specification is maintained alongside a reference implementation.
You can check the reference implementation docs:
See it in action:
Or use the reference implementation:
The abstraction defined here is built on the peer connection, data channel, session description, and media-capture concepts defined by [[WEBRTC]], [[MEDIACAPTURE_STREAMS]], and [[SCREEN_CAPTURE]].
One participant creates an offer. The other participant accepts that offer and returns a corresponding answer inside a role-specific contract copy. Once each participant holds the appropriate contract copy, each participant can construct a live connection and exchange application messages over a data channel.
| Concept | Meaning |
|---|---|
peer |
One of the two participants in a connection. |
offeror |
The peer that creates an offer. |
offeree |
The peer that accepts an offer. |
offer identifier |
A text value that correlates an offer with the contract copies derived from that offer. |
connection |
A live association built from one role-specific contract copy. |
application message |
Any MessagePack-encodable value that is not a reserved internal signal. |
presentation handle |
An implementation-defined value that represents a renderable view of visual media. |
polite peer |
The peer that yields during renegotiation glare. The offeree is the polite peer. |
impolite peer |
The peer that may ignore a colliding renegotiation offer. The offeror is the impolite peer. |
An Offer record transports the local session description
created by the offeror.
| Member | Type | Meaning |
|---|---|---|
offerId |
String | The offer identifier. |
description |
Session description | The local offer description after ICE gathering completes. |
| Member | Type | Meaning |
|---|---|---|
offerId |
String | The offer identifier. |
role |
String | The literal value "offeror". |
answer |
Session description | The local answer created by the offeree. |
| Member | Type | Meaning |
|---|---|---|
offerId |
String | The offer identifier. |
role |
String | The literal value "offeree". |
| Concept | Meaning |
|---|---|
Contract |
Either an offeror contract copy or an offeree contract copy. |
ContractCopies |
A record with members offeror and
offeree, containing the two role-specific contract
copies derived from one accepted offer.
|
The following record shape is reserved for internal renegotiation traffic carried over the data channel:
{
__anbs_peer2peer: 'renegotiate-offer' | 'renegotiate-answer',
description: SessionDescriptionInit
}
A received payload that matches this shape MUST be processed as an internal signal rather than as an application message.
A conforming implementation MUST maintain the following reserved state:
| State | Meaning |
|---|---|
pending offers |
A map from offer identifier to a reserved peer connection and its locally created data channel. |
accepted offers |
A map from offer identifier to a reserved peer connection and a pending incoming data channel. |
shared user-media source |
A cached media source reused by microphone and camera publication. |
shared display-media source |
A cached media source reused by screen publication. |
shared local camera presentation |
A shared presentation handle associated with local camera media. |
shared local screen presentation |
A shared presentation handle associated with local screen media. |
A conforming implementation MUST surface failure conditions when an operation defined by this specification cannot complete.
The representation of those failures is implementation-defined. A conforming implementation MAY expose error codes, error objects, exceptions, rejected promises, events, or equivalent diagnostics.
| Failure condition | Meaning |
|---|---|
| Data channel error before readiness |
The data channel emitted an error indication before reaching the
"open" state.
|
| Data channel close before readiness |
The data channel closed before reaching the
"open" state.
|
| Incoming data channel unavailable |
The peer connection reached "failed" or
"closed" before an incoming data channel was
observed.
|
| Application message sent before readiness | An application message was sent before the data channel was available and open. |
| Unknown contract state | Connection construction was attempted with a contract whose reserved local state did not exist. |
| Missing local description | A local offer or answer description was absent after ICE gathering completed. |
Each connection exposes a connection-scoped event surface with the following event kinds:
| Event kind | Payload | When emitted |
|---|---|---|
message |
Decoded application message | When a received MessagePack payload does not match the reserved internal-signal shape. |
camera |
Presentation handle | When remote user-media is associated with a camera presentation. |
screen |
Presentation handle | When remote display media is associated with a screen presentation. |
| Operation | Purpose |
|---|---|
makeOffer(additionalIceServers?) |
Create a new offer and reserve offeror-side state. |
acceptOffer(offer, additionalIceServers?) |
Accept an offer and derive the paired contract copies. |
Connection construction from Contract |
Create a live connection from one contract copy. |
ready() |
Wait until the data channel is open. |
sendMessage(message) |
Send an application message over the data channel. |
closeConnection() |
Close the channel and the underlying peer connection. |
shareMicrophone() |
Publish microphone media. |
stopSharingMicrophone() |
Stop publishing microphone media. |
shareCamera() |
Publish camera media. |
stopSharingCamera() |
Stop publishing camera media. |
shareScreen() |
Publish display media. |
stopSharingScreen() |
Stop publishing display media. |
Connection-establishment operations MAY apply implementation-defined internal ICE server defaults.
If supplementary ICE server configuration is not supplied, it MUST be treated as empty. If supplementary ICE server configuration is supplied, it MUST be incorporated in addition to any internal defaults.
The peer connection MUST use iceTransportPolicy equal to
"all".
"data".MISSING_LOCAL_DESCRIPTION.
Offer record containing the offer identifier
and the local description.
offer.description.
MISSING_LOCAL_DESCRIPTION.
offer.offerId.
ContractCopies record whose
offeror member is an offeror contract copy and whose
offeree member is an offeree contract copy.
Constructing a connection consumes exactly one reserved state entry. A contract copy MUST NOT be reusable after it has been consumed.
"offeror", look up the pending
offer state using contract.offerId.
UNKNOWN_PEER_CONTRACT.
contract.answer."offeree", look up the
accepted-offer state using contract.offerId.
UNKNOWN_PEER_CONTRACT.
The ready() operation returns a promise-like result that
resolves only after the live data channel reaches the
"open" state.
If the channel is already open, the result MUST resolve immediately.
The result MUST reject with:
CHANNEL_NOT_AVAILABLE if the peer connection reaches
"failed" or "closed" before an incoming
data channel is observed;
CHANNEL_CLOSED if the channel closes before opening; or
CHANNEL_ERROR if the channel emits an error indication
before opening.
The sendMessage(message) operation MUST verify that a
live data channel exists and that its ready state is
"open".
If either condition is false, the operation MUST throw
CONNECTION_NOT_READY.
Otherwise, the operation MUST encode message using
MessagePack as defined by [[MSGPACK]] and send the resulting bytes on
the live data channel.
A connection MUST expose the connection-scoped event surface through an observer registration mechanism.
A conforming implementation MAY realize that mechanism using the
EventTarget model defined by [[DOM]], including
addEventListener() and
removeEventListener(), or an equivalent observer API.
In either case, observers MUST be able to subscribe to and unsubscribe from each event kind defined by this specification.
The closeConnection() operation MUST close the live data
channel if one has been attached and MUST then close the underlying
peer connection.
message notification whose payload is
the decoded value.
If a current user-audio sender exists, remove it from the peer connection and clear the stored sender. Otherwise, do nothing.
If a current user-video sender exists, remove it from the peer connection and clear the stored sender. Otherwise, do nothing.
If a current display-video sender exists, remove it from the peer connection and clear the stored sender. If a current display-audio sender exists, remove it from the peer connection and clear the stored sender. If neither sender exists, do nothing.
camera, and stop.
screen.
The data channel is used as the transport for internal renegotiation.
"renegotiate-offer" and whose description is the new
local offer description.
"renegotiate-answer", mark the connection as currently
applying a remote answer.
"renegotiate-offer", then: create a fresh local answer
description, wait until ICE gathering completes, and send a reserved
internal signal whose discriminator is
"renegotiate-answer" and whose description is the new
local answer description.
Offer and answer values may contain ICE candidates and related network metadata. Signaling paths should therefore be treated as sensitive.
Confidentiality and integrity for the peer-to-peer media and data path depend on the underlying WebRTC stack.
Media capture operations rely on ambient permission and policy controls supplied by the environment.