Unify IdeviceService creation behavior with trait

This commit is contained in:
Jackson Coxson
2025-08-11 13:56:09 -06:00
parent 0a0899cd8a
commit c80512f37f
16 changed files with 59 additions and 455 deletions

View File

@@ -16,10 +16,6 @@ jobs:
run: | run: |
brew install just brew install just
- name: Install libplist
run: |
brew install libplist
- name: Cache Cargo - name: Cache Cargo
uses: actions/cache@v4 uses: actions/cache@v4
with: with:
@@ -73,7 +69,7 @@ jobs:
- name: Install build dependencies - name: Install build dependencies
run: | run: |
sudo apt-get update && sudo apt-get install -y build-essential cmake libplist sudo apt-get update && sudo apt-get install -y build-essential cmake
- name: Install just - name: Install just
run: | run: |

View File

@@ -37,6 +37,8 @@ use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
pub use util::{pretty_print_dictionary, pretty_print_plist}; pub use util::{pretty_print_dictionary, pretty_print_plist};
use crate::services::lockdown::LockdownClient;
/// A trait combining all required characteristics for a device communication socket /// A trait combining all required characteristics for a device communication socket
/// ///
/// This serves as a convenience trait for any type that can be used as an asynchronous /// This serves as a convenience trait for any type that can be used as an asynchronous
@@ -61,9 +63,25 @@ pub trait IdeviceService: Sized {
/// ///
/// # Arguments /// # Arguments
/// * `provider` - The device provider that can supply connections /// * `provider` - The device provider that can supply connections
fn connect( async fn connect(provider: &dyn IdeviceProvider) -> Result<Self, IdeviceError> {
provider: &dyn IdeviceProvider, let mut lockdown = LockdownClient::connect(provider).await?;
) -> impl std::future::Future<Output = Result<Self, IdeviceError>> + Send; lockdown
.start_session(&provider.get_pairing_file().await?)
.await?;
let (port, ssl) = lockdown.start_service(Self::service_name()).await?;
let mut idevice = provider.connect(port).await?;
if ssl {
idevice
.start_session(&provider.get_pairing_file().await?)
.await?;
}
Self::from_stream(idevice).await
}
async fn from_stream(idevice: Idevice) -> Result<Self, IdeviceError>;
} }
#[cfg(feature = "rsd")] #[cfg(feature = "rsd")]

View File

