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

Conversation

elenaf9
Copy link
Contributor

@elenaf9 elenaf9 commented Nov 21, 2022

Description

Add support for QUIC draft-29 / the quic codepoint. This enables both dialing and listening on quic addresses.
The motivation for adding support is to allow users to connect to old go-libp2p nodes that don't support the quic-v1 codepoint.
Per default support is disabled (cc @marten-seemann).

Links to any relevant issues

See discussion in #3133.

Open Questions

We use the same codepoint when reporting our listening addresses as address had that the user called listen_on on.
If users want to report listening addresses for both codepoints they either have to manually duplicate and map each listening address, or create two listeners.
The alternative would be to directly report listening addresses for both codepoints if draft-29 is enabled. I don't have a strong opinion, but I am leaning towards the current implementation to avoid reporting draft-29 addresses unless it is explicitly wanted by the user.

Change checklist

  • I have performed a self-review of my own code
  • I have made corresponding changes to the documentation
  • I have added tests that prove my fix is effective or that my feature works

@mxinden mxinden modified the milestone: v0.50.0 Nov 22, 2022
Copy link
Contributor

@thomaseizinger thomaseizinger left a comment

Choose a reason for hiding this comment

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

Not too invasive so this looks okay to add. We may want to document that this will be removed in the future.

@elenaf9
Copy link
Contributor Author

elenaf9 commented Nov 23, 2022

Not too invasive so this looks okay to add. We may want to document that this will be removed in the future.

Another option would be to deprecate Protocol::Quic in https://github.com/multiformats/rust-multiaddr.

@elenaf9
Copy link
Contributor Author

elenaf9 commented Nov 25, 2022

Would love to get this into #3163 if it gets a review in time and there are no major change requests, but we don't have to block the release on it.

@mxinden
Copy link
Member

mxinden commented Nov 25, 2022

@elenaf9 this is a non-breaking change, right? Mind if we release this as libp2p-quic v0.1.1-alpha then?

Never mind. It adds a pub field to a pub struct.

@mergify
Copy link
Contributor

mergify bot commented Nov 25, 2022

This pull request has merge conflicts. Could you please resolve them @elenaf9? 🙏

@elenaf9
Copy link
Contributor Author

elenaf9 commented Nov 25, 2022

@elenaf9 this is a non-breaking change, right? Mind if we release this as libp2p-quic v0.1.1-alpha then?

Never mind. It adds a pub field to a pub struct.

I am not 100% sure, but is it really a breaking change adding a pub field to a pub struct if that struct also has other private fields anyway (in our case server_tls_config and client_tls_config)? Deconstructions like let quic::Config { handshake_timeout, .. } = config are non-exhaustive anyway due to inaccessible fields I think.

Copy link
Member

@mxinden mxinden left a comment

Choose a reason for hiding this comment

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

This looks good to me. Two suggestions, none of them blocking.

transports/quic/src/endpoint.rs Outdated Show resolved Hide resolved
transports/quic/src/transport.rs Show resolved Hide resolved
@mxinden
Copy link
Member

mxinden commented Nov 25, 2022

@elenaf9 this is a non-breaking change, right? Mind if we release this as libp2p-quic v0.1.1-alpha then?
Never mind. It adds a pub field to a pub struct.

I am not 100% sure, but is it really a breaking change adding a pub field to a pub struct if that struct also has other private fields anyway (in our case server_tls_config and client_tls_config)? Deconstructions like let quic::Config { handshake_timeout, .. } = config are non-exhaustive anyway due to inaccessible fields I think.

Good point. I suggest following whatever cargo semver-checks on our CI says.

As far as I can tell, this is only time critical for hole punching month in December. I am fine with either of:

  • Releasing this as a breaking change.
  • Releasing this as a non-breaking change (see cargo semver-checks comment above).
  • Using an unreleased version in the Rust punchr client for hole punching month.

Copy link
Contributor

@thomaseizinger thomaseizinger left a comment

Choose a reason for hiding this comment

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

LGTM

Only a few nits!

transports/quic/src/transport.rs Outdated Show resolved Hide resolved
let _ = d_transport.poll_next_unpin(cx);
Poll::Pending
});
select! {
Copy link
Contributor

Choose a reason for hiding this comment

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

@mxinden converted me to prefer the select fn. Can we convert you too? :)

Copy link
Contributor Author

@elenaf9 elenaf9 Nov 30, 2022

