-
Notifications
You must be signed in to change notification settings - Fork 171
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: add iroh_net::ConnManager
and use in iroh_gossip::net
#2315
base: main
Are you sure you want to change the base?
Conversation
net
module
In plain TCP simultaneous connect from both sides results in a single connection if socket is bound to a port and the other side tries to connect to the same port: https://stackoverflow.com/questions/2231283/tcp-two-sides-trying-to-connect-simultaneously |
ad018a6
to
6229f8a
Compare
fda1736
to
c8265ee
Compare
net
moduleiroh_net::ConnManager
and use in iroh_gossip::net
d1c775a
to
3b28b28
Compare
0fcb423
to
240eb7a
Compare
240eb7a
to
f70e519
Compare
c204d78
to
95fdddb
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not yet sure about the ConnManager
. I'd be more comfortable if we had some sort of "exprimental" cargo feature or something for it maybe.
impl TestEndpointBuilder { | ||
/// Starts local relay and discovery servers and returns a builder to create readily configured endpoints. | ||
/// | ||
/// The local relay, DNS and pkarr servers will shut down once the [`TestEndpointBuilder`] is dropped. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe also make clear these are listening on a random port on localhost only?
} | ||
|
||
/// Create a new endpoint builder which already has discovery and relays configured. | ||
pub fn create_endpoint_builder(&self, secret_key: SecretKey) -> crate::endpoint::Builder { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Simply endpoint_builder()
is probably a better name?
#[deref] | ||
pub conn: Connection, | ||
/// The node id of the other peer. | ||
pub node_id: NodeId, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can always get the NodeId
from the Connection
, so this is storing duplicate information.
|
||
/// The error returned from [`ConnManager::poll_next`]. | ||
#[derive(thiserror::Error, Debug)] | ||
#[error("Connection to node {} direction {:?} failed: {:?}", self.node_id, self.direction, self.reason)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this use the short NodeId
? This is done by using the alternate formatting: {:#}
. I'm a bit in two minds about it.
/// This is a no-op if the a connection to the node is already active or if we are currently | ||
/// dialing the node already. | ||
/// | ||
/// Returns `true` if this is initiates connecting to the node. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Returns `true` if this is initiates connecting to the node. | |
/// Returns `true` if this initiates a new connection attempt. |
/// the [`ConnManager`]'s execpected ALPN before passing the connection to the sender. | ||
/// | ||
/// If we are currently dialing the node, the connection will be dropped if the peer's node id | ||
/// sorty higher than our node id. Otherwise, the connection will be yielded from the manager |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// sorty higher than our node id. Otherwise, the connection will be yielded from the manager | |
/// sorts higher than our node id. Otherwise, the connection will be yielded from the manager |
Part of me feels this might belong better in the protocol running on top of the provided quic connection rather than in the endpoint layer itself. And to me iroh-net is about the endpoint layer, not the application on top. I'm a little sceptical that an application does even need support like this. Could it not keep a map of confirmed connections, i.e. when it received data on a connection. Any time a connection receives data for the first time, whether that connection was dialed or accepted, it can check the map and reset the connection if the NodeId already exists. This is like a very opiniated and specific version of this. |
Yes, I'm also not too sure anymore. I thought initially that this could be done without opening any streams, which would put it more into endpoint-layer land. Alas, an extra roundtrip, and thus opening streams, is required for consistent deduplication it seems. Which puts it more into application protocol land. At the same time it is a quite common usecase for p2p protocols, and offering something easy-to-use would be nice. Sounds a bit like iroh-net-utils or so material. |
/// Accept a connection. | ||
/// | ||
/// This does not check the connection's ALPN, so you should make sure that the ALPN matches | ||
/// the [`ConnManager`]'s execpected ALPN before passing the connection to the sender. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// the [`ConnManager`]'s execpected ALPN before passing the connection to the sender. | |
/// the [`ConnManager`]'s expected ALPN before passing the connection to the sender. |
/// the [`ConnManager`]'s execpected ALPN before passing the connection to the sender. | ||
/// | ||
/// If we are currently dialing the node, the connection will be dropped if the peer's node id | ||
/// sorty higher than our node id. Otherwise, the connection will be returned. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// sorty higher than our node id. Otherwise, the connection will be returned. | |
/// sorts higher than our node id. Otherwise, the connection will be returned. |
/// rejects the connection if the peer's node id sorts higher than their own node id. | ||
/// | ||
/// To make this reliable even if the dials happen exactly at the same time, a single unidirectional | ||
/// stream is opened, on which a single byte is sent. This additional rountrip ensures that no |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where exactly this sending of a byte happens? Did not find it quickly looking through the changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here:
iroh/iroh-net/src/conn_manager.rs
Line 299 in bfee584
stream.write_all(&[0]).await?; |
I agree something like this is needed. But - how will this play together with the new custom protocols stuff? The custom protocol handler uses the standard endpoint accept. So maybe this needs to be integrated more deeply into iroh-net or at least into the iroh node? |
Description
ConnManager
in iroh_net. Quoting the docs:ConnManager
iniroh_gossip::net
and improve connection handlingBreaking Changes
Notes & open questions
Change checklist