From 35ba07889b5b7a1df995429a1b0222f5ae374334 Mon Sep 17 00:00:00 2001 From: Jackson Coxson Date: Mon, 2 Jun 2025 19:42:17 -0600 Subject: [PATCH] Update FFI to use error struct for message --- ffi/examples/afc.c | 82 ++++++---- ffi/examples/connect.c | 15 +- ffi/examples/debug_proxy.c | 98 ++++++------ ffi/examples/enable_jit.c | 91 +++++++---- ffi/examples/heartbeat.c | 30 ++-- ffi/examples/ipa_installer.c | 44 ++++-- ffi/examples/list_apps.c | 25 +-- ffi/examples/location_simulation.c | 67 +++++--- ffi/examples/lockdownd.c | 62 +++++--- ffi/examples/mount_personalized.c | 52 ++++--- ffi/examples/mounter.c | 62 +++++--- ffi/examples/process_control.c | 67 +++++--- ffi/src/adapter.rs | 57 +++---- ffi/src/afc.rs | 162 ++++++++++---------- ffi/src/amfi.rs | 52 ++++--- ffi/src/core_device_proxy.rs | 89 +++++------ ffi/src/debug_proxy.rs | 108 ++++++------- ffi/src/errors.rs | 178 +++++----------------- ffi/src/heartbeat.rs | 45 +++--- ffi/src/installation_proxy.rs | 114 +++++++------- ffi/src/lib.rs | 61 ++++---- ffi/src/location_simulation.rs | 34 +++-- ffi/src/lockdown.rs | 61 ++++---- ffi/src/misagent.rs | 44 +++--- ffi/src/mobile_image_mounter.rs | 172 ++++++++++----------- ffi/src/os_trace_relay.rs | 45 +++--- ffi/src/pairing_file.rs | 39 ++--- ffi/src/process_control.rs | 49 +++--- ffi/src/provider.rs | 28 ++-- ffi/src/remote_server.rs | 26 ++-- ffi/src/rsd.rs | 72 ++++----- ffi/src/springboardservices.rs | 37 ++--- ffi/src/syslog_relay.rs | 22 +-- ffi/src/usbmuxd.rs | 53 ++++--- ffi/src/util.rs | 15 +- idevice/src/lib.rs | 235 +++++++++++++++++++++-------- 36 files changed, 1358 insertions(+), 1135 deletions(-) diff --git a/ffi/examples/afc.c b/ffi/examples/afc.c index 2039861..c2ac39e 100644 --- a/ffi/examples/afc.c +++ b/ffi/examples/afc.c @@ -161,10 +161,12 @@ int main(int argc, char **argv) { // Read pairing file IdevicePairingFile *pairing_file = NULL; - IdeviceErrorCode err = + IdeviceFfiError *err = idevice_pairing_file_read(pairing_file_path, &pairing_file); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to read pairing file: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to read pairing file: [%d] %s\n", err->code, + err->message); + idevice_error_free(err); return 1; } @@ -172,8 +174,10 @@ int main(int argc, char **argv) { IdeviceProviderHandle *provider = NULL; err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing_file, "ImageMounterTest", &provider); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to create TCP provider: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to create TCP provider: [%d] %s\n", err->code, + err->message); + idevice_error_free(err); idevice_pairing_file_free(pairing_file); return 1; } @@ -181,8 +185,10 @@ int main(int argc, char **argv) { // Connect to AFC service AfcClientHandle *client = NULL; err = afc_client_connect(provider, &client); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to connect to AFC service: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to connect to AFC service: [%d] %s\n", err->code, + err->message); + idevice_error_free(err); idevice_provider_free(provider); return 1; } @@ -190,6 +196,7 @@ int main(int argc, char **argv) { // Process command int success = 1; + if (strcmp(command, "list") == 0) { if (argc < 3) { printf("Error: Missing path argument\n"); @@ -200,14 +207,16 @@ int main(int argc, char **argv) { size_t count = 0; err = afc_list_directory(client, path, &entries, &count); - if (err == IdeviceSuccess) { + if (err == NULL) { printf("Contents of %s:\n", path); for (size_t i = 0; i < count; i++) { printf("- %s\n", entries[i]); } free_directory_listing(entries, count); } else { - fprintf(stderr, "Failed to list directory: %d\n", err); + fprintf(stderr, "Failed to list directory: [%d] %s\n", err->code, + err->message); + idevice_error_free(err); success = 0; } } @@ -218,10 +227,12 @@ int main(int argc, char **argv) { } else { char *path = argv[2]; err = afc_make_directory(client, path); - if (err == IdeviceSuccess) { + if (err == NULL) { printf("Directory created successfully\n"); } else { - fprintf(stderr, "Failed to create directory: %d\n", err); + fprintf(stderr, "Failed to create directory: [%d] %s\n", err->code, + err->message); + idevice_error_free(err); success = 0; } } @@ -235,14 +246,16 @@ int main(int argc, char **argv) { AfcFileHandle *file = NULL; err = afc_file_open(client, src_path, AfcRdOnly, &file); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to open file: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to open file: [%d] %s\n", err->code, + err->message); + idevice_error_free(err); success = 0; } else { uint8_t *data = NULL; size_t length = 0; err = afc_file_read(file, &data, &length); - if (err == IdeviceSuccess) { + if (err == NULL) { if (write_file(dest_path, data, length)) { printf("File downloaded successfully\n"); } else { @@ -250,7 +263,9 @@ int main(int argc, char **argv) { } free(data); } else { - fprintf(stderr, "Failed to read file: %d\n", err); + fprintf(stderr, "Failed to read file: [%d] %s\n", err->code, + err->message); + idevice_error_free(err); success = 0; } afc_file_close(file); @@ -271,15 +286,19 @@ int main(int argc, char **argv) { } else { AfcFileHandle *file = NULL; err = afc_file_open(client, dest_path, AfcWrOnly, &file); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to open file: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to open file: [%d] %s\n", err->code, + err->message); + idevice_error_free(err); success = 0; } else { err = afc_file_write(file, data, length); - if (err == IdeviceSuccess) { + if (err == NULL) { printf("File uploaded successfully\n"); } else { - fprintf(stderr, "Failed to write file: %d\n", err); + fprintf(stderr, "Failed to write file: [%d] %s\n", err->code, + err->message); + idevice_error_free(err); success = 0; } afc_file_close(file); @@ -294,10 +313,12 @@ int main(int argc, char **argv) { } else { char *path = argv[2]; err = afc_remove_path(client, path); - if (err == IdeviceSuccess) { + if (err == NULL) { printf("Path removed successfully\n"); } else { - fprintf(stderr, "Failed to remove path: %d\n", err); + fprintf(stderr, "Failed to remove path: [%d] %s\n", err->code, + err->message); + idevice_error_free(err); success = 0; } } @@ -308,10 +329,12 @@ int main(int argc, char **argv) { } else { char *path = argv[2]; err = afc_remove_path_and_contents(client, path); - if (err == IdeviceSuccess) { + if (err == NULL) { printf("Path and contents removed successfully\n"); } else { - fprintf(stderr, "Failed to remove path and contents: %d\n", err); + fprintf(stderr, "Failed to remove path and contents: [%d] %s\n", + err->code, err->message); + idevice_error_free(err); success = 0; } } @@ -323,22 +346,26 @@ int main(int argc, char **argv) { char *path = argv[2]; AfcFileInfo info = {0}; err = afc_get_file_info(client, path, &info); - if (err == IdeviceSuccess) { + if (err == NULL) { print_file_info(&info); afc_file_info_free(&info); } else { - fprintf(stderr, "Failed to get file info: %d\n", err); + fprintf(stderr, "Failed to get file info: [%d] %s\n", err->code, + err->message); + idevice_error_free(err); success = 0; } } } else if (strcmp(command, "device_info") == 0) { AfcDeviceInfo info = {0}; err = afc_get_device_info(client, &info); - if (err == IdeviceSuccess) { + if (err == NULL) { print_device_info(&info); afc_device_info_free(&info); } else { - fprintf(stderr, "Failed to get device info: %d\n", err); + fprintf(stderr, "Failed to get device info: [%d] %s\n", err->code, + err->message); + idevice_error_free(err); success = 0; } } else { @@ -349,6 +376,5 @@ int main(int argc, char **argv) { // Cleanup afc_client_free(client); - return success ? 0 : 1; } diff --git a/ffi/examples/connect.c b/ffi/examples/connect.c index 8574e78..f36fc49 100644 --- a/ffi/examples/connect.c +++ b/ffi/examples/connect.c @@ -18,11 +18,13 @@ int main() { IdeviceHandle *idevice = NULL; // Call the Rust function to connect - IdeviceErrorCode err = idevice_new_tcp_socket( + IdeviceFfiError *err = idevice_new_tcp_socket( (struct sockaddr *)&addr, sizeof(addr), "TestDevice", &idevice); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to connect to device: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to connect to device: [%d] %s\n", err->code, + err->message); + idevice_error_free(err); return 1; } @@ -32,8 +34,11 @@ int main() { char *device_type = NULL; err = idevice_get_type(idevice, &device_type); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to get device type: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to get device type: [%d] %s\n", err->code, + err->message); + idevice_error_free(err); + idevice_free(idevice); return 1; } diff --git a/ffi/examples/debug_proxy.c b/ffi/examples/debug_proxy.c index 09d8db0..5d88b3d 100644 --- a/ffi/examples/debug_proxy.c +++ b/ffi/examples/debug_proxy.c @@ -27,12 +27,8 @@ int main(int argc, char **argv) { const char *device_ip = argv[1]; const char *pairing_file = argc > 2 ? argv[2] : "pairing.plist"; - /***************************************************************** - * CoreDeviceProxy Setup - *****************************************************************/ printf("=== Setting up CoreDeviceProxy ===\n"); - // Create socket address struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; @@ -42,99 +38,98 @@ int main(int argc, char **argv) { return 1; } - // Read pairing file + IdeviceFfiError *err = NULL; + IdevicePairingFile *pairing = NULL; - IdeviceErrorCode err = idevice_pairing_file_read(pairing_file, &pairing); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to read pairing file: %d\n", err); + err = idevice_pairing_file_read(pairing_file, &pairing); + if (err != NULL) { + fprintf(stderr, "Failed to read pairing file: [%d] %s\n", err->code, + err->message); + idevice_error_free(err); return 1; } - // Create TCP provider IdeviceProviderHandle *tcp_provider = NULL; err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing, "DebugProxyShell", &tcp_provider); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to create TCP provider: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to create TCP provider: [%d] %s\n", err->code, + err->message); + idevice_error_free(err); idevice_pairing_file_free(pairing); return 1; } - // Connect to CoreDeviceProxy CoreDeviceProxyHandle *core_device = NULL; err = core_device_proxy_connect(tcp_provider, &core_device); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to connect to CoreDeviceProxy: %d\n", err); - idevice_provider_free(tcp_provider); + idevice_provider_free(tcp_provider); + if (err != NULL) { + fprintf(stderr, "Failed to connect to CoreDeviceProxy: [%d] %s\n", + err->code, err->message); + idevice_error_free(err); return 1; } - idevice_provider_free(tcp_provider); - // Get server RSD port uint16_t rsd_port; err = core_device_proxy_get_server_rsd_port(core_device, &rsd_port); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to get server RSD port: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to get server RSD port: [%d] %s\n", err->code, + err->message); + idevice_error_free(err); core_device_proxy_free(core_device); return 1; } printf("Server RSD Port: %d\n", rsd_port); - /***************************************************************** - * Create TCP Tunnel Adapter - *****************************************************************/ printf("\n=== Creating TCP Tunnel Adapter ===\n"); AdapterHandle *adapter = NULL; err = core_device_proxy_create_tcp_adapter(core_device, &adapter); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to create TCP adapter: %d\n", err); - core_device_proxy_free(core_device); + core_device_proxy_free(core_device); + if (err != NULL) { + fprintf(stderr, "Failed to create TCP adapter: [%d] %s\n", err->code, + err->message); + idevice_error_free(err); return 1; } - // Connect to RSD port AdapterStreamHandle *stream = NULL; err = adapter_connect(adapter, rsd_port, &stream); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to connect to RSD port: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to connect to RSD port: [%d] %s\n", err->code, + err->message); + idevice_error_free(err); adapter_free(adapter); return 1; } printf("Successfully connected to RSD port\n"); - /***************************************************************** - * RSD Handshake - *****************************************************************/ printf("\n=== Performing RSD Handshake ===\n"); RsdHandshakeHandle *handshake = NULL; err = rsd_handshake_new(stream, &handshake); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to perform RSD handshake: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to perform RSD handshake: [%d] %s\n", err->code, + err->message); + idevice_error_free(err); adapter_close(stream); adapter_free(adapter); return 1; } - /***************************************************************** - * Debug Proxy Setup - *****************************************************************/ printf("\n=== Setting up Debug Proxy ===\n"); - // Create DebugProxyClient DebugProxyHandle *debug_proxy = NULL; err = debug_proxy_connect_rsd(adapter, handshake, &debug_proxy); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to create debug proxy client: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to create debug proxy client: [%d] %s\n", err->code, + err->message); + idevice_error_free(err); rsd_handshake_free(handshake); adapter_free(adapter); return 1; } - /***************************************************************** - * Interactive Shell - *****************************************************************/ printf("\n=== Starting Interactive Debug Shell ===\n"); printf("Type GDB debugserver commands or 'quit' to exit\n\n"); @@ -149,7 +144,6 @@ int main(int argc, char **argv) { break; } - // Remove newline command[strcspn(command, "\n")] = '\0'; if (strcmp(command, "quit") == 0) { @@ -157,14 +151,11 @@ int main(int argc, char **argv) { continue; } - // Split command into name and arguments char *name = strtok(command, " "); char *args = strtok(NULL, ""); - // Create command DebugserverCommandHandle *cmd = NULL; if (args != NULL && args[0] != '\0') { - // Split arguments char *argv[16] = {0}; int argc = 0; char *token = strtok(args, " "); @@ -183,13 +174,13 @@ int main(int argc, char **argv) { continue; } - // Send command char *response = NULL; err = debug_proxy_send_command(debug_proxy, cmd, &response); debugserver_command_free(cmd); - if (err != IdeviceSuccess) { - fprintf(stderr, "Command failed with error: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Command failed: [%d] %s\n", err->code, err->message); + idevice_error_free(err); continue; } @@ -200,10 +191,12 @@ int main(int argc, char **argv) { printf("(no response)\n"); } - // Read any additional responses while (true) { err = debug_proxy_read_response(debug_proxy, &response); - if (err != IdeviceSuccess || response == NULL) { + if (err != NULL || response == NULL) { + if (err != NULL) { + idevice_error_free(err); + } break; } printf("%s\n", response); @@ -211,9 +204,6 @@ int main(int argc, char **argv) { } } - /***************************************************************** - * Cleanup - *****************************************************************/ debug_proxy_free(debug_proxy); rsd_handshake_free(handshake); adapter_free(adapter); diff --git a/ffi/examples/enable_jit.c b/ffi/examples/enable_jit.c index b4f1148..a4ed863 100644 --- a/ffi/examples/enable_jit.c +++ b/ffi/examples/enable_jit.c @@ -43,9 +43,10 @@ int main(int argc, char **argv) { // Read pairing file struct IdevicePairingFile *pairing = NULL; - enum IdeviceErrorCode err = idevice_pairing_file_read(pairing_file, &pairing); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to read pairing file: %d\n", err); + IdeviceFfiError *err = idevice_pairing_file_read(pairing_file, &pairing); + if (err != NULL) { + fprintf(stderr, "Failed to read pairing file: [%d] %s\n", err->code, + err->message); return 1; } @@ -53,8 +54,9 @@ int main(int argc, char **argv) { struct IdeviceProviderHandle *provider = NULL; err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing, "ProcessDebugTest", &provider); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to create TCP provider: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to create TCP provider: [%d] %s\n", err->code, + err->message); idevice_pairing_file_free(pairing); return 1; } @@ -62,8 +64,9 @@ int main(int argc, char **argv) { // Connect to CoreDeviceProxy struct CoreDeviceProxyHandle *core_device = NULL; err = core_device_proxy_connect(provider, &core_device); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to connect to CoreDeviceProxy: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to connect to CoreDeviceProxy: [%d] %s", err->code, + err->message); idevice_provider_free(provider); return 1; } @@ -72,8 +75,9 @@ int main(int argc, char **argv) { // Get server RSD port uint16_t rsd_port; err = core_device_proxy_get_server_rsd_port(core_device, &rsd_port); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to get server RSD port: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to get server RSD port: [%d] %s", err->code, + err->message); core_device_proxy_free(core_device); return 1; } @@ -86,8 +90,9 @@ int main(int argc, char **argv) { struct AdapterHandle *adapter = NULL; err = core_device_proxy_create_tcp_adapter(core_device, &adapter); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to create TCP adapter: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to create TCP adapter: [%d] %s", err->code, + err->message); core_device_proxy_free(core_device); return 1; } @@ -95,8 +100,9 @@ int main(int argc, char **argv) { // Connect to RSD port struct ReadWriteOpaque *rsd_stream = NULL; err = adapter_connect(adapter, rsd_port, &rsd_stream); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to connect to RSD port: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to connect to RSD port: [%d] %s", err->code, + err->message); adapter_free(adapter); return 1; } @@ -111,8 +117,9 @@ int main(int argc, char **argv) { struct RsdHandshakeHandle *rsd_handshake = NULL; err = rsd_handshake_new(rsd_stream, &rsd_handshake); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to create RSD handshake: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to create RSD handshake: [%d] %s", err->code, + err->message); adapter_free(adapter); return 1; } @@ -120,8 +127,9 @@ int main(int argc, char **argv) { // Get services struct CRsdServiceArray *services = NULL; err = rsd_get_services(rsd_handshake, &services); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to get RSD services: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to get RSD services: [%d] %s", err->code, + err->message); rsd_handshake_free(rsd_handshake); adapter_free(adapter); return 1; @@ -157,8 +165,10 @@ int main(int argc, char **argv) { // Connect to process control port struct ReadWriteOpaque *pc_stream = NULL; err = adapter_connect(adapter, pc_port, &pc_stream); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to connect to process control port: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to connect to process control port: [%d] %s", + err->code, err->message); + idevice_error_free(err); adapter_free(adapter); return 1; } @@ -167,8 +177,10 @@ int main(int argc, char **argv) { // Create RemoteServerClient struct RemoteServerHandle *remote_server = NULL; err = remote_server_new(pc_stream, &remote_server); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to create remote server: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to create remote server: [%d] %s", err->code, + err->message); + idevice_error_free(err); adapter_free(adapter); return 1; } @@ -176,8 +188,10 @@ int main(int argc, char **argv) { // Create ProcessControlClient struct ProcessControlHandle *process_control = NULL; err = process_control_new(remote_server, &process_control); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to create process control client: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to create process control client: [%d] %s", + err->code, err->message); + idevice_error_free(err); remote_server_free(remote_server); return 1; } @@ -186,10 +200,11 @@ int main(int argc, char **argv) { uint64_t pid; err = process_control_launch_app(process_control, bundle_id, NULL, 0, NULL, 0, true, false, &pid); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to launch app: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to launch app: [%d] %s", err->code, err->message); process_control_free(process_control); remote_server_free(remote_server); + idevice_error_free(err); return 1; } printf("Successfully launched app with PID: %" PRIu64 "\n", pid); @@ -202,10 +217,12 @@ int main(int argc, char **argv) { // Connect to debug proxy port struct ReadWriteOpaque *debug_stream = NULL; err = adapter_connect(adapter, debug_port, &debug_stream); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to connect to debug proxy port: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to connect to debug proxy port: [%d] %s", err->code, + err->message); process_control_free(process_control); remote_server_free(remote_server); + idevice_error_free(err); return 1; } printf("Successfully connected to debug proxy port\n"); @@ -213,10 +230,12 @@ int main(int argc, char **argv) { // Create DebugProxyClient struct DebugProxyHandle *debug_proxy = NULL; err = debug_proxy_connect_rsd(adapter, rsd_handshake, &debug_proxy); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to create debug proxy client: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to create debug proxy client: [%d] %s", err->code, + err->message); process_control_free(process_control); remote_server_free(remote_server); + idevice_error_free(err); return 1; } @@ -231,6 +250,7 @@ int main(int argc, char **argv) { debug_proxy_free(debug_proxy); process_control_free(process_control); remote_server_free(remote_server); + idevice_error_free(err); return 1; } @@ -238,8 +258,10 @@ int main(int argc, char **argv) { err = debug_proxy_send_command(debug_proxy, attach_cmd, &attach_response); debugserver_command_free(attach_cmd); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to attach to process: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to attach to process: [%d] %s", err->code, + err->message); + idevice_error_free(err); } else if (attach_response != NULL) { printf("Attach response: %s\n", attach_response); idevice_string_free(attach_response); @@ -250,6 +272,7 @@ int main(int argc, char **argv) { debugserver_command_new("D", NULL, 0); if (detach_cmd == NULL) { fprintf(stderr, "Failed to create detach command\n"); + idevice_error_free(err); } else { char *detach_response = NULL; err = debug_proxy_send_command(debug_proxy, detach_cmd, &detach_response); @@ -257,8 +280,10 @@ int main(int argc, char **argv) { err = debug_proxy_send_command(debug_proxy, detach_cmd, &detach_response); debugserver_command_free(detach_cmd); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to detach from process: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to detach from process: [%d] %s", err->code, + err->message); + idevice_error_free(err); } else if (detach_response != NULL) { printf("Detach response: %s\n", detach_response); idevice_string_free(detach_response); diff --git a/ffi/examples/heartbeat.c b/ffi/examples/heartbeat.c index e277494..bda431b 100644 --- a/ffi/examples/heartbeat.c +++ b/ffi/examples/heartbeat.c @@ -20,10 +20,12 @@ int main() { // Read pairing file (replace with your pairing file path) IdevicePairingFile *pairing_file = NULL; - IdeviceErrorCode err = + IdeviceFfiError *err = idevice_pairing_file_read("pairing_file.plist", &pairing_file); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to read pairing file: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to read pairing file: [%d] %s", err->code, + err->message); + idevice_error_free(err); return 1; } @@ -31,18 +33,22 @@ int main() { IdeviceProviderHandle *provider = NULL; err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing_file, "ExampleProvider", &provider); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to create TCP provider: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to create TCP provider: [%d] %s", err->code, + err->message); idevice_pairing_file_free(pairing_file); + idevice_error_free(err); return 1; } // Connect to installation proxy HeartbeatClientHandle *client = NULL; err = heartbeat_connect(provider, &client); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to connect to installation proxy: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to connect to installation proxy: [%d] %s", + err->code, err->message); idevice_provider_free(provider); + idevice_error_free(err); return 1; } idevice_provider_free(provider); @@ -52,18 +58,20 @@ int main() { // Get the new interval u_int64_t new_interval = 0; err = heartbeat_get_marco(client, current_interval, &new_interval); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to get marco: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to get marco: [%d] %s", err->code, err->message); heartbeat_client_free(client); + idevice_error_free(err); return 1; } current_interval = new_interval + 5; // Reply err = heartbeat_send_polo(client); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to get marco: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to get marco: [%d] %s", err->code, err->message); heartbeat_client_free(client); + idevice_error_free(err); return 1; } } diff --git a/ffi/examples/ipa_installer.c b/ffi/examples/ipa_installer.c index 2d838ca..a7fa361 100644 --- a/ffi/examples/ipa_installer.c +++ b/ffi/examples/ipa_installer.c @@ -100,10 +100,12 @@ int main(int argc, char **argv) { // Read pairing file IdevicePairingFile *pairing_file = NULL; - IdeviceErrorCode err = + IdeviceFfiError *err = idevice_pairing_file_read(pairing_file_path, &pairing_file); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to read pairing file: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to read pairing file: [%d] %s", err->code, + err->message); + idevice_error_free(err); return 1; } @@ -111,18 +113,22 @@ int main(int argc, char **argv) { IdeviceProviderHandle *provider = NULL; err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing_file, "IPAInstaller", &provider); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to create TCP provider: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to create TCP provider: [%d] %s", err->code, + err->message); idevice_pairing_file_free(pairing_file); + idevice_error_free(err); return 1; } // Connect to AFC service AfcClientHandle *afc_client = NULL; err = afc_client_connect(provider, &afc_client); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to connect to AFC service: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to connect to AFC service: [%d] %s", err->code, + err->message); idevice_provider_free(provider); + idevice_error_free(err); return 1; } @@ -150,10 +156,12 @@ int main(int argc, char **argv) { AfcFileHandle *file = NULL; err = afc_file_open(afc_client, dest_path, AfcWrOnly, &file); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to open destination file: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to open destination file: [%d] %s", err->code, + err->message); free(data); afc_client_free(afc_client); + idevice_error_free(err); return 1; } @@ -161,9 +169,10 @@ int main(int argc, char **argv) { free(data); afc_file_close(file); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to write file: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to write file: [%d] %s", err->code, err->message); afc_client_free(afc_client); + idevice_error_free(err); return 1; } printf("Upload completed successfully\n"); @@ -171,17 +180,20 @@ int main(int argc, char **argv) { // Connect to installation proxy InstallationProxyClientHandle *instproxy_client = NULL; err = installation_proxy_connect_tcp(provider, &instproxy_client); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to connect to installation proxy: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to connect to installation proxy: [%d] %s", + err->code, err->message); afc_client_free(afc_client); + idevice_error_free(err); return 1; } // Install the uploaded IPA printf("Installing %s...\n", dest_path); err = installation_proxy_install(instproxy_client, dest_path, NULL); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to install IPA: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to install IPA: [%d] %s", err->code, err->message); + idevice_error_free(err); } else { printf("Installation completed successfully\n"); } @@ -191,5 +203,5 @@ int main(int argc, char **argv) { afc_client_free(afc_client); idevice_provider_free(provider); - return err == IdeviceSuccess ? 0 : 1; + return err == NULL ? 0 : 1; } diff --git a/ffi/examples/list_apps.c b/ffi/examples/list_apps.c index 4c9cb9a..66f442b 100644 --- a/ffi/examples/list_apps.c +++ b/ffi/examples/list_apps.c @@ -19,10 +19,12 @@ int main() { // Read pairing file (replace with your pairing file path) IdevicePairingFile *pairing_file = NULL; - IdeviceErrorCode err = + IdeviceFfiError *err = idevice_pairing_file_read("pairing_file.plist", &pairing_file); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to read pairing file: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to read pairing file: [%d] %s", err->code, + err->message); + idevice_error_free(err); return 1; } @@ -30,18 +32,22 @@ int main() { IdeviceProviderHandle *provider = NULL; err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing_file, "ExampleProvider", &provider); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to create TCP provider: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to create TCP provider: [%d] %s", err->code, + err->message); idevice_pairing_file_free(pairing_file); + idevice_error_free(err); return 1; } // Connect to installation proxy InstallationProxyClientHandle *client = NULL; err = installation_proxy_connect_tcp(provider, &client); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to connect to installation proxy: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to connect to installation proxy: [%d] %s", + err->code, err->message); idevice_provider_free(provider); + idevice_error_free(err); return 1; } @@ -53,9 +59,10 @@ int main() { NULL, // bundle_identifiers filter 0, // bundle_identifiers length &apps, &apps_len); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to get apps: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to get apps: [%d] %s", err->code, err->message); installation_proxy_client_free(client); + idevice_error_free(err); idevice_provider_free(provider); return 1; } diff --git a/ffi/examples/location_simulation.c b/ffi/examples/location_simulation.c index bac25a3..e281cc0 100644 --- a/ffi/examples/location_simulation.c +++ b/ffi/examples/location_simulation.c @@ -33,9 +33,11 @@ int main(int argc, char **argv) { // Read pairing file IdevicePairingFile *pairing = NULL; - IdeviceErrorCode err = idevice_pairing_file_read(pairing_file, &pairing); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to read pairing file: %d\n", err); + IdeviceFfiError *err = idevice_pairing_file_read(pairing_file, &pairing); + if (err != NULL) { + fprintf(stderr, "Failed to read pairing file: [%d] %s", err->code, + err->message); + idevice_error_free(err); return 1; } @@ -43,8 +45,10 @@ int main(int argc, char **argv) { IdeviceProviderHandle *tcp_provider = NULL; err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing, "LocationSimCLI", &tcp_provider); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to create TCP provider: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to create TCP provider: [%d] %s", err->code, + err->message); + idevice_error_free(err); idevice_pairing_file_free(pairing); return 1; } @@ -54,16 +58,20 @@ int main(int argc, char **argv) { err = core_device_proxy_connect(tcp_provider, &core_device); idevice_provider_free(tcp_provider); idevice_pairing_file_free(pairing); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to connect to CoreDeviceProxy: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to connect to CoreDeviceProxy: [%d] %s", err->code, + err->message); + idevice_error_free(err); return 1; } // Get server RSD port uint16_t rsd_port; err = core_device_proxy_get_server_rsd_port(core_device, &rsd_port); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to get server RSD port: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to get server RSD port: [%d] %s", err->code, + err->message); + idevice_error_free(err); core_device_proxy_free(core_device); return 1; } @@ -72,24 +80,30 @@ int main(int argc, char **argv) { AdapterHandle *adapter = NULL; err = core_device_proxy_create_tcp_adapter(core_device, &adapter); core_device_proxy_free(core_device); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to create TCP adapter: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to create TCP adapter: [%d] %s", err->code, + err->message); + idevice_error_free(err); return 1; } // Connect to RSD port AdapterStreamHandle *stream = NULL; err = adapter_connect(adapter, rsd_port, &stream); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to connect to RSD port: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to connect to RSD port: [%d] %s", err->code, + err->message); + idevice_error_free(err); adapter_free(adapter); return 1; } RsdHandshakeHandle *handshake = NULL; err = rsd_handshake_new(stream, &handshake); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to perform RSD handshake: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to perform RSD handshake: [%d] %s", err->code, + err->message); + idevice_error_free(err); adapter_close(stream); adapter_free(adapter); return 1; @@ -98,8 +112,10 @@ int main(int argc, char **argv) { // Create RemoteServerClient RemoteServerHandle *remote_server = NULL; err = remote_server_connect_rsd(adapter, handshake, &remote_server); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to create remote server: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to create remote server: [%d] %s", err->code, + err->message); + idevice_error_free(err); adapter_free(adapter); rsd_handshake_free(handshake); return 1; @@ -108,16 +124,19 @@ int main(int argc, char **argv) { // Create LocationSimulationClient LocationSimulationHandle *location_sim = NULL; err = location_simulation_new(remote_server, &location_sim); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to create location simulation client: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to create location simulation client: [%d] %s", + err->code, err->message); + idevice_error_free(err); remote_server_free(remote_server); return 1; } // Set location err = location_simulation_set(location_sim, latitude, longitude); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to set location: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to set location: [%d] %s", err->code, err->message); + idevice_error_free(err); } else { printf("Successfully set location to %.6f, %.6f\n", latitude, longitude); } @@ -127,8 +146,10 @@ int main(int argc, char **argv) { // Clear location err = location_simulation_clear(location_sim); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to clear location: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to clear location: [%d] %s", err->code, + err->message); + idevice_error_free(err); } else { printf("Successfully cleared simulated location\n"); } diff --git a/ffi/examples/lockdownd.c b/ffi/examples/lockdownd.c index 7dd9520..8c2d678 100644 --- a/ffi/examples/lockdownd.c +++ b/ffi/examples/lockdownd.c @@ -21,10 +21,12 @@ int main() { // Read pairing file (replace with your pairing file path) IdevicePairingFile *pairing_file = NULL; - IdeviceErrorCode err = + IdeviceFfiError *err = idevice_pairing_file_read("pairing_file.plist", &pairing_file); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to read pairing file: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to read pairing file: [%d] %s", err->code, + err->message); + idevice_error_free(err); return 1; } @@ -32,8 +34,10 @@ int main() { IdeviceProviderHandle *provider = NULL; err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing_file, "LockdowndTest", &provider); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to create TCP provider: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to create TCP provider: [%d] %s", err->code, + err->message); + idevice_error_free(err); idevice_pairing_file_free(pairing_file); return 1; } @@ -41,8 +45,10 @@ int main() { // Connect to lockdownd LockdowndClientHandle *client = NULL; err = lockdownd_connect(provider, &client); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to connect to lockdownd: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to connect to lockdownd: [%d] %s", err->code, + err->message); + idevice_error_free(err); idevice_provider_free(provider); return 1; } @@ -50,15 +56,19 @@ int main() { // Read pairing file (replace with your pairing file path) IdevicePairingFile *pairing_file_2 = NULL; err = idevice_pairing_file_read("pairing_file.plist", &pairing_file_2); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to read pairing file: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to read pairing file: [%d] %s", err->code, + err->message); + idevice_error_free(err); return 1; } // Start session err = lockdownd_start_session(client, pairing_file_2); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to start session: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to start session: [%d] %s", err->code, + err->message); + idevice_error_free(err); lockdownd_client_free(client); idevice_provider_free(provider); return 1; @@ -67,8 +77,10 @@ int main() { // Get device name plist_t name_plist = NULL; err = lockdownd_get_value(client, "DeviceName", NULL, &name_plist); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to get device name: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to get device name: [%d] %s", err->code, + err->message); + idevice_error_free(err); } else { char *name = NULL; plist_get_string_val(name_plist, &name); @@ -80,8 +92,10 @@ int main() { // Get product version plist_t version_plist = NULL; err = lockdownd_get_value(client, "ProductVersion", NULL, &version_plist); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to get product version: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to get product version: [%d] %s", err->code, + err->message); + idevice_error_free(err); } else { char *version = NULL; plist_get_string_val(version_plist, &version); @@ -95,8 +109,10 @@ int main() { err = lockdownd_get_value(client, "DeveloperModeStatus", "com.apple.security.mac.amfi", &developer_mode_plist); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to get product version: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to get product version: [%d] %s", err->code, + err->message); + idevice_error_free(err); } else { uint8_t enabled = 0; plist_get_bool_val(developer_mode_plist, &enabled); @@ -107,8 +123,10 @@ int main() { // Get all values plist_t all_values = NULL; err = lockdownd_get_all_values(client, &all_values); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to get all values: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to get all values: [%d] %s", err->code, + err->message); + idevice_error_free(err); } else { printf("\nAll device values:\n"); // Iterate through dictionary (simplified example) @@ -150,8 +168,10 @@ int main() { bool ssl = false; err = lockdownd_start_service(client, "com.apple.mobile.heartbeat", &port, &ssl); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to start heartbeat service: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to start heartbeat service: [%d] %s", err->code, + err->message); + idevice_error_free(err); } else { printf("\nStarted heartbeat service on port %d (SSL: %s)\n", port, ssl ? "true" : "false"); diff --git a/ffi/examples/mount_personalized.c b/ffi/examples/mount_personalized.c index ed81190..c245018 100644 --- a/ffi/examples/mount_personalized.c +++ b/ffi/examples/mount_personalized.c @@ -88,10 +88,12 @@ int main(int argc, char **argv) { // Read pairing file IdevicePairingFile *pairing_file = NULL; - IdeviceErrorCode err = + IdeviceFfiError *err = idevice_pairing_file_read(pairing_file_path, &pairing_file); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to read pairing file: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to read pairing file: [%d] %s", err->code, + err->message); + idevice_error_free(err); free(image); free(trustcache); free(build_manifest); @@ -102,8 +104,10 @@ int main(int argc, char **argv) { IdeviceProviderHandle *provider = NULL; err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing_file, "ImageMounterTest", &provider); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to create TCP provider: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to create TCP provider: [%d] %s", err->code, + err->message); + idevice_error_free(err); idevice_pairing_file_free(pairing_file); free(image); free(trustcache); @@ -114,8 +118,10 @@ int main(int argc, char **argv) { // Read pairing file IdevicePairingFile *pairing_file_2 = NULL; err = idevice_pairing_file_read(pairing_file_path, &pairing_file_2); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to read pairing file: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to read pairing file: [%d] %s", err->code, + err->message); + idevice_error_free(err); free(image); free(trustcache); free(build_manifest); @@ -125,8 +131,10 @@ int main(int argc, char **argv) { // Connect to lockdownd LockdowndClientHandle *lockdown_client = NULL; err = lockdownd_connect(provider, &lockdown_client); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to connect to lockdownd: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to connect to lockdownd: [%d] %s", err->code, + err->message); + idevice_error_free(err); idevice_provider_free(provider); free(image); free(trustcache); @@ -136,8 +144,10 @@ int main(int argc, char **argv) { // Start session err = lockdownd_start_session(lockdown_client, pairing_file_2); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to start session: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to start session: [%d] %s", err->code, + err->message); + idevice_error_free(err); lockdownd_client_free(lockdown_client); idevice_provider_free(provider); idevice_pairing_file_free(pairing_file_2); @@ -152,8 +162,10 @@ int main(int argc, char **argv) { plist_t unique_chip_id_plist = NULL; err = lockdownd_get_value(lockdown_client, "UniqueChipID", NULL, &unique_chip_id_plist); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to get UniqueChipID: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to get UniqueChipID: [%d] %s", err->code, + err->message); + idevice_error_free(err); lockdownd_client_free(lockdown_client); idevice_provider_free(provider); free(image); @@ -169,8 +181,10 @@ int main(int argc, char **argv) { // Connect to image mounter ImageMounterHandle *mounter_client = NULL; err = image_mounter_connect(provider, &mounter_client); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to connect to image mounter: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to connect to image mounter: [%d] %s", err->code, + err->message); + idevice_error_free(err); lockdownd_client_free(lockdown_client); idevice_provider_free(provider); free(image); @@ -186,8 +200,10 @@ int main(int argc, char **argv) { NULL, // info_plist unique_chip_id, progress_callback, NULL); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to mount personalized image: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to mount personalized image: [%d] %s", err->code, + err->message); + idevice_error_free(err); } else { printf("Successfully mounted personalized image!\n"); } @@ -200,5 +216,5 @@ int main(int argc, char **argv) { free(trustcache); free(build_manifest); - return err == IdeviceSuccess ? 0 : 1; + return err == NULL ? 0 : 1; } diff --git a/ffi/examples/mounter.c b/ffi/examples/mounter.c index d8a4f23..17870e9 100644 --- a/ffi/examples/mounter.c +++ b/ffi/examples/mounter.c @@ -104,10 +104,12 @@ int main(int argc, char **argv) { // Read pairing file IdevicePairingFile *pairing_file = NULL; - IdeviceErrorCode err = + IdeviceFfiError *err = idevice_pairing_file_read(pairing_file_path, &pairing_file); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to read pairing file: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to read pairing file: [%d] %s", err->code, + err->message); + idevice_error_free(err); return 1; } @@ -115,8 +117,10 @@ int main(int argc, char **argv) { IdeviceProviderHandle *provider = NULL; err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing_file, "ImageMounterTest", &provider); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to create TCP provider: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to create TCP provider: [%d] %s", err->code, + err->message); + idevice_error_free(err); idevice_pairing_file_free(pairing_file); return 1; } @@ -124,8 +128,10 @@ int main(int argc, char **argv) { // Connect to image mounter ImageMounterHandle *client = NULL; err = image_mounter_connect(provider, &client); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to connect to image mounter: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to connect to image mounter: [%d] %s", err->code, + err->message); + idevice_error_free(err); idevice_provider_free(provider); return 1; } @@ -137,7 +143,7 @@ int main(int argc, char **argv) { void *devices = NULL; size_t devices_len = 0; err = image_mounter_copy_devices(client, &devices, &devices_len); - if (err == IdeviceSuccess) { + if (err == NULL) { plist_t *device_list = (plist_t *)devices; printf("Mounted devices:\n"); for (size_t i = 0; i < devices_len; i++) { @@ -150,7 +156,9 @@ int main(int argc, char **argv) { plist_free(device); } } else { - fprintf(stderr, "Failed to get device list: %d\n", err); + fprintf(stderr, "Failed to get device list: [%d] %s", err->code, + err->message); + idevice_error_free(err); success = 0; } } else if (strcmp(command, "lookup") == 0) { @@ -164,7 +172,7 @@ int main(int argc, char **argv) { err = image_mounter_lookup_image(client, image_type, &signature, &signature_len); - if (err == IdeviceSuccess) { + if (err == NULL) { printf("Signature for %s (%zu bytes):\n", image_type, signature_len); for (size_t i = 0; i < signature_len; i++) { printf("%02x", signature[i]); @@ -172,7 +180,9 @@ int main(int argc, char **argv) { printf("\n"); free(signature); } else { - fprintf(stderr, "Failed to lookup image: %d\n", err); + fprintf(stderr, "Failed to lookup image: [%d] %s", err->code, + err->message); + idevice_error_free(err); success = 0; } } @@ -199,10 +209,12 @@ int main(int argc, char **argv) { err = image_mounter_upload_image(client, image_type, image_data, image_len, signature_data, signature_len); - if (err == IdeviceSuccess) { + if (err == NULL) { printf("Image uploaded successfully\n"); } else { - fprintf(stderr, "Failed to upload image: %d\n", err); + fprintf(stderr, "Failed to upload image: [%d] %s", err->code, + err->message); + idevice_error_free(err); success = 0; } @@ -236,10 +248,12 @@ int main(int argc, char **argv) { client, image_type, signature_data, signature_len, trust_cache_data, trust_cache_len, NULL); // No info plist in this example - if (err == IdeviceSuccess) { + if (err == NULL) { printf("Image mounted successfully\n"); } else { - fprintf(stderr, "Failed to mount image: %d\n", err); + fprintf(stderr, "Failed to mount image: [%d] %s", err->code, + err->message); + idevice_error_free(err); success = 0; } @@ -256,20 +270,24 @@ int main(int argc, char **argv) { } else { char *mount_path = argv[2]; err = image_mounter_unmount_image(client, mount_path); - if (err == IdeviceSuccess) { + if (err == NULL) { printf("Image unmounted successfully\n"); } else { - fprintf(stderr, "Failed to unmount image: %d\n", err); + fprintf(stderr, "Failed to unmount image: [%d] %s", err->code, + err->message); + idevice_error_free(err); success = 0; } } } else if (strcmp(command, "dev-status") == 0) { int status = 0; err = image_mounter_query_developer_mode_status(client, &status); - if (err == IdeviceSuccess) { + if (err == NULL) { printf("Developer mode status: %s\n", status ? "enabled" : "disabled"); } else { - fprintf(stderr, "Failed to query developer mode status: %d\n", err); + fprintf(stderr, "Failed to query developer mode status: [%d] %s", + err->code, err->message); + idevice_error_free(err); success = 0; } } else if (strcmp(command, "mount-dev") == 0) { @@ -293,10 +311,12 @@ int main(int argc, char **argv) { } else { err = image_mounter_mount_developer(client, image_data, image_len, signature_data, signature_len); - if (err == IdeviceSuccess) { + if (err == NULL) { printf("Developer image mounted successfully\n"); } else { - fprintf(stderr, "Failed to mount developer image: %d\n", err); + fprintf(stderr, "Failed to mount developer image: [%d] %s", err->code, + err->message); + idevice_error_free(err); success = 0; } diff --git a/ffi/examples/process_control.c b/ffi/examples/process_control.c index 2450e19..ca502e2 100644 --- a/ffi/examples/process_control.c +++ b/ffi/examples/process_control.c @@ -31,9 +31,11 @@ int main(int argc, char **argv) { // Read pairing file IdevicePairingFile *pairing = NULL; - IdeviceErrorCode err = idevice_pairing_file_read(pairing_file, &pairing); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to read pairing file: %d\n", err); + IdeviceFfiError *err = idevice_pairing_file_read(pairing_file, &pairing); + if (err != NULL) { + fprintf(stderr, "Failed to read pairing file: [%d] %s", err->code, + err->message); + idevice_error_free(err); return 1; } @@ -46,8 +48,10 @@ int main(int argc, char **argv) { IdeviceProviderHandle *tcp_provider = NULL; err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing, "ProcessControlTest", &tcp_provider); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to create TCP provider: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to create TCP provider: [%d] %s", err->code, + err->message); + idevice_error_free(err); idevice_pairing_file_free(pairing); return 1; } @@ -55,8 +59,10 @@ int main(int argc, char **argv) { // Connect to CoreDeviceProxy CoreDeviceProxyHandle *core_device = NULL; err = core_device_proxy_connect(tcp_provider, &core_device); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to connect to CoreDeviceProxy: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to connect to CoreDeviceProxy: [%d] %s", err->code, + err->message); + idevice_error_free(err); idevice_provider_free(tcp_provider); idevice_pairing_file_free(pairing); return 1; @@ -66,8 +72,10 @@ int main(int argc, char **argv) { // Get server RSD port uint16_t rsd_port; err = core_device_proxy_get_server_rsd_port(core_device, &rsd_port); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to get server RSD port: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to get server RSD port: [%d] %s", err->code, + err->message); + idevice_error_free(err); core_device_proxy_free(core_device); idevice_pairing_file_free(pairing); return 1; @@ -81,8 +89,10 @@ int main(int argc, char **argv) { AdapterHandle *adapter = NULL; err = core_device_proxy_create_tcp_adapter(core_device, &adapter); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to create TCP adapter: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to create TCP adapter: [%d] %s", err->code, + err->message); + idevice_error_free(err); core_device_proxy_free(core_device); idevice_pairing_file_free(pairing); return 1; @@ -91,16 +101,20 @@ int main(int argc, char **argv) { // Connect to RSD port AdapterStreamHandle *stream = NULL; err = adapter_connect(adapter, rsd_port, &stream); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to connect to RSD port: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to connect to RSD port: [%d] %s", err->code, + err->message); + idevice_error_free(err); adapter_free(adapter); return 1; } RsdHandshakeHandle *handshake = NULL; err = rsd_handshake_new(stream, &handshake); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to perform RSD handshake: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to perform RSD handshake: [%d] %s", err->code, + err->message); + idevice_error_free(err); adapter_close(stream); adapter_free(adapter); return 1; @@ -109,8 +123,10 @@ int main(int argc, char **argv) { // Create RemoteServerClient RemoteServerHandle *remote_server = NULL; err = remote_server_connect_rsd(adapter, handshake, &remote_server); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to create remote server: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to create remote server: [%d] %s", err->code, + err->message); + idevice_error_free(err); adapter_free(adapter); rsd_handshake_free(handshake); return 1; @@ -121,8 +137,10 @@ int main(int argc, char **argv) { // Create ProcessControlClient ProcessControlHandle *process_control = NULL; err = process_control_new(remote_server, &process_control); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to create process control client: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to create process control client: [%d] %s", + err->code, err->message); + idevice_error_free(err); remote_server_free(remote_server); return 1; } @@ -131,8 +149,9 @@ int main(int argc, char **argv) { uint64_t pid; err = process_control_launch_app(process_control, bundle_id, NULL, 0, NULL, 0, true, false, &pid); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to launch app: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to launch app: [%d] %s", err->code, err->message); + idevice_error_free(err); process_control_free(process_control); remote_server_free(remote_server); return 1; @@ -141,8 +160,10 @@ int main(int argc, char **argv) { // Disable memory limits err = process_control_disable_memory_limit(process_control, pid); - if (err != IdeviceSuccess) { - fprintf(stderr, "Failed to disable memory limits: %d\n", err); + if (err != NULL) { + fprintf(stderr, "Failed to disable memory limits: [%d] %s", err->code, + err->message); + idevice_error_free(err); } else { printf("Successfully disabled memory limits\n"); } diff --git a/ffi/src/adapter.rs b/ffi/src/adapter.rs index 306237b..8e6edb8 100644 --- a/ffi/src/adapter.rs +++ b/ffi/src/adapter.rs @@ -1,11 +1,12 @@ // 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::{IdeviceErrorCode, RUNTIME, ReadWriteOpaque}; +use crate::{IdeviceFfiError, RUNTIME, ReadWriteOpaque, ffi_err}; pub struct AdapterStreamHandle<'a>(pub AdapterStream<'a>); @@ -17,7 +18,7 @@ pub struct AdapterStreamHandle<'a>(pub AdapterStream<'a>); /// * [`stream_handle`] - A pointer to allocate the new stream to /// /// # Returns -/// An error code indicating success or failure +/// Null on success, an IdeviceFfiError otherwise /// /// # Safety /// `handle` must be a valid pointer to a handle allocated by this library. @@ -28,9 +29,9 @@ pub unsafe extern "C" fn adapter_connect( adapter_handle: *mut AdapterHandle, port: u16, stream_handle: *mut *mut ReadWriteOpaque, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if adapter_handle.is_null() || stream_handle.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let adapter = unsafe { &mut (*adapter_handle).0 }; @@ -42,11 +43,11 @@ pub unsafe extern "C" fn adapter_connect( inner: Some(Box::new(r)), }); unsafe { *stream_handle = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } Err(e) => { log::error!("Adapter connect failed: {}", e); - IdeviceErrorCode::AdapterIOFailed + ffi_err!(e) } } } @@ -58,7 +59,7 @@ pub unsafe extern "C" fn adapter_connect( /// * [`path`] - The path to save the PCAP file (null-terminated string) /// /// # Returns -/// An error code indicating success or failure +/// Null on success, an IdeviceFfiError otherwise /// /// # Safety /// `handle` must be a valid pointer to a handle allocated by this library @@ -67,25 +68,25 @@ pub unsafe extern "C" fn adapter_connect( pub unsafe extern "C" fn adapter_pcap( handle: *mut AdapterHandle, path: *const c_char, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if handle.is_null() || path.is_null() { - return IdeviceErrorCode::InvalidArg; + 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 IdeviceErrorCode::InvalidArg, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidString), }; let res = RUNTIME.block_on(async move { adapter.pcap(path_str).await }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, + Ok(_) => null_mut(), Err(e) => { log::error!("Adapter pcap failed: {}", e); - IdeviceErrorCode::AdapterIOFailed + ffi_err!(e) } } } @@ -96,24 +97,24 @@ pub unsafe extern "C" fn adapter_pcap( /// * [`handle`] - The adapter stream handle /// /// # Returns -/// An error code indicating success or failure +/// 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) -> IdeviceErrorCode { +pub unsafe extern "C" fn adapter_close(handle: *mut AdapterStreamHandle) -> *mut IdeviceFfiError { if handle.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let adapter = unsafe { &mut (*handle).0 }; let res = RUNTIME.block_on(async move { adapter.close().await }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, + Ok(_) => null_mut(), Err(e) => { log::error!("Adapter close failed: {}", e); - IdeviceErrorCode::AdapterIOFailed + ffi_err!(e) } } } @@ -126,7 +127,7 @@ pub unsafe extern "C" fn adapter_close(handle: *mut AdapterStreamHandle) -> Idev /// * [`length`] - The length of the data /// /// # Returns -/// An error code indicating success or failure +/// Null on success, an IdeviceFfiError otherwise /// /// # Safety /// `handle` must be a valid pointer to a handle allocated by this library @@ -136,9 +137,9 @@ pub unsafe extern "C" fn adapter_send( handle: *mut AdapterStreamHandle, data: *const u8, length: usize, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if handle.is_null() || data.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let adapter = unsafe { &mut (*handle).0 }; @@ -147,10 +148,10 @@ pub unsafe extern "C" fn adapter_send( let res = RUNTIME.block_on(async move { adapter.psh(data_slice).await }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, + Ok(_) => null_mut(), Err(e) => { log::error!("Adapter send failed: {}", e); - IdeviceErrorCode::AdapterIOFailed + ffi_err!(e) } } } @@ -164,7 +165,7 @@ pub unsafe extern "C" fn adapter_send( /// * [`max_length`] - Maximum number of bytes that can be stored in `data` /// /// # Returns -/// An error code indicating success or failure +/// Null on success, an IdeviceFfiError otherwise /// /// # Safety /// `handle` must be a valid pointer to a handle allocated by this library @@ -176,9 +177,9 @@ pub unsafe extern "C" fn adapter_recv( data: *mut u8, length: *mut usize, max_length: usize, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if handle.is_null() || data.is_null() || length.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let adapter = unsafe { &mut (*handle).0 }; @@ -188,7 +189,7 @@ pub unsafe extern "C" fn adapter_recv( Ok(received_data) => { let received_len = received_data.len(); if received_len > max_length { - return IdeviceErrorCode::BufferTooSmall; + return ffi_err!(IdeviceError::FfiBufferTooSmall(received_len, max_length)); } unsafe { @@ -196,11 +197,11 @@ pub unsafe extern "C" fn adapter_recv( *length = received_len; } - IdeviceErrorCode::IdeviceSuccess + null_mut() } Err(e) => { log::error!("Adapter recv failed: {}", e); - IdeviceErrorCode::AdapterIOFailed + ffi_err!(e) } } } diff --git a/ffi/src/afc.rs b/ffi/src/afc.rs index 8b8a016..df9aa67 100644 --- a/ffi/src/afc.rs +++ b/ffi/src/afc.rs @@ -1,12 +1,14 @@ // Jackson Coxson +use std::ptr::null_mut; + use idevice::{ IdeviceError, IdeviceService, afc::{AfcClient, DeviceInfo, FileInfo}, provider::IdeviceProvider, }; -use crate::{IdeviceErrorCode, IdeviceHandle, RUNTIME, provider::IdeviceProviderHandle}; +use crate::{IdeviceFfiError, IdeviceHandle, RUNTIME, ffi_err, provider::IdeviceProviderHandle}; pub struct AfcClientHandle(pub AfcClient); @@ -17,7 +19,7 @@ pub struct AfcClientHandle(pub AfcClient); /// * [`client`] - On success, will be set to point to a newly allocated AfcClient handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `provider` must be a valid pointer to a handle allocated by this library @@ -26,10 +28,10 @@ pub struct AfcClientHandle(pub AfcClient); pub unsafe extern "C" fn afc_client_connect( provider: *mut IdeviceProviderHandle, client: *mut *mut AfcClientHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if provider.is_null() || client.is_null() { log::error!("Null pointer provided"); - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let res = RUNTIME.block_on(async { @@ -42,9 +44,9 @@ pub unsafe extern "C" fn afc_client_connect( Ok(r) => { let boxed = Box::new(AfcClientHandle(r)); unsafe { *client = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -55,7 +57,7 @@ pub unsafe extern "C" fn afc_client_connect( /// * [`client`] - On success, will be set to point to a newly allocated AfcClient handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `socket` must be a valid pointer to a handle allocated by this library @@ -64,15 +66,15 @@ pub unsafe extern "C" fn afc_client_connect( pub unsafe extern "C" fn afc_client_new( socket: *mut IdeviceHandle, client: *mut *mut AfcClientHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if socket.is_null() || client.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let socket = unsafe { Box::from_raw(socket) }.0; let r = AfcClient::new(socket); let boxed = Box::new(AfcClientHandle(r)); unsafe { *client = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } /// Frees an AfcClient handle @@ -100,7 +102,7 @@ pub unsafe extern "C" fn afc_client_free(handle: *mut AfcClientHandle) { /// * [`count`] - Will be set to the number of entries /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// All pointers must be valid and non-null @@ -111,9 +113,9 @@ pub unsafe extern "C" fn afc_list_directory( path: *const libc::c_char, entries: *mut *mut *mut libc::c_char, count: *mut libc::size_t, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if path.is_null() || entries.is_null() || count.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let path_cstr = unsafe { std::ffi::CStr::from_ptr(path) }; @@ -141,7 +143,7 @@ pub unsafe extern "C" fn afc_list_directory( let layout = std::alloc::Layout::array::<*mut libc::c_char>(string_count + 1).unwrap(); let ptr = unsafe { std::alloc::alloc(layout) as *mut *mut libc::c_char }; if ptr.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } // Fill the array with pointers to the strings, then leak each CString @@ -159,9 +161,9 @@ pub unsafe extern "C" fn afc_list_directory( *count = string_count; } - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -172,7 +174,7 @@ pub unsafe extern "C" fn afc_list_directory( /// * [`path`] - Path of the directory to create (UTF-8 null-terminated) /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` must be a valid pointer to a handle allocated by this library @@ -181,15 +183,15 @@ pub unsafe extern "C" fn afc_list_directory( pub unsafe extern "C" fn afc_make_directory( client: *mut AfcClientHandle, path: *const libc::c_char, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if client.is_null() || path.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let path_cstr = unsafe { std::ffi::CStr::from_ptr(path) }; let path = match path_cstr.to_str() { Ok(s) => s, - Err(_) => return IdeviceErrorCode::InvalidArg, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg), }; let res: Result<(), IdeviceError> = RUNTIME.block_on(async move { @@ -198,8 +200,8 @@ pub unsafe extern "C" fn afc_make_directory( }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } @@ -223,7 +225,7 @@ pub struct AfcFileInfo { /// * [`info`] - Will be populated with file information /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` and `path` must be valid pointers @@ -233,15 +235,15 @@ pub unsafe extern "C" fn afc_get_file_info( client: *mut AfcClientHandle, path: *const libc::c_char, info: *mut AfcFileInfo, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if client.is_null() || path.is_null() || info.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let path_cstr = unsafe { std::ffi::CStr::from_ptr(path) }; let path = match path_cstr.to_str() { Ok(s) => s, - Err(_) => return IdeviceErrorCode::InvalidArg, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg), }; let res: Result = RUNTIME.block_on(async move { @@ -270,9 +272,9 @@ pub unsafe extern "C" fn afc_get_file_info( None => std::ptr::null_mut(), }; } - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -316,7 +318,7 @@ pub struct AfcDeviceInfo { /// * [`info`] - Will be populated with device information /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` and `info` must be valid pointers @@ -324,9 +326,9 @@ pub struct AfcDeviceInfo { pub unsafe extern "C" fn afc_get_device_info( client: *mut AfcClientHandle, info: *mut AfcDeviceInfo, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if client.is_null() || info.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let res: Result = RUNTIME.block_on(async move { @@ -344,9 +346,9 @@ pub unsafe extern "C" fn afc_get_device_info( (*info).free_bytes = device_info.free_bytes; (*info).block_size = device_info.block_size; } - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -373,7 +375,7 @@ pub unsafe extern "C" fn afc_device_info_free(info: *mut AfcDeviceInfo) { /// * [`path`] - Path to the file or directory to remove (UTF-8 null-terminated) /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` must be a valid pointer to a handle allocated by this library @@ -382,15 +384,15 @@ pub unsafe extern "C" fn afc_device_info_free(info: *mut AfcDeviceInfo) { pub unsafe extern "C" fn afc_remove_path( client: *mut AfcClientHandle, path: *const libc::c_char, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if client.is_null() || path.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let path_cstr = unsafe { std::ffi::CStr::from_ptr(path) }; let path = match path_cstr.to_str() { Ok(s) => s, - Err(_) => return IdeviceErrorCode::InvalidArg, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg), }; let res: Result<(), IdeviceError> = RUNTIME.block_on(async move { @@ -399,8 +401,8 @@ pub unsafe extern "C" fn afc_remove_path( }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } @@ -411,7 +413,7 @@ pub unsafe extern "C" fn afc_remove_path( /// * [`path`] - Path to the directory to remove (UTF-8 null-terminated) /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` must be a valid pointer to a handle allocated by this library @@ -420,15 +422,15 @@ pub unsafe extern "C" fn afc_remove_path( pub unsafe extern "C" fn afc_remove_path_and_contents( client: *mut AfcClientHandle, path: *const libc::c_char, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if client.is_null() || path.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let path_cstr = unsafe { std::ffi::CStr::from_ptr(path) }; let path = match path_cstr.to_str() { Ok(s) => s, - Err(_) => return IdeviceErrorCode::InvalidArg, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg), }; let res: Result<(), IdeviceError> = RUNTIME.block_on(async move { @@ -437,8 +439,8 @@ pub unsafe extern "C" fn afc_remove_path_and_contents( }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } @@ -478,7 +480,7 @@ pub struct AfcFileHandle<'a>(Box>); // Op /// * [`handle`] - Will be set to a new file handle on success /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// All pointers must be valid and non-null @@ -491,15 +493,15 @@ pub unsafe extern "C" fn afc_file_open( path: *const libc::c_char, mode: AfcFopenMode, handle: *mut *mut AfcFileHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if client.is_null() || path.is_null() || handle.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let path_cstr = unsafe { std::ffi::CStr::from_ptr(path) }; let path = match path_cstr.to_str() { Ok(s) => s, - Err(_) => return IdeviceErrorCode::InvalidArg, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg), }; let mode = mode.into(); @@ -519,9 +521,9 @@ pub unsafe extern "C" fn afc_file_open( match res { Ok(f) => { unsafe { *handle = f } - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -531,22 +533,22 @@ pub unsafe extern "C" fn afc_file_open( /// * [`handle`] - File handle to close /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `handle` must be a valid pointer to a handle allocated by this library #[unsafe(no_mangle)] -pub unsafe extern "C" fn afc_file_close(handle: *mut AfcFileHandle) -> IdeviceErrorCode { +pub unsafe extern "C" fn afc_file_close(handle: *mut AfcFileHandle) -> *mut IdeviceFfiError { if handle.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let fd = unsafe { Box::from_raw(handle as *mut idevice::afc::file::FileDescriptor) }; let res: Result<(), IdeviceError> = RUNTIME.block_on(async move { fd.close().await }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } @@ -558,7 +560,7 @@ pub unsafe extern "C" fn afc_file_close(handle: *mut AfcFileHandle) -> IdeviceEr /// * [`length`] - Will be set to the length of the read data /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// All pointers must be valid and non-null @@ -567,9 +569,9 @@ pub unsafe extern "C" fn afc_file_read( handle: *mut AfcFileHandle, data: *mut *mut u8, length: *mut libc::size_t, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if handle.is_null() || data.is_null() || length.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let fd = unsafe { &mut *(handle as *mut idevice::afc::file::FileDescriptor) }; @@ -583,9 +585,9 @@ pub unsafe extern "C" fn afc_file_read( *length = boxed.len(); } std::mem::forget(boxed); - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -597,7 +599,7 @@ pub unsafe extern "C" fn afc_file_read( /// * [`length`] - Length of data to write /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// All pointers must be valid and non-null @@ -607,9 +609,9 @@ pub unsafe extern "C" fn afc_file_write( handle: *mut AfcFileHandle, data: *const u8, length: libc::size_t, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if handle.is_null() || data.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let fd = unsafe { &mut *(handle as *mut idevice::afc::file::FileDescriptor) }; @@ -618,8 +620,8 @@ pub unsafe extern "C" fn afc_file_write( let res: Result<(), IdeviceError> = RUNTIME.block_on(async move { fd.write(data_slice).await }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } @@ -639,7 +641,7 @@ pub enum AfcLinkType { /// * [`link_type`] - Type of link to create /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// All pointers must be valid and non-null @@ -650,21 +652,21 @@ pub unsafe extern "C" fn afc_make_link( target: *const libc::c_char, source: *const libc::c_char, link_type: AfcLinkType, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if client.is_null() || target.is_null() || source.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let target_cstr = unsafe { std::ffi::CStr::from_ptr(target) }; let target = match target_cstr.to_str() { Ok(s) => s, - Err(_) => return IdeviceErrorCode::InvalidArg, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg), }; let source_cstr = unsafe { std::ffi::CStr::from_ptr(source) }; let source = match source_cstr.to_str() { Ok(s) => s, - Err(_) => return IdeviceErrorCode::InvalidArg, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg), }; let link_type = match link_type { @@ -678,8 +680,8 @@ pub unsafe extern "C" fn afc_make_link( }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } @@ -691,7 +693,7 @@ pub unsafe extern "C" fn afc_make_link( /// * [`target`] - New path for the file/directory (UTF-8 null-terminated) /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// All pointers must be valid and non-null @@ -701,21 +703,21 @@ pub unsafe extern "C" fn afc_rename_path( client: *mut AfcClientHandle, source: *const libc::c_char, target: *const libc::c_char, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if client.is_null() || source.is_null() || target.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let source_cstr = unsafe { std::ffi::CStr::from_ptr(source) }; let source = match source_cstr.to_str() { Ok(s) => s, - Err(_) => return IdeviceErrorCode::InvalidArg, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg), }; let target_cstr = unsafe { std::ffi::CStr::from_ptr(target) }; let target = match target_cstr.to_str() { Ok(s) => s, - Err(_) => return IdeviceErrorCode::InvalidArg, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg), }; let res: Result<(), IdeviceError> = RUNTIME.block_on(async move { @@ -724,8 +726,8 @@ pub unsafe extern "C" fn afc_rename_path( }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } diff --git a/ffi/src/amfi.rs b/ffi/src/amfi.rs index 4cd5ce8..6019826 100644 --- a/ffi/src/amfi.rs +++ b/ffi/src/amfi.rs @@ -1,8 +1,10 @@ // Jackson Coxson +use std::ptr::null_mut; + use idevice::{IdeviceError, IdeviceService, amfi::AmfiClient, provider::IdeviceProvider}; -use crate::{IdeviceErrorCode, IdeviceHandle, RUNTIME, provider::IdeviceProviderHandle}; +use crate::{IdeviceFfiError, IdeviceHandle, RUNTIME, ffi_err, provider::IdeviceProviderHandle}; pub struct AmfiClientHandle(pub AmfiClient); @@ -13,7 +15,7 @@ pub struct AmfiClientHandle(pub AmfiClient); /// * [`client`] - On success, will be set to point to a newly allocated AmfiClient handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `provider` must be a valid pointer to a handle allocated by this library @@ -22,10 +24,10 @@ pub struct AmfiClientHandle(pub AmfiClient); pub unsafe extern "C" fn amfi_connect( provider: *mut IdeviceProviderHandle, client: *mut *mut AmfiClientHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if provider.is_null() || client.is_null() { log::error!("Null pointer provided"); - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let res: Result = RUNTIME.block_on(async move { @@ -39,9 +41,9 @@ pub unsafe extern "C" fn amfi_connect( Ok(r) => { let boxed = Box::new(AmfiClientHandle(r)); unsafe { *client = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -52,7 +54,7 @@ pub unsafe extern "C" fn amfi_connect( /// * [`client`] - On success, will be set to point to a newly allocated AmfiClient handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `socket` must be a valid pointer to a handle allocated by this library. It is consumed, and @@ -62,16 +64,16 @@ pub unsafe extern "C" fn amfi_connect( pub unsafe extern "C" fn amfi_new( socket: *mut IdeviceHandle, client: *mut *mut AmfiClientHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if socket.is_null() || client.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let socket = unsafe { Box::from_raw(socket) }.0; let r = AmfiClient::new(socket); let boxed = Box::new(AmfiClientHandle(r)); unsafe { *client = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } /// Shows the option in the settings UI @@ -80,16 +82,16 @@ pub unsafe extern "C" fn amfi_new( /// * `client` - A valid AmfiClient handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` must be a valid pointer to a handle allocated by this library #[unsafe(no_mangle)] pub unsafe extern "C" fn amfi_reveal_developer_mode_option_in_ui( client: *mut AmfiClientHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if client.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let res: Result<(), IdeviceError> = RUNTIME.block_on(async move { @@ -97,8 +99,8 @@ pub unsafe extern "C" fn amfi_reveal_developer_mode_option_in_ui( client_ref.reveal_developer_mode_option_in_ui().await }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } @@ -108,16 +110,16 @@ pub unsafe extern "C" fn amfi_reveal_developer_mode_option_in_ui( /// * `client` - A valid AmfiClient handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` must be a valid pointer to a handle allocated by this library #[unsafe(no_mangle)] pub unsafe extern "C" fn amfi_enable_developer_mode( client: *mut AmfiClientHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if client.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let res: Result<(), IdeviceError> = RUNTIME.block_on(async move { @@ -125,8 +127,8 @@ pub unsafe extern "C" fn amfi_enable_developer_mode( client_ref.enable_developer_mode().await }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } @@ -136,16 +138,16 @@ pub unsafe extern "C" fn amfi_enable_developer_mode( /// * `client` - A valid AmfiClient handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` must be a valid pointer to a handle allocated by this library #[unsafe(no_mangle)] pub unsafe extern "C" fn amfi_accept_developer_mode( client: *mut AmfiClientHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if client.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let res: Result<(), IdeviceError> = RUNTIME.block_on(async move { @@ -153,8 +155,8 @@ pub unsafe extern "C" fn amfi_accept_developer_mode( client_ref.accept_developer_mode().await }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } diff --git a/ffi/src/core_device_proxy.rs b/ffi/src/core_device_proxy.rs index 4e027bd..2d9960e 100644 --- a/ffi/src/core_device_proxy.rs +++ b/ffi/src/core_device_proxy.rs @@ -1,13 +1,16 @@ // Jackson Coxson -use std::ffi::{CString, c_char}; +use std::{ + ffi::{CString, c_char}, + ptr::null_mut, +}; use idevice::{ IdeviceError, IdeviceService, core_device_proxy::CoreDeviceProxy, provider::IdeviceProvider, tcp::adapter::Adapter, }; -use crate::{IdeviceErrorCode, IdeviceHandle, RUNTIME, provider::IdeviceProviderHandle}; +use crate::{IdeviceFfiError, IdeviceHandle, RUNTIME, ffi_err, provider::IdeviceProviderHandle}; pub struct CoreDeviceProxyHandle(pub CoreDeviceProxy); pub struct AdapterHandle(pub Adapter); @@ -19,7 +22,7 @@ pub struct AdapterHandle(pub Adapter); /// * [`client`] - On success, will be set to point to a newly allocated CoreDeviceProxy handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `provider` must be a valid pointer to a handle allocated by this library @@ -28,10 +31,10 @@ pub struct AdapterHandle(pub Adapter); pub unsafe extern "C" fn core_device_proxy_connect( provider: *mut IdeviceProviderHandle, client: *mut *mut CoreDeviceProxyHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if provider.is_null() || client.is_null() { log::error!("Null pointer provided"); - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let res: Result = RUNTIME.block_on(async move { @@ -45,9 +48,9 @@ pub unsafe extern "C" fn core_device_proxy_connect( Ok(r) => { let boxed = Box::new(CoreDeviceProxyHandle(r)); unsafe { *client = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -58,7 +61,7 @@ pub unsafe extern "C" fn core_device_proxy_connect( /// * [`client`] - On success, will be set to point to a newly allocated CoreDeviceProxy handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `socket` must be a valid pointer to a handle allocated by this library. It is consumed and @@ -68,9 +71,9 @@ pub unsafe extern "C" fn core_device_proxy_connect( pub unsafe extern "C" fn core_device_proxy_new( socket: *mut IdeviceHandle, client: *mut *mut CoreDeviceProxyHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if socket.is_null() || client.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let socket = unsafe { Box::from_raw(socket) }.0; let r: Result = @@ -79,9 +82,9 @@ pub unsafe extern "C" fn core_device_proxy_new( Ok(r) => { let boxed = Box::new(CoreDeviceProxyHandle(r)); unsafe { *client = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -93,7 +96,7 @@ pub unsafe extern "C" fn core_device_proxy_new( /// * [`length`] - The length of the data /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `handle` must be a valid pointer to a handle allocated by this library @@ -103,9 +106,9 @@ pub unsafe extern "C" fn core_device_proxy_send( handle: *mut CoreDeviceProxyHandle, data: *const u8, length: usize, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if handle.is_null() || data.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let proxy = unsafe { &mut (*handle).0 }; @@ -114,8 +117,8 @@ pub unsafe extern "C" fn core_device_proxy_send( let res = RUNTIME.block_on(async move { proxy.send(data_slice).await }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } @@ -128,7 +131,7 @@ pub unsafe extern "C" fn core_device_proxy_send( /// * [`max_length`] - Maximum number of bytes that can be stored in `data` /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `handle` must be a valid pointer to a handle allocated by this library @@ -140,9 +143,9 @@ pub unsafe extern "C" fn core_device_proxy_recv( data: *mut u8, length: *mut usize, max_length: usize, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if handle.is_null() || data.is_null() || length.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let proxy = unsafe { &mut (*handle).0 }; @@ -153,7 +156,7 @@ pub unsafe extern "C" fn core_device_proxy_recv( Ok(received_data) => { let received_len = received_data.len(); if received_len > max_length { - return IdeviceErrorCode::BufferTooSmall; + return ffi_err!(IdeviceError::FfiBufferTooSmall(received_len, max_length)); } unsafe { @@ -161,9 +164,9 @@ pub unsafe extern "C" fn core_device_proxy_recv( *length = received_len; } - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -176,7 +179,7 @@ pub unsafe extern "C" fn core_device_proxy_recv( /// * [`netmask`] - Pointer to store the netmask string /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `handle` must be a valid pointer to a handle allocated by this library @@ -188,10 +191,10 @@ pub unsafe extern "C" fn core_device_proxy_get_client_parameters( mtu: *mut u16, address: *mut *mut c_char, netmask: *mut *mut c_char, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if handle.is_null() { log::error!("Passed null handle"); - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let proxy = unsafe { &(*handle).0 }; @@ -204,12 +207,12 @@ pub unsafe extern "C" fn core_device_proxy_get_client_parameters( // Allocate both strings, but handle partial failure let address_cstring = match CString::new(params.address.clone()) { Ok(s) => s, - Err(_) => return IdeviceErrorCode::InvalidString, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidString), }; let netmask_cstring = match CString::new(params.netmask.clone()) { Ok(s) => s, - Err(_) => return IdeviceErrorCode::InvalidString, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidString), }; // Only assign to output pointers after both succeed @@ -218,7 +221,7 @@ pub unsafe extern "C" fn core_device_proxy_get_client_parameters( *netmask = netmask_cstring.into_raw(); } - IdeviceErrorCode::IdeviceSuccess + null_mut() } /// Gets the server address from the handshake @@ -228,7 +231,7 @@ pub unsafe extern "C" fn core_device_proxy_get_client_parameters( /// * [`address`] - Pointer to store the server address string /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `handle` must be a valid pointer to a handle allocated by this library @@ -237,9 +240,9 @@ pub unsafe extern "C" fn core_device_proxy_get_client_parameters( pub unsafe extern "C" fn core_device_proxy_get_server_address( handle: *mut CoreDeviceProxyHandle, address: *mut *mut c_char, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if handle.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let proxy = unsafe { &(*handle).0 }; @@ -247,11 +250,11 @@ pub unsafe extern "C" fn core_device_proxy_get_server_address( unsafe { *address = match CString::new(proxy.handshake.server_address.clone()) { Ok(s) => s.into_raw(), - Err(_) => return IdeviceErrorCode::InvalidString, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidString), }; } - IdeviceErrorCode::IdeviceSuccess + null_mut() } /// Gets the server RSD port from the handshake @@ -261,7 +264,7 @@ pub unsafe extern "C" fn core_device_proxy_get_server_address( /// * [`port`] - Pointer to store the port number /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `handle` must be a valid pointer to a handle allocated by this library @@ -270,9 +273,9 @@ pub unsafe extern "C" fn core_device_proxy_get_server_address( pub unsafe extern "C" fn core_device_proxy_get_server_rsd_port( handle: *mut CoreDeviceProxyHandle, port: *mut u16, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if handle.is_null() || port.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let proxy = unsafe { &(*handle).0 }; @@ -280,7 +283,7 @@ pub unsafe extern "C" fn core_device_proxy_get_server_rsd_port( *port = proxy.handshake.server_rsd_port; } - IdeviceErrorCode::IdeviceSuccess + null_mut() } /// Creates a software TCP tunnel adapter @@ -290,7 +293,7 @@ pub unsafe extern "C" fn core_device_proxy_get_server_rsd_port( /// * [`adapter`] - Pointer to store the newly created adapter handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `handle` must be a valid pointer to a handle allocated by this library, and never used again @@ -299,9 +302,9 @@ pub unsafe extern "C" fn core_device_proxy_get_server_rsd_port( pub unsafe extern "C" fn core_device_proxy_create_tcp_adapter( handle: *mut CoreDeviceProxyHandle, adapter: *mut *mut AdapterHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if handle.is_null() || adapter.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let proxy = unsafe { Box::from_raw(handle) }; @@ -311,9 +314,9 @@ pub unsafe extern "C" fn core_device_proxy_create_tcp_adapter( Ok(adapter_obj) => { let boxed = Box::new(AdapterHandle(adapter_obj)); unsafe { *adapter = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } diff --git a/ffi/src/debug_proxy.rs b/ffi/src/debug_proxy.rs index cb1fc85..1ab061e 100644 --- a/ffi/src/debug_proxy.rs +++ b/ffi/src/debug_proxy.rs @@ -2,7 +2,7 @@ use std::ffi::{CStr, CString, c_char}; use std::os::raw::c_int; -use std::ptr; +use std::ptr::{self, null_mut}; use idevice::debug_proxy::{DebugProxyClient, DebugserverCommand}; use idevice::tcp::stream::AdapterStream; @@ -10,7 +10,7 @@ use idevice::{IdeviceError, ReadWrite, RsdService}; use crate::core_device_proxy::AdapterHandle; use crate::rsd::RsdHandshakeHandle; -use crate::{IdeviceErrorCode, RUNTIME}; +use crate::{IdeviceFfiError, RUNTIME, ffi_err}; /// Opaque handle to a DebugProxyClient pub struct DebugProxyHandle(pub DebugProxyClient>); @@ -122,7 +122,7 @@ pub unsafe extern "C" fn debugserver_command_free(command: *mut DebugserverComma /// * [`handshake`] - An RSD handshake from the same provider /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `provider` must be a valid pointer to a handle allocated by this library @@ -132,9 +132,9 @@ pub unsafe extern "C" fn debug_proxy_connect_rsd( provider: *mut AdapterHandle, handshake: *mut RsdHandshakeHandle, handle: *mut *mut DebugProxyHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if provider.is_null() || handshake.is_null() || handshake.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let res: Result, IdeviceError> = RUNTIME.block_on(async move { let provider_ref = unsafe { &mut (*provider).0 }; @@ -150,9 +150,9 @@ pub unsafe extern "C" fn debug_proxy_connect_rsd( d.into_inner(), )))); unsafe { *handle = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -163,7 +163,7 @@ pub unsafe extern "C" fn debug_proxy_connect_rsd( /// * [`handle`] - Pointer to store the newly created DebugProxyClient handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `socket` must be a valid pointer to a handle allocated by this library @@ -172,9 +172,9 @@ pub unsafe extern "C" fn debug_proxy_connect_rsd( pub unsafe extern "C" fn debug_proxy_new( socket: *mut Box, handle: *mut *mut DebugProxyHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if socket.is_null() || handle.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let socket = unsafe { Box::from_raw(socket) }; @@ -182,7 +182,7 @@ pub unsafe extern "C" fn debug_proxy_new( let new_handle = DebugProxyHandle(client); unsafe { *handle = Box::into_raw(Box::new(new_handle)) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } /// Frees a DebugProxyClient handle @@ -207,7 +207,7 @@ pub unsafe extern "C" fn debug_proxy_free(handle: *mut DebugProxyHandle) { /// * [`response`] - Pointer to store the response (caller must free) /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `handle` and `command` must be valid pointers @@ -217,9 +217,9 @@ pub unsafe extern "C" fn debug_proxy_send_command( handle: *mut DebugProxyHandle, command: *mut DebugserverCommandHandle, response: *mut *mut c_char, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if handle.is_null() || command.is_null() || response.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let client = unsafe { &mut (*handle).0 }; @@ -247,16 +247,16 @@ pub unsafe extern "C" fn debug_proxy_send_command( Ok(Some(r)) => { let cstr = match CString::new(r) { Ok(c) => c, - Err(_) => return IdeviceErrorCode::InvalidString, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidString), }; unsafe { *response = cstr.into_raw() }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } Ok(None) => { unsafe { *response = ptr::null_mut() }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -267,7 +267,7 @@ pub unsafe extern "C" fn debug_proxy_send_command( /// * [`response`] - Pointer to store the response (caller must free) /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `handle` must be a valid pointer @@ -276,9 +276,9 @@ pub unsafe extern "C" fn debug_proxy_send_command( pub unsafe extern "C" fn debug_proxy_read_response( handle: *mut DebugProxyHandle, response: *mut *mut c_char, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if handle.is_null() || response.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let client = unsafe { &mut (*handle).0 }; @@ -288,16 +288,16 @@ pub unsafe extern "C" fn debug_proxy_read_response( Ok(Some(r)) => { let cstr = match CString::new(r) { Ok(c) => c, - Err(_) => return IdeviceErrorCode::InvalidString, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidString), }; unsafe { *response = cstr.into_raw() }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } Ok(None) => { unsafe { *response = ptr::null_mut() }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -309,7 +309,7 @@ pub unsafe extern "C" fn debug_proxy_read_response( /// * [`len`] - Length of the data /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `handle` must be a valid pointer @@ -319,9 +319,9 @@ pub unsafe extern "C" fn debug_proxy_send_raw( handle: *mut DebugProxyHandle, data: *const u8, len: usize, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if handle.is_null() || data.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let client = unsafe { &mut (*handle).0 }; @@ -329,8 +329,8 @@ pub unsafe extern "C" fn debug_proxy_send_raw( let res = RUNTIME.block_on(async move { client.send_raw(data_slice).await }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } @@ -342,7 +342,7 @@ pub unsafe extern "C" fn debug_proxy_send_raw( /// * [`response`] - Pointer to store the response (caller must free) /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `handle` must be a valid pointer @@ -352,9 +352,9 @@ pub unsafe extern "C" fn debug_proxy_read( handle: *mut DebugProxyHandle, len: usize, response: *mut *mut c_char, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if handle.is_null() || response.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let client = unsafe { &mut (*handle).0 }; @@ -364,12 +364,12 @@ pub unsafe extern "C" fn debug_proxy_read( Ok(r) => { let cstr = match CString::new(r) { Ok(c) => c, - Err(_) => return IdeviceErrorCode::InvalidString, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidString), }; unsafe { *response = cstr.into_raw() }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -382,7 +382,7 @@ pub unsafe extern "C" fn debug_proxy_read( /// * [`response`] - Pointer to store the response (caller must free) /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `handle` must be a valid pointer @@ -394,9 +394,9 @@ pub unsafe extern "C" fn debug_proxy_set_argv( argv: *const *const c_char, argv_count: usize, response: *mut *mut c_char, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if handle.is_null() || response.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let client = unsafe { &mut (*handle).0 }; @@ -422,12 +422,12 @@ pub unsafe extern "C" fn debug_proxy_set_argv( Ok(r) => { let cstr = match CString::new(r) { Ok(c) => c, - Err(_) => return IdeviceErrorCode::InvalidString, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidString), }; unsafe { *response = cstr.into_raw() }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -437,22 +437,24 @@ pub unsafe extern "C" fn debug_proxy_set_argv( /// * [`handle`] - The DebugProxyClient handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `handle` must be a valid pointer #[unsafe(no_mangle)] -pub unsafe extern "C" fn debug_proxy_send_ack(handle: *mut DebugProxyHandle) -> IdeviceErrorCode { +pub unsafe extern "C" fn debug_proxy_send_ack( + handle: *mut DebugProxyHandle, +) -> *mut IdeviceFfiError { if handle.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let client = unsafe { &mut (*handle).0 }; let res = RUNTIME.block_on(async move { client.send_ack().await }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } @@ -462,22 +464,24 @@ pub unsafe extern "C" fn debug_proxy_send_ack(handle: *mut DebugProxyHandle) -> /// * [`handle`] - The DebugProxyClient handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `handle` must be a valid pointer #[unsafe(no_mangle)] -pub unsafe extern "C" fn debug_proxy_send_nack(handle: *mut DebugProxyHandle) -> IdeviceErrorCode { +pub unsafe extern "C" fn debug_proxy_send_nack( + handle: *mut DebugProxyHandle, +) -> *mut IdeviceFfiError { if handle.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let client = unsafe { &mut (*handle).0 }; let res = RUNTIME.block_on(async move { client.send_noack().await }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } diff --git a/ffi/src/errors.rs b/ffi/src/errors.rs index 375430f..de4868b 100644 --- a/ffi/src/errors.rs +++ b/ffi/src/errors.rs @@ -1,147 +1,47 @@ // Jackson Coxson -use idevice::IdeviceError; +use std::ffi::{CString, c_char}; #[repr(C)] -pub enum IdeviceErrorCode { - IdeviceSuccess = 0, - // Main library - Socket = -1, - Tls = -2, - TlsBuilderFailed = -3, - Plist = -4, - Utf8 = -5, - UnexpectedResponse = -6, - GetProhibited = -7, - SessionInactive = -8, - InvalidHostID = -9, - NoEstablishedConnection = -10, - HeartbeatSleepyTime = -11, - HeartbeatTimeout = -12, - NotFound = -13, - CdtunnelPacketTooShort = -14, - CdtunnelPacketInvalidMagic = -15, - PacketSizeMismatch = -16, - Json = -17, - DeviceNotFound = -18, - DeviceLocked = -19, - UsbConnectionRefused = -20, - UsbBadCommand = -21, - UsbBadDevice = -22, - UsbBadVersion = -23, - BadBuildManifest = -24, - ImageNotMounted = -25, - Reqwest = -26, - InternalError = -27, - NsKeyedArchiveError = -29, - UnknownAuxValueType = -30, - UnknownChannel = -31, - AddrParseError = -32, - DisableMemoryLimitFailed = -33, - NotEnoughBytes = -34, - Utf8Error = -35, - InvalidArgument = -36, - UnknownErrorType = -37, - PemParseFailed = -38, - MisagentFailure = -39, - InstallationProxyOperationFailed = -40, - Afc = -41, - UnknownAfcOpcode = -42, - InvalidAfcMagic = -43, - AfcMissingAttribute = -44, - ServiceNotFound = -45, - PairingDialogResponsePending = -46, - UserDeniedPairing = -47, - PasswordProtected = -48, - CrashReportMoverBadResponse = -49, - UnknownFrame = -50, - UnknownHttpSetting = -51, - UninitializedStreamId = -52, - UnknownXpcType = -53, - MalformedXpc = -54, - InvalidXpcMagic = -55, - UnexpectedXpcVersion = -56, - InvalidCString = -57, - HttpStreamReset = -58, - HttpGoAway = -59, - - // FFI specific bindings - AdapterIOFailed = -996, - BufferTooSmall = -998, - InvalidString = -999, - InvalidArg = -1000, +#[derive(Debug)] +pub struct IdeviceFfiError { + pub code: i32, + pub message: *const c_char, } -impl From for IdeviceErrorCode { - fn from(err: IdeviceError) -> Self { - match err { - IdeviceError::Socket(_) => IdeviceErrorCode::Socket, - IdeviceError::Rustls(_) => IdeviceErrorCode::Tls, - IdeviceError::TlsBuilderFailed(_) => IdeviceErrorCode::TlsBuilderFailed, - IdeviceError::Plist(_) => IdeviceErrorCode::Plist, - IdeviceError::Utf8(_) => IdeviceErrorCode::Utf8, - IdeviceError::UnexpectedResponse => IdeviceErrorCode::UnexpectedResponse, - IdeviceError::GetProhibited => IdeviceErrorCode::GetProhibited, - IdeviceError::SessionInactive => IdeviceErrorCode::SessionInactive, - IdeviceError::InvalidHostID => IdeviceErrorCode::InvalidHostID, - IdeviceError::NoEstablishedConnection => IdeviceErrorCode::NoEstablishedConnection, - IdeviceError::HeartbeatSleepyTime => IdeviceErrorCode::HeartbeatSleepyTime, - IdeviceError::HeartbeatTimeout => IdeviceErrorCode::HeartbeatTimeout, - IdeviceError::NotFound => IdeviceErrorCode::NotFound, - IdeviceError::CdtunnelPacketTooShort => IdeviceErrorCode::CdtunnelPacketTooShort, - IdeviceError::CdtunnelPacketInvalidMagic => { - IdeviceErrorCode::CdtunnelPacketInvalidMagic - } - IdeviceError::PacketSizeMismatch => IdeviceErrorCode::PacketSizeMismatch, - IdeviceError::Json(_) => IdeviceErrorCode::Json, - IdeviceError::DeviceNotFound => IdeviceErrorCode::DeviceNotFound, - IdeviceError::DeviceLocked => IdeviceErrorCode::DeviceLocked, - IdeviceError::UsbConnectionRefused => IdeviceErrorCode::UsbConnectionRefused, - IdeviceError::UsbBadCommand => IdeviceErrorCode::UsbBadCommand, - IdeviceError::UsbBadDevice => IdeviceErrorCode::UsbBadDevice, - IdeviceError::UsbBadVersion => IdeviceErrorCode::UsbBadVersion, - IdeviceError::BadBuildManifest => IdeviceErrorCode::BadBuildManifest, - IdeviceError::ImageNotMounted => IdeviceErrorCode::ImageNotMounted, - IdeviceError::Reqwest(_) => IdeviceErrorCode::Reqwest, - IdeviceError::InternalError(_) => IdeviceErrorCode::InternalError, - IdeviceError::NsKeyedArchiveError(_) => IdeviceErrorCode::NsKeyedArchiveError, - IdeviceError::UnknownAuxValueType(_) => IdeviceErrorCode::UnknownAuxValueType, - IdeviceError::UnknownChannel(_) => IdeviceErrorCode::UnknownChannel, - IdeviceError::AddrParseError(_) => IdeviceErrorCode::AddrParseError, - IdeviceError::DisableMemoryLimitFailed => IdeviceErrorCode::DisableMemoryLimitFailed, - IdeviceError::NotEnoughBytes(_, _) => IdeviceErrorCode::NotEnoughBytes, - IdeviceError::Utf8Error => IdeviceErrorCode::Utf8Error, - IdeviceError::InvalidArgument => IdeviceErrorCode::InvalidArgument, - IdeviceError::UnknownErrorType(_) => IdeviceErrorCode::UnknownErrorType, - IdeviceError::PemParseFailed(_) => IdeviceErrorCode::PemParseFailed, - IdeviceError::MisagentFailure => IdeviceErrorCode::MisagentFailure, - IdeviceError::InstallationProxyOperationFailed(_) => { - IdeviceErrorCode::InstallationProxyOperationFailed - } - IdeviceError::Afc(_) => IdeviceErrorCode::Afc, - IdeviceError::UnknownAfcOpcode => IdeviceErrorCode::UnknownAfcOpcode, - IdeviceError::InvalidAfcMagic => IdeviceErrorCode::InvalidAfcMagic, - IdeviceError::AfcMissingAttribute => IdeviceErrorCode::AfcMissingAttribute, - IdeviceError::ServiceNotFound => IdeviceErrorCode::ServiceNotFound, - IdeviceError::PairingDialogResponsePending => { - IdeviceErrorCode::PairingDialogResponsePending - } - IdeviceError::UserDeniedPairing => IdeviceErrorCode::UserDeniedPairing, - IdeviceError::PasswordProtected => IdeviceErrorCode::PasswordProtected, - IdeviceError::CrashReportMoverBadResponse(_) => { - IdeviceErrorCode::CrashReportMoverBadResponse - } - IdeviceError::UnknownFrame(_) => IdeviceErrorCode::UnknownFrame, - IdeviceError::UnknownHttpSetting(_) => IdeviceErrorCode::UnknownHttpSetting, - IdeviceError::UninitializedStreamId => IdeviceErrorCode::UninitializedStreamId, - IdeviceError::UnknownXpcType(_) => IdeviceErrorCode::UnknownXpcType, - IdeviceError::MalformedXpc => IdeviceErrorCode::MalformedXpc, - IdeviceError::InvalidXpcMagic => IdeviceErrorCode::InvalidXpcMagic, - IdeviceError::UnexpectedXpcVersion => IdeviceErrorCode::UnexpectedXpcVersion, - IdeviceError::InvalidCString => IdeviceErrorCode::InvalidCString, - IdeviceError::HttpStreamReset => IdeviceErrorCode::HttpStreamReset, - IdeviceError::HttpGoAway(_) => IdeviceErrorCode::HttpGoAway, - _ => IdeviceErrorCode::InternalError, - } +/// Frees the IdeviceFfiError +/// +/// # Safety +/// `err` must be a struct allocated by this library +#[unsafe(no_mangle)] +pub unsafe extern "C" fn idevice_error_free(err: *mut IdeviceFfiError) { + if err.is_null() { + return; + } + unsafe { + // Free the message first + let _ = CString::from_raw((*err).message as *mut c_char); + // Then free the struct itself + let _ = Box::from_raw(err); } } + +#[macro_export] +macro_rules! ffi_err { + ($err:expr) => {{ + use idevice::IdeviceError; + use std::ffi::CString; + use $crate::IdeviceFfiError; + + let err: IdeviceError = $err.into(); + let code = err.code(); + let msg = CString::new(err.to_string()) + .unwrap_or_else(|_| CString::new("invalid error").unwrap()); + let raw_msg = msg.into_raw(); + + Box::into_raw(Box::new(IdeviceFfiError { + code, + message: raw_msg, + })) + }}; +} diff --git a/ffi/src/heartbeat.rs b/ffi/src/heartbeat.rs index 6b30261..994ced8 100644 --- a/ffi/src/heartbeat.rs +++ b/ffi/src/heartbeat.rs @@ -1,10 +1,12 @@ // Jackson Coxson +use std::ptr::null_mut; + use idevice::{ IdeviceError, IdeviceService, heartbeat::HeartbeatClient, provider::IdeviceProvider, }; -use crate::{IdeviceErrorCode, IdeviceHandle, RUNTIME, provider::IdeviceProviderHandle}; +use crate::{IdeviceFfiError, IdeviceHandle, RUNTIME, ffi_err, provider::IdeviceProviderHandle}; pub struct HeartbeatClientHandle(pub HeartbeatClient); @@ -15,7 +17,7 @@ pub struct HeartbeatClientHandle(pub HeartbeatClient); /// * [`client`] - On success, will be set to point to a newly allocated InstallationProxyClient handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `provider` must be a valid pointer to a handle allocated by this library @@ -24,10 +26,10 @@ pub struct HeartbeatClientHandle(pub HeartbeatClient); pub unsafe extern "C" fn heartbeat_connect( provider: *mut IdeviceProviderHandle, client: *mut *mut HeartbeatClientHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if provider.is_null() || client.is_null() { log::error!("Null pointer provided"); - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let res: Result = RUNTIME.block_on(async move { @@ -40,13 +42,10 @@ pub unsafe extern "C" fn heartbeat_connect( Ok(r) => { let boxed = Box::new(HeartbeatClientHandle(r)); unsafe { *client = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } Err(e) => { - // If connection failed, the provider_box was already forgotten, - // so we need to reconstruct it to avoid leak - let _ = unsafe { Box::from_raw(provider) }; - e.into() + ffi_err!(e) } } } @@ -58,7 +57,7 @@ pub unsafe extern "C" fn heartbeat_connect( /// * [`client`] - On success, will be set to point to a newly allocated InstallationProxyClient handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `socket` must be a valid pointer to a handle allocated by this library. The socket is consumed, @@ -68,15 +67,15 @@ pub unsafe extern "C" fn heartbeat_connect( pub unsafe extern "C" fn heartbeat_new( socket: *mut IdeviceHandle, client: *mut *mut HeartbeatClientHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if socket.is_null() || client.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let socket = unsafe { Box::from_raw(socket) }.0; let r = HeartbeatClient::new(socket); let boxed = Box::new(HeartbeatClientHandle(r)); unsafe { *client = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } /// Sends a polo to the device @@ -85,24 +84,24 @@ pub unsafe extern "C" fn heartbeat_new( /// * `client` - A valid HeartbeatClient handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` must be a valid pointer to a handle allocated by this library #[unsafe(no_mangle)] pub unsafe extern "C" fn heartbeat_send_polo( client: *mut HeartbeatClientHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if client.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let res: Result<(), IdeviceError> = RUNTIME.block_on(async move { let client_ref = unsafe { &mut (*client).0 }; client_ref.send_polo().await }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } @@ -114,7 +113,7 @@ pub unsafe extern "C" fn heartbeat_send_polo( /// * `new_interval` - A pointer to set the requested marco /// /// # Returns -/// An error code indicating success or failure. +/// An IdeviceFfiError on error, null on success. /// /// # Safety /// `client` must be a valid pointer to a handle allocated by this library @@ -123,9 +122,9 @@ pub unsafe extern "C" fn heartbeat_get_marco( client: *mut HeartbeatClientHandle, interval: u64, new_interval: *mut u64, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if client.is_null() || new_interval.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let res: Result = RUNTIME.block_on(async move { let client_ref = unsafe { &mut (*client).0 }; @@ -134,9 +133,9 @@ pub unsafe extern "C" fn heartbeat_get_marco( match res { Ok(n) => { unsafe { *new_interval = n }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } diff --git a/ffi/src/installation_proxy.rs b/ffi/src/installation_proxy.rs index 42c50dc..e3c4c65 100644 --- a/ffi/src/installation_proxy.rs +++ b/ffi/src/installation_proxy.rs @@ -1,13 +1,15 @@ // Jackson Coxson -use std::ffi::c_void; +use std::{ffi::c_void, ptr::null_mut}; use idevice::{ IdeviceError, IdeviceService, installation_proxy::InstallationProxyClient, provider::IdeviceProvider, }; -use crate::{IdeviceErrorCode, IdeviceHandle, RUNTIME, provider::IdeviceProviderHandle, util}; +use crate::{ + IdeviceFfiError, IdeviceHandle, RUNTIME, ffi_err, provider::IdeviceProviderHandle, util, +}; pub struct InstallationProxyClientHandle(pub InstallationProxyClient); @@ -18,7 +20,7 @@ pub struct InstallationProxyClientHandle(pub InstallationProxyClient); /// * [`client`] - On success, will be set to point to a newly allocated InstallationProxyClient handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `provider` must be a valid pointer to a handle allocated by this library @@ -27,10 +29,10 @@ pub struct InstallationProxyClientHandle(pub InstallationProxyClient); pub unsafe extern "C" fn installation_proxy_connect_tcp( provider: *mut IdeviceProviderHandle, client: *mut *mut InstallationProxyClientHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if provider.is_null() || client.is_null() { log::error!("Null pointer provided"); - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let res: Result = RUNTIME.block_on(async move { @@ -42,9 +44,9 @@ pub unsafe extern "C" fn installation_proxy_connect_tcp( Ok(r) => { let boxed = Box::new(InstallationProxyClientHandle(r)); unsafe { *client = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -55,7 +57,7 @@ pub unsafe extern "C" fn installation_proxy_connect_tcp( /// * [`client`] - On success, will be set to point to a newly allocated InstallationProxyClient handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `socket` must be a valid pointer to a handle allocated by this library. The socket is consumed, @@ -65,15 +67,15 @@ pub unsafe extern "C" fn installation_proxy_connect_tcp( pub unsafe extern "C" fn installation_proxy_new( socket: *mut IdeviceHandle, client: *mut *mut InstallationProxyClientHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if socket.is_null() || client.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let socket = unsafe { Box::from_raw(socket) }.0; let r = InstallationProxyClient::new(socket); let boxed = Box::new(InstallationProxyClientHandle(r)); unsafe { *client = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } /// Gets installed apps on the device @@ -85,7 +87,7 @@ pub unsafe extern "C" fn installation_proxy_new( /// * [`out_result`] - On success, will be set to point to a newly allocated array of PlistRef /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` must be a valid pointer to a handle allocated by this library @@ -98,10 +100,10 @@ pub unsafe extern "C" fn installation_proxy_get_apps( bundle_identifiers_len: libc::size_t, out_result: *mut *mut c_void, out_result_len: *mut libc::size_t, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if client.is_null() || out_result.is_null() || out_result_len.is_null() { log::error!("Invalid arguments: {client:?}, {out_result:?}"); - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let client = unsafe { &mut *client }; @@ -148,9 +150,9 @@ pub unsafe extern "C" fn installation_proxy_get_apps( *out_result = ptr as *mut c_void; *out_result_len = len; } - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -180,7 +182,7 @@ pub unsafe extern "C" fn installation_proxy_client_free( /// * [`options`] - Optional installation options as a plist dictionary (can be NULL) /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` must be a valid pointer to a handle allocated by this library @@ -191,9 +193,9 @@ pub unsafe extern "C" fn installation_proxy_install( client: *mut InstallationProxyClientHandle, package_path: *const libc::c_char, options: *mut c_void, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if client.is_null() || package_path.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let package_path = unsafe { std::ffi::CStr::from_ptr(package_path) } @@ -213,8 +215,8 @@ pub unsafe extern "C" fn installation_proxy_install( }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } @@ -228,7 +230,7 @@ pub unsafe extern "C" fn installation_proxy_install( /// * [`context`] - User context to pass to callback /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` must be a valid pointer to a handle allocated by this library @@ -241,9 +243,9 @@ pub unsafe extern "C" fn installation_proxy_install_with_callback( options: *mut c_void, callback: extern "C" fn(progress: u64, context: *mut c_void), context: *mut c_void, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if client.is_null() || package_path.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let package_path = unsafe { std::ffi::CStr::from_ptr(package_path) } @@ -267,8 +269,8 @@ pub unsafe extern "C" fn installation_proxy_install_with_callback( }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } @@ -280,7 +282,7 @@ pub unsafe extern "C" fn installation_proxy_install_with_callback( /// * [`options`] - Optional upgrade options as a plist dictionary (can be NULL) /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` must be a valid pointer to a handle allocated by this library @@ -291,9 +293,9 @@ pub unsafe extern "C" fn installation_proxy_upgrade( client: *mut InstallationProxyClientHandle, package_path: *const libc::c_char, options: *mut c_void, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if client.is_null() || package_path.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let package_path = unsafe { std::ffi::CStr::from_ptr(package_path) } @@ -313,8 +315,8 @@ pub unsafe extern "C" fn installation_proxy_upgrade( }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } @@ -328,7 +330,7 @@ pub unsafe extern "C" fn installation_proxy_upgrade( /// * [`context`] - User context to pass to callback /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` must be a valid pointer to a handle allocated by this library @@ -341,9 +343,9 @@ pub unsafe extern "C" fn installation_proxy_upgrade_with_callback( options: *mut c_void, callback: extern "C" fn(progress: u64, context: *mut c_void), context: *mut c_void, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if client.is_null() || package_path.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let package_path = unsafe { std::ffi::CStr::from_ptr(package_path) } @@ -367,8 +369,8 @@ pub unsafe extern "C" fn installation_proxy_upgrade_with_callback( }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } @@ -380,7 +382,7 @@ pub unsafe extern "C" fn installation_proxy_upgrade_with_callback( /// * [`options`] - Optional uninstall options as a plist dictionary (can be NULL) /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` must be a valid pointer to a handle allocated by this library @@ -391,9 +393,9 @@ pub unsafe extern "C" fn installation_proxy_uninstall( client: *mut InstallationProxyClientHandle, bundle_id: *const libc::c_char, options: *mut c_void, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if client.is_null() || bundle_id.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let bundle_id = unsafe { std::ffi::CStr::from_ptr(bundle_id) } @@ -413,8 +415,8 @@ pub unsafe extern "C" fn installation_proxy_uninstall( }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } @@ -428,7 +430,7 @@ pub unsafe extern "C" fn installation_proxy_uninstall( /// * [`context`] - User context to pass to callback /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` must be a valid pointer to a handle allocated by this library @@ -441,9 +443,9 @@ pub unsafe extern "C" fn installation_proxy_uninstall_with_callback( options: *mut c_void, callback: extern "C" fn(progress: u64, context: *mut c_void), context: *mut c_void, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if client.is_null() || bundle_id.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let bundle_id = unsafe { std::ffi::CStr::from_ptr(bundle_id) } @@ -467,8 +469,8 @@ pub unsafe extern "C" fn installation_proxy_uninstall_with_callback( }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } @@ -482,7 +484,7 @@ pub unsafe extern "C" fn installation_proxy_uninstall_with_callback( /// * [`out_result`] - Will be set to true if all capabilities are supported, false otherwise /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` must be a valid pointer to a handle allocated by this library @@ -496,9 +498,9 @@ pub unsafe extern "C" fn installation_proxy_check_capabilities_match( capabilities_len: libc::size_t, options: *mut c_void, out_result: *mut bool, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if client.is_null() || out_result.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let capabilities = if capabilities.is_null() { @@ -526,9 +528,9 @@ pub unsafe extern "C" fn installation_proxy_check_capabilities_match( match res { Ok(result) => { unsafe { *out_result = result }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -541,7 +543,7 @@ pub unsafe extern "C" fn installation_proxy_check_capabilities_match( /// * [`out_result_len`] - Will be set to the length of the result array /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` must be a valid pointer to a handle allocated by this library @@ -554,9 +556,9 @@ pub unsafe extern "C" fn installation_proxy_browse( options: *mut c_void, out_result: *mut *mut c_void, out_result_len: *mut libc::size_t, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if client.is_null() || out_result.is_null() || out_result_len.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let options = if options.is_null() { @@ -583,8 +585,8 @@ pub unsafe extern "C" fn installation_proxy_browse( *out_result = ptr as *mut c_void; *out_result_len = len; } - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } diff --git a/ffi/src/lib.rs b/ffi/src/lib.rs index f7ce0a2..8d23831 100644 --- a/ffi/src/lib.rs +++ b/ffi/src/lib.rs @@ -46,7 +46,10 @@ pub use pairing_file::*; use idevice::{Idevice, IdeviceSocket, ReadWrite}; use once_cell::sync::Lazy; -use std::ffi::{CStr, CString, c_char}; +use std::{ + ffi::{CStr, CString, c_char}, + ptr::null_mut, +}; use tokio::runtime::{self, Runtime}; static RUNTIME: Lazy = Lazy::new(|| { @@ -80,7 +83,7 @@ struct sockaddr; /// * [`idevice`] - On success, will be set to point to a newly allocated Idevice handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `label` must be a valid null-terminated C string @@ -90,9 +93,9 @@ pub unsafe extern "C" fn idevice_new( socket: *mut IdeviceSocketHandle, label: *const c_char, idevice: *mut *mut IdeviceHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if socket.is_null() || label.is_null() || idevice.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } // Get socket ownership @@ -101,7 +104,7 @@ pub unsafe extern "C" fn idevice_new( // Convert C string to Rust string let c_str = match unsafe { CStr::from_ptr(label).to_str() } { Ok(s) => s, - Err(_) => return IdeviceErrorCode::InvalidString, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidString), }; // Create new Idevice instance @@ -109,7 +112,7 @@ pub unsafe extern "C" fn idevice_new( let boxed = Box::new(IdeviceHandle(dev)); unsafe { *idevice = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } /// Creates a new Idevice connection @@ -121,7 +124,7 @@ pub unsafe extern "C" fn idevice_new( /// * [`idevice`] - On success, will be set to point to a newly allocated Idevice handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `addr` must be a valid sockaddr @@ -133,21 +136,21 @@ pub unsafe extern "C" fn idevice_new_tcp_socket( addr_len: libc::socklen_t, label: *const c_char, idevice: *mut *mut IdeviceHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if addr.is_null() { log::error!("socket addr null pointer"); - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } // Convert C string to Rust string let label = match unsafe { CStr::from_ptr(label).to_str() } { Ok(s) => s, - Err(_) => return IdeviceErrorCode::InvalidArg, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg), }; let addr = match util::c_socket_to_rust(addr, addr_len) { Ok(a) => a, - Err(e) => return e, + Err(e) => return ffi_err!(e), }; let device: Result = RUNTIME.block_on(async move { @@ -161,9 +164,9 @@ pub unsafe extern "C" fn idevice_new_tcp_socket( Ok(dev) => { let boxed = Box::new(IdeviceHandle(dev)); unsafe { *idevice = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -174,7 +177,7 @@ pub unsafe extern "C" fn idevice_new_tcp_socket( /// * [`device_type`] - On success, will be set to point to a newly allocated string containing the device type /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `idevice` must be a valid, non-null pointer to an Idevice handle @@ -183,9 +186,9 @@ pub unsafe extern "C" fn idevice_new_tcp_socket( pub unsafe extern "C" fn idevice_get_type( idevice: *mut IdeviceHandle, device_type: *mut *mut c_char, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if idevice.is_null() || device_type.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } // Get the Idevice reference @@ -198,11 +201,11 @@ pub unsafe extern "C" fn idevice_get_type( Ok(type_str) => match CString::new(type_str) { Ok(c_string) => { unsafe { *device_type = c_string.into_raw() }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(_) => IdeviceErrorCode::InvalidString, + Err(_) => ffi_err!(IdeviceError::FfiInvalidString), }, - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -212,14 +215,14 @@ pub unsafe extern "C" fn idevice_get_type( /// * [`idevice`] - The Idevice handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `idevice` must be a valid, non-null pointer to an Idevice handle #[unsafe(no_mangle)] -pub unsafe extern "C" fn idevice_rsd_checkin(idevice: *mut IdeviceHandle) -> IdeviceErrorCode { +pub unsafe extern "C" fn idevice_rsd_checkin(idevice: *mut IdeviceHandle) -> *mut IdeviceFfiError { if idevice.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } // Get the Idevice reference @@ -229,8 +232,8 @@ pub unsafe extern "C" fn idevice_rsd_checkin(idevice: *mut IdeviceHandle) -> Ide let result = RUNTIME.block_on(async { dev.rsd_checkin().await }); match result { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } @@ -241,7 +244,7 @@ pub unsafe extern "C" fn idevice_rsd_checkin(idevice: *mut IdeviceHandle) -> Ide /// * [`pairing_file`] - The pairing file to use for TLS /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `idevice` must be a valid, non-null pointer to an Idevice handle @@ -250,9 +253,9 @@ pub unsafe extern "C" fn idevice_rsd_checkin(idevice: *mut IdeviceHandle) -> Ide pub unsafe extern "C" fn idevice_start_session( idevice: *mut IdeviceHandle, pairing_file: *const IdevicePairingFile, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if idevice.is_null() || pairing_file.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } // Get the Idevice reference @@ -265,8 +268,8 @@ pub unsafe extern "C" fn idevice_start_session( let result = RUNTIME.block_on(async { dev.start_session(pf).await }); match result { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } diff --git a/ffi/src/location_simulation.rs b/ffi/src/location_simulation.rs index e4ca9fe..841840a 100644 --- a/ffi/src/location_simulation.rs +++ b/ffi/src/location_simulation.rs @@ -1,8 +1,10 @@ // Jackson Coxson +use std::ptr::null_mut; + use idevice::{ReadWrite, dvt::location_simulation::LocationSimulationClient}; -use crate::{IdeviceErrorCode, RUNTIME, remote_server::RemoteServerHandle}; +use crate::{IdeviceFfiError, RUNTIME, ffi_err, remote_server::RemoteServerHandle}; /// Opaque handle to a ProcessControlClient pub struct LocationSimulationHandle<'a>(pub LocationSimulationClient<'a, Box>); @@ -14,7 +16,7 @@ pub struct LocationSimulationHandle<'a>(pub LocationSimulationClient<'a, Box(pub LocationSimulationClient<'a, Box, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if server.is_null() || handle.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let server = unsafe { &mut (*server).0 }; @@ -35,9 +37,9 @@ pub unsafe extern "C" fn location_simulation_new( Ok(client) => { let boxed = Box::new(LocationSimulationHandle(client)); unsafe { *handle = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -61,24 +63,24 @@ pub unsafe extern "C" fn location_simulation_free(handle: *mut LocationSimulatio /// * [`handle`] - The LocationSimulation handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// All pointers must be valid or NULL where appropriate #[unsafe(no_mangle)] pub unsafe extern "C" fn location_simulation_clear( handle: *mut LocationSimulationHandle<'static>, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if handle.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let client = unsafe { &mut (*handle).0 }; let res = RUNTIME.block_on(async move { client.clear().await }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } @@ -90,7 +92,7 @@ pub unsafe extern "C" fn location_simulation_clear( /// * [`longitude`] - The longitude to set /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// All pointers must be valid or NULL where appropriate @@ -99,16 +101,16 @@ pub unsafe extern "C" fn location_simulation_set( handle: *mut LocationSimulationHandle<'static>, latitude: f64, longitude: f64, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if handle.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let client = unsafe { &mut (*handle).0 }; let res = RUNTIME.block_on(async move { client.set(latitude, longitude).await }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } diff --git a/ffi/src/lockdown.rs b/ffi/src/lockdown.rs index 66aefe9..baaf9ab 100644 --- a/ffi/src/lockdown.rs +++ b/ffi/src/lockdown.rs @@ -1,11 +1,12 @@ // Jackson Coxson -use std::ffi::c_void; +use std::{ffi::c_void, ptr::null_mut}; use idevice::{IdeviceError, IdeviceService, lockdown::LockdownClient, provider::IdeviceProvider}; use crate::{ - IdeviceErrorCode, IdeviceHandle, IdevicePairingFile, RUNTIME, provider::IdeviceProviderHandle, + IdeviceFfiError, IdeviceHandle, IdevicePairingFile, RUNTIME, ffi_err, + provider::IdeviceProviderHandle, }; pub struct LockdowndClientHandle(pub LockdownClient); @@ -17,7 +18,7 @@ pub struct LockdowndClientHandle(pub LockdownClient); /// * [`client`] - On success, will be set to point to a newly allocated LockdowndClient handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `provider` must be a valid pointer to a handle allocated by this library @@ -26,10 +27,10 @@ pub struct LockdowndClientHandle(pub LockdownClient); pub unsafe extern "C" fn lockdownd_connect( provider: *mut IdeviceProviderHandle, client: *mut *mut LockdowndClientHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if provider.is_null() || client.is_null() { log::error!("Null pointer provided"); - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let res: Result = RUNTIME.block_on(async move { @@ -41,11 +42,11 @@ pub unsafe extern "C" fn lockdownd_connect( Ok(r) => { let boxed = Box::new(LockdowndClientHandle(r)); unsafe { *client = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } Err(e) => { let _ = unsafe { Box::from_raw(provider) }; - e.into() + ffi_err!(e) } } } @@ -57,7 +58,7 @@ pub unsafe extern "C" fn lockdownd_connect( /// * [`client`] - On success, will be set to point to a newly allocated LockdowndClient handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `socket` must be a valid pointer to a handle allocated by this library. The socket is consumed, @@ -67,15 +68,15 @@ pub unsafe extern "C" fn lockdownd_connect( pub unsafe extern "C" fn lockdownd_new( socket: *mut IdeviceHandle, client: *mut *mut LockdowndClientHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if socket.is_null() || client.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let socket = unsafe { Box::from_raw(socket) }.0; let r = LockdownClient::new(socket); let boxed = Box::new(LockdowndClientHandle(r)); unsafe { *client = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } /// Starts a session with lockdownd @@ -85,7 +86,7 @@ pub unsafe extern "C" fn lockdownd_new( /// * `pairing_file` - An IdevicePairingFile alocated by this library /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` must be a valid pointer to a handle allocated by this library @@ -94,7 +95,7 @@ pub unsafe extern "C" fn lockdownd_new( pub unsafe extern "C" fn lockdownd_start_session( client: *mut LockdowndClientHandle, pairing_file: *mut IdevicePairingFile, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { let res: Result<(), IdeviceError> = RUNTIME.block_on(async move { let client_ref = unsafe { &mut (*client).0 }; let pairing_file_ref = unsafe { &(*pairing_file).0 }; @@ -103,8 +104,8 @@ pub unsafe extern "C" fn lockdownd_start_session( }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } @@ -117,7 +118,7 @@ pub unsafe extern "C" fn lockdownd_start_session( /// * `ssl` - Pointer to store whether SSL should be enabled /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` must be a valid pointer to a handle allocated by this library @@ -129,9 +130,9 @@ pub unsafe extern "C" fn lockdownd_start_service( identifier: *const libc::c_char, port: *mut u16, ssl: *mut bool, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if identifier.is_null() || port.is_null() || ssl.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let identifier = unsafe { std::ffi::CStr::from_ptr(identifier) } @@ -149,9 +150,9 @@ pub unsafe extern "C" fn lockdownd_start_service( *port = p; *ssl = s; } - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -164,7 +165,7 @@ pub unsafe extern "C" fn lockdownd_start_service( /// * `out_plist` - Pointer to store the returned plist value /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` must be a valid pointer to a handle allocated by this library @@ -176,9 +177,9 @@ pub unsafe extern "C" fn lockdownd_get_value( key: *const libc::c_char, domain: *const libc::c_char, out_plist: *mut *mut c_void, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if key.is_null() || out_plist.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let value = unsafe { std::ffi::CStr::from_ptr(key) } @@ -205,9 +206,9 @@ pub unsafe extern "C" fn lockdownd_get_value( unsafe { *out_plist = crate::util::plist_to_libplist(&value); } - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -218,7 +219,7 @@ pub unsafe extern "C" fn lockdownd_get_value( /// * `out_plist` - Pointer to store the returned plist dictionary /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` must be a valid pointer to a handle allocated by this library @@ -227,9 +228,9 @@ pub unsafe extern "C" fn lockdownd_get_value( pub unsafe extern "C" fn lockdownd_get_all_values( client: *mut LockdowndClientHandle, out_plist: *mut *mut c_void, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if out_plist.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let res: Result = RUNTIME.block_on(async move { @@ -242,9 +243,9 @@ pub unsafe extern "C" fn lockdownd_get_all_values( unsafe { *out_plist = crate::util::plist_to_libplist(&plist::Value::Dictionary(dict)); } - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } diff --git a/ffi/src/misagent.rs b/ffi/src/misagent.rs index 704d58b..4028a8e 100644 --- a/ffi/src/misagent.rs +++ b/ffi/src/misagent.rs @@ -2,9 +2,11 @@ //! //! Provides C-compatible bindings for interacting with the misagent service on iOS devices. +use std::ptr::null_mut; + use idevice::{IdeviceError, IdeviceService, misagent::MisagentClient, provider::IdeviceProvider}; -use crate::{IdeviceErrorCode, RUNTIME, provider::IdeviceProviderHandle}; +use crate::{IdeviceFfiError, RUNTIME, ffi_err, provider::IdeviceProviderHandle}; pub struct MisagentClientHandle(pub MisagentClient); @@ -15,7 +17,7 @@ pub struct MisagentClientHandle(pub MisagentClient); /// * [`client`] - On success, will be set to point to a newly allocated MisagentClient handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `provider` must be a valid pointer to a handle allocated by this library @@ -24,10 +26,10 @@ pub struct MisagentClientHandle(pub MisagentClient); pub unsafe extern "C" fn misagent_connect( provider: *mut IdeviceProviderHandle, client: *mut *mut MisagentClientHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if provider.is_null() || client.is_null() { log::error!("Null pointer provided"); - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let res: Result = RUNTIME.block_on(async move { @@ -39,9 +41,9 @@ pub unsafe extern "C" fn misagent_connect( Ok(r) => { let boxed = Box::new(MisagentClientHandle(r)); unsafe { *client = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -53,7 +55,7 @@ pub unsafe extern "C" fn misagent_connect( /// * [`profile_len`] - Length of the profile data /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` must be a valid pointer to a handle allocated by this library @@ -63,9 +65,9 @@ pub unsafe extern "C" fn misagent_install( client: *mut MisagentClientHandle, profile_data: *const u8, profile_len: libc::size_t, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if client.is_null() || profile_data.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let profile = unsafe { std::slice::from_raw_parts(profile_data, profile_len) }.to_vec(); @@ -73,8 +75,8 @@ pub unsafe extern "C" fn misagent_install( let res = RUNTIME.block_on(async { unsafe { &mut *client }.0.install(profile).await }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } @@ -85,7 +87,7 @@ pub unsafe extern "C" fn misagent_install( /// * [`profile_id`] - The UUID of the profile to remove (C string) /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` must be a valid pointer to a handle allocated by this library @@ -94,9 +96,9 @@ pub unsafe extern "C" fn misagent_install( pub unsafe extern "C" fn misagent_remove( client: *mut MisagentClientHandle, profile_id: *const libc::c_char, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if client.is_null() || profile_id.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let id = unsafe { std::ffi::CStr::from_ptr(profile_id) } @@ -106,8 +108,8 @@ pub unsafe extern "C" fn misagent_remove( let res = RUNTIME.block_on(async { unsafe { &mut *client }.0.remove(&id).await }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } @@ -119,7 +121,7 @@ pub unsafe extern "C" fn misagent_remove( /// * [`out_profiles_len`] - On success, will be set to the number of profiles /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` must be a valid pointer to a handle allocated by this library @@ -131,13 +133,13 @@ pub unsafe extern "C" fn misagent_copy_all( out_profiles: *mut *mut *mut u8, out_profiles_len: *mut *mut libc::size_t, out_count: *mut libc::size_t, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if client.is_null() || out_profiles.is_null() || out_profiles_len.is_null() || out_count.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let res: Result>, IdeviceError> = @@ -167,9 +169,9 @@ pub unsafe extern "C" fn misagent_copy_all( *out_count = count; } - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } diff --git a/ffi/src/mobile_image_mounter.rs b/ffi/src/mobile_image_mounter.rs index c20839c..9a4c797 100644 --- a/ffi/src/mobile_image_mounter.rs +++ b/ffi/src/mobile_image_mounter.rs @@ -1,13 +1,15 @@ // Jackson Coxson -use std::ffi::c_void; +use std::{ffi::c_void, ptr::null_mut}; use idevice::{ IdeviceError, IdeviceService, mobile_image_mounter::ImageMounter, provider::IdeviceProvider, }; use plist::Value; -use crate::{IdeviceErrorCode, IdeviceHandle, RUNTIME, provider::IdeviceProviderHandle, util}; +use crate::{ + IdeviceFfiError, IdeviceHandle, RUNTIME, ffi_err, provider::IdeviceProviderHandle, util, +}; pub struct ImageMounterHandle(pub ImageMounter); @@ -18,7 +20,7 @@ pub struct ImageMounterHandle(pub ImageMounter); /// * [`client`] - On success, will be set to point to a newly allocated ImageMounter handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `provider` must be a valid pointer to a handle allocated by this library @@ -27,10 +29,10 @@ pub struct ImageMounterHandle(pub ImageMounter); pub unsafe extern "C" fn image_mounter_connect( provider: *mut IdeviceProviderHandle, client: *mut *mut ImageMounterHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if provider.is_null() || client.is_null() { log::error!("Null pointer provided"); - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let res: Result = RUNTIME.block_on(async move { @@ -42,11 +44,11 @@ pub unsafe extern "C" fn image_mounter_connect( Ok(r) => { let boxed = Box::new(ImageMounterHandle(r)); unsafe { *client = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } Err(e) => { let _ = unsafe { Box::from_raw(provider) }; - e.into() + ffi_err!(e) } } } @@ -58,7 +60,7 @@ pub unsafe extern "C" fn image_mounter_connect( /// * [`client`] - On success, will be set to point to a newly allocated ImageMounter handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `socket` must be a valid pointer to a handle allocated by this library @@ -67,15 +69,15 @@ pub unsafe extern "C" fn image_mounter_connect( pub unsafe extern "C" fn image_mounter_new( socket: *mut IdeviceHandle, client: *mut *mut ImageMounterHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if socket.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let socket = unsafe { Box::from_raw(socket) }.0; let r = ImageMounter::new(socket); let boxed = Box::new(ImageMounterHandle(r)); unsafe { *client = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } /// Frees an ImageMounter handle @@ -102,7 +104,7 @@ pub unsafe extern "C" fn image_mounter_free(handle: *mut ImageMounterHandle) { /// * [`devices_len`] - Will be set to the number of devices copied /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` must be a valid pointer to a handle allocated by this library @@ -112,7 +114,7 @@ pub unsafe extern "C" fn image_mounter_copy_devices( client: *mut ImageMounterHandle, devices: *mut *mut c_void, devices_len: *mut libc::size_t, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { let res: Result, IdeviceError> = RUNTIME.block_on(async move { let client_ref = unsafe { &mut (*client).0 }; client_ref.copy_devices().await @@ -132,9 +134,9 @@ pub unsafe extern "C" fn image_mounter_copy_devices( *devices = ptr as *mut c_void; *devices_len = len; } - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -147,7 +149,7 @@ pub unsafe extern "C" fn image_mounter_copy_devices( /// * [`signature_len`] - Will be set to the length of the signature data /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` must be a valid pointer to a handle allocated by this library @@ -159,15 +161,15 @@ pub unsafe extern "C" fn image_mounter_lookup_image( image_type: *const libc::c_char, signature: *mut *mut u8, signature_len: *mut libc::size_t, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if image_type.is_null() || signature.is_null() || signature_len.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let image_type_cstr = unsafe { std::ffi::CStr::from_ptr(image_type) }; let image_type = match image_type_cstr.to_str() { Ok(s) => s, - Err(_) => return IdeviceErrorCode::InvalidArg, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg), }; let res: Result, IdeviceError> = RUNTIME.block_on(async move { @@ -183,9 +185,9 @@ pub unsafe extern "C" fn image_mounter_lookup_image( *signature_len = boxed.len(); } std::mem::forget(boxed); - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -200,7 +202,7 @@ pub unsafe extern "C" fn image_mounter_lookup_image( /// * [`signature_len`] - Length of the signature data /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// All pointers must be valid and non-null @@ -213,15 +215,15 @@ pub unsafe extern "C" fn image_mounter_upload_image( image_len: libc::size_t, signature: *const u8, signature_len: libc::size_t, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if image_type.is_null() || image.is_null() || signature.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let image_type_cstr = unsafe { std::ffi::CStr::from_ptr(image_type) }; let image_type = match image_type_cstr.to_str() { Ok(s) => s, - Err(_) => return IdeviceErrorCode::InvalidArg, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg), }; let image_slice = unsafe { std::slice::from_raw_parts(image, image_len) }; @@ -235,8 +237,8 @@ pub unsafe extern "C" fn image_mounter_upload_image( }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } @@ -252,7 +254,7 @@ pub unsafe extern "C" fn image_mounter_upload_image( /// * [`info_plist`] - Pointer to info plist (optional) /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// All pointers must be valid (except optional ones which can be null) @@ -266,15 +268,15 @@ pub unsafe extern "C" fn image_mounter_mount_image( trust_cache: *const u8, trust_cache_len: libc::size_t, info_plist: *const c_void, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if image_type.is_null() || signature.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let image_type_cstr = unsafe { std::ffi::CStr::from_ptr(image_type) }; let image_type = match image_type_cstr.to_str() { Ok(s) => s, - Err(_) => return IdeviceErrorCode::InvalidArg, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg), }; let signature_slice = unsafe { std::slice::from_raw_parts(signature, signature_len) }; @@ -307,8 +309,8 @@ pub unsafe extern "C" fn image_mounter_mount_image( }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } @@ -319,7 +321,7 @@ pub unsafe extern "C" fn image_mounter_mount_image( /// * [`mount_path`] - The path where the image is mounted /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` must be a valid pointer to a handle allocated by this library @@ -328,15 +330,15 @@ pub unsafe extern "C" fn image_mounter_mount_image( pub unsafe extern "C" fn image_mounter_unmount_image( client: *mut ImageMounterHandle, mount_path: *const libc::c_char, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if mount_path.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let mount_path_cstr = unsafe { std::ffi::CStr::from_ptr(mount_path) }; let mount_path = match mount_path_cstr.to_str() { Ok(s) => s, - Err(_) => return IdeviceErrorCode::InvalidArg, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg), }; let res: Result<(), IdeviceError> = RUNTIME.block_on(async move { @@ -345,8 +347,8 @@ pub unsafe extern "C" fn image_mounter_unmount_image( }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } @@ -357,7 +359,7 @@ pub unsafe extern "C" fn image_mounter_unmount_image( /// * [`status`] - Will be set to the developer mode status (1 = enabled, 0 = disabled) /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` must be a valid pointer to a handle allocated by this library @@ -366,9 +368,9 @@ pub unsafe extern "C" fn image_mounter_unmount_image( pub unsafe extern "C" fn image_mounter_query_developer_mode_status( client: *mut ImageMounterHandle, status: *mut libc::c_int, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if status.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let res: Result = RUNTIME.block_on(async move { @@ -379,9 +381,9 @@ pub unsafe extern "C" fn image_mounter_query_developer_mode_status( match res { Ok(s) => { unsafe { *status = if s { 1 } else { 0 } }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -395,7 +397,7 @@ pub unsafe extern "C" fn image_mounter_query_developer_mode_status( /// * [`signature_len`] - Length of the signature data /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// All pointers must be valid and non-null @@ -406,9 +408,9 @@ pub unsafe extern "C" fn image_mounter_mount_developer( image_len: libc::size_t, signature: *const u8, signature_len: libc::size_t, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if image.is_null() || signature.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let image_slice = unsafe { std::slice::from_raw_parts(image, image_len) }; @@ -422,8 +424,8 @@ pub unsafe extern "C" fn image_mounter_mount_developer( }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } @@ -438,7 +440,7 @@ pub unsafe extern "C" fn image_mounter_mount_developer( /// * [`manifest_len`] - Will be set to the length of the manifest data /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// All pointers must be valid and non-null @@ -451,15 +453,15 @@ pub unsafe extern "C" fn image_mounter_query_personalization_manifest( signature_len: libc::size_t, manifest: *mut *mut u8, manifest_len: *mut libc::size_t, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if image_type.is_null() || signature.is_null() || manifest.is_null() || manifest_len.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let image_type_cstr = unsafe { std::ffi::CStr::from_ptr(image_type) }; let image_type = match image_type_cstr.to_str() { Ok(s) => s, - Err(_) => return IdeviceErrorCode::InvalidArg, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg), }; let signature_slice = unsafe { std::slice::from_raw_parts(signature, signature_len) }; @@ -479,9 +481,9 @@ pub unsafe extern "C" fn image_mounter_query_personalization_manifest( *manifest_len = boxed.len(); } std::mem::forget(boxed); - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -494,7 +496,7 @@ pub unsafe extern "C" fn image_mounter_query_personalization_manifest( /// * [`nonce_len`] - Will be set to the length of the nonce data /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client`, `nonce`, and `nonce_len` must be valid pointers @@ -505,16 +507,16 @@ pub unsafe extern "C" fn image_mounter_query_nonce( personalized_image_type: *const libc::c_char, nonce: *mut *mut u8, nonce_len: *mut libc::size_t, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if nonce.is_null() || nonce_len.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let image_type = if !personalized_image_type.is_null() { let image_type_cstr = unsafe { std::ffi::CStr::from_ptr(personalized_image_type) }; match image_type_cstr.to_str() { Ok(s) => Some(s.to_string()), - Err(_) => return IdeviceErrorCode::InvalidArg, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg), } } else { None @@ -533,9 +535,9 @@ pub unsafe extern "C" fn image_mounter_query_nonce( *nonce_len = boxed.len(); } std::mem::forget(boxed); - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -547,7 +549,7 @@ pub unsafe extern "C" fn image_mounter_query_nonce( /// * [`identifiers`] - Will be set to point to the identifiers plist on success /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` and `identifiers` must be valid pointers @@ -557,16 +559,16 @@ pub unsafe extern "C" fn image_mounter_query_personalization_identifiers( client: *mut ImageMounterHandle, image_type: *const libc::c_char, identifiers: *mut *mut c_void, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if identifiers.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let image_type = if !image_type.is_null() { let image_type_cstr = unsafe { std::ffi::CStr::from_ptr(image_type) }; match image_type_cstr.to_str() { Ok(s) => Some(s.to_string()), - Err(_) => return IdeviceErrorCode::InvalidArg, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg), } } else { None @@ -583,9 +585,9 @@ pub unsafe extern "C" fn image_mounter_query_personalization_identifiers( Ok(id) => { let plist = util::plist_to_libplist(&plist::Value::Dictionary(id)); unsafe { *identifiers = plist }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -595,22 +597,22 @@ pub unsafe extern "C" fn image_mounter_query_personalization_identifiers( /// * [`client`] - A valid ImageMounter handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` must be a valid pointer to a handle allocated by this library #[unsafe(no_mangle)] pub unsafe extern "C" fn image_mounter_roll_personalization_nonce( client: *mut ImageMounterHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { let res: Result<(), IdeviceError> = RUNTIME.block_on(async move { let client_ref = unsafe { &mut (*client).0 }; client_ref.roll_personalization_nonce().await }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } @@ -620,22 +622,22 @@ pub unsafe extern "C" fn image_mounter_roll_personalization_nonce( /// * [`client`] - A valid ImageMounter handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` must be a valid pointer to a handle allocated by this library #[unsafe(no_mangle)] pub unsafe extern "C" fn image_mounter_roll_cryptex_nonce( client: *mut ImageMounterHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { let res: Result<(), IdeviceError> = RUNTIME.block_on(async move { let client_ref = unsafe { &mut (*client).0 }; client_ref.roll_cryptex_nonce().await }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } @@ -654,7 +656,7 @@ pub unsafe extern "C" fn image_mounter_roll_cryptex_nonce( /// * [`unique_chip_id`] - The device's unique chip ID /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// All pointers must be valid (except optional ones which can be null) @@ -671,9 +673,9 @@ pub unsafe extern "C" fn image_mounter_mount_personalized( build_manifest_len: libc::size_t, info_plist: *const c_void, unique_chip_id: u64, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if provider.is_null() || image.is_null() || trust_cache.is_null() || build_manifest.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let image_slice = unsafe { std::slice::from_raw_parts(image, image_len) }; @@ -707,8 +709,8 @@ pub unsafe extern "C" fn image_mounter_mount_personalized( }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } @@ -729,7 +731,7 @@ pub unsafe extern "C" fn image_mounter_mount_personalized( /// * [`context`] - User context to pass to callback /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// All pointers must be valid (except optional ones which can be null) @@ -748,9 +750,9 @@ pub unsafe extern "C" fn image_mounter_mount_personalized_with_callback( unique_chip_id: u64, callback: extern "C" fn(progress: libc::size_t, total: libc::size_t, context: *mut c_void), context: *mut c_void, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if provider.is_null() || image.is_null() || trust_cache.is_null() || build_manifest.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let image_slice = unsafe { std::slice::from_raw_parts(image, image_len) }; @@ -791,7 +793,7 @@ pub unsafe extern "C" fn image_mounter_mount_personalized_with_callback( }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } diff --git a/ffi/src/os_trace_relay.rs b/ffi/src/os_trace_relay.rs index 9aaa747..0e1d8e0 100644 --- a/ffi/src/os_trace_relay.rs +++ b/ffi/src/os_trace_relay.rs @@ -1,11 +1,11 @@ -use std::ffi::CString; use std::os::raw::c_char; +use std::{ffi::CString, ptr::null_mut}; use idevice::{ IdeviceError, IdeviceService, os_trace_relay::OsTraceRelayClient, provider::IdeviceProvider, }; -use crate::{IdeviceErrorCode, RUNTIME, provider::IdeviceProviderHandle}; +use crate::{IdeviceFfiError, RUNTIME, ffi_err, provider::IdeviceProviderHandle}; pub struct OsTraceRelayClientHandle(pub OsTraceRelayClient); pub struct OsTraceRelayReceiverHandle(pub idevice::os_trace_relay::OsTraceRelayReceiver); @@ -36,7 +36,7 @@ pub struct SyslogLabel { /// * [`client`] - A pointer where the handle will be allocated /// /// # Returns -/// 0 for success, an IdeviceErrorCode otherwise +/// 0 for success, an *mut IdeviceFfiError otherwise /// /// # Safety /// None of the arguments can be null. Provider must be allocated by this library. @@ -44,10 +44,10 @@ pub struct SyslogLabel { pub unsafe extern "C" fn os_trace_relay_connect( provider: *mut IdeviceProviderHandle, client: *mut *mut OsTraceRelayClientHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if provider.is_null() { log::error!("Null pointer provided"); - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let res: Result = RUNTIME.block_on(async move { @@ -59,11 +59,11 @@ pub unsafe extern "C" fn os_trace_relay_connect( Ok(c) => { let boxed = Box::new(OsTraceRelayClientHandle(c)); unsafe { *client = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } Err(e) => { let _ = unsafe { Box::from_raw(provider) }; - e.into() + ffi_err!(e) } } } @@ -91,7 +91,7 @@ pub unsafe extern "C" fn os_trace_relay_free(handle: *mut OsTraceRelayClientHand /// * [`pid`] - An optional pointer to a PID to get logs for. May be null. /// /// # Returns -/// 0 for success, an IdeviceErrorCode otherwise +/// 0 for success, an *mut IdeviceFfiError otherwise /// /// # Safety /// The handle must be allocated by this library. It is consumed, and must never be used again. @@ -100,10 +100,10 @@ pub unsafe extern "C" fn os_trace_relay_start_trace( client: *mut OsTraceRelayClientHandle, receiver: *mut *mut OsTraceRelayReceiverHandle, pid: *const u32, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if receiver.is_null() || client.is_null() { log::error!("Null pointer provided"); - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let pid_option = if pid.is_null() { @@ -121,9 +121,9 @@ pub unsafe extern "C" fn os_trace_relay_start_trace( let boxed = Box::new(OsTraceRelayReceiverHandle(relay)); unsafe { *receiver = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -149,7 +149,7 @@ pub unsafe extern "C" fn os_trace_relay_receiver_free(handle: *mut OsTraceRelayR /// * [`list`] - A pointer to allocate a list of PIDs to /// /// # Returns -/// 0 for success, an IdeviceErrorCode otherwise +/// 0 for success, an *mut IdeviceFfiError otherwise /// /// # Safety /// The handle must be allocated by this library. @@ -157,15 +157,15 @@ pub unsafe extern "C" fn os_trace_relay_receiver_free(handle: *mut OsTraceRelayR pub unsafe extern "C" fn os_trace_relay_get_pid_list( client: *mut OsTraceRelayClientHandle, list: *mut *mut Vec, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { let res = RUNTIME.block_on(async { unsafe { &mut *client }.0.get_pid_list().await }); match res { Ok(r) => { unsafe { *list = Box::into_raw(Box::new(r)) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -176,7 +176,7 @@ pub unsafe extern "C" fn os_trace_relay_get_pid_list( /// * [`log`] - A pointer to allocate the new log /// /// # Returns -/// 0 for success, an IdeviceErrorCode otherwise +/// 0 for success, an *mut IdeviceFfiError otherwise /// /// # Safety /// The handle must be allocated by this library. @@ -184,10 +184,10 @@ pub unsafe extern "C" fn os_trace_relay_get_pid_list( pub unsafe extern "C" fn os_trace_relay_next( client: *mut OsTraceRelayReceiverHandle, log: *mut *mut OsTraceLog, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if client.is_null() { log::error!("Null pointer provided"); - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let res = RUNTIME.block_on(async { unsafe { &mut *client }.0.next().await }); @@ -212,9 +212,9 @@ pub unsafe extern "C" fn os_trace_relay_next( }); unsafe { *log = Box::into_raw(log_entry) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -224,7 +224,7 @@ pub unsafe extern "C" fn os_trace_relay_next( /// * [`log`] - The log to free /// /// # Returns -/// 0 for success, an IdeviceErrorCode otherwise +/// 0 for success, an *mut IdeviceFfiError otherwise /// /// # Safety /// The log must be allocated by this library. It is consumed and must not be used again. @@ -259,4 +259,3 @@ pub unsafe extern "C" fn os_trace_relay_free_log(log: *mut OsTraceLog) { } } } - diff --git a/ffi/src/pairing_file.rs b/ffi/src/pairing_file.rs index c42ecef..a221e14 100644 --- a/ffi/src/pairing_file.rs +++ b/ffi/src/pairing_file.rs @@ -1,9 +1,12 @@ // Jackson Coxson use idevice::pairing_file::PairingFile; -use std::ffi::{CStr, c_char}; +use std::{ + ffi::{CStr, c_char}, + ptr::null_mut, +}; -use crate::IdeviceErrorCode; +use crate::{IdeviceFfiError, ffi_err}; /// Opaque C-compatible handle to a PairingFile pub struct IdevicePairingFile(pub PairingFile); @@ -15,7 +18,7 @@ pub struct IdevicePairingFile(pub PairingFile); /// * [`pairing_file`] - On success, will be set to point to a newly allocated pairing file instance /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `path` must be a valid null-terminated C string @@ -24,15 +27,15 @@ pub struct IdevicePairingFile(pub PairingFile); pub unsafe extern "C" fn idevice_pairing_file_read( path: *const c_char, pairing_file: *mut *mut IdevicePairingFile, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if path.is_null() || pairing_file.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } // Convert C string to Rust path let c_str = match unsafe { CStr::from_ptr(path) }.to_str() { Ok(s) => s, - Err(_) => return IdeviceErrorCode::InvalidArg, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg), }; // Read the pairing file @@ -42,9 +45,9 @@ pub unsafe extern "C" fn idevice_pairing_file_read( unsafe { *pairing_file = Box::into_raw(boxed); } - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -56,7 +59,7 @@ pub unsafe extern "C" fn idevice_pairing_file_read( /// * [`pairing_file`] - On success, will be set to point to a newly allocated pairing file instance /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `data` must be a valid pointer to a buffer of at least `size` bytes @@ -66,9 +69,9 @@ pub unsafe extern "C" fn idevice_pairing_file_from_bytes( data: *const u8, size: usize, pairing_file: *mut *mut IdevicePairingFile, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if data.is_null() || pairing_file.is_null() || size == 0 { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } // Convert to Rust slice @@ -79,9 +82,9 @@ pub unsafe extern "C" fn idevice_pairing_file_from_bytes( Ok(pf) => { let boxed = Box::new(IdevicePairingFile(pf)); unsafe { *pairing_file = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -93,7 +96,7 @@ pub unsafe extern "C" fn idevice_pairing_file_from_bytes( /// * [`size`] - On success, will be set to the size of the allocated buffer /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `pairing_file` must be a valid, non-null pointer to a pairing file instance @@ -104,9 +107,9 @@ pub unsafe extern "C" fn idevice_pairing_file_serialize( pairing_file: *const IdevicePairingFile, data: *mut *mut u8, size: *mut usize, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if pairing_file.is_null() || data.is_null() || size.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } // Get the pairing file @@ -119,9 +122,9 @@ pub unsafe extern "C" fn idevice_pairing_file_serialize( let buffer_ptr = Box::into_raw(buffer.into_boxed_slice()) as *mut u8; unsafe { *data = buffer_ptr }; unsafe { *size = buffer_size }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } diff --git a/ffi/src/process_control.rs b/ffi/src/process_control.rs index ef69ad0..2ed84b9 100644 --- a/ffi/src/process_control.rs +++ b/ffi/src/process_control.rs @@ -1,11 +1,14 @@ // Jackson Coxson -use std::ffi::{CStr, c_char}; +use std::{ + ffi::{CStr, c_char}, + ptr::null_mut, +}; use idevice::{ReadWrite, dvt::process_control::ProcessControlClient}; use plist::{Dictionary, Value}; -use crate::{IdeviceErrorCode, RUNTIME, remote_server::RemoteServerHandle}; +use crate::{IdeviceFfiError, RUNTIME, ffi_err, remote_server::RemoteServerHandle}; /// Opaque handle to a ProcessControlClient pub struct ProcessControlHandle<'a>(pub ProcessControlClient<'a, Box>); @@ -17,7 +20,7 @@ pub struct ProcessControlHandle<'a>(pub ProcessControlClient<'a, Box(pub ProcessControlClient<'a, Box, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if server.is_null() || handle.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let server = unsafe { &mut (*server).0 }; @@ -38,9 +41,9 @@ pub unsafe extern "C" fn process_control_new( Ok(client) => { let boxed = Box::new(ProcessControlHandle(client)); unsafe { *handle = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -70,7 +73,7 @@ pub unsafe extern "C" fn process_control_free(handle: *mut ProcessControlHandle< /// * [`pid`] - Pointer to store the process ID of the launched app /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// All pointers must be valid or NULL where appropriate @@ -85,15 +88,15 @@ pub unsafe extern "C" fn process_control_launch_app( start_suspended: bool, kill_existing: bool, pid: *mut u64, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if handle.is_null() || bundle_id.is_null() || pid.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let bundle_id = unsafe { CStr::from_ptr(bundle_id) }; let bundle_id = match bundle_id.to_str() { Ok(s) => s.to_string(), - Err(_) => return IdeviceErrorCode::InvalidArg, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg), }; let mut env_dict = Dictionary::new(); @@ -140,9 +143,9 @@ pub unsafe extern "C" fn process_control_launch_app( match res { Ok(p) => { unsafe { *pid = p }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -153,7 +156,7 @@ pub unsafe extern "C" fn process_control_launch_app( /// * [`pid`] - The process ID to kill /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `handle` must be a valid pointer to a handle allocated by this library @@ -161,17 +164,17 @@ pub unsafe extern "C" fn process_control_launch_app( pub unsafe extern "C" fn process_control_kill_app( handle: *mut ProcessControlHandle<'static>, pid: u64, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if handle.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let client = unsafe { &mut (*handle).0 }; let res = RUNTIME.block_on(async move { client.kill_app(pid).await }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } @@ -182,7 +185,7 @@ pub unsafe extern "C" fn process_control_kill_app( /// * [`pid`] - The process ID to modify /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `handle` must be a valid pointer to a handle allocated by this library @@ -190,16 +193,16 @@ pub unsafe extern "C" fn process_control_kill_app( pub unsafe extern "C" fn process_control_disable_memory_limit( handle: *mut ProcessControlHandle<'static>, pid: u64, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if handle.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let client = unsafe { &mut (*handle).0 }; let res = RUNTIME.block_on(async move { client.disable_memory_limit(pid).await }); match res { - Ok(_) => IdeviceErrorCode::IdeviceSuccess, - Err(e) => e.into(), + Ok(_) => null_mut(), + Err(e) => ffi_err!(e), } } diff --git a/ffi/src/provider.rs b/ffi/src/provider.rs index 493c567..f6cb00a 100644 --- a/ffi/src/provider.rs +++ b/ffi/src/provider.rs @@ -1,10 +1,10 @@ // Jackson Coxson use idevice::provider::{IdeviceProvider, TcpProvider, UsbmuxdProvider}; -use std::ffi::CStr; use std::os::raw::c_char; +use std::{ffi::CStr, ptr::null_mut}; -use crate::{IdeviceErrorCode, usbmuxd::UsbmuxdAddrHandle, util}; +use crate::{IdeviceFfiError, ffi_err, usbmuxd::UsbmuxdAddrHandle, util}; pub struct IdeviceProviderHandle(pub Box); @@ -17,7 +17,7 @@ pub struct IdeviceProviderHandle(pub Box); /// * [`provider`] - A pointer to a newly allocated provider /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `ip` must be a valid sockaddr @@ -31,22 +31,22 @@ pub unsafe extern "C" fn idevice_tcp_provider_new( pairing_file: *mut crate::pairing_file::IdevicePairingFile, label: *const c_char, provider: *mut *mut IdeviceProviderHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if ip.is_null() || label.is_null() || provider.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let addr = match util::c_addr_to_rust(ip) { Ok(i) => i, Err(e) => { - return e; + return ffi_err!(e); } }; let label = match unsafe { CStr::from_ptr(label) }.to_str() { Ok(l) => l.to_string(), Err(e) => { log::error!("Invalid label string: {e:?}"); - return IdeviceErrorCode::InvalidString; + return ffi_err!(IdeviceError::FfiInvalidString); } }; @@ -59,7 +59,7 @@ pub unsafe extern "C" fn idevice_tcp_provider_new( let boxed = Box::new(IdeviceProviderHandle(Box::new(t))); unsafe { *provider = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } /// Frees an IdeviceProvider handle @@ -89,7 +89,7 @@ pub unsafe extern "C" fn idevice_provider_free(provider: *mut IdeviceProviderHan /// * [`provider`] - A pointer to a newly allocated provider /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `addr` must be a valid pointer to UsbmuxdAddrHandle created by this library, and never used again @@ -104,16 +104,16 @@ pub unsafe extern "C" fn usbmuxd_provider_new( device_id: u32, label: *const c_char, provider: *mut *mut IdeviceProviderHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if addr.is_null() || udid.is_null() || label.is_null() || provider.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let udid = match unsafe { CStr::from_ptr(udid) }.to_str() { Ok(u) => u.to_string(), Err(e) => { log::error!("Invalid UDID string: {e:?}"); - return IdeviceErrorCode::InvalidString; + return ffi_err!(IdeviceError::FfiInvalidString); } }; @@ -121,7 +121,7 @@ pub unsafe extern "C" fn usbmuxd_provider_new( Ok(l) => l.to_string(), Err(e) => { log::error!("Invalid label string: {e:?}"); - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } }; @@ -138,5 +138,5 @@ pub unsafe extern "C" fn usbmuxd_provider_new( let boxed = Box::new(IdeviceProviderHandle(Box::new(p))); unsafe { *provider = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } diff --git a/ffi/src/remote_server.rs b/ffi/src/remote_server.rs index f8385b3..236c131 100644 --- a/ffi/src/remote_server.rs +++ b/ffi/src/remote_server.rs @@ -1,8 +1,10 @@ // Jackson Coxson +use std::ptr::null_mut; + use crate::core_device_proxy::AdapterHandle; use crate::rsd::RsdHandshakeHandle; -use crate::{IdeviceErrorCode, RUNTIME, ReadWriteOpaque}; +use crate::{IdeviceFfiError, RUNTIME, ReadWriteOpaque, ffi_err}; use idevice::dvt::remote_server::RemoteServerClient; use idevice::tcp::stream::AdapterStream; use idevice::{IdeviceError, ReadWrite, RsdService}; @@ -17,7 +19,7 @@ pub struct RemoteServerHandle(pub RemoteServerClient>); /// * [`handle`] - Pointer to store the newly created RemoteServerClient handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `socket` must be a valid pointer to a handle allocated by this library. It is consumed and may @@ -27,9 +29,9 @@ pub struct RemoteServerHandle(pub RemoteServerClient>); pub unsafe extern "C" fn remote_server_new( socket: *mut ReadWriteOpaque, handle: *mut *mut RemoteServerHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if socket.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let wrapper = unsafe { &mut *socket }; @@ -41,16 +43,16 @@ pub unsafe extern "C" fn remote_server_new( client.read_message(0).await?; Ok(client) }), - None => return IdeviceErrorCode::InvalidArg, + None => return ffi_err!(IdeviceError::FfiInvalidArg), }; match res { Ok(client) => { let boxed = Box::new(RemoteServerHandle(client)); unsafe { *handle = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -61,7 +63,7 @@ pub unsafe extern "C" fn remote_server_new( /// * [`handshake`] - An RSD handshake from the same provider /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `provider` must be a valid pointer to a handle allocated by this library @@ -71,9 +73,9 @@ pub unsafe extern "C" fn remote_server_connect_rsd( provider: *mut AdapterHandle, handshake: *mut RsdHandshakeHandle, handle: *mut *mut RemoteServerHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if provider.is_null() || handshake.is_null() || handshake.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let res: Result, IdeviceError> = RUNTIME.block_on(async move { @@ -90,9 +92,9 @@ pub unsafe extern "C" fn remote_server_connect_rsd( d.into_inner(), )))); unsafe { *handle = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } diff --git a/ffi/src/rsd.rs b/ffi/src/rsd.rs index 83d7e5c..9ab2bcb 100644 --- a/ffi/src/rsd.rs +++ b/ffi/src/rsd.rs @@ -3,11 +3,11 @@ //! Provides C-compatible bindings for RSD handshake and service discovery on iOS devices. use std::ffi::{CStr, CString}; -use std::ptr; +use std::ptr::{self, null_mut}; use idevice::rsd::RsdHandshake; -use crate::{IdeviceErrorCode, RUNTIME, ReadWriteOpaque}; +use crate::{IdeviceFfiError, RUNTIME, ReadWriteOpaque, ffi_err}; /// Opaque handle to an RsdHandshake pub struct RsdHandshakeHandle(pub RsdHandshake); @@ -47,7 +47,7 @@ pub struct CRsdServiceArray { /// * [`handle`] - Pointer to store the newly created RsdHandshake handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `socket` must be a valid pointer to a ReadWrite handle allocated by this library. It is @@ -57,9 +57,9 @@ pub struct CRsdServiceArray { pub unsafe extern "C" fn rsd_handshake_new( socket: *mut ReadWriteOpaque, handle: *mut *mut RsdHandshakeHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if socket.is_null() || handle.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let wrapper = unsafe { &mut *socket }; @@ -67,7 +67,7 @@ pub unsafe extern "C" fn rsd_handshake_new( let res = match wrapper.inner.take() { Some(mut w) => RUNTIME.block_on(async move { RsdHandshake::new(w.as_mut()).await }), None => { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } }; @@ -75,9 +75,9 @@ pub unsafe extern "C" fn rsd_handshake_new( Ok(handshake) => { let boxed = Box::new(RsdHandshakeHandle(handshake)); unsafe { *handle = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -88,7 +88,7 @@ pub unsafe extern "C" fn rsd_handshake_new( /// * [`version`] - Pointer to store the protocol version /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `handle` must be a valid pointer to a handle allocated by this library @@ -97,15 +97,15 @@ pub unsafe extern "C" fn rsd_handshake_new( pub unsafe extern "C" fn rsd_get_protocol_version( handle: *mut RsdHandshakeHandle, version: *mut libc::size_t, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if handle.is_null() || version.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } unsafe { *version = (*handle).0.protocol_version; } - IdeviceErrorCode::IdeviceSuccess + null_mut() } /// Gets the UUID from the RSD handshake @@ -115,7 +115,7 @@ pub unsafe extern "C" fn rsd_get_protocol_version( /// * [`uuid`] - Pointer to store the UUID string (caller must free with rsd_free_string) /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `handle` must be a valid pointer to a handle allocated by this library @@ -124,18 +124,18 @@ pub unsafe extern "C" fn rsd_get_protocol_version( pub unsafe extern "C" fn rsd_get_uuid( handle: *mut RsdHandshakeHandle, uuid: *mut *mut libc::c_char, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if handle.is_null() || uuid.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let uuid_str = &unsafe { &*handle }.0.uuid; match CString::new(uuid_str.as_str()) { Ok(c_str) => { unsafe { *uuid = c_str.into_raw() }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(_) => IdeviceErrorCode::InvalidString, + Err(_) => ffi_err!(IdeviceError::FfiInvalidString), } } @@ -146,7 +146,7 @@ pub unsafe extern "C" fn rsd_get_uuid( /// * [`services`] - Pointer to store the services array /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `handle` must be a valid pointer to a handle allocated by this library @@ -156,9 +156,9 @@ pub unsafe extern "C" fn rsd_get_uuid( pub unsafe extern "C" fn rsd_get_services( handle: *mut RsdHandshakeHandle, services: *mut *mut CRsdServiceArray, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if handle.is_null() || services.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let handshake = unsafe { &*handle }; @@ -201,7 +201,7 @@ pub unsafe extern "C" fn rsd_get_services( } } // Return early to avoid the move below - return IdeviceErrorCode::InvalidString; + return ffi_err!(IdeviceError::FfiInvalidString); } } } @@ -234,7 +234,7 @@ pub unsafe extern "C" fn rsd_get_services( }); unsafe { *services = Box::into_raw(array) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } /// Checks if a specific service is available @@ -245,7 +245,7 @@ pub unsafe extern "C" fn rsd_get_services( /// * [`available`] - Pointer to store the availability result /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `handle` must be a valid pointer to a handle allocated by this library @@ -256,20 +256,20 @@ pub unsafe extern "C" fn rsd_service_available( handle: *mut RsdHandshakeHandle, service_name: *const libc::c_char, available: *mut bool, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if handle.is_null() || service_name.is_null() || available.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let name = match unsafe { CStr::from_ptr(service_name) }.to_str() { Ok(s) => s, - Err(_) => return IdeviceErrorCode::InvalidArg, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg), }; let handshake = unsafe { &*handle }; unsafe { *available = handshake.0.services.contains_key(name) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } /// Gets information about a specific service @@ -280,7 +280,7 @@ pub unsafe extern "C" fn rsd_service_available( /// * [`service_info`] - Pointer to store the service information /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `handle` must be a valid pointer to a handle allocated by this library @@ -292,26 +292,26 @@ pub unsafe extern "C" fn rsd_get_service_info( handle: *mut RsdHandshakeHandle, service_name: *const libc::c_char, service_info: *mut *mut CRsdService, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if handle.is_null() || service_name.is_null() || service_info.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let name = match unsafe { CStr::from_ptr(service_name) }.to_str() { Ok(s) => s, - Err(_) => return IdeviceErrorCode::InvalidArg, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg), }; let handshake = unsafe { &*handle }; let service = match handshake.0.services.get(name) { Some(s) => s, - None => return IdeviceErrorCode::ServiceNotFound, + None => return ffi_err!(IdeviceError::ServiceNotFound), }; // Convert service to C representation (similar to rsd_get_services logic) let c_name = match CString::new(name) { Ok(s) => s.into_raw(), - Err(_) => return IdeviceErrorCode::InvalidString, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidString), }; let c_entitlement = match CString::new(service.entitlement.as_str()) { @@ -320,7 +320,7 @@ pub unsafe extern "C" fn rsd_get_service_info( unsafe { let _ = CString::from_raw(c_name); } - return IdeviceErrorCode::InvalidString; + return ffi_err!(IdeviceError::FfiInvalidString); } }; @@ -343,7 +343,7 @@ pub unsafe extern "C" fn rsd_get_service_info( let _ = CString::from_raw(c_name); let _ = CString::from_raw(c_entitlement); } - return IdeviceErrorCode::InvalidString; + return ffi_err!(IdeviceError::FfiInvalidString); } } } @@ -367,7 +367,7 @@ pub unsafe extern "C" fn rsd_get_service_info( }); unsafe { *service_info = Box::into_raw(c_service) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } /// Frees a string returned by RSD functions diff --git a/ffi/src/springboardservices.rs b/ffi/src/springboardservices.rs index 67d6533..3c5715c 100644 --- a/ffi/src/springboardservices.rs +++ b/ffi/src/springboardservices.rs @@ -1,11 +1,14 @@ -use std::ffi::{CStr, c_void}; +use std::{ + ffi::{CStr, c_void}, + ptr::null_mut, +}; use idevice::{ IdeviceError, IdeviceService, provider::IdeviceProvider, springboardservices::SpringBoardServicesClient, }; -use crate::{IdeviceErrorCode, IdeviceHandle, RUNTIME, provider::IdeviceProviderHandle}; +use crate::{IdeviceFfiError, IdeviceHandle, RUNTIME, ffi_err, provider::IdeviceProviderHandle}; pub struct SpringBoardServicesClientHandle(pub SpringBoardServicesClient); @@ -16,7 +19,7 @@ pub struct SpringBoardServicesClientHandle(pub SpringBoardServicesClient); /// * [`client`] - On success, will be set to point to a newly allocated SpringBoardServicesClient handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `provider` must be a valid pointer to a handle allocated by this library @@ -25,10 +28,10 @@ pub struct SpringBoardServicesClientHandle(pub SpringBoardServicesClient); pub unsafe extern "C" fn springboard_services_connect( provider: *mut IdeviceProviderHandle, client: *mut *mut SpringBoardServicesClientHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if provider.is_null() || client.is_null() { log::error!("Null pointer provided"); - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let res: Result = RUNTIME.block_on(async move { @@ -40,13 +43,13 @@ pub unsafe extern "C" fn springboard_services_connect( Ok(r) => { let boxed = Box::new(SpringBoardServicesClientHandle(r)); unsafe { *client = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } Err(e) => { // If connection failed, the provider_box was already forgotten, // so we need to reconstruct it to avoid leak let _ = unsafe { Box::from_raw(provider) }; - e.into() + ffi_err!(e) } } } @@ -58,7 +61,7 @@ pub unsafe extern "C" fn springboard_services_connect( /// * [`client`] - On success, will be set to point to a newly allocated SpringBoardServicesClient handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `socket` must be a valid pointer to a handle allocated by this library. The socket is consumed, @@ -68,15 +71,15 @@ pub unsafe extern "C" fn springboard_services_connect( pub unsafe extern "C" fn springboard_services_new( socket: *mut IdeviceHandle, client: *mut *mut SpringBoardServicesClientHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if socket.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let socket = unsafe { Box::from_raw(socket) }.0; let r = SpringBoardServicesClient::new(socket); let boxed = Box::new(SpringBoardServicesClientHandle(r)); unsafe { *client = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } /// Gets the icon of the specified app by bundle identifier @@ -87,7 +90,7 @@ pub unsafe extern "C" fn springboard_services_new( /// * `out_result` - On success, will be set to point to a newly allocated png data /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `client` must be a valid pointer to a handle allocated by this library @@ -98,17 +101,17 @@ pub unsafe extern "C" fn springboard_services_get_icon( bundle_identifier: *const libc::c_char, out_result: *mut *mut c_void, out_result_len: *mut libc::size_t, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if client.is_null() || out_result.is_null() || out_result_len.is_null() { log::error!("Invalid arguments: {client:?}, {out_result:?}"); - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let client = unsafe { &mut *client }; let name_cstr = unsafe { CStr::from_ptr(bundle_identifier) }; let bundle_id = match name_cstr.to_str() { Ok(s) => s.to_string(), - Err(_) => return IdeviceErrorCode::InvalidArg, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg), }; let res: Result, IdeviceError> = @@ -125,9 +128,9 @@ pub unsafe extern "C" fn springboard_services_get_icon( *out_result = ptr as *mut c_void; *out_result_len = len; } - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } diff --git a/ffi/src/syslog_relay.rs b/ffi/src/syslog_relay.rs index 0c00c18..ad38b1d 100644 --- a/ffi/src/syslog_relay.rs +++ b/ffi/src/syslog_relay.rs @@ -1,10 +1,10 @@ -use std::os::raw::c_char; +use std::{os::raw::c_char, ptr::null_mut}; use idevice::{ IdeviceError, IdeviceService, provider::IdeviceProvider, syslog_relay::SyslogRelayClient, }; -use crate::{IdeviceErrorCode, RUNTIME, provider::IdeviceProviderHandle}; +use crate::{IdeviceFfiError, RUNTIME, ffi_err, provider::IdeviceProviderHandle}; pub struct SyslogRelayClientHandle(pub SyslogRelayClient); @@ -21,10 +21,10 @@ pub struct SyslogRelayClientHandle(pub SyslogRelayClient); pub unsafe extern "C" fn syslog_relay_connect_tcp( provider: *mut IdeviceProviderHandle, client: *mut *mut SyslogRelayClientHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if provider.is_null() { log::error!("Null pointer provided"); - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let res: Result = RUNTIME.block_on(async move { @@ -38,11 +38,11 @@ pub unsafe extern "C" fn syslog_relay_connect_tcp( unsafe { *client = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } Err(e) => { let _ = unsafe { Box::from_raw(provider) }; - e.into() + ffi_err!(e) } } } @@ -76,9 +76,9 @@ pub unsafe extern "C" fn syslog_relay_client_free(handle: *mut SyslogRelayClient pub unsafe extern "C" fn syslog_relay_next( client: *mut SyslogRelayClientHandle, log_message: *mut *mut c_char, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { if client.is_null() || log_message.is_null() { - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } let res = RUNTIME.block_on(async { unsafe { &mut *client }.0.next().await }); @@ -93,14 +93,14 @@ pub unsafe extern "C" fn syslog_relay_next( match CString::new(safe_log) { Ok(c_string) => { unsafe { *log_message = c_string.into_raw() }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } Err(_) => { log::error!("Failed to convert log message to C string"); - IdeviceErrorCode::InvalidString + ffi_err!(IdeviceError::FfiInvalidString) } } } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } diff --git a/ffi/src/usbmuxd.rs b/ffi/src/usbmuxd.rs index ce6956c..f39cf9f 100644 --- a/ffi/src/usbmuxd.rs +++ b/ffi/src/usbmuxd.rs @@ -1,8 +1,11 @@ // Jackson Coxson -use std::ffi::{CStr, c_char}; +use std::{ + ffi::{CStr, c_char}, + ptr::null_mut, +}; -use crate::{IdeviceErrorCode, RUNTIME, util::c_socket_to_rust}; +use crate::{IdeviceFfiError, RUNTIME, ffi_err, util::c_socket_to_rust}; use idevice::{ IdeviceError, usbmuxd::{UsbmuxdAddr, UsbmuxdConnection}, @@ -20,7 +23,7 @@ pub struct UsbmuxdAddrHandle(pub UsbmuxdAddr); /// * [`usbmuxd_connection`] - On success, will be set to point to a newly allocated UsbmuxdConnection handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `addr` must be a valid sockaddr @@ -31,10 +34,10 @@ pub unsafe extern "C" fn idevice_usbmuxd_new_tcp_connection( addr_len: libc::socklen_t, tag: u32, usbmuxd_connection: *mut *mut UsbmuxdConnectionHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { let addr = match c_socket_to_rust(addr, addr_len) { Ok(a) => a, - Err(e) => return e, + Err(e) => return ffi_err!(e), }; let res: Result = RUNTIME.block_on(async move { @@ -46,9 +49,9 @@ pub unsafe extern "C" fn idevice_usbmuxd_new_tcp_connection( Ok(r) => { let boxed = Box::new(UsbmuxdConnectionHandle(r)); unsafe { *usbmuxd_connection = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -60,7 +63,7 @@ pub unsafe extern "C" fn idevice_usbmuxd_new_tcp_connection( /// * [`usbmuxd_connection`] - On success, will be set to point to a newly allocated UsbmuxdConnection handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `addr` must be a valid CStr @@ -71,10 +74,10 @@ pub unsafe extern "C" fn idevice_usbmuxd_new_unix_socket_connection( addr: *const c_char, tag: u32, usbmuxd_connection: *mut *mut UsbmuxdConnectionHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { let addr = match unsafe { CStr::from_ptr(addr).to_str() } { Ok(s) => s, - Err(_) => return IdeviceErrorCode::InvalidArg, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg), }; let res: Result = RUNTIME.block_on(async move { @@ -86,9 +89,9 @@ pub unsafe extern "C" fn idevice_usbmuxd_new_unix_socket_connection( Ok(r) => { let boxed = Box::new(UsbmuxdConnectionHandle(r)); unsafe { *usbmuxd_connection = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -100,7 +103,7 @@ pub unsafe extern "C" fn idevice_usbmuxd_new_unix_socket_connection( /// * [`usbmuxd_connection`] - On success, will be set to point to a newly allocated UsbmuxdConnection handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `addr` must be a valid CStr @@ -108,12 +111,12 @@ pub unsafe extern "C" fn idevice_usbmuxd_new_unix_socket_connection( pub unsafe extern "C" fn idevice_usbmuxd_new_default_connection( tag: u32, usbmuxd_connection: *mut *mut UsbmuxdConnectionHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { let addr = match UsbmuxdAddr::from_env_var() { Ok(a) => a, Err(e) => { log::error!("Invalid address set: {e:?}"); - return IdeviceErrorCode::InvalidArg; + return ffi_err!(IdeviceError::FfiInvalidArg); } }; @@ -124,9 +127,9 @@ pub unsafe extern "C" fn idevice_usbmuxd_new_default_connection( Ok(r) => { let boxed = Box::new(UsbmuxdConnectionHandle(r)); unsafe { *usbmuxd_connection = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } - Err(e) => e.into(), + Err(e) => ffi_err!(e), } } @@ -155,7 +158,7 @@ pub unsafe extern "C" fn idevice_usbmuxd_connection_free( /// * [`usbmuxd_addr`] - On success, will be set to point to a newly allocated UsbmuxdAddr handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `addr` must be a valid sockaddr @@ -165,17 +168,17 @@ pub unsafe extern "C" fn idevice_usbmuxd_tcp_addr_new( addr: *const libc::sockaddr, addr_len: libc::socklen_t, usbmuxd_addr: *mut *mut UsbmuxdAddrHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { let addr = match c_socket_to_rust(addr, addr_len) { Ok(a) => a, - Err(e) => return e, + Err(e) => return ffi_err!(e), }; let u = UsbmuxdAddr::TcpSocket(addr); let boxed = Box::new(UsbmuxdAddrHandle(u)); unsafe { *usbmuxd_addr = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } /// Creates a new UsbmuxdAddr struct with a unix socket @@ -185,7 +188,7 @@ pub unsafe extern "C" fn idevice_usbmuxd_tcp_addr_new( /// * [`usbmuxd_addr`] - On success, will be set to point to a newly allocated UsbmuxdAddr handle /// /// # Returns -/// An error code indicating success or failure +/// An IdeviceFfiError on error, null on success /// /// # Safety /// `addr` must be a valid CStr @@ -195,17 +198,17 @@ pub unsafe extern "C" fn idevice_usbmuxd_tcp_addr_new( pub unsafe extern "C" fn idevice_usbmuxd_unix_addr_new( addr: *const c_char, usbmuxd_addr: *mut *mut UsbmuxdAddrHandle, -) -> IdeviceErrorCode { +) -> *mut IdeviceFfiError { let addr = match unsafe { CStr::from_ptr(addr).to_str() } { Ok(s) => s, - Err(_) => return IdeviceErrorCode::InvalidArg, + Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg), }; let u = UsbmuxdAddr::UnixSocket(addr.to_string()); let boxed = Box::new(UsbmuxdAddrHandle(u)); unsafe { *usbmuxd_addr = Box::into_raw(boxed) }; - IdeviceErrorCode::IdeviceSuccess + null_mut() } /// Frees a UsbmuxdAddr handle diff --git a/ffi/src/util.rs b/ffi/src/util.rs index 96e0c4d..989cf77 100644 --- a/ffi/src/util.rs +++ b/ffi/src/util.rs @@ -6,21 +6,20 @@ use std::{ os::raw::c_void, }; +use idevice::IdeviceError; use libc::{sockaddr_in, sockaddr_in6}; use plist::Value; -use crate::IdeviceErrorCode; - pub(crate) fn c_socket_to_rust( addr: *const libc::sockaddr, addr_len: libc::socklen_t, -) -> Result { +) -> Result { Ok(unsafe { match (*addr).sa_family as c_int { libc::AF_INET => { if (addr_len as usize) < std::mem::size_of::() { log::error!("Invalid sockaddr_in size"); - return Err(IdeviceErrorCode::InvalidArg); + return Err(IdeviceError::FfiInvalidArg); } let addr_in = *(addr as *const sockaddr_in); let ip = std::net::Ipv4Addr::from(u32::from_be(addr_in.sin_addr.s_addr)); @@ -40,18 +39,18 @@ pub(crate) fn c_socket_to_rust( )) } else { log::error!("Invalid sockaddr_in6 size"); - return Err(IdeviceErrorCode::InvalidArg); + return Err(IdeviceError::FfiInvalidArg); } } _ => { log::error!("Unsupported socket address family: {}", (*addr).sa_family); - return Err(IdeviceErrorCode::InvalidArg); + return Err(IdeviceError::FfiInvalidArg); } } }) } -pub(crate) fn c_addr_to_rust(addr: *const libc::sockaddr) -> Result { +pub(crate) fn c_addr_to_rust(addr: *const libc::sockaddr) -> Result { unsafe { // Check the address family match (*addr).sa_family as c_int { @@ -72,7 +71,7 @@ pub(crate) fn c_addr_to_rust(addr: *const libc::sockaddr) -> Result { log::error!("Unsupported socket address family: {}", (*addr).sa_family); - Err(IdeviceErrorCode::InvalidArg) + Err(IdeviceError::FfiInvalidArg) } } } diff --git a/idevice/src/lib.rs b/idevice/src/lib.rs index 550112a..f6614c8 100644 --- a/idevice/src/lib.rs +++ b/idevice/src/lib.rs @@ -413,187 +413,195 @@ impl Idevice { /// Comprehensive error type for all device communication failures #[derive(Error, Debug)] +#[repr(i32)] #[non_exhaustive] pub enum IdeviceError { #[error("device socket io failed")] - Socket(#[from] io::Error), + Socket(#[from] io::Error) = -1, #[error("PEM parse failed")] - PemParseFailed(#[from] rustls::pki_types::pem::Error), + PemParseFailed(#[from] rustls::pki_types::pem::Error) = -2, #[error("TLS error")] - Rustls(#[from] rustls::Error), + Rustls(#[from] rustls::Error) = -3, #[error("TLS verifiction build failed")] - TlsBuilderFailed(#[from] rustls::server::VerifierBuilderError), + TlsBuilderFailed(#[from] rustls::server::VerifierBuilderError) = -4, #[error("io on plist")] - Plist(#[from] plist::Error), + Plist(#[from] plist::Error) = -5, #[error("can't convert bytes to utf8")] - Utf8(#[from] std::string::FromUtf8Error), + Utf8(#[from] std::string::FromUtf8Error) = -6, #[error("unexpected response from device")] - UnexpectedResponse, + UnexpectedResponse = -7, #[error("this request was prohibited")] - GetProhibited, + GetProhibited = -8, #[error("no SSL session is active")] - SessionInactive, + SessionInactive = -9, #[error("device does not have pairing file")] - InvalidHostID, + InvalidHostID = -10, #[error("no established connection")] - NoEstablishedConnection, + NoEstablishedConnection = -11, #[error("device went to sleep")] - HeartbeatSleepyTime, + HeartbeatSleepyTime = -12, #[error("heartbeat timeout")] - HeartbeatTimeout, + HeartbeatTimeout = -13, #[error("not found")] - NotFound, + NotFound = -14, #[error("service not found")] - ServiceNotFound, + ServiceNotFound = -15, #[error("CDTunnel packet too short")] - CdtunnelPacketTooShort, + CdtunnelPacketTooShort = -16, #[error("CDTunnel packet invalid magic")] - CdtunnelPacketInvalidMagic, + CdtunnelPacketInvalidMagic = -17, #[error("Proclaimed packet size does not match actual size")] - PacketSizeMismatch, + PacketSizeMismatch = -18, #[cfg(feature = "core_device_proxy")] #[error("JSON serialization failed")] - Json(#[from] serde_json::Error), + Json(#[from] serde_json::Error) = -19, #[error("device not found")] - DeviceNotFound, + DeviceNotFound = -20, #[error("device lockded")] - DeviceLocked, + DeviceLocked = -21, #[error("device refused connection")] - UsbConnectionRefused, + UsbConnectionRefused = -22, #[error("bad command")] - UsbBadCommand, + UsbBadCommand = -23, #[error("bad device")] - UsbBadDevice, + UsbBadDevice = -24, #[error("usb bad version")] - UsbBadVersion, + UsbBadVersion = -25, #[error("bad build manifest")] - BadBuildManifest, + BadBuildManifest = -26, #[error("image not mounted")] - ImageNotMounted, + ImageNotMounted = -27, #[cfg(feature = "pair")] #[error("pairing trust dialog pending")] - PairingDialogResponsePending, + PairingDialogResponsePending = -28, #[cfg(feature = "pair")] #[error("user denied pairing trust")] - UserDeniedPairing, + UserDeniedPairing = -29, #[cfg(feature = "pair")] #[error("device is locked")] - PasswordProtected, + PasswordProtected = -30, #[cfg(feature = "misagent")] #[error("misagent operation failed")] - MisagentFailure, + MisagentFailure = -31, #[cfg(feature = "installation_proxy")] #[error("installation proxy operation failed")] - InstallationProxyOperationFailed(String), + InstallationProxyOperationFailed(String) = -32, #[cfg(feature = "afc")] - #[error("afc error")] - Afc(#[from] afc::errors::AfcError), + #[error("afc error: {0}")] + Afc(#[from] afc::errors::AfcError) = -33, #[cfg(feature = "afc")] #[error("unknown afc opcode")] - UnknownAfcOpcode, + UnknownAfcOpcode = -34, #[cfg(feature = "afc")] #[error("invalid afc magic")] - InvalidAfcMagic, + InvalidAfcMagic = -35, #[cfg(feature = "afc")] #[error("missing file attribute")] - AfcMissingAttribute, + AfcMissingAttribute = -36, #[cfg(feature = "crashreportcopymobile")] #[error("crash report mover sent the wrong response")] - CrashReportMoverBadResponse(Vec), + CrashReportMoverBadResponse(Vec) = -37, #[cfg(any(feature = "tss", feature = "tunneld"))] #[error("http reqwest error")] - Reqwest(#[from] reqwest::Error), + Reqwest(#[from] reqwest::Error) = -38, #[error("internal error")] - InternalError(String), + InternalError(String) = -39, #[cfg(feature = "xpc")] #[error("unknown http frame type")] - UnknownFrame(u8), + UnknownFrame(u8) = -40, #[cfg(feature = "xpc")] #[error("unknown http setting type")] - UnknownHttpSetting(u16), + UnknownHttpSetting(u16) = -41, #[cfg(feature = "xpc")] #[error("Unintialized stream ID")] - UninitializedStreamId, + UninitializedStreamId = -42, #[cfg(feature = "xpc")] #[error("unknown XPC type")] - UnknownXpcType(u32), + UnknownXpcType(u32) = -43, #[cfg(feature = "xpc")] #[error("malformed XPC message")] - MalformedXpc, + MalformedXpc = -44, #[cfg(feature = "xpc")] #[error("invalid XPC magic")] - InvalidXpcMagic, + InvalidXpcMagic = -45, #[cfg(feature = "xpc")] #[error("unexpected XPC version")] - UnexpectedXpcVersion, + UnexpectedXpcVersion = -46, #[cfg(feature = "xpc")] #[error("invalid C string")] - InvalidCString, + InvalidCString = -47, #[cfg(feature = "xpc")] #[error("stream reset")] - HttpStreamReset, + HttpStreamReset = -48, #[cfg(feature = "xpc")] #[error("go away packet received")] - HttpGoAway(String), + HttpGoAway(String) = -49, #[cfg(feature = "dvt")] #[error("NSKeyedArchive error")] - NsKeyedArchiveError(#[from] ns_keyed_archive::ConverterError), + NsKeyedArchiveError(#[from] ns_keyed_archive::ConverterError) = -50, #[cfg(feature = "dvt")] #[error("Unknown aux value type")] - UnknownAuxValueType(u32), + UnknownAuxValueType(u32) = -51, #[cfg(feature = "dvt")] #[error("unknown channel")] - UnknownChannel(u32), + UnknownChannel(u32) = -52, #[error("cannot parse string as IpAddr")] - AddrParseError(#[from] std::net::AddrParseError), + AddrParseError(#[from] std::net::AddrParseError) = -53, #[cfg(feature = "dvt")] #[error("disable memory limit failed")] - DisableMemoryLimitFailed, + DisableMemoryLimitFailed = -54, #[error("not enough bytes, expected {1}, got {0}")] - NotEnoughBytes(usize, usize), + NotEnoughBytes(usize, usize) = -55, #[error("failed to parse bytes as valid utf8")] - Utf8Error, + Utf8Error = -56, #[cfg(feature = "debug_proxy")] #[error("invalid argument passed")] - InvalidArgument, + InvalidArgument = -57, #[error("unknown error `{0}` returned from device")] - UnknownErrorType(String), + UnknownErrorType(String) = -59, + + #[error("invalid arguments were passed")] + FfiInvalidArg = -60, + #[error("invalid string was passed")] + FfiInvalidString = -61, + #[error("buffer passed is too small - needs {0}, got {1}")] + FfiBufferTooSmall(usize, usize) = -62, } impl IdeviceError { @@ -633,4 +641,113 @@ impl IdeviceError { _ => None, } } + + pub fn code(&self) -> i32 { + match self { + IdeviceError::Socket(_) => -1, + IdeviceError::PemParseFailed(_) => -2, + IdeviceError::Rustls(_) => -3, + IdeviceError::TlsBuilderFailed(_) => -4, + IdeviceError::Plist(_) => -5, + IdeviceError::Utf8(_) => -6, + IdeviceError::UnexpectedResponse => -7, + IdeviceError::GetProhibited => -8, + IdeviceError::SessionInactive => -9, + IdeviceError::InvalidHostID => -10, + IdeviceError::NoEstablishedConnection => -11, + IdeviceError::HeartbeatSleepyTime => -12, + IdeviceError::HeartbeatTimeout => -13, + IdeviceError::NotFound => -14, + IdeviceError::ServiceNotFound => -15, + IdeviceError::CdtunnelPacketTooShort => -16, + IdeviceError::CdtunnelPacketInvalidMagic => -17, + IdeviceError::PacketSizeMismatch => -18, + + #[cfg(feature = "core_device_proxy")] + IdeviceError::Json(_) => -19, + + IdeviceError::DeviceNotFound => -20, + IdeviceError::DeviceLocked => -21, + IdeviceError::UsbConnectionRefused => -22, + IdeviceError::UsbBadCommand => -23, + IdeviceError::UsbBadDevice => -24, + IdeviceError::UsbBadVersion => -25, + IdeviceError::BadBuildManifest => -26, + IdeviceError::ImageNotMounted => -27, + + #[cfg(feature = "pair")] + IdeviceError::PairingDialogResponsePending => -28, + #[cfg(feature = "pair")] + IdeviceError::UserDeniedPairing => -29, + #[cfg(feature = "pair")] + IdeviceError::PasswordProtected => -30, + + #[cfg(feature = "misagent")] + IdeviceError::MisagentFailure => -31, + + #[cfg(feature = "installation_proxy")] + IdeviceError::InstallationProxyOperationFailed(_) => -32, + + #[cfg(feature = "afc")] + IdeviceError::Afc(_) => -33, + #[cfg(feature = "afc")] + IdeviceError::UnknownAfcOpcode => -34, + #[cfg(feature = "afc")] + IdeviceError::InvalidAfcMagic => -35, + #[cfg(feature = "afc")] + IdeviceError::AfcMissingAttribute => -36, + + #[cfg(feature = "crashreportcopymobile")] + IdeviceError::CrashReportMoverBadResponse(_) => -37, + + #[cfg(any(feature = "tss", feature = "tunneld"))] + IdeviceError::Reqwest(_) => -38, + + IdeviceError::InternalError(_) => -39, + + #[cfg(feature = "xpc")] + IdeviceError::UnknownFrame(_) => -40, + #[cfg(feature = "xpc")] + IdeviceError::UnknownHttpSetting(_) => -41, + #[cfg(feature = "xpc")] + IdeviceError::UninitializedStreamId => -42, + #[cfg(feature = "xpc")] + IdeviceError::UnknownXpcType(_) => -43, + #[cfg(feature = "xpc")] + IdeviceError::MalformedXpc => -44, + #[cfg(feature = "xpc")] + IdeviceError::InvalidXpcMagic => -45, + #[cfg(feature = "xpc")] + IdeviceError::UnexpectedXpcVersion => -46, + #[cfg(feature = "xpc")] + IdeviceError::InvalidCString => -47, + #[cfg(feature = "xpc")] + IdeviceError::HttpStreamReset => -48, + #[cfg(feature = "xpc")] + IdeviceError::HttpGoAway(_) => -49, + + #[cfg(feature = "dvt")] + IdeviceError::NsKeyedArchiveError(_) => -50, + #[cfg(feature = "dvt")] + IdeviceError::UnknownAuxValueType(_) => -51, + #[cfg(feature = "dvt")] + IdeviceError::UnknownChannel(_) => -52, + + IdeviceError::AddrParseError(_) => -53, + + #[cfg(feature = "dvt")] + IdeviceError::DisableMemoryLimitFailed => -54, + + IdeviceError::NotEnoughBytes(_, _) => -55, + IdeviceError::Utf8Error => -56, + + #[cfg(feature = "debug_proxy")] + IdeviceError::InvalidArgument => -57, + + IdeviceError::UnknownErrorType(_) => -59, + IdeviceError::FfiInvalidArg => -60, + IdeviceError::FfiInvalidString => -61, + IdeviceError::FfiBufferTooSmall(_, _) => -62, + } + } }