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

libp2p-webrtc-browser-to-server blog post #18

Merged
merged 61 commits into from
Feb 8, 2023
Merged
Show file tree
Hide file tree
Changes from 45 commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
2286498
libp2p-webrtc-browser-to-server blog post
ddimaria Dec 20, 2022
514db39
libp2p-webrtc-browser-to-server blog post
ddimaria Dec 20, 2022
a627e96
Update src/_blog/libp2p-webrtc-browser-to-server.md as per Prithvi
ddimaria Dec 21, 2022
31b1550
Update src/_blog/libp2p-webrtc-browser-to-server.md as per Prithvi
ddimaria Dec 21, 2022
eac587c
Update src/_blog/libp2p-webrtc-browser-to-server.md as per Prithvi
ddimaria Dec 21, 2022
fccf8b9
Update src/_blog/libp2p-webrtc-browser-to-server.md as per Prithvi
ddimaria Dec 21, 2022
3da034a
Update src/_blog/libp2p-webrtc-browser-to-server.md as per Prithvi
ddimaria Dec 21, 2022
ef35faf
Update src/_blog/libp2p-webrtc-browser-to-server.md as per Prithvi
ddimaria Dec 21, 2022
e9b7253
Update src/_blog/libp2p-webrtc-browser-to-server.md as per Prithvi
ddimaria Dec 21, 2022
23d6b5b
Update src/_blog/libp2p-webrtc-browser-to-server.md as per Prithvi
ddimaria Dec 21, 2022
90d2674
Update src/_blog/libp2p-webrtc-browser-to-server.md as per Prithvi
ddimaria Dec 21, 2022
9dac046
reorder paragraphs
p-shahi Dec 21, 2022
047bae8
Apply suggestions from code review
p-shahi Dec 21, 2022
a51f0c9
Apply suggestions from code review by Danny
ddimaria Dec 21, 2022
56093d2
Apply suggestions from code review
ddimaria Dec 22, 2022
09f8d98
Incorporate feedback from Max, Marten, and Danny
ddimaria Dec 22, 2022
b82bbdd
Merge branch 'libp2p-webrtc-browser-to-server' of github.com:ddimaria…
ddimaria Dec 22, 2022
e990ab8
Update src/_blog/libp2p-webrtc-browser-to-server.md as per Danny
ddimaria Dec 22, 2022
e824967
Update based on Danny's suggestions
ddimaria Dec 22, 2022
636e455
Merge branch 'libp2p-webrtc-browser-to-server' of github.com:ddimaria…
ddimaria Dec 22, 2022
00c18e3
Incorporate Prithvi's suggestion about attribution
ddimaria Dec 22, 2022
81876a4
Apply suggestions from code review
p-shahi Dec 28, 2022
1c39d6d
Apply suggestions
ddimaria Jan 3, 2023
1ba1293
Merge branch 'libp2p-webrtc-browser-to-server' of github.com:ddimaria…
ddimaria Jan 3, 2023
8c729d5
Apply suggestions from Danny and melekes
ddimaria Jan 3, 2023
66fc8f3
Incorporate Marten's feedback
ddimaria Jan 4, 2023
2390141
Add Extensive Roundtrips section to WebRTC limitations
ddimaria Jan 4, 2023
6c4f12b
Incorporate Marten's overall feedback
ddimaria Jan 4, 2023
4c50e05
Marten and Glen's suggestions
ddimaria Jan 4, 2023
9b42b76
Apply suggestions from code review
ddimaria Jan 4, 2023
3c85be9
Merge branch 'libp2p-webrtc-browser-to-server' of github.com:ddimaria…
ddimaria Jan 4, 2023
f6fbfd3
Fixed grammar error
ddimaria Jan 4, 2023
04a1514
Update sequence diagram to show 3 RTs in the DTLS handshake
ddimaria Jan 4, 2023
99e0678
Apply suggestions from code review by mxinden
ddimaria Jan 5, 2023
9196b43
Remove inacurate signaling sentence
ddimaria Jan 5, 2023
9cfafb4
Add webrtc blog header
ddimaria Jan 6, 2023
a6caa0d
Remove ds_store
ddimaria Jan 6, 2023
75d1542
Apply suggestions from code review
ddimaria Jan 9, 2023
f6a7e43
Apply suggestions from code review
ddimaria Jan 9, 2023
07fc6aa
Apply suggestions from code review
ddimaria Jan 9, 2023
67774a5
Apply suggestions from code review
ddimaria Jan 9, 2023
260fb2c
More of Danny's suggestions
ddimaria Jan 9, 2023
acf7c8c
Implement Danny's subsection suggestion
ddimaria Jan 9, 2023
fd0b8ed
Apply suggestions from code review
ddimaria Jan 13, 2023
249d769
Incorporated feedback from thomaseizinger and mxinden
ddimaria Jan 13, 2023
fc28c41
remove .gitignore
ddimaria Jan 20, 2023
afa75de
Update src/_blog/libp2p-webrtc-browser-to-server.md
ddimaria Jan 20, 2023
b5f855c
Fix spelling issue in DiMaria
ddimaria Jan 20, 2023
fcfc991
Apply suggestions from code review by steve
ddimaria Jan 21, 2023
67482d2
Apply suggestions from code review
ddimaria Jan 24, 2023
7459fae
Update Acknowledgements from review feedback
ddimaria Jan 24, 2023
60aa500
Apply suggestions from mxinden
ddimaria Jan 26, 2023
35eee32
Add server STUN binding response to the sequence diagram
ddimaria Jan 26, 2023
f639c08
Reverse DTLS handshake flows
ddimaria Jan 26, 2023
82631a6
Update Setup and configuration section to elaborate on server setup
ddimaria Jan 26, 2023
527ba38
Add more info about the DTLS roundtrips in the box in the diagram
ddimaria Jan 26, 2023
8e997f9
Update go link to issue instead of PR
ddimaria Jan 31, 2023
b3f188e
add diagram
p-shahi Feb 7, 2023
058bf88
edits
p-shahi Feb 7, 2023
2a1f04b
update diagram
p-shahi Feb 7, 2023
733fe9d
update
p-shahi Feb 8, 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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.DS_Store
ddimaria marked this conversation as resolved.
Show resolved Hide resolved
Binary file removed src/.DS_Store
Binary file not shown.
253 changes: 253 additions & 0 deletions src/_blog/libp2p-webrtc-browser-to-server.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
---
tags:
- browser
- transport
- webrtc
title: WebRTC in libp2p
description:
date:
Copy link
Member

