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 1 commit
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
44 changes: 34 additions & 10 deletions transports/quic/src/endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,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 +93,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 +124,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 +150,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 +295,8 @@ pub enum ToEndpoint {
Dial {
/// UDP address to connect to.
addr: SocketAddr,
/// Whether to dial the remote on QUIC version draft-29.
is_draft_29: bool,
elenaf9 marked this conversation as resolved.
Show resolved Hide resolved
/// Channel to return the result of the dialing to.
result: oneshot::Sender<Result<Connection, Error>>,
},
Expand Down Expand Up @@ -403,18 +420,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,
is_draft_29,
} => {
let mut config = self.client_config.clone();
if is_draft_29 {
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