diff --git a/Cargo.lock b/Cargo.lock index 8c12938c..2c7de713 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -181,17 +181,6 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] - [[package]] name = "autocfg" version = "1.4.0" @@ -648,21 +637,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "clap" -version = "3.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" -dependencies = [ - "atty", - "bitflags 1.3.2", - "clap_lex 0.2.4", - "indexmap 1.9.3", - "strsim", - "termcolor", - "textwrap", -] - [[package]] name = "clap" version = "4.5.23" @@ -678,17 +652,10 @@ version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" dependencies = [ + "anstream", "anstyle", - "clap_lex 0.7.4", -] - -[[package]] -name = "clap_lex" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" -dependencies = [ - "os_str_bytes", + "clap_lex", + "strsim", ] [[package]] @@ -863,7 +830,7 @@ dependencies = [ "anes", "cast", "ciborium", - "clap 4.5.23", + "clap", "criterion-plot", "is-terminal", "itertools 0.10.5", @@ -1048,7 +1015,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", "syn 2.0.92", @@ -1424,27 +1391,12 @@ dependencies = [ "stable_deref_trait", ] -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - [[package]] name = "heck" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - [[package]] name = "hermit-abi" version = "0.4.0" @@ -1905,7 +1857,7 @@ version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" dependencies = [ - "hermit-abi 0.4.0", + "hermit-abi", "libc", "windows-sys 0.52.0", ] @@ -2231,7 +2183,7 @@ dependencies = [ "nix 0.29.0", "once_cell", "pyo3", - "pyo3-asyncio-0-21", + "pyo3-async-runtimes", "pyo3-log", "rand_core", "tar", @@ -2355,12 +2307,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" -[[package]] -name = "os_str_bytes" -version = "6.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" - [[package]] name = "parking" version = "2.2.1" @@ -2606,16 +2552,16 @@ dependencies = [ [[package]] name = "pyo3" -version = "0.21.2" +version = "0.23.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e00b96a521718e08e03b1a622f01c8a8deb50719335de3f60b3b3950f069d8" +checksum = "e484fd2c8b4cb67ab05a318f1fd6fa8f199fcc30819f08f07d200809dba26c15" dependencies = [ "anyhow", "cfg-if", "indoc", "libc", "memoffset", - "parking_lot", + "once_cell", "portable-atomic", "pyo3-build-config", "pyo3-ffi", @@ -2624,37 +2570,37 @@ dependencies = [ ] [[package]] -name = "pyo3-asyncio-0-21" -version = "0.21.0" +name = "pyo3-async-runtimes" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fde289486f7d5cee0ac7c20b2637a0657654681079cc5eedc90d9a2a79af1e5" +checksum = "977dc837525cfd22919ba6a831413854beb7c99a256c03bf8624ad707e45810e" dependencies = [ - "clap 3.2.25", + "clap", "futures", "inventory", "once_cell", "pin-project-lite", "pyo3", - "pyo3-asyncio-macros-0-21", + "pyo3-async-runtimes-macros", "tokio", ] [[package]] -name = "pyo3-asyncio-macros-0-21" -version = "0.21.0" +name = "pyo3-async-runtimes-macros" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e5ffc4e987e866bf54b781235a6c3b91e7e67df14f73ce716625ee78728554a" +checksum = "b2df2884957d2476731f987673befac5d521dff10abb0a7cbe12015bc7702fe9" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.92", ] [[package]] name = "pyo3-build-config" -version = "0.21.2" +version = "0.23.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7883df5835fafdad87c0d888b266c8ec0f4c9ca48a5bed6bbb592e8dedee1b50" +checksum = "dc0e0469a84f208e20044b98965e1561028180219e35352a2afaf2b942beff3b" dependencies = [ "once_cell", "target-lexicon", @@ -2662,9 +2608,9 @@ dependencies = [ [[package]] name = "pyo3-ffi" -version = "0.21.2" +version = "0.23.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01be5843dc60b916ab4dad1dca6d20b9b4e6ddc8e15f50c47fe6d85f1fb97403" +checksum = "eb1547a7f9966f6f1a0f0227564a9945fe36b90da5a93b3933fc3dc03fae372d" dependencies = [ "libc", "pyo3-build-config", @@ -2672,9 +2618,9 @@ dependencies = [ [[package]] name = "pyo3-log" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ac84e6eec1159bc2a575c9ae6723baa6ee9d45873e9bebad1e3ad7e8d28a443" +checksum = "be5bb22b77965a7b5394e9aae9897a0607b51df5167561ffc3b02643b4200bc7" dependencies = [ "arc-swap", "log", @@ -2683,9 +2629,9 @@ dependencies = [ [[package]] name = "pyo3-macros" -version = "0.21.2" +version = "0.23.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77b34069fc0682e11b31dbd10321cbf94808394c56fd996796ce45217dfac53c" +checksum = "fdb6da8ec6fa5cedd1626c886fc8749bdcbb09424a86461eb8cdf096b7c33257" dependencies = [ "proc-macro2", "pyo3-macros-backend", @@ -2695,11 +2641,11 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.21.2" +version = "0.23.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08260721f32db5e1a5beae69a55553f56b99bd0e1c3e6e0a5e8851a9d0f5a85c" +checksum = "38a385202ff5a92791168b1136afae5059d3ac118457bb7bc304c197c2d33e7d" dependencies = [ - "heck 0.4.1", + "heck", "proc-macro2", "pyo3-build-config", "quote", @@ -3052,9 +2998,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "subtle" @@ -3145,21 +3091,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "textwrap" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" - [[package]] name = "thiserror" version = "1.0.69" diff --git a/mitmproxy-rs/Cargo.toml b/mitmproxy-rs/Cargo.toml index 080860c8..c7bf484b 100644 --- a/mitmproxy-rs/Cargo.toml +++ b/mitmproxy-rs/Cargo.toml @@ -21,9 +21,9 @@ anyhow = { version = "1.0.93", features = ["backtrace"] } data-encoding = "2.6.0" log = "0.4.22" once_cell = "1" -pyo3 = { version = "0.21", features = ["abi3", "abi3-py310", "anyhow", "experimental-declarative-modules"] } -pyo3-asyncio-0-21 = { version = "0.21", features = ["tokio-runtime", "testing", "attributes"] } -pyo3-log = "0.11.0" +pyo3 = { version = "0.23", features = ["abi3", "abi3-py310", "anyhow"] } +pyo3-async-runtimes = { version = "0.23", features = ["tokio-runtime", "testing", "attributes"] } +pyo3-log = "0.12.0" rand_core = { version = "0.6.4", features = ["getrandom"] } tokio = { version = "1.41", features = ["macros", "net", "rt-multi-thread", "sync"] } boringtun = "0.6" diff --git a/mitmproxy-rs/pytests/logger.rs b/mitmproxy-rs/pytests/logger.rs index 642bbe72..a1bae5ac 100644 --- a/mitmproxy-rs/pytests/logger.rs +++ b/mitmproxy-rs/pytests/logger.rs @@ -70,7 +70,7 @@ static _LOGGER: LazyLock> = LazyLock::new(|| { }); /// Initialize the logger. -/// pyo3-asyncio tests all run in parallel in the same runtime, so we use a mutex to ensure +/// pyo3_async_runtimes tests all run in parallel in the same runtime, so we use a mutex to ensure /// that only one test that uses TestLogger runs at the same time. pub async fn setup_logger() -> MutexGuard<'static, &'static TestLogger> { let logger = _LOGGER.lock().await; diff --git a/mitmproxy-rs/pytests/test_task.rs b/mitmproxy-rs/pytests/test_task.rs index 320e9ea9..9071092d 100644 --- a/mitmproxy-rs/pytests/test_task.rs +++ b/mitmproxy-rs/pytests/test_task.rs @@ -1,7 +1,7 @@ mod logger; mod tests { - + use std::ffi::CString; use std::future::Future; use mitmproxy::messages::{ConnectionId, TransportEvent, TunnelInfo}; @@ -14,7 +14,7 @@ mod tests { use mitmproxy::shutdown; use tokio::sync::mpsc; - #[pyo3_asyncio_0_21::tokio::test] + #[pyo3_async_runtimes::tokio::test] async fn test_handler_invalid_signature() -> PyResult<()> { let logger = setup_logger().await; _test_task_error_handling( @@ -26,7 +26,7 @@ mod tests { Ok(()) } - #[pyo3_asyncio_0_21::tokio::test] + #[pyo3_async_runtimes::tokio::test] async fn test_handler_runtime_error() -> PyResult<()> { let logger = setup_logger().await; _test_task_error_handling( @@ -38,7 +38,7 @@ mod tests { Ok(()) } - #[pyo3_asyncio_0_21::tokio::test] + #[pyo3_async_runtimes::tokio::test] async fn test_handler_cancelled() -> PyResult<()> { let logger = setup_logger().await; _test_task_error_handling( @@ -63,19 +63,15 @@ mod tests { let (event_tx, event_rx) = mpsc::channel(1); let (shutdown_tx, shutdown_rx) = shutdown::channel(); - let conn_handler = Python::with_gil(|py| { - let locals = PyDict::new_bound(py); - py.run_bound(code, None, Some(&locals)).unwrap(); - locals.get_item("handler").unwrap().unwrap().to_object(py) + let (tcp_handler, udp_handler) = Python::with_gil(|py| { + let locals = PyDict::new(py); + let code = CString::new(code).unwrap(); + py.run(&code, None, Some(&locals)).unwrap(); + let handler = locals.get_item("handler").unwrap().unwrap().unbind(); + (handler.clone_ref(py), handler) }); - let task = PyInteropTask::new( - command_tx, - event_rx, - conn_handler.clone(), - conn_handler, - shutdown_rx, - )?; + let task = PyInteropTask::new(command_tx, event_rx, tcp_handler, udp_handler, shutdown_rx)?; let task = tokio::spawn(task.run()); event_tx @@ -99,7 +95,7 @@ mod tests { } } -#[pyo3_asyncio_0_21::tokio::main] +#[pyo3_async_runtimes::tokio::main] async fn main() -> pyo3::PyResult<()> { - pyo3_asyncio_0_21::testing::main().await + pyo3_async_runtimes::testing::main().await } diff --git a/mitmproxy-rs/src/dns_resolver.rs b/mitmproxy-rs/src/dns_resolver.rs index 68509914..81cde8f6 100644 --- a/mitmproxy-rs/src/dns_resolver.rs +++ b/mitmproxy-rs/src/dns_resolver.rs @@ -38,7 +38,7 @@ impl DnsResolver { /// Raises `socket.gaierror` if the domain does not exist, has no records, or there is a general connectivity failure. pub fn lookup_ip<'py>(&self, py: Python<'py>, host: String) -> PyResult> { let resolver = self.0.clone(); - pyo3_asyncio_0_21::tokio::future_into_py(py, async move { + pyo3_async_runtimes::tokio::future_into_py(py, async move { let resolved = resolver.lookup_ip(host).await; resolve_result_to_py(resolved) }) @@ -49,7 +49,7 @@ impl DnsResolver { /// Raises `socket.gaierror` if the domain does not exist, has no records, or there is a general connectivity failure. pub fn lookup_ipv4<'py>(&self, py: Python<'py>, host: String) -> PyResult> { let resolver = self.0.clone(); - pyo3_asyncio_0_21::tokio::future_into_py(py, async move { + pyo3_async_runtimes::tokio::future_into_py(py, async move { let resolved = resolver.lookup_ipv4(host).await; resolve_result_to_py(resolved) }) @@ -60,7 +60,7 @@ impl DnsResolver { /// Raises `socket.gaierror` if the domain does not exist, has no records, or there is a general connectivity failure. pub fn lookup_ipv6<'py>(&self, py: Python<'py>, host: String) -> PyResult> { let resolver = self.0.clone(); - pyo3_asyncio_0_21::tokio::future_into_py(py, async move { + pyo3_async_runtimes::tokio::future_into_py(py, async move { let resolved = resolver.lookup_ipv6(host).await; resolve_result_to_py(resolved) }) @@ -86,7 +86,7 @@ impl AddrInfoErrorConst { fn get(&self) -> isize { *self.1.get_or_init(|| { Python::with_gil(|py| { - py.import_bound("socket") + py.import("socket") .and_then(|m| m.getattr(self.0)) .and_then(|m| m.extract()) .unwrap_or_else(|e| { diff --git a/mitmproxy-rs/src/lib.rs b/mitmproxy-rs/src/lib.rs index a44c885d..994ae0ce 100644 --- a/mitmproxy-rs/src/lib.rs +++ b/mitmproxy-rs/src/lib.rs @@ -96,9 +96,11 @@ mod mitmproxy_rs { // Import platform-specific modules here so that missing dependencies are raising immediately. #[cfg(target_os = "macos")] - m.py().import_bound("mitmproxy_macos")?; + m.py().import("mitmproxy_macos")?; + #[cfg(target_os = "linux")] + m.py().import("mitmproxy_linux")?; #[cfg(windows)] - m.py().import_bound("mitmproxy_windows")?; + m.py().import("mitmproxy_windows")?; Ok(()) } diff --git a/mitmproxy-rs/src/process_info.rs b/mitmproxy-rs/src/process_info.rs index ffcc2003..a8747034 100644 --- a/mitmproxy-rs/src/process_info.rs +++ b/mitmproxy-rs/src/process_info.rs @@ -73,7 +73,7 @@ pub fn executable_icon(path: PathBuf) -> Result { let mut icon_cache = processes::ICON_CACHE.lock().unwrap(); let png_bytes = icon_cache.get_png(path)?; Ok(Python::with_gil(|py| { - pyo3::types::PyBytes::new_bound(py, png_bytes).to_object(py) + pyo3::types::PyBytes::new(py, png_bytes).to_object(py) })) } #[cfg(not(any(windows, target_os = "macos")))] diff --git a/mitmproxy-rs/src/server/base.rs b/mitmproxy-rs/src/server/base.rs index ab8b85ef..9f97472e 100644 --- a/mitmproxy-rs/src/server/base.rs +++ b/mitmproxy-rs/src/server/base.rs @@ -27,7 +27,7 @@ impl Server { pub fn wait_closed<'py>(&self, py: Python<'py>) -> PyResult> { let mut receiver = self.shutdown_done.clone(); - pyo3_asyncio_0_21::tokio::future_into_py(py, async move { + pyo3_async_runtimes::tokio::future_into_py(py, async move { receiver.recv().await; Ok(()) }) diff --git a/mitmproxy-rs/src/server/local_redirector.rs b/mitmproxy-rs/src/server/local_redirector.rs index 3371406b..9af96e87 100644 --- a/mitmproxy-rs/src/server/local_redirector.rs +++ b/mitmproxy-rs/src/server/local_redirector.rs @@ -103,14 +103,14 @@ pub fn start_local_redirector( #[cfg(windows)] { let executable_path: std::path::PathBuf = py - .import_bound("mitmproxy_windows")? + .import("mitmproxy_windows")? .call_method0("executable_path")? .extract()?; if !executable_path.exists() { return Err(anyhow::anyhow!("{} does not exist", executable_path.display()).into()); } let conf = WindowsConf { executable_path }; - pyo3_asyncio_0_21::tokio::future_into_py(py, async move { + pyo3_async_runtimes::tokio::future_into_py(py, async move { let (server, conf_tx) = Server::init(conf, handle_tcp_stream, handle_udp_stream).await?; @@ -120,14 +120,14 @@ pub fn start_local_redirector( #[cfg(target_os = "linux")] { let executable_path: std::path::PathBuf = py - .import_bound("mitmproxy_linux")? + .import("mitmproxy_linux")? .call_method0("executable_path")? .extract()?; if !executable_path.exists() { return Err(anyhow::anyhow!("{} does not exist", executable_path.display()).into()); } let conf = LinuxConf { executable_path }; - pyo3_asyncio_0_21::tokio::future_into_py(py, async move { + pyo3_async_runtimes::tokio::future_into_py(py, async move { let (server, conf_tx) = Server::init(conf, handle_tcp_stream, handle_udp_stream).await?; @@ -141,7 +141,7 @@ pub fn start_local_redirector( if destination_path.exists() { log::info!("Using existing mitmproxy redirector app."); } else { - let filename = py.import_bound("mitmproxy_macos")?.filename()?; + let filename = py.import("mitmproxy_macos")?.filename()?; let source_path = std::path::Path::new(filename.to_str()?) .parent() @@ -159,7 +159,7 @@ pub fn start_local_redirector( }); } let conf = MacosConf; - pyo3_asyncio_0_21::tokio::future_into_py(py, async move { + pyo3_async_runtimes::tokio::future_into_py(py, async move { if let Some(copy_task) = copy_task { tokio::task::spawn_blocking(copy_task) .await diff --git a/mitmproxy-rs/src/server/tun.rs b/mitmproxy-rs/src/server/tun.rs index 261287bd..9e90567a 100644 --- a/mitmproxy-rs/src/server/tun.rs +++ b/mitmproxy-rs/src/server/tun.rs @@ -61,6 +61,7 @@ impl TunInterface { /// *Availability: Linux* #[pyfunction] #[allow(unused_variables)] +#[pyo3(signature = (handle_tcp_stream, handle_udp_stream, tun_name=None))] pub fn create_tun_interface( py: Python<'_>, handle_tcp_stream: PyObject, @@ -70,7 +71,7 @@ pub fn create_tun_interface( #[cfg(target_os = "linux")] { let conf = mitmproxy::packet_sources::tun::TunConf { tun_name }; - pyo3_asyncio_0_21::tokio::future_into_py(py, async move { + pyo3_async_runtimes::tokio::future_into_py(py, async move { let (server, tun_name) = Server::init(conf, handle_tcp_stream, handle_udp_stream).await?; Ok(TunInterface { server, tun_name }) diff --git a/mitmproxy-rs/src/server/udp.rs b/mitmproxy-rs/src/server/udp.rs index a293f0c1..b30eba47 100644 --- a/mitmproxy-rs/src/server/udp.rs +++ b/mitmproxy-rs/src/server/udp.rs @@ -6,8 +6,6 @@ use pyo3::prelude::*; use crate::server::base::Server; -use crate::util::socketaddr_to_py; - /// A running UDP server. /// /// A new server can be started by calling `start_udp_server`. @@ -41,8 +39,8 @@ impl UdpServer { } /// Get the local socket address that the UDP server is listening on. - pub fn getsockname(&self, py: Python) -> PyObject { - socketaddr_to_py(py, self.local_addr) + pub fn getsockname(&self) -> (String, u16) { + (self.local_addr.ip().to_string(), self.local_addr.port()) } pub fn __repr__(&self) -> String { @@ -64,7 +62,7 @@ pub fn start_udp_server( ) -> PyResult> { let conf = UdpConf { host, port }; let handle_tcp_stream = py.None(); - pyo3_asyncio_0_21::tokio::future_into_py(py, async move { + pyo3_async_runtimes::tokio::future_into_py(py, async move { let (server, local_addr) = Server::init(conf, handle_tcp_stream, handle_udp_stream).await?; Ok(UdpServer { server, local_addr }) }) diff --git a/mitmproxy-rs/src/server/wireguard.rs b/mitmproxy-rs/src/server/wireguard.rs index cda0a488..1d5ea8b5 100644 --- a/mitmproxy-rs/src/server/wireguard.rs +++ b/mitmproxy-rs/src/server/wireguard.rs @@ -1,6 +1,6 @@ use std::net::SocketAddr; -use crate::util::{socketaddr_to_py, string_to_key}; +use crate::util::string_to_key; use mitmproxy::packet_sources::wireguard::WireGuardConf; @@ -43,8 +43,8 @@ impl WireGuardServer { } /// Get the local socket address that the WireGuard server is listening on. - pub fn getsockname(&self, py: Python) -> PyObject { - socketaddr_to_py(py, self.local_addr) + pub fn getsockname(&self) -> (String, u16) { + (self.local_addr.ip().to_string(), self.local_addr.port()) } pub fn __repr__(&self) -> String { @@ -81,7 +81,7 @@ pub fn start_wireguard_server( private_key, peer_public_keys, }; - pyo3_asyncio_0_21::tokio::future_into_py(py, async move { + pyo3_async_runtimes::tokio::future_into_py(py, async move { let (server, local_addr) = Server::init(conf, handle_tcp_stream, handle_udp_stream).await?; Ok(WireGuardServer { server, local_addr }) }) diff --git a/mitmproxy-rs/src/stream.rs b/mitmproxy-rs/src/stream.rs index dc2ba4fa..f55585ba 100644 --- a/mitmproxy-rs/src/stream.rs +++ b/mitmproxy-rs/src/stream.rs @@ -1,9 +1,7 @@ use std::net::SocketAddr; -use once_cell::sync::Lazy; - use pyo3::exceptions::PyKeyError; -use pyo3::{exceptions::PyOSError, intern, prelude::*, types::PyBytes}; +use pyo3::{exceptions::PyOSError, intern, prelude::*, IntoPyObjectExt}; use tokio::sync::{ mpsc::{self}, @@ -35,10 +33,6 @@ pub struct Stream { pub tunnel_info: TunnelInfo, } -/// Do *not* hold the GIL while accessing. -static EMPTY_BYTES: Lazy> = - Lazy::new(|| Python::with_gil(|py| PyBytes::new_bound(py, &[]).unbind())); - #[pymethods] impl Stream { /// Read up to `n` bytes of a TCP stream, or a single UDP packet (`n` is ignored for UDP). @@ -54,16 +48,12 @@ impl Stream { .send(TransportCommand::ReadData(self.connection_id, n, tx)) .ok(); // if this fails tx is dropped and rx.await will error. - pyo3_asyncio_0_21::tokio::future_into_py(py, async move { - if let Ok(data) = rx.await { - Python::with_gil(|py| Ok(PyBytes::new_bound(py, &data).unbind())) - } else { - Ok(EMPTY_BYTES.clone()) - } + pyo3_async_runtimes::tokio::future_into_py(py, async move { + Ok(rx.await.unwrap_or_default()) }) } StreamState::Closed => { - pyo3_asyncio_0_21::tokio::future_into_py(py, async move { Ok(EMPTY_BYTES.clone()) }) + pyo3_async_runtimes::tokio::future_into_py(py, async move { Ok(Vec::::new()) }) } } } @@ -97,7 +87,7 @@ impl Stream { .send(TransportCommand::DrainWriter(self.connection_id, tx)) .map_err(event_queue_unavailable)?; - pyo3_asyncio_0_21::tokio::future_into_py(py, async move { + pyo3_async_runtimes::tokio::future_into_py(py, async move { rx.await .map_err(|_| PyOSError::new_err("connection closed")) }) @@ -147,7 +137,7 @@ impl Stream { /// Wait until the stream is closed (currently a no-op). fn wait_closed<'py>(&self, py: Python<'py>) -> PyResult> { - pyo3_asyncio_0_21::tokio::future_into_py(py, std::future::ready(Ok(()))) + pyo3_async_runtimes::tokio::future_into_py(py, std::future::ready(Ok(()))) } /// Query the stream for details of the underlying network connection. @@ -156,6 +146,7 @@ impl Stream { /// - Always available: `transport_protocol`, `peername`, `sockname` /// - WireGuard mode: `original_dst`, `original_src` /// - Local redirector mode: `pid`, `process_name`, `remote_endpoint` + #[pyo3(signature = (name, default=None))] fn get_extra_info( &self, py: Python, @@ -164,20 +155,21 @@ impl Stream { ) -> PyResult { match name.as_str() { "transport_protocol" => { - if self.connection_id.is_tcp() { - return Ok(intern!(py, "tcp").to_object(py)); + let proto = if self.connection_id.is_tcp() { + intern!(py, "tcp") } else { - return Ok(intern!(py, "udp").to_object(py)); - } + intern!(py, "udp") + }; + return Ok(proto.clone().unbind().into_any()); } - "peername" => return Ok(socketaddr_to_py(py, self.peername)), - "sockname" => return Ok(socketaddr_to_py(py, self.sockname)), + "peername" => return socketaddr_to_py(py, self.peername), + "sockname" => return socketaddr_to_py(py, self.sockname), _ => (), } match &self.tunnel_info { TunnelInfo::WireGuard { src_addr, dst_addr } => match name.as_str() { - "original_src" => return Ok(socketaddr_to_py(py, *src_addr)), - "original_dst" => return Ok(socketaddr_to_py(py, *dst_addr)), + "original_src" => return socketaddr_to_py(py, *src_addr), + "original_dst" => return socketaddr_to_py(py, *dst_addr), _ => (), }, TunnelInfo::LocalRedirector { @@ -185,11 +177,11 @@ impl Stream { process_name, remote_endpoint, } => match name.as_str() { - "pid" => return Ok(pid.into_py(py)), - "process_name" => return Ok(process_name.clone().into_py(py)), + "pid" => return pid.into_py_any(py), + "process_name" => return process_name.clone().into_py_any(py), "remote_endpoint" => { if let Some(endpoint) = remote_endpoint { - return Ok(endpoint.clone().into_py(py)); + return endpoint.into_py_any(py); } } _ => (), diff --git a/mitmproxy-rs/src/task.rs b/mitmproxy-rs/src/task.rs index cf99b187..c912a9b8 100644 --- a/mitmproxy-rs/src/task.rs +++ b/mitmproxy-rs/src/task.rs @@ -4,7 +4,7 @@ use std::sync::Arc; use anyhow::{Context, Result}; use pyo3::exceptions::asyncio::CancelledError; use pyo3::prelude::*; -use pyo3_asyncio_0_21::TaskLocals; +use pyo3_async_runtimes::TaskLocals; use tokio::sync::{mpsc, Mutex}; use crate::stream::Stream; @@ -32,7 +32,7 @@ impl PyInteropTask { ) -> Result { // Note: The current asyncio event loop needs to be determined here on the main thread. let locals = Python::with_gil(|py| -> Result { - let py_loop = pyo3_asyncio_0_21::tokio::get_current_loop(py)?; + let py_loop = pyo3_async_runtimes::tokio::get_current_loop(py)?; TaskLocals::new(py_loop).copy_context(py) }) .context("failed to get python task locals")?; @@ -83,7 +83,6 @@ impl PyInteropTask { // spawn connection handler coroutine if let Err(err) = Python::with_gil(|py| -> Result<(), PyErr> { - let stream = stream.into_py(py); // calling Python coroutine object yields an awaitable object let coro = if connection_id.is_tcp() { @@ -93,7 +92,7 @@ impl PyInteropTask { }; // convert Python awaitable into Rust Future - let future = pyo3_asyncio_0_21::into_future_with_locals(&self.locals, coro.into_bound(py))?; + let future = pyo3_async_runtimes::into_future_with_locals(&self.locals, coro.into_bound(py))?; // run Future on a new Tokio task let handle = { diff --git a/mitmproxy-rs/src/udp_client.rs b/mitmproxy-rs/src/udp_client.rs index fcf67779..315404c9 100644 --- a/mitmproxy-rs/src/udp_client.rs +++ b/mitmproxy-rs/src/udp_client.rs @@ -26,7 +26,7 @@ pub fn open_udp_connection( port: u16, local_addr: Option<(String, u16)>, ) -> PyResult> { - pyo3_asyncio_0_21::tokio::future_into_py(py, async move { + pyo3_async_runtimes::tokio::future_into_py(py, async move { let socket = udp_connect(host, port, local_addr).await?; let peername = socket.peer_addr()?; diff --git a/mitmproxy-rs/src/util.rs b/mitmproxy-rs/src/util.rs index f61e8bb9..02029936 100644 --- a/mitmproxy-rs/src/util.rs +++ b/mitmproxy-rs/src/util.rs @@ -5,14 +5,12 @@ use data_encoding::BASE64; use mitmproxy::certificates; use pyo3::exceptions::PyOSError; -use pyo3::types::{PyString, PyTuple}; -use pyo3::{exceptions::PyValueError, prelude::*}; +use pyo3::{exceptions::PyValueError, prelude::*, IntoPyObjectExt}; use rand_core::OsRng; -use std::net::{IpAddr, SocketAddr}; +use std::net::SocketAddr; use boringtun::x25519::{PublicKey, StaticSecret}; -use std::str::FromStr; use tokio::sync::mpsc; pub fn string_to_key(data: String) -> PyResult @@ -27,21 +25,8 @@ where .ok_or_else(|| PyValueError::new_err("Invalid key.")) } -pub fn socketaddr_to_py(py: Python, s: SocketAddr) -> PyObject { - (s.ip().to_string(), s.port()).into_py(py) -} - -#[allow(dead_code)] -pub fn py_to_socketaddr(t: &PyTuple) -> PyResult { - if t.len() == 2 { - let host = t.get_item(0)?.downcast::()?; - let port: u16 = t.get_item(1)?.extract()?; - - let addr = IpAddr::from_str(host.to_str()?)?; - Ok(SocketAddr::from((addr, port))) - } else { - Err(PyValueError::new_err("not a socket address")) - } +pub fn socketaddr_to_py(py: Python, s: SocketAddr) -> PyResult { + (s.ip().to_string(), s.port()).into_py_any(py) } pub fn event_queue_unavailable(_: mpsc::error::SendError) -> PyErr { @@ -61,7 +46,7 @@ pub fn pubkey(private_key: String) -> PyResult { Ok(BASE64.encode(PublicKey::from(&private_key).as_bytes())) } -/// Convert pem certificate to der certificate and add it to macos keychain. +/// Convert pem certificate to der certificate and add it to macOS keychain. #[pyfunction] #[allow(unused_variables)] pub fn add_cert(py: Python<'_>, pem: String) -> PyResult<()> { @@ -73,7 +58,7 @@ pub fn add_cert(py: Python<'_>, pem: String) -> PyResult<()> { .take_while(|&line| line != "-----END CERTIFICATE-----") .collect::(); - let filename = py.import_bound("mitmproxy_rs")?.filename()?; + let filename = py.import("mitmproxy_rs")?.filename()?; let executable_path = std::path::Path::new(filename.to_str()?) .parent() .ok_or_else(|| anyhow!("invalid path"))? diff --git a/src/lib.rs b/src/lib.rs index 17a0a5c0..ae3a8748 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,6 +9,5 @@ pub mod network; pub mod packet_sources; pub mod processes; pub mod shutdown; -pub mod util; #[cfg(windows)] pub mod windows; diff --git a/src/util.rs b/src/util.rs deleted file mode 100755 index 8b137891..00000000 --- a/src/util.rs +++ /dev/null @@ -1 +0,0 @@ -