@mxinden mxinden Jan 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't forget to add a date. Otherwise it seems to show up as the last post on the blog.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@p-shahi should we populate this now, or is it's population part of a release prcoess?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a single update right before merging is the way to go. I am not aware of a formal "release process".

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ddimaria This is still missing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I read @mxinden's comment as the date should be added immediately before merging, so this is intentionally unaddressed until we get the green light to merge. If you have a date that you think it will be merged ahead of time, I can add that in? I can optionally add today's date and just update again prior to merging? I don't have a strong opinion on any approach.

permalink: ""
ddimaria marked this conversation as resolved.
Show resolved Hide resolved
translationKey: ''
header_image: /libp2p_WebRTC_blog_header-1.png
author: David Di Maria
---


# WebRTC (Browser-to-Server) in libp2p

<!--
WebTransport in libp2p: Part 1 of Universal Browser Connectivity
WebRTC (Browser to Server): Part 2 of Universal Browser Connectivity
WebRTC (Browser to Browser): Part 3 of Universal Browser Connectivity
-->
This is the second entry in the Universal Browser Connectivity series on how libp2p achieves browser connectivity.
Read about WebTransport in the [first post](https://blog.libp2p.io/2022-12-19-libp2p-webtransport/).

**Table of Contents**


[[toc]]

## Overview

The [libp2p project](https://libp2p.io) supports many [transport protocols](https://libp2p.io/implementations/#transports) across a variety of implementations.
These transport protocols enable applications using libp2p to run as server nodes (on a personal laptop or in a datacenter) or as browser nodes (inside a Web browser).

ddimaria marked this conversation as resolved.
Show resolved Hide resolved
Historically, libp2p has bridged these runtime environments with different node connectivity options to varying degrees:
p-shahi marked this conversation as resolved.
Show resolved Hide resolved
- server node to server node via TCP and QUIC;
p-shahi marked this conversation as resolved.
Show resolved Hide resolved
- browser node to server node via WebSockets and, more recently, [WebTransport](https://blog.libp2p.io/2022-12-19-libp2p-webtransport);
ddimaria marked this conversation as resolved.
Show resolved Hide resolved
- browser node to browser node (via [less than ideal solutions](#prior-webrtc-implementations).
ddimaria marked this conversation as resolved.
Show resolved Hide resolved

salmad3 marked this conversation as resolved.
Show resolved Hide resolved
Today our focus is on advancements in the **browser to server** use case...🥁*drumroll*
ddimaria marked this conversation as resolved.
Show resolved Hide resolved

We're excited to present a new paradigm for browser-to-server connectivity and announce,

**native support for WebRTC now exists in libp2p!**
ddimaria marked this conversation as resolved.
Show resolved Hide resolved

Browser to server offerings, old and new, came with their own set of shortcomings.
p-shahi marked this conversation as resolved.
Show resolved Hide resolved
A new libp2p WebRTC solution establishes browser-to-server connectivity in a decentralized way across a broad spectrum of browsers and in multiple libp2p implementations.

> If you're familiar with the libp2p ecosystem, you may wonder, is this new? Hasn't there already been support for WebRTC in libp2p? The answer to both questions is **yes** - although support has existed, this new WebRTC solution is a fresh departure from older uses for WebRTC in libp2p. We describe more below.

## Acknowledgements

We would like to recognize and express our gratitude to [Little Bear Labs](https://littlebearlabs.io/) and [Parity Technologies](https://www.parity.io/) for their contributions to the development of the WebRTC specification and implementation in libp2p.

Little Bear Labs worked in collaboration with Protocol Labs and the libp2p community to define the WebRTC specification, and also focused on the Go and JavaScript implementations. Meanwhile, Parity Technologies focused on the Rust implementation and initiated this effort [several years ago](https://github.com/paritytech/smoldot/issues/1712). We appreciate the time and effort that both of these organizations have put into this project, and their invaluable input has been instrumental in its success.
First, kudos to [Little Bear Labs](https://littlebearlabs.io/), who teamed up with Protocol Labs and the libp2p community to define the WebRTC specification and work on the implementation. Second, thanks to [Parity Technologies](https://www.parity.io/) for helping initiate this effort [many years ago](https://github.com/paritytech/smoldot/issues/1712) and for all the valuable input on the specification and Rust implementation.
ddimaria marked this conversation as resolved.
Show resolved Hide resolved

Before diving into the details of the WebRTC implementation in libp2p, let's first understand what WebRTC is and how it is used in the context of browser-based use cases.

## WebRTC in the browser

WebRTC, or Web Real-Time Communication, is a [set of standards](https://w3c.github.io/webrtc-pc/) that enables peer-to-peer connections between browsers, clients, and servers and the exchange of audio, video, and data in real-time. It is built directly into modern browsers and is straightforward to use via its API.

While WebRTC handles audio, video, and data traffic, we're just going to focus on the data aspect because that's the API leveraged in libp2p-webrtc.

In most cases, peers directly connect to other peers, improving privacy and requiring fewer hops than on a relay. Peers connect via an [RTCPeerConnection](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection) interface. Once connected, [RTCDataChannels](https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel) can be added to the connection to send and receive binary data.

To connect to each other, peers need to learn their public IP address and any router restrictions along the path that would prohibit peer-to-peer communication. WebRTC specifies the [STUN](https://datatracker.ietf.org/doc/html/rfc3489) protocol for that. In the case of a restriction, [TURN](https://datatracker.ietf.org/doc/html/rfc8656) servers relay data between peers using a Signaling Channel. In libp2p, we don't use these protocols.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In libp2p, we don't use these protocols.

Something I'm not seeing answered in this text flow is: if we don't use these WebRTC protocols, how do we determine public IP addresses?

Copy link
Member

@jxs jxs Jan 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Also technically it's not correct, a browser uses a STUN binding request to get its public ip (server reflexive candidate) from the server node using ICE Lite.
Wdyt of expanding on the wording used on the spec?

Given that B is publicly reachable, B acts as a ICE Lite agent. It binds to a UDP port waiting for incoming STUN and SCTP packets and multiplexes based on source IP and source port.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@BigLep as this section is about WebRTC built into the browser, I didn't touch on not-using WebRTC protocols. Were you thinking of an alternative networking stack to use in lieu of WebRTC for browser-based real time communication in cases where STUN/TURN aren't options? Conversely, if we're talking about "private" servers in the context of libp2p, we may want to keep that in the subsequent section (WebRTC in libp2p) 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jxs can you elaborate on server node in the context of using traditional WebRTC in the browser? That spec entry relates to a lbp2p use case.

Copy link
Member

@jxs jxs Jan 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah sure David, sorry if was not clear on the comment above.

In the context of traditional WebRTC in the browser a server node is usually a SFU or a MCU. As they are deployed to public reachable addresses they can offer ICE Lite implementation and therefore act as STUN agent that the browser can then use to get its public IP.

The aforementioned paragraph describes the WebRTC protocol from the browser perspective and mentions STUN and TURN as tools that "peers need to learn their public IP address and any router restrictions along the path that would prohibit peer-to-peer communication." but then it mentions that in libp2p we don't use these two protocols whereas in fact, in the libp2p context the publicly available WebRTC libp2p server node offers the same ICE Lite via "a=ice-lite" session-level attribute in its SDP offer see the Rust case for example.
The browser then uses a STUN binding request to get its public ip address from the same libp2p server node it is connecting to.

Does this help make it clear?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In libp2p, we don't use these protocols.

Something I'm not seeing answered in this text flow is: if we don't use these WebRTC protocols, how do we determine public IP addresses?

To answer the initial question directly: A libp2p WebRTC server discovers its public IP address by either (a) being told by the operator directly or (b) through the identify protocol when connecting via WebRTC to another public server.

On the meta level, I think the root of the confusion here is that the blog post is about libp2p WebRTC browser-to-server while this paragraph is about vanilla WebRTC browser-to-browser.

To move forward here, I suggest either detailing the vanilla browser-to-server flow via ICE lite and SFUs / MCUs as suggested by @jxs, and not the vanilla browser-to-browser flow, or drop this and the following paragraphs entirely.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for clarifying @jxs and @mxinden, I made the assumption of browser to browser in this section to inform the reader about the typical WebRTC use case (and one they'd be most familiar with). SFUs/MCUs are common of course, and necessary for certain functionality (e.g. recording) and optimizations, though add a lot of complexity to the conversation 🤔


Once IP addresses are obtained, a peer sends an Offer [SDP](https://datatracker.ietf.org/doc/html/rfc4566) to the other peer. This Offer SDP details how the initiating peer can communicate (IP address, protocols, fingerprints, encryption, etc.). The other peer sends an Answer SDP to the initiating peer. Both peers now have enough information to start the DTLS handshake.
ddimaria marked this conversation as resolved.
Show resolved Hide resolved

The DTLS handshake is performed using fingerprints contained in the Offer and Answer SDPs. After the handshake is complete, data is sent between peers using the SCTP (Stream Control Transmission Protocol) protocol, encrypting messages with DTLS over UDP or TCP.


## WebRTC in libp2p

<!--
participantspacing 20
entryspacing 0.75

participant Browser
participant Server
box over Server: Generate TLS Certificate
box over Server: Listen on UDP Port
box over Browser: Create RTCPeerConnection
box over Browser: Create Server's Answer SDP
box over Browser: Create Offer SDP
Browser->Server:STUN Binding Request
ddimaria marked this conversation as resolved.
Show resolved Hide resolved
box over Server: Create Browser's Offer SDP

Server->(1)Browser:DTLS Handshake
ddimaria marked this conversation as resolved.
Show resolved Hide resolved
Browser->(1)Server:DTLS Handshake
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since WebRTC uses DTLS 1.2, the handshake takes 2 roundtrips. The diagram should probably reflect that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can add that level of fidelity. IIRC there are 3 RTs for DTLS (6 flights total), assuming no retransmissions. I'm wondering if it would be OK to add some messaging around this w/o 6 lines (noisy) 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a box beneath the handshake to provide info about the 3 RTs.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I am not mistaken 3 round trips are only needed as a denial-of-service countermeasure, see https://www.rfc-editor.org/rfc/rfc6347#section-4.2.1.

In order to counter both of these attacks, DTLS borrows the stateless
cookie technique used by Photuris [PHOTURIS] and IKE [IKEv2]. When
the client sends its ClientHello message to the server, the server
MAY respond with a HelloVerifyRequest message. This message contains
a stateless cookie generated using the technique of [PHOTURIS]. The
client MUST retransmit the ClientHello with the cookie added.

I am not sure what the default in major implementations is, 3 RT or 2 RT.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll do some digging. This is a chart from the author of Pion:
image

I'll need to see how Chrome does this. I may need to have Wireshark observe the handshake to be certain.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the server here? I'm surprised to see a Hello Verify Request here. That's an anti-DoS measure in DTLS (similar to the Retry mechanism in QUIC, for those familiar with the QUIC spec). It adds 1 RTT to the handshake. If that's either rust-libp2p or go-libp2p, it would be worth investigating how / if we can turn this off. In terms of DoS defense, it doesn't buy us a lot here since we already create state when we receive the STUN packet, so doing a DoS defense in DTLS arguably comes to late.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The server is a Go libp2p server.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To summarize:

  • During a DTLS handshake the server side MAY send a HelloVerifyRequest, thus adding an additional RTT to the DTLS handshake (2 RTT -> 3 RTT).
  • This seems to be the default behavior of Pion.

The discussion on whether to tackle the optimization to only send HelloVerifyRequest when being DOS attacked is out of scope for this blog post. Further, it is an implementation decision, that can be rolled out by server implementations independently.

To move forward I suggest going with the conservative (current) 3 RTT (including HelloVerifyRequest), but adding a small note like the below:

- box over Browser,Server: Full DTLS Handshake is 3 round trips
+ box over Browser,Server: Full DTLS Handshake is 3 round trips (2 without `HelloVerifyRequest` DOS prottection)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change has been made.

box over Browser,Server: Full DTLS Handshake is 3 round trips

Server->(1)Browser:Libp2p Noise Handshake
Browser->(1)Server:Libp2p Noise Handshake


Browser<->Server:Multiplex Send/Receive Framed Data
-->
![](https://i.imgur.com/jF69zwh.png)

Connecting to a server from a browser in the WebRTC implementation in libp2p has some similarities but differs in several ways. Many of the features supported in the WebRTC standard, such as video, audio, and STUN and Turn servers, are not needed in libp2p. The primary WebRTC component that libp2p leverages is the [RTCDataChannels(https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel).
ddimaria marked this conversation as resolved.
Show resolved Hide resolved

### Server Setup
To establish a connection with the browser, the server performs the following steps:
ddimaria marked this conversation as resolved.
Show resolved Hide resolved

1. Generates a self-signed TLS certificate.
1. Listens on a UDP port for incoming STUN packets.

ddimaria marked this conversation as resolved.
Show resolved Hide resolved
### Browser Connection
The browser initiates the connection by performing the following actions:
ddimaria marked this conversation as resolved.
Show resolved Hide resolved

1. Assembles the multiaddress of the server, which is either known upfront or discovered.
1. Creates an [RTCPeerConnection](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection).
1. Generates the server's Answer SDP using the components in the multiaddress.
1. Modifies the SDP, or "munges" it, to include an auto-generated ufrag and password, as well as the server's IP and port.
1. Creates an Offer SDP and modifies it with the same values.
1. Sets the Offer and Answer SDP on the browser, which triggers the sending of STUN packets to the server.


### Server Response
The server responds by creating the browser's Offer SDP using the values in the STUN Binding Request.

### DTLS Handshake
The browser and server then engage in a DTLS handshake to open a DTLS connection that WebRTC can run SCTP on top of. A [Noise handshake](https://github.com/libp2p/specs/blob/master/noise/README.md) is initiated by the server using the fingerprints in the SDP as input to the [prologue data](https://noiseprotocol.org/noise.html#prologue), and completed by the browser over the Data Channel. This handshake authenticates the browser and the server, although Noise is not used for the encryption of data. A total of six roundtrips are performed.
ddimaria marked this conversation as resolved.
Show resolved Hide resolved

Once the DTLS and Noise handshakes are complete, DTLS-encrypted SCTP data is ready to be exchanged over the UDP socket.

> :bulb: Unlike standard WebRTC, signaling is completely removed in libp2p browser-to-server communication, and Signal Channels are not needed. Removing signaling results in fewer roundtrips to establish a Data Channel and reduces complexity by eliminating the need for signaling.

#### Message Framing
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure this adds a lot of value. I would assume that it confuses more than it helps. Not a strong opinion. Feel free to leave as is.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@marten-seemann what are your thoughts? I know you wanted some inclusion of framing, but maybe my approach is overkill? Maybe removing the protobuf message structure will lessen any confusion?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might be missing some past discussion. Again, please feel free to ignore my comment.


Since the browser's implementation of WebRTC doesn't support stream resets or half-closing of streams, message framing was implemented on the data channels to achieve those goals.

#### Multiaddress

The [multiaddress](https://docs.libp2p.io/concepts/fundamentals/addressing/) of a WebRTC address begins like a standard UDP address, but adds three additional protocols: `webrtc`, `hash`, and `p2p`.

```shell
/ip4/1.2.3.4/udp/1234/webrtc/certhash/<hash>/p2p/<peer-id>
```

* `webrtc`: the name of this transport
* `hash`: the [multihash](https://github.com/multiformats/multihash) of the certificate used in the DTLS handshake
* `p2p`: the peer-id of the libp2p node (optional)

### Benefits

#### Self-signed Certificate

WebRTC enables browsers to connect to public libp2p nodes without the nodes requiring a TLS certificate in the browser's [certificate chain](https://en.wikipedia.org/wiki/X.509#Certificate_chains_and_cross-certification). WebRTC allows the server to use a self-signed TLS certificate, eliminating the need for additional services like DNS and Let's Encrypt.

#### Broad support

WebRTC has been supported in Chrome since 2012, and support has since been added to all [evergreen browsers](https://caniuse.com/?search=webrtc). This makes WebRTC widely available and easy to implement in libp2p.

### Limitations

ddimaria marked this conversation as resolved.
Show resolved Hide resolved
While WebRTC has several advantages, it also has some limitations to consider:

#### Setup and configuration

WebRTC is a complex set of technologies that requires extensive setup and configuration. This can be a drawback for some users.
ddimaria marked this conversation as resolved.
Show resolved Hide resolved

#### Extensive Roundtrips

Another limitation is the 6 roundtrips required before data is exchanged. This may make other transports, such as [WebTransport](https://docs.libp2p.io/concepts/transports/webtransport/), more appealing for certain use cases where the browser supports it.
ddimaria marked this conversation as resolved.
Show resolved Hide resolved

### Usage

The complexity of WebRTC is abstracted in the libp2p implementations, making it easy to swap in WebRTC as the transport. In the JavaScript implementation, for example, all you need to do is initialize with:

ddimaria marked this conversation as resolved.
Show resolved Hide resolved
```javascript
import { webRTC } from 'js-libp2p-webrtc'

const node = await createLibp2p({
transports: [webRTC()],
connectionEncryption: [() => new Noise()],
});
```

The only difference from other transports is initializing with `webRTC()`. That's all you need to do to implement WebRTC in the browser. Easy, right?
## Alternative transports
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would consider removing this seciton. I think it makes more sense in the connectivity website or the docs. Basically keep the post focused on WebRTC and leave education about other transports to other places.

Maybe we have a post at the end of the connectivity series that gives a textual overview of the pros and cons of the transports.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can see the benefits of keeping it as well as removing it. It really depends if a blog post reader use case includes reading the post in isolation (not reading other blog posts and/or not relying on external links). The additional information doesn't overwhelm the reader in this case, but offers an immediate compare/contrast experience. I'll let others weigh in on this.


WebRTC is just one option for connecting browsers to libp2p nodes. libp2p supports a variety of transports, and choosing the right one for your use case is an important consideration. The [libp2p connectivity site](https://connectivity.libp2p.io/) was designed to help developers to consider the available options.

### WebSocket

The WebSocket protocol, defined in the [WebSocket RFC](https://datatracker.ietf.org/doc/html/rfc6455), allows for the opening of a two-way socket between a browser and a server over TCP. It is supported in the [Rust](https://github.com/libp2p/rust-libp2p/tree/master/transports/websocket), [Go](https://github.com/libp2p/go-libp2p/tree/master/p2p/transport/websocket), and [JavaScript](https://github.com/libp2p/js-libp2p-websockets) libp2p implementations.

#### Limitations

One limitation of WebSocket is the number of roundtrips required to establish a connection. Handshakes and other upgrades add up to six roundtrips, which can be slower than other transports. Additionally, WebSocket requires the server to have a trusted TLS certificate using TCP, unlike WebRTC which can use a self-signed certificate.

### WebTransport

[WebTransport](https://datatracker.ietf.org/doc/html/draft-ietf-webtrans-overview) is the new kid on the block for communication in the browser. WebTransport is implemented in [Go](https://github.com/libp2p/go-libp2p/tree/master/p2p/transport/webtransport) and [JavaScript](https://github.com/libp2p/js-libp2p-webtransport) implementations.

#### Benefits

WebTransport has many of the same benefits as WebRTC, such as fast, secure, and multiplexed connections, without requiring servers to implement the stack. It also allows libp2p to use raw WebTransport streams and avoid double encryption. Additionally, WebTransport requires fewer roundtrips to establish a connection than WebRTC, making it the preferred choice when supported.

As opposed to WebSockets, libp2p can use raw WebTransport streams and avoid the need for double encryption.

#### Limitations

You might be asking yourself, why pick WebRTC over WebTransport in libp2p? It's like WebRTC but easier to implement and with less complexity. Still, WebTransport is not without its limitations.

Comment on lines +211 to +212
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
You might be asking yourself, why pick WebRTC over WebTransport in libp2p? It's like WebRTC but easier to implement and with less complexity. Still, WebTransport is not without its limitations.

I would remove as I don't think this is providing more value in saying. This is the "Limitations" section.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to think about this one as I don't have insight into the intent of the post. It makes sense to orient the reader and transition into the limitations and appropriate in a blog post, but would be out of place in a technical paper. Does anyone have direction on the stylistic goals?

Currently, it is only implemented in Chrome and is still under development. Until WebTransport is supported by all major browsers, WebRTC can serve as a good fallback option.

## Legacy WebRTC implementations in libp2p

This new implementation of WebRTC in libp2p is a departure from previous, less effective solutions that were previously used to establish connectivity.

### libp2p-webrtc-star

libp2p-webrtc-star was [released]( https://github.com/libp2p/js-libp2p-webrtc-star/releases/tag/v0.5.0) in 2016. This transport utilizes centralized STUN and TURN servers to handle signaling and was [never intended](https://github.com/libp2p/js-libp2p/issues/385) to be a long-term solution. The repository was archived in November in favor of the new js-libp2p-webrtc transport due to the dependence on centralized servers.
ddimaria marked this conversation as resolved.
Show resolved Hide resolved

### libp2p-webrtc-direct

libp2p-webrtc-direct utilizes WebSockets to exchange SDPs, removing the need for centralized dependency in libp2p-webrtc-star. While libp2p-webrtc-direct solved the centralized problem, the servers must have valid TLS certificates for WebSocket connectivity. The repository was archived in November.
ddimaria marked this conversation as resolved.
Show resolved Hide resolved

## Can I use WebRTC now?

Yes, you can use libp2p-webrtc in the [Rust](https://github.com/libp2p/rust-libp2p/tree/master/transports/webrtc) and [JavaScript](https://github.com/libp2p/js-libp2p-webrtc) implementations! The [Go](https://github.com/libp2p/go-libp2p) implementation is close to completion. Follow the [development in go-libp2p](https://github.com/libp2p/go-libp2p/pull/1655) to get notified when it gets shipped.
ddimaria marked this conversation as resolved.
Show resolved Hide resolved

In fact, the Rust implementation of WebRTC has already been put into use by the Parity team!
It has been enabled as an experimental feature and added to [Smoldot](https://github.com/paritytech/smoldot/issues/1712) (a lightweight client for [Substrate](https://substrate.io/) and [Polkadot](https://polkadot.network/).
ddimaria marked this conversation as resolved.
Show resolved Hide resolved
There is also [ongoing work to enable it directly in Substrate](https://github.com/paritytech/substrate/pull/12529).

This is exciting news as WebRTC is already contributing to Parity's [roadmap to enable browser to server connectivity](https://github.com/paritytech/substrate/issues/7467) on their network!

p-shahi marked this conversation as resolved.
Show resolved Hide resolved
## What's next?
ddimaria marked this conversation as resolved.
Show resolved Hide resolved

WebRTC offers the capability for browsers to connect to browsers 🎉. This isn't currently possible in any of the active libp2p transports and represents a significant achievement in libp2p.

The [WebRTC browser-to-browser connectivity spec](https://github.com/libp2p/specs/pull/497) is currently being authored and development will soon start. Follow the [PR](https://github.com/libp2p/specs/pull/497) for up-to-date information.

## Resources and how you can help contribute

If you would like to read further about WebRTC. Please see the libp2p:

- [WebRTC Docs](https://github.com/libp2p/docs/pull/264)
- [WebRTC Connectivity](https://connectivity.libp2p.io/#webrtc)
- This describes WebRTC along with other transport implementations
- [WebRTC Spec](https://github.com/libp2p/specs/tree/master/webrtc)

If you would like to contribute, please [connect with the libp2p maintainers](https://libp2p.io/#community).


Thank you for reading!
Binary file added src/assets/libp2p_WebRTC_blog_header-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.