@@ -11,7 +11,7 @@ use log::warn;
use opcode::{AfcFopenMode, AfcOpcode}; use opcode::{AfcFopenMode, AfcOpcode};
use packet::{AfcPacket, AfcPacketHeader}; use packet::{AfcPacket, AfcPacketHeader};
use crate::{lockdown::LockdownClient, obf, Idevice, IdeviceError, IdeviceService}; use crate::{obf, Idevice, IdeviceError, IdeviceService};
pub mod errors; pub mod errors;
pub mod file; pub mod file;
@@ -65,30 +65,7 @@ impl IdeviceService for AfcClient {
obf!("com.apple.afc") obf!("com.apple.afc")
} }
/// Connects to the AFC service on the device async fn from_stream(idevice: Idevice) -> Result<Self, IdeviceError> {
///
/// # Arguments
/// * `provider` - The iDevice provider to use for the connection
///
/// # Returns
/// A new `AfcClient` instance on success
async fn connect(
provider: &dyn crate::provider::IdeviceProvider,
) -> Result<Self, IdeviceError> {
let mut lockdown = LockdownClient::connect(provider).await?;
lockdown
.start_session(&provider.get_pairing_file().await?)
.await?;
let (port, ssl) = lockdown.start_service(Self::service_name()).await?;
let mut idevice = provider.connect(port).await?;
if ssl {
idevice
.start_session(&provider.get_pairing_file().await?)
.await?;
}
Ok(Self { Ok(Self {
idevice, idevice,
package_number: 0, package_number: 0,

View File

@@ -2,7 +2,7 @@
use plist::Dictionary; use plist::Dictionary;
use crate::{lockdown::LockdownClient, obf, Idevice, IdeviceError, IdeviceService}; use crate::{obf, Idevice, IdeviceError, IdeviceService};
/// Client for interacting with the AMFI service on the device /// Client for interacting with the AMFI service on the device
pub struct AmfiClient { pub struct AmfiClient {
@@ -16,41 +16,8 @@ impl IdeviceService for AmfiClient {
obf!("com.apple.amfi.lockdown") obf!("com.apple.amfi.lockdown")
} }
/// Establishes a connection to the amfi service async fn from_stream(idevice: Idevice) -> Result<Self, crate::IdeviceError> {
/// Ok(Self::new(idevice))
/// # Arguments
/// * `provider` - Device connection provider
///
/// # Returns
/// A connected `AmfiClient` instance
///
/// # Errors
/// Returns `IdeviceError` if any step of the connection process fails
///
/// # Process
/// 1. Connects to lockdownd service
/// 2. Starts a lockdown session
/// 3. Requests the amfi service port
/// 4. Establishes connection to the amfi port
/// 5. Optionally starts TLS if required by service
async fn connect(
provider: &dyn crate::provider::IdeviceProvider,
) -> Result<Self, IdeviceError> {
let mut lockdown = LockdownClient::connect(provider).await?;
lockdown
.start_session(&provider.get_pairing_file().await?)
.await?;
let (port, ssl) = lockdown.start_service(Self::service_name()).await?;
let mut idevice = provider.connect(port).await?;
if ssl {
idevice
.start_session(&provider.get_pairing_file().await?)
.await?;
}
Ok(Self { idevice })
} }
} }

View File

@@ -13,7 +13,7 @@
//! # Features //! # Features
//! - `tunnel_tcp_stack`: Enables software TCP/IP tunnel creation using a virtual adapter. See the tcp moduel. //! - `tunnel_tcp_stack`: Enables software TCP/IP tunnel creation using a virtual adapter. See the tcp moduel.
use crate::{lockdown::LockdownClient, obf, Idevice, IdeviceError, IdeviceService}; use crate::{obf, Idevice, IdeviceError, IdeviceService};
use byteorder::{BigEndian, WriteBytesExt}; use byteorder::{BigEndian, WriteBytesExt};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -97,34 +97,7 @@ impl IdeviceService for CoreDeviceProxy {
obf!("com.apple.internal.devicecompute.CoreDeviceProxy") obf!("com.apple.internal.devicecompute.CoreDeviceProxy")
} }
/// Connects to the CoreDeviceProxy service async fn from_stream(idevice: Idevice) -> Result<Self, crate::IdeviceError> {
///
/// # Arguments
///
/// * `provider` - An implementation of `IdeviceProvider` that supplies
/// pairing data and socket connections.
///
/// # Returns
///
/// * `Ok(CoreDeviceProxy)` if connection and handshake succeed.
/// * `Err(IdeviceError)` if any step fails.
async fn connect(
provider: &dyn crate::provider::IdeviceProvider,
) -> Result<Self, IdeviceError> {
let mut lockdown = LockdownClient::connect(provider).await?;
lockdown
.start_session(&provider.get_pairing_file().await?)
.await?;
let (port, ssl) = lockdown.start_service(Self::service_name()).await?;
let mut idevice = provider.connect(port).await?;
if ssl {
idevice
.start_session(&provider.get_pairing_file().await?)
.await?;
}
Self::new(idevice).await Self::new(idevice).await
} }
} }

View File

@@ -26,43 +26,8 @@ impl IdeviceService for CrashReportCopyMobileClient {
obf!("com.apple.crashreportcopymobile") obf!("com.apple.crashreportcopymobile")
} }
/// Connects to the CrashReportCopyMobile service on the device. async fn from_stream(idevice: Idevice) -> Result<Self, crate::IdeviceError> {
/// Ok(Self::new(idevice))
/// # Arguments
/// * `provider` - The provider used to access the device and pairing info.
///
/// # Returns
/// A connected `CrashReportCopyMobileClient`.
///
/// # Errors
/// Returns `IdeviceError` if the connection fails at any stage.
///
/// # Process
/// 1. Connects to the lockdownd service.
/// 2. Starts a lockdown session.
/// 3. Requests the CrashReportCopyMobile service.
/// 4. Establishes a connection to the service.
/// 5. Performs SSL handshake if required.
async fn connect(
provider: &dyn crate::provider::IdeviceProvider,
) -> Result<Self, IdeviceError> {
let mut lockdown = LockdownClient::connect(provider).await?;
lockdown
.start_session(&provider.get_pairing_file().await?)
.await?;
let (port, ssl) = lockdown.start_service(Self::service_name()).await?;
let mut idevice = provider.connect(port).await?;
if ssl {
idevice
.start_session(&provider.get_pairing_file().await?)
.await?;
}
Ok(Self {
afc_client: AfcClient::new(idevice),
})
} }
} }