Choose a reason for hiding this comment

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

Can you point me to the discussion about the reasoning behind this? Right now I have a slight preference for the macro because of the readability.

Copy link
Contributor

Choose a reason for hiding this comment

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

Basically the rationale is:

  • Plays better with IDEs
  • Much easier to understand
  • Clear type-safety in how to handle the various outcomes
  • No fuse needed
  • No magic syntax to learn

I don't know where exactly we had this discussion, so can't link you to it unfortunately.

Copy link
Member

Choose a reason for hiding this comment

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

While I very much believe in the cause @thomaseizinger, I suggest we delay further select-evangelizing towards @elenaf9 and others to future pull request. In other words, I don't think we need to block here. (Also gives us more time to print t-shirts and stickers.)

Comment on lines 203 to 213
let a_quic_mapped_addr = a_quic_addr
.clone()
.into_iter()
.map(|p| {
if matches!(p, Protocol::QuicV1) {
Protocol::Quic
} else {
p
}
})
.collect();
Copy link
Contributor

Choose a reason for hiding this comment

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

This snippet is repeated 3 times in the test. Can we make a little swap_protocol utility so these are one-liners?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Wdyt of 4cd494d?

transports/quic/src/transport.rs Outdated Show resolved Hide resolved
transports/quic/src/transport.rs Outdated Show resolved Hide resolved
@thomaseizinger
Copy link
Contributor

@elenaf9 this is a non-breaking change, right? Mind if we release this as libp2p-quic v0.1.1-alpha then?

Never mind. It adds a pub field to a pub struct.

I am not 100% sure, but is it really a breaking change adding a pub field to a pub struct if that struct also has other private fields anyway (in our case server_tls_config and client_tls_config)? Deconstructions like let quic::Config { handshake_timeout, .. } = config are non-exhaustive anyway due to inaccessible fields I think.

We are currently on an "alpha" version. Anything is allowed there, i.e. a user doesn't get any guarantees (which is probably why we shouldn't export it by default from the root libp2p).

@@ -1,6 +1,6 @@
[package]
name = "libp2p-quic"
version = "0.7.0-alpha"
version = "0.7.1-alpha"
Copy link
Contributor

@thomaseizinger thomaseizinger Nov 29, 2022

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 :)

@thomaseizinger
Copy link
Contributor

@elenaf9 this is a non-breaking change, right? Mind if we release this as libp2p-quic v0.1.1-alpha then?

Never mind. It adds a pub field to a pub struct.

I am not 100% sure, but is it really a breaking change adding a pub field to a pub struct if that struct also has other private fields anyway (in our case server_tls_config and client_tls_config)? Deconstructions like let quic::Config { handshake_timeout, .. } = config are non-exhaustive anyway due to inaccessible fields I think.

We are currently on an "alpha" version. Anything is allowed there, i.e. a user doesn't get any guarantees (which is probably why we shouldn't export it by default from the root libp2p).

Note that the breaking/non-breaking aspect still matters for the re-exported interface in libp2p.

Change version to 0.7.0-alpha.2 rather than 0.7.1-alpha. The latter
wrongly implies that we are pre-releasing 0.7.1.
Revert version bump and changelog entry in `libp2p` crate.
Co-authored-by: Thomas Eizinger <thomas@eizinger.io>
@elenaf9
Copy link
Contributor Author

elenaf9 commented Nov 30, 2022

The semver check in our CI passes.
Also, the Rust API evolution RFC only defines adding a public field as major (= breaking) change if no private fields exist on the struct: https://github.com/rust-lang/rfcs/blob/master/text/1105-api-evolution.md#major-change-adding-a-public-field-when-no-private-field-exists.
Thus I think we can release this as a new alpha release 0.7.0-alpha.2

Copy link
Member

@mxinden mxinden left a comment

Choose a reason for hiding this comment

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

Changes and version handling looks good to me.

@mxinden mxinden added the send-it label Dec 2, 2022
@mxinden
Copy link
Member

mxinden commented Dec 2, 2022

Interpreting @thomaseizinger approval as still valid.

@mxinden
Copy link
Member

mxinden commented Dec 2, 2022

libp2p-dcutr and libp2p-relay failures are unrelated and handled in #2647 (comment). Moving forward here.

@mxinden mxinden merged commit dfc5ec8 into libp2p:master Dec 2, 2022
@elenaf9 elenaf9 deleted the quic/draft-29 branch December 3, 2022 00:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants