Update FFI to use error struct for message

This commit is contained in:
Jackson Coxson
2025-06-02 19:42:17 -06:00
parent 5d7aa50a7d
commit 35ba07889b
36 changed files with 1358 additions and 1135 deletions

View File

@@ -161,10 +161,12 @@ int main(int argc, char **argv) {
// Read pairing file // Read pairing file
IdevicePairingFile *pairing_file = NULL; IdevicePairingFile *pairing_file = NULL;
IdeviceErrorCode err = IdeviceFfiError *err =
idevice_pairing_file_read(pairing_file_path, &pairing_file); idevice_pairing_file_read(pairing_file_path, &pairing_file);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to read pairing file: %d\n", err); fprintf(stderr, "Failed to read pairing file: [%d] %s\n", err->code,
err->message);
idevice_error_free(err);
return 1; return 1;
} }
@@ -172,8 +174,10 @@ int main(int argc, char **argv) {
IdeviceProviderHandle *provider = NULL; IdeviceProviderHandle *provider = NULL;
err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing_file, err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing_file,
"ImageMounterTest", &provider); "ImageMounterTest", &provider);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to create TCP provider: %d\n", err); fprintf(stderr, "Failed to create TCP provider: [%d] %s\n", err->code,
err->message);
idevice_error_free(err);
idevice_pairing_file_free(pairing_file); idevice_pairing_file_free(pairing_file);
return 1; return 1;
} }
@@ -181,8 +185,10 @@ int main(int argc, char **argv) {
// Connect to AFC service // Connect to AFC service
AfcClientHandle *client = NULL; AfcClientHandle *client = NULL;
err = afc_client_connect(provider, &client); err = afc_client_connect(provider, &client);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to connect to AFC service: %d\n", err); fprintf(stderr, "Failed to connect to AFC service: [%d] %s\n", err->code,
err->message);
idevice_error_free(err);
idevice_provider_free(provider); idevice_provider_free(provider);
return 1; return 1;
} }
@@ -190,6 +196,7 @@ int main(int argc, char **argv) {
// Process command // Process command
int success = 1; int success = 1;
if (strcmp(command, "list") == 0) { if (strcmp(command, "list") == 0) {
if (argc < 3) { if (argc < 3) {
printf("Error: Missing path argument\n"); printf("Error: Missing path argument\n");
@@ -200,14 +207,16 @@ int main(int argc, char **argv) {
size_t count = 0; size_t count = 0;
err = afc_list_directory(client, path, &entries, &count); err = afc_list_directory(client, path, &entries, &count);
if (err == IdeviceSuccess) { if (err == NULL) {
printf("Contents of %s:\n", path); printf("Contents of %s:\n", path);
for (size_t i = 0; i < count; i++) { for (size_t i = 0; i < count; i++) {
printf("- %s\n", entries[i]); printf("- %s\n", entries[i]);
} }
free_directory_listing(entries, count); free_directory_listing(entries, count);
} else { } 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; success = 0;
} }
} }
@@ -218,10 +227,12 @@ int main(int argc, char **argv) {
} else { } else {
char *path = argv[2]; char *path = argv[2];
err = afc_make_directory(client, path); err = afc_make_directory(client, path);
if (err == IdeviceSuccess) { if (err == NULL) {
printf("Directory created successfully\n"); printf("Directory created successfully\n");
} else { } 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; success = 0;
} }
} }
@@ -235,14 +246,16 @@ int main(int argc, char **argv) {
AfcFileHandle *file = NULL; AfcFileHandle *file = NULL;
err = afc_file_open(client, src_path, AfcRdOnly, &file); err = afc_file_open(client, src_path, AfcRdOnly, &file);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to open file: %d\n", err); fprintf(stderr, "Failed to open file: [%d] %s\n", err->code,
err->message);
idevice_error_free(err);
success = 0; success = 0;
} else { } else {
uint8_t *data = NULL; uint8_t *data = NULL;
size_t length = 0; size_t length = 0;
err = afc_file_read(file, &data, &length); err = afc_file_read(file, &data, &length);
if (err == IdeviceSuccess) { if (err == NULL) {
if (write_file(dest_path, data, length)) { if (write_file(dest_path, data, length)) {
printf("File downloaded successfully\n"); printf("File downloaded successfully\n");
} else { } else {
@@ -250,7 +263,9 @@ int main(int argc, char **argv) {
} }
free(data); free(data);
} else { } 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; success = 0;
} }
afc_file_close(file); afc_file_close(file);
@@ -271,15 +286,19 @@ int main(int argc, char **argv) {
} else { } else {
AfcFileHandle *file = NULL; AfcFileHandle *file = NULL;
err = afc_file_open(client, dest_path, AfcWrOnly, &file); err = afc_file_open(client, dest_path, AfcWrOnly, &file);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to open file: %d\n", err); fprintf(stderr, "Failed to open file: [%d] %s\n", err->code,
err->message);
idevice_error_free(err);
success = 0; success = 0;
} else { } else {
err = afc_file_write(file, data, length); err = afc_file_write(file, data, length);
if (err == IdeviceSuccess) { if (err == NULL) {
printf("File uploaded successfully\n"); printf("File uploaded successfully\n");
} else { } 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; success = 0;
} }
afc_file_close(file); afc_file_close(file);
@@ -294,10 +313,12 @@ int main(int argc, char **argv) {
} else { } else {
char *path = argv[2]; char *path = argv[2];
err = afc_remove_path(client, path); err = afc_remove_path(client, path);
if (err == IdeviceSuccess) { if (err == NULL) {
printf("Path removed successfully\n"); printf("Path removed successfully\n");
} else { } 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; success = 0;
} }
} }
@@ -308,10 +329,12 @@ int main(int argc, char **argv) {
} else { } else {
char *path = argv[2]; char *path = argv[2];
err = afc_remove_path_and_contents(client, path); err = afc_remove_path_and_contents(client, path);
if (err == IdeviceSuccess) { if (err == NULL) {
printf("Path and contents removed successfully\n"); printf("Path and contents removed successfully\n");
} else { } 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; success = 0;
} }
} }
@@ -323,22 +346,26 @@ int main(int argc, char **argv) {
char *path = argv[2]; char *path = argv[2];
AfcFileInfo info = {0}; AfcFileInfo info = {0};
err = afc_get_file_info(client, path, &info); err = afc_get_file_info(client, path, &info);
if (err == IdeviceSuccess) { if (err == NULL) {
print_file_info(&info); print_file_info(&info);
afc_file_info_free(&info); afc_file_info_free(&info);
} else { } 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; success = 0;
} }
} }
} else if (strcmp(command, "device_info") == 0) { } else if (strcmp(command, "device_info") == 0) {
AfcDeviceInfo info = {0}; AfcDeviceInfo info = {0};
err = afc_get_device_info(client, &info); err = afc_get_device_info(client, &info);
if (err == IdeviceSuccess) { if (err == NULL) {
print_device_info(&info); print_device_info(&info);
afc_device_info_free(&info); afc_device_info_free(&info);
} else { } 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; success = 0;
} }
} else { } else {
@@ -349,6 +376,5 @@ int main(int argc, char **argv) {
// Cleanup // Cleanup
afc_client_free(client); afc_client_free(client);
return success ? 0 : 1; return success ? 0 : 1;
} }

View File

@@ -18,11 +18,13 @@ int main() {
IdeviceHandle *idevice = NULL; IdeviceHandle *idevice = NULL;
// Call the Rust function to connect // 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); (struct sockaddr *)&addr, sizeof(addr), "TestDevice", &idevice);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to connect to device: %d\n", err); fprintf(stderr, "Failed to connect to device: [%d] %s\n", err->code,
err->message);
idevice_error_free(err);
return 1; return 1;
} }
@@ -32,8 +34,11 @@ int main() {
char *device_type = NULL; char *device_type = NULL;
err = idevice_get_type(idevice, &device_type); err = idevice_get_type(idevice, &device_type);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to get device type: %d\n", err); fprintf(stderr, "Failed to get device type: [%d] %s\n", err->code,
err->message);
idevice_error_free(err);
idevice_free(idevice);
return 1; return 1;
} }

View File

@@ -27,12 +27,8 @@ int main(int argc, char **argv) {
const char *device_ip = argv[1]; const char *device_ip = argv[1];
const char *pairing_file = argc > 2 ? argv[2] : "pairing.plist"; const char *pairing_file = argc > 2 ? argv[2] : "pairing.plist";
/*****************************************************************
* CoreDeviceProxy Setup
*****************************************************************/
printf("=== Setting up CoreDeviceProxy ===\n"); printf("=== Setting up CoreDeviceProxy ===\n");
// Create socket address
struct sockaddr_in addr; struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
@@ -42,99 +38,98 @@ int main(int argc, char **argv) {
return 1; return 1;
} }
// Read pairing file IdeviceFfiError *err = NULL;
IdevicePairingFile *pairing = NULL; IdevicePairingFile *pairing = NULL;
IdeviceErrorCode err = idevice_pairing_file_read(pairing_file, &pairing); err = idevice_pairing_file_read(pairing_file, &pairing);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to read pairing file: %d\n", err); fprintf(stderr, "Failed to read pairing file: [%d] %s\n", err->code,
err->message);
idevice_error_free(err);
return 1; return 1;
} }
// Create TCP provider
IdeviceProviderHandle *tcp_provider = NULL; IdeviceProviderHandle *tcp_provider = NULL;
err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing, err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing,
"DebugProxyShell", &tcp_provider); "DebugProxyShell", &tcp_provider);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to create TCP provider: %d\n", err); fprintf(stderr, "Failed to create TCP provider: [%d] %s\n", err->code,
err->message);
idevice_error_free(err);
idevice_pairing_file_free(pairing); idevice_pairing_file_free(pairing);
return 1; return 1;
} }
// Connect to CoreDeviceProxy
CoreDeviceProxyHandle *core_device = NULL; CoreDeviceProxyHandle *core_device = NULL;
err = core_device_proxy_connect(tcp_provider, &core_device); 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; return 1;
} }
idevice_provider_free(tcp_provider);
// Get server RSD port
uint16_t rsd_port; uint16_t rsd_port;
err = core_device_proxy_get_server_rsd_port(core_device, &rsd_port); err = core_device_proxy_get_server_rsd_port(core_device, &rsd_port);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to get server RSD port: %d\n", err); 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); core_device_proxy_free(core_device);
return 1; return 1;
} }
printf("Server RSD Port: %d\n", rsd_port); printf("Server RSD Port: %d\n", rsd_port);
/*****************************************************************
* Create TCP Tunnel Adapter
*****************************************************************/
printf("\n=== Creating TCP Tunnel Adapter ===\n"); printf("\n=== Creating TCP Tunnel Adapter ===\n");
AdapterHandle *adapter = NULL; AdapterHandle *adapter = NULL;
err = core_device_proxy_create_tcp_adapter(core_device, &adapter); 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; return 1;
} }
// Connect to RSD port
AdapterStreamHandle *stream = NULL; AdapterStreamHandle *stream = NULL;
err = adapter_connect(adapter, rsd_port, &stream); err = adapter_connect(adapter, rsd_port, &stream);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to connect to RSD port: %d\n", err); fprintf(stderr, "Failed to connect to RSD port: [%d] %s\n", err->code,
err->message);
idevice_error_free(err);
adapter_free(adapter); adapter_free(adapter);
return 1; return 1;
} }
printf("Successfully connected to RSD port\n"); printf("Successfully connected to RSD port\n");
/*****************************************************************
* RSD Handshake
*****************************************************************/
printf("\n=== Performing RSD Handshake ===\n"); printf("\n=== Performing RSD Handshake ===\n");
RsdHandshakeHandle *handshake = NULL; RsdHandshakeHandle *handshake = NULL;
err = rsd_handshake_new(stream, &handshake); err = rsd_handshake_new(stream, &handshake);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to perform RSD handshake: %d\n", err); fprintf(stderr, "Failed to perform RSD handshake: [%d] %s\n", err->code,
err->message);
idevice_error_free(err);
adapter_close(stream); adapter_close(stream);
adapter_free(adapter); adapter_free(adapter);
return 1; return 1;
} }
/*****************************************************************
* Debug Proxy Setup
*****************************************************************/
printf("\n=== Setting up Debug Proxy ===\n"); printf("\n=== Setting up Debug Proxy ===\n");
// Create DebugProxyClient
DebugProxyHandle *debug_proxy = NULL; DebugProxyHandle *debug_proxy = NULL;
err = debug_proxy_connect_rsd(adapter, handshake, &debug_proxy); err = debug_proxy_connect_rsd(adapter, handshake, &debug_proxy);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to create debug proxy client: %d\n", err); fprintf(stderr, "Failed to create debug proxy client: [%d] %s\n", err->code,
err->message);
idevice_error_free(err);
rsd_handshake_free(handshake); rsd_handshake_free(handshake);
adapter_free(adapter); adapter_free(adapter);
return 1; return 1;
} }
/*****************************************************************
* Interactive Shell
*****************************************************************/
printf("\n=== Starting Interactive Debug Shell ===\n"); printf("\n=== Starting Interactive Debug Shell ===\n");
printf("Type GDB debugserver commands or 'quit' to exit\n\n"); printf("Type GDB debugserver commands or 'quit' to exit\n\n");
@@ -149,7 +144,6 @@ int main(int argc, char **argv) {
break; break;
} }
// Remove newline
command[strcspn(command, "\n")] = '\0'; command[strcspn(command, "\n")] = '\0';
if (strcmp(command, "quit") == 0) { if (strcmp(command, "quit") == 0) {
@@ -157,14 +151,11 @@ int main(int argc, char **argv) {
continue; continue;
} }
// Split command into name and arguments
char *name = strtok(command, " "); char *name = strtok(command, " ");
char *args = strtok(NULL, ""); char *args = strtok(NULL, "");
// Create command
DebugserverCommandHandle *cmd = NULL; DebugserverCommandHandle *cmd = NULL;
if (args != NULL && args[0] != '\0') { if (args != NULL && args[0] != '\0') {
// Split arguments
char *argv[16] = {0}; char *argv[16] = {0};
int argc = 0; int argc = 0;
char *token = strtok(args, " "); char *token = strtok(args, " ");
@@ -183,13 +174,13 @@ int main(int argc, char **argv) {
continue; continue;
} }
// Send command
char *response = NULL; char *response = NULL;
err = debug_proxy_send_command(debug_proxy, cmd, &response); err = debug_proxy_send_command(debug_proxy, cmd, &response);
debugserver_command_free(cmd); debugserver_command_free(cmd);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Command failed with error: %d\n", err); fprintf(stderr, "Command failed: [%d] %s\n", err->code, err->message);
idevice_error_free(err);
continue; continue;
} }
@@ -200,10 +191,12 @@ int main(int argc, char **argv) {
printf("(no response)\n"); printf("(no response)\n");
} }
// Read any additional responses
while (true) { while (true) {
err = debug_proxy_read_response(debug_proxy, &response); 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; break;
} }
printf("%s\n", response); printf("%s\n", response);
@@ -211,9 +204,6 @@ int main(int argc, char **argv) {
} }
} }
/*****************************************************************
* Cleanup
*****************************************************************/
debug_proxy_free(debug_proxy); debug_proxy_free(debug_proxy);
rsd_handshake_free(handshake); rsd_handshake_free(handshake);
adapter_free(adapter); adapter_free(adapter);

View File

@@ -43,9 +43,10 @@ int main(int argc, char **argv) {
// Read pairing file // Read pairing file
struct IdevicePairingFile *pairing = NULL; struct IdevicePairingFile *pairing = NULL;
enum IdeviceErrorCode err = idevice_pairing_file_read(pairing_file, &pairing); IdeviceFfiError *err = idevice_pairing_file_read(pairing_file, &pairing);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to read pairing file: %d\n", err); fprintf(stderr, "Failed to read pairing file: [%d] %s\n", err->code,
err->message);
return 1; return 1;
} }
@@ -53,8 +54,9 @@ int main(int argc, char **argv) {
struct IdeviceProviderHandle *provider = NULL; struct IdeviceProviderHandle *provider = NULL;
err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing, err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing,
"ProcessDebugTest", &provider); "ProcessDebugTest", &provider);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to create TCP provider: %d\n", err); fprintf(stderr, "Failed to create TCP provider: [%d] %s\n", err->code,
err->message);
idevice_pairing_file_free(pairing); idevice_pairing_file_free(pairing);
return 1; return 1;
} }
@@ -62,8 +64,9 @@ int main(int argc, char **argv) {
// Connect to CoreDeviceProxy // Connect to CoreDeviceProxy
struct CoreDeviceProxyHandle *core_device = NULL; struct CoreDeviceProxyHandle *core_device = NULL;
err = core_device_proxy_connect(provider, &core_device); err = core_device_proxy_connect(provider, &core_device);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to connect to CoreDeviceProxy: %d\n", err); fprintf(stderr, "Failed to connect to CoreDeviceProxy: [%d] %s", err->code,
err->message);
idevice_provider_free(provider); idevice_provider_free(provider);
return 1; return 1;
} }
@@ -72,8 +75,9 @@ int main(int argc, char **argv) {
// Get server RSD port // Get server RSD port
uint16_t rsd_port; uint16_t rsd_port;
err = core_device_proxy_get_server_rsd_port(core_device, &rsd_port); err = core_device_proxy_get_server_rsd_port(core_device, &rsd_port);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to get server RSD port: %d\n", err); fprintf(stderr, "Failed to get server RSD port: [%d] %s", err->code,
err->message);
core_device_proxy_free(core_device); core_device_proxy_free(core_device);
return 1; return 1;
} }
@@ -86,8 +90,9 @@ int main(int argc, char **argv) {
struct AdapterHandle *adapter = NULL; struct AdapterHandle *adapter = NULL;
err = core_device_proxy_create_tcp_adapter(core_device, &adapter); err = core_device_proxy_create_tcp_adapter(core_device, &adapter);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to create TCP adapter: %d\n", err); fprintf(stderr, "Failed to create TCP adapter: [%d] %s", err->code,
err->message);
core_device_proxy_free(core_device); core_device_proxy_free(core_device);
return 1; return 1;
} }
@@ -95,8 +100,9 @@ int main(int argc, char **argv) {
// Connect to RSD port // Connect to RSD port
struct ReadWriteOpaque *rsd_stream = NULL; struct ReadWriteOpaque *rsd_stream = NULL;
err = adapter_connect(adapter, rsd_port, &rsd_stream); err = adapter_connect(adapter, rsd_port, &rsd_stream);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to connect to RSD port: %d\n", err); fprintf(stderr, "Failed to connect to RSD port: [%d] %s", err->code,
err->message);
adapter_free(adapter); adapter_free(adapter);
return 1; return 1;
} }
@@ -111,8 +117,9 @@ int main(int argc, char **argv) {
struct RsdHandshakeHandle *rsd_handshake = NULL; struct RsdHandshakeHandle *rsd_handshake = NULL;
err = rsd_handshake_new(rsd_stream, &rsd_handshake); err = rsd_handshake_new(rsd_stream, &rsd_handshake);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to create RSD handshake: %d\n", err); fprintf(stderr, "Failed to create RSD handshake: [%d] %s", err->code,
err->message);
adapter_free(adapter); adapter_free(adapter);
return 1; return 1;
} }
@@ -120,8 +127,9 @@ int main(int argc, char **argv) {
// Get services // Get services
struct CRsdServiceArray *services = NULL; struct CRsdServiceArray *services = NULL;
err = rsd_get_services(rsd_handshake, &services); err = rsd_get_services(rsd_handshake, &services);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to get RSD services: %d\n", err); fprintf(stderr, "Failed to get RSD services: [%d] %s", err->code,
err->message);
rsd_handshake_free(rsd_handshake); rsd_handshake_free(rsd_handshake);
adapter_free(adapter); adapter_free(adapter);
return 1; return 1;
@@ -157,8 +165,10 @@ int main(int argc, char **argv) {
// Connect to process control port // Connect to process control port
struct ReadWriteOpaque *pc_stream = NULL; struct ReadWriteOpaque *pc_stream = NULL;
err = adapter_connect(adapter, pc_port, &pc_stream); err = adapter_connect(adapter, pc_port, &pc_stream);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to connect to process control port: %d\n", err); fprintf(stderr, "Failed to connect to process control port: [%d] %s",
err->code, err->message);
idevice_error_free(err);
adapter_free(adapter); adapter_free(adapter);
return 1; return 1;
} }
@@ -167,8 +177,10 @@ int main(int argc, char **argv) {
// Create RemoteServerClient // Create RemoteServerClient
struct RemoteServerHandle *remote_server = NULL; struct RemoteServerHandle *remote_server = NULL;
err = remote_server_new(pc_stream, &remote_server); err = remote_server_new(pc_stream, &remote_server);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to create remote server: %d\n", err); fprintf(stderr, "Failed to create remote server: [%d] %s", err->code,
err->message);
idevice_error_free(err);
adapter_free(adapter); adapter_free(adapter);
return 1; return 1;
} }
@@ -176,8 +188,10 @@ int main(int argc, char **argv) {
// Create ProcessControlClient // Create ProcessControlClient
struct ProcessControlHandle *process_control = NULL; struct ProcessControlHandle *process_control = NULL;
err = process_control_new(remote_server, &process_control); err = process_control_new(remote_server, &process_control);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to create process control client: %d\n", err); fprintf(stderr, "Failed to create process control client: [%d] %s",
err->code, err->message);
idevice_error_free(err);
remote_server_free(remote_server); remote_server_free(remote_server);
return 1; return 1;
} }
@@ -186,10 +200,11 @@ int main(int argc, char **argv) {
uint64_t pid; uint64_t pid;
err = process_control_launch_app(process_control, bundle_id, NULL, 0, NULL, 0, err = process_control_launch_app(process_control, bundle_id, NULL, 0, NULL, 0,
true, false, &pid); true, false, &pid);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to launch app: %d\n", err); fprintf(stderr, "Failed to launch app: [%d] %s", err->code, err->message);
process_control_free(process_control); process_control_free(process_control);
remote_server_free(remote_server); remote_server_free(remote_server);
idevice_error_free(err);
return 1; return 1;
} }
printf("Successfully launched app with PID: %" PRIu64 "\n", pid); printf("Successfully launched app with PID: %" PRIu64 "\n", pid);
@@ -202,10 +217,12 @@ int main(int argc, char **argv) {
// Connect to debug proxy port // Connect to debug proxy port
struct ReadWriteOpaque *debug_stream = NULL; struct ReadWriteOpaque *debug_stream = NULL;
err = adapter_connect(adapter, debug_port, &debug_stream); err = adapter_connect(adapter, debug_port, &debug_stream);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to connect to debug proxy port: %d\n", err); fprintf(stderr, "Failed to connect to debug proxy port: [%d] %s", err->code,
err->message);
process_control_free(process_control); process_control_free(process_control);
remote_server_free(remote_server); remote_server_free(remote_server);
idevice_error_free(err);
return 1; return 1;
} }
printf("Successfully connected to debug proxy port\n"); printf("Successfully connected to debug proxy port\n");
@@ -213,10 +230,12 @@ int main(int argc, char **argv) {
// Create DebugProxyClient // Create DebugProxyClient
struct DebugProxyHandle *debug_proxy = NULL; struct DebugProxyHandle *debug_proxy = NULL;
err = debug_proxy_connect_rsd(adapter, rsd_handshake, &debug_proxy); err = debug_proxy_connect_rsd(adapter, rsd_handshake, &debug_proxy);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to create debug proxy client: %d\n", err); fprintf(stderr, "Failed to create debug proxy client: [%d] %s", err->code,
err->message);
process_control_free(process_control); process_control_free(process_control);
remote_server_free(remote_server); remote_server_free(remote_server);
idevice_error_free(err);
return 1; return 1;
} }
@@ -231,6 +250,7 @@ int main(int argc, char **argv) {
debug_proxy_free(debug_proxy); debug_proxy_free(debug_proxy);
process_control_free(process_control); process_control_free(process_control);
remote_server_free(remote_server); remote_server_free(remote_server);
idevice_error_free(err);
return 1; return 1;
} }
@@ -238,8 +258,10 @@ int main(int argc, char **argv) {
err = debug_proxy_send_command(debug_proxy, attach_cmd, &attach_response); err = debug_proxy_send_command(debug_proxy, attach_cmd, &attach_response);
debugserver_command_free(attach_cmd); debugserver_command_free(attach_cmd);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to attach to process: %d\n", err); fprintf(stderr, "Failed to attach to process: [%d] %s", err->code,
err->message);
idevice_error_free(err);
} else if (attach_response != NULL) { } else if (attach_response != NULL) {
printf("Attach response: %s\n", attach_response); printf("Attach response: %s\n", attach_response);
idevice_string_free(attach_response); idevice_string_free(attach_response);
@@ -250,6 +272,7 @@ int main(int argc, char **argv) {
debugserver_command_new("D", NULL, 0); debugserver_command_new("D", NULL, 0);
if (detach_cmd == NULL) { if (detach_cmd == NULL) {
fprintf(stderr, "Failed to create detach command\n"); fprintf(stderr, "Failed to create detach command\n");
idevice_error_free(err);
} else { } else {
char *detach_response = NULL; char *detach_response = NULL;
err = debug_proxy_send_command(debug_proxy, detach_cmd, &detach_response); 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); err = debug_proxy_send_command(debug_proxy, detach_cmd, &detach_response);
debugserver_command_free(detach_cmd); debugserver_command_free(detach_cmd);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to detach from process: %d\n", err); fprintf(stderr, "Failed to detach from process: [%d] %s", err->code,
err->message);
idevice_error_free(err);
} else if (detach_response != NULL) { } else if (detach_response != NULL) {
printf("Detach response: %s\n", detach_response); printf("Detach response: %s\n", detach_response);
idevice_string_free(detach_response); idevice_string_free(detach_response);

View File

@@ -20,10 +20,12 @@ int main() {
// Read pairing file (replace with your pairing file path) // Read pairing file (replace with your pairing file path)
IdevicePairingFile *pairing_file = NULL; IdevicePairingFile *pairing_file = NULL;
IdeviceErrorCode err = IdeviceFfiError *err =
idevice_pairing_file_read("pairing_file.plist", &pairing_file); idevice_pairing_file_read("pairing_file.plist", &pairing_file);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to read pairing file: %d\n", err); fprintf(stderr, "Failed to read pairing file: [%d] %s", err->code,
err->message);
idevice_error_free(err);
return 1; return 1;
} }
@@ -31,18 +33,22 @@ int main() {
IdeviceProviderHandle *provider = NULL; IdeviceProviderHandle *provider = NULL;
err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing_file, err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing_file,
"ExampleProvider", &provider); "ExampleProvider", &provider);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to create TCP provider: %d\n", err); fprintf(stderr, "Failed to create TCP provider: [%d] %s", err->code,
err->message);
idevice_pairing_file_free(pairing_file); idevice_pairing_file_free(pairing_file);
idevice_error_free(err);
return 1; return 1;
} }
// Connect to installation proxy // Connect to installation proxy
HeartbeatClientHandle *client = NULL; HeartbeatClientHandle *client = NULL;
err = heartbeat_connect(provider, &client); err = heartbeat_connect(provider, &client);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to connect to installation proxy: %d\n", err); fprintf(stderr, "Failed to connect to installation proxy: [%d] %s",
err->code, err->message);
idevice_provider_free(provider); idevice_provider_free(provider);
idevice_error_free(err);
return 1; return 1;
} }
idevice_provider_free(provider); idevice_provider_free(provider);
@@ -52,18 +58,20 @@ int main() {
// Get the new interval // Get the new interval
u_int64_t new_interval = 0; u_int64_t new_interval = 0;
err = heartbeat_get_marco(client, current_interval, &new_interval); err = heartbeat_get_marco(client, current_interval, &new_interval);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to get marco: %d\n", err); fprintf(stderr, "Failed to get marco: [%d] %s", err->code, err->message);
heartbeat_client_free(client); heartbeat_client_free(client);
idevice_error_free(err);
return 1; return 1;
} }
current_interval = new_interval + 5; current_interval = new_interval + 5;
// Reply // Reply
err = heartbeat_send_polo(client); err = heartbeat_send_polo(client);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to get marco: %d\n", err); fprintf(stderr, "Failed to get marco: [%d] %s", err->code, err->message);
heartbeat_client_free(client); heartbeat_client_free(client);
idevice_error_free(err);
return 1; return 1;
} }
} }

