use std::{future::Future, pin::Pin};
use std::net::IpAddr;
use std::net::{SocketAddr, SocketAddrV6};
#[cfg(feature = "tcp")]
use tokio::net::TcpStream;
use crate::{Idevice, IdeviceError, ReadWrite, pairing_file::PairingFile};
#[cfg(feature = "usbmuxd")]
use crate::usbmuxd::UsbmuxdAddr;
pub trait IdeviceProvider: Unpin + Send + Sync + std::fmt::Debug {
fn connect(
&self,
port: u16,
) -> Pin<Box<dyn Future<Output = Result<Idevice, IdeviceError>> + Send>>;
fn label(&self) -> &str;
fn get_pairing_file(
&self,
) -> Pin<Box<dyn Future<Output = Result<PairingFile, IdeviceError>> + Send>>;
}
pub trait RsdProvider: Unpin + Send + Sync + std::fmt::Debug {
fn connect_to_service_port(
&mut self,
port: u16,
) -> impl std::future::Future<Output = Result<Box<dyn ReadWrite>, IdeviceError>> + Send;
}
#[cfg(feature = "tcp")]
#[derive(Debug)]
pub struct TcpProvider {
pub addr: std::net::IpAddr,
pub scope_id: Option<u32>,
pub pairing_file: PairingFile,
pub label: String,
}
#[cfg(feature = "tcp")]
impl IdeviceProvider for TcpProvider {
fn connect(
&self,
port: u16,
) -> Pin<Box<dyn Future<Output = Result<Idevice, IdeviceError>> + Send>> {
let addr = self.addr;
let label = self.label.clone();
let scope_id = self.scope_id.unwrap_or(0);
Box::pin(async move {
let socket_addr = match addr {
IpAddr::V4(_) => SocketAddr::new(addr, port),
IpAddr::V6(ipv6) => SocketAddr::V6(SocketAddrV6::new(ipv6, port, 0, scope_id)),
};
let stream = TcpStream::connect(socket_addr).await?;
Ok(Idevice::new(Box::new(stream), label))
})
}
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, Clone)]
pub struct UsbmuxdProvider {
pub addr: UsbmuxdAddr,
pub tag: u32,
pub udid: String,
pub device_id: u32,
pub label: String,
}
#[cfg(feature = "usbmuxd")]
impl IdeviceProvider for UsbmuxdProvider {
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
}
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
})
}
}
#[cfg(feature = "tcp")]
impl RsdProvider for std::net::IpAddr {
async fn connect_to_service_port(
&mut self,
port: u16,
) -> Result<Box<dyn ReadWrite>, IdeviceError> {
Ok(Box::new(
tokio::net::TcpStream::connect((*self, port)).await?,
))
}
}