View File

@@ -1,6 +1,6 @@
//! Diagnostics Relay //! Diagnostics Relay
use crate::{lockdown::LockdownClient, obf, Idevice, IdeviceError, IdeviceService}; use crate::{obf, Idevice, IdeviceError, IdeviceService};
/// Client for interacting with the Diagnostics Relay /// Client for interacting with the Diagnostics Relay
pub struct DiagnosticsRelayClient { pub struct DiagnosticsRelayClient {
@@ -14,41 +14,8 @@ impl IdeviceService for DiagnosticsRelayClient {
obf!("com.apple.mobile.diagnostics_relay") obf!("com.apple.mobile.diagnostics_relay")
} }
/// Establishes a connection to the service async fn from_stream(idevice: Idevice) -> Result<Self, crate::IdeviceError> {
/// Ok(Self::new(idevice))
/// # Arguments
/// * `provider` - Device connection provider
///
/// # Returns
/// A connected `DiagnosticsRelayClient` instance
///
/// # Errors
/// Returns `IdeviceError` if any step of the connection process fails
///
/// # Process
/// 1. Connects to lockdownd service
/// 2. Starts a lockdown session
/// 3. Requests the service port
/// 4. Establishes connection to the port
/// 5. Optionally starts TLS if required by service
async fn connect(
provider: &dyn crate::provider::IdeviceProvider,
) -> Result<Self, IdeviceError> {
let mut lockdown = LockdownClient::connect(provider).await?;
lockdown
.start_session(&provider.get_pairing_file().await?)
.await?;
let (port, ssl) = lockdown.start_service(Self::service_name()).await?;
let mut idevice = provider.connect(port).await?;
if ssl {
idevice
.start_session(&provider.get_pairing_file().await?)
.await?;
}
Ok(Self { idevice })
} }
} }

View File

@@ -3,7 +3,7 @@
//! iOS automatically closes service connections if there is no heartbeat client connected and //! iOS automatically closes service connections if there is no heartbeat client connected and
//! responding. //! responding.
use crate::{lockdown::LockdownClient, obf, Idevice, IdeviceError, IdeviceService}; use crate::{obf, Idevice, IdeviceError, IdeviceService};
/// Client for interacting with the iOS device heartbeat service /// Client for interacting with the iOS device heartbeat service
/// ///
@@ -22,42 +22,8 @@ impl IdeviceService for HeartbeatClient {
fn service_name() -> std::borrow::Cow<'static, str> { fn service_name() -> std::borrow::Cow<'static, str> {
obf!("com.apple.mobile.heartbeat") obf!("com.apple.mobile.heartbeat")
} }
async fn from_stream(idevice: Idevice) -> Result<Self, crate::IdeviceError> {
/// Establishes a connection to the heartbeat service Ok(Self::new(idevice))
///
/// # Arguments
/// * `provider` - Device connection provider
///
/// # Returns
/// A connected `HeartbeatClient` instance
///
/// # Errors
/// Returns `IdeviceError` if any step of the connection process fails
///
/// # Process
/// 1. Connects to lockdownd service
/// 2. Starts a lockdown session
/// 3. Requests the heartbeat service port
/// 4. Establishes connection to the heartbeat port
/// 5. Optionally starts TLS if required by service
async fn connect(
provider: &dyn crate::provider::IdeviceProvider,
) -> Result<Self, IdeviceError> {
let mut lockdown = LockdownClient::connect(provider).await?;
lockdown
.start_session(&provider.get_pairing_file().await?)
.await?;
let (port, ssl) = lockdown.start_service(Self::service_name()).await?;
let mut idevice = provider.connect(port).await?;
if ssl {
idevice
.start_session(&provider.get_pairing_file().await?)
.await?;
}
Ok(Self { idevice })
} }
} }

View File

