Our Info panel, hole punch race fix, NAT profiles in relay introduction
- Network Diagnostics: "Our Info" button shows addresses with NAT status, device role, UPnP, HTTP capability. Addresses stacked for mobile. - Hole punch race: re-check for existing connection before and after relay introduction to avoid wasting minutes on redundant punch attempts. - Relay introduction now carries requester/target NAT mapping+filtering so hole punch strategy uses fresh profiles instead of stale stored ones. Critical for phones that switch between WiFi/cellular/VPN. - STUN fix: filter DNS results to IPv4 (was resolving to IPv6 first on dual-stack, causing silent send failure and "NAT unknown"). - Welcome screen: Ready button with loading bar for instant feed access. - LAN addresses show just "LAN" (no misleading punchability label). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
e354ccc388
commit
be253e8001
7 changed files with 266 additions and 9 deletions
|
|
@ -3868,12 +3868,15 @@ impl ConnectionManager {
|
|||
}
|
||||
}
|
||||
|
||||
let our_profile = self.our_nat_profile();
|
||||
let payload = RelayIntroducePayload {
|
||||
intro_id,
|
||||
target: *target,
|
||||
requester: self.our_node_id,
|
||||
requester_addresses: our_addrs,
|
||||
ttl,
|
||||
nat_mapping: Some(our_profile.mapping.to_string()),
|
||||
nat_filtering: Some(our_profile.filtering.to_string()),
|
||||
};
|
||||
|
||||
let (mut send, mut recv) = pc.connection.open_bi().await?;
|
||||
|
|
@ -3909,6 +3912,8 @@ impl ConnectionManager {
|
|||
target_addresses: vec![],
|
||||
relay_available: false,
|
||||
reject_reason: Some("duplicate intro".to_string()),
|
||||
nat_mapping: None,
|
||||
nat_filtering: None,
|
||||
};
|
||||
write_typed_message(&mut send, MessageType::RelayIntroduceResult, &result).await?;
|
||||
send.finish()?;
|
||||
|
|
@ -3932,12 +3937,15 @@ impl ConnectionManager {
|
|||
}
|
||||
}
|
||||
|
||||
let our_profile = self.our_nat_profile();
|
||||
let result = RelayIntroduceResultPayload {
|
||||
intro_id: payload.intro_id,
|
||||
accepted: true,
|
||||
target_addresses: our_addrs,
|
||||
relay_available: false,
|
||||
reject_reason: None,
|
||||
nat_mapping: Some(our_profile.mapping.to_string()),
|
||||
nat_filtering: Some(our_profile.filtering.to_string()),
|
||||
};
|
||||
write_typed_message(&mut send, MessageType::RelayIntroduceResult, &result).await?;
|
||||
send.finish()?;
|
||||
|
|
@ -3963,7 +3971,20 @@ impl ConnectionManager {
|
|||
let our_http_capable = self.http_capable;
|
||||
let our_http_addr = self.http_addr.clone();
|
||||
let our_nat_profile = self.our_nat_profile();
|
||||
let peer_nat_profile = {
|
||||
// Prefer fresh NAT profile from relay payload over stale stored profile
|
||||
let peer_nat_profile = if payload.nat_mapping.is_some() || payload.nat_filtering.is_some() {
|
||||
let mapping = payload.nat_mapping.as_deref()
|
||||
.map(crate::types::NatMapping::from_str_label)
|
||||
.unwrap_or(crate::types::NatMapping::Unknown);
|
||||
let filtering = payload.nat_filtering.as_deref()
|
||||
.map(crate::types::NatFiltering::from_str_label)
|
||||
.unwrap_or(crate::types::NatFiltering::Unknown);
|
||||
let fresh = crate::types::NatProfile::new(mapping, filtering);
|
||||
// Update storage with fresh profile
|
||||
let s = self.storage.get().await;
|
||||
let _ = s.set_peer_nat_profile(&requester, &fresh);
|
||||
fresh
|
||||
} else {
|
||||
let s = self.storage.get().await;
|
||||
s.get_peer_nat_profile(&requester)
|
||||
};
|
||||
|
|
@ -4081,6 +4102,7 @@ impl ConnectionManager {
|
|||
target_addresses: vec![],
|
||||
relay_available: false,
|
||||
reject_reason: Some(format!("relay forward failed: {}", e)),
|
||||
nat_mapping: None, nat_filtering: None,
|
||||
};
|
||||
write_typed_message(&mut send, MessageType::RelayIntroduceResult, &result).await?;
|
||||
send.finish()?;
|
||||
|
|
@ -4155,6 +4177,7 @@ impl ConnectionManager {
|
|||
target_addresses: vec![],
|
||||
relay_available: false,
|
||||
reject_reason: Some(format!("relay forward to session failed: {}", e)),
|
||||
nat_mapping: None, nat_filtering: None,
|
||||
};
|
||||
write_typed_message(&mut send, MessageType::RelayIntroduceResult, &result).await?;
|
||||
send.finish()?;
|
||||
|
|
@ -4194,6 +4217,8 @@ impl ConnectionManager {
|
|||
requester: payload.requester,
|
||||
requester_addresses: req_addrs,
|
||||
ttl: payload.ttl - 1,
|
||||
nat_mapping: payload.nat_mapping.clone(),
|
||||
nat_filtering: payload.nat_filtering.clone(),
|
||||
};
|
||||
|
||||
let forward_result = async {
|
||||
|
|
@ -4246,6 +4271,7 @@ impl ConnectionManager {
|
|||
target_addresses: vec![],
|
||||
relay_available: false,
|
||||
reject_reason: Some("target not reachable through relay".to_string()),
|
||||
nat_mapping: None, nat_filtering: None,
|
||||
};
|
||||
write_typed_message(&mut send, MessageType::RelayIntroduceResult, &result).await?;
|
||||
send.finish()?;
|
||||
|
|
@ -4273,6 +4299,7 @@ impl ConnectionManager {
|
|||
target_addresses: vec![],
|
||||
relay_available: false,
|
||||
reject_reason: Some("relay at capacity".to_string()),
|
||||
nat_mapping: None, nat_filtering: None,
|
||||
};
|
||||
write_typed_message(&mut requester_send, MessageType::RelayIntroduceResult, &result).await?;
|
||||
requester_send.finish()?;
|
||||
|
|
@ -4293,6 +4320,7 @@ impl ConnectionManager {
|
|||
target_addresses: vec![],
|
||||
relay_available: false,
|
||||
reject_reason: Some("target not connected to relay".to_string()),
|
||||
nat_mapping: None, nat_filtering: None,
|
||||
};
|
||||
write_typed_message(&mut requester_send, MessageType::RelayIntroduceResult, &result).await?;
|
||||
requester_send.finish()?;
|
||||
|
|
@ -5811,6 +5839,7 @@ impl ConnectionManager {
|
|||
let result = RelayIntroduceResultPayload {
|
||||
intro_id: payload.intro_id, accepted: false, target_addresses: vec![],
|
||||
relay_available: false, reject_reason: Some("duplicate intro".to_string()),
|
||||
nat_mapping: None, nat_filtering: None,
|
||||
};
|
||||
write_typed_message(&mut send, MessageType::RelayIntroduceResult, &result).await?;
|
||||
send.finish()?;
|
||||
|
|
@ -5836,7 +5865,22 @@ impl ConnectionManager {
|
|||
let our_http_capable = cm.http_capable;
|
||||
let our_http_addr = cm.http_addr.clone();
|
||||
let our_nat_profile = cm.our_nat_profile();
|
||||
let peer_nat_profile = { let s = cm.storage.get().await; s.get_peer_nat_profile(&payload.requester) };
|
||||
// Prefer fresh NAT profile from relay payload over stale stored profile
|
||||
let peer_nat_profile = if payload.nat_mapping.is_some() || payload.nat_filtering.is_some() {
|
||||
let mapping = payload.nat_mapping.as_deref()
|
||||
.map(crate::types::NatMapping::from_str_label)
|
||||
.unwrap_or(crate::types::NatMapping::Unknown);
|
||||
let filtering = payload.nat_filtering.as_deref()
|
||||
.map(crate::types::NatFiltering::from_str_label)
|
||||
.unwrap_or(crate::types::NatFiltering::Unknown);
|
||||
let fresh = crate::types::NatProfile::new(mapping, filtering);
|
||||
let s = cm.storage.get().await;
|
||||
let _ = s.set_peer_nat_profile(&payload.requester, &fresh);
|
||||
fresh
|
||||
} else {
|
||||
let s = cm.storage.get().await;
|
||||
s.get_peer_nat_profile(&payload.requester)
|
||||
};
|
||||
Some(RelayGathered::WeAreTarget { our_addrs, endpoint, storage, our_node_id, our_nat_type, our_http_capable, our_http_addr, our_nat_profile, peer_nat_profile })
|
||||
} else {
|
||||
// We are relay — gather target connection, requester observed addr, etc.
|
||||
|
|
@ -5866,6 +5910,8 @@ impl ConnectionManager {
|
|||
let result = RelayIntroduceResultPayload {
|
||||
intro_id: payload.intro_id, accepted: true, target_addresses: our_addrs,
|
||||
relay_available: false, reject_reason: None,
|
||||
nat_mapping: Some(our_nat_profile.mapping.to_string()),
|
||||
nat_filtering: Some(our_nat_profile.filtering.to_string()),
|
||||
};
|
||||
write_typed_message(&mut send, MessageType::RelayIntroduceResult, &result).await?;
|
||||
send.finish()?;
|
||||
|
|
@ -5954,6 +6000,7 @@ impl ConnectionManager {
|
|||
let result = RelayIntroduceResultPayload {
|
||||
intro_id: payload.intro_id, accepted: false, target_addresses: vec![],
|
||||
relay_available: false, reject_reason: Some(format!("relay forward failed: {}", e_msg)),
|
||||
nat_mapping: None, nat_filtering: None,
|
||||
};
|
||||
write_typed_message(&mut send, MessageType::RelayIntroduceResult, &result).await?;
|
||||
send.finish()?;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue