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(quic): Add draft-29 support #3151

Merged
merged 15 commits into from
Dec 2, 2022
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Expand Up @@ -45,6 +45,11 @@

# `libp2p` facade crate

# 0.50.1 [unreleased]

- Update individual crates.
- Update to [`libp2p-quic` `v0.7.1-alpha`](transports/quic/CHANGELOG.md).

# 0.50.0

This is a large release. After > 4 years, rust-libp2p ships with an [(alpha) QUIC
Expand Down
4 changes: 2 additions & 2 deletions Cargo.toml
Expand Up @@ -3,7 +3,7 @@ name = "libp2p"
edition = "2021"
rust-version = "1.62.0"
description = "Peer-to-peer networking library"
version = "0.50.0"
version = "0.50.1"
authors = ["Parity Technologies <admin@parity.io>"]
license = "MIT"
repository = "https://github.com/libp2p/rust-libp2p"
Expand Down Expand Up @@ -120,7 +120,7 @@ smallvec = "1.6.1"
libp2p-deflate = { version = "0.38.0", path = "transports/deflate", optional = true }
libp2p-dns = { version = "0.38.0", path = "transports/dns", optional = true }
libp2p-mdns = { version = "0.42.0", path = "protocols/mdns", optional = true }
libp2p-quic = { version = "0.7.0-alpha", path = "transports/quic", optional = true }
libp2p-quic = { version = "0.7.1-alpha", path = "transports/quic", optional = true }
libp2p-tcp = { version = "0.38.0", path = "transports/tcp", optional = true }
libp2p-tls = { version = "0.1.0-alpha", path = "transports/tls", optional = true }
libp2p-webrtc = { version = "0.4.0-alpha", path = "transports/webrtc", optional = true }
Expand Down
7 changes: 7 additions & 0 deletions transports/quic/CHANGELOG.md
@@ -1,3 +1,10 @@
# 0.7.1-alpha [unreleased]

- Add opt-in support for the `/quic` codepoint, interpreted as QUIC version draft-29.
See [PR 3151].

[PR 3151]: https://github.com/libp2p/rust-libp2p/pull/3151

# 0.7.0-alpha

- Initial alpha release.
2 changes: 1 addition & 1 deletion transports/quic/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "libp2p-quic"
version = "0.7.0-alpha"
version = "0.7.1-alpha"
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the appropriate bump would be:

Suggested change
version = "0.7.1-alpha"
version = "0.7.0-alpha.2"

0.7.1-alpha suggests that a 0.7.0 exists and we are pre-releasing a patch version (although the non-breaking aspect of said patch version is not guaranteed, hence the alpha).

We haven't even released 0.7.0 so we may as well push more alpha's out until we are happy with it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah yes you are right! Fixed in 2a83d3c. This also means that we don't need to bump the version in the libp2p crate.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah yes you are right! Fixed in 2a83d3c. This also means that we don't need to bump the version in the libp2p crate.

I think you will have to, I don't think alpha versions update automatically. AFAIK, they are basically major version bumps but with an "unstable" co-notation.

Copy link
Contributor

Choose a reason for hiding this comment

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

I could be wrong though, please test it :)

authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"
rust-version = "1.62.0"
Expand Down
50 changes: 39 additions & 11 deletions transports/quic/src/endpoint.rs
Expand Up @@ -18,7 +18,11 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

use crate::{provider::Provider, transport::SocketFamily, ConnectError, Connection, Error};
use crate::{
provider::Provider,
transport::{QuicVersion, SocketFamily},
ConnectError, Connection, Error,
};

use bytes::BytesMut;
use futures::{
Expand Down Expand Up @@ -69,6 +73,16 @@ pub struct Config {
/// of a connection.
pub max_connection_data: u32,

/// Support QUIC version draft-29 for dialing and listening.
///
/// Per default only QUIC Version 1 / [`libp2p_core::multiaddr::Protocol::QuicV1`]
/// is supported.
///
/// If support for draft-29 is enabled servers support draft-29 and version 1 on all
/// QUIC listening addresses.
/// As client the version is chosen based on the remote's address.
pub support_draft_29: bool,

/// TLS client config for the inner [`quinn_proto::ClientConfig`].
client_tls_config: Arc<rustls::ClientConfig>,
/// TLS server config for the inner [`quinn_proto::ServerConfig`].
Expand All @@ -83,6 +97,7 @@ impl Config {
Self {
client_tls_config,
server_tls_config,
support_draft_29: false,
handshake_timeout: Duration::from_secs(5),
max_idle_timeout: 30 * 1000,
max_concurrent_stream_limit: 256,
Expand Down Expand Up @@ -113,6 +128,7 @@ impl From<Config> for QuinnConfig {
keep_alive_interval,
max_connection_data,
max_stream_data,
support_draft_29,
handshake_timeout: _,
} = config;
let mut transport = quinn_proto::TransportConfig::default();
Expand All @@ -138,7 +154,10 @@ impl From<Config> for QuinnConfig {
let mut client_config = quinn_proto::ClientConfig::new(client_tls_config);
client_config.transport_config(transport);

let endpoint_config = quinn_proto::EndpointConfig::default();
let mut endpoint_config = quinn_proto::EndpointConfig::default();
if !support_draft_29 {
endpoint_config.supported_versions(vec![1]);
}

QuinnConfig {
client_config,
Expand Down Expand Up @@ -280,6 +299,8 @@ pub enum ToEndpoint {
Dial {
/// UDP address to connect to.
addr: SocketAddr,
/// Version to dial the remote on.
version: QuicVersion,
/// Channel to return the result of the dialing to.
result: oneshot::Sender<Result<Connection, Error>>,
},
Expand Down Expand Up @@ -403,18 +424,25 @@ impl<P: Provider> Driver<P> {
to_endpoint: ToEndpoint,
) -> ControlFlow<(), Option<quinn_proto::Transmit>> {
match to_endpoint {
ToEndpoint::Dial { addr, result } => {
ToEndpoint::Dial {
addr,
result,
version,
} => {
let mut config = self.client_config.clone();
if version == QuicVersion::Draft29 {
config.version(0xff00_001d);
}
// This `"l"` seems necessary because an empty string is an invalid domain
// name. While we don't use domain names, the underlying rustls library
// is based upon the assumption that we do.
let (connection_id, connection) =
match self.endpoint.connect(self.client_config.clone(), addr, "l") {
Ok(c) => c,
Err(err) => {
let _ = result.send(Err(ConnectError::from(err).into()));
return ControlFlow::Continue(None);
}
};
let (connection_id, connection) = match self.endpoint.connect(config, addr, "l") {
Ok(c) => c,
Err(err) => {
let _ = result.send(Err(ConnectError::from(err).into()));
return ControlFlow::Continue(None);
}
};

debug_assert_eq!(connection.side(), quinn_proto::Side::Client);
let (tx, rx) = mpsc::channel(CHANNEL_CAPACITY);
Expand Down