From f469f3168a52e422c28f7805a68da9e9c465d37e Mon Sep 17 00:00:00 2001 From: Jackson Coxson Date: Sat, 1 Feb 2025 15:38:29 -0700 Subject: [PATCH] Pin and box IdeviceProvider because async traits are unstable --- idevice/src/core_device_proxy.rs | 2 +- idevice/src/heartbeat.rs | 2 +- idevice/src/installation_proxy.rs | 2 +- idevice/src/lib.rs | 5 +- idevice/src/lockdownd.rs | 4 +- idevice/src/mounter.rs | 2 +- idevice/src/provider.rs | 99 +++++++++++++++++++++---------- 7 files changed, 78 insertions(+), 38 deletions(-) diff --git a/idevice/src/core_device_proxy.rs b/idevice/src/core_device_proxy.rs index f059da9..2d1b11b 100644 --- a/idevice/src/core_device_proxy.rs +++ b/idevice/src/core_device_proxy.rs @@ -70,7 +70,7 @@ impl IdeviceService for CoreDeviceProxy { } async fn connect( - provider: &impl crate::provider::IdeviceProvider, + provider: &dyn crate::provider::IdeviceProvider, ) -> Result { let mut lockdown = LockdowndClient::connect(provider).await?; let (port, ssl) = lockdown.start_service(Self::service_name()).await?; diff --git a/idevice/src/heartbeat.rs b/idevice/src/heartbeat.rs index acf07f5..563a9a6 100644 --- a/idevice/src/heartbeat.rs +++ b/idevice/src/heartbeat.rs @@ -13,7 +13,7 @@ impl IdeviceService for HeartbeatClient { } async fn connect( - provider: &impl crate::provider::IdeviceProvider, + provider: &dyn crate::provider::IdeviceProvider, ) -> Result { let mut lockdown = LockdowndClient::connect(provider).await?; let (port, ssl) = lockdown.start_service(Self::service_name()).await?; diff --git a/idevice/src/installation_proxy.rs b/idevice/src/installation_proxy.rs index 5c420b0..3fcf5b5 100644 --- a/idevice/src/installation_proxy.rs +++ b/idevice/src/installation_proxy.rs @@ -15,7 +15,7 @@ impl IdeviceService for InstallationProxyClient { } async fn connect( - provider: &impl crate::provider::IdeviceProvider, + provider: &dyn crate::provider::IdeviceProvider, ) -> Result { let mut lockdown = LockdowndClient::connect(provider).await?; let (port, ssl) = lockdown.start_service(Self::service_name()).await?; diff --git a/idevice/src/lib.rs b/idevice/src/lib.rs index 8bfc2ce..14189a1 100644 --- a/idevice/src/lib.rs +++ b/idevice/src/lib.rs @@ -31,7 +31,7 @@ impl ReadWrit pub trait IdeviceService: Sized { fn service_name() -> &'static str; fn connect( - provider: &impl IdeviceProvider, + provider: &dyn IdeviceProvider, ) -> impl std::future::Future> + Send; } @@ -202,6 +202,9 @@ pub enum IdeviceError { #[error("JSON serialization failed")] Json(#[from] serde_json::Error), + #[error("device not found")] + DeviceNotFound, + #[error("unknown error `{0}` returned from device")] UnknownErrorType(String), } diff --git a/idevice/src/lockdownd.rs b/idevice/src/lockdownd.rs index 964e268..62ce39b 100644 --- a/idevice/src/lockdownd.rs +++ b/idevice/src/lockdownd.rs @@ -16,10 +16,10 @@ impl IdeviceService for LockdowndClient { } async fn connect( - provider: &impl crate::provider::IdeviceProvider, + provider: &dyn crate::provider::IdeviceProvider, ) -> Result { let idevice = provider.connect(Self::LOCKDOWND_PORT).await?; - Ok(Self { idevice }) + Ok(Self::new(idevice)) } } diff --git a/idevice/src/mounter.rs b/idevice/src/mounter.rs index 1ed1e6f..d555d49 100644 --- a/idevice/src/mounter.rs +++ b/idevice/src/mounter.rs @@ -12,7 +12,7 @@ impl IdeviceService for ImageMounter { } async fn connect( - provider: &impl crate::provider::IdeviceProvider, + provider: &dyn crate::provider::IdeviceProvider, ) -> Result { let mut lockdown = LockdowndClient::connect(provider).await?; let (port, ssl) = lockdown.start_service(Self::service_name()).await?; diff --git a/idevice/src/provider.rs b/idevice/src/provider.rs index 12e046d..6938ba7 100644 --- a/idevice/src/provider.rs +++ b/idevice/src/provider.rs @@ -1,70 +1,107 @@ // Jackson Coxson -use std::net::{IpAddr, SocketAddr}; +use std::{ + future::Future, + net::{IpAddr, SocketAddr}, + pin::Pin, +}; use tokio::net::TcpStream; -use crate::{pairing_file::PairingFile, usbmuxd::UsbmuxdAddr, Idevice, IdeviceError}; +use crate::{pairing_file::PairingFile, Idevice, IdeviceError}; +#[cfg(feature = "usbmuxd")] +use crate::usbmuxd::UsbmuxdAddr; + +/// A provider for connecting to the iOS device +/// This is an ugly trait until async traits are stabilized pub trait IdeviceProvider: Unpin + Send + Sync + std::fmt::Debug { - // https://blog.rust-lang.org/2023/12/21/async-fn-rpit-in-traits.html#is-it-okay-to-use-async-fn-in-traits-what-are-the-limitations fn connect( &self, port: u16, - ) -> impl std::future::Future> + Send; + ) -> Pin> + Send>>; + fn label(&self) -> &str; + fn get_pairing_file( &self, - ) -> impl std::future::Future> + Send; + ) -> Pin> + Send>>; } #[derive(Debug)] pub struct TcpProvider { - addr: IpAddr, - pairing_file: PairingFile, - label: String, + pub addr: IpAddr, + pub pairing_file: PairingFile, + pub label: String, } impl IdeviceProvider for TcpProvider { - async fn connect(&self, port: u16) -> Result { - let socket_addr = SocketAddr::new(self.addr, port); - let stream = TcpStream::connect(socket_addr).await?; - Ok(Idevice::new(Box::new(stream), self.label.to_owned())) - } - fn label(&self) -> &str { - self.label.as_str() + fn connect( + &self, + port: u16, + ) -> Pin> + Send>> { + let addr = self.addr; + let label = self.label.clone(); + Box::pin(async move { + let socket_addr = SocketAddr::new(addr, port); + let stream = TcpStream::connect(socket_addr).await?; + Ok(Idevice::new(Box::new(stream), label)) + }) } - async fn get_pairing_file(&self) -> Result { - Ok(self.pairing_file.clone()) + fn label(&self) -> &str { + &self.label + } + + fn get_pairing_file( + &self, + ) -> Pin> + Send>> { + let pairing_file = self.pairing_file.clone(); + Box::pin(async move { Ok(pairing_file) }) } } #[cfg(feature = "usbmuxd")] #[derive(Debug)] pub struct UsbmuxdProvider { - addr: UsbmuxdAddr, - tag: u32, - udid: String, - device_id: u32, - label: String, + pub addr: UsbmuxdAddr, + pub tag: u32, + pub udid: String, + pub device_id: u32, + pub label: String, } #[cfg(feature = "usbmuxd")] impl IdeviceProvider for UsbmuxdProvider { - async fn connect(&self, port: u16) -> Result { - let usbmuxd = self.addr.connect(self.tag).await?; - usbmuxd - .connect_to_device(self.device_id, port, &self.label) - .await + fn connect( + &self, + port: u16, + ) -> Pin> + Send>> { + let addr = self.addr.clone(); + let tag = self.tag; + let device_id = self.device_id; + let label = self.label.clone(); + + Box::pin(async move { + let usbmuxd = addr.connect(tag).await?; + usbmuxd.connect_to_device(device_id, port, &label).await + }) } fn label(&self) -> &str { - self.label.as_str() + &self.label } - async fn get_pairing_file(&self) -> Result { - let mut usbmuxd = self.addr.connect(self.tag).await?; - usbmuxd.get_pair_record(&self.udid).await + fn get_pairing_file( + &self, + ) -> Pin> + Send>> { + let addr = self.addr.clone(); + let tag = self.tag; + let udid = self.udid.clone(); + + Box::pin(async move { + let mut usbmuxd = addr.connect(tag).await?; + usbmuxd.get_pair_record(&udid).await + }) } }