Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(webrtc): add WebRTC (prev. browser-to-browser) spec #497

Merged
merged 58 commits into from
Apr 12, 2023
Merged
Changes from 8 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
58acd82
webrtc/: Initialize browser-to-browser specification
mxinden Dec 15, 2022
35841c3
Document that Noise handshake is not required
mxinden Jan 4, 2023
c41007e
Discourage certificate reuse
mxinden Jan 5, 2023
29d166b
Draft signaling protocol
mxinden Jan 5, 2023
5615e2f
Document outstanding role assignment
mxinden Jan 5, 2023
cc1a8f1
Change format to one line per sentence
mxinden Jan 5, 2023
78fae26
Document open question on advertising support in Multiaddr
mxinden Jan 16, 2023
4fa8da4
Extend signaling protocol section and process
mxinden Jan 16, 2023
7da6004
Define role distribution among A and B
mxinden Jan 18, 2023
badcb1f
Detail STUN section
mxinden Jan 18, 2023
d92e673
Document relaying on failure to be out of scope
mxinden Jan 18, 2023
1b86e62
Remove trickle candidate alternative
mxinden Jan 18, 2023
79ee3b0
Document non-browser behind NAT and/or firewall
mxinden Jan 18, 2023
e384839
Minor edits
mxinden Jan 18, 2023
b5d82c4
Mark proto fields as optional
mxinden Jan 18, 2023
6c139b6
Move mention of existing (deprecated) protocols
mxinden Jan 18, 2023
74c1bc0
Document not using DCUtR
mxinden Jan 18, 2023
619e4e6
Fix STUN section link
mxinden Jan 18, 2023
aa62e92
Fix signaling protocol link
mxinden Jan 18, 2023
fa79a13
Add uvarint link
mxinden Jan 18, 2023
f5ea248
refactor(proto): Rename to SDP_{OFFER,ANSWER} and ICE_CANDIDATE
mxinden Jan 23, 2023
39ed458
Update webrtc/browser-to-browser.md
mxinden Jan 23, 2023
2408db9
Use proto3
mxinden Jan 24, 2023
e1e6a0c
Make explicit that A and B might as well be non-browser
mxinden Jan 24, 2023
30b0d53
Document reset on failure
mxinden Jan 24, 2023
ebc3d5c
Remove sub heading implied by document title
mxinden Jan 24, 2023
6406947
Document latency of relayed connection
mxinden Jan 24, 2023
5a9e553
Rename signaling protocol to `/webrtc-signaling`
mxinden Feb 15, 2023
2d6ef30
Contrast to DCUtR protocol for two non-browsers
mxinden Feb 15, 2023
4255246
Reword TLS certificate validation sentence
mxinden Feb 15, 2023
e99d582
Have A initiate the signaling protocol
mxinden Feb 21, 2023
c09392b
Document advertisement via /webrtc-direct
mxinden Feb 21, 2023
0a0a30a
Rename to /webrtc-w3c and /webrtc-w3c-signaling
mxinden Feb 27, 2023
165bd52
Use webtransport instead of plain quic for relay
mxinden Feb 27, 2023
ec68ec3
Rename title to WebRTC W3C
mxinden Mar 2, 2023
c5b36d2
Introduce naming of w3c in motivation
mxinden Mar 2, 2023
e119c1d
Update webrtc/browser-to-browser.md
mxinden Mar 2, 2023
5a48183
Document the origin of `RTCPeerConnection
mxinden Mar 2, 2023
3744342
Rephrase browser being one example of a constrained env
mxinden Mar 3, 2023
4cca1f1
Restructure documents with browser-to-server and w3c subdocuments
mxinden Mar 3, 2023
d63368a
Fix indentation
mxinden Mar 3, 2023
25e5774
Introduce private-to-private rename
mxinden Mar 10, 2023
e171330
Rename webrtc to webrtc-direct and webrtc-private-to-private to webrtc
mxinden Mar 23, 2023
96529cf
Merge branch 'master' of https://github.com/libp2p/specs into webrtc-…
mxinden Mar 23, 2023
610a3dd
Rename to "Shared concepts"
mxinden Mar 27, 2023
249ff1b
Don't expand on relayed address in example
mxinden Mar 27, 2023
8c4d450
Remove mention of constrained w3c api
mxinden Mar 27, 2023
ad2549b
Stress that _B_ creates RTCPeerConnection after incoming stream
mxinden Mar 27, 2023
2b506ab
"Cannot"
mxinden Mar 27, 2023
01f78a7
Require A to support B initiating the signaling process
mxinden Mar 27, 2023
fca22b3
Expand on trickle ICE
mxinden Mar 27, 2023
669e0c3
Port for a webrtc connection
mxinden Mar 27, 2023
7a2bf0a
Reword dedicated STUN
mxinden Mar 27, 2023
3425f01
Replace note with not necessary
mxinden Mar 27, 2023
554e3db
Wording on STUN
mxinden Mar 30, 2023
2cd2f19
Fix typo in webrtc/webrtc.md
mxinden Apr 9, 2023
1160982
Update spec headers
mxinden Apr 12, 2023
63b141d
Signal in root readme that there is more than one webrtc
mxinden Apr 12, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions webrtc/browser-to-browser.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# WebRTC browser-to-browser
mxinden marked this conversation as resolved.
Show resolved Hide resolved

| Lifecycle Stage | Maturity | Status | Latest Revision |
|-----------------|---------------|--------|-----------------|
| 1A | Working Draft | Active | r0, 2022-12-15 |

## Motivation

1. **Hole punching in the browser**: Enable two browsers or a browser and a server node to connect even though one or both are behind a NAT / firewall.

TODO: Doucment use-case where A is a browser and B is a non-browser but behind firewall and/or NAT.

## Connection Establishment

### Browser to Browser

Scenario: Browser _A_ wants to connect to Browser node _B_ with the help of server node _R_.
Both _A_ and _B_ can not listen for incoming connections due to the restriction of the browser platform and being behind a NAT and/or firewall.

TODO: Define which node on a relayed connection is _A_ and which one is _B_, i.e. which one initiates (offer) and which one responds (answer).

1. _A_ and _B_ establish a relayed connection through some protocol, e.g. the Circuit Relay v2 protocol.
Note that further steps depend on the relayed connection to be authenticated, i.e. that data send on the relayed connection can be trusted.
mxinden marked this conversation as resolved.
Show resolved Hide resolved

2. _A_ creates an `RTCPeerConnection`.
See [#STUN] on what STUN servers to configure at creation time.
_A_ creates an SDP offer via `RTCPeerConnection.createOffer()`.
_A_ initiates the signaling protocol to _B_ via the relayed connection from (1), see [#Signaling protocol] and sends the offer to _B_.

3. _B_ creates an `RTCPeerConnection`.
Again see [#STUN] on what STUN servers to configure at creation time.
_B_ receives _A_'s offer send in (2) via the signaling protocol stream and provides the offer to its `RTCPeerConnection` via `RTCPeerConnection.setRemoteDescription`.
_B_ then creates an answer via `RTCPeerConnection.createAnswer` and sends it to _A_ via the existing signaling protocol stream (see [#signaling protocol]).

4. _A_ receives _B_'s answer via the signaling protocol stream and sets it locally via `RTCPeerConnection.setRemoteDescription`.

5. _A_ and _B_ send their local ICE candidates via the existing signaling protocol stream.
Both nodes continuously read from the stream, adding incoming remote candidates via `RTCPeerConnection.addIceCandidate()`.

6. On successful establishment or failure of the direct connection, _A_ and _B_ close the signaling protocol stream.
TODO: Is there value in retrying on failure?

7. Messages on `RTCDataChannel`s on the established `RTCPeerConnection` are framed using the message framing mechanism described in [Multiplexing](#multiplexing).

The above browser-to-browser WebRTC connection establishment replaces the existing [libp2p WebRTC star](https://github.com/libp2p/js-libp2p-webrtc-star) and [libp2p WebRTC direct](https://github.com/libp2p/js-libp2p-webrtc-direct) protocols.

## STUN

TODO: Specify

## Signaling protocol

The protocol id is `/webrtc-direct`.
mxinden marked this conversation as resolved.
Show resolved Hide resolved
mxinden marked this conversation as resolved.
Show resolved Hide resolved
Messages are sent prefixed with the message length in bytes, encoded as an unsigned variable length integer as defined by the [multiformats unsigned-varint spec][uvarint-spec].

``` protobuf
syntax = "proto2";
mxinden marked this conversation as resolved.
Show resolved Hide resolved

