Skip to content

Commit eec5425

Browse files
fix(iroh-net): ping via relay, enable relay ping in derp only mode (#1632)
## Description - pings the derp region when we ping the udp addresses - handles pongs via derp - enables ping and pongs via relay in derp only mode ## Notes & open questions I left two nodes in my machine, in derp only mode running and they never became direct peers so I consider this a safe change wrt the derp only env flag This fixes the second part of #1576 Output example ```bash > node connections # node id region conn type latency # xqcdy7bioujckakup5iicwfgppljpffbmelwssj4hngf5u3satga 1 relay 166ms,859μs ``` ## Change checklist - [x] Self-review. - [ ] Documentation updates if relevant. - [ ] Tests if relevant.
1 parent 14c4497 commit eec5425

1 file changed

Lines changed: 58 additions & 24 deletions

File tree

iroh-net/src/magicsock/endpoint.rs

Lines changed: 58 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -324,24 +324,25 @@ impl Endpoint {
324324
let mut msgs = Vec::new();
325325
let (udp_addr, derp_region, _should_ping) = self.addr_for_send(&now);
326326
if let Some(derp_region) = derp_region {
327-
// TODO(@divma):: this is cli_ping, never used. Intentionally commented out
328-
// if let Some(msg) = self.start_ping(SendAddr::Derp(derp_region), DiscoPingPurpose::Cli) {
329-
// msgs.push(msg);
330-
// }
327+
if let Some(msg) = self.start_ping(SendAddr::Derp(derp_region), DiscoPingPurpose::Cli) {
328+
msgs.push(msg);
329+
}
331330
}
332331
if let Some(udp_addr) = udp_addr {
333332
if self.is_best_addr_valid(now) {
334333
// Already have an active session, so just ping the address we're using.
335334
// Otherwise "tailscale ping" results to a node on the local network
336335
// can look like they're bouncing between, say 10.0.0.0/9 and the peer's
337336
// IPv6 address, both 1ms away, and it's random who replies first.
338-
if let Some(msg) = self.start_ping(udp_addr.into(), DiscoPingPurpose::Cli) {
337+
if let Some(msg) = self.start_ping(SendAddr::Udp(udp_addr), DiscoPingPurpose::Cli) {
339338
msgs.push(msg);
340339
}
341340
} else {
342341
let eps: Vec<_> = self.direct_addr_state.keys().cloned().collect();
343342
for ep in eps {
344-
if let Some(msg) = self.start_ping(ep, DiscoPingPurpose::Cli) {
343+
if let Some(msg) =
344+
self.start_ping(SendAddr::Udp(ep.into()), DiscoPingPurpose::Cli)
345+
{
345346
msgs.push(msg);
346347
}
347348
}
@@ -400,18 +401,17 @@ impl Endpoint {
400401
}
401402
}
402403

403-
// TODO(@divma): intentionally changed to prove we don't ping via relay.
404-
fn start_ping(&mut self, ip_port: IpPort, purpose: DiscoPingPurpose) -> Option<PingAction> {
405-
if derp_only_mode() {
404+
fn start_ping(&mut self, dst: SendAddr, purpose: DiscoPingPurpose) -> Option<PingAction> {
405+
if derp_only_mode() && !dst.is_derp() {
406406
// don't attempt any hole punching in derp only mode
407407
warn!("in `DEV_DERP_ONLY` mode, ignoring request to start a hole punching attempt.");
408408
return None;
409409
}
410-
info!("start ping to {}: {:?}", ip_port, purpose);
410+
info!("start ping to {}: {:?}", dst, purpose);
411411
let tx_id = stun::TransactionId::default();
412412
Some(PingAction::SendPing {
413413
id: self.id,
414-
dst: SendAddr::Udp(ip_port.into()),
414+
dst,
415415
dst_key: self.public_key,
416416
tx_id,
417417
purpose,
@@ -477,6 +477,17 @@ impl Endpoint {
477477

478478
fn send_pings(&mut self, now: Instant, send_call_me_maybe: bool) -> Vec<PingAction> {
479479
let mut msgs = Vec::new();
480+
481+
if let Some((region, state)) = self.derp_region.as_ref() {
482+
if state.needs_ping(&now) {
483+
if let Some(msg) =
484+
self.start_ping(SendAddr::Derp(*region), DiscoPingPurpose::Discovery)
485+
{
486+
msgs.push(msg)
487+
}
488+
}
489+
}
490+
480491
if derp_only_mode() {
481492
// don't send or respond to any hole punching pings if we are in
482493
// derp only mode
@@ -511,7 +522,9 @@ impl Endpoint {
511522
debug!("disco: send, starting discovery for {:?}", self.public_key);
512523
}
513524

514-
if let Some(msg) = self.start_ping(ep, DiscoPingPurpose::Discovery) {
525+
if let Some(msg) =
526+
self.start_ping(SendAddr::Udp(ep.into()), DiscoPingPurpose::Discovery)
527+
{
515528
msgs.push(msg);
516529
}
517530
}
@@ -725,24 +738,43 @@ impl Endpoint {
725738
let now = Instant::now();
726739
let latency = now - sp.at;
727740

728-
if let SendAddr::Udp(addr) = src {
729-
let key = self.public_key;
730-
match self.direct_addr_state.get_mut(&addr.into()) {
731-
None => {
732-
info!("disco: ignoring pong: {}", sp.to);
733-
// This is no longer an endpoint we care about.
734-
return peer_map_insert;
741+
match src {
742+
SendAddr::Udp(addr) => {
743+
let key = self.public_key;
744+
match self.direct_addr_state.get_mut(&addr.into()) {
745+
None => {
746+
info!("disco: ignoring pong: {}", sp.to);
747+
// This is no longer an endpoint we care about.
748+
return peer_map_insert;
749+
}
750+
Some(st) => {
751+
peer_map_insert = Some((addr, key));
752+
st.add_pong_reply(PongReply {
753+
latency,
754+
pong_at: now,
755+
from: src,
756+
pong_src: m.src,
757+
});
758+
}
735759
}
736-
Some(st) => {
737-
peer_map_insert = Some((addr, key));
738-
st.add_pong_reply(PongReply {
760+
}
761+
SendAddr::Derp(region) => match self.derp_region.as_mut() {
762+
Some((home_region, state)) if *home_region == region => {
763+
state.add_pong_reply(PongReply {
739764
latency,
740765
pong_at: now,
741766
from: src,
742767
pong_src: m.src,
743768
});
744769
}
745-
}
770+
other => {
771+
// if we are here then we sent this ping, but the region changed
772+
// waiting for the response. It was either set to None or changed to
773+
// another region. This should either never happen or be extremely
774+
// unlikely. Log and ignore for now
775+
warn!(stored=?other, received=?region, "disco: ignoring pong via derp for region different to last one stored");
776+
}
777+
},
746778
}
747779

748780
info!(
@@ -950,7 +982,9 @@ impl Endpoint {
950982
"stayin alive ping for {}: {:?} {:?}",
951983
udp_addr, elapsed, now
952984
);
953-
if let Some(msg) = self.start_ping(udp_addr.into(), DiscoPingPurpose::StayinAlive) {
985+
if let Some(msg) =
986+
self.start_ping(SendAddr::Udp(udp_addr), DiscoPingPurpose::StayinAlive)
987+
{
954988
return vec![msg];
955989
}
956990
}

0 commit comments

Comments
 (0)