-
Notifications
You must be signed in to change notification settings - Fork 148
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
feat: add MagicEndpoint to iroh-net #1133
feat: add MagicEndpoint to iroh-net #1133
Conversation
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've also been wondering about simplifying the use of the magicsocket. But I was initially thinking of adding a bit of functionality to Conn
(or maybe a new MagicEndpoint
, this is a pretty good name) that would have a method to give you a new quinn::Endpoint
which is configured to use this magicsocket.
That way you'd have to call .add_know_addrs()
and .get_mapping_addr()
before you can call .connect()
on a quinn::Endpoint
making the relation between both sockets endpoints a bit more explicit. But it would not put us in the game of having to wrap all quinn::Endpoint
APIs.
iroh-net/src/defaults.rs
Outdated
host_name: "derp.iroh.network".into(), | ||
stun_only: false, | ||
stun_port: 3478, | ||
ipv4: UseIpv4::Some("35.175.99.113".parse().unwrap()), |
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.
FWIW I tend to slightly prefer one of the non-.parse().unwrap()
variants, e.g. (35.175.99.133).into()
or similar (writing this from memory after a holiday - so that's probably wrong!).
More interestingly though: are we fine with hardcoding an IP address here?
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.
Ack to the first comment. Wrt to the second, I don't know ;-) Copied it from iroh/config.rs
.
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.
More interestingly though: are we fine with hardcoding an IP address here?
It is not great, but okay for the moment I would say
iroh-net/src/endpoint.rs
Outdated
client_config | ||
}; | ||
|
||
debug!("connecting to {}: (via {} - {:?})", peer_id, addr, addrs); |
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 wonder if the addrs
is really correct here? it could have even more addresses than we have here in the addrs
variable i think?
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.
Very much possible, I copied this from iroh-net/src/client.rs:132
and did not check it at all
Aha, yeah that would work as well. Somehow, the notion of
That is true. However, the API surface of
|
Thanks for the reviews! I added a |
@Frando would be great if you could do the integration/usage of it in |
iroh-net/src/endpoint.rs
Outdated
pub async fn bind(self, bind_addr: SocketAddr) -> anyhow::Result<MagicEndpoint> { | ||
let keypair = self.keypair.unwrap_or_else(|| Keypair::generate()); | ||
let tls_server_config = | ||
tls::make_server_config(&keypair, self.alpn_protocols, self.keylog)?; |
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.
does this error if alpn_protocols
is empty?
dd39d43
to
a9a6693
Compare
Allright, I took a stab at this, the latest commit uses |
Very nice and clean :) really like having this abstraction. |
@Frando the last integration I would love to see is replacing the structure in |
I just had a look at this. The tests access more internals of the magic socket than the current API exposes. Most seems to me for validation of those internals.
I haven't worked with the internals of the magic socket much yet so not sure if those are needed outside of testing. So, should I ..
|
And CI passed on the last commit, including CLI tests! Only netsim failures, but seems unrelated (github bucket something something) |
I think a first pass just exposing things that are needed using |
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.
some smaller nits, other than that this is looking good :)
ff41242
to
0c6bfe0
Compare
I addressed the last comments and rebased onto main. Let's see what CI says. One thing I'm not super sure about is the netmap managment. But I think this can be refined later. |
@@ -2649,7 +2658,7 @@ mod tests { | |||
nodes: vec![DerpNode { | |||
name: "t1".into(), | |||
region_id: 1, | |||
host_name: "http://test-node.invalid".parse().unwrap(), | |||
host_name: "https://test-node.invalid".parse().unwrap(), |
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.
does this need to be https
?
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.
probably does, just wondering why this change was necessary now
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.
good question. I can't tell for sure, but this way the tests passed.
pub mod hp; | ||
pub mod magic_endpoint; |
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.
can we make this private, if we reexport the MagicEndpoint
?
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.
There's also the MagicEndpointBuilder
struct and accept_conn
functions in there (and possible get_alpn
and get_peer_id
, see below). Not sure if they should all be at the top level?
I think I'd defer this to later, currently pretty much everything in iroh-net
is public anyway - and once things stabilize a bit we might want to change this overall and actually define the public API surface for iroh-net
?
} | ||
|
||
/// Extract the [`PeerId`] from the peer's TLS certificate. | ||
pub async fn get_peer_id(connection: &quinn::Connection) -> anyhow::Result<PeerId> { |
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.
does this need to be public?
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.
So they are used in the accept_conn
above, which definitely should be public. I left them public, because get_alpn
already works after the first handshake phase (on quinn::Connecting
) whereas get_peer_id
only works on the established quinn::Connection
. So I wasn't sure if maybe you'd want to do the alpn extraction earlier, potentially abort if it's not what you expected, and then to get_peer_id
afterwards. However I don't think it makes much of a difference, so also fine to make them non-public for now and advise to use accept_conn
.
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.
lets leave it as is for now then
* move dial_peer onto MagicEndpoint * some renames for clarity * remove iroh_net::client module
08c9154
to
0129484
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.
Nice! Most of my comments are about the public docs from a user point of view. But nothing is blocking.
iroh-net/src/magic_endpoint.rs
Outdated
/// Connect to a remote endpoint, creating an endpoint on the fly. | ||
/// | ||
/// The PeerId and the ALPN protocol are required. If you happen to know dialable addresses of | ||
/// the remote endpoint, they can be specified and will be added to the endpoint's peer map. |
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.
Is it possible to describe what the "endpoint's peer map" means?
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 removed the term for now and took over the description you proposed in connect
iroh-net/src/magic_endpoint.rs
Outdated
.conn | ||
.get_mapping_addr(&node_key) | ||
.await | ||
.expect("just inserted"); |
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.
There is an .await
involved... so who knows?
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.
True! Made it an error instead. Will have to check in practice if this occurs, but not panicing sounds like the right thing to do.
} | ||
|
||
/// Accept an incoming connection and extract the client-provided [`PeerId`] and ALPN protocol. | ||
pub async fn accept_conn( |
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'd be tempted to experiment with an extension trait or a wrapper for Connecting
(and I guess Accept
). But we can do that later.
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.
Yup I thought about that too. However we'd either have to use async_trait
or write the futures by hand. I'd defer this to post-merge I think.
@@ -2826,7 +2820,7 @@ mod tests { | |||
}) | |||
} | |||
|
|||
fn setup_logging() { | |||
pub fn setup_logging() { |
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 kind of wish you copied in iroh-bytes/src/test_utils.rs
to iroh-net/src/test_utils.rs
and used it's setup_logging
call for your functions instead of making this pub... But I tried to clean this up earlier and utterly failed failed. For new #[tokio::test]
tests it should just work though, since they're single-threaded runtimes. Just don't try change existing tests.
But if you don't want to do that now that's fine, it's my fault for not managing to clean this up before.
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.
Yes this sounds good to me too. I also want to expose run_derp_and_stun
in a test_util module also to other crates (i.e. iroh-gossip) that use iroh-net and need to test things with a local derper.
However I'd prefer to do this after the merge in a new PR.
This is a first pass at adding a
MagicEndpoint
that combines a magicsock and a quinn endpoint. The API is minimalistic so far and allows to both accept and create connections. I also added two utility functions to extract the ALPN and PeerId on incoming connections, and a maximally-simple example to test things.An endpoint-like struct that can create and accept connections will be needed for peer-to-peer sockets as e.g. in the upcoming gossipswarm impl. (It could also work with functions only but would involve more code copying I think).
I mostly copied code around from the existing listen and dial functions. No tests or other code is yet converted over to actually use this. Sharing now to get feedback on the API.