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

refactor(iroh): Allow to register custom protocols #2358

Merged
merged 35 commits into from
Jun 19, 2024
Merged

Conversation

Frando
Copy link
Member

@Frando Frando commented Jun 12, 2024

Description

  • feat(iroh-net): Allow to set the list of accepted ALPN protocols at runtime
  • refactor(iroh): Spawning a node can now be performed in two stages: First Builder::build() is called, which returns a Future that resolves to a new type ProtocolBuilder. The ProtocolBuilder is then spawned into the actual, running Node. If the intermediate step is not needed, Builder::spawn performs both in one call, therefore this change is not breaking.
  • feat(iroh): Allow to accept custom ALPN protocols in an Iroh node. Introduce a ProtocolHandler trait for accepting incoming connections and adds ProtocolBuilder::accept to register these handlers per ALPN.
  • refactor(iroh): Move towards more structured concurrency by spawning tasks into a JoinSet
  • refactor(iroh): Improve shutdown flow and perform more things concurently.

originally based on #2357 but now directly to main

Breaking Changes

  • iroh_net::endpoint::make_server_config takes Arc<quinn::TransportConfig> instead of Option<quinn::TransportConfig>. If you used the None case, replace with quinn::TransportConfig::default().

Notes & open questions

Change checklist

  • Self-review.
  • Documentation updates if relevant.
  • Tests if relevant.
  • All breaking changes documented.

iroh/src/node.rs Outdated Show resolved Hide resolved
@Frando Frando force-pushed the optional-protocols branch from a439a5f to 9a46f6f Compare June 12, 2024 16:27
@Frando Frando force-pushed the optional-protocols branch from 9a46f6f to a369048 Compare June 12, 2024 16:35
@dignifiedquire dignifiedquire added this to the v0.19.0 milestone Jun 13, 2024
@Frando Frando force-pushed the optional-protocols branch from 40f734f to 5703d6e Compare June 13, 2024 22:08
@Frando Frando changed the title refactor(iroh): Use new protocols API and make docs engine optional refactor(iroh): Allow to register custom protocols and make docs engine optional Jun 13, 2024
@Frando Frando changed the base branch from custom-protocols-new to main June 13, 2024 23:13
iroh-net/src/endpoint.rs Outdated Show resolved Hide resolved
iroh/src/node/builder.rs Outdated Show resolved Hide resolved
iroh/src/node/builder.rs Outdated Show resolved Hide resolved
iroh/src/node.rs Outdated Show resolved Hide resolved
/// Note that the client returned from [`Self::client`] can only be used after spawning the node,
/// until then all RPC calls will time out.
#[derive(derive_more::Debug)]
pub struct UnspawnedNode<D, E> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe call this CustomProtocolBuilder since you will use it only when you want to register custom protocols? Naming 🤷

Copy link
Member Author

Choose a reason for hiding this comment

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

Went with ProtocolBuilder for now. Open to changing further :)

Copy link
Contributor

@rklaehn rklaehn left a comment

Choose a reason for hiding this comment

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

Added a bunch of comments. Overall looks great.

@Frando
Copy link
Member Author

Frando commented Jun 19, 2024

Addressed most review comments. And:

  • Renamed UnspawnedNode to ProtocolBuilder

Other public API namings we could bikeshed a bit:

  • trait Protocol: Fine as is? Or better ProtocolHandler?
  • ProtocolBuilder::accept(&self, alpn: &'static [u8], protocol: Arc<dyn Protocol>: Fine as is? Or better register_protocol?

I think I'm fine with the current namings, but also very open to changing if others find other names more intuitive.

@rklaehn
Copy link
Contributor

rklaehn commented Jun 19, 2024

trait Protocol: Fine as is? Or better ProtocolHandler?

I don't hate trait Protocol, but like ProtocolHandler a bit more. For me a protocol is a rust module containing a bunch of request and response types, usually in some enums, and some help text describing how to use them (e.g. serialize them with postcard), not something active. Or maybe AcceptHandler? After all the "active/outgoing" part of the protocol might live somewhere else.

ProtocolBuilder::accept(&self, alpn: &'static [u8], protocol: Arc: Fine as is? Or better register_protocol?

I think accept is fine. I mean, this is basically building a dispatcher for accept. As mentioned above, this part is only for the listen/accept part of the protocol, the active part will usually be created before using the iroh-net endpoint and then maybe end up in some tokio task.

@rklaehn
Copy link
Contributor

rklaehn commented Jun 19, 2024

Not sure if we want to address this in this PR or the next, but in Builder::build it now always calls register_iroh_protocols. So there is no way to opt out of them, just to add extra protocols.

I wasn't quite sure how it should look if you want to have a "naked" node. Also, it seems that we are not really ready to create a naked node. So maybe let's do it in the next PR that will allow disabling docs.

@Frando
Copy link
Member Author

Frando commented Jun 19, 2024

I renamed Protocol to ProtocolHandler. Agree with @rklaehn that this looks better.

Not sure if we want to address this in this PR or the next, but in Builder::build it now always calls register_iroh_protocols. So there is no way to opt out of them, just to add extra protocols.

Yup, let's defer this to a followup.

@Frando Frando added this pull request to the merge queue Jun 19, 2024
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.

I like this approach of structured concurrency, essentially the same as I did in iroh-relay. Also TIL about SharedAbortingJoinHandle. I'm a little unsure if there's any downsides to having many clones of the JoinHandle, but let's see. It makes it a lot easier to use.

})
}