View File

@@ -100,10 +100,12 @@ int main(int argc, char **argv) {
// Read pairing file // Read pairing file
IdevicePairingFile *pairing_file = NULL; IdevicePairingFile *pairing_file = NULL;
IdeviceErrorCode err = IdeviceFfiError *err =
idevice_pairing_file_read(pairing_file_path, &pairing_file); idevice_pairing_file_read(pairing_file_path, &pairing_file);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to read pairing file: %d\n", err); fprintf(stderr, "Failed to read pairing file: [%d] %s", err->code,
err->message);
idevice_error_free(err);
return 1; return 1;
} }
@@ -111,18 +113,22 @@ int main(int argc, char **argv) {
IdeviceProviderHandle *provider = NULL; IdeviceProviderHandle *provider = NULL;
err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing_file, err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing_file,
"IPAInstaller", &provider); "IPAInstaller", &provider);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to create TCP provider: %d\n", err); fprintf(stderr, "Failed to create TCP provider: [%d] %s", err->code,
err->message);
idevice_pairing_file_free(pairing_file); idevice_pairing_file_free(pairing_file);
idevice_error_free(err);
return 1; return 1;
} }
// Connect to AFC service // Connect to AFC service
AfcClientHandle *afc_client = NULL; AfcClientHandle *afc_client = NULL;
err = afc_client_connect(provider, &afc_client); err = afc_client_connect(provider, &afc_client);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to connect to AFC service: %d\n", err); fprintf(stderr, "Failed to connect to AFC service: [%d] %s", err->code,
err->message);
idevice_provider_free(provider); idevice_provider_free(provider);
idevice_error_free(err);
return 1; return 1;
} }
@@ -150,10 +156,12 @@ int main(int argc, char **argv) {
AfcFileHandle *file = NULL; AfcFileHandle *file = NULL;
err = afc_file_open(afc_client, dest_path, AfcWrOnly, &file); err = afc_file_open(afc_client, dest_path, AfcWrOnly, &file);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to open destination file: %d\n", err); fprintf(stderr, "Failed to open destination file: [%d] %s", err->code,
err->message);
free(data); free(data);
afc_client_free(afc_client); afc_client_free(afc_client);
idevice_error_free(err);
return 1; return 1;
} }
@@ -161,9 +169,10 @@ int main(int argc, char **argv) {
free(data); free(data);
afc_file_close(file); afc_file_close(file);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to write file: %d\n", err); fprintf(stderr, "Failed to write file: [%d] %s", err->code, err->message);
afc_client_free(afc_client); afc_client_free(afc_client);
idevice_error_free(err);
return 1; return 1;
} }
printf("Upload completed successfully\n"); printf("Upload completed successfully\n");
@@ -171,17 +180,20 @@ int main(int argc, char **argv) {
// Connect to installation proxy // Connect to installation proxy
InstallationProxyClientHandle *instproxy_client = NULL; InstallationProxyClientHandle *instproxy_client = NULL;
err = installation_proxy_connect_tcp(provider, &instproxy_client); err = installation_proxy_connect_tcp(provider, &instproxy_client);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to connect to installation proxy: %d\n", err); fprintf(stderr, "Failed to connect to installation proxy: [%d] %s",
err->code, err->message);
afc_client_free(afc_client); afc_client_free(afc_client);
idevice_error_free(err);
return 1; return 1;
} }
// Install the uploaded IPA // Install the uploaded IPA
printf("Installing %s...\n", dest_path); printf("Installing %s...\n", dest_path);
err = installation_proxy_install(instproxy_client, dest_path, NULL); err = installation_proxy_install(instproxy_client, dest_path, NULL);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to install IPA: %d\n", err); fprintf(stderr, "Failed to install IPA: [%d] %s", err->code, err->message);
idevice_error_free(err);
} else { } else {
printf("Installation completed successfully\n"); printf("Installation completed successfully\n");
} }
@@ -191,5 +203,5 @@ int main(int argc, char **argv) {
afc_client_free(afc_client); afc_client_free(afc_client);
idevice_provider_free(provider); idevice_provider_free(provider);
return err == IdeviceSuccess ? 0 : 1; return err == NULL ? 0 : 1;
} }

View File

@@ -19,10 +19,12 @@ int main() {
// Read pairing file (replace with your pairing file path) // Read pairing file (replace with your pairing file path)
IdevicePairingFile *pairing_file = NULL; IdevicePairingFile *pairing_file = NULL;
IdeviceErrorCode err = IdeviceFfiError *err =
idevice_pairing_file_read("pairing_file.plist", &pairing_file); idevice_pairing_file_read("pairing_file.plist", &pairing_file);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to read pairing file: %d\n", err); fprintf(stderr, "Failed to read pairing file: [%d] %s", err->code,
err->message);
idevice_error_free(err);
return 1; return 1;
} }
@@ -30,18 +32,22 @@ int main() {
IdeviceProviderHandle *provider = NULL; IdeviceProviderHandle *provider = NULL;
err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing_file, err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing_file,
"ExampleProvider", &provider); "ExampleProvider", &provider);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to create TCP provider: %d\n", err); fprintf(stderr, "Failed to create TCP provider: [%d] %s", err->code,
err->message);
idevice_pairing_file_free(pairing_file); idevice_pairing_file_free(pairing_file);
idevice_error_free(err);
return 1; return 1;
} }
// Connect to installation proxy // Connect to installation proxy
InstallationProxyClientHandle *client = NULL; InstallationProxyClientHandle *client = NULL;
err = installation_proxy_connect_tcp(provider, &client); err = installation_proxy_connect_tcp(provider, &client);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to connect to installation proxy: %d\n", err); fprintf(stderr, "Failed to connect to installation proxy: [%d] %s",
err->code, err->message);
idevice_provider_free(provider); idevice_provider_free(provider);
idevice_error_free(err);
return 1; return 1;
} }
@@ -53,9 +59,10 @@ int main() {
NULL, // bundle_identifiers filter NULL, // bundle_identifiers filter
0, // bundle_identifiers length 0, // bundle_identifiers length
&apps, &apps_len); &apps, &apps_len);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to get apps: %d\n", err); fprintf(stderr, "Failed to get apps: [%d] %s", err->code, err->message);
installation_proxy_client_free(client); installation_proxy_client_free(client);
idevice_error_free(err);
idevice_provider_free(provider); idevice_provider_free(provider);
return 1; return 1;
} }

View File

@@ -33,9 +33,11 @@ int main(int argc, char **argv) {
// Read pairing file // Read pairing file
IdevicePairingFile *pairing = NULL; IdevicePairingFile *pairing = NULL;
IdeviceErrorCode err = idevice_pairing_file_read(pairing_file, &pairing); IdeviceFfiError *err = idevice_pairing_file_read(pairing_file, &pairing);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to read pairing file: %d\n", err); fprintf(stderr, "Failed to read pairing file: [%d] %s", err->code,
err->message);
idevice_error_free(err);
return 1; return 1;
} }
@@ -43,8 +45,10 @@ int main(int argc, char **argv) {
IdeviceProviderHandle *tcp_provider = NULL; IdeviceProviderHandle *tcp_provider = NULL;
err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing, err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing,
"LocationSimCLI", &tcp_provider); "LocationSimCLI", &tcp_provider);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to create TCP provider: %d\n", err); fprintf(stderr, "Failed to create TCP provider: [%d] %s", err->code,
err->message);
idevice_error_free(err);
idevice_pairing_file_free(pairing); idevice_pairing_file_free(pairing);
return 1; return 1;
} }
@@ -54,16 +58,20 @@ int main(int argc, char **argv) {
err = core_device_proxy_connect(tcp_provider, &core_device); err = core_device_proxy_connect(tcp_provider, &core_device);
idevice_provider_free(tcp_provider); idevice_provider_free(tcp_provider);
idevice_pairing_file_free(pairing); idevice_pairing_file_free(pairing);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to connect to CoreDeviceProxy: %d\n", err); fprintf(stderr, "Failed to connect to CoreDeviceProxy: [%d] %s", err->code,
err->message);
idevice_error_free(err);
return 1; return 1;
} }
// Get server RSD port // Get server RSD port
uint16_t rsd_port; uint16_t rsd_port;
err = core_device_proxy_get_server_rsd_port(core_device, &rsd_port); err = core_device_proxy_get_server_rsd_port(core_device, &rsd_port);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to get server RSD port: %d\n", err); fprintf(stderr, "Failed to get server RSD port: [%d] %s", err->code,
err->message);
idevice_error_free(err);
core_device_proxy_free(core_device); core_device_proxy_free(core_device);
return 1; return 1;
} }
@@ -72,24 +80,30 @@ int main(int argc, char **argv) {
AdapterHandle *adapter = NULL; AdapterHandle *adapter = NULL;
err = core_device_proxy_create_tcp_adapter(core_device, &adapter); err = core_device_proxy_create_tcp_adapter(core_device, &adapter);
core_device_proxy_free(core_device); core_device_proxy_free(core_device);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to create TCP adapter: %d\n", err); fprintf(stderr, "Failed to create TCP adapter: [%d] %s", err->code,
err->message);
idevice_error_free(err);
return 1; return 1;
} }
// Connect to RSD port // Connect to RSD port
AdapterStreamHandle *stream = NULL; AdapterStreamHandle *stream = NULL;
err = adapter_connect(adapter, rsd_port, &stream); err = adapter_connect(adapter, rsd_port, &stream);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to connect to RSD port: %d\n", err); fprintf(stderr, "Failed to connect to RSD port: [%d] %s", err->code,
err->message);
idevice_error_free(err);
adapter_free(adapter); adapter_free(adapter);
return 1; return 1;
} }
RsdHandshakeHandle *handshake = NULL; RsdHandshakeHandle *handshake = NULL;
err = rsd_handshake_new(stream, &handshake); err = rsd_handshake_new(stream, &handshake);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to perform RSD handshake: %d\n", err); fprintf(stderr, "Failed to perform RSD handshake: [%d] %s", err->code,
err->message);
idevice_error_free(err);
adapter_close(stream); adapter_close(stream);
adapter_free(adapter); adapter_free(adapter);
return 1; return 1;
@@ -98,8 +112,10 @@ int main(int argc, char **argv) {
// Create RemoteServerClient // Create RemoteServerClient
RemoteServerHandle *remote_server = NULL; RemoteServerHandle *remote_server = NULL;
err = remote_server_connect_rsd(adapter, handshake, &remote_server); err = remote_server_connect_rsd(adapter, handshake, &remote_server);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to create remote server: %d\n", err); fprintf(stderr, "Failed to create remote server: [%d] %s", err->code,
err->message);
idevice_error_free(err);
adapter_free(adapter); adapter_free(adapter);
rsd_handshake_free(handshake); rsd_handshake_free(handshake);
return 1; return 1;
@@ -108,16 +124,19 @@ int main(int argc, char **argv) {
// Create LocationSimulationClient // Create LocationSimulationClient
LocationSimulationHandle *location_sim = NULL; LocationSimulationHandle *location_sim = NULL;
err = location_simulation_new(remote_server, &location_sim); err = location_simulation_new(remote_server, &location_sim);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to create location simulation client: %d\n", err); fprintf(stderr, "Failed to create location simulation client: [%d] %s",
err->code, err->message);
idevice_error_free(err);
remote_server_free(remote_server); remote_server_free(remote_server);
return 1; return 1;
} }
// Set location // Set location
err = location_simulation_set(location_sim, latitude, longitude); err = location_simulation_set(location_sim, latitude, longitude);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to set location: %d\n", err); fprintf(stderr, "Failed to set location: [%d] %s", err->code, err->message);
idevice_error_free(err);
} else { } else {
printf("Successfully set location to %.6f, %.6f\n", latitude, longitude); printf("Successfully set location to %.6f, %.6f\n", latitude, longitude);
} }
@@ -127,8 +146,10 @@ int main(int argc, char **argv) {
// Clear location // Clear location
err = location_simulation_clear(location_sim); err = location_simulation_clear(location_sim);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to clear location: %d\n", err); fprintf(stderr, "Failed to clear location: [%d] %s", err->code,
err->message);
idevice_error_free(err);
} else { } else {
printf("Successfully cleared simulated location\n"); printf("Successfully cleared simulated location\n");
} }

View File

@@ -21,10 +21,12 @@ int main() {
// Read pairing file (replace with your pairing file path) // Read pairing file (replace with your pairing file path)
IdevicePairingFile *pairing_file = NULL; IdevicePairingFile *pairing_file = NULL;
IdeviceErrorCode err = IdeviceFfiError *err =
idevice_pairing_file_read("pairing_file.plist", &pairing_file); idevice_pairing_file_read("pairing_file.plist", &pairing_file);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to read pairing file: %d\n", err); fprintf(stderr, "Failed to read pairing file: [%d] %s", err->code,
err->message);
idevice_error_free(err);
return 1; return 1;
} }
@@ -32,8 +34,10 @@ int main() {
IdeviceProviderHandle *provider = NULL; IdeviceProviderHandle *provider = NULL;
err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing_file, err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing_file,
"LockdowndTest", &provider); "LockdowndTest", &provider);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to create TCP provider: %d\n", err); fprintf(stderr, "Failed to create TCP provider: [%d] %s", err->code,
err->message);
idevice_error_free(err);
idevice_pairing_file_free(pairing_file); idevice_pairing_file_free(pairing_file);
return 1; return 1;
} }
@@ -41,8 +45,10 @@ int main() {
// Connect to lockdownd // Connect to lockdownd
LockdowndClientHandle *client = NULL; LockdowndClientHandle *client = NULL;
err = lockdownd_connect(provider, &client); err = lockdownd_connect(provider, &client);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to connect to lockdownd: %d\n", err); fprintf(stderr, "Failed to connect to lockdownd: [%d] %s", err->code,
err->message);
idevice_error_free(err);
idevice_provider_free(provider); idevice_provider_free(provider);
return 1; return 1;
} }
@@ -50,15 +56,19 @@ int main() {
// Read pairing file (replace with your pairing file path) // Read pairing file (replace with your pairing file path)
IdevicePairingFile *pairing_file_2 = NULL; IdevicePairingFile *pairing_file_2 = NULL;
err = idevice_pairing_file_read("pairing_file.plist", &pairing_file_2); err = idevice_pairing_file_read("pairing_file.plist", &pairing_file_2);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to read pairing file: %d\n", err); fprintf(stderr, "Failed to read pairing file: [%d] %s", err->code,
err->message);
idevice_error_free(err);
return 1; return 1;
} }
// Start session // Start session
err = lockdownd_start_session(client, pairing_file_2); err = lockdownd_start_session(client, pairing_file_2);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to start session: %d\n", err); fprintf(stderr, "Failed to start session: [%d] %s", err->code,
err->message);
idevice_error_free(err);
lockdownd_client_free(client); lockdownd_client_free(client);
idevice_provider_free(provider); idevice_provider_free(provider);
return 1; return 1;
@@ -67,8 +77,10 @@ int main() {
// Get device name // Get device name
plist_t name_plist = NULL; plist_t name_plist = NULL;
err = lockdownd_get_value(client, "DeviceName", NULL, &name_plist); err = lockdownd_get_value(client, "DeviceName", NULL, &name_plist);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to get device name: %d\n", err); fprintf(stderr, "Failed to get device name: [%d] %s", err->code,
err->message);
idevice_error_free(err);
} else { } else {
char *name = NULL; char *name = NULL;
plist_get_string_val(name_plist, &name); plist_get_string_val(name_plist, &name);
@@ -80,8 +92,10 @@ int main() {
// Get product version // Get product version
plist_t version_plist = NULL; plist_t version_plist = NULL;
err = lockdownd_get_value(client, "ProductVersion", NULL, &version_plist); err = lockdownd_get_value(client, "ProductVersion", NULL, &version_plist);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to get product version: %d\n", err); fprintf(stderr, "Failed to get product version: [%d] %s", err->code,
err->message);
idevice_error_free(err);
} else { } else {
char *version = NULL; char *version = NULL;
plist_get_string_val(version_plist, &version); plist_get_string_val(version_plist, &version);
@@ -95,8 +109,10 @@ int main() {
err = err =
lockdownd_get_value(client, "DeveloperModeStatus", lockdownd_get_value(client, "DeveloperModeStatus",
"com.apple.security.mac.amfi", &developer_mode_plist); "com.apple.security.mac.amfi", &developer_mode_plist);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to get product version: %d\n", err); fprintf(stderr, "Failed to get product version: [%d] %s", err->code,
err->message);
idevice_error_free(err);
} else { } else {
uint8_t enabled = 0; uint8_t enabled = 0;
plist_get_bool_val(developer_mode_plist, &enabled); plist_get_bool_val(developer_mode_plist, &enabled);
@@ -107,8 +123,10 @@ int main() {
// Get all values // Get all values
plist_t all_values = NULL; plist_t all_values = NULL;
err = lockdownd_get_all_values(client, &all_values); err = lockdownd_get_all_values(client, &all_values);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to get all values: %d\n", err); fprintf(stderr, "Failed to get all values: [%d] %s", err->code,
err->message);
idevice_error_free(err);
} else { } else {
printf("\nAll device values:\n"); printf("\nAll device values:\n");
// Iterate through dictionary (simplified example) // Iterate through dictionary (simplified example)
@@ -150,8 +168,10 @@ int main() {
bool ssl = false; bool ssl = false;
err = lockdownd_start_service(client, "com.apple.mobile.heartbeat", &port, err = lockdownd_start_service(client, "com.apple.mobile.heartbeat", &port,
&ssl); &ssl);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to start heartbeat service: %d\n", err); fprintf(stderr, "Failed to start heartbeat service: [%d] %s", err->code,
err->message);
idevice_error_free(err);
} else { } else {
printf("\nStarted heartbeat service on port %d (SSL: %s)\n", port, printf("\nStarted heartbeat service on port %d (SSL: %s)\n", port,
ssl ? "true" : "false"); ssl ? "true" : "false");

View File

@@ -88,10 +88,12 @@ int main(int argc, char **argv) {
// Read pairing file // Read pairing file
IdevicePairingFile *pairing_file = NULL; IdevicePairingFile *pairing_file = NULL;
IdeviceErrorCode err = IdeviceFfiError *err =
idevice_pairing_file_read(pairing_file_path, &pairing_file); idevice_pairing_file_read(pairing_file_path, &pairing_file);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to read pairing file: %d\n", err); fprintf(stderr, "Failed to read pairing file: [%d] %s", err->code,
err->message);
idevice_error_free(err);
free(image); free(image);
free(trustcache); free(trustcache);
free(build_manifest); free(build_manifest);
@@ -102,8 +104,10 @@ int main(int argc, char **argv) {
IdeviceProviderHandle *provider = NULL; IdeviceProviderHandle *provider = NULL;
err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing_file, err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing_file,
"ImageMounterTest", &provider); "ImageMounterTest", &provider);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to create TCP provider: %d\n", err); fprintf(stderr, "Failed to create TCP provider: [%d] %s", err->code,
err->message);
idevice_error_free(err);
idevice_pairing_file_free(pairing_file); idevice_pairing_file_free(pairing_file);
free(image); free(image);
free(trustcache); free(trustcache);
@@ -114,8 +118,10 @@ int main(int argc, char **argv) {
// Read pairing file // Read pairing file
IdevicePairingFile *pairing_file_2 = NULL; IdevicePairingFile *pairing_file_2 = NULL;
err = idevice_pairing_file_read(pairing_file_path, &pairing_file_2); err = idevice_pairing_file_read(pairing_file_path, &pairing_file_2);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to read pairing file: %d\n", err); fprintf(stderr, "Failed to read pairing file: [%d] %s", err->code,
err->message);
idevice_error_free(err);
free(image); free(image);
free(trustcache); free(trustcache);
free(build_manifest); free(build_manifest);
@@ -125,8 +131,10 @@ int main(int argc, char **argv) {
// Connect to lockdownd // Connect to lockdownd
LockdowndClientHandle *lockdown_client = NULL; LockdowndClientHandle *lockdown_client = NULL;
err = lockdownd_connect(provider, &lockdown_client); err = lockdownd_connect(provider, &lockdown_client);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to connect to lockdownd: %d\n", err); fprintf(stderr, "Failed to connect to lockdownd: [%d] %s", err->code,
err->message);
idevice_error_free(err);
idevice_provider_free(provider); idevice_provider_free(provider);
free(image); free(image);
free(trustcache); free(trustcache);
@@ -136,8 +144,10 @@ int main(int argc, char **argv) {
// Start session // Start session
err = lockdownd_start_session(lockdown_client, pairing_file_2); err = lockdownd_start_session(lockdown_client, pairing_file_2);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to start session: %d\n", err); fprintf(stderr, "Failed to start session: [%d] %s", err->code,
err->message);
idevice_error_free(err);
lockdownd_client_free(lockdown_client); lockdownd_client_free(lockdown_client);
idevice_provider_free(provider); idevice_provider_free(provider);
idevice_pairing_file_free(pairing_file_2); idevice_pairing_file_free(pairing_file_2);
@@ -152,8 +162,10 @@ int main(int argc, char **argv) {
plist_t unique_chip_id_plist = NULL; plist_t unique_chip_id_plist = NULL;
err = lockdownd_get_value(lockdown_client, "UniqueChipID", NULL, err = lockdownd_get_value(lockdown_client, "UniqueChipID", NULL,
&unique_chip_id_plist); &unique_chip_id_plist);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to get UniqueChipID: %d\n", err); fprintf(stderr, "Failed to get UniqueChipID: [%d] %s", err->code,
err->message);
idevice_error_free(err);
lockdownd_client_free(lockdown_client); lockdownd_client_free(lockdown_client);
idevice_provider_free(provider); idevice_provider_free(provider);
free(image); free(image);
@@ -169,8 +181,10 @@ int main(int argc, char **argv) {
// Connect to image mounter // Connect to image mounter
ImageMounterHandle *mounter_client = NULL; ImageMounterHandle *mounter_client = NULL;
err = image_mounter_connect(provider, &mounter_client); err = image_mounter_connect(provider, &mounter_client);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to connect to image mounter: %d\n", err); fprintf(stderr, "Failed to connect to image mounter: [%d] %s", err->code,
err->message);
idevice_error_free(err);
lockdownd_client_free(lockdown_client); lockdownd_client_free(lockdown_client);
idevice_provider_free(provider); idevice_provider_free(provider);
free(image); free(image);
@@ -186,8 +200,10 @@ int main(int argc, char **argv) {
NULL, // info_plist NULL, // info_plist
unique_chip_id, progress_callback, NULL); unique_chip_id, progress_callback, NULL);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to mount personalized image: %d\n", err); fprintf(stderr, "Failed to mount personalized image: [%d] %s", err->code,
err->message);
idevice_error_free(err);
} else { } else {
printf("Successfully mounted personalized image!\n"); printf("Successfully mounted personalized image!\n");
} }
@@ -200,5 +216,5 @@ int main(int argc, char **argv) {
free(trustcache); free(trustcache);
free(build_manifest); free(build_manifest);
return err == IdeviceSuccess ? 0 : 1; return err == NULL ? 0 : 1;
} }