message Message {
// Specifies type in `data` field.
enum Type {
// String of `RTCSessionDescription.sdp`
OFFER = 0;
// String of `RTCSessionDescription.sdp`
ANSWER = 1;
// String of `RTCIceCandidate.toJSON()`
CANDIDATE = 2;
}
mxinden marked this conversation as resolved.
Show resolved Hide resolved

// TODO: Consider removal of `required` for future compatibility.
required Type type = 1;
required string data = 2;
mxinden marked this conversation as resolved.
Show resolved Hide resolved
}
```

## Open Questions

- Do we need a mechanism for browsers to advertise support for WebRTC browser-to-browser?

Say that browser B supports WebRTC browser-to-browser.
B listens via a relay and advertises its relayed address.
A discovers B's relayed address.
At this point A does not know whether B is a browser and thus supports WebRTC browser-to-browser, or whether B is e.g. a laptop potentially supporting TCP and QUIC hole punching via DCUtR but not WebRTC browser-to-browser.
In the latter case, A can not establish a direct connection to B.

Potential solution would be for B to advertise some protocol after the `/p2p-circuit` within its Multiaddr, e.g. `/ip6/<RELAY_IP>/udp/4001/p2p/<RELAY_PEER_ID>/p2p-circuit/webrtc-direct/p2p/<B_PEER_ID>`.
mxinden marked this conversation as resolved.
Show resolved Hide resolved
As an alternative, A can discover B's support via the identify protocol on the relayed connection or by optimistically opening a stream using the signaling protocol.
Both of the latter options would on failure happen at the expense of a wasted relayed connection.
mxinden marked this conversation as resolved.
Show resolved Hide resolved

- Instead of using trickle ICE, we could as well wait for the candidate gathering.
See https://github.com/pion/webrtc/blob/c1467e4871c78ee3f463b50d858d13dc6f2874a4/examples/insertable-streams/main.go#L141-L142 as one example.
In the browser, one can wait for the [`icegatheringstatechange` event](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/icegatheringstatechange_event).

## FAQ

- Why is there no additional Noise handshake needed?

This specification (browser-to-browser) requires _A_ and _B_ to exchange their SDP offer and answer over an authenticated channel.
Offer and answer contain the TLS certificate fingerprint.
The browser validates the TLS certificate fingerprint through the TLS handshake on the direct connection.
mxinden marked this conversation as resolved.
Show resolved Hide resolved

In contrast, the browser-to-server specification allows exchange of the server's multiaddr, containing the server's TLS certificate fingerprint, over unauthenticated channels.
mxinden marked this conversation as resolved.
Show resolved Hide resolved
In other words, the browser-to-server specification does not consider the TLS certificate fingerprint in the server's multiaddr to be trusted.