/// Set the list of accepted ALPN protocols.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
/// Set the list of accepted ALPN protocols.
/// Sets the list of accepted ALPN protocols.

https://github.com/rust-lang/rfcs/blob/master/text/1574-more-api-documentation-conventions.md#appendix-a-full-conventions-text

unspawned_node.spawn().await
}

/// Build a node without spawning it.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
/// Build a node without spawning it.
/// Builds a node without spawning it.


/// Build a node without spawning it.
///
/// Returns an `UnspawnedNode`, on which custom protocols can be registered with
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
/// Returns an `UnspawnedNode`, on which custom protocols can be registered with
/// Returns an [`UnspawnedNode`], on which custom protocols can be registered with

}

impl<D: iroh_blobs::store::Store, E: ServiceEndpoint<RpcService>> ProtocolBuilder<D, E> {
/// Register a protocol handler for incoming connections.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
/// Register a protocol handler for incoming connections.
/// Registers a protocol handler for incoming connections.

self
}

/// Return a client to control this node over an in-memory channel.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
/// Return a client to control this node over an in-memory channel.
/// Returns a client to control this node over an in-memory channel.

self.protocols.get_typed(alpn)
}

/// Register the core iroh protocols (blobs, gossip, docs).
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
/// Register the core iroh protocols (blobs, gossip, docs).
/// Registers the core iroh protocols (blobs, gossip, docs).

self
}

/// Spawn the node and start accepting connections.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
/// Spawn the node and start accepting connections.
/// Spawns the node and start accepting connections.


impl ProtocolMap {
/// Returns the registered protocol handler for an ALPN as a concrete type.
pub fn get_typed<P: ProtocolHandler>(&self, alpn: &[u8]) -> Option<Arc<P>> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we have the same visibility marker here as on the struct, so pub(super)? I find that a lot easier to read. Plus there's fewer surprises: if the super module decides to export this than suddenly these functions are really pub, and that might have been unintended.

self.0.get(alpn).cloned()
}

/// Insert a protocol handler.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
/// Insert a protocol handler.
/// Inserts a protocol handler.

self.0.keys()
}

/// Shutdown all protocol handlers.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
/// Shutdown all protocol handlers.
/// Shuts down all protocol handlers.

Merged via the queue into main with commit 13ded84 Jun 19, 2024
27 checks passed
github-merge-queue bot pushed a commit that referenced this pull request Jun 19, 2024
## Description

Addresses review by @flub on #2358 (which is already merged).

## Breaking Changes

<!-- Optional, if there are any breaking changes document them,
including how to migrate older code. -->

## Notes & open questions

<!-- Any notes, remarks or open questions you have to make about the PR.
-->

## Change checklist

- [x] Self-review.
- [x] Documentation updates if relevant.
- [ ] ~~Tests if relevant.~~
- [x] All breaking changes documented.
ppodolsky pushed a commit to izihawa/iroh that referenced this pull request Jun 22, 2024
* feat(iroh-net): Allow to set the list of accepted ALPN protocols at
runtime
* refactor(iroh): Spawning a node can now be performed in two stages:
First `Builder::build()` is called, which returns a Future that resolves
to a new type `ProtocolBuilder`. The `ProtocolBuilder` is then spawned
into the actual, running `Node`. If the intermediate step is not needed,
`Builder::spawn` performs both in one call, therefore this change is not
breaking.
* feat(iroh): Allow to accept custom ALPN protocols in an Iroh node.
Introduce a `ProtocolHandler` trait for accepting incoming connections
and adds `ProtocolBuilder::accept` to register these handlers per ALPN.
* refactor(iroh): Move towards more structured concurrency by spawning
tasks into a `JoinSet`
* refactor(iroh): Improve shutdown flow and perform more things
concurently.

originally based on n0-computer#2357 but now directly to main

* `iroh_net::endpoint::make_server_config` takes
`Arc<quinn::TransportConfig>` instead of
`Option<quinn::TransportConfig>`. If you used the `None` case, replace
with `quinn::TransportConfig::default()`.

<!-- Any notes, remarks or open questions you have to make about the PR.
-->

- [x] Self-review.
- [x] Documentation updates if relevant.
- [ ] Tests if relevant.
- [x] All breaking changes documented.
ppodolsky pushed a commit to izihawa/iroh that referenced this pull request Jun 22, 2024
## Description

Addresses review by @flub on n0-computer#2358 (which is already merged).

## Breaking Changes

<!-- Optional, if there are any breaking changes document them,
including how to migrate older code. -->

## Notes & open questions

<!-- Any notes, remarks or open questions you have to make about the PR.
-->

## Change checklist

- [x] Self-review.
- [x] Documentation updates if relevant.
- [ ] ~~Tests if relevant.~~
- [x] All breaking changes documented.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

4 participants