Skip to content

feat: WebTransport on top QUIC transport #5564

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

Draft
wants to merge 25 commits into
base: master
Choose a base branch
from

Conversation

dgarus
Copy link
Contributor

@dgarus dgarus commented Aug 20, 2024

related to #2993

@thomaseizinger
Hi! There were so many changes in the master branch, so it was easier for me to create a new PR from scratch. I tried to consider all your previous comments and our discussions.

Here are the main points:

Instead of rolling certificates, I'd suggest (something like) the following:

Give our users a simple API to generate and parse certificates
Allow the user to pass in a list of certificates in the QUIC config, explicitly for WebTransport
For the QUIC functionality, we can generate one similarly to how we do it currently
When the user calls listen_on for webtransport, we validate the certificates have a valid date range (the webtransport spec requires +/- 14 days I think)
Whilst not super convenient, this allows users to externally manage certificates until we can generate them deterministically. 
What is important is that we give users some way of restarting a libp2p-node and retain the certificate. 
WebTransport is of no use if the certificate hashes change constantly.

I would like to avoid interacting with the file system as much as possible. My suggestion would be:

- libp2p::webtransport::Transport::new takes a list of certificates (of type libp2p::webtransport::Certificate)
- libp2p::webtransport::Certificate::generate allows users generate a new certificate with certain parameters (validity date etc)
- libp2p::webtransport::Certificate::{parse,to_bytes} allow users to serialize and deserialize certificates

For simplicity, I made a single cert.

Let's consider the following scenario:

User calls listen_on for /quic-v1
User calls listen_on for /webtransport using the same port
Another peer attempts to connect using the /webtransport address
The incoming connection will be picked up by one of the two listeners. 
Until we inspect the Connecting struct, we don't actually know whether it is a QUIC or a WebTransport connection.

So I think what we need to do is:

At most have 1 Listener for a given socket address
The listener needs to be one of 3 modes:
- Only QUIC
- Only WT
- Both
When we receive a listen_on for a socket with an existing listener, we need to update its mode
For incoming connections, we need to inspect it whether it is a QUIC or 
WT connection and check whether the listener supports whatever is incoming. If yes, upgrade it accordingly.

@dgarus dgarus marked this pull request as draft August 20, 2024 13:47
@dgarus
Copy link
Contributor Author

dgarus commented Aug 20, 2024

@jxs Hello!
Please review this PR as well.
This is a draft, but before cleaning it would be great to know what you think.
Thanks!

@dgarus dgarus changed the title WebTransport on top QUIC transport fear: WebTransport on top QUIC transport Aug 20, 2024
@dgarus dgarus changed the title fear: WebTransport on top QUIC transport feat: WebTransport on top QUIC transport Aug 20, 2024
@dgarus dgarus mentioned this pull request Aug 20, 2024
4 tasks
@thomaseizinger
Copy link
Contributor

Thank you @dgarus ! I hope to give this a review soon.

@dgarus
Copy link
Contributor Author

dgarus commented Sep 4, 2024

@thomaseizinger
Thank you so much for your efforts!
Currently, I’m stuck with an integration test writing. The problem is what can i use as a webtransport client?
I'm looking at transports/webtransport-websys/src/transport.rs. What do you think this is a good idea using webtransport-websys to test webtransport transport?

@thomaseizinger
Copy link
Contributor

@thomaseizinger Thank you so much for your efforts! Currently, I’m stuck with an integration test writing. The problem is what can i use as a webtransport client? I'm looking at transports/webtransport-websys/src/transport.rs. What do you think this is a good idea using webtransport-websys to test webtransport transport?

You should get some basic coverage by adding webtransport here:

Copy link
Member

@elenaf9 elenaf9 left a comment

Choose a reason for hiding this comment

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

Some first comments.
I like that in this approach the webtransport is integrated in the existing quic crate and that we can to support both on one listener!

Sorry of some of my comments have already been discussed in previous iterations on the PR.