@@ -6,7 +6,7 @@
use plist::{Dictionary, Value}; use plist::{Dictionary, Value};
use crate::{lockdown::LockdownClient, obf, Idevice, IdeviceError, IdeviceService}; use crate::{obf, Idevice, IdeviceError, IdeviceService};
use super::afc::AfcClient; use super::afc::AfcClient;
@@ -25,41 +25,8 @@ impl IdeviceService for HouseArrestClient {
obf!("com.apple.mobile.house_arrest") obf!("com.apple.mobile.house_arrest")
} }
/// Establishes a connection to the HouseArrest service async fn from_stream(idevice: Idevice) -> Result<Self, crate::IdeviceError> {
/// Ok(Self::new(idevice))
/// # Arguments
/// * `provider` - Device connection provider
///
/// # Returns
/// A connected `HouseArrestClient` instance
///
/// # Errors
/// Returns `IdeviceError` if any step of the connection process fails
///
/// # Process
/// 1. Connect to the lockdownd service
/// 2. Start a lockdown session
/// 3. Request the HouseArrest service
/// 4. Connect to the returned service port
/// 5. Start TLS if required by the service
async fn connect(
provider: &dyn crate::provider::IdeviceProvider,
) -> Result<Self, IdeviceError> {
let mut lockdown = LockdownClient::connect(provider).await?;
lockdown
.start_session(&provider.get_pairing_file().await?)
.await?;
let (port, ssl) = lockdown.start_service(Self::service_name()).await?;
let mut idevice = provider.connect(port).await?;
if ssl {
idevice
.start_session(&provider.get_pairing_file().await?)
.await?;
}
Ok(Self { idevice })
} }
} }

View File

@@ -8,7 +8,7 @@ use std::collections::HashMap;
use log::warn; use log::warn;
use plist::Dictionary; use plist::Dictionary;
use crate::{lockdown::LockdownClient, obf, Idevice, IdeviceError, IdeviceService}; use crate::{obf, Idevice, IdeviceError, IdeviceService};
/// Client for interacting with the iOS installation proxy service /// Client for interacting with the iOS installation proxy service
/// ///
@@ -25,39 +25,7 @@ impl IdeviceService for InstallationProxyClient {
obf!("com.apple.mobile.installation_proxy") obf!("com.apple.mobile.installation_proxy")
} }
/// Establishes a connection to the installation proxy service async fn from_stream(idevice: Idevice) -> Result<Self, crate::IdeviceError> {
///
/// # Arguments
/// * `provider` - Device connection provider
///
/// # Returns
/// A connected `InstallationProxyClient` instance
///
/// # Errors
/// Returns `IdeviceError` if any step of the connection process fails
///
/// # Process
/// 1. Connects to lockdownd service
/// 2. Starts a lockdown session
/// 3. Requests the installation proxy service port
/// 4. Establishes connection to the service port
/// 5. Optionally starts TLS if required by service
async fn connect(
provider: &dyn crate::provider::IdeviceProvider,
) -> Result<Self, IdeviceError> {
let mut lockdown = LockdownClient::connect(provider).await?;
lockdown
.start_session(&provider.get_pairing_file().await?)
.await?;
let (port, ssl) = lockdown.start_service(Self::service_name()).await?;
let mut idevice = provider.connect(port).await?;
if ssl {
idevice
.start_session(&provider.get_pairing_file().await?)
.await?;
}
Ok(Self::new(idevice)) Ok(Self::new(idevice))
} }
} }

View File

@@ -42,6 +42,10 @@ impl IdeviceService for LockdownClient {
let idevice = provider.connect(Self::LOCKDOWND_PORT).await?; let idevice = provider.connect(Self::LOCKDOWND_PORT).await?;
Ok(Self::new(idevice)) Ok(Self::new(idevice))
} }
async fn from_stream(idevice: Idevice) -> Result<Self, crate::IdeviceError> {
Ok(Self::new(idevice))
}
} }
/// Internal structure for lockdown protocol requests /// Internal structure for lockdown protocol requests

View File

