mirror of
https://github.com/jkcoxson/idevice.git
synced 2026-03-02 06:26:15 +01:00
208 lines
5.9 KiB
Rust
208 lines
5.9 KiB
Rust
// Jackson Coxson
|
|
|
|
use std::ffi::{CStr, c_char};
|
|
use std::ptr::null_mut;
|
|
|
|
use idevice::tcp::stream::AdapterStream;
|
|
|
|
use crate::core_device_proxy::AdapterHandle;
|
|
use crate::{IdeviceFfiError, RUNTIME, ReadWriteOpaque, ffi_err};
|
|
|
|
pub struct AdapterStreamHandle<'a>(pub AdapterStream<'a>);
|
|
|
|
/// Connects the adapter to a specific port
|
|
///
|
|
/// # Arguments
|
|
/// * [`adapter_handle`] - The adapter handle
|
|
/// * [`port`] - The port to connect to
|
|
/// * [`stream_handle`] - A pointer to allocate the new stream to
|
|
///
|
|
/// # Returns
|
|
/// Null on success, an IdeviceFfiError otherwise
|
|
///
|
|
/// # Safety
|
|
/// `handle` must be a valid pointer to a handle allocated by this library.
|
|
/// Any stream allocated must be used in the same thread as the adapter. The handles are NOT thread
|
|
/// safe.
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn adapter_connect(
|
|
adapter_handle: *mut AdapterHandle,
|
|
port: u16,
|
|
stream_handle: *mut *mut ReadWriteOpaque,
|
|
) -> *mut IdeviceFfiError {
|
|
if adapter_handle.is_null() || stream_handle.is_null() {
|
|
return ffi_err!(IdeviceError::FfiInvalidArg);
|
|
}
|
|
|
|
let adapter = unsafe { &mut (*adapter_handle).0 };
|
|
let res = RUNTIME.block_on(async move { adapter.connect(port).await });
|
|
|
|
match res {
|
|
Ok(r) => {
|
|
let boxed = Box::new(ReadWriteOpaque {
|
|
inner: Some(Box::new(r)),
|
|
});
|
|
unsafe { *stream_handle = Box::into_raw(boxed) };
|
|
null_mut()
|
|
}
|
|
Err(e) => {
|
|
log::error!("Adapter connect failed: {e}");
|
|
ffi_err!(e)
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Enables PCAP logging for the adapter
|
|
///
|
|
/// # Arguments
|
|
/// * [`handle`] - The adapter handle
|
|
/// * [`path`] - The path to save the PCAP file (null-terminated string)
|
|
///
|
|
/// # Returns
|
|
/// Null on success, an IdeviceFfiError otherwise
|
|
///
|
|
/// # Safety
|
|
/// `handle` must be a valid pointer to a handle allocated by this library
|
|
/// `path` must be a valid null-terminated string
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn adapter_pcap(
|
|
handle: *mut AdapterHandle,
|
|
path: *const c_char,
|
|
) -> *mut IdeviceFfiError {
|
|
if handle.is_null() || path.is_null() {
|
|
return ffi_err!(IdeviceError::FfiInvalidArg);
|
|
}
|
|
|
|
let adapter = unsafe { &mut (*handle).0 };
|
|
let c_str = unsafe { CStr::from_ptr(path) };
|
|
let path_str = match c_str.to_str() {
|
|
Ok(s) => s,
|
|
Err(_) => return ffi_err!(IdeviceError::FfiInvalidString),
|
|
};
|
|
|
|
let res = RUNTIME.block_on(async move { adapter.pcap(path_str).await });
|
|
|
|
match res {
|
|
Ok(_) => null_mut(),
|
|
Err(e) => {
|
|
log::error!("Adapter pcap failed: {e}");
|
|
ffi_err!(e)
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Closes the adapter stream connection
|
|
///
|
|
/// # Arguments
|
|
/// * [`handle`] - The adapter stream handle
|
|
///
|
|
/// # Returns
|
|
/// Null on success, an IdeviceFfiError otherwise
|
|
///
|
|
/// # Safety
|
|
/// `handle` must be a valid pointer to a handle allocated by this library
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn adapter_close(handle: *mut AdapterStreamHandle) -> *mut IdeviceFfiError {
|
|
if handle.is_null() {
|
|
return ffi_err!(IdeviceError::FfiInvalidArg);
|
|
}
|
|
|
|
let adapter = unsafe { &mut (*handle).0 };
|
|
let res = RUNTIME.block_on(async move { adapter.close().await });
|
|
|
|
match res {
|
|
Ok(_) => null_mut(),
|
|
Err(e) => {
|
|
log::error!("Adapter close failed: {e}");
|
|
ffi_err!(e)
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Sends data through the adapter stream
|
|
///
|
|
/// # Arguments
|
|
/// * [`handle`] - The adapter stream handle
|
|
/// * [`data`] - The data to send
|
|
/// * [`length`] - The length of the data
|
|
///
|
|
/// # Returns
|
|
/// Null on success, an IdeviceFfiError otherwise
|
|
///
|
|
/// # Safety
|
|
/// `handle` must be a valid pointer to a handle allocated by this library
|
|
/// `data` must be a valid pointer to at least `length` bytes
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn adapter_send(
|
|
handle: *mut AdapterStreamHandle,
|
|
data: *const u8,
|
|
length: usize,
|
|
) -> *mut IdeviceFfiError {
|
|
if handle.is_null() || data.is_null() {
|
|
return ffi_err!(IdeviceError::FfiInvalidArg);
|
|
}
|
|
|
|
let adapter = unsafe { &mut (*handle).0 };
|
|
let data_slice = unsafe { std::slice::from_raw_parts(data, length) };
|
|
|
|
let res = RUNTIME.block_on(async move { adapter.psh(data_slice).await });
|
|
|
|
match res {
|
|
Ok(_) => null_mut(),
|
|
Err(e) => {
|
|
log::error!("Adapter send failed: {e}");
|
|
ffi_err!(e)
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Receives data from the adapter stream
|
|
///
|
|
/// # Arguments
|
|
/// * [`handle`] - The adapter stream handle
|
|
/// * [`data`] - Pointer to a buffer where the received data will be stored
|
|
/// * [`length`] - Pointer to store the actual length of received data
|
|
/// * [`max_length`] - Maximum number of bytes that can be stored in `data`
|
|
///
|
|
/// # Returns
|
|
/// Null on success, an IdeviceFfiError otherwise
|
|
///
|
|
/// # Safety
|
|
/// `handle` must be a valid pointer to a handle allocated by this library
|
|
/// `data` must be a valid pointer to at least `max_length` bytes
|
|
/// `length` must be a valid pointer to a usize
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn adapter_recv(
|
|
handle: *mut AdapterStreamHandle,
|
|
data: *mut u8,
|
|
length: *mut usize,
|
|
max_length: usize,
|
|
) -> *mut IdeviceFfiError {
|
|
if handle.is_null() || data.is_null() || length.is_null() {
|
|
return ffi_err!(IdeviceError::FfiInvalidArg);
|
|
}
|
|
|
|
let adapter = unsafe { &mut (*handle).0 };
|
|
let res = RUNTIME.block_on(async move { adapter.recv().await });
|
|
|
|
match res {
|
|
Ok(received_data) => {
|
|
let received_len = received_data.len();
|
|
if received_len > max_length {
|
|
return ffi_err!(IdeviceError::FfiBufferTooSmall(received_len, max_length));
|
|
}
|
|
|
|
unsafe {
|
|
std::ptr::copy_nonoverlapping(received_data.as_ptr(), data, received_len);
|
|
*length = received_len;
|
|
}
|
|
|
|
null_mut()
|
|
}
|
|
Err(e) => {
|
|
log::error!("Adapter recv failed: {e}");
|
|
ffi_err!(e)
|
|
}
|
|
}
|
|
}
|