diff --git a/Cargo.lock b/Cargo.lock index 3b4fb10..f076bee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2732,7 +2732,7 @@ checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "itsgoin-cli" -version = "0.5.0" +version = "0.3.0" dependencies = [ "anyhow", "hex", @@ -2744,7 +2744,7 @@ dependencies = [ [[package]] name = "itsgoin-core" -version = "0.5.0" +version = "0.3.0" dependencies = [ "anyhow", "base64 0.22.1", @@ -2767,7 +2767,7 @@ dependencies = [ [[package]] name = "itsgoin-desktop" -version = "0.5.0" +version = "0.4.4" dependencies = [ "anyhow", "base64 0.22.1", diff --git a/crates/core/src/connection.rs b/crates/core/src/connection.rs index 2b74e16..84383c5 100644 --- a/crates/core/src/connection.rs +++ b/crates/core/src/connection.rs @@ -3868,15 +3868,12 @@ 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?; @@ -3912,8 +3909,6 @@ 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()?; @@ -3937,15 +3932,12 @@ 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()?; @@ -3971,20 +3963,7 @@ 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(); - // 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 peer_nat_profile = { let s = self.storage.get().await; s.get_peer_nat_profile(&requester) }; @@ -4102,7 +4081,6 @@ 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()?; @@ -4177,7 +4155,6 @@ 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()?; @@ -4217,8 +4194,6 @@ 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 { @@ -4271,7 +4246,6 @@ 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()?; @@ -4299,7 +4273,6 @@ 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()?; @@ -4320,7 +4293,6 @@ 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()?; @@ -5839,7 +5811,6 @@ 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()?; @@ -5865,22 +5836,7 @@ 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(); - // 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) - }; + let peer_nat_profile = { 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. @@ -5910,8 +5866,6 @@ 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()?; @@ -6000,7 +5954,6 @@ 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()?; diff --git a/crates/core/src/network.rs b/crates/core/src/network.rs index 0566035..446b2ef 100644 --- a/crates/core/src/network.rs +++ b/crates/core/src/network.rs @@ -349,11 +349,6 @@ impl Network { self.device_role } - /// Get the explicit bind address (from --bind flag), if any. - pub fn bind_addr(&self) -> Option { - self.bind_addr - } - /// Whether this node can serve HTTP (has TCP reachability). pub fn is_http_capable(&self) -> bool { self.has_upnp_tcp || self.has_public_v6 || self.bind_addr.is_some() @@ -1957,13 +1952,7 @@ impl Network { } } - // 4. Re-check connection — peer may have connected to us while we were trying direct - if let Some(conn) = self.conn_handle.get_any_connection(peer_id).await { - debug!(peer = hex::encode(peer_id), "Peer connected to us while we were trying — using existing connection"); - return Ok(conn); - } - - // 5. Try relay introduction + hole punch (no lock during I/O) + // 4. Try relay introduction + hole punch (no lock during I/O) let relay_candidates = self.conn_handle.find_relays_for(peer_id).await; if relay_candidates.is_empty() { @@ -1986,28 +1975,10 @@ impl Network { self.send_relay_introduce_standalone(relay_peer, peer_id, *ttl), ).await; - // Re-check: peer may have connected while relay intro was in flight - if let Some(conn) = self.conn_handle.get_any_connection(peer_id).await { - debug!(peer = hex::encode(peer_id), "Peer connected during relay intro — using existing"); - return Ok(conn); - } - match intro_result { - Ok(Ok(ref result)) if result.accepted => { + Ok(Ok(result)) if result.accepted => { let our_profile = self.conn_handle.our_nat_profile().await; - // Prefer fresh NAT profile from relay response over stale stored profile - let peer_profile = if result.nat_mapping.is_some() || result.nat_filtering.is_some() { - let mapping = result.nat_mapping.as_deref() - .map(crate::types::NatMapping::from_str_label) - .unwrap_or(crate::types::NatMapping::Unknown); - let filtering = result.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 = self.storage.get().await; - let _ = s.set_peer_nat_profile(peer_id, &fresh); - fresh - } else { + let peer_profile = { let s = self.storage.get().await; s.get_peer_nat_profile(peer_id) }; @@ -2303,15 +2274,12 @@ impl Network { } } - let our_profile = self.conn_handle.our_nat_profile().await; let payload = crate::protocol::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) = conn.open_bi().await?; diff --git a/crates/core/src/protocol.rs b/crates/core/src/protocol.rs index 8fdd71c..50e2565 100644 --- a/crates/core/src/protocol.rs +++ b/crates/core/src/protocol.rs @@ -461,12 +461,6 @@ pub struct RelayIntroducePayload { pub requester_addresses: Vec, /// Max forwarding hops remaining (0 = relay must know target directly) pub ttl: u8, - /// Requester's current NAT mapping type (for hole punch strategy) - #[serde(default, skip_serializing_if = "Option::is_none")] - pub nat_mapping: Option, - /// Requester's current NAT filtering type - #[serde(default, skip_serializing_if = "Option::is_none")] - pub nat_filtering: Option, } /// Target's response to a relay introduction (bi-stream response) @@ -478,12 +472,6 @@ pub struct RelayIntroduceResultPayload { /// Relay is willing to serve as stream relay fallback pub relay_available: bool, pub reject_reason: Option, - /// Target's current NAT mapping type (for hole punch strategy) - #[serde(default, skip_serializing_if = "Option::is_none")] - pub nat_mapping: Option, - /// Target's current NAT filtering type - #[serde(default, skip_serializing_if = "Option::is_none")] - pub nat_filtering: Option, } /// Open a relay pipe — intermediary splices two bi-streams (bi-stream) @@ -870,8 +858,6 @@ mod tests { requester: [2u8; 32], requester_addresses: vec!["10.0.0.2:4433".to_string()], ttl: 1, - nat_mapping: Some("eim".to_string()), - nat_filtering: Some("open".to_string()), }; let json = serde_json::to_string(&payload).unwrap(); let decoded: RelayIntroducePayload = serde_json::from_str(&json).unwrap(); @@ -890,8 +876,6 @@ mod tests { target_addresses: vec!["10.0.0.1:4433".to_string(), "192.168.1.1:4433".to_string()], relay_available: true, reject_reason: None, - nat_mapping: Some("eim".to_string()), - nat_filtering: Some("open".to_string()), }; let json = serde_json::to_string(&payload).unwrap(); let decoded: RelayIntroduceResultPayload = serde_json::from_str(&json).unwrap(); @@ -908,8 +892,6 @@ mod tests { target_addresses: vec![], relay_available: false, reject_reason: Some("target not reachable".to_string()), - nat_mapping: None, - nat_filtering: None, }; let json2 = serde_json::to_string(&rejected).unwrap(); let decoded2: RelayIntroduceResultPayload = serde_json::from_str(&json2).unwrap(); diff --git a/crates/core/src/stun.rs b/crates/core/src/stun.rs index 792f378..35284df 100644 --- a/crates/core/src/stun.rs +++ b/crates/core/src/stun.rs @@ -103,9 +103,8 @@ fn parse_xor_mapped_address(resp: &[u8], txn_id: &[u8; 12]) -> Option Option { use std::net::ToSocketAddrs; - // Filter for IPv4 since our socket is bound to 0.0.0.0 (IPv4) let server_addr = match server.to_socket_addrs() { - Ok(addrs) => addrs.filter(|a| a.is_ipv4()).next()?, + Ok(mut addrs) => addrs.next()?, Err(e) => { debug!(server, error = %e, "STUN DNS resolution failed"); return None; diff --git a/crates/tauri-app/src/lib.rs b/crates/tauri-app/src/lib.rs index 5ddc679..443fbcd 100644 --- a/crates/tauri-app/src/lib.rs +++ b/crates/tauri-app/src/lib.rs @@ -1623,120 +1623,6 @@ async fn get_network_summary(state: State<'_, AppNode>) -> Result, - nat_type: String, - device_role: String, - upnp: bool, - http_capable: bool, - http_addr: Option, -} - -#[derive(Serialize)] -#[serde(rename_all = "camelCase")] -struct AddressInfoDto { - addr: String, - family: String, // "IPv4" or "IPv6" - status: String, // "Public", "NAT (easy)", "NAT (hard)", "UPnP", "LAN", "Server" -} - -#[tauri::command] -async fn get_our_info(state: State<'_, AppNode>) -> Result { - let node = get_node(&state).await; - let net = &node.network; - let nat_type = net.conn_handle().nat_type().await; - let has_upnp = net.has_upnp(); - let _has_public_v6 = net.has_public_v6(); - let bind_addr = net.bind_addr(); - - let mut addresses = Vec::new(); - - // Collect bound socket addresses (these are our local interfaces) - let bound: std::collections::HashSet = net.bound_sockets() - .iter() - .map(|s| s.to_string()) - .collect(); - - // Gather bound (local) addresses with classification - for sock in net.bound_sockets() { - if sock.ip().is_loopback() || sock.ip().is_unspecified() { continue; } - let family = if sock.ip().is_ipv4() { "IPv4" } else { "IPv6" }; - let status = classify_addr(&sock, &nat_type, has_upnp, bind_addr.is_some(), false); - addresses.push(AddressInfoDto { - addr: sock.to_string(), - family: family.to_string(), - status, - }); - } - - // Add UPnP external address if different from bound - if let Some(ref mapping) = net.upnp_mapping() { - let ext = mapping.external_addr; - if !addresses.iter().any(|a| a.addr == ext.to_string()) { - addresses.insert(0, AddressInfoDto { - addr: ext.to_string(), - family: if ext.ip().is_ipv4() { "IPv4" } else { "IPv6" }.to_string(), - status: "UPnP external".to_string(), - }); - } - } - - // Add iroh-discovered addresses not already listed (STUN-observed externals) - for sock in net.endpoint_addr().ip_addrs() { - if sock.ip().is_loopback() || sock.ip().is_unspecified() { continue; } - let s = sock.to_string(); - if addresses.iter().any(|a| a.addr == s) { continue; } - let family = if sock.ip().is_ipv4() { "IPv4" } else { "IPv6" }; - let is_observed = !bound.contains(&s); - let status = classify_addr(sock, &nat_type, has_upnp, bind_addr.is_some(), is_observed); - addresses.push(AddressInfoDto { - addr: s, - family: family.to_string(), - status, - }); - } - - Ok(OurInfoDto { - node_id: hex::encode(net.node_id_bytes()), - addresses, - nat_type: nat_type.to_string(), - device_role: format!("{:?}", net.device_role()), - upnp: has_upnp, - http_capable: net.is_http_capable(), - http_addr: net.http_addr(), - }) -} - -fn classify_addr(sock: &std::net::SocketAddr, nat_type: &itsgoin_core::types::NatType, has_upnp: bool, is_server: bool, is_observed: bool) -> String { - use std::net::IpAddr; - let ip = sock.ip(); - let is_v6 = ip.is_ipv6(); - let is_pub = match ip { - IpAddr::V4(v4) => !v4.is_private() && !v4.is_loopback() && !v4.is_link_local(), - IpAddr::V6(v6) => !v6.is_loopback() && { - let seg = v6.segments(); - seg[0] & 0xfe00 != 0xfe00 && seg[0] & 0xffc0 != 0xfe80 - }, - }; - if is_server { return "Server".to_string(); } - if is_pub { - if is_observed && !is_v6 { - return match nat_type { - itsgoin_core::types::NatType::Public | - itsgoin_core::types::NatType::Easy => "External · easy punch".to_string(), - itsgoin_core::types::NatType::Hard => "External · hard punch (scan)".to_string(), - itsgoin_core::types::NatType::Unknown => "External".to_string(), - }; - } - return "Public".to_string(); - } - if is_v6 { return "Link-local".to_string(); } - "LAN".to_string() -} - #[derive(Serialize)] #[serde(rename_all = "camelCase")] struct ActivityEventDto { @@ -2501,7 +2387,6 @@ pub fn run() { sync_all, sync_from_peer, get_network_summary, - get_our_info, get_activity_log, trigger_rebalance, request_referrals, diff --git a/frontend/app.js b/frontend/app.js index bf16e44..62f8461 100644 --- a/frontend/app.js +++ b/frontend/app.js @@ -2986,14 +2986,9 @@ function openDiagnostics() {
-
- -
-
-
-
- -