Pin and box IdeviceProvider because async traits are unstable

This commit is contained in:
Jackson Coxson
2025-02-01 15:38:29 -07:00
parent 046be92bba
commit f469f3168a
7 changed files with 78 additions and 38 deletions

View File

@@ -70,7 +70,7 @@ impl IdeviceService for CoreDeviceProxy {
}
async fn connect(
provider: &impl crate::provider::IdeviceProvider,
provider: &dyn crate::provider::IdeviceProvider,
) -> Result<Self, IdeviceError> {
let mut lockdown = LockdowndClient::connect(provider).await?;
let (port, ssl) = lockdown.start_service(Self::service_name()).await?;

View File

@@ -13,7 +13,7 @@ impl IdeviceService for HeartbeatClient {
}
async fn connect(
provider: &impl crate::provider::IdeviceProvider,
provider: &dyn crate::provider::IdeviceProvider,
) -> Result<Self, IdeviceError> {
let mut lockdown = LockdowndClient::connect(provider).await?;
let (port, ssl) = lockdown.start_service(Self::service_name()).await?;

View File

@@ -15,7 +15,7 @@ impl IdeviceService for InstallationProxyClient {
}
async fn connect(
provider: &impl crate::provider::IdeviceProvider,
provider: &dyn crate::provider::IdeviceProvider,
) -> Result<Self, IdeviceError> {
let mut lockdown = LockdowndClient::connect(provider).await?;
let (port, ssl) = lockdown.start_service(Self::service_name()).await?;

View File

@@ -31,7 +31,7 @@ impl<T: AsyncRead + AsyncWrite + Unpin + Send + Sync + std::fmt::Debug> ReadWrit
pub trait IdeviceService: Sized {
fn service_name() -> &'static str;
fn connect(
provider: &impl IdeviceProvider,
provider: &dyn IdeviceProvider,
) -> impl std::future::Future<Output = Result<Self, IdeviceError>> + 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),
}

View File

@@ -16,10 +16,10 @@ impl IdeviceService for LockdowndClient {
}
async fn connect(
provider: &impl crate::provider::IdeviceProvider,
provider: &dyn crate::provider::IdeviceProvider,
) -> Result<Self, IdeviceError> {
let idevice = provider.connect(Self::LOCKDOWND_PORT).await?;
Ok(Self { idevice })
Ok(Self::new(idevice))
}
}

View File

@@ -12,7 +12,7 @@ impl IdeviceService for ImageMounter {
}
async fn connect(
provider: &impl crate::provider::IdeviceProvider,
provider: &dyn crate::provider::IdeviceProvider,
) -> Result<Self, IdeviceError> {
let mut lockdown = LockdowndClient::connect(provider).await?;
let (port, ssl) = lockdown.start_service(Self::service_name()).await?;

View File

@@ -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<Output = Result<Idevice, IdeviceError>> + Send;
) -> Pin<Box<dyn Future<Output = Result<Idevice, IdeviceError>> + Send>>;
fn label(&self) -> &str;
fn get_pairing_file(
&self,
) -> impl std::future::Future<Output = Result<PairingFile, IdeviceError>> + Send;
) -> Pin<Box<dyn Future<Output = Result<PairingFile, IdeviceError>> + 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<Idevice, IdeviceError> {
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<Box<dyn Future<Output = Result<Idevice, IdeviceError>> + 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<PairingFile, IdeviceError> {
Ok(self.pairing_file.clone())
fn label(&self) -> &str {
&self.label
}
fn get_pairing_file(
&self,
) -> Pin<Box<dyn Future<Output = Result<PairingFile, IdeviceError>> + 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<Idevice, IdeviceError> {
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<Box<dyn Future<Output = Result<Idevice, IdeviceError>> + 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<PairingFile, IdeviceError> {
let mut usbmuxd = self.addr.connect(self.tag).await?;
usbmuxd.get_pair_record(&self.udid).await
fn get_pairing_file(
&self,
) -> Pin<Box<dyn Future<Output = Result<PairingFile, IdeviceError>> + 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
})
}
}