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

swarm: Remove PollParameters #3124

Closed
thomaseizinger opened this issue Nov 15, 2022 · 13 comments · Fixed by #4490
Closed

swarm: Remove PollParameters #3124

thomaseizinger opened this issue Nov 15, 2022 · 13 comments · Fixed by #4490

Comments

@thomaseizinger
Copy link
Contributor

Description

Remove the PollParameters trait.

  • local_peer_id can be removed in favor of users having to pass it into their behaviour in the constructor.
  • external_addresses can be built up from the inject_new_external_addr and inject_expired_external_addr callbacks.
  • listened_addresses can be built up from the inject_new_listen_addr and inject_expired_listen_addr callbacks

The only function that does not have a replacement at the moment is supported_protocols.

Any ideas for how we could model that one differently?

As per usual, we should first deprecate the existing functions, give users a release or two to upgrade and then remove the deprecated code.

Motivation

rust-libp2p is primarily designed around an async message-passing system. Accessing information synchronously as part of the poll function is not inline with this philosophy.

Current Implementation

Are you planning to do it yourself in a pull request?

Maybe.

@thomaseizinger thomaseizinger added priority:nicetohave difficulty:easy decision-pending Marks issues where a decision is pending before we can move forward. labels Nov 15, 2022
@mxinden
Copy link
Member

mxinden commented Nov 15, 2022

I am in favor of removing PollParameters.

The only function that does not have a replacement at the moment is supported_protocols.

I suggest similar to how we would communicate supported protocols of remote peers via #2680, we can do the same for supported protocols of the local peer.

As an aside, the set of supported protocols can change at runtime. E.g. libp2p-kad with #2032 will only offer the Kademlia protocol for incoming streams when not behind a firewall or NAT. Thus the current mechanism is flawed.

@thomaseizinger
Copy link
Contributor Author

I am in favor of removing PollParameters.

The only function that does not have a replacement at the moment is supported_protocols.

I suggest similar to how we would communicate supported protocols of remote peers via #2680, we can do the same for supported protocols of the local peer.

As an aside, the set of supported protocols can change at runtime. E.g. libp2p-kad with #2032 will only offer the Kademlia protocol for incoming streams when not behind a firewall or NAT. Thus the current mechanism is flawed.

In theory, it could be that one connection of a node is behind firewall or NAT and the other one isn't. For example, lets say I am listening on TCP and WebRTC connections but only the WebRTC one is port-forwarded.

This thought experiment suggests that we'd have to tell our behaviour the supported protocols PER connection. In a way, this would fit in well with #3099 where we only learn our supported protocols after we established the connection to another peer.

Thoughts?

@mxinden
Copy link
Member

mxinden commented Nov 16, 2022

In theory, it could be that one connection of a node is behind firewall or NAT and the other one isn't. For example, lets say I am listening on TCP and WebRTC connections but only the WebRTC one is port-forwarded.

While I am sure we will find this case in the wild, I would assume that it is rare. Thus I suggest not designing for it.

@rkuhn
Copy link
Contributor

rkuhn commented Nov 16, 2022

My only (but important!) use-case for supported_protocols is that my Identify information going to remote hosts should accurately reflect my set of available protocols with that peer — I use that in multiple places to keep things compatible in a long-term fashion. So if we can enable a behaviour to obtain that list of protocols when an outbound substream is about to be opened, that would be enough.

@thomaseizinger
Copy link
Contributor Author

My only (but important!) use-case for supported_protocols is that my Identify information going to remote hosts should accurately reflect my set of available protocols with that peer — I use that in multiple places to keep things compatible in a long-term fashion. So if we can enable a behaviour to obtain that list of protocols when an outbound substream is about to be opened, that would be enough.

Yes. I think that is the right way to think about it. Because ConnectionHandlers end up deciding about the protocols they use / offer to the other party, we should scope the supported protocols by peer as well.

At the moment, a ConnectionHandler may decide to produce a different protocol for different substreams.

This makes it difficult to accurately cache this information. We'd almost have to tell the NetworkBehaviour upon every substream, whether the list of supported protocols changed.

Instead of that, we could also build a mechanism where a ConnectionHandler has to explicitly emit an "update" of its InboundProtocol if it wants to change it.

@rkuhn
Copy link
Contributor

rkuhn commented Nov 23, 2022

Yes, that sounds good (if my understanding is correct): ConnectionHandler is interrogated for supported protocols at start of connection and can update its contribution by emitting an event, and that (updated) set is available to all sub-handlers of the same connection (by some means TBD). Is that what you meant?

@thomaseizinger
Copy link
Contributor Author

available to all sub-handlers

I wouldn't make the supported protocols available to the other handlers but report it back to the behaviour via a (newly introduced) FromConnection event:

enum FromConnection {
	Event(E),
	ProtocolsChanged(Vec<String>) // Note: Simplified type here.
}

Protocols are specific to a connection so I don't think other connections need to know about them. A behaviour can always forward it though if really needed.

The only thing I don't really like about this design is that a ConnectionHandler ends up providing two ways of exposing protocols:

  • The initially supported protocols
  • The update

Maybe we could make handlers produce an update to begin with and until then, they don't support any protocols?

@rkuhn
Copy link
Contributor

rkuhn commented Nov 24, 2022