Comment on lines 141 to 148
let mut h3_conn = h3::server::builder()
.enable_webtransport(true)
.enable_connect(true)
.enable_datagram(false)
.max_webtransport_sessions(1)
.send_grease(true)
.build(h3_quinn::Connection::new(connection.clone()))
.await?;
Copy link
Member

Choose a reason for hiding this comment

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

Does that mean we create a new h3 server for each connection? Sorry if that's a noob question but if this is an incoming connection on a listener, couldn't we just have one server per listener?

request.uri().path(),
)));
}
if request.uri().query() == Some(webtransport::NOISE_QUERY) {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if request.uri().query() == Some(webtransport::NOISE_QUERY) {
if request.uri().query() != Some(webtransport::NOISE_QUERY) {

It should be the NOISE_QUERY, right?

Comment on lines 154 to 155
if Some(&Protocol::WEB_TRANSPORT) == proto {
let method = request.method();
Copy link
Member

Choose a reason for hiding this comment

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

Nit: just early return here an Err if proto != Some(&Protocol::WEB_TRANSPORT) like you also do it when checking the method, path, etc.

Comment on lines +190 to +191
// indicating no more streams to be received
return Err(WebtransportConnectingError::NoMoreStreams);
Copy link
Member

Choose a reason for hiding this comment

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

What does "NoMoreStreams" mean? When does it happen?

# Conflicts:
#	Cargo.lock
#	transports/quic/Cargo.toml
#	transports/quic/src/config.rs
#	transports/quic/src/connection/connecting.rs
#	transports/quic/src/transport.rs
#	transports/tls/src/certificate.rs
#	transports/tls/src/lib.rs
@dgarus
Copy link
Contributor Author

dgarus commented Mar 11, 2025

Some first comments. I like that in this approach the webtransport is integrated in the existing quic crate and that we can to support both on one listener!

Sorry of some of my comments have already been discussed in previous iterations on the PR.

Hi!
I tried fixing compilation problems, but unfortunately couldn't.
So I decided to ask h3 for release.

@dgarus
Copy link
Contributor Author

dgarus commented Mar 18, 2025

@elenaf9 Good day!
@jxs told me you're planning to removeasync-std feature from quic.
If this is the case, I could do it to make 'quic' a bit simpler and then continue with 'webtransport'. I don't think it takes much time.
What do you think?

@elenaf9
Copy link
Member

elenaf9 commented Mar 18, 2025

@elenaf9 Good day! @jxs told me you're planning to removeasync-std feature from quic. If this is the case, I could do it to make 'quic' a bit simpler and then continue with 'webtransport'. I don't think it takes much time. What do you think?

Yes, we are planning to remove support for async_std for all of rust-libp2p.
However, we would first just deprecate async_std support, and then only in a second release completely remove it. So I am not sure how much of the code we can simplify right now.
Does the existing async_std support complicate much of your work in webtransport?

Also related: #3515 (comment)

@dgarus
Copy link
Contributor Author

dgarus commented Mar 19, 2025

@elenaf9 Good day! @jxs told me you're planning to removeasync-std feature from quic. If this is the case, I could do it to make 'quic' a bit simpler and then continue with 'webtransport'. I don't think it takes much time. What do you think?

Yes, we are planning to remove support for async_std for all of rust-libp2p. However, we would first just deprecate async_std support, and then only in a second release completely remove it. So I am not sure how much of the code we can simplify right now. Does the existing async_std support complicate much of your work in webtransport?

Also related: #3515 (comment)

Ok, I got it, you're right.

Does the existing async_std support complicate much of your work in webtransport?

No, just a bit less code base, that is all.

@dgarus
Copy link
Contributor Author

dgarus commented Jun 21, 2025

@elenaf9
Hello!
I apologize for the delay.
There is one thing I'd like to talk about regarding ConnectingMode::Mixed. When I was trying to implement some logic for this mode, it became unclear to me how we could differentiate between quic and webtransport connections in this mode. Another question is whether it is a real scenario where one listener should act as both a quic listener and a webtransport listener at the same time.
I propose removing this mode. In this case, one transport instance could listen to several addresses, but each address would be for a specific protocol. What do you think?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

transport/webtransport: Add WebTransport protocol
4 participants