diff --git a/crates/dap/src/adapters.rs b/crates/dap/src/adapters.rs index 96a35bc8ab6..0f4bb937c1b 100644 --- a/crates/dap/src/adapters.rs +++ b/crates/dap/src/adapters.rs @@ -18,7 +18,7 @@ use std::{ borrow::Borrow, ffi::OsStr, fmt::Debug, - net::Ipv4Addr, + net::IpAddr, ops::Deref, path::{Path, PathBuf}, sync::Arc, @@ -106,7 +106,7 @@ impl<'a> From<&'a str> for DebugAdapterName { #[derive(Debug, Clone, PartialEq, Serialize)] pub struct TcpArguments { - pub host: Ipv4Addr, + pub host: IpAddr, pub port: u16, pub timeout: Option, } diff --git a/crates/dap/src/dap.rs b/crates/dap/src/dap.rs index 10a584e61b8..72446d86f0c 100644 --- a/crates/dap/src/dap.rs +++ b/crates/dap/src/dap.rs @@ -6,7 +6,7 @@ pub mod proto_conversions; mod registry; pub mod transport; -use std::net::Ipv4Addr; +use std::net::IpAddr; pub use dap_types::*; use debugger_settings::DebuggerSettings; @@ -26,7 +26,7 @@ use task::{DebugScenario, TcpArgumentsTemplate}; pub async fn configure_tcp_connection( tcp_connection: TcpArgumentsTemplate, -) -> anyhow::Result<(Ipv4Addr, u16, Option)> { +) -> anyhow::Result<(IpAddr, u16, Option)> { let host = tcp_connection.host(); let timeout = tcp_connection.timeout; diff --git a/crates/dap/src/transport.rs b/crates/dap/src/transport.rs index 2bb55af74ec..ff04c414517 100644 --- a/crates/dap/src/transport.rs +++ b/crates/dap/src/transport.rs @@ -18,7 +18,7 @@ use smol::{ }; use std::{ collections::HashMap, - net::{Ipv4Addr, SocketAddrV4}, + net::{IpAddr, SocketAddr}, process::Stdio, sync::Arc, time::Duration, @@ -472,7 +472,7 @@ impl TransportDelegate { pub struct TcpTransport { executor: BackgroundExecutor, pub port: u16, - pub host: Ipv4Addr, + pub host: IpAddr, pub timeout: u64, process: Arc>>, _stderr_task: Option>, @@ -489,8 +489,8 @@ impl TcpTransport { } } - pub async fn unused_port(host: Ipv4Addr) -> Result { - Ok(TcpListener::bind(SocketAddrV4::new(host, 0)) + pub async fn unused_port(host: IpAddr) -> Result { + Ok(TcpListener::bind(SocketAddr::new(host, 0)) .await? .local_addr()? .port()) @@ -598,7 +598,7 @@ impl Transport for TcpTransport { > { let executor = self.executor.clone(); let timeout = self.timeout; - let address = SocketAddrV4::new(self.host, self.port); + let address = SocketAddr::new(self.host, self.port); let process = self.process.clone(); executor.clone().spawn(async move { select! { diff --git a/crates/dap_adapters/src/python.rs b/crates/dap_adapters/src/python.rs index 111eab5a1d1..07eed167e69 100644 --- a/crates/dap_adapters/src/python.rs +++ b/crates/dap_adapters/src/python.rs @@ -14,7 +14,7 @@ use smol::fs::File; use smol::io::AsyncReadExt; use smol::lock::OnceCell; use std::ffi::OsString; -use std::net::Ipv4Addr; +use std::net::IpAddr; use std::str::FromStr; use std::{ ffi::OsStr, @@ -42,7 +42,7 @@ impl PythonDebugAdapter { const LANGUAGE_NAME: &'static str = "Python"; async fn generate_debugpy_arguments<'a>( - host: &'a Ipv4Addr, + host: &'a IpAddr, port: u16, launch_mode: DebugpyLaunchMode<'a>, user_installed_path: Option<&'a Path>, @@ -380,7 +380,7 @@ impl PythonDebugAdapter { } if let Some(hostname) = config_host { - tcp_connection.host = Some(hostname.parse().context("hostname must be IPv4")?); + tcp_connection.host = Some(hostname.parse().context("invalid IP address")?); } tcp_connection.port = config_port; DebugpyLaunchMode::AttachWithConnect { host: config_host } @@ -974,7 +974,7 @@ mod tests { .contains("Cannot have two different ports") ); - let host = Ipv4Addr::new(127, 0, 0, 1); + let host = IpAddr::V4(std::net::Ipv4Addr::LOCALHOST); let config_with_host_conflict = json!({ "request": "attach", "connect": { @@ -1018,7 +1018,7 @@ mod tests { #[gpui::test] async fn test_attach_with_connect_mode_generates_correct_arguments() { - let host = Ipv4Addr::new(127, 0, 0, 1); + let host = IpAddr::V4(std::net::Ipv4Addr::LOCALHOST); let port = 5678; let args_without_host = PythonDebugAdapter::generate_debugpy_arguments( @@ -1071,7 +1071,7 @@ mod tests { #[gpui::test] async fn test_debugpy_install_path_cases() { - let host = Ipv4Addr::new(127, 0, 0, 1); + let host = IpAddr::V4(std::net::Ipv4Addr::LOCALHOST); let port = 5678; // Case 1: User-defined debugpy path (highest precedence) diff --git a/crates/extension_host/src/wasm_host/wit/since_v0_8_0.rs b/crates/extension_host/src/wasm_host/wit/since_v0_8_0.rs index 683e69e0870..24cf0affd77 100644 --- a/crates/extension_host/src/wasm_host/wit/since_v0_8_0.rs +++ b/crates/extension_host/src/wasm_host/wit/since_v0_8_0.rs @@ -24,7 +24,7 @@ use project::project_settings::ProjectSettings; use semver::Version; use std::{ env, - net::Ipv4Addr, + net::{IpAddr, Ipv4Addr}, path::{Path, PathBuf}, str::FromStr, sync::{Arc, OnceLock}, @@ -117,7 +117,7 @@ impl TryFrom for extension::StartDebuggingReques impl From for extension::TcpArguments { fn from(value: TcpArguments) -> Self { Self { - host: value.host.into(), + host: IpAddr::V4(Ipv4Addr::from_bits(value.host)), port: value.port, timeout: value.timeout, } @@ -127,7 +127,10 @@ impl From for extension::TcpArguments { impl From for TcpArgumentsTemplate { fn from(value: extension::TcpArgumentsTemplate) -> Self { Self { - host: value.host.map(Ipv4Addr::to_bits), + host: value.host.and_then(|addr| match addr { + IpAddr::V4(v4) => Some(v4.to_bits()), + IpAddr::V6(_) => None, + }), port: value.port, timeout: value.timeout, } @@ -137,7 +140,7 @@ impl From for TcpArgumentsTemplate { impl From for extension::TcpArgumentsTemplate { fn from(value: TcpArgumentsTemplate) -> Self { Self { - host: value.host.map(Ipv4Addr::from_bits), + host: value.host.map(|bits| IpAddr::V4(Ipv4Addr::from_bits(bits))), port: value.port, timeout: value.timeout, } @@ -904,13 +907,21 @@ impl dap::Host for WasmState { let (host, port, timeout) = ::dap::configure_tcp_connection(task::TcpArgumentsTemplate { port: template.port, - host: template.host.map(Ipv4Addr::from_bits), + host: template + .host + .map(|bits| IpAddr::V4(Ipv4Addr::from_bits(bits))), timeout: template.timeout, }) .await?; + let host_bits = match host { + IpAddr::V4(v4) => v4.to_bits(), + IpAddr::V6(_) => { + anyhow::bail!("IPv6 addresses are not supported in the extension API") + } + }; Ok(TcpArguments { port, - host: host.to_bits(), + host: host_bits, timeout, }) }) diff --git a/crates/project/src/debugger/dap_store.rs b/crates/project/src/debugger/dap_store.rs index 6d320bc06e6..7ac9c02fe4f 100644 --- a/crates/project/src/debugger/dap_store.rs +++ b/crates/project/src/debugger/dap_store.rs @@ -47,7 +47,7 @@ use std::{ borrow::Borrow, collections::BTreeMap, ffi::OsStr, - net::Ipv4Addr, + net::{IpAddr, Ipv4Addr}, path::{Path, PathBuf}, sync::{Arc, Once}, }; @@ -323,7 +323,7 @@ impl DapStore { let port_forwarding; let connection; if let Some(c) = binary.connection { - let host = Ipv4Addr::LOCALHOST; + let host = IpAddr::V4(Ipv4Addr::LOCALHOST); let port; if remote.read_with(cx, |remote, _cx| remote.shares_network_interface()) { port = c.port; diff --git a/crates/project/src/debugger/session.rs b/crates/project/src/debugger/session.rs index 87e11cfd97a..feba6ff5520 100644 --- a/crates/project/src/debugger/session.rs +++ b/crates/project/src/debugger/session.rs @@ -48,7 +48,7 @@ use serde_json::Value; use smol::net::{TcpListener, TcpStream}; use std::any::TypeId; use std::collections::{BTreeMap, VecDeque}; -use std::net::Ipv4Addr; +use std::net::{IpAddr, Ipv4Addr}; use std::ops::RangeInclusive; use std::path::PathBuf; use std::time::Duration; @@ -2901,7 +2901,7 @@ impl Session { ); None } else { - let port = TcpTransport::unused_port(Ipv4Addr::LOCALHOST) + let port = TcpTransport::unused_port(IpAddr::V4(Ipv4Addr::LOCALHOST)) .await .context("getting port for DAP")?; request diff --git a/crates/task/src/debug_format.rs b/crates/task/src/debug_format.rs index 5609e2565c8..72c12324c73 100644 --- a/crates/task/src/debug_format.rs +++ b/crates/task/src/debug_format.rs @@ -4,7 +4,7 @@ use gpui::SharedString; use log as _; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use std::net::Ipv4Addr; +use std::net::IpAddr; use std::path::PathBuf; use util::{debug_panic, schemars::add_new_subschema}; @@ -20,7 +20,7 @@ pub struct TcpArgumentsTemplate { /// The host that the debug adapter is listening too /// /// Default: 127.0.0.1 - pub host: Option, + pub host: Option, /// The max amount of time in milliseconds to connect to a tcp DAP before returning an error /// /// Default: 2000ms @@ -29,8 +29,9 @@ pub struct TcpArgumentsTemplate { impl TcpArgumentsTemplate { /// Get the host or fallback to the default host - pub fn host(&self) -> Ipv4Addr { - self.host.unwrap_or_else(|| Ipv4Addr::new(127, 0, 0, 1)) + pub fn host(&self) -> IpAddr { + self.host + .unwrap_or(IpAddr::V4(std::net::Ipv4Addr::LOCALHOST)) } pub fn from_proto(proto: proto::TcpHost) -> Result { @@ -389,8 +390,7 @@ impl DebugTaskFile { }, "host": { "type": "string", - "pattern": "^((25[0-5]|(2[0-4]|1\\d|[1-9]|)\\d)\\.?\\b){4}$", - "description": "The host that the debug adapter is listening to (default: 127.0.0.1)" + "description": "The host that the debug adapter is listening to, as an IPv4 or IPv6 address (default: 127.0.0.1)" }, "timeout": { "type": "integer",