-
Notifications
You must be signed in to change notification settings - Fork 184
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(iroh)!: Wrap the Connection struct so we own the type #3110
Conversation
This makes iroh own the Connection type. This is desireable because: - Some: upstream APIs don't work well for us, e.g. Connection::remote_address is not that meaningful. This allows us to remove those and replace them with more appropriate APIs. This has not yet been done in this PR however. - The connection type and changes are currently on the Endpoint, they also belong on the Connection. - Connection information, like which pats are used, the latencies of those paths etc, also belong on the Connection. - It is generally not great to expose types which you have no control over in your public API. For the 1.0 we do not want to have any such structs. This takes an important step in that direction. As part of this change Connection::remote_node_id replaces the get_remote_node_id function. Also Connection::alpn now exists.
Documentation for this PR has been generated and is available at: https://n0-computer.github.io/iroh/pr/3110/docs/iroh/ Last updated: 2025-01-23T13:51:13Z |
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 really like this.
I'd personally love to go even further and remove Connection::remote_address
already, etc. but I get that you're going to do that as follow-ups instead.
You requested a review of this, but there weren't any changes since I last accepted this PR. |
The new review requests is to see whether you're happy with #3110 (comment) and deferring it to an issue. |
The |
Hehe, see also the discussion here: #3123 |
succumb to the "same review twice" feedback flub. Just... succumb. 😂 |
Fine by me! If you're all sure that these are real invariants that won't change them I'm all for it. I don't like that they'd need an So please tell me: should I unwrap/expect all these:
so that they are no longer |
Actually, sorry. I took a closer look at this again. I think the right thing to do would be to just ship the PR as is - and then we'll hash out a way to do this without |
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 think checking handshake_data
and whether an ALPN is present
- should be an
Err(ConnectionError)
inConnecting::alpn
and<Connecting as Future>::poll
- should be an
.expect
inConnection::<methods>
It's entirely possible we get an Incoming
and Connecting
from an untrusted peer with e.g. a modified iroh. We don't want to crash because we receive such a connection attempt.
But once we actually verified the Connecting
and turned it into a Connection
, it should be safe to .expect
, since the state in the Connection
isn't determined by the remote anymore, but instead was checked by us previously when it was a Connecting
.
iroh/src/endpoint.rs
Outdated
pub fn peer_identity(&self) -> Box<dyn Any> { | ||
self.inner | ||
.peer_identity() | ||
.expect("we always have a peer identity") |
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 like this expect, but I don't understand where this is checked.
Can we have a message similar to the above? ("checked in <...>")
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 assume we have this any time we manage to establish the TLS connection with our configuration. But yes, the message can be better.
iroh/src/endpoint.rs
Outdated
} | ||
let certs = data | ||
.downcast::<Vec<rustls::pki_types::CertificateDer>>() | ||
.expect("we always have a cert"); |
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.
Would prefer a message like "checked in ::poll" (and actually checking it there).
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 was assuming that this type would always be correct if we got this far. But maybe it's not.
iroh/src/endpoint.rs
Outdated
let handshake_data = conn.handshake_data(); | ||
let handshake_data = handshake_data | ||
.downcast::<quinn::crypto::rustls::HandshakeData>() | ||
.expect("fixed crypto setup for iroh"); |
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.
Sorry for the back and forth on this.
I actually don't think this should be an .expect
, because you cannot guarantee that the other side runs a truthful implementation of iroh.
If we keep it like this, this is a free ticket for getting DoSed from anyone who knows your NodeId, if you're accepting connections.
(I mean we're far from being DoS-safe, but let's at least try to avoid it in this case.)
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.
It is my understanding that this downcast only depends on how we configure Rustls. If the other side does something different this does not make a difference to the type can downcast to.
iroh/src/endpoint.rs
Outdated
Err(_) => bail!("unknown handshake type"), | ||
let data = data | ||
.downcast::<quinn::crypto::rustls::HandshakeData>() | ||
.expect("fixed crypto setup for iroh"); |
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.
(similar to the other comment - at this point we haven't verified that the handshake data is there for sure, so we should probably return an error if it isn't. IMO a CONNECTION_REFUSED is totally fine for this case as well.)
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 going to remove the last commit that was trying to remove some Options and Results. I think it mixes two separate efforts, it will be a lot nicer to have this merged independently with separate PRs, discussions and commit messages.
Also, it really not clear everything is correct. Even the checks I added for the ALPN are weird: because of our Rustls config we probably don't need those. But it gets worse, we can still create a server with no ALPN but then just can't connect to it. This needs more time. I'll file an issue for this instead.
Edit: I updated #3123 instead.
iroh/src/endpoint.rs
Outdated
let handshake_data = conn.handshake_data(); | ||
let handshake_data = handshake_data | ||
.downcast::<quinn::crypto::rustls::HandshakeData>() | ||
.expect("fixed crypto setup for iroh"); |
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.
It is my understanding that this downcast only depends on how we configure Rustls. If the other side does something different this does not make a difference to the type can downcast to.
iroh/src/endpoint.rs
Outdated
pub fn peer_identity(&self) -> Box<dyn Any> { | ||
self.inner | ||
.peer_identity() | ||
.expect("we always have a peer identity") |
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 assume we have this any time we manage to establish the TLS connection with our configuration. But yes, the message can be better.
iroh/src/endpoint.rs
Outdated
} | ||
let certs = data | ||
.downcast::<Vec<rustls::pki_types::CertificateDer>>() | ||
.expect("we always have a cert"); |
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 was assuming that this type would always be correct if we got this far. But maybe it's not.
68ce91e
to
4741be8
Compare
Pushed without the last commit that changes APIs. Let's not mix things up. |
Description
This makes iroh own the Connection type. This is desirable because:
Some: upstream APIs don't work well for us,
e.g. Connection::remote_address is not that meaningful. This allows
us to remove those and replace them with more appropriate APIs. This
has not yet been done in this PR however.
The connection type and changes are currently on the Endpoint, they
also belong on the Connection.
Connection information, like which pats are used, the latencies of
those paths etc, also belong on the Connection.
It is generally not great to expose types which you have no control
over in your public API. For the 1.0 we do not want to have any
such structs. This takes an important step in that direction.
As part of this change Connection::remote_node_id replaces the
get_remote_node_id function. Also Connection::alpn now exists.
Breaking Changes
iroh
iroh::endpoint::get_remote_node_id
has been removed. Useiroh::endpoint::Connection::remote_node_id
instead.Notes & open questions
This does not yet clean up the existing methods in the Connection,
preserving most of them as-is. It is easier to handle those
separately as each one involves careful decisions about the API.
Replaces #2768
Change checklist