@@ -6,7 +6,7 @@
use log::warn; use log::warn;
use plist::Dictionary; use plist::Dictionary;
use crate::{lockdown::LockdownClient, obf, Idevice, IdeviceError, IdeviceService, RsdService}; use crate::{obf, Idevice, IdeviceError, IdeviceService, RsdService};
/// Client for interacting with the iOS misagent service /// Client for interacting with the iOS misagent service
/// ///
@@ -37,39 +37,7 @@ impl IdeviceService for MisagentClient {
obf!("com.apple.misagent") obf!("com.apple.misagent")
} }
/// Establishes a connection to the misagent service async fn from_stream(idevice: Idevice) -> Result<Self, crate::IdeviceError> {
///
/// # Arguments
/// * `provider` - Device connection provider
///
/// # Returns
/// A connected `MisagentClient` instance
///
/// # Errors
/// Returns `IdeviceError` if any step of the connection process fails
///
/// # Process
/// 1. Connects to lockdownd service
/// 2. Starts a lockdown session
/// 3. Requests the misagent service port
/// 4. Establishes connection to the service port
/// 5. Optionally starts TLS if required by service
async fn connect(
provider: &dyn crate::provider::IdeviceProvider,
) -> Result<Self, IdeviceError> {
let mut lockdown = LockdownClient::connect(provider).await?;
lockdown
.start_session(&provider.get_pairing_file().await?)
.await?;
let (port, ssl) = lockdown.start_service(Self::service_name()).await?;
let mut idevice = provider.connect(port).await?;
if ssl {
idevice
.start_session(&provider.get_pairing_file().await?)
.await?;
}
Ok(Self::new(idevice)) Ok(Self::new(idevice))
} }
} }

View File

@@ -9,7 +9,7 @@
use log::debug; use log::debug;
use crate::{lockdown::LockdownClient, obf, Idevice, IdeviceError, IdeviceService}; use crate::{obf, Idevice, IdeviceError, IdeviceService};
use sha2::{Digest, Sha384}; use sha2::{Digest, Sha384};
#[cfg(feature = "tss")] #[cfg(feature = "tss")]
@@ -33,41 +33,8 @@ impl IdeviceService for ImageMounter {
obf!("com.apple.mobile.mobile_image_mounter") obf!("com.apple.mobile.mobile_image_mounter")
} }
/// Establishes a connection to the image mounter service async fn from_stream(idevice: Idevice) -> Result<Self, crate::IdeviceError> {
/// Ok(Self::new(idevice))
/// # Arguments
/// * `provider` - Device connection provider
///
/// # Returns
/// A connected `ImageMounter` instance
///
/// # Errors
/// Returns `IdeviceError` if any step of the connection process fails
///
/// # Process
/// 1. Connects to lockdownd service
/// 2. Starts a lockdown session
/// 3. Requests the image mounter service port
/// 4. Establishes connection to the service port
/// 5. Optionally starts TLS if required by service
async fn connect(
provider: &dyn crate::provider::IdeviceProvider,
) -> Result<Self, IdeviceError> {
let mut lockdown = LockdownClient::connect(provider).await?;
lockdown
.start_session(&provider.get_pairing_file().await?)
.await?;
let (port, ssl) = lockdown.start_service(Self::service_name()).await?;
let mut idevice = provider.connect(port).await?;
if ssl {
idevice
.start_session(&provider.get_pairing_file().await?)
.await?;
}
Ok(Self { idevice })
} }
} }

View File

@@ -7,7 +7,7 @@ use chrono::{DateTime, NaiveDateTime};
use plist::Dictionary; use plist::Dictionary;
use tokio::io::AsyncWriteExt; use tokio::io::AsyncWriteExt;
use crate::{lockdown::LockdownClient, obf, Idevice, IdeviceError, IdeviceService}; use crate::{obf, Idevice, IdeviceError, IdeviceService};
/// Client for interacting with the iOS device OsTraceRelay service /// Client for interacting with the iOS device OsTraceRelay service
pub struct OsTraceRelayClient { pub struct OsTraceRelayClient {
@@ -21,40 +21,7 @@ impl IdeviceService for OsTraceRelayClient {
obf!("com.apple.os_trace_relay") obf!("com.apple.os_trace_relay")
} }
/// Establishes a connection to the OsTraceRelay service async fn from_stream(idevice: Idevice) -> Result<Self, crate::IdeviceError> {
///
/// # Arguments
/// * `provider` - Device connection provider
///
/// # Returns
/// A connected `OsTraceRelayClient` instance
///
/// # Errors
/// Returns `IdeviceError` if any step of the connection process fails
///
/// # Process
/// 1. Connects to lockdownd service
/// 2. Starts a lockdown session
/// 3. Requests the OsTraceRelay service port
/// 4. Establishes connection to the OsTraceRelay port
/// 5. Optionally starts TLS if required by service
async fn connect(
provider: &dyn crate::provider::IdeviceProvider,
) -> Result<Self, IdeviceError> {
let mut lockdown = LockdownClient::connect(provider).await?;
lockdown
.start_session(&provider.get_pairing_file().await?)
.await?;
let (port, ssl) = lockdown.start_service(Self::service_name()).await?;
let mut idevice = provider.connect(port).await?;
if ssl {
idevice
.start_session(&provider.get_pairing_file().await?)
.await?;
}
Ok(Self { idevice }) Ok(Self { idevice })
} }
} }

View File

@@ -3,7 +3,7 @@
//! Provides functionality for interacting with the SpringBoard services on iOS devices, //! Provides functionality for interacting with the SpringBoard services on iOS devices,
//! which manages home screen and app icon related operations. //! which manages home screen and app icon related operations.
use crate::{lockdown::LockdownClient, obf, Idevice, IdeviceError, IdeviceService}; use crate::{obf, Idevice, IdeviceError, IdeviceService};
/// Client for interacting with the iOS SpringBoard services /// Client for interacting with the iOS SpringBoard services
/// ///
@@ -20,41 +20,8 @@ impl IdeviceService for SpringBoardServicesClient {
obf!("com.apple.springboardservices") obf!("com.apple.springboardservices")
} }
/// Establishes a connection to the SpringBoard services async fn from_stream(idevice: Idevice) -> Result<Self, crate::IdeviceError> {
/// Ok(Self::new(idevice))
/// # Arguments
/// * `provider` - Device connection provider
///
/// # Returns
/// A connected `SpringBoardServicesClient` instance
///
/// # Errors
/// Returns `IdeviceError` if any step of the connection process fails
///
/// # Process
/// 1. Connects to lockdownd service
/// 2. Starts a lockdown session
/// 3. Requests the SpringBoard services port
/// 4. Establishes connection to the service port
/// 5. Optionally starts TLS if required by service
async fn connect(
provider: &dyn crate::provider::IdeviceProvider,
) -> Result<Self, IdeviceError> {
let mut lockdown = LockdownClient::connect(provider).await?;
lockdown
.start_session(&provider.get_pairing_file().await?)
.await?;
let (port, ssl) = lockdown.start_service(Self::service_name()).await?;
let mut idevice = provider.connect(port).await?;
if ssl {
idevice
.start_session(&provider.get_pairing_file().await?)
.await?;
}
Ok(Self { idevice })
} }
} }

View File

@@ -1,6 +1,6 @@
//! iOS Device SyslogRelay Service Abstraction //! iOS Device SyslogRelay Service Abstraction
use crate::{lockdown::LockdownClient, obf, Idevice, IdeviceError, IdeviceService}; use crate::{obf, Idevice, IdeviceError, IdeviceService};
/// Client for interacting with the iOS device SyslogRelay service /// Client for interacting with the iOS device SyslogRelay service
pub struct SyslogRelayClient { pub struct SyslogRelayClient {
@@ -14,41 +14,8 @@ impl IdeviceService for SyslogRelayClient {
obf!("com.apple.syslog_relay") obf!("com.apple.syslog_relay")
} }
/// Establishes a connection to the SyslogRelay service async fn from_stream(idevice: Idevice) -> Result<Self, crate::IdeviceError> {
/// Ok(Self::new(idevice))
/// # Arguments
/// * `provider` - Device connection provider
///
/// # Returns
/// A connected `SyslogRelayClient` instance
///
/// # Errors
/// Returns `IdeviceError` if any step of the connection process fails
///
/// # Process
/// 1. Connects to lockdownd service
/// 2. Starts a lockdown session
/// 3. Requests the SyslogRelay service port
/// 4. Establishes connection to the SyslogRelay port
/// 5. Optionally starts TLS if required by service
async fn connect(
provider: &dyn crate::provider::IdeviceProvider,
) -> Result<Self, IdeviceError> {
let mut lockdown = LockdownClient::connect(provider).await?;
lockdown
.start_session(&provider.get_pairing_file().await?)
.await?;
let (port, ssl) = lockdown.start_service(Self::service_name()).await?;
let mut idevice = provider.connect(port).await?;
if ssl {
idevice
.start_session(&provider.get_pairing_file().await?)
.await?;
}
Ok(Self { idevice })
} }
} }