Skip to content

Conversation

@ramfox
Copy link
Member

@ramfox ramfox commented Dec 10, 2025

Description

Incoming::retry returns a RetryError, which you can turn back into a quinn::Incoming. We want that quinn::Incoming to instead be an iroh::endpoint::Incoming. This PR fixes that.

Incoming::accept_with takes a quinn::ServerConfig, however the quinn::ServerConfig allows you to override the quinn::TransportConfig, which we have new typed to QuicTransportConfig. So, this PR new types quinn::ServerConfig to quic::ServerConfig, and ensures that the quinn::TransportConfig is set appropriately for multipath use.

This PR also explicitly comments on each quinn export and labels what type uses that export and where it enters the public iroh API.

Breaking Changes

iroh:
- changed
- Incoming::retry now returns an iroh::endpoint::RetryError, rather than a quinn::RetryError
- Incoming::accept_with now takes a iroh::endpoint::ServerConfig, rather than a quinn::ServerConfig

Notes & open questions

Okay. So. I impl'd all of the methods one-to-one from quinn::ServerConfig, but I think there are a bunch of fields we may want to restrict folks from messing with when they use Incoming::accept_with, as currently, they can use this API to replace our normal TlsConfig entirely.

I'm also unsure if there are any other bits in here (for example the quinn::ServerConfig::migrate field) that may interfere with expected multipath usage.

My proposal would be to either eliminate the Incoming::accept_with method entirely (therefore removing the need to publically export the ServerConfig), or reduce ServerConfig in scope so that only fields that will not interfere with "business as usual" for multipath/iroh remain.

Change checklist

  • Self-review.
  • Documentation updates following the style guide, if relevant.
  • All breaking changes documented.

“ramfox” added 3 commits December 9, 2025 23:56
`ServerConfig` is used in the public API in `Incoming::accept_with`. `quinn::ServerConfig` takes a `TransportConfig`. However, we want to maintain control over the `TransportConfig` fields, so we new typed it to `QuicTransportConfig`. So, we needed to new type `quinn::ServerConfig`, which ensures setting the `QuicTransportConfig` correctly.

This also organizes the quinn imports and labels where each type comes from.
@ramfox ramfox self-assigned this Dec 10, 2025
@ramfox ramfox changed the base branch from main to feat-multipath December 10, 2025 05:33
@github-actions
Copy link

github-actions bot commented Dec 10, 2025

Documentation for this PR has been generated and is available at: https://n0-computer.github.io/iroh/pr/3757/docs/iroh/

Last updated: 2025-12-12T03:28:29Z

@ramfox ramfox added this to iroh Dec 10, 2025
@github-project-automation github-project-automation bot moved this to 🏗 In progress in iroh Dec 10, 2025
Copy link
Contributor

@flub flub left a comment

Choose a reason for hiding this comment

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

Really nice to get all the imports cleaned up, thank you for slogging through that!

self,
server_config: Arc<ServerConfig>,
) -> Result<Accepting, ConnectionError> {
pub fn accept_with(self, server_config: ServerConfig) -> Result<Accepting, ConnectionError> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Curious why the signature change? It does make sense to put the Arc into the user's control. Usually you'd call this many times with the same config and thus would be forced to clone the ServerConfig a lot.

Copy link
Member Author

@ramfox ramfox Dec 12, 2025

Choose a reason for hiding this comment

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

yea that's a good point and I will add it back, since it does save some resources, however I removed it because our new-typing kind of made cloning the inner quinn::ServerConfig necessary.

We need to have a non-arc'ed quinn::ServerConfig inside our ServerConfig so that we can edit it, so under the hood we have to clone the quinn::ServerConfig anyway 🙃

If I'm thinking about it the wrong way, I'm happy to be wrong.

}

/// Create a default config with a particular handshake token key
pub fn new(crypto: Arc<dyn CryptoServerConfig>, token_key: Arc<dyn HandshakeTokenKey>) -> Self {
Copy link
Contributor

Choose a reason for hiding this comment

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

My inclination would be to forbid people from customising the ServerConfig::crypto entirely. Accessing it via the pub fn crypto function above is fine I think.

Copy link
Contributor

Choose a reason for hiding this comment

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

Looking at the default code that creates this it seems that the token_key is normally 64 bytes of randomness put into ring::hkdf::Salt::new(hkdf::HKDF_SHA256, &[]).extract(&the_64_random_bytes). It feels like a tall order to ask folks to figure this out, though on the other hand it's a suitably high barrier to using this API which could be helpful.

Anyway, point is I think it's fine to allow folks to customise this value.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, seems like with_crypto was the API that allowed you to bypass constructing that token_key. We could make new without any arguments and have a with_token_key constructor that takes the token_key I guess.

Copy link
Member Author

@ramfox ramfox Dec 12, 2025

Choose a reason for hiding this comment

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

Okay, so we can't just create a ServerConfig using a new without any arguments from some outside source. To allow users to create a StaticConfig that doesn't totally bork iroh, I added a method on the Endpoint called create_server_config (bikeshed welcome). It uses the internal StaticConfig that contains the TLS options and default transport config options, but expects the method caller to supply alpns.

That way a user can then replace the bits we want to allow them to replace, without replacing expected iroh crypto.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah, seems like with_crypto was the API that allowed you to bypass constructing that token_key. We could make new without any arguments and have a with_token_key constructor that takes the token_key I guess.

Oh, also the token_key (now set_token_key) method allows setting a different token key already, so I think we have that covered?

@ramfox ramfox requested a review from flub December 12, 2025 03:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: 🏗 In progress

Development

Successfully merging this pull request may close these issues.

3 participants