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

Rework the way one combines NetworkBehaviours together #1021

Closed
tomaka opened this issue Mar 22, 2019 · 6 comments
Closed

Rework the way one combines NetworkBehaviours together #1021

tomaka opened this issue Mar 22, 2019 · 6 comments

Comments

@tomaka
Copy link
Member

tomaka commented Mar 22, 2019

The NetworkBehaviour custom derive is a bit weird in terms of API (especially when it comes to the event handling trait and having to override a poll() function), and is also imprecise in terms of ordering of operations.

For example, addresses_of_peers is supposed to return the addresses in a specific order, but it is unclear to the user how to influence this order.

I think a better solution would be to make the trait easy to implement manually, so that everything is clear.
Additionally, we would provide in libp2p itself some common combinations to easily get started, such as Ping+Identify+Kademlia+Floodsub+mDNS.

@tomaka tomaka changed the title Remove the NetworkBehaviour custom derive, and instead make NetworkBehaviour easy to implement Remove the way one combines NetworkBehaviours together Mar 28, 2019
@tomaka
Copy link
Member Author

tomaka commented Mar 28, 2019

I think a better solution would be to make the trait easy to implement manually, so that everything is clear.
Additionally, we would provide in libp2p itself some common combinations to easily get started, such as Ping+Identify+Kademlia+Floodsub+mDNS.

Alternatively, a different (and IMO better) long term vision for combining network behaviours together would be to do something like that:

let behaviour = Ping::new().join(Identify::new()).join(Kademlia::new());
let swarm = Swarm::new(behaviour, ...);

At the moment the problem with that is that we cannot easily express the type of the Swarm. It would be extremely long and annoying to do so. This can be solved:

  • Either with impl Trait in the future.
  • Or by adding a BoxedNetworkBehaviour type similar to BoxedTransport and BoxedStreamMuxer.

So the first step for this issue would be to create a BoxedNetworkBehaviour that takes as little template parameters as possible (normally just the substream and event type) and makes it possible to abstract over a NetworkBehaviour.

@tomaka tomaka changed the title Remove the way one combines NetworkBehaviours together Rework the way one combines NetworkBehaviours together Mar 28, 2019
@tomaka
Copy link
Member Author

tomaka commented Apr 28, 2019

Another possibility would be to specialize the Swarm a bit more.
Instead of having only NetworkBehaviour, we would have several DiscoveryBehaviour, PubsubBehaviour, etc. traits with a mandatory output event type and a mandatory set of methods to implement. This makes it possible to combine behaviours in a straight-forward way.

@tomaka
Copy link
Member Author

tomaka commented Oct 8, 2019

Digging up this issue.

So the first step for this issue would be to create a BoxedNetworkBehaviour that takes as little template parameters as possible (normally just the substream and event type) and makes it possible to abstract over a NetworkBehaviour.

I think this is the way to go, not only for grouping together network behaviours but also as a general direction.

One major pain points of the API of rust-libp2p right now in my opinion is the fact that being generic over a NetworkBehaviour requires you to copy-paste most of these trait bounds into your code:

where TBehaviour: NetworkBehaviour<ProtocolsHandler = THandler>,
TMuxer: StreamMuxer + Send + Sync + 'static,
<TMuxer as StreamMuxer>::OutboundSubstream: Send + 'static,
<TMuxer as StreamMuxer>::Substream: Send + 'static,
TTransport: Transport<Output = (TConnInfo, TMuxer)> + Clone,
TTransport::Error: Send + 'static,
TTransport::Listener: Send + 'static,
TTransport::ListenerUpgrade: Send + 'static,
TTransport::Dial: Send + 'static,
THandlerErr: error::Error,
THandler: IntoProtocolsHandler + Send + 'static,
<THandler as IntoProtocolsHandler>::Handler: ProtocolsHandler<InEvent = TInEvent, OutEvent = TOutEvent, Substream = Substream<TMuxer>, Error = THandlerErr> + Send + 'static,
<<THandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::InEvent: Send + 'static,
<<THandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::OutEvent: Send + 'static,
<<THandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::Error: Send + 'static,
<<THandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::OutboundOpenInfo: Send + 'static, // TODO: shouldn't be necessary
<<THandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::InboundProtocol: InboundUpgrade<Substream<TMuxer>> + Send + 'static,
<<<THandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::InboundProtocol as UpgradeInfo>::Info: Send + 'static,
<<<THandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::InboundProtocol as UpgradeInfo>::InfoIter: Send + 'static,
<<<<THandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::InboundProtocol as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send + 'static,
<<<THandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::InboundProtocol as InboundUpgrade<Substream<TMuxer>>>::Error: Send + 'static,
<<<THandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::InboundProtocol as InboundUpgrade<Substream<TMuxer>>>::Future: Send + 'static,
<<THandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::OutboundProtocol: OutboundUpgrade<Substream<TMuxer>> + Send + 'static,
<<<THandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::OutboundProtocol as UpgradeInfo>::Info: Send + 'static,
<<<THandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::OutboundProtocol as UpgradeInfo>::InfoIter: Send + 'static,
<<<<THandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::OutboundProtocol as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send + 'static,
<<<THandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::OutboundProtocol as OutboundUpgrade<Substream<TMuxer>>>::Future: Send + 'static,
<<<THandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::OutboundProtocol as OutboundUpgrade<Substream<TMuxer>>>::Error: Send + 'static,
<NodeHandlerWrapper<<THandler as IntoProtocolsHandler>::Handler> as NodeHandler>::OutboundOpenInfo: Send + 'static, // TODO: shouldn't be necessary
TConnInfo: ConnectionInfo<PeerId = PeerId> + fmt::Debug + Clone + Send + 'static,

@tomaka
Copy link
Member Author

tomaka commented Jan 23, 2020

So the first step for this issue would be to create a BoxedNetworkBehaviour that takes as little template parameters as possible (normally just the substream and event type) and makes it possible to abstract over a NetworkBehaviour.

I ended up implementing that (in a local branch).
The problem is that you then cannot call the methods of the NetworkBehaviour.

I think that doing this would also be a good idea:

Instead of having only NetworkBehaviour, we would have several DiscoveryBehaviour, PubsubBehaviour, etc. traits with a mandatory output event type and a mandatory set of methods to implement. This makes it possible to combine behaviours in a straight-forward way.

@mxinden
Copy link
Member

mxinden commented Jan 24, 2020

Related pull request: #1405

@thomaseizinger
Copy link
Contributor

I don't think we will be doing this any time soon, closing as stale.

@thomaseizinger thomaseizinger closed this as not planned Won't fix, can't repro, duplicate, stale Mar 29, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants