-
-
Notifications
You must be signed in to change notification settings - Fork 404
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: QUIC Address discovery extension #2043
base: main
Are you sure you want to change the base?
feat: QUIC Address discovery extension #2043
Conversation
276c164
to
b0f0a30
Compare
eaa83bc
to
5c0e633
Compare
5c0e633
to
60b2e57
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.
Thanks for working on this!
@@ -636,6 +636,12 @@ impl Connection { | |||
// May need to send MAX_STREAMS to make progress | |||
conn.wake(); | |||
} | |||
|
|||
/// Track changed on our external address as reported by the peer. | |||
pub fn observed_external_addr(&self) -> watch::Receiver<Option<SocketAddr>> { |
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.
Explicitly document when this is None
, whether it might contain spurious updates, and the influence of configuration and peer support.
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.
Not sure about exposing the watch::Receiver
as part of the public API, that seems like it's leaking a bunch of implementation details?
/// NOTE: this test is the same as zero_rtt_happypath, changing client transport parameters on | ||
/// resumption. | ||
#[test] | ||
fn address_discovery_zero_rtt_accepted() { |
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.
What additional coverage does this case supply? I don't think changing client transport parameters are ever a concern for 0-RTT.
@@ -3760,6 +3874,8 @@ pub enum Event { | |||
DatagramReceived, | |||
/// One or more application datagrams have been sent after blocking | |||
DatagramsUnblocked, | |||
/// Received an observation of our external address from the peer. |
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.
Explicitly document whether this is necessarily different from the previous one, and the required configuration and peer support.
// include in migration | ||
migration_observed_addr = Some(observed) |
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.
Why is this a special case?
{ | ||
return Err(TransportError::PROTOCOL_VIOLATION( | ||
"received OBSERVED_ADDRESS frame when not negotiated", | ||
)); |
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.
Could we yield this error from within should_report()
instead? (Maybe also pass in packet.header.space()
?)
quinn-proto/src/connection/mod.rs
Outdated
new_path.last_observed_addr_report = self.path.last_observed_addr_report.clone(); | ||
if let Some(report) = observed_addr { | ||
if let Some(updated) = new_path.update_observed_addr_report(report) { | ||
self.events.push_back(Event::ObservedAddr(updated)); | ||
} | ||
} |
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 push all/most of this logic into a method on PathData
?
let mut external_addresses = conn.observed_external_addr(); | ||
tokio::spawn(async move { | ||
loop { | ||
if let Some(new_addr) = *external_addresses.borrow_and_update() { | ||
info!(%new_addr, "new external address report"); | ||
} | ||
if external_addresses.changed().await.is_err() { | ||
break; | ||
} | ||
} | ||
}); |
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 don't think this is widely used enough that it merits real estate in these examples.
@@ -636,6 +636,12 @@ impl Connection { | |||
// May need to send MAX_STREAMS to make progress | |||
conn.wake(); | |||
} | |||
|
|||
/// Track changed on our external address as reported by the peer. | |||
pub fn observed_external_addr(&self) -> watch::Receiver<Option<SocketAddr>> { |
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.
Not sure about exposing the watch::Receiver
as part of the public API, that seems like it's leaking a bunch of implementation details?
60b2e57
to
903743a
Compare
903743a
to
db19d8b
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.
Looks promising so far!
@@ -222,6 +222,12 @@ pub struct Connection { | |||
/// no outgoing application data. | |||
app_limited: bool, | |||
|
|||
// | |||
// ObservedAddr |
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 Address discovery
would be a better section divider comment
@@ -3058,6 +3103,53 @@ impl Connection { | |||
self.stats.frame_tx.handshake_done.saturating_add(1); | |||
} | |||
|
|||
// OBSERVED_ADDR | |||
let mut send_observed_address = |
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 looks like the only reason for this to be a lambda is because of the short-circuit. I think this can be refactored from:
let do_thing = |a, b, c, d, e| {
if (!should_do_thing) {
return;
}
do_stuff....
}
do_thing(a, b, c, d, e);
To just:
if (should_do_thing) {
do_stuff...
}
It would be equally indented.
@@ -37,6 +40,11 @@ pub(super) struct PathData { | |||
/// Used in persistent congestion determination. | |||
pub(super) first_packet_after_rtt_sample: Option<(SpaceId, u64)>, | |||
pub(super) in_flight: InFlight, | |||
/// Whether this path has had it's remote address reported back to the peer. This only happens | |||
/// if both peers agree to so based on their transport parameters. | |||
pub(super) observed_addr_sent: bool, |
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.
&mut self, | ||
observed: ObservedAddr, | ||
) -> Option<SocketAddr> { | ||
match self.last_observed_addr_report.as_mut() { |
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 this could be shorted a lot. ObservedAddr
is copy. Maybe something like this?
let prev = self.last_observed_addr_report;
if prev.map(|prev| prev.seq_no < observed.seq_no).unwrap_or(true) {
self.last_observed_addr_report = Some(observed);
}
if Some(observed.socket_addr()) != prev.map(|prev| prev.socket_addr()) {
Some(observed.socket_addr())
} else {
None
}
It could be golfed more but something like the above perhaps is at a nice spot for readability.
IpAddr::V6(ipv6_addr) => { | ||
buf.write(ipv6_addr); | ||
} | ||
} |
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.
Nit: Maybe just this?
match self.ip {
IpAddr::V4(ipv4_addr) => buf.write(ipv4_addr),
IpAddr::V6(ipv6_addr) => buf.write(ipv6_addr),
}
Ok(Self { seq_no, ip, port }) | ||
} | ||
|
||
/// Gives the [`SocketAddr`] reported in the frame. |
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.
This project's convention is to have the first line of a doc comment not end with a period
quinn-proto/src/address_discovery.rs
Outdated
/// Whether this peer should report observed addresses to the other peer. | ||
pub(crate) fn should_report(&self, other: &Self) -> bool { | ||
self.is_reporter() && other.receives_reports() | ||
} |
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 maybe this should just be inlined into its call sites, I don't think the abstraction is helping
db19d8b
to
6d67b90
Compare
Implements the Quic Address discovery extension IETF draft