My question was not about other connections, it was specifically about handler::either::Either: given an Either<A, B>, what I’m asking is how B will learn of the protocols supported by A so that it can correctly advertise them (in case this is B’s core reponsibility, like B=Identify).


Regarding the Update mechanism: changes will be much less frequent (as witnessed by currently known protocols) than connections, so I’d find it quite reasonable to have a nice and easy (i.e. non-foot-gun) normal case (providing protocols via a method is type-checked) and a documented special case (forgetting to emit that event in some cases will lead to some head scratching when connections “half work”).

@mxinden
Copy link
Member

mxinden commented Nov 30, 2022

Maybe we could make handlers produce an update to begin with and until then, they don't support any protocols?

On start-up the Swarm would call NetworkBehaviour::new_handler and call ConnectionHandler::listen_protocol and then extract the supported protocols @thomaseizinger?

@thomaseizinger
Copy link
Contributor Author

Maybe we could make handlers produce an update to begin with and until then, they don't support any protocols?

On start-up the Swarm would call NetworkBehaviour::new_handler and call ConnectionHandler::listen_protocol and then extract the supported protocols @thomaseizinger?

new_handler would only be called on the first connection, not at start-up.

But yes, listen_protocol would be called once the connection is established.

Perhaps instead of producing an update, the handler could produce an event that just invalidates the "cache" for the supported protocols. A connection would then inquire again about the supported protocols via listen_protocol.

@thomaseizinger
Copy link
Contributor Author

Instead of treating it as a cache, we could also call listen_protocol after each update to the handler.

We would need some kind of diffing strategy to not emit updates about unchanged protocols to the behaviour.

Ideally, before we do that, we already got rid of the "upgrade" notation to have listen_protocol only return the protocol string.

mergify bot pushed a commit that referenced this issue Dec 14, 2022
This patch deprecates 3 out of 4 functions on `PollParameters`:

- `local_peer_id`
- `listened_addresses`
- `external_addresses`

The addresses can be obtained by inspecting the `FromSwarm` event. To make this easier, we introduce two utility structs in `libp2p-swarm`:

- `ExternalAddresses`
- `ListenAddresses`

A node's `PeerId` is always known to the caller, thus we can require them to pass it in.

Related: #3124.
jxs pushed a commit to jxs/rust-libp2p that referenced this issue Dec 14, 2022
)

This patch deprecates 3 out of 4 functions on `PollParameters`:

- `local_peer_id`
- `listened_addresses`
- `external_addresses`

The addresses can be obtained by inspecting the `FromSwarm` event. To make this easier, we introduce two utility structs in `libp2p-swarm`:

- `ExternalAddresses`
- `ListenAddresses`

A node's `PeerId` is always known to the caller, thus we can require them to pass it in.

Related: libp2p#3124.
@thomaseizinger thomaseizinger removed the decision-pending Marks issues where a decision is pending before we can move forward. label Jan 9, 2023
@thomaseizinger
Copy link
Contributor Author

Given that we merged #3153, I am assuming we have agreed that this is a good idea.

@thomaseizinger
Copy link
Contributor Author

With #3651, PollParameters will be completely deprecated and removed in the next release after this one 🎉

@thomaseizinger thomaseizinger added this to the v0.53.0 milestone May 8, 2023
mergify bot pushed a commit that referenced this issue May 8, 2023
With this patch, implementations of `ConnectionHandler` (which are typically composed in a tree) can exchange information about the supported protocols of a remote with each other via `ConnectionHandlerEvent::ReportRemoteProtocols`. The provided `ProtocolSupport` enum can describe either additions or removals of the remote peer's protocols.

This information is aggregated in the connection and passed down to the `ConnectionHandler` via `ConnectionEvent::RemoteProtocolsChange`.

Similarly, if the listen protocols of a connection change, all `ConnectionHandler`s on the connection will be notified via `ConnectionEvent::LocalProtocolsChange`. This will allow us to eventually remove `PollParameters` from `NetworkBehaviour`.

This pattern allows protocols on a connection to communicate with each other. For example, protocols like identify can share the list of (supposedly) supported protocols by the remote with all other handlers. A protocol like kademlia can accurately add and remove a remote from its routing table as a result.

Resolves: #2680.
Related: #3124.

Pull-Request: #3651.
@thomaseizinger thomaseizinger removed this from the v0.53.0 milestone Sep 12, 2023
@thomaseizinger thomaseizinger self-assigned this Sep 22, 2023
@mergify mergify bot closed this as completed in #4490 Oct 24, 2023
mergify bot pushed a commit that referenced this issue Oct 24, 2023
umgefahren pushed a commit to umgefahren/rust-libp2p that referenced this issue Mar 8, 2024
)

This patch deprecates 3 out of 4 functions on `PollParameters`:

- `local_peer_id`
- `listened_addresses`
- `external_addresses`

The addresses can be obtained by inspecting the `FromSwarm` event. To make this easier, we introduce two utility structs in `libp2p-swarm`:

- `ExternalAddresses`
- `ListenAddresses`

A node's `PeerId` is always known to the caller, thus we can require them to pass it in.

Related: libp2p#3124.
umgefahren pushed a commit to umgefahren/rust-libp2p that referenced this issue Mar 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants