mirror of
https://github.com/jkcoxson/idevice.git
synced 2026-03-02 06:26:15 +01:00
add diag relay c++ bindings, screenshotr ffi (#58)
This commit is contained in:
@@ -50,6 +50,7 @@ tss = ["idevice/tss"]
|
||||
tunneld = ["idevice/tunneld"]
|
||||
usbmuxd = ["idevice/usbmuxd"]
|
||||
xpc = ["idevice/xpc"]
|
||||
screenshotr = ["idevice/screenshotr"]
|
||||
full = [
|
||||
"afc",
|
||||
"amfi",
|
||||
@@ -75,6 +76,7 @@ full = [
|
||||
"tunneld",
|
||||
"springboardservices",
|
||||
"syslog_relay",
|
||||
"screenshotr",
|
||||
]
|
||||
default = ["full", "aws-lc"]
|
||||
|
||||
|
||||
@@ -620,10 +620,10 @@ pub unsafe extern "C" fn afc_file_read(
|
||||
|
||||
let fd = unsafe { &mut *(handle as *mut FileDescriptor) };
|
||||
let res: Result<Vec<u8>, IdeviceError> = run_sync({
|
||||
let mut buf = Vec::with_capacity(len);
|
||||
let mut buf = vec![0u8; len];
|
||||
async move {
|
||||
let r = fd.read(&mut buf).await?;
|
||||
buf.resize(r, 0);
|
||||
buf.truncate(r);
|
||||
Ok(buf)
|
||||
}
|
||||
});
|
||||
|
||||
@@ -190,7 +190,7 @@ pub unsafe extern "C" fn diagnostics_relay_client_mobilegestalt(
|
||||
return ffi_err!(IdeviceError::FfiInvalidArg);
|
||||
}
|
||||
|
||||
let keys = if keys.is_null() {
|
||||
let keys = if !keys.is_null() {
|
||||
let keys = unsafe { std::slice::from_raw_parts(keys, keys_len) };
|
||||
Some(
|
||||
keys.iter()
|
||||
|
||||
@@ -35,6 +35,8 @@ mod pairing_file;
|
||||
pub mod provider;
|
||||
#[cfg(feature = "xpc")]
|
||||
pub mod rsd;
|
||||
#[cfg(feature = "screenshotr")]
|
||||
pub mod screenshotr;
|
||||
#[cfg(feature = "springboardservices")]
|
||||
pub mod springboardservices;
|
||||
#[cfg(feature = "syslog_relay")]
|
||||
|
||||
@@ -250,6 +250,60 @@ pub unsafe extern "C" fn lockdownd_enter_recovery(
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets a value in lockdownd
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `client` - A valid LockdowndClient handle
|
||||
/// * `key` - The key to set (null-terminated string)
|
||||
/// * `value` - The value to set as a plist
|
||||
/// * `domain` - The domain to set in (null-terminated string, optional)
|
||||
///
|
||||
/// # Returns
|
||||
/// An IdeviceFfiError on error, null on success
|
||||
///
|
||||
/// # Safety
|
||||
/// `client` must be a valid pointer to a handle allocated by this library
|
||||
/// `key` must be a valid null-terminated string
|
||||
/// `value` must be a valid plist
|
||||
/// `domain` must be a valid null-terminated string or NULL
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn lockdownd_set_value(
|
||||
client: *mut LockdowndClientHandle,
|
||||
key: *const libc::c_char,
|
||||
value: plist_t,
|
||||
domain: *const libc::c_char,
|
||||
) -> *mut IdeviceFfiError {
|
||||
if client.is_null() || key.is_null() || value.is_null() {
|
||||
return ffi_err!(IdeviceError::FfiInvalidArg);
|
||||
}
|
||||
|
||||
let key = match unsafe { std::ffi::CStr::from_ptr(key) }.to_str() {
|
||||
Ok(k) => k,
|
||||
Err(_) => return ffi_err!(IdeviceError::InvalidCString),
|
||||
};
|
||||
|
||||
let domain = if domain.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(match unsafe { std::ffi::CStr::from_ptr(domain) }.to_str() {
|
||||
Ok(d) => d,
|
||||
Err(_) => return ffi_err!(IdeviceError::InvalidCString),
|
||||
})
|
||||
};
|
||||
|
||||
let value = unsafe { &mut *value }.borrow_self().clone();
|
||||
|
||||
let res: Result<(), IdeviceError> = run_sync_local(async move {
|
||||
let client_ref = unsafe { &mut (*client).0 };
|
||||
client_ref.set_value(key, value, domain).await
|
||||
});
|
||||
|
||||
match res {
|
||||
Ok(_) => null_mut(),
|
||||
Err(e) => ffi_err!(e),
|
||||
}
|
||||
}
|
||||
|
||||
/// Frees a LockdowndClient handle
|
||||
///
|
||||
/// # Arguments
|
||||
|
||||
132
ffi/src/screenshotr.rs
Normal file
132
ffi/src/screenshotr.rs
Normal file
@@ -0,0 +1,132 @@
|
||||
// Jackson Coxson
|
||||
|
||||
use std::ptr::null_mut;
|
||||
|
||||
use idevice::{
|
||||
IdeviceError, IdeviceService, provider::IdeviceProvider,
|
||||
services::screenshotr::ScreenshotService,
|
||||
};
|
||||
|
||||
use crate::{IdeviceFfiError, ffi_err, provider::IdeviceProviderHandle, run_sync_local};
|
||||
|
||||
pub struct ScreenshotrClientHandle(pub ScreenshotService);
|
||||
|
||||
/// Represents a screenshot data buffer
|
||||
#[repr(C)]
|
||||
pub struct ScreenshotData {
|
||||
pub data: *mut u8,
|
||||
pub length: usize,
|
||||
}
|
||||
|
||||
/// Connects to screenshotr service using provider
|
||||
///
|
||||
/// # Arguments
|
||||
/// * [`provider`] - An IdeviceProvider
|
||||
/// * [`client`] - On success, will be set to point to a newly allocated ScreenshotrClient handle
|
||||
///
|
||||
/// # Returns
|
||||
/// An IdeviceFfiError on error, null on success
|
||||
///
|
||||
/// # Safety
|
||||
/// `provider` must be a valid pointer to a handle allocated by this library
|
||||
/// `client` must be a valid, non-null pointer to a location where the handle will be stored
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn screenshotr_connect(
|
||||
provider: *mut IdeviceProviderHandle,
|
||||
client: *mut *mut ScreenshotrClientHandle,
|
||||
) -> *mut IdeviceFfiError {
|
||||
if provider.is_null() || client.is_null() {
|
||||
tracing::error!("Null pointer provided");
|
||||
return ffi_err!(IdeviceError::FfiInvalidArg);
|
||||
}
|
||||
|
||||
let res: Result<ScreenshotService, IdeviceError> = run_sync_local(async move {
|
||||
let provider_ref: &dyn IdeviceProvider = unsafe { &*(*provider).0 };
|
||||
ScreenshotService::connect(provider_ref).await
|
||||
});
|
||||
|
||||
match res {
|
||||
Ok(r) => {
|
||||
let boxed = Box::new(ScreenshotrClientHandle(r));
|
||||
unsafe { *client = Box::into_raw(boxed) };
|
||||
null_mut()
|
||||
}
|
||||
Err(e) => ffi_err!(e),
|
||||
}
|
||||
}
|
||||
|
||||
/// Takes a screenshot from the device
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `client` - A valid ScreenshotrClient handle
|
||||
/// * `screenshot` - Pointer to store the screenshot data
|
||||
///
|
||||
/// # Returns
|
||||
/// An IdeviceFfiError on error, null on success
|
||||
///
|
||||
/// # Safety
|
||||
/// `client` must be a valid pointer to a handle allocated by this library
|
||||
/// `screenshot` must be a valid pointer to store the screenshot data
|
||||
/// The caller is responsible for freeing the screenshot data using screenshotr_screenshot_free
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn screenshotr_take_screenshot(
|
||||
client: *mut ScreenshotrClientHandle,
|
||||
screenshot: *mut ScreenshotData,
|
||||
) -> *mut IdeviceFfiError {
|
||||
if client.is_null() || screenshot.is_null() {
|
||||
return ffi_err!(IdeviceError::FfiInvalidArg);
|
||||
}
|
||||
|
||||
let res: Result<Vec<u8>, IdeviceError> = run_sync_local(async move {
|
||||
let client_ref = unsafe { &mut (*client).0 };
|
||||
client_ref.take_screenshot().await
|
||||
});
|
||||
|
||||
match res {
|
||||
Ok(data) => {
|
||||
let len = data.len();
|
||||
let boxed = data.into_boxed_slice();
|
||||
let ptr = Box::into_raw(boxed) as *mut u8;
|
||||
|
||||
unsafe {
|
||||
(*screenshot).data = ptr;
|
||||
(*screenshot).length = len;
|
||||
}
|
||||
null_mut()
|
||||
}
|
||||
Err(e) => ffi_err!(e),
|
||||
}
|
||||
}
|
||||
|
||||
/// Frees screenshot data
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `screenshot` - The screenshot data to free
|
||||
///
|
||||
/// # Safety
|
||||
/// `screenshot` must be a valid ScreenshotData that was allocated by screenshotr_take_screenshot
|
||||
/// or NULL (in which case this function does nothing)
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn screenshotr_screenshot_free(screenshot: ScreenshotData) {
|
||||
if !screenshot.data.is_null() && screenshot.length > 0 {
|
||||
tracing::debug!("Freeing screenshot data");
|
||||
let _ =
|
||||
unsafe { Vec::from_raw_parts(screenshot.data, screenshot.length, screenshot.length) };
|
||||
}
|
||||
}
|
||||
|
||||
/// Frees a ScreenshotrClient handle
|
||||
///
|
||||
/// # Arguments
|
||||
/// * [`handle`] - The handle to free
|
||||
///
|
||||
/// # Safety
|
||||
/// `handle` must be a valid pointer to the handle that was allocated by this library,
|
||||
/// or NULL (in which case this function does nothing)
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn screenshotr_client_free(handle: *mut ScreenshotrClientHandle) {
|
||||
if !handle.is_null() {
|
||||
tracing::debug!("Freeing screenshotr_client");
|
||||
let _ = unsafe { Box::from_raw(handle) };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user