View File

@@ -104,10 +104,12 @@ int main(int argc, char **argv) {
// Read pairing file // Read pairing file
IdevicePairingFile *pairing_file = NULL; IdevicePairingFile *pairing_file = NULL;
IdeviceErrorCode err = IdeviceFfiError *err =
idevice_pairing_file_read(pairing_file_path, &pairing_file); idevice_pairing_file_read(pairing_file_path, &pairing_file);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to read pairing file: %d\n", err); fprintf(stderr, "Failed to read pairing file: [%d] %s", err->code,
err->message);
idevice_error_free(err);
return 1; return 1;
} }
@@ -115,8 +117,10 @@ int main(int argc, char **argv) {
IdeviceProviderHandle *provider = NULL; IdeviceProviderHandle *provider = NULL;
err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing_file, err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing_file,
"ImageMounterTest", &provider); "ImageMounterTest", &provider);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to create TCP provider: %d\n", err); fprintf(stderr, "Failed to create TCP provider: [%d] %s", err->code,
err->message);
idevice_error_free(err);
idevice_pairing_file_free(pairing_file); idevice_pairing_file_free(pairing_file);
return 1; return 1;
} }
@@ -124,8 +128,10 @@ int main(int argc, char **argv) {
// Connect to image mounter // Connect to image mounter
ImageMounterHandle *client = NULL; ImageMounterHandle *client = NULL;
err = image_mounter_connect(provider, &client); err = image_mounter_connect(provider, &client);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to connect to image mounter: %d\n", err); fprintf(stderr, "Failed to connect to image mounter: [%d] %s", err->code,
err->message);
idevice_error_free(err);
idevice_provider_free(provider); idevice_provider_free(provider);
return 1; return 1;
} }
@@ -137,7 +143,7 @@ int main(int argc, char **argv) {
void *devices = NULL; void *devices = NULL;
size_t devices_len = 0; size_t devices_len = 0;
err = image_mounter_copy_devices(client, &devices, &devices_len); err = image_mounter_copy_devices(client, &devices, &devices_len);
if (err == IdeviceSuccess) { if (err == NULL) {
plist_t *device_list = (plist_t *)devices; plist_t *device_list = (plist_t *)devices;
printf("Mounted devices:\n"); printf("Mounted devices:\n");
for (size_t i = 0; i < devices_len; i++) { for (size_t i = 0; i < devices_len; i++) {
@@ -150,7 +156,9 @@ int main(int argc, char **argv) {
plist_free(device); plist_free(device);
} }
} else { } 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; success = 0;
} }
} else if (strcmp(command, "lookup") == 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, err = image_mounter_lookup_image(client, image_type, &signature,
&signature_len); &signature_len);
if (err == IdeviceSuccess) { if (err == NULL) {
printf("Signature for %s (%zu bytes):\n", image_type, signature_len); printf("Signature for %s (%zu bytes):\n", image_type, signature_len);
for (size_t i = 0; i < signature_len; i++) { for (size_t i = 0; i < signature_len; i++) {
printf("%02x", signature[i]); printf("%02x", signature[i]);
@@ -172,7 +180,9 @@ int main(int argc, char **argv) {
printf("\n"); printf("\n");
free(signature); free(signature);
} else { } 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; success = 0;
} }
} }
@@ -199,10 +209,12 @@ int main(int argc, char **argv) {
err = image_mounter_upload_image(client, image_type, image_data, err = image_mounter_upload_image(client, image_type, image_data,
image_len, signature_data, image_len, signature_data,
signature_len); signature_len);
if (err == IdeviceSuccess) { if (err == NULL) {
printf("Image uploaded successfully\n"); printf("Image uploaded successfully\n");
} else { } 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; success = 0;
} }
@@ -236,10 +248,12 @@ int main(int argc, char **argv) {
client, image_type, signature_data, signature_len, client, image_type, signature_data, signature_len,
trust_cache_data, trust_cache_len, trust_cache_data, trust_cache_len,
NULL); // No info plist in this example NULL); // No info plist in this example
if (err == IdeviceSuccess) { if (err == NULL) {
printf("Image mounted successfully\n"); printf("Image mounted successfully\n");
} else { } 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; success = 0;
} }
@@ -256,20 +270,24 @@ int main(int argc, char **argv) {
} else { } else {
char *mount_path = argv[2]; char *mount_path = argv[2];
err = image_mounter_unmount_image(client, mount_path); err = image_mounter_unmount_image(client, mount_path);
if (err == IdeviceSuccess) { if (err == NULL) {
printf("Image unmounted successfully\n"); printf("Image unmounted successfully\n");
} else { } 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; success = 0;
} }
} }
} else if (strcmp(command, "dev-status") == 0) { } else if (strcmp(command, "dev-status") == 0) {
int status = 0; int status = 0;
err = image_mounter_query_developer_mode_status(client, &status); err = image_mounter_query_developer_mode_status(client, &status);
if (err == IdeviceSuccess) { if (err == NULL) {
printf("Developer mode status: %s\n", status ? "enabled" : "disabled"); printf("Developer mode status: %s\n", status ? "enabled" : "disabled");
} else { } 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; success = 0;
} }
} else if (strcmp(command, "mount-dev") == 0) { } else if (strcmp(command, "mount-dev") == 0) {
@@ -293,10 +311,12 @@ int main(int argc, char **argv) {
} else { } else {
err = image_mounter_mount_developer(client, image_data, image_len, err = image_mounter_mount_developer(client, image_data, image_len,
signature_data, signature_len); signature_data, signature_len);
if (err == IdeviceSuccess) { if (err == NULL) {
printf("Developer image mounted successfully\n"); printf("Developer image mounted successfully\n");
} else { } 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; success = 0;
} }

View File

@@ -31,9 +31,11 @@ int main(int argc, char **argv) {
// Read pairing file // Read pairing file
IdevicePairingFile *pairing = NULL; IdevicePairingFile *pairing = NULL;
IdeviceErrorCode err = idevice_pairing_file_read(pairing_file, &pairing); IdeviceFfiError *err = idevice_pairing_file_read(pairing_file, &pairing);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to read pairing file: %d\n", err); fprintf(stderr, "Failed to read pairing file: [%d] %s", err->code,
err->message);
idevice_error_free(err);
return 1; return 1;
} }
@@ -46,8 +48,10 @@ int main(int argc, char **argv) {
IdeviceProviderHandle *tcp_provider = NULL; IdeviceProviderHandle *tcp_provider = NULL;
err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing, err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing,
"ProcessControlTest", &tcp_provider); "ProcessControlTest", &tcp_provider);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to create TCP provider: %d\n", err); fprintf(stderr, "Failed to create TCP provider: [%d] %s", err->code,
err->message);
idevice_error_free(err);
idevice_pairing_file_free(pairing); idevice_pairing_file_free(pairing);
return 1; return 1;
} }
@@ -55,8 +59,10 @@ int main(int argc, char **argv) {
// Connect to CoreDeviceProxy // Connect to CoreDeviceProxy
CoreDeviceProxyHandle *core_device = NULL; CoreDeviceProxyHandle *core_device = NULL;
err = core_device_proxy_connect(tcp_provider, &core_device); err = core_device_proxy_connect(tcp_provider, &core_device);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to connect to CoreDeviceProxy: %d\n", err); fprintf(stderr, "Failed to connect to CoreDeviceProxy: [%d] %s", err->code,
err->message);
idevice_error_free(err);
idevice_provider_free(tcp_provider); idevice_provider_free(tcp_provider);
idevice_pairing_file_free(pairing); idevice_pairing_file_free(pairing);
return 1; return 1;
@@ -66,8 +72,10 @@ int main(int argc, char **argv) {
// Get server RSD port // Get server RSD port
uint16_t rsd_port; uint16_t rsd_port;
err = core_device_proxy_get_server_rsd_port(core_device, &rsd_port); err = core_device_proxy_get_server_rsd_port(core_device, &rsd_port);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to get server RSD port: %d\n", err); fprintf(stderr, "Failed to get server RSD port: [%d] %s", err->code,
err->message);
idevice_error_free(err);
core_device_proxy_free(core_device); core_device_proxy_free(core_device);
idevice_pairing_file_free(pairing); idevice_pairing_file_free(pairing);
return 1; return 1;
@@ -81,8 +89,10 @@ int main(int argc, char **argv) {
AdapterHandle *adapter = NULL; AdapterHandle *adapter = NULL;
err = core_device_proxy_create_tcp_adapter(core_device, &adapter); err = core_device_proxy_create_tcp_adapter(core_device, &adapter);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to create TCP adapter: %d\n", err); fprintf(stderr, "Failed to create TCP adapter: [%d] %s", err->code,
err->message);
idevice_error_free(err);
core_device_proxy_free(core_device); core_device_proxy_free(core_device);
idevice_pairing_file_free(pairing); idevice_pairing_file_free(pairing);
return 1; return 1;
@@ -91,16 +101,20 @@ int main(int argc, char **argv) {
// Connect to RSD port // Connect to RSD port
AdapterStreamHandle *stream = NULL; AdapterStreamHandle *stream = NULL;
err = adapter_connect(adapter, rsd_port, &stream); err = adapter_connect(adapter, rsd_port, &stream);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to connect to RSD port: %d\n", err); fprintf(stderr, "Failed to connect to RSD port: [%d] %s", err->code,
err->message);
idevice_error_free(err);
adapter_free(adapter); adapter_free(adapter);
return 1; return 1;
} }
RsdHandshakeHandle *handshake = NULL; RsdHandshakeHandle *handshake = NULL;
err = rsd_handshake_new(stream, &handshake); err = rsd_handshake_new(stream, &handshake);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to perform RSD handshake: %d\n", err); fprintf(stderr, "Failed to perform RSD handshake: [%d] %s", err->code,
err->message);
idevice_error_free(err);
adapter_close(stream); adapter_close(stream);
adapter_free(adapter); adapter_free(adapter);
return 1; return 1;
@@ -109,8 +123,10 @@ int main(int argc, char **argv) {
// Create RemoteServerClient // Create RemoteServerClient
RemoteServerHandle *remote_server = NULL; RemoteServerHandle *remote_server = NULL;
err = remote_server_connect_rsd(adapter, handshake, &remote_server); err = remote_server_connect_rsd(adapter, handshake, &remote_server);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to create remote server: %d\n", err); fprintf(stderr, "Failed to create remote server: [%d] %s", err->code,
err->message);
idevice_error_free(err);
adapter_free(adapter); adapter_free(adapter);
rsd_handshake_free(handshake); rsd_handshake_free(handshake);
return 1; return 1;
@@ -121,8 +137,10 @@ int main(int argc, char **argv) {
// Create ProcessControlClient // Create ProcessControlClient
ProcessControlHandle *process_control = NULL; ProcessControlHandle *process_control = NULL;
err = process_control_new(remote_server, &process_control); err = process_control_new(remote_server, &process_control);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to create process control client: %d\n", err); fprintf(stderr, "Failed to create process control client: [%d] %s",
err->code, err->message);
idevice_error_free(err);
remote_server_free(remote_server); remote_server_free(remote_server);
return 1; return 1;
} }
@@ -131,8 +149,9 @@ int main(int argc, char **argv) {
uint64_t pid; uint64_t pid;
err = process_control_launch_app(process_control, bundle_id, NULL, 0, NULL, 0, err = process_control_launch_app(process_control, bundle_id, NULL, 0, NULL, 0,
true, false, &pid); true, false, &pid);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to launch app: %d\n", err); fprintf(stderr, "Failed to launch app: [%d] %s", err->code, err->message);
idevice_error_free(err);
process_control_free(process_control); process_control_free(process_control);
remote_server_free(remote_server); remote_server_free(remote_server);
return 1; return 1;
@@ -141,8 +160,10 @@ int main(int argc, char **argv) {
// Disable memory limits // Disable memory limits
err = process_control_disable_memory_limit(process_control, pid); err = process_control_disable_memory_limit(process_control, pid);
if (err != IdeviceSuccess) { if (err != NULL) {
fprintf(stderr, "Failed to disable memory limits: %d\n", err); fprintf(stderr, "Failed to disable memory limits: [%d] %s", err->code,
err->message);
idevice_error_free(err);
} else { } else {
printf("Successfully disabled memory limits\n"); printf("Successfully disabled memory limits\n");
} }

View File

@@ -1,11 +1,12 @@
// Jackson Coxson // Jackson Coxson
use std::ffi::{CStr, c_char}; use std::ffi::{CStr, c_char};
use std::ptr::null_mut;
use idevice::tcp::stream::AdapterStream; use idevice::tcp::stream::AdapterStream;
use crate::core_device_proxy::AdapterHandle; 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>); 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 /// * [`stream_handle`] - A pointer to allocate the new stream to
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// Null on success, an IdeviceFfiError otherwise
/// ///
/// # Safety /// # Safety
/// `handle` must be a valid pointer to a handle allocated by this library. /// `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, adapter_handle: *mut AdapterHandle,
port: u16, port: u16,
stream_handle: *mut *mut ReadWriteOpaque, stream_handle: *mut *mut ReadWriteOpaque,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if adapter_handle.is_null() || stream_handle.is_null() { if adapter_handle.is_null() || stream_handle.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let adapter = unsafe { &mut (*adapter_handle).0 }; let adapter = unsafe { &mut (*adapter_handle).0 };
@@ -42,11 +43,11 @@ pub unsafe extern "C" fn adapter_connect(
inner: Some(Box::new(r)), inner: Some(Box::new(r)),
}); });
unsafe { *stream_handle = Box::into_raw(boxed) }; unsafe { *stream_handle = Box::into_raw(boxed) };
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
Err(e) => { Err(e) => {
log::error!("Adapter connect failed: {}", 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) /// * [`path`] - The path to save the PCAP file (null-terminated string)
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// Null on success, an IdeviceFfiError otherwise
/// ///
/// # Safety /// # Safety
/// `handle` must be a valid pointer to a handle allocated by this library /// `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( pub unsafe extern "C" fn adapter_pcap(
handle: *mut AdapterHandle, handle: *mut AdapterHandle,
path: *const c_char, path: *const c_char,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if handle.is_null() || path.is_null() { if handle.is_null() || path.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let adapter = unsafe { &mut (*handle).0 }; let adapter = unsafe { &mut (*handle).0 };
let c_str = unsafe { CStr::from_ptr(path) }; let c_str = unsafe { CStr::from_ptr(path) };
let path_str = match c_str.to_str() { let path_str = match c_str.to_str() {
Ok(s) => s, 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 }); let res = RUNTIME.block_on(async move { adapter.pcap(path_str).await });
match res { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => { Err(e) => {
log::error!("Adapter pcap failed: {}", 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 /// * [`handle`] - The adapter stream handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// Null on success, an IdeviceFfiError otherwise
/// ///
/// # Safety /// # Safety
/// `handle` must be a valid pointer to a handle allocated by this library /// `handle` must be a valid pointer to a handle allocated by this library
#[unsafe(no_mangle)] #[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() { if handle.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let adapter = unsafe { &mut (*handle).0 }; let adapter = unsafe { &mut (*handle).0 };
let res = RUNTIME.block_on(async move { adapter.close().await }); let res = RUNTIME.block_on(async move { adapter.close().await });
match res { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => { Err(e) => {
log::error!("Adapter close failed: {}", 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 /// * [`length`] - The length of the data
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// Null on success, an IdeviceFfiError otherwise
/// ///
/// # Safety /// # Safety
/// `handle` must be a valid pointer to a handle allocated by this library /// `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, handle: *mut AdapterStreamHandle,
data: *const u8, data: *const u8,
length: usize, length: usize,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if handle.is_null() || data.is_null() { if handle.is_null() || data.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let adapter = unsafe { &mut (*handle).0 }; 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 }); let res = RUNTIME.block_on(async move { adapter.psh(data_slice).await });
match res { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => { Err(e) => {
log::error!("Adapter send failed: {}", 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` /// * [`max_length`] - Maximum number of bytes that can be stored in `data`
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// Null on success, an IdeviceFfiError otherwise
/// ///
/// # Safety /// # Safety
/// `handle` must be a valid pointer to a handle allocated by this library /// `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, data: *mut u8,
length: *mut usize, length: *mut usize,
max_length: usize, max_length: usize,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if handle.is_null() || data.is_null() || length.is_null() { if handle.is_null() || data.is_null() || length.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let adapter = unsafe { &mut (*handle).0 }; let adapter = unsafe { &mut (*handle).0 };
@@ -188,7 +189,7 @@ pub unsafe extern "C" fn adapter_recv(
Ok(received_data) => { Ok(received_data) => {
let received_len = received_data.len(); let received_len = received_data.len();
if received_len > max_length { if received_len > max_length {
return IdeviceErrorCode::BufferTooSmall; return ffi_err!(IdeviceError::FfiBufferTooSmall(received_len, max_length));
} }
unsafe { unsafe {
@@ -196,11 +197,11 @@ pub unsafe extern "C" fn adapter_recv(
*length = received_len; *length = received_len;
} }
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
Err(e) => { Err(e) => {
log::error!("Adapter recv failed: {}", e); log::error!("Adapter recv failed: {}", e);
IdeviceErrorCode::AdapterIOFailed ffi_err!(e)
} }
} }
} }

View File

@@ -1,12 +1,14 @@
// Jackson Coxson // Jackson Coxson
use std::ptr::null_mut;
use idevice::{ use idevice::{
IdeviceError, IdeviceService, IdeviceError, IdeviceService,
afc::{AfcClient, DeviceInfo, FileInfo}, afc::{AfcClient, DeviceInfo, FileInfo},
provider::IdeviceProvider, provider::IdeviceProvider,
}; };
use crate::{IdeviceErrorCode, IdeviceHandle, RUNTIME, provider::IdeviceProviderHandle}; use crate::{IdeviceFfiError, IdeviceHandle, RUNTIME, ffi_err, provider::IdeviceProviderHandle};
pub struct AfcClientHandle(pub AfcClient); 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 /// * [`client`] - On success, will be set to point to a newly allocated AfcClient handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `provider` must be a valid pointer to a handle allocated by this library /// `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( pub unsafe extern "C" fn afc_client_connect(
provider: *mut IdeviceProviderHandle, provider: *mut IdeviceProviderHandle,
client: *mut *mut AfcClientHandle, client: *mut *mut AfcClientHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if provider.is_null() || client.is_null() { if provider.is_null() || client.is_null() {
log::error!("Null pointer provided"); log::error!("Null pointer provided");
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let res = RUNTIME.block_on(async { let res = RUNTIME.block_on(async {
@@ -42,9 +44,9 @@ pub unsafe extern "C" fn afc_client_connect(
Ok(r) => { Ok(r) => {
let boxed = Box::new(AfcClientHandle(r)); let boxed = Box::new(AfcClientHandle(r));
unsafe { *client = Box::into_raw(boxed) }; 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 /// * [`client`] - On success, will be set to point to a newly allocated AfcClient handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `socket` must be a valid pointer to a handle allocated by this library /// `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( pub unsafe extern "C" fn afc_client_new(
socket: *mut IdeviceHandle, socket: *mut IdeviceHandle,
client: *mut *mut AfcClientHandle, client: *mut *mut AfcClientHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if socket.is_null() || client.is_null() { if socket.is_null() || client.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let socket = unsafe { Box::from_raw(socket) }.0; let socket = unsafe { Box::from_raw(socket) }.0;
let r = AfcClient::new(socket); let r = AfcClient::new(socket);
let boxed = Box::new(AfcClientHandle(r)); let boxed = Box::new(AfcClientHandle(r));
unsafe { *client = Box::into_raw(boxed) }; unsafe { *client = Box::into_raw(boxed) };
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
/// Frees an AfcClient handle /// 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 /// * [`count`] - Will be set to the number of entries
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// All pointers must be valid and non-null /// 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, path: *const libc::c_char,
entries: *mut *mut *mut libc::c_char, entries: *mut *mut *mut libc::c_char,
count: *mut libc::size_t, count: *mut libc::size_t,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if path.is_null() || entries.is_null() || count.is_null() { 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) }; 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 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 }; let ptr = unsafe { std::alloc::alloc(layout) as *mut *mut libc::c_char };
if ptr.is_null() { if ptr.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
// Fill the array with pointers to the strings, then leak each CString // 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; *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) /// * [`path`] - Path of the directory to create (UTF-8 null-terminated)
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` must be a valid pointer to a handle allocated by this library /// `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( pub unsafe extern "C" fn afc_make_directory(
client: *mut AfcClientHandle, client: *mut AfcClientHandle,
path: *const libc::c_char, path: *const libc::c_char,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if client.is_null() || path.is_null() { 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_cstr = unsafe { std::ffi::CStr::from_ptr(path) };
let path = match path_cstr.to_str() { let path = match path_cstr.to_str() {
Ok(s) => s, Ok(s) => s,
Err(_) => return IdeviceErrorCode::InvalidArg, Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg),
}; };
let res: Result<(), IdeviceError> = RUNTIME.block_on(async move { let res: Result<(), IdeviceError> = RUNTIME.block_on(async move {
@@ -198,8 +200,8 @@ pub unsafe extern "C" fn afc_make_directory(
}); });
match res { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), Err(e) => ffi_err!(e),
} }
} }
@@ -223,7 +225,7 @@ pub struct AfcFileInfo {
/// * [`info`] - Will be populated with file information /// * [`info`] - Will be populated with file information
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` and `path` must be valid pointers /// `client` and `path` must be valid pointers
@@ -233,15 +235,15 @@ pub unsafe extern "C" fn afc_get_file_info(
client: *mut AfcClientHandle, client: *mut AfcClientHandle,
path: *const libc::c_char, path: *const libc::c_char,
info: *mut AfcFileInfo, info: *mut AfcFileInfo,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if client.is_null() || path.is_null() || info.is_null() { 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_cstr = unsafe { std::ffi::CStr::from_ptr(path) };
let path = match path_cstr.to_str() { let path = match path_cstr.to_str() {
Ok(s) => s, Ok(s) => s,
Err(_) => return IdeviceErrorCode::InvalidArg, Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg),
}; };
let res: Result<FileInfo, IdeviceError> = RUNTIME.block_on(async move { let res: Result<FileInfo, IdeviceError> = RUNTIME.block_on(async move {
@@ -270,9 +272,9 @@ pub unsafe extern "C" fn afc_get_file_info(
None => std::ptr::null_mut(), 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 /// * [`info`] - Will be populated with device information
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` and `info` must be valid pointers /// `client` and `info` must be valid pointers
@@ -324,9 +326,9 @@ pub struct AfcDeviceInfo {
pub unsafe extern "C" fn afc_get_device_info( pub unsafe extern "C" fn afc_get_device_info(
client: *mut AfcClientHandle, client: *mut AfcClientHandle,
info: *mut AfcDeviceInfo, info: *mut AfcDeviceInfo,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if client.is_null() || info.is_null() { if client.is_null() || info.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let res: Result<DeviceInfo, IdeviceError> = RUNTIME.block_on(async move { let res: Result<DeviceInfo, IdeviceError> = 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).free_bytes = device_info.free_bytes;
(*info).block_size = device_info.block_size; (*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) /// * [`path`] - Path to the file or directory to remove (UTF-8 null-terminated)
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` must be a valid pointer to a handle allocated by this library /// `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( pub unsafe extern "C" fn afc_remove_path(
client: *mut AfcClientHandle, client: *mut AfcClientHandle,
path: *const libc::c_char, path: *const libc::c_char,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if client.is_null() || path.is_null() { 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_cstr = unsafe { std::ffi::CStr::from_ptr(path) };
let path = match path_cstr.to_str() { let path = match path_cstr.to_str() {
Ok(s) => s, Ok(s) => s,
Err(_) => return IdeviceErrorCode::InvalidArg, Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg),
}; };
let res: Result<(), IdeviceError> = RUNTIME.block_on(async move { let res: Result<(), IdeviceError> = RUNTIME.block_on(async move {
@@ -399,8 +401,8 @@ pub unsafe extern "C" fn afc_remove_path(
}); });
match res { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), 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) /// * [`path`] - Path to the directory to remove (UTF-8 null-terminated)
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` must be a valid pointer to a handle allocated by this library /// `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( pub unsafe extern "C" fn afc_remove_path_and_contents(
client: *mut AfcClientHandle, client: *mut AfcClientHandle,
path: *const libc::c_char, path: *const libc::c_char,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if client.is_null() || path.is_null() { 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_cstr = unsafe { std::ffi::CStr::from_ptr(path) };
let path = match path_cstr.to_str() { let path = match path_cstr.to_str() {
Ok(s) => s, Ok(s) => s,
Err(_) => return IdeviceErrorCode::InvalidArg, Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg),
}; };
let res: Result<(), IdeviceError> = RUNTIME.block_on(async move { 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 { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), Err(e) => ffi_err!(e),
} }
} }
@@ -478,7 +480,7 @@ pub struct AfcFileHandle<'a>(Box<idevice::afc::file::FileDescriptor<'a>>); // Op
/// * [`handle`] - Will be set to a new file handle on success /// * [`handle`] - Will be set to a new file handle on success
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// All pointers must be valid and non-null /// 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, path: *const libc::c_char,
mode: AfcFopenMode, mode: AfcFopenMode,
handle: *mut *mut AfcFileHandle, handle: *mut *mut AfcFileHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if client.is_null() || path.is_null() || handle.is_null() { 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_cstr = unsafe { std::ffi::CStr::from_ptr(path) };
let path = match path_cstr.to_str() { let path = match path_cstr.to_str() {
Ok(s) => s, Ok(s) => s,
Err(_) => return IdeviceErrorCode::InvalidArg, Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg),
}; };
let mode = mode.into(); let mode = mode.into();
@@ -519,9 +521,9 @@ pub unsafe extern "C" fn afc_file_open(
match res { match res {
Ok(f) => { Ok(f) => {
unsafe { *handle = 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 /// * [`handle`] - File handle to close
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `handle` must be a valid pointer to a handle allocated by this library /// `handle` must be a valid pointer to a handle allocated by this library
#[unsafe(no_mangle)] #[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() { 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 fd = unsafe { Box::from_raw(handle as *mut idevice::afc::file::FileDescriptor) };
let res: Result<(), IdeviceError> = RUNTIME.block_on(async move { fd.close().await }); let res: Result<(), IdeviceError> = RUNTIME.block_on(async move { fd.close().await });
match res { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), 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 /// * [`length`] - Will be set to the length of the read data
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// All pointers must be valid and non-null /// All pointers must be valid and non-null
@@ -567,9 +569,9 @@ pub unsafe extern "C" fn afc_file_read(
handle: *mut AfcFileHandle, handle: *mut AfcFileHandle,
data: *mut *mut u8, data: *mut *mut u8,
length: *mut libc::size_t, length: *mut libc::size_t,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if handle.is_null() || data.is_null() || length.is_null() { 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) }; 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(); *length = boxed.len();
} }
std::mem::forget(boxed); 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 /// * [`length`] - Length of data to write
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// All pointers must be valid and non-null /// All pointers must be valid and non-null
@@ -607,9 +609,9 @@ pub unsafe extern "C" fn afc_file_write(
handle: *mut AfcFileHandle, handle: *mut AfcFileHandle,
data: *const u8, data: *const u8,
length: libc::size_t, length: libc::size_t,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if handle.is_null() || data.is_null() { 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) }; 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 }); let res: Result<(), IdeviceError> = RUNTIME.block_on(async move { fd.write(data_slice).await });
match res { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), Err(e) => ffi_err!(e),
} }
} }
@@ -639,7 +641,7 @@ pub enum AfcLinkType {
/// * [`link_type`] - Type of link to create /// * [`link_type`] - Type of link to create
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// All pointers must be valid and non-null /// 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, target: *const libc::c_char,
source: *const libc::c_char, source: *const libc::c_char,
link_type: AfcLinkType, link_type: AfcLinkType,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if client.is_null() || target.is_null() || source.is_null() { 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_cstr = unsafe { std::ffi::CStr::from_ptr(target) };
let target = match target_cstr.to_str() { let target = match target_cstr.to_str() {
Ok(s) => s, 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_cstr = unsafe { std::ffi::CStr::from_ptr(source) };
let source = match source_cstr.to_str() { let source = match source_cstr.to_str() {
Ok(s) => s, Ok(s) => s,
Err(_) => return IdeviceErrorCode::InvalidArg, Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg),
}; };
let link_type = match link_type { let link_type = match link_type {
@@ -678,8 +680,8 @@ pub unsafe extern "C" fn afc_make_link(
}); });
match res { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), 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) /// * [`target`] - New path for the file/directory (UTF-8 null-terminated)
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// All pointers must be valid and non-null /// All pointers must be valid and non-null
@@ -701,21 +703,21 @@ pub unsafe extern "C" fn afc_rename_path(
client: *mut AfcClientHandle, client: *mut AfcClientHandle,
source: *const libc::c_char, source: *const libc::c_char,
target: *const libc::c_char, target: *const libc::c_char,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if client.is_null() || source.is_null() || target.is_null() { 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_cstr = unsafe { std::ffi::CStr::from_ptr(source) };
let source = match source_cstr.to_str() { let source = match source_cstr.to_str() {
Ok(s) => s, 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_cstr = unsafe { std::ffi::CStr::from_ptr(target) };
let target = match target_cstr.to_str() { let target = match target_cstr.to_str() {
Ok(s) => s, Ok(s) => s,
Err(_) => return IdeviceErrorCode::InvalidArg, Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg),
}; };
let res: Result<(), IdeviceError> = RUNTIME.block_on(async move { let res: Result<(), IdeviceError> = RUNTIME.block_on(async move {
@@ -724,8 +726,8 @@ pub unsafe extern "C" fn afc_rename_path(
}); });
match res { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), Err(e) => ffi_err!(e),
} }
} }

View File

@@ -1,8 +1,10 @@
// Jackson Coxson // Jackson Coxson
use std::ptr::null_mut;
use idevice::{IdeviceError, IdeviceService, amfi::AmfiClient, provider::IdeviceProvider}; 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); 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 /// * [`client`] - On success, will be set to point to a newly allocated AmfiClient handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `provider` must be a valid pointer to a handle allocated by this library /// `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( pub unsafe extern "C" fn amfi_connect(
provider: *mut IdeviceProviderHandle, provider: *mut IdeviceProviderHandle,
client: *mut *mut AmfiClientHandle, client: *mut *mut AmfiClientHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if provider.is_null() || client.is_null() { if provider.is_null() || client.is_null() {
log::error!("Null pointer provided"); log::error!("Null pointer provided");
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let res: Result<AmfiClient, IdeviceError> = RUNTIME.block_on(async move { let res: Result<AmfiClient, IdeviceError> = RUNTIME.block_on(async move {
@@ -39,9 +41,9 @@ pub unsafe extern "C" fn amfi_connect(
Ok(r) => { Ok(r) => {
let boxed = Box::new(AmfiClientHandle(r)); let boxed = Box::new(AmfiClientHandle(r));
unsafe { *client = Box::into_raw(boxed) }; 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 /// * [`client`] - On success, will be set to point to a newly allocated AmfiClient handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `socket` must be a valid pointer to a handle allocated by this library. It is consumed, and /// `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( pub unsafe extern "C" fn amfi_new(
socket: *mut IdeviceHandle, socket: *mut IdeviceHandle,
client: *mut *mut AmfiClientHandle, client: *mut *mut AmfiClientHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if socket.is_null() || client.is_null() { if socket.is_null() || client.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let socket = unsafe { Box::from_raw(socket) }.0; let socket = unsafe { Box::from_raw(socket) }.0;
let r = AmfiClient::new(socket); let r = AmfiClient::new(socket);
let boxed = Box::new(AmfiClientHandle(r)); let boxed = Box::new(AmfiClientHandle(r));
unsafe { *client = Box::into_raw(boxed) }; unsafe { *client = Box::into_raw(boxed) };
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
/// Shows the option in the settings UI /// Shows the option in the settings UI
@@ -80,16 +82,16 @@ pub unsafe extern "C" fn amfi_new(
/// * `client` - A valid AmfiClient handle /// * `client` - A valid AmfiClient handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` must be a valid pointer to a handle allocated by this library /// `client` must be a valid pointer to a handle allocated by this library
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub unsafe extern "C" fn amfi_reveal_developer_mode_option_in_ui( pub unsafe extern "C" fn amfi_reveal_developer_mode_option_in_ui(
client: *mut AmfiClientHandle, client: *mut AmfiClientHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if client.is_null() { if client.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let res: Result<(), IdeviceError> = RUNTIME.block_on(async move { 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 client_ref.reveal_developer_mode_option_in_ui().await
}); });
match res { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), 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 /// * `client` - A valid AmfiClient handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` must be a valid pointer to a handle allocated by this library /// `client` must be a valid pointer to a handle allocated by this library
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub unsafe extern "C" fn amfi_enable_developer_mode( pub unsafe extern "C" fn amfi_enable_developer_mode(
client: *mut AmfiClientHandle, client: *mut AmfiClientHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if client.is_null() { if client.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let res: Result<(), IdeviceError> = RUNTIME.block_on(async move { 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 client_ref.enable_developer_mode().await
}); });
match res { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), Err(e) => ffi_err!(e),
} }
} }
@@ -136,16 +138,16 @@ pub unsafe extern "C" fn amfi_enable_developer_mode(
/// * `client` - A valid AmfiClient handle /// * `client` - A valid AmfiClient handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` must be a valid pointer to a handle allocated by this library /// `client` must be a valid pointer to a handle allocated by this library
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub unsafe extern "C" fn amfi_accept_developer_mode( pub unsafe extern "C" fn amfi_accept_developer_mode(
client: *mut AmfiClientHandle, client: *mut AmfiClientHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if client.is_null() { if client.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let res: Result<(), IdeviceError> = RUNTIME.block_on(async move { 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 client_ref.accept_developer_mode().await
}); });
match res { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), Err(e) => ffi_err!(e),
} }
} }

View File

@@ -1,13 +1,16 @@
// Jackson Coxson // Jackson Coxson
use std::ffi::{CString, c_char}; use std::{
ffi::{CString, c_char},
ptr::null_mut,
};
use idevice::{ use idevice::{
IdeviceError, IdeviceService, core_device_proxy::CoreDeviceProxy, provider::IdeviceProvider, IdeviceError, IdeviceService, core_device_proxy::CoreDeviceProxy, provider::IdeviceProvider,
tcp::adapter::Adapter, 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 CoreDeviceProxyHandle(pub CoreDeviceProxy);
pub struct AdapterHandle(pub Adapter); 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 /// * [`client`] - On success, will be set to point to a newly allocated CoreDeviceProxy handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `provider` must be a valid pointer to a handle allocated by this library /// `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( pub unsafe extern "C" fn core_device_proxy_connect(
provider: *mut IdeviceProviderHandle, provider: *mut IdeviceProviderHandle,
client: *mut *mut CoreDeviceProxyHandle, client: *mut *mut CoreDeviceProxyHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if provider.is_null() || client.is_null() { if provider.is_null() || client.is_null() {
log::error!("Null pointer provided"); log::error!("Null pointer provided");
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let res: Result<CoreDeviceProxy, IdeviceError> = RUNTIME.block_on(async move { let res: Result<CoreDeviceProxy, IdeviceError> = RUNTIME.block_on(async move {
@@ -45,9 +48,9 @@ pub unsafe extern "C" fn core_device_proxy_connect(
Ok(r) => { Ok(r) => {
let boxed = Box::new(CoreDeviceProxyHandle(r)); let boxed = Box::new(CoreDeviceProxyHandle(r));
unsafe { *client = Box::into_raw(boxed) }; 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 /// * [`client`] - On success, will be set to point to a newly allocated CoreDeviceProxy handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `socket` must be a valid pointer to a handle allocated by this library. It is consumed and /// `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( pub unsafe extern "C" fn core_device_proxy_new(
socket: *mut IdeviceHandle, socket: *mut IdeviceHandle,
client: *mut *mut CoreDeviceProxyHandle, client: *mut *mut CoreDeviceProxyHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if socket.is_null() || client.is_null() { if socket.is_null() || client.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let socket = unsafe { Box::from_raw(socket) }.0; let socket = unsafe { Box::from_raw(socket) }.0;
let r: Result<CoreDeviceProxy, IdeviceError> = let r: Result<CoreDeviceProxy, IdeviceError> =
@@ -79,9 +82,9 @@ pub unsafe extern "C" fn core_device_proxy_new(
Ok(r) => { Ok(r) => {
let boxed = Box::new(CoreDeviceProxyHandle(r)); let boxed = Box::new(CoreDeviceProxyHandle(r));
unsafe { *client = Box::into_raw(boxed) }; 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 /// * [`length`] - The length of the data
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `handle` must be a valid pointer to a handle allocated by this library /// `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, handle: *mut CoreDeviceProxyHandle,
data: *const u8, data: *const u8,
length: usize, length: usize,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if handle.is_null() || data.is_null() { if handle.is_null() || data.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let proxy = unsafe { &mut (*handle).0 }; 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 }); let res = RUNTIME.block_on(async move { proxy.send(data_slice).await });
match res { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), 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` /// * [`max_length`] - Maximum number of bytes that can be stored in `data`
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `handle` must be a valid pointer to a handle allocated by this library /// `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, data: *mut u8,
length: *mut usize, length: *mut usize,
max_length: usize, max_length: usize,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if handle.is_null() || data.is_null() || length.is_null() { if handle.is_null() || data.is_null() || length.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let proxy = unsafe { &mut (*handle).0 }; let proxy = unsafe { &mut (*handle).0 };
@@ -153,7 +156,7 @@ pub unsafe extern "C" fn core_device_proxy_recv(
Ok(received_data) => { Ok(received_data) => {
let received_len = received_data.len(); let received_len = received_data.len();
if received_len > max_length { if received_len > max_length {
return IdeviceErrorCode::BufferTooSmall; return ffi_err!(IdeviceError::FfiBufferTooSmall(received_len, max_length));
} }
unsafe { unsafe {
@@ -161,9 +164,9 @@ pub unsafe extern "C" fn core_device_proxy_recv(
*length = received_len; *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 /// * [`netmask`] - Pointer to store the netmask string
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `handle` must be a valid pointer to a handle allocated by this library /// `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, mtu: *mut u16,
address: *mut *mut c_char, address: *mut *mut c_char,
netmask: *mut *mut c_char, netmask: *mut *mut c_char,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if handle.is_null() { if handle.is_null() {
log::error!("Passed null handle"); log::error!("Passed null handle");
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let proxy = unsafe { &(*handle).0 }; 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 // Allocate both strings, but handle partial failure
let address_cstring = match CString::new(params.address.clone()) { let address_cstring = match CString::new(params.address.clone()) {
Ok(s) => s, Ok(s) => s,
Err(_) => return IdeviceErrorCode::InvalidString, Err(_) => return ffi_err!(IdeviceError::FfiInvalidString),
}; };
let netmask_cstring = match CString::new(params.netmask.clone()) { let netmask_cstring = match CString::new(params.netmask.clone()) {
Ok(s) => s, Ok(s) => s,
Err(_) => return IdeviceErrorCode::InvalidString, Err(_) => return ffi_err!(IdeviceError::FfiInvalidString),
}; };
// Only assign to output pointers after both succeed // 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(); *netmask = netmask_cstring.into_raw();
} }
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
/// Gets the server address from the handshake /// 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 /// * [`address`] - Pointer to store the server address string
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `handle` must be a valid pointer to a handle allocated by this library /// `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( pub unsafe extern "C" fn core_device_proxy_get_server_address(
handle: *mut CoreDeviceProxyHandle, handle: *mut CoreDeviceProxyHandle,
address: *mut *mut c_char, address: *mut *mut c_char,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if handle.is_null() { if handle.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let proxy = unsafe { &(*handle).0 }; let proxy = unsafe { &(*handle).0 };
@@ -247,11 +250,11 @@ pub unsafe extern "C" fn core_device_proxy_get_server_address(
unsafe { unsafe {
*address = match CString::new(proxy.handshake.server_address.clone()) { *address = match CString::new(proxy.handshake.server_address.clone()) {
Ok(s) => s.into_raw(), 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 /// 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 /// * [`port`] - Pointer to store the port number
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `handle` must be a valid pointer to a handle allocated by this library /// `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( pub unsafe extern "C" fn core_device_proxy_get_server_rsd_port(
handle: *mut CoreDeviceProxyHandle, handle: *mut CoreDeviceProxyHandle,
port: *mut u16, port: *mut u16,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if handle.is_null() || port.is_null() { if handle.is_null() || port.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let proxy = unsafe { &(*handle).0 }; 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; *port = proxy.handshake.server_rsd_port;
} }
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
/// Creates a software TCP tunnel adapter /// 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 /// * [`adapter`] - Pointer to store the newly created adapter handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `handle` must be a valid pointer to a handle allocated by this library, and never used again /// `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( pub unsafe extern "C" fn core_device_proxy_create_tcp_adapter(
handle: *mut CoreDeviceProxyHandle, handle: *mut CoreDeviceProxyHandle,
adapter: *mut *mut AdapterHandle, adapter: *mut *mut AdapterHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if handle.is_null() || adapter.is_null() { if handle.is_null() || adapter.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let proxy = unsafe { Box::from_raw(handle) }; 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) => { Ok(adapter_obj) => {
let boxed = Box::new(AdapterHandle(adapter_obj)); let boxed = Box::new(AdapterHandle(adapter_obj));
unsafe { *adapter = Box::into_raw(boxed) }; unsafe { *adapter = Box::into_raw(boxed) };
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
Err(e) => e.into(), Err(e) => ffi_err!(e),
} }
} }

View File

@@ -2,7 +2,7 @@
use std::ffi::{CStr, CString, c_char}; use std::ffi::{CStr, CString, c_char};
use std::os::raw::c_int; use std::os::raw::c_int;
use std::ptr; use std::ptr::{self, null_mut};
use idevice::debug_proxy::{DebugProxyClient, DebugserverCommand}; use idevice::debug_proxy::{DebugProxyClient, DebugserverCommand};
use idevice::tcp::stream::AdapterStream; use idevice::tcp::stream::AdapterStream;
@@ -10,7 +10,7 @@ use idevice::{IdeviceError, ReadWrite, RsdService};
use crate::core_device_proxy::AdapterHandle; use crate::core_device_proxy::AdapterHandle;
use crate::rsd::RsdHandshakeHandle; use crate::rsd::RsdHandshakeHandle;
use crate::{IdeviceErrorCode, RUNTIME}; use crate::{IdeviceFfiError, RUNTIME, ffi_err};
/// Opaque handle to a DebugProxyClient /// Opaque handle to a DebugProxyClient
pub struct DebugProxyHandle(pub DebugProxyClient<Box<dyn ReadWrite>>); pub struct DebugProxyHandle(pub DebugProxyClient<Box<dyn ReadWrite>>);
@@ -122,7 +122,7 @@ pub unsafe extern "C" fn debugserver_command_free(command: *mut DebugserverComma
/// * [`handshake`] - An RSD handshake from the same provider /// * [`handshake`] - An RSD handshake from the same provider
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `provider` must be a valid pointer to a handle allocated by this library /// `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, provider: *mut AdapterHandle,
handshake: *mut RsdHandshakeHandle, handshake: *mut RsdHandshakeHandle,
handle: *mut *mut DebugProxyHandle, handle: *mut *mut DebugProxyHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if provider.is_null() || handshake.is_null() || handshake.is_null() { if provider.is_null() || handshake.is_null() || handshake.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let res: Result<DebugProxyClient<AdapterStream>, IdeviceError> = RUNTIME.block_on(async move { let res: Result<DebugProxyClient<AdapterStream>, IdeviceError> = RUNTIME.block_on(async move {
let provider_ref = unsafe { &mut (*provider).0 }; let provider_ref = unsafe { &mut (*provider).0 };
@@ -150,9 +150,9 @@ pub unsafe extern "C" fn debug_proxy_connect_rsd(
d.into_inner(), d.into_inner(),
)))); ))));
unsafe { *handle = Box::into_raw(boxed) }; 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 /// * [`handle`] - Pointer to store the newly created DebugProxyClient handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `socket` must be a valid pointer to a handle allocated by this library /// `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( pub unsafe extern "C" fn debug_proxy_new(
socket: *mut Box<dyn ReadWrite>, socket: *mut Box<dyn ReadWrite>,
handle: *mut *mut DebugProxyHandle, handle: *mut *mut DebugProxyHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if socket.is_null() || handle.is_null() { if socket.is_null() || handle.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let socket = unsafe { Box::from_raw(socket) }; let socket = unsafe { Box::from_raw(socket) };
@@ -182,7 +182,7 @@ pub unsafe extern "C" fn debug_proxy_new(
let new_handle = DebugProxyHandle(client); let new_handle = DebugProxyHandle(client);
unsafe { *handle = Box::into_raw(Box::new(new_handle)) }; unsafe { *handle = Box::into_raw(Box::new(new_handle)) };
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
/// Frees a DebugProxyClient handle /// 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) /// * [`response`] - Pointer to store the response (caller must free)
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `handle` and `command` must be valid pointers /// `handle` and `command` must be valid pointers
@@ -217,9 +217,9 @@ pub unsafe extern "C" fn debug_proxy_send_command(
handle: *mut DebugProxyHandle, handle: *mut DebugProxyHandle,
command: *mut DebugserverCommandHandle, command: *mut DebugserverCommandHandle,
response: *mut *mut c_char, response: *mut *mut c_char,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if handle.is_null() || command.is_null() || response.is_null() { if handle.is_null() || command.is_null() || response.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let client = unsafe { &mut (*handle).0 }; let client = unsafe { &mut (*handle).0 };
@@ -247,16 +247,16 @@ pub unsafe extern "C" fn debug_proxy_send_command(
Ok(Some(r)) => { Ok(Some(r)) => {
let cstr = match CString::new(r) { let cstr = match CString::new(r) {
Ok(c) => c, Ok(c) => c,
Err(_) => return IdeviceErrorCode::InvalidString, Err(_) => return ffi_err!(IdeviceError::FfiInvalidString),
}; };
unsafe { *response = cstr.into_raw() }; unsafe { *response = cstr.into_raw() };
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
Ok(None) => { Ok(None) => {
unsafe { *response = ptr::null_mut() }; 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) /// * [`response`] - Pointer to store the response (caller must free)
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `handle` must be a valid pointer /// `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( pub unsafe extern "C" fn debug_proxy_read_response(
handle: *mut DebugProxyHandle, handle: *mut DebugProxyHandle,
response: *mut *mut c_char, response: *mut *mut c_char,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if handle.is_null() || response.is_null() { if handle.is_null() || response.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let client = unsafe { &mut (*handle).0 }; let client = unsafe { &mut (*handle).0 };
@@ -288,16 +288,16 @@ pub unsafe extern "C" fn debug_proxy_read_response(
Ok(Some(r)) => { Ok(Some(r)) => {
let cstr = match CString::new(r) { let cstr = match CString::new(r) {
Ok(c) => c, Ok(c) => c,
Err(_) => return IdeviceErrorCode::InvalidString, Err(_) => return ffi_err!(IdeviceError::FfiInvalidString),
}; };
unsafe { *response = cstr.into_raw() }; unsafe { *response = cstr.into_raw() };
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
Ok(None) => { Ok(None) => {
unsafe { *response = ptr::null_mut() }; 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 /// * [`len`] - Length of the data
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `handle` must be a valid pointer /// `handle` must be a valid pointer
@@ -319,9 +319,9 @@ pub unsafe extern "C" fn debug_proxy_send_raw(
handle: *mut DebugProxyHandle, handle: *mut DebugProxyHandle,
data: *const u8, data: *const u8,
len: usize, len: usize,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if handle.is_null() || data.is_null() { if handle.is_null() || data.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let client = unsafe { &mut (*handle).0 }; 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 }); let res = RUNTIME.block_on(async move { client.send_raw(data_slice).await });
match res { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), 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) /// * [`response`] - Pointer to store the response (caller must free)
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `handle` must be a valid pointer /// `handle` must be a valid pointer
@@ -352,9 +352,9 @@ pub unsafe extern "C" fn debug_proxy_read(
handle: *mut DebugProxyHandle, handle: *mut DebugProxyHandle,
len: usize, len: usize,
response: *mut *mut c_char, response: *mut *mut c_char,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if handle.is_null() || response.is_null() { if handle.is_null() || response.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let client = unsafe { &mut (*handle).0 }; let client = unsafe { &mut (*handle).0 };
@@ -364,12 +364,12 @@ pub unsafe extern "C" fn debug_proxy_read(
Ok(r) => { Ok(r) => {
let cstr = match CString::new(r) { let cstr = match CString::new(r) {
Ok(c) => c, Ok(c) => c,
Err(_) => return IdeviceErrorCode::InvalidString, Err(_) => return ffi_err!(IdeviceError::FfiInvalidString),
}; };
unsafe { *response = cstr.into_raw() }; 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) /// * [`response`] - Pointer to store the response (caller must free)
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `handle` must be a valid pointer /// `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: *const *const c_char,
argv_count: usize, argv_count: usize,
response: *mut *mut c_char, response: *mut *mut c_char,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if handle.is_null() || response.is_null() { if handle.is_null() || response.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let client = unsafe { &mut (*handle).0 }; let client = unsafe { &mut (*handle).0 };
@@ -422,12 +422,12 @@ pub unsafe extern "C" fn debug_proxy_set_argv(
Ok(r) => { Ok(r) => {
let cstr = match CString::new(r) { let cstr = match CString::new(r) {
Ok(c) => c, Ok(c) => c,
Err(_) => return IdeviceErrorCode::InvalidString, Err(_) => return ffi_err!(IdeviceError::FfiInvalidString),
}; };
unsafe { *response = cstr.into_raw() }; 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 /// * [`handle`] - The DebugProxyClient handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `handle` must be a valid pointer /// `handle` must be a valid pointer
#[unsafe(no_mangle)] #[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() { if handle.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let client = unsafe { &mut (*handle).0 }; let client = unsafe { &mut (*handle).0 };
let res = RUNTIME.block_on(async move { client.send_ack().await }); let res = RUNTIME.block_on(async move { client.send_ack().await });
match res { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), 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 /// * [`handle`] - The DebugProxyClient handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `handle` must be a valid pointer /// `handle` must be a valid pointer
#[unsafe(no_mangle)] #[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() { if handle.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let client = unsafe { &mut (*handle).0 }; let client = unsafe { &mut (*handle).0 };
let res = RUNTIME.block_on(async move { client.send_noack().await }); let res = RUNTIME.block_on(async move { client.send_noack().await });
match res { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), Err(e) => ffi_err!(e),
} }
} }

View File

@@ -1,147 +1,47 @@
// Jackson Coxson // Jackson Coxson
use idevice::IdeviceError; use std::ffi::{CString, c_char};
#[repr(C)] #[repr(C)]
pub enum IdeviceErrorCode { #[derive(Debug)]
IdeviceSuccess = 0, pub struct IdeviceFfiError {
// Main library pub code: i32,
Socket = -1, pub message: *const c_char,
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,
} }
impl From<IdeviceError> for IdeviceErrorCode { /// Frees the IdeviceFfiError
fn from(err: IdeviceError) -> Self { ///
match err { /// # Safety
IdeviceError::Socket(_) => IdeviceErrorCode::Socket, /// `err` must be a struct allocated by this library
IdeviceError::Rustls(_) => IdeviceErrorCode::Tls, #[unsafe(no_mangle)]
IdeviceError::TlsBuilderFailed(_) => IdeviceErrorCode::TlsBuilderFailed, pub unsafe extern "C" fn idevice_error_free(err: *mut IdeviceFfiError) {
IdeviceError::Plist(_) => IdeviceErrorCode::Plist, if err.is_null() {
IdeviceError::Utf8(_) => IdeviceErrorCode::Utf8, return;
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,
} }
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,
}))
}};
}

View File

@@ -1,10 +1,12 @@
// Jackson Coxson // Jackson Coxson
use std::ptr::null_mut;
use idevice::{ use idevice::{
IdeviceError, IdeviceService, heartbeat::HeartbeatClient, provider::IdeviceProvider, 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); 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 /// * [`client`] - On success, will be set to point to a newly allocated InstallationProxyClient handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `provider` must be a valid pointer to a handle allocated by this library /// `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( pub unsafe extern "C" fn heartbeat_connect(
provider: *mut IdeviceProviderHandle, provider: *mut IdeviceProviderHandle,
client: *mut *mut HeartbeatClientHandle, client: *mut *mut HeartbeatClientHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if provider.is_null() || client.is_null() { if provider.is_null() || client.is_null() {
log::error!("Null pointer provided"); log::error!("Null pointer provided");
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let res: Result<HeartbeatClient, IdeviceError> = RUNTIME.block_on(async move { let res: Result<HeartbeatClient, IdeviceError> = RUNTIME.block_on(async move {
@@ -40,13 +42,10 @@ pub unsafe extern "C" fn heartbeat_connect(
Ok(r) => { Ok(r) => {
let boxed = Box::new(HeartbeatClientHandle(r)); let boxed = Box::new(HeartbeatClientHandle(r));
unsafe { *client = Box::into_raw(boxed) }; unsafe { *client = Box::into_raw(boxed) };
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
Err(e) => { Err(e) => {
// If connection failed, the provider_box was already forgotten, ffi_err!(e)
// so we need to reconstruct it to avoid leak
let _ = unsafe { Box::from_raw(provider) };
e.into()
} }
} }
} }
@@ -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 /// * [`client`] - On success, will be set to point to a newly allocated InstallationProxyClient handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `socket` must be a valid pointer to a handle allocated by this library. The socket is consumed, /// `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( pub unsafe extern "C" fn heartbeat_new(
socket: *mut IdeviceHandle, socket: *mut IdeviceHandle,
client: *mut *mut HeartbeatClientHandle, client: *mut *mut HeartbeatClientHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if socket.is_null() || client.is_null() { if socket.is_null() || client.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let socket = unsafe { Box::from_raw(socket) }.0; let socket = unsafe { Box::from_raw(socket) }.0;
let r = HeartbeatClient::new(socket); let r = HeartbeatClient::new(socket);
let boxed = Box::new(HeartbeatClientHandle(r)); let boxed = Box::new(HeartbeatClientHandle(r));
unsafe { *client = Box::into_raw(boxed) }; unsafe { *client = Box::into_raw(boxed) };
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
/// Sends a polo to the device /// Sends a polo to the device
@@ -85,24 +84,24 @@ pub unsafe extern "C" fn heartbeat_new(
/// * `client` - A valid HeartbeatClient handle /// * `client` - A valid HeartbeatClient handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` must be a valid pointer to a handle allocated by this library /// `client` must be a valid pointer to a handle allocated by this library
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub unsafe extern "C" fn heartbeat_send_polo( pub unsafe extern "C" fn heartbeat_send_polo(
client: *mut HeartbeatClientHandle, client: *mut HeartbeatClientHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if client.is_null() { if client.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let res: Result<(), IdeviceError> = RUNTIME.block_on(async move { let res: Result<(), IdeviceError> = RUNTIME.block_on(async move {
let client_ref = unsafe { &mut (*client).0 }; let client_ref = unsafe { &mut (*client).0 };
client_ref.send_polo().await client_ref.send_polo().await
}); });
match res { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), 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 /// * `new_interval` - A pointer to set the requested marco
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure. /// An IdeviceFfiError on error, null on success.
/// ///
/// # Safety /// # Safety
/// `client` must be a valid pointer to a handle allocated by this library /// `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, client: *mut HeartbeatClientHandle,
interval: u64, interval: u64,
new_interval: *mut u64, new_interval: *mut u64,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if client.is_null() || new_interval.is_null() { if client.is_null() || new_interval.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let res: Result<u64, IdeviceError> = RUNTIME.block_on(async move { let res: Result<u64, IdeviceError> = RUNTIME.block_on(async move {
let client_ref = unsafe { &mut (*client).0 }; let client_ref = unsafe { &mut (*client).0 };
@@ -134,9 +133,9 @@ pub unsafe extern "C" fn heartbeat_get_marco(
match res { match res {
Ok(n) => { Ok(n) => {
unsafe { *new_interval = n }; unsafe { *new_interval = n };
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
Err(e) => e.into(), Err(e) => ffi_err!(e),
} }
} }

View File

@@ -1,13 +1,15 @@
// Jackson Coxson // Jackson Coxson
use std::ffi::c_void; use std::{ffi::c_void, ptr::null_mut};
use idevice::{ use idevice::{
IdeviceError, IdeviceService, installation_proxy::InstallationProxyClient, IdeviceError, IdeviceService, installation_proxy::InstallationProxyClient,
provider::IdeviceProvider, 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); 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 /// * [`client`] - On success, will be set to point to a newly allocated InstallationProxyClient handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `provider` must be a valid pointer to a handle allocated by this library /// `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( pub unsafe extern "C" fn installation_proxy_connect_tcp(
provider: *mut IdeviceProviderHandle, provider: *mut IdeviceProviderHandle,
client: *mut *mut InstallationProxyClientHandle, client: *mut *mut InstallationProxyClientHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if provider.is_null() || client.is_null() { if provider.is_null() || client.is_null() {
log::error!("Null pointer provided"); log::error!("Null pointer provided");
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let res: Result<InstallationProxyClient, IdeviceError> = RUNTIME.block_on(async move { let res: Result<InstallationProxyClient, IdeviceError> = RUNTIME.block_on(async move {
@@ -42,9 +44,9 @@ pub unsafe extern "C" fn installation_proxy_connect_tcp(
Ok(r) => { Ok(r) => {
let boxed = Box::new(InstallationProxyClientHandle(r)); let boxed = Box::new(InstallationProxyClientHandle(r));
unsafe { *client = Box::into_raw(boxed) }; 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 /// * [`client`] - On success, will be set to point to a newly allocated InstallationProxyClient handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `socket` must be a valid pointer to a handle allocated by this library. The socket is consumed, /// `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( pub unsafe extern "C" fn installation_proxy_new(
socket: *mut IdeviceHandle, socket: *mut IdeviceHandle,
client: *mut *mut InstallationProxyClientHandle, client: *mut *mut InstallationProxyClientHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if socket.is_null() || client.is_null() { if socket.is_null() || client.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let socket = unsafe { Box::from_raw(socket) }.0; let socket = unsafe { Box::from_raw(socket) }.0;
let r = InstallationProxyClient::new(socket); let r = InstallationProxyClient::new(socket);
let boxed = Box::new(InstallationProxyClientHandle(r)); let boxed = Box::new(InstallationProxyClientHandle(r));
unsafe { *client = Box::into_raw(boxed) }; unsafe { *client = Box::into_raw(boxed) };
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
/// Gets installed apps on the device /// 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 /// * [`out_result`] - On success, will be set to point to a newly allocated array of PlistRef
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` must be a valid pointer to a handle allocated by this library /// `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, bundle_identifiers_len: libc::size_t,
out_result: *mut *mut c_void, out_result: *mut *mut c_void,
out_result_len: *mut libc::size_t, out_result_len: *mut libc::size_t,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if client.is_null() || out_result.is_null() || out_result_len.is_null() { if client.is_null() || out_result.is_null() || out_result_len.is_null() {
log::error!("Invalid arguments: {client:?}, {out_result:?}"); log::error!("Invalid arguments: {client:?}, {out_result:?}");
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let client = unsafe { &mut *client }; 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 = ptr as *mut c_void;
*out_result_len = len; *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) /// * [`options`] - Optional installation options as a plist dictionary (can be NULL)
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` must be a valid pointer to a handle allocated by this library /// `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, client: *mut InstallationProxyClientHandle,
package_path: *const libc::c_char, package_path: *const libc::c_char,
options: *mut c_void, options: *mut c_void,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if client.is_null() || package_path.is_null() { 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) } 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 { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), Err(e) => ffi_err!(e),
} }
} }
@@ -228,7 +230,7 @@ pub unsafe extern "C" fn installation_proxy_install(
/// * [`context`] - User context to pass to callback /// * [`context`] - User context to pass to callback
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` must be a valid pointer to a handle allocated by this library /// `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, options: *mut c_void,
callback: extern "C" fn(progress: u64, context: *mut c_void), callback: extern "C" fn(progress: u64, context: *mut c_void),
context: *mut c_void, context: *mut c_void,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if client.is_null() || package_path.is_null() { 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) } 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 { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), 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) /// * [`options`] - Optional upgrade options as a plist dictionary (can be NULL)
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` must be a valid pointer to a handle allocated by this library /// `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, client: *mut InstallationProxyClientHandle,
package_path: *const libc::c_char, package_path: *const libc::c_char,
options: *mut c_void, options: *mut c_void,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if client.is_null() || package_path.is_null() { 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) } 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 { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), Err(e) => ffi_err!(e),
} }
} }
@@ -328,7 +330,7 @@ pub unsafe extern "C" fn installation_proxy_upgrade(
/// * [`context`] - User context to pass to callback /// * [`context`] - User context to pass to callback
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` must be a valid pointer to a handle allocated by this library /// `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, options: *mut c_void,
callback: extern "C" fn(progress: u64, context: *mut c_void), callback: extern "C" fn(progress: u64, context: *mut c_void),
context: *mut c_void, context: *mut c_void,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if client.is_null() || package_path.is_null() { 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) } 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 { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), 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) /// * [`options`] - Optional uninstall options as a plist dictionary (can be NULL)
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` must be a valid pointer to a handle allocated by this library /// `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, client: *mut InstallationProxyClientHandle,
bundle_id: *const libc::c_char, bundle_id: *const libc::c_char,
options: *mut c_void, options: *mut c_void,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if client.is_null() || bundle_id.is_null() { 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) } 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 { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), Err(e) => ffi_err!(e),
} }
} }
@@ -428,7 +430,7 @@ pub unsafe extern "C" fn installation_proxy_uninstall(
/// * [`context`] - User context to pass to callback /// * [`context`] - User context to pass to callback
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` must be a valid pointer to a handle allocated by this library /// `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, options: *mut c_void,
callback: extern "C" fn(progress: u64, context: *mut c_void), callback: extern "C" fn(progress: u64, context: *mut c_void),
context: *mut c_void, context: *mut c_void,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if client.is_null() || bundle_id.is_null() { 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) } 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 { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), 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 /// * [`out_result`] - Will be set to true if all capabilities are supported, false otherwise
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` must be a valid pointer to a handle allocated by this library /// `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, capabilities_len: libc::size_t,
options: *mut c_void, options: *mut c_void,
out_result: *mut bool, out_result: *mut bool,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if client.is_null() || out_result.is_null() { if client.is_null() || out_result.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let capabilities = if capabilities.is_null() { let capabilities = if capabilities.is_null() {
@@ -526,9 +528,9 @@ pub unsafe extern "C" fn installation_proxy_check_capabilities_match(
match res { match res {
Ok(result) => { Ok(result) => {
unsafe { *out_result = 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 /// * [`out_result_len`] - Will be set to the length of the result array
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` must be a valid pointer to a handle allocated by this library /// `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, options: *mut c_void,
out_result: *mut *mut c_void, out_result: *mut *mut c_void,
out_result_len: *mut libc::size_t, out_result_len: *mut libc::size_t,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if client.is_null() || out_result.is_null() || out_result_len.is_null() { 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() { 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 = ptr as *mut c_void;
*out_result_len = len; *out_result_len = len;
} }
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
Err(e) => e.into(), Err(e) => ffi_err!(e),
} }
} }

View File

@@ -46,7 +46,10 @@ pub use pairing_file::*;
use idevice::{Idevice, IdeviceSocket, ReadWrite}; use idevice::{Idevice, IdeviceSocket, ReadWrite};
use once_cell::sync::Lazy; 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}; use tokio::runtime::{self, Runtime};
static RUNTIME: Lazy<Runtime> = Lazy::new(|| { static RUNTIME: Lazy<Runtime> = Lazy::new(|| {
@@ -80,7 +83,7 @@ struct sockaddr;
/// * [`idevice`] - On success, will be set to point to a newly allocated Idevice handle /// * [`idevice`] - On success, will be set to point to a newly allocated Idevice handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `label` must be a valid null-terminated C string /// `label` must be a valid null-terminated C string
@@ -90,9 +93,9 @@ pub unsafe extern "C" fn idevice_new(
socket: *mut IdeviceSocketHandle, socket: *mut IdeviceSocketHandle,
label: *const c_char, label: *const c_char,
idevice: *mut *mut IdeviceHandle, idevice: *mut *mut IdeviceHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if socket.is_null() || label.is_null() || idevice.is_null() { if socket.is_null() || label.is_null() || idevice.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
// Get socket ownership // Get socket ownership
@@ -101,7 +104,7 @@ pub unsafe extern "C" fn idevice_new(
// Convert C string to Rust string // Convert C string to Rust string
let c_str = match unsafe { CStr::from_ptr(label).to_str() } { let c_str = match unsafe { CStr::from_ptr(label).to_str() } {
Ok(s) => s, Ok(s) => s,
Err(_) => return IdeviceErrorCode::InvalidString, Err(_) => return ffi_err!(IdeviceError::FfiInvalidString),
}; };
// Create new Idevice instance // Create new Idevice instance
@@ -109,7 +112,7 @@ pub unsafe extern "C" fn idevice_new(
let boxed = Box::new(IdeviceHandle(dev)); let boxed = Box::new(IdeviceHandle(dev));
unsafe { *idevice = Box::into_raw(boxed) }; unsafe { *idevice = Box::into_raw(boxed) };
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
/// Creates a new Idevice connection /// 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 /// * [`idevice`] - On success, will be set to point to a newly allocated Idevice handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `addr` must be a valid sockaddr /// `addr` must be a valid sockaddr
@@ -133,21 +136,21 @@ pub unsafe extern "C" fn idevice_new_tcp_socket(
addr_len: libc::socklen_t, addr_len: libc::socklen_t,
label: *const c_char, label: *const c_char,
idevice: *mut *mut IdeviceHandle, idevice: *mut *mut IdeviceHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if addr.is_null() { if addr.is_null() {
log::error!("socket addr null pointer"); log::error!("socket addr null pointer");
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
// Convert C string to Rust string // Convert C string to Rust string
let label = match unsafe { CStr::from_ptr(label).to_str() } { let label = match unsafe { CStr::from_ptr(label).to_str() } {
Ok(s) => s, Ok(s) => s,
Err(_) => return IdeviceErrorCode::InvalidArg, Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg),
}; };
let addr = match util::c_socket_to_rust(addr, addr_len) { let addr = match util::c_socket_to_rust(addr, addr_len) {
Ok(a) => a, Ok(a) => a,
Err(e) => return e, Err(e) => return ffi_err!(e),
}; };
let device: Result<idevice::Idevice, idevice::IdeviceError> = RUNTIME.block_on(async move { let device: Result<idevice::Idevice, idevice::IdeviceError> = RUNTIME.block_on(async move {
@@ -161,9 +164,9 @@ pub unsafe extern "C" fn idevice_new_tcp_socket(
Ok(dev) => { Ok(dev) => {
let boxed = Box::new(IdeviceHandle(dev)); let boxed = Box::new(IdeviceHandle(dev));
unsafe { *idevice = Box::into_raw(boxed) }; 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 /// * [`device_type`] - On success, will be set to point to a newly allocated string containing the device type
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `idevice` must be a valid, non-null pointer to an Idevice handle /// `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( pub unsafe extern "C" fn idevice_get_type(
idevice: *mut IdeviceHandle, idevice: *mut IdeviceHandle,
device_type: *mut *mut c_char, device_type: *mut *mut c_char,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if idevice.is_null() || device_type.is_null() { if idevice.is_null() || device_type.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
// Get the Idevice reference // 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(type_str) => match CString::new(type_str) {
Ok(c_string) => { Ok(c_string) => {
unsafe { *device_type = c_string.into_raw() }; 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 /// * [`idevice`] - The Idevice handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `idevice` must be a valid, non-null pointer to an Idevice handle /// `idevice` must be a valid, non-null pointer to an Idevice handle
#[unsafe(no_mangle)] #[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() { if idevice.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
// Get the Idevice reference // 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 }); let result = RUNTIME.block_on(async { dev.rsd_checkin().await });
match result { match result {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), 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 /// * [`pairing_file`] - The pairing file to use for TLS
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `idevice` must be a valid, non-null pointer to an Idevice handle /// `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( pub unsafe extern "C" fn idevice_start_session(
idevice: *mut IdeviceHandle, idevice: *mut IdeviceHandle,
pairing_file: *const IdevicePairingFile, pairing_file: *const IdevicePairingFile,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if idevice.is_null() || pairing_file.is_null() { if idevice.is_null() || pairing_file.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
// Get the Idevice reference // 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 }); let result = RUNTIME.block_on(async { dev.start_session(pf).await });
match result { match result {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), Err(e) => ffi_err!(e),
} }
} }

View File

@@ -1,8 +1,10 @@
// Jackson Coxson // Jackson Coxson
use std::ptr::null_mut;
use idevice::{ReadWrite, dvt::location_simulation::LocationSimulationClient}; 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 /// Opaque handle to a ProcessControlClient
pub struct LocationSimulationHandle<'a>(pub LocationSimulationClient<'a, Box<dyn ReadWrite>>); pub struct LocationSimulationHandle<'a>(pub LocationSimulationClient<'a, Box<dyn ReadWrite>>);
@@ -14,7 +16,7 @@ pub struct LocationSimulationHandle<'a>(pub LocationSimulationClient<'a, Box<dyn
/// * [`handle`] - Pointer to store the newly created ProcessControlClient handle /// * [`handle`] - Pointer to store the newly created ProcessControlClient handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `server` must be a valid pointer to a handle allocated by this library /// `server` must be a valid pointer to a handle allocated by this library
@@ -23,9 +25,9 @@ pub struct LocationSimulationHandle<'a>(pub LocationSimulationClient<'a, Box<dyn
pub unsafe extern "C" fn location_simulation_new( pub unsafe extern "C" fn location_simulation_new(
server: *mut RemoteServerHandle, server: *mut RemoteServerHandle,
handle: *mut *mut LocationSimulationHandle<'static>, handle: *mut *mut LocationSimulationHandle<'static>,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if server.is_null() || handle.is_null() { if server.is_null() || handle.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let server = unsafe { &mut (*server).0 }; let server = unsafe { &mut (*server).0 };
@@ -35,9 +37,9 @@ pub unsafe extern "C" fn location_simulation_new(
Ok(client) => { Ok(client) => {
let boxed = Box::new(LocationSimulationHandle(client)); let boxed = Box::new(LocationSimulationHandle(client));
unsafe { *handle = Box::into_raw(boxed) }; 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 /// * [`handle`] - The LocationSimulation handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// All pointers must be valid or NULL where appropriate /// All pointers must be valid or NULL where appropriate
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub unsafe extern "C" fn location_simulation_clear( pub unsafe extern "C" fn location_simulation_clear(
handle: *mut LocationSimulationHandle<'static>, handle: *mut LocationSimulationHandle<'static>,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if handle.is_null() { if handle.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let client = unsafe { &mut (*handle).0 }; let client = unsafe { &mut (*handle).0 };
let res = RUNTIME.block_on(async move { client.clear().await }); let res = RUNTIME.block_on(async move { client.clear().await });
match res { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), Err(e) => ffi_err!(e),
} }
} }
@@ -90,7 +92,7 @@ pub unsafe extern "C" fn location_simulation_clear(
/// * [`longitude`] - The longitude to set /// * [`longitude`] - The longitude to set
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// All pointers must be valid or NULL where appropriate /// 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>, handle: *mut LocationSimulationHandle<'static>,
latitude: f64, latitude: f64,
longitude: f64, longitude: f64,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if handle.is_null() { if handle.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let client = unsafe { &mut (*handle).0 }; let client = unsafe { &mut (*handle).0 };
let res = RUNTIME.block_on(async move { client.set(latitude, longitude).await }); let res = RUNTIME.block_on(async move { client.set(latitude, longitude).await });
match res { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), Err(e) => ffi_err!(e),
} }
} }

View File

@@ -1,11 +1,12 @@
// Jackson Coxson // Jackson Coxson
use std::ffi::c_void; use std::{ffi::c_void, ptr::null_mut};
use idevice::{IdeviceError, IdeviceService, lockdown::LockdownClient, provider::IdeviceProvider}; use idevice::{IdeviceError, IdeviceService, lockdown::LockdownClient, provider::IdeviceProvider};
use crate::{ use crate::{
IdeviceErrorCode, IdeviceHandle, IdevicePairingFile, RUNTIME, provider::IdeviceProviderHandle, IdeviceFfiError, IdeviceHandle, IdevicePairingFile, RUNTIME, ffi_err,
provider::IdeviceProviderHandle,
}; };
pub struct LockdowndClientHandle(pub LockdownClient); 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 /// * [`client`] - On success, will be set to point to a newly allocated LockdowndClient handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `provider` must be a valid pointer to a handle allocated by this library /// `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( pub unsafe extern "C" fn lockdownd_connect(
provider: *mut IdeviceProviderHandle, provider: *mut IdeviceProviderHandle,
client: *mut *mut LockdowndClientHandle, client: *mut *mut LockdowndClientHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if provider.is_null() || client.is_null() { if provider.is_null() || client.is_null() {
log::error!("Null pointer provided"); log::error!("Null pointer provided");
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let res: Result<LockdownClient, IdeviceError> = RUNTIME.block_on(async move { let res: Result<LockdownClient, IdeviceError> = RUNTIME.block_on(async move {
@@ -41,11 +42,11 @@ pub unsafe extern "C" fn lockdownd_connect(
Ok(r) => { Ok(r) => {
let boxed = Box::new(LockdowndClientHandle(r)); let boxed = Box::new(LockdowndClientHandle(r));
unsafe { *client = Box::into_raw(boxed) }; unsafe { *client = Box::into_raw(boxed) };
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
Err(e) => { Err(e) => {
let _ = unsafe { Box::from_raw(provider) }; 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 /// * [`client`] - On success, will be set to point to a newly allocated LockdowndClient handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `socket` must be a valid pointer to a handle allocated by this library. The socket is consumed, /// `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( pub unsafe extern "C" fn lockdownd_new(
socket: *mut IdeviceHandle, socket: *mut IdeviceHandle,
client: *mut *mut LockdowndClientHandle, client: *mut *mut LockdowndClientHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if socket.is_null() || client.is_null() { if socket.is_null() || client.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let socket = unsafe { Box::from_raw(socket) }.0; let socket = unsafe { Box::from_raw(socket) }.0;
let r = LockdownClient::new(socket); let r = LockdownClient::new(socket);
let boxed = Box::new(LockdowndClientHandle(r)); let boxed = Box::new(LockdowndClientHandle(r));
unsafe { *client = Box::into_raw(boxed) }; unsafe { *client = Box::into_raw(boxed) };
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
/// Starts a session with lockdownd /// Starts a session with lockdownd
@@ -85,7 +86,7 @@ pub unsafe extern "C" fn lockdownd_new(
/// * `pairing_file` - An IdevicePairingFile alocated by this library /// * `pairing_file` - An IdevicePairingFile alocated by this library
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` must be a valid pointer to a handle allocated by this library /// `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( pub unsafe extern "C" fn lockdownd_start_session(
client: *mut LockdowndClientHandle, client: *mut LockdowndClientHandle,
pairing_file: *mut IdevicePairingFile, pairing_file: *mut IdevicePairingFile,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
let res: Result<(), IdeviceError> = RUNTIME.block_on(async move { let res: Result<(), IdeviceError> = RUNTIME.block_on(async move {
let client_ref = unsafe { &mut (*client).0 }; let client_ref = unsafe { &mut (*client).0 };
let pairing_file_ref = unsafe { &(*pairing_file).0 }; let pairing_file_ref = unsafe { &(*pairing_file).0 };
@@ -103,8 +104,8 @@ pub unsafe extern "C" fn lockdownd_start_session(
}); });
match res { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), 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 /// * `ssl` - Pointer to store whether SSL should be enabled
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` must be a valid pointer to a handle allocated by this library /// `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, identifier: *const libc::c_char,
port: *mut u16, port: *mut u16,
ssl: *mut bool, ssl: *mut bool,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if identifier.is_null() || port.is_null() || ssl.is_null() { 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) } let identifier = unsafe { std::ffi::CStr::from_ptr(identifier) }
@@ -149,9 +150,9 @@ pub unsafe extern "C" fn lockdownd_start_service(
*port = p; *port = p;
*ssl = s; *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 /// * `out_plist` - Pointer to store the returned plist value
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` must be a valid pointer to a handle allocated by this library /// `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, key: *const libc::c_char,
domain: *const libc::c_char, domain: *const libc::c_char,
out_plist: *mut *mut c_void, out_plist: *mut *mut c_void,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if key.is_null() || out_plist.is_null() { 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) } let value = unsafe { std::ffi::CStr::from_ptr(key) }
@@ -205,9 +206,9 @@ pub unsafe extern "C" fn lockdownd_get_value(
unsafe { unsafe {
*out_plist = crate::util::plist_to_libplist(&value); *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 /// * `out_plist` - Pointer to store the returned plist dictionary
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` must be a valid pointer to a handle allocated by this library /// `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( pub unsafe extern "C" fn lockdownd_get_all_values(
client: *mut LockdowndClientHandle, client: *mut LockdowndClientHandle,
out_plist: *mut *mut c_void, out_plist: *mut *mut c_void,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if out_plist.is_null() { if out_plist.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let res: Result<plist::Dictionary, IdeviceError> = RUNTIME.block_on(async move { let res: Result<plist::Dictionary, IdeviceError> = RUNTIME.block_on(async move {
@@ -242,9 +243,9 @@ pub unsafe extern "C" fn lockdownd_get_all_values(
unsafe { unsafe {
*out_plist = crate::util::plist_to_libplist(&plist::Value::Dictionary(dict)); *out_plist = crate::util::plist_to_libplist(&plist::Value::Dictionary(dict));
} }
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
Err(e) => e.into(), Err(e) => ffi_err!(e),
} }
} }

View File

@@ -2,9 +2,11 @@
//! //!
//! Provides C-compatible bindings for interacting with the misagent service on iOS devices. //! 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 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); 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 /// * [`client`] - On success, will be set to point to a newly allocated MisagentClient handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `provider` must be a valid pointer to a handle allocated by this library /// `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( pub unsafe extern "C" fn misagent_connect(
provider: *mut IdeviceProviderHandle, provider: *mut IdeviceProviderHandle,
client: *mut *mut MisagentClientHandle, client: *mut *mut MisagentClientHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if provider.is_null() || client.is_null() { if provider.is_null() || client.is_null() {
log::error!("Null pointer provided"); log::error!("Null pointer provided");
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let res: Result<MisagentClient, IdeviceError> = RUNTIME.block_on(async move { let res: Result<MisagentClient, IdeviceError> = RUNTIME.block_on(async move {
@@ -39,9 +41,9 @@ pub unsafe extern "C" fn misagent_connect(
Ok(r) => { Ok(r) => {
let boxed = Box::new(MisagentClientHandle(r)); let boxed = Box::new(MisagentClientHandle(r));
unsafe { *client = Box::into_raw(boxed) }; 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 /// * [`profile_len`] - Length of the profile data
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` must be a valid pointer to a handle allocated by this library /// `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, client: *mut MisagentClientHandle,
profile_data: *const u8, profile_data: *const u8,
profile_len: libc::size_t, profile_len: libc::size_t,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if client.is_null() || profile_data.is_null() { 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(); 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 }); let res = RUNTIME.block_on(async { unsafe { &mut *client }.0.install(profile).await });
match res { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), 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) /// * [`profile_id`] - The UUID of the profile to remove (C string)
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` must be a valid pointer to a handle allocated by this library /// `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( pub unsafe extern "C" fn misagent_remove(
client: *mut MisagentClientHandle, client: *mut MisagentClientHandle,
profile_id: *const libc::c_char, profile_id: *const libc::c_char,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if client.is_null() || profile_id.is_null() { 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) } 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 }); let res = RUNTIME.block_on(async { unsafe { &mut *client }.0.remove(&id).await });
match res { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), 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 /// * [`out_profiles_len`] - On success, will be set to the number of profiles
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` must be a valid pointer to a handle allocated by this library /// `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: *mut *mut *mut u8,
out_profiles_len: *mut *mut libc::size_t, out_profiles_len: *mut *mut libc::size_t,
out_count: *mut libc::size_t, out_count: *mut libc::size_t,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if client.is_null() if client.is_null()
|| out_profiles.is_null() || out_profiles.is_null()
|| out_profiles_len.is_null() || out_profiles_len.is_null()
|| out_count.is_null() || out_count.is_null()
{ {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let res: Result<Vec<Vec<u8>>, IdeviceError> = let res: Result<Vec<Vec<u8>>, IdeviceError> =
@@ -167,9 +169,9 @@ pub unsafe extern "C" fn misagent_copy_all(
*out_count = count; *out_count = count;
} }
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
Err(e) => e.into(), Err(e) => ffi_err!(e),
} }
} }

View File

@@ -1,13 +1,15 @@
// Jackson Coxson // Jackson Coxson
use std::ffi::c_void; use std::{ffi::c_void, ptr::null_mut};
use idevice::{ use idevice::{
IdeviceError, IdeviceService, mobile_image_mounter::ImageMounter, provider::IdeviceProvider, IdeviceError, IdeviceService, mobile_image_mounter::ImageMounter, provider::IdeviceProvider,
}; };
use plist::Value; 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); 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 /// * [`client`] - On success, will be set to point to a newly allocated ImageMounter handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `provider` must be a valid pointer to a handle allocated by this library /// `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( pub unsafe extern "C" fn image_mounter_connect(
provider: *mut IdeviceProviderHandle, provider: *mut IdeviceProviderHandle,
client: *mut *mut ImageMounterHandle, client: *mut *mut ImageMounterHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if provider.is_null() || client.is_null() { if provider.is_null() || client.is_null() {
log::error!("Null pointer provided"); log::error!("Null pointer provided");
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let res: Result<ImageMounter, IdeviceError> = RUNTIME.block_on(async move { let res: Result<ImageMounter, IdeviceError> = RUNTIME.block_on(async move {
@@ -42,11 +44,11 @@ pub unsafe extern "C" fn image_mounter_connect(
Ok(r) => { Ok(r) => {
let boxed = Box::new(ImageMounterHandle(r)); let boxed = Box::new(ImageMounterHandle(r));
unsafe { *client = Box::into_raw(boxed) }; unsafe { *client = Box::into_raw(boxed) };
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
Err(e) => { Err(e) => {
let _ = unsafe { Box::from_raw(provider) }; 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 /// * [`client`] - On success, will be set to point to a newly allocated ImageMounter handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `socket` must be a valid pointer to a handle allocated by this library /// `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( pub unsafe extern "C" fn image_mounter_new(
socket: *mut IdeviceHandle, socket: *mut IdeviceHandle,
client: *mut *mut ImageMounterHandle, client: *mut *mut ImageMounterHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if socket.is_null() { if socket.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let socket = unsafe { Box::from_raw(socket) }.0; let socket = unsafe { Box::from_raw(socket) }.0;
let r = ImageMounter::new(socket); let r = ImageMounter::new(socket);
let boxed = Box::new(ImageMounterHandle(r)); let boxed = Box::new(ImageMounterHandle(r));
unsafe { *client = Box::into_raw(boxed) }; unsafe { *client = Box::into_raw(boxed) };
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
/// Frees an ImageMounter handle /// 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 /// * [`devices_len`] - Will be set to the number of devices copied
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` must be a valid pointer to a handle allocated by this library /// `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, client: *mut ImageMounterHandle,
devices: *mut *mut c_void, devices: *mut *mut c_void,
devices_len: *mut libc::size_t, devices_len: *mut libc::size_t,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
let res: Result<Vec<Value>, IdeviceError> = RUNTIME.block_on(async move { let res: Result<Vec<Value>, IdeviceError> = RUNTIME.block_on(async move {
let client_ref = unsafe { &mut (*client).0 }; let client_ref = unsafe { &mut (*client).0 };
client_ref.copy_devices().await 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 = ptr as *mut c_void;
*devices_len = len; *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 /// * [`signature_len`] - Will be set to the length of the signature data
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` must be a valid pointer to a handle allocated by this library /// `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, image_type: *const libc::c_char,
signature: *mut *mut u8, signature: *mut *mut u8,
signature_len: *mut libc::size_t, signature_len: *mut libc::size_t,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if image_type.is_null() || signature.is_null() || signature_len.is_null() { 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_cstr = unsafe { std::ffi::CStr::from_ptr(image_type) };
let image_type = match image_type_cstr.to_str() { let image_type = match image_type_cstr.to_str() {
Ok(s) => s, Ok(s) => s,
Err(_) => return IdeviceErrorCode::InvalidArg, Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg),
}; };
let res: Result<Vec<u8>, IdeviceError> = RUNTIME.block_on(async move { let res: Result<Vec<u8>, IdeviceError> = RUNTIME.block_on(async move {
@@ -183,9 +185,9 @@ pub unsafe extern "C" fn image_mounter_lookup_image(
*signature_len = boxed.len(); *signature_len = boxed.len();
} }
std::mem::forget(boxed); 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 /// * [`signature_len`] - Length of the signature data
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// All pointers must be valid and non-null /// 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, image_len: libc::size_t,
signature: *const u8, signature: *const u8,
signature_len: libc::size_t, signature_len: libc::size_t,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if image_type.is_null() || image.is_null() || signature.is_null() { 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_cstr = unsafe { std::ffi::CStr::from_ptr(image_type) };
let image_type = match image_type_cstr.to_str() { let image_type = match image_type_cstr.to_str() {
Ok(s) => s, 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) }; 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 { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), 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) /// * [`info_plist`] - Pointer to info plist (optional)
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// All pointers must be valid (except optional ones which can be null) /// 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: *const u8,
trust_cache_len: libc::size_t, trust_cache_len: libc::size_t,
info_plist: *const c_void, info_plist: *const c_void,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if image_type.is_null() || signature.is_null() { 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_cstr = unsafe { std::ffi::CStr::from_ptr(image_type) };
let image_type = match image_type_cstr.to_str() { let image_type = match image_type_cstr.to_str() {
Ok(s) => s, 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) }; 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 { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), 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 /// * [`mount_path`] - The path where the image is mounted
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` must be a valid pointer to a handle allocated by this library /// `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( pub unsafe extern "C" fn image_mounter_unmount_image(
client: *mut ImageMounterHandle, client: *mut ImageMounterHandle,
mount_path: *const libc::c_char, mount_path: *const libc::c_char,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if mount_path.is_null() { 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_cstr = unsafe { std::ffi::CStr::from_ptr(mount_path) };
let mount_path = match mount_path_cstr.to_str() { let mount_path = match mount_path_cstr.to_str() {
Ok(s) => s, Ok(s) => s,
Err(_) => return IdeviceErrorCode::InvalidArg, Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg),
}; };
let res: Result<(), IdeviceError> = RUNTIME.block_on(async move { let res: Result<(), IdeviceError> = RUNTIME.block_on(async move {
@@ -345,8 +347,8 @@ pub unsafe extern "C" fn image_mounter_unmount_image(
}); });
match res { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), 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) /// * [`status`] - Will be set to the developer mode status (1 = enabled, 0 = disabled)
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` must be a valid pointer to a handle allocated by this library /// `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( pub unsafe extern "C" fn image_mounter_query_developer_mode_status(
client: *mut ImageMounterHandle, client: *mut ImageMounterHandle,
status: *mut libc::c_int, status: *mut libc::c_int,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if status.is_null() { if status.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let res: Result<bool, IdeviceError> = RUNTIME.block_on(async move { let res: Result<bool, IdeviceError> = RUNTIME.block_on(async move {
@@ -379,9 +381,9 @@ pub unsafe extern "C" fn image_mounter_query_developer_mode_status(
match res { match res {
Ok(s) => { Ok(s) => {
unsafe { *status = if s { 1 } else { 0 } }; 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 /// * [`signature_len`] - Length of the signature data
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// All pointers must be valid and non-null /// 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, image_len: libc::size_t,
signature: *const u8, signature: *const u8,
signature_len: libc::size_t, signature_len: libc::size_t,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if image.is_null() || signature.is_null() { 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) }; 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 { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), 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 /// * [`manifest_len`] - Will be set to the length of the manifest data
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// All pointers must be valid and non-null /// 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, signature_len: libc::size_t,
manifest: *mut *mut u8, manifest: *mut *mut u8,
manifest_len: *mut libc::size_t, manifest_len: *mut libc::size_t,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if image_type.is_null() || signature.is_null() || manifest.is_null() || manifest_len.is_null() { 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_cstr = unsafe { std::ffi::CStr::from_ptr(image_type) };
let image_type = match image_type_cstr.to_str() { let image_type = match image_type_cstr.to_str() {
Ok(s) => s, 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) }; 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(); *manifest_len = boxed.len();
} }
std::mem::forget(boxed); 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 /// * [`nonce_len`] - Will be set to the length of the nonce data
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client`, `nonce`, and `nonce_len` must be valid pointers /// `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, personalized_image_type: *const libc::c_char,
nonce: *mut *mut u8, nonce: *mut *mut u8,
nonce_len: *mut libc::size_t, nonce_len: *mut libc::size_t,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if nonce.is_null() || nonce_len.is_null() { 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 = if !personalized_image_type.is_null() {
let image_type_cstr = unsafe { std::ffi::CStr::from_ptr(personalized_image_type) }; let image_type_cstr = unsafe { std::ffi::CStr::from_ptr(personalized_image_type) };
match image_type_cstr.to_str() { match image_type_cstr.to_str() {
Ok(s) => Some(s.to_string()), Ok(s) => Some(s.to_string()),
Err(_) => return IdeviceErrorCode::InvalidArg, Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg),
} }
} else { } else {
None None
@@ -533,9 +535,9 @@ pub unsafe extern "C" fn image_mounter_query_nonce(
*nonce_len = boxed.len(); *nonce_len = boxed.len();
} }
std::mem::forget(boxed); 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 /// * [`identifiers`] - Will be set to point to the identifiers plist on success
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` and `identifiers` must be valid pointers /// `client` and `identifiers` must be valid pointers
@@ -557,16 +559,16 @@ pub unsafe extern "C" fn image_mounter_query_personalization_identifiers(
client: *mut ImageMounterHandle, client: *mut ImageMounterHandle,
image_type: *const libc::c_char, image_type: *const libc::c_char,
identifiers: *mut *mut c_void, identifiers: *mut *mut c_void,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if identifiers.is_null() { if identifiers.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let image_type = if !image_type.is_null() { let image_type = if !image_type.is_null() {
let image_type_cstr = unsafe { std::ffi::CStr::from_ptr(image_type) }; let image_type_cstr = unsafe { std::ffi::CStr::from_ptr(image_type) };
match image_type_cstr.to_str() { match image_type_cstr.to_str() {
Ok(s) => Some(s.to_string()), Ok(s) => Some(s.to_string()),
Err(_) => return IdeviceErrorCode::InvalidArg, Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg),
} }
} else { } else {
None None
@@ -583,9 +585,9 @@ pub unsafe extern "C" fn image_mounter_query_personalization_identifiers(
Ok(id) => { Ok(id) => {
let plist = util::plist_to_libplist(&plist::Value::Dictionary(id)); let plist = util::plist_to_libplist(&plist::Value::Dictionary(id));
unsafe { *identifiers = plist }; 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 /// * [`client`] - A valid ImageMounter handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` must be a valid pointer to a handle allocated by this library /// `client` must be a valid pointer to a handle allocated by this library
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub unsafe extern "C" fn image_mounter_roll_personalization_nonce( pub unsafe extern "C" fn image_mounter_roll_personalization_nonce(
client: *mut ImageMounterHandle, client: *mut ImageMounterHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
let res: Result<(), IdeviceError> = RUNTIME.block_on(async move { let res: Result<(), IdeviceError> = RUNTIME.block_on(async move {
let client_ref = unsafe { &mut (*client).0 }; let client_ref = unsafe { &mut (*client).0 };
client_ref.roll_personalization_nonce().await client_ref.roll_personalization_nonce().await
}); });
match res { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), Err(e) => ffi_err!(e),
} }
} }
@@ -620,22 +622,22 @@ pub unsafe extern "C" fn image_mounter_roll_personalization_nonce(
/// * [`client`] - A valid ImageMounter handle /// * [`client`] - A valid ImageMounter handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` must be a valid pointer to a handle allocated by this library /// `client` must be a valid pointer to a handle allocated by this library
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub unsafe extern "C" fn image_mounter_roll_cryptex_nonce( pub unsafe extern "C" fn image_mounter_roll_cryptex_nonce(
client: *mut ImageMounterHandle, client: *mut ImageMounterHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
let res: Result<(), IdeviceError> = RUNTIME.block_on(async move { let res: Result<(), IdeviceError> = RUNTIME.block_on(async move {
let client_ref = unsafe { &mut (*client).0 }; let client_ref = unsafe { &mut (*client).0 };
client_ref.roll_cryptex_nonce().await client_ref.roll_cryptex_nonce().await
}); });
match res { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), 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 /// * [`unique_chip_id`] - The device's unique chip ID
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// All pointers must be valid (except optional ones which can be null) /// 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, build_manifest_len: libc::size_t,
info_plist: *const c_void, info_plist: *const c_void,
unique_chip_id: u64, unique_chip_id: u64,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if provider.is_null() || image.is_null() || trust_cache.is_null() || build_manifest.is_null() { 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) }; 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 { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), 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 /// * [`context`] - User context to pass to callback
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// All pointers must be valid (except optional ones which can be null) /// 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, unique_chip_id: u64,
callback: extern "C" fn(progress: libc::size_t, total: libc::size_t, context: *mut c_void), callback: extern "C" fn(progress: libc::size_t, total: libc::size_t, context: *mut c_void),
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() { 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) }; 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 { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), Err(e) => ffi_err!(e),
} }
} }

View File

@@ -1,11 +1,11 @@
use std::ffi::CString;
use std::os::raw::c_char; use std::os::raw::c_char;
use std::{ffi::CString, ptr::null_mut};
use idevice::{ use idevice::{
IdeviceError, IdeviceService, os_trace_relay::OsTraceRelayClient, provider::IdeviceProvider, 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 OsTraceRelayClientHandle(pub OsTraceRelayClient);
pub struct OsTraceRelayReceiverHandle(pub idevice::os_trace_relay::OsTraceRelayReceiver); 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 /// * [`client`] - A pointer where the handle will be allocated
/// ///
/// # Returns /// # Returns
/// 0 for success, an IdeviceErrorCode otherwise /// 0 for success, an *mut IdeviceFfiError otherwise
/// ///
/// # Safety /// # Safety
/// None of the arguments can be null. Provider must be allocated by this library. /// 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( pub unsafe extern "C" fn os_trace_relay_connect(
provider: *mut IdeviceProviderHandle, provider: *mut IdeviceProviderHandle,
client: *mut *mut OsTraceRelayClientHandle, client: *mut *mut OsTraceRelayClientHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if provider.is_null() { if provider.is_null() {
log::error!("Null pointer provided"); log::error!("Null pointer provided");
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let res: Result<OsTraceRelayClient, IdeviceError> = RUNTIME.block_on(async move { let res: Result<OsTraceRelayClient, IdeviceError> = RUNTIME.block_on(async move {
@@ -59,11 +59,11 @@ pub unsafe extern "C" fn os_trace_relay_connect(
Ok(c) => { Ok(c) => {
let boxed = Box::new(OsTraceRelayClientHandle(c)); let boxed = Box::new(OsTraceRelayClientHandle(c));
unsafe { *client = Box::into_raw(boxed) }; unsafe { *client = Box::into_raw(boxed) };
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
Err(e) => { Err(e) => {
let _ = unsafe { Box::from_raw(provider) }; 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. /// * [`pid`] - An optional pointer to a PID to get logs for. May be null.
/// ///
/// # Returns /// # Returns
/// 0 for success, an IdeviceErrorCode otherwise /// 0 for success, an *mut IdeviceFfiError otherwise
/// ///
/// # Safety /// # Safety
/// The handle must be allocated by this library. It is consumed, and must never be used again. /// 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, client: *mut OsTraceRelayClientHandle,
receiver: *mut *mut OsTraceRelayReceiverHandle, receiver: *mut *mut OsTraceRelayReceiverHandle,
pid: *const u32, pid: *const u32,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if receiver.is_null() || client.is_null() { if receiver.is_null() || client.is_null() {
log::error!("Null pointer provided"); log::error!("Null pointer provided");
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let pid_option = if pid.is_null() { 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)); let boxed = Box::new(OsTraceRelayReceiverHandle(relay));
unsafe { *receiver = Box::into_raw(boxed) }; 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 /// * [`list`] - A pointer to allocate a list of PIDs to
/// ///
/// # Returns /// # Returns
/// 0 for success, an IdeviceErrorCode otherwise /// 0 for success, an *mut IdeviceFfiError otherwise
/// ///
/// # Safety /// # Safety
/// The handle must be allocated by this library. /// 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( pub unsafe extern "C" fn os_trace_relay_get_pid_list(
client: *mut OsTraceRelayClientHandle, client: *mut OsTraceRelayClientHandle,
list: *mut *mut Vec<u64>, list: *mut *mut Vec<u64>,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
let res = RUNTIME.block_on(async { unsafe { &mut *client }.0.get_pid_list().await }); let res = RUNTIME.block_on(async { unsafe { &mut *client }.0.get_pid_list().await });
match res { match res {
Ok(r) => { Ok(r) => {
unsafe { *list = Box::into_raw(Box::new(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 /// * [`log`] - A pointer to allocate the new log
/// ///
/// # Returns /// # Returns
/// 0 for success, an IdeviceErrorCode otherwise /// 0 for success, an *mut IdeviceFfiError otherwise
/// ///
/// # Safety /// # Safety
/// The handle must be allocated by this library. /// 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( pub unsafe extern "C" fn os_trace_relay_next(
client: *mut OsTraceRelayReceiverHandle, client: *mut OsTraceRelayReceiverHandle,
log: *mut *mut OsTraceLog, log: *mut *mut OsTraceLog,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if client.is_null() { if client.is_null() {
log::error!("Null pointer provided"); 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 }); 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) }; 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 /// * [`log`] - The log to free
/// ///
/// # Returns /// # Returns
/// 0 for success, an IdeviceErrorCode otherwise /// 0 for success, an *mut IdeviceFfiError otherwise
/// ///
/// # Safety /// # Safety
/// The log must be allocated by this library. It is consumed and must not be used again. /// 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) {
} }
} }
} }

View File

@@ -1,9 +1,12 @@
// Jackson Coxson // Jackson Coxson
use idevice::pairing_file::PairingFile; 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 /// Opaque C-compatible handle to a PairingFile
pub struct IdevicePairingFile(pub 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 /// * [`pairing_file`] - On success, will be set to point to a newly allocated pairing file instance
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `path` must be a valid null-terminated C string /// `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( pub unsafe extern "C" fn idevice_pairing_file_read(
path: *const c_char, path: *const c_char,
pairing_file: *mut *mut IdevicePairingFile, pairing_file: *mut *mut IdevicePairingFile,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if path.is_null() || pairing_file.is_null() { if path.is_null() || pairing_file.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
// Convert C string to Rust path // Convert C string to Rust path
let c_str = match unsafe { CStr::from_ptr(path) }.to_str() { let c_str = match unsafe { CStr::from_ptr(path) }.to_str() {
Ok(s) => s, Ok(s) => s,
Err(_) => return IdeviceErrorCode::InvalidArg, Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg),
}; };
// Read the pairing file // Read the pairing file
@@ -42,9 +45,9 @@ pub unsafe extern "C" fn idevice_pairing_file_read(
unsafe { unsafe {
*pairing_file = Box::into_raw(boxed); *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 /// * [`pairing_file`] - On success, will be set to point to a newly allocated pairing file instance
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `data` must be a valid pointer to a buffer of at least `size` bytes /// `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, data: *const u8,
size: usize, size: usize,
pairing_file: *mut *mut IdevicePairingFile, pairing_file: *mut *mut IdevicePairingFile,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if data.is_null() || pairing_file.is_null() || size == 0 { if data.is_null() || pairing_file.is_null() || size == 0 {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
// Convert to Rust slice // Convert to Rust slice
@@ -79,9 +82,9 @@ pub unsafe extern "C" fn idevice_pairing_file_from_bytes(
Ok(pf) => { Ok(pf) => {
let boxed = Box::new(IdevicePairingFile(pf)); let boxed = Box::new(IdevicePairingFile(pf));
unsafe { *pairing_file = Box::into_raw(boxed) }; 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 /// * [`size`] - On success, will be set to the size of the allocated buffer
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `pairing_file` must be a valid, non-null pointer to a pairing file instance /// `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, pairing_file: *const IdevicePairingFile,
data: *mut *mut u8, data: *mut *mut u8,
size: *mut usize, size: *mut usize,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if pairing_file.is_null() || data.is_null() || size.is_null() { if pairing_file.is_null() || data.is_null() || size.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
// Get the pairing file // 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; let buffer_ptr = Box::into_raw(buffer.into_boxed_slice()) as *mut u8;
unsafe { *data = buffer_ptr }; unsafe { *data = buffer_ptr };
unsafe { *size = buffer_size }; unsafe { *size = buffer_size };
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
Err(e) => e.into(), Err(e) => ffi_err!(e),
} }
} }

View File

@@ -1,11 +1,14 @@
// Jackson Coxson // 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 idevice::{ReadWrite, dvt::process_control::ProcessControlClient};
use plist::{Dictionary, Value}; 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 /// Opaque handle to a ProcessControlClient
pub struct ProcessControlHandle<'a>(pub ProcessControlClient<'a, Box<dyn ReadWrite>>); pub struct ProcessControlHandle<'a>(pub ProcessControlClient<'a, Box<dyn ReadWrite>>);
@@ -17,7 +20,7 @@ pub struct ProcessControlHandle<'a>(pub ProcessControlClient<'a, Box<dyn ReadWri
/// * [`handle`] - Pointer to store the newly created ProcessControlClient handle /// * [`handle`] - Pointer to store the newly created ProcessControlClient handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `server` must be a valid pointer to a handle allocated by this library /// `server` must be a valid pointer to a handle allocated by this library
@@ -26,9 +29,9 @@ pub struct ProcessControlHandle<'a>(pub ProcessControlClient<'a, Box<dyn ReadWri
pub unsafe extern "C" fn process_control_new( pub unsafe extern "C" fn process_control_new(
server: *mut RemoteServerHandle, server: *mut RemoteServerHandle,
handle: *mut *mut ProcessControlHandle<'static>, handle: *mut *mut ProcessControlHandle<'static>,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if server.is_null() || handle.is_null() { if server.is_null() || handle.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let server = unsafe { &mut (*server).0 }; let server = unsafe { &mut (*server).0 };
@@ -38,9 +41,9 @@ pub unsafe extern "C" fn process_control_new(
Ok(client) => { Ok(client) => {
let boxed = Box::new(ProcessControlHandle(client)); let boxed = Box::new(ProcessControlHandle(client));
unsafe { *handle = Box::into_raw(boxed) }; 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 /// * [`pid`] - Pointer to store the process ID of the launched app
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// All pointers must be valid or NULL where appropriate /// 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, start_suspended: bool,
kill_existing: bool, kill_existing: bool,
pid: *mut u64, pid: *mut u64,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if handle.is_null() || bundle_id.is_null() || pid.is_null() { 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 = unsafe { CStr::from_ptr(bundle_id) };
let bundle_id = match bundle_id.to_str() { let bundle_id = match bundle_id.to_str() {
Ok(s) => s.to_string(), Ok(s) => s.to_string(),
Err(_) => return IdeviceErrorCode::InvalidArg, Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg),
}; };
let mut env_dict = Dictionary::new(); let mut env_dict = Dictionary::new();
@@ -140,9 +143,9 @@ pub unsafe extern "C" fn process_control_launch_app(
match res { match res {
Ok(p) => { Ok(p) => {
unsafe { *pid = 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 /// * [`pid`] - The process ID to kill
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `handle` must be a valid pointer to a handle allocated by this library /// `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( pub unsafe extern "C" fn process_control_kill_app(
handle: *mut ProcessControlHandle<'static>, handle: *mut ProcessControlHandle<'static>,
pid: u64, pid: u64,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if handle.is_null() { if handle.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let client = unsafe { &mut (*handle).0 }; let client = unsafe { &mut (*handle).0 };
let res = RUNTIME.block_on(async move { client.kill_app(pid).await }); let res = RUNTIME.block_on(async move { client.kill_app(pid).await });
match res { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), Err(e) => ffi_err!(e),
} }
} }
@@ -182,7 +185,7 @@ pub unsafe extern "C" fn process_control_kill_app(
/// * [`pid`] - The process ID to modify /// * [`pid`] - The process ID to modify
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `handle` must be a valid pointer to a handle allocated by this library /// `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( pub unsafe extern "C" fn process_control_disable_memory_limit(
handle: *mut ProcessControlHandle<'static>, handle: *mut ProcessControlHandle<'static>,
pid: u64, pid: u64,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if handle.is_null() { if handle.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let client = unsafe { &mut (*handle).0 }; let client = unsafe { &mut (*handle).0 };
let res = RUNTIME.block_on(async move { client.disable_memory_limit(pid).await }); let res = RUNTIME.block_on(async move { client.disable_memory_limit(pid).await });
match res { match res {
Ok(_) => IdeviceErrorCode::IdeviceSuccess, Ok(_) => null_mut(),
Err(e) => e.into(), Err(e) => ffi_err!(e),
} }
} }

View File

@@ -1,10 +1,10 @@
// Jackson Coxson // Jackson Coxson
use idevice::provider::{IdeviceProvider, TcpProvider, UsbmuxdProvider}; use idevice::provider::{IdeviceProvider, TcpProvider, UsbmuxdProvider};
use std::ffi::CStr;
use std::os::raw::c_char; 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<dyn IdeviceProvider>); pub struct IdeviceProviderHandle(pub Box<dyn IdeviceProvider>);
@@ -17,7 +17,7 @@ pub struct IdeviceProviderHandle(pub Box<dyn IdeviceProvider>);
/// * [`provider`] - A pointer to a newly allocated provider /// * [`provider`] - A pointer to a newly allocated provider
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `ip` must be a valid sockaddr /// `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, pairing_file: *mut crate::pairing_file::IdevicePairingFile,
label: *const c_char, label: *const c_char,
provider: *mut *mut IdeviceProviderHandle, provider: *mut *mut IdeviceProviderHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if ip.is_null() || label.is_null() || provider.is_null() { 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) { let addr = match util::c_addr_to_rust(ip) {
Ok(i) => i, Ok(i) => i,
Err(e) => { Err(e) => {
return e; return ffi_err!(e);
} }
}; };
let label = match unsafe { CStr::from_ptr(label) }.to_str() { let label = match unsafe { CStr::from_ptr(label) }.to_str() {
Ok(l) => l.to_string(), Ok(l) => l.to_string(),
Err(e) => { Err(e) => {
log::error!("Invalid label string: {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))); let boxed = Box::new(IdeviceProviderHandle(Box::new(t)));
unsafe { *provider = Box::into_raw(boxed) }; unsafe { *provider = Box::into_raw(boxed) };
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
/// Frees an IdeviceProvider handle /// 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 /// * [`provider`] - A pointer to a newly allocated provider
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `addr` must be a valid pointer to UsbmuxdAddrHandle created by this library, and never used again /// `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, device_id: u32,
label: *const c_char, label: *const c_char,
provider: *mut *mut IdeviceProviderHandle, provider: *mut *mut IdeviceProviderHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if addr.is_null() || udid.is_null() || label.is_null() || provider.is_null() { 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() { let udid = match unsafe { CStr::from_ptr(udid) }.to_str() {
Ok(u) => u.to_string(), Ok(u) => u.to_string(),
Err(e) => { Err(e) => {
log::error!("Invalid UDID string: {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(), Ok(l) => l.to_string(),
Err(e) => { Err(e) => {
log::error!("Invalid label string: {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))); let boxed = Box::new(IdeviceProviderHandle(Box::new(p)));
unsafe { *provider = Box::into_raw(boxed) }; unsafe { *provider = Box::into_raw(boxed) };
IdeviceErrorCode::IdeviceSuccess null_mut()
} }

View File

@@ -1,8 +1,10 @@
// Jackson Coxson // Jackson Coxson
use std::ptr::null_mut;
use crate::core_device_proxy::AdapterHandle; use crate::core_device_proxy::AdapterHandle;
use crate::rsd::RsdHandshakeHandle; use crate::rsd::RsdHandshakeHandle;
use crate::{IdeviceErrorCode, RUNTIME, ReadWriteOpaque}; use crate::{IdeviceFfiError, RUNTIME, ReadWriteOpaque, ffi_err};
use idevice::dvt::remote_server::RemoteServerClient; use idevice::dvt::remote_server::RemoteServerClient;
use idevice::tcp::stream::AdapterStream; use idevice::tcp::stream::AdapterStream;
use idevice::{IdeviceError, ReadWrite, RsdService}; use idevice::{IdeviceError, ReadWrite, RsdService};
@@ -17,7 +19,7 @@ pub struct RemoteServerHandle(pub RemoteServerClient<Box<dyn ReadWrite>>);
/// * [`handle`] - Pointer to store the newly created RemoteServerClient handle /// * [`handle`] - Pointer to store the newly created RemoteServerClient handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `socket` must be a valid pointer to a handle allocated by this library. It is consumed and may /// `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<Box<dyn ReadWrite>>);
pub unsafe extern "C" fn remote_server_new( pub unsafe extern "C" fn remote_server_new(
socket: *mut ReadWriteOpaque, socket: *mut ReadWriteOpaque,
handle: *mut *mut RemoteServerHandle, handle: *mut *mut RemoteServerHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if socket.is_null() { if socket.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let wrapper = unsafe { &mut *socket }; let wrapper = unsafe { &mut *socket };
@@ -41,16 +43,16 @@ pub unsafe extern "C" fn remote_server_new(
client.read_message(0).await?; client.read_message(0).await?;
Ok(client) Ok(client)
}), }),
None => return IdeviceErrorCode::InvalidArg, None => return ffi_err!(IdeviceError::FfiInvalidArg),
}; };
match res { match res {
Ok(client) => { Ok(client) => {
let boxed = Box::new(RemoteServerHandle(client)); let boxed = Box::new(RemoteServerHandle(client));
unsafe { *handle = Box::into_raw(boxed) }; 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 /// * [`handshake`] - An RSD handshake from the same provider
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `provider` must be a valid pointer to a handle allocated by this library /// `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, provider: *mut AdapterHandle,
handshake: *mut RsdHandshakeHandle, handshake: *mut RsdHandshakeHandle,
handle: *mut *mut RemoteServerHandle, handle: *mut *mut RemoteServerHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if provider.is_null() || handshake.is_null() || handshake.is_null() { if provider.is_null() || handshake.is_null() || handshake.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let res: Result<RemoteServerClient<AdapterStream>, IdeviceError> = let res: Result<RemoteServerClient<AdapterStream>, IdeviceError> =
RUNTIME.block_on(async move { RUNTIME.block_on(async move {
@@ -90,9 +92,9 @@ pub unsafe extern "C" fn remote_server_connect_rsd(
d.into_inner(), d.into_inner(),
)))); ))));
unsafe { *handle = Box::into_raw(boxed) }; unsafe { *handle = Box::into_raw(boxed) };
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
Err(e) => e.into(), Err(e) => ffi_err!(e),
} }
} }

View File

@@ -3,11 +3,11 @@
//! Provides C-compatible bindings for RSD handshake and service discovery on iOS devices. //! Provides C-compatible bindings for RSD handshake and service discovery on iOS devices.
use std::ffi::{CStr, CString}; use std::ffi::{CStr, CString};
use std::ptr; use std::ptr::{self, null_mut};
use idevice::rsd::RsdHandshake; use idevice::rsd::RsdHandshake;
use crate::{IdeviceErrorCode, RUNTIME, ReadWriteOpaque}; use crate::{IdeviceFfiError, RUNTIME, ReadWriteOpaque, ffi_err};
/// Opaque handle to an RsdHandshake /// Opaque handle to an RsdHandshake
pub struct RsdHandshakeHandle(pub RsdHandshake); pub struct RsdHandshakeHandle(pub RsdHandshake);
@@ -47,7 +47,7 @@ pub struct CRsdServiceArray {
/// * [`handle`] - Pointer to store the newly created RsdHandshake handle /// * [`handle`] - Pointer to store the newly created RsdHandshake handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `socket` must be a valid pointer to a ReadWrite handle allocated by this library. It is /// `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( pub unsafe extern "C" fn rsd_handshake_new(
socket: *mut ReadWriteOpaque, socket: *mut ReadWriteOpaque,
handle: *mut *mut RsdHandshakeHandle, handle: *mut *mut RsdHandshakeHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if socket.is_null() || handle.is_null() { if socket.is_null() || handle.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let wrapper = unsafe { &mut *socket }; let wrapper = unsafe { &mut *socket };
@@ -67,7 +67,7 @@ pub unsafe extern "C" fn rsd_handshake_new(
let res = match wrapper.inner.take() { let res = match wrapper.inner.take() {
Some(mut w) => RUNTIME.block_on(async move { RsdHandshake::new(w.as_mut()).await }), Some(mut w) => RUNTIME.block_on(async move { RsdHandshake::new(w.as_mut()).await }),
None => { None => {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
}; };
@@ -75,9 +75,9 @@ pub unsafe extern "C" fn rsd_handshake_new(
Ok(handshake) => { Ok(handshake) => {
let boxed = Box::new(RsdHandshakeHandle(handshake)); let boxed = Box::new(RsdHandshakeHandle(handshake));
unsafe { *handle = Box::into_raw(boxed) }; 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 /// * [`version`] - Pointer to store the protocol version
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `handle` must be a valid pointer to a handle allocated by this library /// `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( pub unsafe extern "C" fn rsd_get_protocol_version(
handle: *mut RsdHandshakeHandle, handle: *mut RsdHandshakeHandle,
version: *mut libc::size_t, version: *mut libc::size_t,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if handle.is_null() || version.is_null() { if handle.is_null() || version.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
unsafe { unsafe {
*version = (*handle).0.protocol_version; *version = (*handle).0.protocol_version;
} }
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
/// Gets the UUID from the RSD handshake /// 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) /// * [`uuid`] - Pointer to store the UUID string (caller must free with rsd_free_string)
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `handle` must be a valid pointer to a handle allocated by this library /// `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( pub unsafe extern "C" fn rsd_get_uuid(
handle: *mut RsdHandshakeHandle, handle: *mut RsdHandshakeHandle,
uuid: *mut *mut libc::c_char, uuid: *mut *mut libc::c_char,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if handle.is_null() || uuid.is_null() { if handle.is_null() || uuid.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let uuid_str = &unsafe { &*handle }.0.uuid; let uuid_str = &unsafe { &*handle }.0.uuid;
match CString::new(uuid_str.as_str()) { match CString::new(uuid_str.as_str()) {
Ok(c_str) => { Ok(c_str) => {
unsafe { *uuid = c_str.into_raw() }; 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 /// * [`services`] - Pointer to store the services array
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `handle` must be a valid pointer to a handle allocated by this library /// `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( pub unsafe extern "C" fn rsd_get_services(
handle: *mut RsdHandshakeHandle, handle: *mut RsdHandshakeHandle,
services: *mut *mut CRsdServiceArray, services: *mut *mut CRsdServiceArray,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if handle.is_null() || services.is_null() { if handle.is_null() || services.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let handshake = unsafe { &*handle }; let handshake = unsafe { &*handle };
@@ -201,7 +201,7 @@ pub unsafe extern "C" fn rsd_get_services(
} }
} }
// Return early to avoid the move below // 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) }; unsafe { *services = Box::into_raw(array) };
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
/// Checks if a specific service is available /// 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 /// * [`available`] - Pointer to store the availability result
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `handle` must be a valid pointer to a handle allocated by this library /// `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, handle: *mut RsdHandshakeHandle,
service_name: *const libc::c_char, service_name: *const libc::c_char,
available: *mut bool, available: *mut bool,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if handle.is_null() || service_name.is_null() || available.is_null() { 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() { let name = match unsafe { CStr::from_ptr(service_name) }.to_str() {
Ok(s) => s, Ok(s) => s,
Err(_) => return IdeviceErrorCode::InvalidArg, Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg),
}; };
let handshake = unsafe { &*handle }; let handshake = unsafe { &*handle };
unsafe { *available = handshake.0.services.contains_key(name) }; unsafe { *available = handshake.0.services.contains_key(name) };
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
/// Gets information about a specific service /// 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 /// * [`service_info`] - Pointer to store the service information
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `handle` must be a valid pointer to a handle allocated by this library /// `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, handle: *mut RsdHandshakeHandle,
service_name: *const libc::c_char, service_name: *const libc::c_char,
service_info: *mut *mut CRsdService, service_info: *mut *mut CRsdService,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if handle.is_null() || service_name.is_null() || service_info.is_null() { 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() { let name = match unsafe { CStr::from_ptr(service_name) }.to_str() {
Ok(s) => s, Ok(s) => s,
Err(_) => return IdeviceErrorCode::InvalidArg, Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg),
}; };
let handshake = unsafe { &*handle }; let handshake = unsafe { &*handle };
let service = match handshake.0.services.get(name) { let service = match handshake.0.services.get(name) {
Some(s) => s, Some(s) => s,
None => return IdeviceErrorCode::ServiceNotFound, None => return ffi_err!(IdeviceError::ServiceNotFound),
}; };
// Convert service to C representation (similar to rsd_get_services logic) // Convert service to C representation (similar to rsd_get_services logic)
let c_name = match CString::new(name) { let c_name = match CString::new(name) {
Ok(s) => s.into_raw(), 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()) { let c_entitlement = match CString::new(service.entitlement.as_str()) {
@@ -320,7 +320,7 @@ pub unsafe extern "C" fn rsd_get_service_info(
unsafe { unsafe {
let _ = CString::from_raw(c_name); 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_name);
let _ = CString::from_raw(c_entitlement); 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) }; unsafe { *service_info = Box::into_raw(c_service) };
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
/// Frees a string returned by RSD functions /// Frees a string returned by RSD functions

View File

@@ -1,11 +1,14 @@
use std::ffi::{CStr, c_void}; use std::{
ffi::{CStr, c_void},
ptr::null_mut,
};
use idevice::{ use idevice::{
IdeviceError, IdeviceService, provider::IdeviceProvider, IdeviceError, IdeviceService, provider::IdeviceProvider,
springboardservices::SpringBoardServicesClient, springboardservices::SpringBoardServicesClient,
}; };
use crate::{IdeviceErrorCode, IdeviceHandle, RUNTIME, provider::IdeviceProviderHandle}; use crate::{IdeviceFfiError, IdeviceHandle, RUNTIME, ffi_err, provider::IdeviceProviderHandle};
pub struct SpringBoardServicesClientHandle(pub SpringBoardServicesClient); 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 /// * [`client`] - On success, will be set to point to a newly allocated SpringBoardServicesClient handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `provider` must be a valid pointer to a handle allocated by this library /// `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( pub unsafe extern "C" fn springboard_services_connect(
provider: *mut IdeviceProviderHandle, provider: *mut IdeviceProviderHandle,
client: *mut *mut SpringBoardServicesClientHandle, client: *mut *mut SpringBoardServicesClientHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if provider.is_null() || client.is_null() { if provider.is_null() || client.is_null() {
log::error!("Null pointer provided"); log::error!("Null pointer provided");
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let res: Result<SpringBoardServicesClient, IdeviceError> = RUNTIME.block_on(async move { let res: Result<SpringBoardServicesClient, IdeviceError> = RUNTIME.block_on(async move {
@@ -40,13 +43,13 @@ pub unsafe extern "C" fn springboard_services_connect(
Ok(r) => { Ok(r) => {
let boxed = Box::new(SpringBoardServicesClientHandle(r)); let boxed = Box::new(SpringBoardServicesClientHandle(r));
unsafe { *client = Box::into_raw(boxed) }; unsafe { *client = Box::into_raw(boxed) };
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
Err(e) => { Err(e) => {
// If connection failed, the provider_box was already forgotten, // If connection failed, the provider_box was already forgotten,
// so we need to reconstruct it to avoid leak // so we need to reconstruct it to avoid leak
let _ = unsafe { Box::from_raw(provider) }; 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 /// * [`client`] - On success, will be set to point to a newly allocated SpringBoardServicesClient handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `socket` must be a valid pointer to a handle allocated by this library. The socket is consumed, /// `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( pub unsafe extern "C" fn springboard_services_new(
socket: *mut IdeviceHandle, socket: *mut IdeviceHandle,
client: *mut *mut SpringBoardServicesClientHandle, client: *mut *mut SpringBoardServicesClientHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if socket.is_null() { if socket.is_null() {
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let socket = unsafe { Box::from_raw(socket) }.0; let socket = unsafe { Box::from_raw(socket) }.0;
let r = SpringBoardServicesClient::new(socket); let r = SpringBoardServicesClient::new(socket);
let boxed = Box::new(SpringBoardServicesClientHandle(r)); let boxed = Box::new(SpringBoardServicesClientHandle(r));
unsafe { *client = Box::into_raw(boxed) }; unsafe { *client = Box::into_raw(boxed) };
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
/// Gets the icon of the specified app by bundle identifier /// 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 /// * `out_result` - On success, will be set to point to a newly allocated png data
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `client` must be a valid pointer to a handle allocated by this library /// `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, bundle_identifier: *const libc::c_char,
out_result: *mut *mut c_void, out_result: *mut *mut c_void,
out_result_len: *mut libc::size_t, out_result_len: *mut libc::size_t,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if client.is_null() || out_result.is_null() || out_result_len.is_null() { if client.is_null() || out_result.is_null() || out_result_len.is_null() {
log::error!("Invalid arguments: {client:?}, {out_result:?}"); log::error!("Invalid arguments: {client:?}, {out_result:?}");
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let client = unsafe { &mut *client }; let client = unsafe { &mut *client };
let name_cstr = unsafe { CStr::from_ptr(bundle_identifier) }; let name_cstr = unsafe { CStr::from_ptr(bundle_identifier) };
let bundle_id = match name_cstr.to_str() { let bundle_id = match name_cstr.to_str() {
Ok(s) => s.to_string(), Ok(s) => s.to_string(),
Err(_) => return IdeviceErrorCode::InvalidArg, Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg),
}; };
let res: Result<Vec<u8>, IdeviceError> = let res: Result<Vec<u8>, IdeviceError> =
@@ -125,9 +128,9 @@ pub unsafe extern "C" fn springboard_services_get_icon(
*out_result = ptr as *mut c_void; *out_result = ptr as *mut c_void;
*out_result_len = len; *out_result_len = len;
} }
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
Err(e) => e.into(), Err(e) => ffi_err!(e),
} }
} }

View File

@@ -1,10 +1,10 @@
use std::os::raw::c_char; use std::{os::raw::c_char, ptr::null_mut};
use idevice::{ use idevice::{
IdeviceError, IdeviceService, provider::IdeviceProvider, syslog_relay::SyslogRelayClient, 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); pub struct SyslogRelayClientHandle(pub SyslogRelayClient);
@@ -21,10 +21,10 @@ pub struct SyslogRelayClientHandle(pub SyslogRelayClient);
pub unsafe extern "C" fn syslog_relay_connect_tcp( pub unsafe extern "C" fn syslog_relay_connect_tcp(
provider: *mut IdeviceProviderHandle, provider: *mut IdeviceProviderHandle,
client: *mut *mut SyslogRelayClientHandle, client: *mut *mut SyslogRelayClientHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if provider.is_null() { if provider.is_null() {
log::error!("Null pointer provided"); log::error!("Null pointer provided");
return IdeviceErrorCode::InvalidArg; return ffi_err!(IdeviceError::FfiInvalidArg);
} }
let res: Result<SyslogRelayClient, IdeviceError> = RUNTIME.block_on(async move { let res: Result<SyslogRelayClient, IdeviceError> = RUNTIME.block_on(async move {
@@ -38,11 +38,11 @@ pub unsafe extern "C" fn syslog_relay_connect_tcp(
unsafe { *client = Box::into_raw(boxed) }; unsafe { *client = Box::into_raw(boxed) };
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
Err(e) => { Err(e) => {
let _ = unsafe { Box::from_raw(provider) }; 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( pub unsafe extern "C" fn syslog_relay_next(
client: *mut SyslogRelayClientHandle, client: *mut SyslogRelayClientHandle,
log_message: *mut *mut c_char, log_message: *mut *mut c_char,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
if client.is_null() || log_message.is_null() { 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 }); 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) { match CString::new(safe_log) {
Ok(c_string) => { Ok(c_string) => {
unsafe { *log_message = c_string.into_raw() }; unsafe { *log_message = c_string.into_raw() };
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
Err(_) => { Err(_) => {
log::error!("Failed to convert log message to C string"); 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),
} }
} }

View File

@@ -1,8 +1,11 @@
// Jackson Coxson // 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::{ use idevice::{
IdeviceError, IdeviceError,
usbmuxd::{UsbmuxdAddr, UsbmuxdConnection}, 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 /// * [`usbmuxd_connection`] - On success, will be set to point to a newly allocated UsbmuxdConnection handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `addr` must be a valid sockaddr /// `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, addr_len: libc::socklen_t,
tag: u32, tag: u32,
usbmuxd_connection: *mut *mut UsbmuxdConnectionHandle, usbmuxd_connection: *mut *mut UsbmuxdConnectionHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
let addr = match c_socket_to_rust(addr, addr_len) { let addr = match c_socket_to_rust(addr, addr_len) {
Ok(a) => a, Ok(a) => a,
Err(e) => return e, Err(e) => return ffi_err!(e),
}; };
let res: Result<UsbmuxdConnection, IdeviceError> = RUNTIME.block_on(async move { let res: Result<UsbmuxdConnection, IdeviceError> = RUNTIME.block_on(async move {
@@ -46,9 +49,9 @@ pub unsafe extern "C" fn idevice_usbmuxd_new_tcp_connection(
Ok(r) => { Ok(r) => {
let boxed = Box::new(UsbmuxdConnectionHandle(r)); let boxed = Box::new(UsbmuxdConnectionHandle(r));
unsafe { *usbmuxd_connection = Box::into_raw(boxed) }; 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 /// * [`usbmuxd_connection`] - On success, will be set to point to a newly allocated UsbmuxdConnection handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `addr` must be a valid CStr /// `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, addr: *const c_char,
tag: u32, tag: u32,
usbmuxd_connection: *mut *mut UsbmuxdConnectionHandle, usbmuxd_connection: *mut *mut UsbmuxdConnectionHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
let addr = match unsafe { CStr::from_ptr(addr).to_str() } { let addr = match unsafe { CStr::from_ptr(addr).to_str() } {
Ok(s) => s, Ok(s) => s,
Err(_) => return IdeviceErrorCode::InvalidArg, Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg),
}; };
let res: Result<UsbmuxdConnection, IdeviceError> = RUNTIME.block_on(async move { let res: Result<UsbmuxdConnection, IdeviceError> = RUNTIME.block_on(async move {
@@ -86,9 +89,9 @@ pub unsafe extern "C" fn idevice_usbmuxd_new_unix_socket_connection(
Ok(r) => { Ok(r) => {
let boxed = Box::new(UsbmuxdConnectionHandle(r)); let boxed = Box::new(UsbmuxdConnectionHandle(r));
unsafe { *usbmuxd_connection = Box::into_raw(boxed) }; 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 /// * [`usbmuxd_connection`] - On success, will be set to point to a newly allocated UsbmuxdConnection handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `addr` must be a valid CStr /// `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( pub unsafe extern "C" fn idevice_usbmuxd_new_default_connection(
tag: u32, tag: u32,
usbmuxd_connection: *mut *mut UsbmuxdConnectionHandle, usbmuxd_connection: *mut *mut UsbmuxdConnectionHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
let addr = match UsbmuxdAddr::from_env_var() { let addr = match UsbmuxdAddr::from_env_var() {
Ok(a) => a, Ok(a) => a,
Err(e) => { Err(e) => {
log::error!("Invalid address set: {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) => { Ok(r) => {
let boxed = Box::new(UsbmuxdConnectionHandle(r)); let boxed = Box::new(UsbmuxdConnectionHandle(r));
unsafe { *usbmuxd_connection = Box::into_raw(boxed) }; 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 /// * [`usbmuxd_addr`] - On success, will be set to point to a newly allocated UsbmuxdAddr handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `addr` must be a valid sockaddr /// `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: *const libc::sockaddr,
addr_len: libc::socklen_t, addr_len: libc::socklen_t,
usbmuxd_addr: *mut *mut UsbmuxdAddrHandle, usbmuxd_addr: *mut *mut UsbmuxdAddrHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
let addr = match c_socket_to_rust(addr, addr_len) { let addr = match c_socket_to_rust(addr, addr_len) {
Ok(a) => a, Ok(a) => a,
Err(e) => return e, Err(e) => return ffi_err!(e),
}; };
let u = UsbmuxdAddr::TcpSocket(addr); let u = UsbmuxdAddr::TcpSocket(addr);
let boxed = Box::new(UsbmuxdAddrHandle(u)); let boxed = Box::new(UsbmuxdAddrHandle(u));
unsafe { *usbmuxd_addr = Box::into_raw(boxed) }; unsafe { *usbmuxd_addr = Box::into_raw(boxed) };
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
/// Creates a new UsbmuxdAddr struct with a unix socket /// 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 /// * [`usbmuxd_addr`] - On success, will be set to point to a newly allocated UsbmuxdAddr handle
/// ///
/// # Returns /// # Returns
/// An error code indicating success or failure /// An IdeviceFfiError on error, null on success
/// ///
/// # Safety /// # Safety
/// `addr` must be a valid CStr /// `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( pub unsafe extern "C" fn idevice_usbmuxd_unix_addr_new(
addr: *const c_char, addr: *const c_char,
usbmuxd_addr: *mut *mut UsbmuxdAddrHandle, usbmuxd_addr: *mut *mut UsbmuxdAddrHandle,
) -> IdeviceErrorCode { ) -> *mut IdeviceFfiError {
let addr = match unsafe { CStr::from_ptr(addr).to_str() } { let addr = match unsafe { CStr::from_ptr(addr).to_str() } {
Ok(s) => s, Ok(s) => s,
Err(_) => return IdeviceErrorCode::InvalidArg, Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg),
}; };
let u = UsbmuxdAddr::UnixSocket(addr.to_string()); let u = UsbmuxdAddr::UnixSocket(addr.to_string());
let boxed = Box::new(UsbmuxdAddrHandle(u)); let boxed = Box::new(UsbmuxdAddrHandle(u));
unsafe { *usbmuxd_addr = Box::into_raw(boxed) }; unsafe { *usbmuxd_addr = Box::into_raw(boxed) };
IdeviceErrorCode::IdeviceSuccess null_mut()
} }
/// Frees a UsbmuxdAddr handle /// Frees a UsbmuxdAddr handle

View File

@@ -6,21 +6,20 @@ use std::{
os::raw::c_void, os::raw::c_void,
}; };
use idevice::IdeviceError;
use libc::{sockaddr_in, sockaddr_in6}; use libc::{sockaddr_in, sockaddr_in6};
use plist::Value; use plist::Value;
use crate::IdeviceErrorCode;
pub(crate) fn c_socket_to_rust( pub(crate) fn c_socket_to_rust(
addr: *const libc::sockaddr, addr: *const libc::sockaddr,
addr_len: libc::socklen_t, addr_len: libc::socklen_t,
) -> Result<SocketAddr, IdeviceErrorCode> { ) -> Result<SocketAddr, IdeviceError> {
Ok(unsafe { Ok(unsafe {
match (*addr).sa_family as c_int { match (*addr).sa_family as c_int {
libc::AF_INET => { libc::AF_INET => {
if (addr_len as usize) < std::mem::size_of::<sockaddr_in>() { if (addr_len as usize) < std::mem::size_of::<sockaddr_in>() {
log::error!("Invalid sockaddr_in size"); log::error!("Invalid sockaddr_in size");
return Err(IdeviceErrorCode::InvalidArg); return Err(IdeviceError::FfiInvalidArg);
} }
let addr_in = *(addr as *const sockaddr_in); let addr_in = *(addr as *const sockaddr_in);
let ip = std::net::Ipv4Addr::from(u32::from_be(addr_in.sin_addr.s_addr)); 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 { } else {
log::error!("Invalid sockaddr_in6 size"); log::error!("Invalid sockaddr_in6 size");
return Err(IdeviceErrorCode::InvalidArg); return Err(IdeviceError::FfiInvalidArg);
} }
} }
_ => { _ => {
log::error!("Unsupported socket address family: {}", (*addr).sa_family); 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<IpAddr, IdeviceErrorCode> { pub(crate) fn c_addr_to_rust(addr: *const libc::sockaddr) -> Result<IpAddr, IdeviceError> {
unsafe { unsafe {
// Check the address family // Check the address family
match (*addr).sa_family as c_int { match (*addr).sa_family as c_int {
@@ -72,7 +71,7 @@ pub(crate) fn c_addr_to_rust(addr: *const libc::sockaddr) -> Result<IpAddr, Idev
} }
_ => { _ => {
log::error!("Unsupported socket address family: {}", (*addr).sa_family); log::error!("Unsupported socket address family: {}", (*addr).sa_family);
Err(IdeviceErrorCode::InvalidArg) Err(IdeviceError::FfiInvalidArg)
} }
} }
} }

View File

@@ -413,187 +413,195 @@ impl Idevice {
/// Comprehensive error type for all device communication failures /// Comprehensive error type for all device communication failures
#[derive(Error, Debug)] #[derive(Error, Debug)]
#[repr(i32)]
#[non_exhaustive] #[non_exhaustive]
pub enum IdeviceError { pub enum IdeviceError {
#[error("device socket io failed")] #[error("device socket io failed")]
Socket(#[from] io::Error), Socket(#[from] io::Error) = -1,
#[error("PEM parse failed")] #[error("PEM parse failed")]
PemParseFailed(#[from] rustls::pki_types::pem::Error), PemParseFailed(#[from] rustls::pki_types::pem::Error) = -2,
#[error("TLS error")] #[error("TLS error")]
Rustls(#[from] rustls::Error), Rustls(#[from] rustls::Error) = -3,
#[error("TLS verifiction build failed")] #[error("TLS verifiction build failed")]
TlsBuilderFailed(#[from] rustls::server::VerifierBuilderError), TlsBuilderFailed(#[from] rustls::server::VerifierBuilderError) = -4,
#[error("io on plist")] #[error("io on plist")]
Plist(#[from] plist::Error), Plist(#[from] plist::Error) = -5,
#[error("can't convert bytes to utf8")] #[error("can't convert bytes to utf8")]
Utf8(#[from] std::string::FromUtf8Error), Utf8(#[from] std::string::FromUtf8Error) = -6,
#[error("unexpected response from device")] #[error("unexpected response from device")]
UnexpectedResponse, UnexpectedResponse = -7,
#[error("this request was prohibited")] #[error("this request was prohibited")]
GetProhibited, GetProhibited = -8,
#[error("no SSL session is active")] #[error("no SSL session is active")]
SessionInactive, SessionInactive = -9,
#[error("device does not have pairing file")] #[error("device does not have pairing file")]
InvalidHostID, InvalidHostID = -10,
#[error("no established connection")] #[error("no established connection")]
NoEstablishedConnection, NoEstablishedConnection = -11,
#[error("device went to sleep")] #[error("device went to sleep")]
HeartbeatSleepyTime, HeartbeatSleepyTime = -12,
#[error("heartbeat timeout")] #[error("heartbeat timeout")]
HeartbeatTimeout, HeartbeatTimeout = -13,
#[error("not found")] #[error("not found")]
NotFound, NotFound = -14,
#[error("service not found")] #[error("service not found")]
ServiceNotFound, ServiceNotFound = -15,
#[error("CDTunnel packet too short")] #[error("CDTunnel packet too short")]
CdtunnelPacketTooShort, CdtunnelPacketTooShort = -16,
#[error("CDTunnel packet invalid magic")] #[error("CDTunnel packet invalid magic")]
CdtunnelPacketInvalidMagic, CdtunnelPacketInvalidMagic = -17,
#[error("Proclaimed packet size does not match actual size")] #[error("Proclaimed packet size does not match actual size")]
PacketSizeMismatch, PacketSizeMismatch = -18,
#[cfg(feature = "core_device_proxy")] #[cfg(feature = "core_device_proxy")]
#[error("JSON serialization failed")] #[error("JSON serialization failed")]
Json(#[from] serde_json::Error), Json(#[from] serde_json::Error) = -19,
#[error("device not found")] #[error("device not found")]
DeviceNotFound, DeviceNotFound = -20,
#[error("device lockded")] #[error("device lockded")]
DeviceLocked, DeviceLocked = -21,
#[error("device refused connection")] #[error("device refused connection")]
UsbConnectionRefused, UsbConnectionRefused = -22,
#[error("bad command")] #[error("bad command")]
UsbBadCommand, UsbBadCommand = -23,
#[error("bad device")] #[error("bad device")]
UsbBadDevice, UsbBadDevice = -24,
#[error("usb bad version")] #[error("usb bad version")]
UsbBadVersion, UsbBadVersion = -25,
#[error("bad build manifest")] #[error("bad build manifest")]
BadBuildManifest, BadBuildManifest = -26,
#[error("image not mounted")] #[error("image not mounted")]
ImageNotMounted, ImageNotMounted = -27,
#[cfg(feature = "pair")] #[cfg(feature = "pair")]
#[error("pairing trust dialog pending")] #[error("pairing trust dialog pending")]
PairingDialogResponsePending, PairingDialogResponsePending = -28,
#[cfg(feature = "pair")] #[cfg(feature = "pair")]
#[error("user denied pairing trust")] #[error("user denied pairing trust")]
UserDeniedPairing, UserDeniedPairing = -29,
#[cfg(feature = "pair")] #[cfg(feature = "pair")]
#[error("device is locked")] #[error("device is locked")]
PasswordProtected, PasswordProtected = -30,
#[cfg(feature = "misagent")] #[cfg(feature = "misagent")]
#[error("misagent operation failed")] #[error("misagent operation failed")]
MisagentFailure, MisagentFailure = -31,
#[cfg(feature = "installation_proxy")] #[cfg(feature = "installation_proxy")]
#[error("installation proxy operation failed")] #[error("installation proxy operation failed")]
InstallationProxyOperationFailed(String), InstallationProxyOperationFailed(String) = -32,
#[cfg(feature = "afc")] #[cfg(feature = "afc")]
#[error("afc error")] #[error("afc error: {0}")]
Afc(#[from] afc::errors::AfcError), Afc(#[from] afc::errors::AfcError) = -33,
#[cfg(feature = "afc")] #[cfg(feature = "afc")]
#[error("unknown afc opcode")] #[error("unknown afc opcode")]
UnknownAfcOpcode, UnknownAfcOpcode = -34,
#[cfg(feature = "afc")] #[cfg(feature = "afc")]
#[error("invalid afc magic")] #[error("invalid afc magic")]
InvalidAfcMagic, InvalidAfcMagic = -35,
#[cfg(feature = "afc")] #[cfg(feature = "afc")]
#[error("missing file attribute")] #[error("missing file attribute")]
AfcMissingAttribute, AfcMissingAttribute = -36,
#[cfg(feature = "crashreportcopymobile")] #[cfg(feature = "crashreportcopymobile")]
#[error("crash report mover sent the wrong response")] #[error("crash report mover sent the wrong response")]
CrashReportMoverBadResponse(Vec<u8>), CrashReportMoverBadResponse(Vec<u8>) = -37,
#[cfg(any(feature = "tss", feature = "tunneld"))] #[cfg(any(feature = "tss", feature = "tunneld"))]
#[error("http reqwest error")] #[error("http reqwest error")]
Reqwest(#[from] reqwest::Error), Reqwest(#[from] reqwest::Error) = -38,
#[error("internal error")] #[error("internal error")]
InternalError(String), InternalError(String) = -39,
#[cfg(feature = "xpc")] #[cfg(feature = "xpc")]
#[error("unknown http frame type")] #[error("unknown http frame type")]
UnknownFrame(u8), UnknownFrame(u8) = -40,
#[cfg(feature = "xpc")] #[cfg(feature = "xpc")]
#[error("unknown http setting type")] #[error("unknown http setting type")]
UnknownHttpSetting(u16), UnknownHttpSetting(u16) = -41,
#[cfg(feature = "xpc")] #[cfg(feature = "xpc")]
#[error("Unintialized stream ID")] #[error("Unintialized stream ID")]
UninitializedStreamId, UninitializedStreamId = -42,
#[cfg(feature = "xpc")] #[cfg(feature = "xpc")]
#[error("unknown XPC type")] #[error("unknown XPC type")]
UnknownXpcType(u32), UnknownXpcType(u32) = -43,
#[cfg(feature = "xpc")] #[cfg(feature = "xpc")]
#[error("malformed XPC message")] #[error("malformed XPC message")]
MalformedXpc, MalformedXpc = -44,
#[cfg(feature = "xpc")] #[cfg(feature = "xpc")]
#[error("invalid XPC magic")] #[error("invalid XPC magic")]
InvalidXpcMagic, InvalidXpcMagic = -45,
#[cfg(feature = "xpc")] #[cfg(feature = "xpc")]
#[error("unexpected XPC version")] #[error("unexpected XPC version")]
UnexpectedXpcVersion, UnexpectedXpcVersion = -46,
#[cfg(feature = "xpc")] #[cfg(feature = "xpc")]
#[error("invalid C string")] #[error("invalid C string")]
InvalidCString, InvalidCString = -47,
#[cfg(feature = "xpc")] #[cfg(feature = "xpc")]
#[error("stream reset")] #[error("stream reset")]
HttpStreamReset, HttpStreamReset = -48,
#[cfg(feature = "xpc")] #[cfg(feature = "xpc")]
#[error("go away packet received")] #[error("go away packet received")]
HttpGoAway(String), HttpGoAway(String) = -49,
#[cfg(feature = "dvt")] #[cfg(feature = "dvt")]
#[error("NSKeyedArchive error")] #[error("NSKeyedArchive error")]
NsKeyedArchiveError(#[from] ns_keyed_archive::ConverterError), NsKeyedArchiveError(#[from] ns_keyed_archive::ConverterError) = -50,
#[cfg(feature = "dvt")] #[cfg(feature = "dvt")]
#[error("Unknown aux value type")] #[error("Unknown aux value type")]
UnknownAuxValueType(u32), UnknownAuxValueType(u32) = -51,
#[cfg(feature = "dvt")] #[cfg(feature = "dvt")]
#[error("unknown channel")] #[error("unknown channel")]
UnknownChannel(u32), UnknownChannel(u32) = -52,
#[error("cannot parse string as IpAddr")] #[error("cannot parse string as IpAddr")]
AddrParseError(#[from] std::net::AddrParseError), AddrParseError(#[from] std::net::AddrParseError) = -53,
#[cfg(feature = "dvt")] #[cfg(feature = "dvt")]
#[error("disable memory limit failed")] #[error("disable memory limit failed")]
DisableMemoryLimitFailed, DisableMemoryLimitFailed = -54,
#[error("not enough bytes, expected {1}, got {0}")] #[error("not enough bytes, expected {1}, got {0}")]
NotEnoughBytes(usize, usize), NotEnoughBytes(usize, usize) = -55,
#[error("failed to parse bytes as valid utf8")] #[error("failed to parse bytes as valid utf8")]
Utf8Error, Utf8Error = -56,
#[cfg(feature = "debug_proxy")] #[cfg(feature = "debug_proxy")]
#[error("invalid argument passed")] #[error("invalid argument passed")]
InvalidArgument, InvalidArgument = -57,
#[error("unknown error `{0}` returned from device")] #[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 { impl IdeviceError {
@@ -633,4 +641,113 @@ impl IdeviceError {
_ => None, _ => 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,
}
}
} }