Skip to content

feat(iroh): add new protocols to router at runtime #3355

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

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

Frando
Copy link
Member

@Frando Frando commented Jun 23, 2025

Description

This allows adding new protocols and removing protocols to an iroh Router after the router is built.
Also adds a timeout to shutdown for a protocol handler of 30s.

Also wrote a test for this.

Breaking Changes

Notes & open questions

Change checklist

  • Self-review.
  • Documentation updates following the style guide, if relevant.
  • Tests if relevant.

Copy link

github-actions bot commented Jun 23, 2025

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

Last updated: 2025-06-26T11:14:04Z

Copy link

github-actions bot commented Jun 23, 2025

Netsim report & logs for this PR have been generated and is available at: LOGS
This report will remain available for 3 days.

Last updated for commit: 0fcccf4

@n0bot n0bot bot added this to iroh Jun 23, 2025
@github-project-automation github-project-automation bot moved this to 🏗 In progress in iroh Jun 23, 2025
@Frando Frando changed the title feat: add new protocols to router at runtime feat(iroh): add new protocols to router at runtime Jun 23, 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.

largely looks good to me, nice to have this!

#[derive(Debug, Snafu)]
#[non_exhaustive]
pub enum RouterError {
#[snafu(display("The router actor closed"))]
Copy link
Contributor

Choose a reason for hiding this comment

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

"router actor" is something rather internal, no? Can we not say "the router closed" or maybe even "the endpoint closed"?

/// Configures the router to accept the [`ProtocolHandler`] when receiving a connection
/// with this `alpn`.
///
/// Once the function yields, new connections with this `alpn` will be handled.
Copy link
Contributor

Choose a reason for hiding this comment

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

"yields" or returns? As far as I read the code it should be "returns"?

///
/// Once the function yields, new connections with this `alpn` will be handled.
///
/// If a protocol handler was already registered for `alpn`, the previous handler will be shutdown.
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you elaborate more on what happens to existing connections? Will they all be closed by the old handler? How does that work? If you're repeating how handlers shut down connections that's fine, docs should repeat things.

/// Stops accepting a protocol.
///
/// Note that this has only an effect on new connections. Existing connections that were
/// accepted with `alpn` won't be closed when calling [`Router::stop_accepting`].
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you call out the differences in behaviour with calling accept where a previous handler was already handling this protocol?

@Frando
Copy link
Member Author

Frando commented Jun 23, 2025

@flub Thanks for the review, clarified the docs. LMK if there's still something unclear from reading the docs.

@TheButlah
Copy link

TheButlah commented Jun 25, 2025

unsure if I should post here or open an issue. is there some way that we can allow end-users to have a Box<dyn DynProtocolHandler>? Or at least, introduce a BoxedProtocolHandler type? Those types appear private rn.

Use case: facilitating third-party routers, or facilitating storing protocol handlers in structs, such as for the purposes of configuration:

#[derive(Debug, bon::Builder)]
pub struct Agent {
    #[builder(field)]
    handlers: HashMap<Alpn, Box<dyn ProtocolHandler>>,
    /// Provide a specific secret key for mTLS, instead of dynamically generating one
    secret_key: Option<iroh::SecretKey>,
    #[builder(default)]
    discovery: EnabledDiscoveryServices,
    /// in QUIC, the ALPN allows for multiple connections on same port, and it is ideal
    /// to circumvent firewalls to always use port 443 (same as https). You can also set
    /// this to 0 to dynamically choose a port.
    #[builder(default = 443)]
    port: u16,
}

impl<S: agent_builder::State> AgentBuilder<S> {
    fn router(
        mut self,
        alpn: &'static str,
        router: impl Into<Box<dyn ProtocolHandler>>,
    ) -> Self {
        self.handlers.insert(Alpn(alpn), router.into());
        self
    }
}

//...

        let mut router = iroh::protocol::Router::builder(endpoint);
        for (alpn, handler) in self.handlers {
            router = router.accept(alpn.0, handler);
        }

@Frando Frando force-pushed the Frando/router-add-protocol branch from 2aa24ec to 9f01dd5 Compare June 26, 2025 11:12
@Frando
Copy link
Member Author

Frando commented Jun 26, 2025

unsure if I should post here or open an issue. is there some way that we can allow end-users to have a Box<dyn DynProtocolHandler>? Or at least, introduce a BoxedProtocolHandler type? Those types appear private rn.

That's valid, IMO. I opened #3366.

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