diff --git a/StikJIT/StikJIT-Bridging-Header.h b/StikJIT/StikJIT-Bridging-Header.h index dfaf4557..9e96e7f8 100644 --- a/StikJIT/StikJIT-Bridging-Header.h +++ b/StikJIT/StikJIT-Bridging-Header.h @@ -5,7 +5,6 @@ #include "idevice/JITEnableContext.h" #import "Utilities/ProcessInspectorBridge.h" #include "idevice/idevice.h" -#include "idevice/heartbeat.h" #include "JSSupport/JSSupport.h" #include "idevice/ideviceinfo.h" #include "idevice/location_simulation.h" diff --git a/StikJIT/StikJITApp.swift b/StikJIT/StikJITApp.swift index a4709b08..61465ec5 100644 --- a/StikJIT/StikJITApp.swift +++ b/StikJIT/StikJITApp.swift @@ -117,17 +117,17 @@ class DNSChecker: ObservableObject { // MARK: - Main App -// Global state variable for the heartbeat response. -var pubHeartBeat = false -private var heartbeatStartPending = false -private var heartbeatStartInProgress = false -private var heartbeatPendingShowUI = true +// Global state variable for the tunnel connection. +var pubTunnelConnected = false +private var tunnelStartPending = false +private var tunnelStartInProgress = false +private var tunnelPendingShowUI = true @main struct HeartbeatApp: App { @StateObject private var mount = MountingProgress.shared @Environment(\.scenePhase) private var scenePhase // Observe scene lifecycle - @State private var shouldAttemptHeartbeatRestart = false + @State private var shouldAttemptTunnelReconnect = false init() { registerAdvancedOptionsDefault() @@ -144,11 +144,11 @@ struct HeartbeatApp: App { private func handleScenePhaseChange(_ newPhase: ScenePhase) { switch newPhase { case .background: - shouldAttemptHeartbeatRestart = true + shouldAttemptTunnelReconnect = true case .active: - if shouldAttemptHeartbeatRestart { - shouldAttemptHeartbeatRestart = false - startHeartbeatInBackground(showErrorUI: false) + if shouldAttemptTunnelReconnect { + shouldAttemptTunnelReconnect = false + startTunnelInBackground(showErrorUI: false) } default: break @@ -270,42 +270,42 @@ class MountingProgress: ObservableObject { func isPairing() -> Bool { let pairingpath = URL.documentsDirectory.appendingPathComponent("pairingFile.plist").path - var pairingFile: IdevicePairingFile? - let err = idevice_pairing_file_read(pairingpath, &pairingFile) + var pairingFile: RpPairingFileHandle? + let err = rp_pairing_file_read(pairingpath, &pairingFile) if err != nil { return false } - idevice_pairing_file_free(pairingFile) + rp_pairing_file_free(pairingFile) return true } -func startHeartbeatInBackground(showErrorUI: Bool = true) { - assert(Thread.isMainThread, "startHeartbeatInBackground must be called on the main thread") +func startTunnelInBackground(showErrorUI: Bool = true) { + assert(Thread.isMainThread, "startTunnelInBackground must be called on the main thread") let pairingFileURL = URL.documentsDirectory.appendingPathComponent("pairingFile.plist") - + guard FileManager.default.fileExists(atPath: pairingFileURL.path) else { - heartbeatStartPending = false - heartbeatPendingShowUI = true + tunnelStartPending = false + tunnelPendingShowUI = true return } - - guard !heartbeatStartInProgress else { + + guard !tunnelStartInProgress else { return } - - heartbeatStartPending = false - heartbeatPendingShowUI = true - heartbeatStartInProgress = true - + + tunnelStartPending = false + tunnelPendingShowUI = true + tunnelStartInProgress = true + DispatchQueue.global(qos: .userInteractive).async { defer { DispatchQueue.main.async { - heartbeatStartInProgress = false + tunnelStartInProgress = false } } do { - try JITEnableContext.shared.startHeartbeat() - LogManager.shared.addInfoLog("Heartbeat started successfully") - pubHeartBeat = true - + try JITEnableContext.shared.startTunnel() + LogManager.shared.addInfoLog("Tunnel connected successfully") + pubTunnelConnected = true + DispatchQueue.main.async { let trustcachePath = URL.documentsDirectory.appendingPathComponent("DDI/Image.dmg.trustcache").path guard FileManager.default.fileExists(atPath: trustcachePath), @@ -326,7 +326,7 @@ func startHeartbeatInBackground(showErrorUI: Bool = true) { } catch { LogManager.shared.addErrorLog("Failed to remove invalid pairing file: \(error.localizedDescription)") } - + showAlert( title: "Invalid Pairing File", message: "The pairing file is invalid or expired. Please select a new pairing file.", @@ -338,14 +338,14 @@ func startHeartbeatInBackground(showErrorUI: Bool = true) { } } else { showAlert( - title: "Heartbeat Error", + title: "Connection Error", message: "\(error.localizedDescription)\n\nMake sure Wi‑Fi and LocalDevVPN are connected and that the device is reachable.", showOk: false, showTryAgain: true ) { shouldTryAgain in if shouldTryAgain { DispatchQueue.main.async { - startHeartbeatInBackground() + startTunnelInBackground() } } } diff --git a/StikJIT/Utilities/DeviceInfoManager.swift b/StikJIT/Utilities/DeviceInfoManager.swift index f402607f..b0db7f68 100644 --- a/StikJIT/Utilities/DeviceInfoManager.swift +++ b/StikJIT/Utilities/DeviceInfoManager.swift @@ -30,7 +30,7 @@ final class DeviceInfoManager: ObservableObject { busy = true Task.detached { do { - try JITEnableContext.shared.ensureHeartbeat() + try JITEnableContext.shared.ensureTunnel() } catch { await MainActor.run { self.error = ("Initialization Failed", error.localizedDescription) diff --git a/StikJIT/Utilities/Intents.swift b/StikJIT/Utilities/Intents.swift index a37044df..40a0af13 100644 --- a/StikJIT/Utilities/Intents.swift +++ b/StikJIT/Utilities/Intents.swift @@ -38,7 +38,7 @@ struct InstalledAppQuery: EntityStringQuery { } func suggestedEntities() async throws -> [InstalledAppEntity] { - await ensureHeartbeat() + await ensureTunnel() let allApps = (try? JITEnableContext.shared.getAppList()) ?? [:] return allApps.map { InstalledAppEntity(id: $0.key, displayName: $0.value) } .sorted { $0.displayName.localizedCaseInsensitiveCompare($1.displayName) == .orderedAscending } @@ -94,7 +94,7 @@ struct RunningProcessEntity: AppEntity { struct RunningProcessQuery: EntityStringQuery { func entities(for identifiers: [String]) async throws -> [RunningProcessEntity] { // Always fetch fresh so PIDs are current - await ensureHeartbeat() + await ensureTunnel() let all = try fetchProcessEntities() let idSet = Set(identifiers) return all.filter { idSet.contains($0.id) } @@ -112,7 +112,7 @@ struct RunningProcessQuery: EntityStringQuery { } func suggestedEntities() async throws -> [RunningProcessEntity] { - await ensureHeartbeat() + await ensureTunnel() return try fetchProcessEntities() } @@ -172,7 +172,7 @@ struct EnableJITIntent: AppIntent, ForegroundContinuableIntent { return .result(value: "Select an app to enable JIT for.") } - await ensureHeartbeat() + await ensureTunnel() var scriptData: Data? = nil var scriptName: String? = nil @@ -250,9 +250,9 @@ struct KillProcessIntent: AppIntent { if let pid { targetPID = pid targetName = "PID \(pid)" - await ensureHeartbeat() + await ensureTunnel() } else if let process { - await ensureHeartbeat() + await ensureTunnel() // Always re-resolve to get the current PID — the stored one may be stale guard let resolved = process.resolveCurrentPID() else { @@ -313,12 +313,12 @@ struct StikDebugShortcuts: AppShortcutsProvider { } } -// MARK: - Shared Heartbeat Helper +// MARK: - Shared Tunnel Helper -func ensureHeartbeat() async { +func ensureTunnel() async { await MainActor.run { - pubHeartBeat = false - startHeartbeatInBackground(showErrorUI: false) + pubTunnelConnected = false + startTunnelInBackground(showErrorUI: false) } try? await Task.sleep(nanoseconds: 1_000_000_000) } diff --git a/StikJIT/Utilities/mountDDI.swift b/StikJIT/Utilities/mountDDI.swift index db922ca8..75176e11 100644 --- a/StikJIT/Utilities/mountDDI.swift +++ b/StikJIT/Utilities/mountDDI.swift @@ -7,10 +7,9 @@ import Foundation -typealias IdevicePairingFile = OpaquePointer -typealias TcpProviderHandle = OpaquePointer -typealias CoreDeviceProxyHandle = OpaquePointer +typealias RpPairingFileHandle = OpaquePointer typealias AdapterHandle = OpaquePointer +typealias RsdHandshakeHandle = OpaquePointer typealias ImageMounterHandle = OpaquePointer typealias LockdowndClientHandle = OpaquePointer diff --git a/StikJIT/Views/HomeView.swift b/StikJIT/Views/HomeView.swift index 92056640..f05b1d61 100644 --- a/StikJIT/Views/HomeView.swift +++ b/StikJIT/Views/HomeView.swift @@ -40,7 +40,7 @@ struct HomeView: View { startJITInBackground(bundleID: selectedBundle) }, showDoneButton: false, onImportPairingFile: { isShowingPairingFilePicker = true }) .onAppear { - startHeartbeatInBackground() + startTunnelInBackground() MountingProgress.shared.checkforMounted() viewDidAppeared = true if let config = pendingJITEnableConfiguration { @@ -94,8 +94,8 @@ struct HomeView: View { } case "kill-process": if let pidStr = components?.queryItems?.first(where: { $0.name == "pid" })?.value, let pid = Int(pidStr) { - pubHeartBeat = false - startHeartbeatInBackground(showErrorUI: false) + pubTunnelConnected = false + startTunnelInBackground(showErrorUI: false) DispatchQueue.global(qos: .userInitiated).async { sleep(1) do { @@ -133,10 +133,10 @@ struct HomeView: View { try fileManager.removeItem(at: dest) } try fileManager.copyItem(at: url, to: dest) - pubHeartBeat = false - startHeartbeatInBackground() + pubTunnelConnected = false + startTunnelInBackground() NotificationCenter.default.post(name: .pairingFileImported, object: nil) - // Dismiss any existing heartbeat error alert + // Dismiss any existing connection error alert if let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene, let root = scene.windows.first?.rootViewController { var top = root @@ -268,8 +268,8 @@ struct HomeView: View { BackgroundLocationManager.shared.requestStart() if triggeredByURLScheme { - pubHeartBeat = false - startHeartbeatInBackground(showErrorUI: false) + pubTunnelConnected = false + startTunnelInBackground(showErrorUI: false) } DispatchQueue.global(qos: .background).async { diff --git a/StikJIT/Views/SettingsView.swift b/StikJIT/Views/SettingsView.swift index a17b94b6..de8c443b 100644 --- a/StikJIT/Views/SettingsView.swift +++ b/StikJIT/Views/SettingsView.swift @@ -224,7 +224,7 @@ struct SettingsView: View { RunLoop.current.add(progressTimer, forMode: .common) DispatchQueue.main.async { - startHeartbeatInBackground() + startTunnelInBackground() } } catch { } diff --git a/StikJIT/idevice/JITEnableContext.h b/StikJIT/idevice/JITEnableContext.h index 68a3175e..7d71dd1c 100644 --- a/StikJIT/idevice/JITEnableContext.h +++ b/StikJIT/idevice/JITEnableContext.h @@ -8,35 +8,35 @@ @import UIKit; #include "idevice.h" #include "jit.h" -#include "heartbeat.h" #include "mount.h" -typedef void (^HeartbeatCompletionHandler)(int result, NSString *message); typedef void (^LogFuncC)(const char* message, ...); typedef void (^LogFunc)(NSString *message); typedef void (^SyslogLineHandler)(NSString *line); typedef void (^SyslogErrorHandler)(NSError *error); @interface JITEnableContext : NSObject { + // tunnel + @protected AdapterHandle *adapter; + @protected RsdHandshakeHandle *handshake; + // process @protected dispatch_queue_t processInspectorQueue; - @protected IdeviceProviderHandle* provider; - + // syslog @protected dispatch_queue_t syslogQueue; @protected BOOL syslogStreaming; @protected SyslogRelayClientHandle *syslogClient; @protected SyslogLineHandler syslogLineHandler; @protected SyslogErrorHandler syslogErrorHandler; - + // ideviceInfo @protected LockdowndClientHandle * g_client; } @property (class, readonly)JITEnableContext* shared; -- (IdevicePairingFile*)getPairingFileWithError:(NSError**)error; -- (IdeviceProviderHandle*)getTcpProviderHandle; -- (BOOL)ensureHeartbeatWithError:(NSError**)err; -- (BOOL)startHeartbeat:(NSError**)err; +- (RpPairingFileHandle*)getPairingFileWithError:(NSError**)error; +- (BOOL)ensureTunnelWithError:(NSError**)err; +- (BOOL)startTunnel:(NSError**)err; @end diff --git a/StikJIT/idevice/JITEnableContext.m b/StikJIT/idevice/JITEnableContext.m index 06bc3905..4b3af85e 100644 --- a/StikJIT/idevice/JITEnableContext.m +++ b/StikJIT/idevice/JITEnableContext.m @@ -9,7 +9,6 @@ #include #include -#include "heartbeat.h" #include "jit.h" #include "applist.h" #include "profiles.h" @@ -21,13 +20,11 @@ static JITEnableContext* sharedJITContext = nil; -@implementation JITEnableContext { - int heartbeatToken; - NSError* lastHeartbeatError; - os_unfair_lock heartbeatLock; - BOOL heartbeatRunning; - dispatch_semaphore_t heartbeatSemaphore; - +@implementation JITEnableContext { + NSError* lastTunnelError; + os_unfair_lock tunnelLock; + BOOL tunnelConnecting; + dispatch_semaphore_t tunnelSemaphore; } + (instancetype)shared { @@ -48,12 +45,11 @@ - (instancetype)init { syslogClient = NULL; dispatch_queue_attr_t qosAttr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_USER_INITIATED, 0); processInspectorQueue = dispatch_queue_create("com.stikdebug.processInspector", qosAttr); - - heartbeatToken = 0; - heartbeatLock = OS_UNFAIR_LOCK_INIT; - heartbeatRunning = NO; - heartbeatSemaphore = NULL; - lastHeartbeatError = nil; + + tunnelLock = OS_UNFAIR_LOCK_INIT; + tunnelConnecting = NO; + tunnelSemaphore = NULL; + lastTunnelError = nil; return self; } @@ -88,7 +84,7 @@ - (LogFuncC)createCLogger:(LogFunc)logger { }; } -- (IdevicePairingFile*)getPairingFileWithError:(NSError**)error { +- (RpPairingFileHandle*)getPairingFileWithError:(NSError**)error { NSFileManager* fm = [NSFileManager defaultManager]; NSURL* docPathUrl = [fm URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask].firstObject; NSURL* pairingFileURL = [docPathUrl URLByAppendingPathComponent:@"pairingFile.plist"]; @@ -98,112 +94,108 @@ - (IdevicePairingFile*)getPairingFileWithError:(NSError**)error { return nil; } - IdevicePairingFile* pairingFile = NULL; - IdeviceFfiError* err = idevice_pairing_file_read(pairingFileURL.fileSystemRepresentation, &pairingFile); + RpPairingFileHandle* pairingFile = NULL; + IdeviceFfiError* err = rp_pairing_file_read(pairingFileURL.fileSystemRepresentation, &pairingFile); if (err) { *error = [self errorWithStr:@"Failed to read pairing file!" code:err->code]; + idevice_error_free(err); return nil; } return pairingFile; } -- (IdeviceProviderHandle*)getTcpProviderHandle { - return provider; -} +- (BOOL)startTunnel:(NSError**)err { + os_unfair_lock_lock(&tunnelLock); + + // If tunnel is already being created, wait for it to complete + if (tunnelConnecting) { + dispatch_semaphore_t waitSemaphore = tunnelSemaphore; + os_unfair_lock_unlock(&tunnelLock); -// only block until first heartbeat is completed or failed. -- (BOOL)startHeartbeat:(NSError**)err { - os_unfair_lock_lock(&heartbeatLock); - - // If heartbeat is already running, wait for it to complete - if (heartbeatRunning) { - dispatch_semaphore_t waitSemaphore = heartbeatSemaphore; - os_unfair_lock_unlock(&heartbeatLock); - if (waitSemaphore) { dispatch_semaphore_wait(waitSemaphore, DISPATCH_TIME_FOREVER); dispatch_semaphore_signal(waitSemaphore); } - *err = lastHeartbeatError; + *err = lastTunnelError; return *err == nil; } - - // Mark heartbeat as running - heartbeatRunning = YES; - heartbeatSemaphore = dispatch_semaphore_create(0); - dispatch_semaphore_t completionSemaphore = heartbeatSemaphore; - os_unfair_lock_unlock(&heartbeatLock); - - IdevicePairingFile* pairingFile = [self getPairingFileWithError:err]; + + // Mark tunnel as connecting + tunnelConnecting = YES; + tunnelSemaphore = dispatch_semaphore_create(0); + dispatch_semaphore_t completionSemaphore = tunnelSemaphore; + os_unfair_lock_unlock(&tunnelLock); + + RpPairingFileHandle* pairingFile = [self getPairingFileWithError:err]; if (*err) { - os_unfair_lock_lock(&heartbeatLock); - heartbeatRunning = NO; - heartbeatSemaphore = NULL; - os_unfair_lock_unlock(&heartbeatLock); + os_unfair_lock_lock(&tunnelLock); + tunnelConnecting = NO; + tunnelSemaphore = NULL; + os_unfair_lock_unlock(&tunnelLock); dispatch_semaphore_signal(completionSemaphore); return NO; } - globalHeartbeatToken++; - dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); - __block bool completionCalled = false; - HeartbeatCompletionHandlerC Ccompletion = ^(int result, const char *message) { - if(completionCalled) { - return; - } - if (result != 0) { - *err = [self errorWithStr:[NSString stringWithCString:message - encoding:NSASCIIStringEncoding] code:result]; - self->lastHeartbeatError = *err; - } else { - self->lastHeartbeatError = nil; - } - completionCalled = true; - - dispatch_semaphore_signal(semaphore); - }; - - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ - startHeartbeat( - pairingFile, - &self->provider, - globalHeartbeatToken,Ccompletion - ); - }); - // allow 5 seconds for heartbeat, otherwise we declare timeout - intptr_t isTimeout = dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, (uint64_t)(5 * NSEC_PER_SEC))); - if(isTimeout) { - Ccompletion(-1, "Heartbeat failed to complete in reasonable time."); + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(49152); + + NSString* deviceIP = [[NSUserDefaults standardUserDefaults] stringForKey:@"customTargetIP"]; + inet_pton(AF_INET, (deviceIP && deviceIP.length > 0) ? [deviceIP UTF8String] : "10.7.0.1", &addr.sin_addr); + + AdapterHandle *newAdapter = NULL; + RsdHandshakeHandle *newHandshake = NULL; + IdeviceFfiError *ffiErr = tunnel_create_rppairing( + (const idevice_sockaddr *)&addr, + sizeof(addr), + "StikDebug", + pairingFile, + NULL, + NULL, + &newAdapter, + &newHandshake + ); + rp_pairing_file_free(pairingFile); + + if (ffiErr) { + *err = [self errorWithStr:[NSString stringWithUTF8String:ffiErr->message ?: "Failed to create tunnel"] + code:ffiErr->code]; + lastTunnelError = *err; + idevice_error_free(ffiErr); + } else { + // Clean up old tunnel if any + if (handshake) { rsd_handshake_free(handshake); } + if (adapter) { adapter_free(adapter); } + adapter = newAdapter; + handshake = newHandshake; + lastTunnelError = nil; } - os_unfair_lock_lock(&heartbeatLock); - heartbeatRunning = NO; - heartbeatSemaphore = NULL; - os_unfair_lock_unlock(&heartbeatLock); + os_unfair_lock_lock(&tunnelLock); + tunnelConnecting = NO; + tunnelSemaphore = NULL; + os_unfair_lock_unlock(&tunnelLock); dispatch_semaphore_signal(completionSemaphore); - + return *err == nil; } -- (BOOL)ensureHeartbeatWithError:(NSError**)err { - // if it's 15s after last heartbeat, we restart heartbeat. - if((!lastHeartbeatDate || [[NSDate now] timeIntervalSinceDate:lastHeartbeatDate] > 15)) { - return [self startHeartbeat:err]; +- (BOOL)ensureTunnelWithError:(NSError**)err { + if (!adapter || !handshake) { + return [self startTunnel:err]; } return YES; } - - - (void)dealloc { [self stopSyslogRelay]; - if (provider) { - idevice_provider_free(provider); + if (handshake) { + rsd_handshake_free(handshake); + } + if (adapter) { + adapter_free(adapter); } } - - - - @end diff --git a/StikJIT/idevice/applist.h b/StikJIT/idevice/applist.h index a6907b83..1731cd8d 100644 --- a/StikJIT/idevice/applist.h +++ b/StikJIT/idevice/applist.h @@ -10,9 +10,9 @@ @import Foundation; @import UIKit; -NSDictionary* list_installed_apps(IdeviceProviderHandle* provider, NSString** error); -NSDictionary* list_all_apps(IdeviceProviderHandle* provider, NSString** error); -NSDictionary* list_hidden_system_apps(IdeviceProviderHandle* provider, NSString** error); -UIImage* getAppIcon(IdeviceProviderHandle* provider, NSString* bundleID, NSString** error); +NSDictionary* list_installed_apps(AdapterHandle* adapter, RsdHandshakeHandle* handshake, NSString** error); +NSDictionary* list_all_apps(AdapterHandle* adapter, RsdHandshakeHandle* handshake, NSString** error); +NSDictionary* list_hidden_system_apps(AdapterHandle* adapter, RsdHandshakeHandle* handshake, NSString** error); +UIImage* getAppIcon(AdapterHandle* adapter, RsdHandshakeHandle* handshake, NSString* bundleID, NSString** error); #endif /* APPLIST_H */ diff --git a/StikJIT/idevice/applist.m b/StikJIT/idevice/applist.m index 002d4eb4..f39d17f0 100644 --- a/StikJIT/idevice/applist.m +++ b/StikJIT/idevice/applist.m @@ -149,10 +149,11 @@ static BOOL isHiddenSystemApp(plist_t app) return result; } -static NSArray* getSideloadedApps(IdeviceProviderHandle *provider, +static NSArray* getSideloadedApps(AdapterHandle *adapter, + RsdHandshakeHandle *handshake, NSString **error) { InstallationProxyClientHandle *client = NULL; - IdeviceFfiError* err = installation_proxy_connect(provider, &client); + IdeviceFfiError* err = installation_proxy_connect_rsd(adapter, handshake, &client); if (err) { *error = [NSString stringWithFormat:@"Failed to connect to installation proxy: %s", err->message]; idevice_error_free(err); @@ -208,13 +209,14 @@ static BOOL isHiddenSystemApp(plist_t app) return result; } -static NSDictionary *performAppQuery(IdeviceProviderHandle *provider, +static NSDictionary *performAppQuery(AdapterHandle *adapter, + RsdHandshakeHandle *handshake, BOOL requireGetTaskAllow, NSString **error, BOOL (^filter)(plist_t app)) { InstallationProxyClientHandle *client = NULL; - IdeviceFfiError* err = installation_proxy_connect(provider, &client); + IdeviceFfiError* err = installation_proxy_connect_rsd(adapter, handshake, &client); if (err) { *error = [NSString stringWithFormat:@"Failed to connect to installation proxy: %s", err->message]; idevice_error_free(err); @@ -240,23 +242,23 @@ static BOOL isHiddenSystemApp(plist_t app) return result; } -NSDictionary* list_installed_apps(IdeviceProviderHandle* provider, NSString** error) { - return performAppQuery(provider, YES, error, nil); +NSDictionary* list_installed_apps(AdapterHandle* adapter, RsdHandshakeHandle* handshake, NSString** error) { + return performAppQuery(adapter, handshake, YES, error, nil); } -NSDictionary* list_all_apps(IdeviceProviderHandle* provider, NSString** error) { - return performAppQuery(provider, NO, error, nil); +NSDictionary* list_all_apps(AdapterHandle* adapter, RsdHandshakeHandle* handshake, NSString** error) { + return performAppQuery(adapter, handshake, NO, error, nil); } -NSDictionary* list_hidden_system_apps(IdeviceProviderHandle* provider, NSString** error) { - return performAppQuery(provider, NO, error, ^BOOL(plist_t app) { +NSDictionary* list_hidden_system_apps(AdapterHandle* adapter, RsdHandshakeHandle* handshake, NSString** error) { + return performAppQuery(adapter, handshake, NO, error, ^BOOL(plist_t app) { return isHiddenSystemApp(app); }); } -UIImage* getAppIcon(IdeviceProviderHandle* provider, NSString* bundleID, NSString** error) { +UIImage* getAppIcon(AdapterHandle* adapter, RsdHandshakeHandle* handshake, NSString* bundleID, NSString** error) { SpringBoardServicesClientHandle *client = NULL; - IdeviceFfiError *err = springboard_services_connect(provider, &client); + IdeviceFfiError *err = springboard_services_connect_rsd(adapter, handshake, &client); if (err) { *error = [NSString stringWithUTF8String:err->message ?: "Failed to connect to SpringBoard Services"]; idevice_error_free(err); @@ -284,13 +286,13 @@ static BOOL isHiddenSystemApp(plist_t app) @implementation JITEnableContext(App) - (NSDictionary*)getAppListWithError:(NSError**)error { - [self ensureHeartbeatWithError:error]; + [self ensureTunnelWithError:error]; if(*error) { return nil; } NSString* errorStr = nil; - NSDictionary* apps = list_installed_apps(provider, &errorStr); + NSDictionary* apps = list_installed_apps(adapter, handshake, &errorStr); if (errorStr) { *error = [self errorWithStr:errorStr code:-17]; return nil; @@ -299,13 +301,13 @@ @implementation JITEnableContext(App) } - (NSDictionary*)getAllAppsWithError:(NSError**)error { - [self ensureHeartbeatWithError:error]; + [self ensureTunnelWithError:error]; if(*error) { return nil; } NSString* errorStr = nil; - NSDictionary* apps = list_all_apps(provider, &errorStr); + NSDictionary* apps = list_all_apps(adapter, handshake, &errorStr); if (errorStr) { *error = [self errorWithStr:errorStr code:-17]; return nil; @@ -314,13 +316,13 @@ @implementation JITEnableContext(App) } - (NSDictionary*)getHiddenSystemAppsWithError:(NSError**)error { - [self ensureHeartbeatWithError:error]; + [self ensureTunnelWithError:error]; if(*error) { return nil; } NSString* errorStr = nil; - NSDictionary* apps = list_hidden_system_apps(provider, &errorStr); + NSDictionary* apps = list_hidden_system_apps(adapter, handshake, &errorStr); if (errorStr) { *error = [self errorWithStr:errorStr code:-17]; return nil; @@ -329,13 +331,13 @@ @implementation JITEnableContext(App) } - (NSArray*)getSideloadedAppsWithError:(NSError**)error { - [self ensureHeartbeatWithError:error]; + [self ensureTunnelWithError:error]; if(*error) { return nil; } NSString* errorStr = nil; - NSArray* apps = getSideloadedApps(provider, &errorStr); + NSArray* apps = getSideloadedApps(adapter, handshake, &errorStr); if (errorStr) { *error = [self errorWithStr:errorStr code:-17]; return nil; @@ -344,13 +346,13 @@ @implementation JITEnableContext(App) } - (UIImage*)getAppIconWithBundleId:(NSString*)bundleId error:(NSError**)error { - [self ensureHeartbeatWithError:error]; + [self ensureTunnelWithError:error]; if(*error) { return nil; } NSString* errorStr = nil; - UIImage* icon = getAppIcon(provider, bundleId, &errorStr); + UIImage* icon = getAppIcon(adapter, handshake, bundleId, &errorStr); if (errorStr) { *error = [self errorWithStr:errorStr code:-17]; return nil; diff --git a/StikJIT/idevice/heartbeat.h b/StikJIT/idevice/heartbeat.h deleted file mode 100644 index f39d37ea..00000000 --- a/StikJIT/idevice/heartbeat.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// heartbeat.h -// StikJIT -// -// Created by Stephen on 3/27/25. -// - -// heartbeat.h -#ifndef HEARTBEAT_H -#define HEARTBEAT_H -#include "idevice.h" -@import Foundation; - -typedef void (^HeartbeatCompletionHandlerC)(int result, const char *message); -typedef void (^LogFuncC)(const char* message, ...); - -extern int globalHeartbeatToken; -extern NSDate* lastHeartbeatDate; - -void startHeartbeat(IdevicePairingFile* pairing_file, IdeviceProviderHandle** provider, int heartbeatToken, HeartbeatCompletionHandlerC completion); -#endif /* HEARTBEAT_H */ diff --git a/StikJIT/idevice/heartbeat.m b/StikJIT/idevice/heartbeat.m deleted file mode 100644 index 63953876..00000000 --- a/StikJIT/idevice/heartbeat.m +++ /dev/null @@ -1,95 +0,0 @@ -// Jackson Coxson -// heartbeat.c - -#include "idevice.h" -#include -#include -#include -#include -#include -#include -#include -#include "heartbeat.h" -#include -@import Foundation; - -int globalHeartbeatToken = 0; -NSDate* lastHeartbeatDate = nil; - -void startHeartbeat(IdevicePairingFile* pairing_file, IdeviceProviderHandle** provider, int heartbeatToken, HeartbeatCompletionHandlerC completion) { - IdeviceProviderHandle* newProvider = *provider; - IdeviceFfiError* err = nil; - - struct sockaddr_in addr; - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(LOCKDOWN_PORT); - - NSString* deviceIP = [[NSUserDefaults standardUserDefaults] stringForKey:@"customTargetIP"]; - inet_pton(AF_INET, (deviceIP && deviceIP.length > 0) ? [deviceIP UTF8String] : "10.7.0.1", &addr.sin_addr); - - err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing_file, - "ExampleProvider", &newProvider); - if (err != NULL) { - completion(err->code, err->message); - idevice_pairing_file_free(pairing_file); - idevice_error_free(err); - return; - } - - HeartbeatClientHandle *client = NULL; - err = heartbeat_connect(newProvider, &client); - if (err != NULL) { - completion(err->code, err->message); - idevice_provider_free(newProvider); - idevice_error_free(err); - return; - } - - *provider = newProvider; - - bool completionCalled = false; - u_int64_t current_interval = 15; - - while (1) { - u_int64_t new_interval = 0; - err = heartbeat_get_marco(client, current_interval, &new_interval); - if (err != NULL) { - if (!completionCalled) { - completion(err->code, err->message); - } - heartbeat_client_free(client); - idevice_error_free(err); - return; - } - - // If a newer heartbeat thread has started, yield to it - if (heartbeatToken != globalHeartbeatToken) { - heartbeat_client_free(client); - return; - } - - current_interval = new_interval + 5; - - err = heartbeat_send_polo(client); - if (err != NULL) { - if (!completionCalled) { - completion(err->code, err->message); - } - heartbeat_client_free(client); - idevice_error_free(err); - return; - } - - if (lastHeartbeatDate && [[NSDate now] timeIntervalSinceDate:lastHeartbeatDate] > current_interval) { - lastHeartbeatDate = nil; - return; - } - lastHeartbeatDate = [NSDate now]; - - if (!completionCalled) { - completion(0, "Heartbeat succeeded"); - completionCalled = true; - } - } -} diff --git a/StikJIT/idevice/idevice.h b/StikJIT/idevice/idevice.h index 7524bb23..4d51cc6e 100644 --- a/StikJIT/idevice/idevice.h +++ b/StikJIT/idevice/idevice.h @@ -78,6 +78,10 @@ typedef struct AmfiClientHandle AmfiClientHandle; */ typedef struct AppServiceHandle AppServiceHandle; +typedef struct BtPacketLoggerClientHandle BtPacketLoggerClientHandle; + +typedef struct CompanionProxyClientHandle CompanionProxyClientHandle; + typedef struct CoreDeviceProxyHandle CoreDeviceProxyHandle; typedef struct CrashReportCopyMobileHandle CrashReportCopyMobileHandle; @@ -116,21 +120,37 @@ typedef struct ImageMounterHandle ImageMounterHandle; typedef struct InstallationProxyClientHandle InstallationProxyClientHandle; +typedef struct InstallcoordinationProxyHandle InstallcoordinationProxyHandle; + /** * Opaque handle to a ProcessControlClient */ typedef struct LocationSimulationHandle LocationSimulationHandle; +typedef struct LocationSimulationServiceHandle LocationSimulationServiceHandle; + typedef struct LockdowndClientHandle LockdowndClientHandle; typedef struct MisagentClientHandle MisagentClientHandle; +/** + * Opaque handle wrapping a provider pointer for MobileActivationd. + * The client is recreated per call since each request requires a new connection. + */ +typedef struct MobileActivationdClientHandle MobileActivationdClientHandle; + +typedef struct MobileBackup2ClientHandle MobileBackup2ClientHandle; + typedef struct NotificationProxyClientHandle NotificationProxyClientHandle; typedef struct OsTraceRelayClientHandle OsTraceRelayClientHandle; typedef struct OsTraceRelayReceiverHandle OsTraceRelayReceiverHandle; +typedef struct PcapdClientHandle PcapdClientHandle; + +typedef struct PreboardServiceClientHandle PreboardServiceClientHandle; + /** * Opaque handle to a ProcessControlClient */ @@ -143,6 +163,13 @@ typedef struct ReadWriteOpaque ReadWriteOpaque; */ typedef struct RemoteServerHandle RemoteServerHandle; +typedef struct RestoreServiceClientHandle RestoreServiceClientHandle; + +/** + * Opaque handle to an RPPairing file + */ +typedef struct RpPairingFileHandle RpPairingFileHandle; + /** * Opaque handle to an RsdHandshake */ @@ -211,6 +238,36 @@ typedef struct AfcDeviceInfo { size_t block_size; } AfcDeviceInfo; +/** + * Represents a parsed BT packet from the logger + */ +typedef struct BtPacketHandle { + /** + * Header: advisory length + */ + uint32_t length; + /** + * Header: timestamp seconds + */ + uint32_t ts_secs; + /** + * Header: timestamp microseconds + */ + uint32_t ts_usecs; + /** + * Packet kind byte (0x00=HciCmd, 0x01=HciEvt, 0x02=AclSent, 0x03=AclRecv, etc.) + */ + uint8_t kind; + /** + * H4-ready payload data + */ + uint8_t *h4_data; + /** + * Length of h4_data + */ + uintptr_t h4_data_len; +} BtPacketHandle; + /** * C-compatible app list entry */ @@ -278,6 +335,43 @@ typedef struct DebugserverCommandHandle { uintptr_t argv_count; } DebugserverCommandHandle; +/** + * C-compatible delegate for mobilebackup2 operations. + * + * All function pointers are required except `on_file_received` and + * `on_progress` which may be NULL. + * + * Every path argument is a null-terminated UTF-8 string. + * `context` is forwarded unchanged from the struct field. + */ +typedef struct Mobilebackup2BackupDelegateFFI { + void *context; + uint64_t (*get_free_disk_space)(const char *path, void *context); + struct IdeviceFfiError *(*open_file_read)(const char *path, + uint8_t **out_data, + uintptr_t *out_len, + void *context); + struct IdeviceFfiError *(*create_file_write)(const char *path, void *context); + struct IdeviceFfiError *(*write_chunk)(const char *path, + const uint8_t *data, + uintptr_t len, + void *context); + struct IdeviceFfiError *(*close_file)(const char *path, void *context); + struct IdeviceFfiError *(*create_dir_all)(const char *path, void *context); + struct IdeviceFfiError *(*remove)(const char *path, void *context); + struct IdeviceFfiError *(*rename)(const char *from, const char *to, void *context); + struct IdeviceFfiError *(*copy)(const char *src, const char *dst, void *context); + bool (*exists)(const char *path, void *context); + bool (*is_dir)(const char *path, void *context); + /** + * Optional progress callback. May be NULL. + */ + void (*on_progress)(uint64_t bytes_done, + uint64_t bytes_total, + double overall_progress, + void *context); +} Mobilebackup2BackupDelegateFFI; + typedef struct SyslogLabel { const char *subsystem; const char *category; @@ -293,6 +387,31 @@ typedef struct OsTraceLog { const struct SyslogLabel *label; } OsTraceLog; +/** + * Represents a captured device packet from pcapd + */ +typedef struct DevicePacketHandle { + uint32_t header_length; + uint8_t header_version; + uint32_t packet_length; + uint8_t interface_type; + uint16_t unit; + uint8_t io; + uint32_t protocol_family; + uint32_t frame_pre_length; + uint32_t frame_post_length; + char *interface_name; + uint32_t pid; + char *comm; + uint32_t svc; + uint32_t epid; + char *ecomm; + uint32_t seconds; + uint32_t microseconds; + uint8_t *data; + uintptr_t data_len; +} DevicePacketHandle; + /** * C-compatible representation of an RSD service */ @@ -637,6 +756,26 @@ struct IdeviceFfiError *adapter_recv(struct AdapterStreamHandle *handle, struct IdeviceFfiError *afc_client_connect(struct IdeviceProviderHandle *provider, struct AfcClientHandle **client); +/** + * Creates a new AfcClient via RSD + * + * # Arguments + * * [`provider`] - An adapter created by this library + * * [`handshake`] - An RSD handshake from the same provider + * * [`client`] - On success, will be set to point to a newly allocated AfcClient handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `handshake` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *afc_client_connect_rsd(struct AdapterHandle *provider, + struct RsdHandshakeHandle *handshake, + struct AfcClientHandle **client); + /** * Connects to the AFC2 service using a TCP provider * @@ -1020,6 +1159,26 @@ void afc_file_read_data_free(uint8_t *data, struct IdeviceFfiError *amfi_connect(struct IdeviceProviderHandle *provider, struct AmfiClientHandle **client); +/** + * Creates a new AmfiClient via RSD + * + * # Arguments + * * [`provider`] - An adapter created by this library + * * [`handshake`] - An RSD handshake from the same provider + * * [`client`] - On success, will be set to point to a newly allocated AmfiClient handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `handshake` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *amfi_connect_rsd(struct AdapterHandle *provider, + struct RsdHandshakeHandle *handshake, + struct AmfiClientHandle **client); + /** * Automatically creates and connects to AMFI service, returning a client handle * @@ -1091,6 +1250,224 @@ struct IdeviceFfiError *amfi_accept_developer_mode(struct AmfiClientHandle *clie */ void amfi_client_free(struct AmfiClientHandle *handle); +/** + * Automatically creates and connects to BTPacketLogger, returning a client handle + * + * # Arguments + * * [`provider`] - An IdeviceProvider + * * [`client`] - On success, will be set to point to a newly allocated BtPacketLoggerClient handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *bt_packet_logger_connect(struct IdeviceProviderHandle *provider, + struct BtPacketLoggerClientHandle **client); + +/** + * Creates a new BtPacketLoggerClient via RSD + * + * # Arguments + * * [`provider`] - An adapter created by this library + * * [`handshake`] - An RSD handshake from the same provider + * * [`client`] - On success, will be set to point to a newly allocated BtPacketLoggerClient handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `handshake` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *bt_packet_logger_connect_rsd(struct AdapterHandle *provider, + struct RsdHandshakeHandle *handshake, + struct BtPacketLoggerClientHandle **client); + +/** + * Creates a new BtPacketLoggerClient from an existing socket + * + * # Arguments + * * [`socket`] - An IdeviceSocket handle + * * [`client`] - On success, will be set to point to a newly allocated BtPacketLoggerClient handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `socket` must be a valid pointer to a handle allocated by this library. The socket is consumed, + * and may not be used again. + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *bt_packet_logger_new(struct IdeviceHandle *socket, + struct BtPacketLoggerClientHandle **client); + +/** + * Reads the next BT packet from the logger + * + * # Arguments + * * `client` - A valid BtPacketLoggerClient handle + * * `packet` - On success, will be set to point to a newly allocated BtPacketHandle. + * May be set to NULL if EOF was reached. + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `client` must be a valid pointer to a handle allocated by this library + * The returned packet must be freed with `bt_packet_free` + */ +struct IdeviceFfiError *bt_packet_logger_next_packet(struct BtPacketLoggerClientHandle *client, + struct BtPacketHandle **packet); + +/** + * Frees a BtPacketHandle + * + * # Arguments + * * [`handle`] - The handle to free + * + * # Safety + * `handle` must be a valid pointer to the handle that was allocated by this library, + * or NULL (in which case this function does nothing) + */ +void bt_packet_free(struct BtPacketHandle *handle); + +/** + * Frees a BtPacketLoggerClient handle + * + * # Arguments + * * [`handle`] - The handle to free + * + * # Safety + * `handle` must be a valid pointer to the handle that was allocated by this library, + * or NULL (in which case this function does nothing) + */ +void bt_packet_logger_client_free(struct BtPacketLoggerClientHandle *handle); + +/** + * Automatically creates and connects to Companion Proxy, returning a client handle + * + * # Arguments + * * [`provider`] - An IdeviceProvider + * * [`client`] - On success, will be set to point to a newly allocated CompanionProxy handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *companion_proxy_connect(struct IdeviceProviderHandle *provider, + struct CompanionProxyClientHandle **client); + +/** + * Creates a new CompanionProxy client via RSD + * + * # Arguments + * * [`provider`] - An adapter created by this library + * * [`handshake`] - An RSD handshake from the same provider + * * [`client`] - On success, will be set to point to a newly allocated CompanionProxy handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `handshake` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *companion_proxy_connect_rsd(struct AdapterHandle *provider, + struct RsdHandshakeHandle *handshake, + struct CompanionProxyClientHandle **client); + +/** + * Creates a new CompanionProxy client from an existing socket + * + * # Arguments + * * [`socket`] - An IdeviceSocket handle + * * [`client`] - On success, will be set to point to a newly allocated CompanionProxy handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `socket` must be a valid pointer to a handle allocated by this library. The socket is consumed, + * and may not be used again. + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *companion_proxy_new(struct IdeviceHandle *socket, + struct CompanionProxyClientHandle **client); + +/** + * Gets the device registry from Companion Proxy, returning paired watch UDIDs + * + * # Arguments + * * `client` - A valid CompanionProxy handle + * * `udids` - On success, will be set to point to a newly allocated array of C strings + * * `udids_len` - On success, will be set to the length of the array + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `client` must be a valid pointer to a handle allocated by this library + * The returned strings must be freed with `idevice_string_free` and the outer array + * with `idevice_outer_slice_free` + */ +struct IdeviceFfiError *companion_proxy_get_device_registry(struct CompanionProxyClientHandle *client, + char ***udids, + uintptr_t *udids_len); + +/** + * Starts forwarding a service port through the companion proxy + * + * # Arguments + * * `client` - A valid CompanionProxy handle + * * `port` - The remote port number on the watch + * * `local_port` - On success, will be set to the local forwarded port number + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `client` must be a valid pointer to a handle allocated by this library + */ +struct IdeviceFfiError *companion_proxy_start_forwarding_service_port(struct CompanionProxyClientHandle *client, + uint16_t port, + uint16_t *local_port); + +/** + * Stops forwarding a service port through the companion proxy + * + * # Arguments + * * `client` - A valid CompanionProxy handle + * * `port` - The remote port number to stop forwarding + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `client` must be a valid pointer to a handle allocated by this library + */ +struct IdeviceFfiError *companion_proxy_stop_forwarding_service_port(struct CompanionProxyClientHandle *client, + uint16_t port); + +/** + * Frees a CompanionProxy client handle + * + * # Arguments + * * [`handle`] - The handle to free + * + * # Safety + * `handle` must be a valid pointer to the handle that was allocated by this library, + * or NULL (in which case this function does nothing) + */ +void companion_proxy_client_free(struct CompanionProxyClientHandle *handle); + /** * Creates a new AppServiceClient using RSD connection * @@ -1601,6 +1978,26 @@ void adapter_free(struct AdapterHandle *handle); struct IdeviceFfiError *crash_report_client_connect(struct IdeviceProviderHandle *provider, struct CrashReportCopyMobileHandle **client); +/** + * Creates a new CrashReportCopyMobileClient via RSD + * + * # Arguments + * * [`provider`] - An adapter created by this library + * * [`handshake`] - An RSD handshake from the same provider + * * [`client`] - On success, will be set to point to a newly allocated handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `handshake` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *crash_report_client_connect_rsd(struct AdapterHandle *provider, + struct RsdHandshakeHandle *handshake, + struct CrashReportCopyMobileHandle **client); + /** * Creates a new CrashReportCopyMobile client from an existing Idevice connection * @@ -1942,25 +2339,45 @@ struct IdeviceFfiError *diagnostics_relay_client_connect(struct IdeviceProviderH struct DiagnosticsRelayClientHandle **client); /** - * Automatically creates and connects to Diagnostics Relay, returning a client handle + * Creates a new DiagnosticsRelayClient via RSD * * # Arguments - * * [`socket`] - An IdeviceSocket handle + * * [`provider`] - An adapter created by this library + * * [`handshake`] - An RSD handshake from the same provider * * [`client`] - On success, will be set to point to a newly allocated DiagnosticsRelayClient handle * * # Returns * An IdeviceFfiError on error, null on success * * # Safety - * `socket` must be a valid pointer to a handle allocated by this library. The socket is consumed, - * and may not be used again. + * `provider` must be a valid pointer to a handle allocated by this library + * `handshake` must be a valid pointer to a handle allocated by this library * `client` must be a valid, non-null pointer to a location where the handle will be stored */ -struct IdeviceFfiError *diagnostics_relay_client_new(struct IdeviceHandle *socket, - struct DiagnosticsRelayClientHandle **client); +struct IdeviceFfiError *diagnostics_relay_client_connect_rsd(struct AdapterHandle *provider, + struct RsdHandshakeHandle *handshake, + struct DiagnosticsRelayClientHandle **client); /** - * Queries the device IO registry + * Automatically creates and connects to Diagnostics Relay, returning a client handle + * + * # Arguments + * * [`socket`] - An IdeviceSocket handle + * * [`client`] - On success, will be set to point to a newly allocated DiagnosticsRelayClient handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `socket` must be a valid pointer to a handle allocated by this library. The socket is consumed, + * and may not be used again. + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *diagnostics_relay_client_new(struct IdeviceHandle *socket, + struct DiagnosticsRelayClientHandle **client); + +/** + * Queries the device IO registry * * # Arguments * * `client` - A valid DiagnosticsRelayClient handle @@ -2416,6 +2833,26 @@ void idevice_error_free(struct IdeviceFfiError *err); struct IdeviceFfiError *heartbeat_connect(struct IdeviceProviderHandle *provider, struct HeartbeatClientHandle **client); +/** + * Creates a new HeartbeatClient via RSD + * + * # Arguments + * * [`provider`] - An adapter created by this library + * * [`handshake`] - An RSD handshake from the same provider + * * [`client`] - On success, will be set to point to a newly allocated HeartbeatClient handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `handshake` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *heartbeat_connect_rsd(struct AdapterHandle *provider, + struct RsdHandshakeHandle *handshake, + struct HeartbeatClientHandle **client); + /** * Automatically creates and connects to Installation Proxy, returning a client handle * @@ -2495,6 +2932,26 @@ void heartbeat_client_free(struct HeartbeatClientHandle *handle); struct IdeviceFfiError *house_arrest_client_connect(struct IdeviceProviderHandle *provider, struct HouseArrestClientHandle **client); +/** + * Creates a new HouseArrestClient via RSD + * + * # Arguments + * * [`provider`] - An adapter created by this library + * * [`handshake`] - An RSD handshake from the same provider + * * [`client`] - On success, will be set to point to a newly allocated HouseArrestClient handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `handshake` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *house_arrest_client_connect_rsd(struct AdapterHandle *provider, + struct RsdHandshakeHandle *handshake, + struct HouseArrestClientHandle **client); + /** * Creates a new HouseArrestClient from an existing Idevice connection * @@ -2581,6 +3038,26 @@ void house_arrest_client_free(struct HouseArrestClientHandle *handle); struct IdeviceFfiError *installation_proxy_connect(struct IdeviceProviderHandle *provider, struct InstallationProxyClientHandle **client); +/** + * Creates a new InstallationProxyClient via RSD + * + * # Arguments + * * [`provider`] - An adapter created by this library + * * [`handshake`] - An RSD handshake from the same provider + * * [`client`] - On success, will be set to point to a newly allocated InstallationProxyClient handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `handshake` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *installation_proxy_connect_rsd(struct AdapterHandle *provider, + struct RsdHandshakeHandle *handshake, + struct InstallationProxyClientHandle **client); + /** * Automatically creates and connects to Installation Proxy, returning a client handle * @@ -2817,6 +3294,147 @@ struct IdeviceFfiError *installation_proxy_browse(struct InstallationProxyClient plist_t **out_result, size_t *out_result_len); +/** + * Creates a new InstallcoordinationProxy client from a ReadWrite stream + * + * # Arguments + * * [`socket`] - A ReadWriteOpaque handle (consumed) + * * [`client`] - On success, will be set to point to a newly allocated handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `socket` must be a valid pointer to a handle allocated by this library. The socket is consumed, + * and may not be used again. + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *installcoordination_proxy_new(struct ReadWriteOpaque *socket, + struct InstallcoordinationProxyHandle **client); + +/** + * Creates a new InstallcoordinationProxy client via RSD + * + * # Arguments + * * [`provider`] - An adapter created by this library + * * [`handshake`] - An RSD handshake from the same provider + * * [`client`] - On success, will be set to point to a newly allocated InstallcoordinationProxy handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `handshake` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *installcoordination_proxy_connect_rsd(struct AdapterHandle *provider, + struct RsdHandshakeHandle *handshake, + struct InstallcoordinationProxyHandle **client); + +/** + * Uninstalls an app by bundle ID + * + * # Arguments + * * `client` - A valid InstallcoordinationProxy handle + * * `bundle_id` - The bundle identifier of the app to uninstall + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `client` must be a valid pointer to a handle allocated by this library + * `bundle_id` must be a valid null-terminated C string + */ +struct IdeviceFfiError *installcoordination_proxy_uninstall_app(struct InstallcoordinationProxyHandle *client, + const char *bundle_id); + +/** + * Queries the install path of an app by bundle ID + * + * # Arguments + * * `client` - A valid InstallcoordinationProxy handle + * * `bundle_id` - The bundle identifier of the app to query + * * `path` - On success, will be set to a newly allocated C string with the install path + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `client` must be a valid pointer to a handle allocated by this library + * `bundle_id` must be a valid null-terminated C string + * The returned string must be freed with `idevice_string_free` + */ +struct IdeviceFfiError *installcoordination_proxy_query_app_path(struct InstallcoordinationProxyHandle *client, + const char *bundle_id, + char **path); + +/** + * Frees an InstallcoordinationProxy client handle + * + * # Arguments + * * [`handle`] - The handle to free + * + * # Safety + * `handle` must be a valid pointer to the handle that was allocated by this library, + * or NULL (in which case this function does nothing) + */ +void installcoordination_proxy_client_free(struct InstallcoordinationProxyHandle *handle); + +/** + * Connects to the Location Simulation service using a provider + * This is the location_simulation api for iOS 16 and below + * You must have a developer disk image mounted to use this API + * + * # Safety + * `provider` must be valid; `client` must be a non-null pointer to store the handle. + */ +struct IdeviceFfiError *lockdown_location_simulation_connect(struct IdeviceProviderHandle *provider, + struct LocationSimulationServiceHandle **handle); + +/** + * Creates a new Location Simulation service client directly from an existing `IdeviceHandle` (socket). + * + * # Safety + * - `socket` must be a valid, unowned pointer to an `IdeviceHandle` that has been properly + * initialized and represents an open connection to the Location Simulation service. + * Ownership of the `IdeviceHandle` is transferred to this function. + * - `client` must be a non-null pointer to a location where the newly created + * `*mut LocationSimulationServiceHandle` will be stored. + * + */ +struct IdeviceFfiError *lockdown_location_simulation_new(struct IdeviceHandle *socket, + struct LocationSimulationServiceHandle **client); + +/** + * Sets the device's simulated location. + * This is the location_simulation api for iOS 16 and below. + * + * # Safety + * `handle` must be a valid pointer to a `LocationSimulationServiceHandle` returned by `lockdown_location_simulation_connect`. + * `latitude` and `longitude` must be valid, null-terminated C strings. + */ +struct IdeviceFfiError *lockdown_location_simulation_set(struct LocationSimulationServiceHandle *handle, + const char *latitude, + const char *longitude); + +/** + * Clears the device's simulated location, returning it to the actual location. + * This is the location_simulation api for iOS 16 and below. + * + * # Safety + * `handle` must be a valid pointer to a `LocationSimulationServiceHandle` returned by `lockdown_location_simulation_connect`. + */ +struct IdeviceFfiError *lockdown_location_simulation_clear(struct LocationSimulationServiceHandle *handle); + +/** + * Frees a LocationSimulationService handle + * + * # Safety + * `handle` must be a pointer returned by `lockdown_location_simulation_connect`. + */ +void lockdown_location_simulation_free(struct LocationSimulationServiceHandle *handle); + /** * Connects to lockdownd service using provider * @@ -2834,6 +3452,26 @@ struct IdeviceFfiError *installation_proxy_browse(struct InstallationProxyClient struct IdeviceFfiError *lockdownd_connect(struct IdeviceProviderHandle *provider, struct LockdowndClientHandle **client); +/** + * Creates a new LockdownClient via RSD + * + * # Arguments + * * [`provider`] - An adapter created by this library + * * [`handshake`] - An RSD handshake from the same provider + * * [`client`] - On success, will be set to point to a newly allocated LockdownClient handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `handshake` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *lockdownd_connect_rsd(struct AdapterHandle *provider, + struct RsdHandshakeHandle *handshake, + struct LockdowndClientHandle **client); + /** * Creates a new LockdowndClient from an existing Idevice connection * @@ -2891,6 +3529,30 @@ struct IdeviceFfiError *lockdownd_start_service(struct LockdowndClientHandle *cl uint16_t *port, bool *ssl); +/** + * Pairs with the device using lockdownd + * + * # Arguments + * * `client` - A valid LockdowndClient handle + * * `host_id` - The host ID (null-terminated string) + * * `system_buid` - The system BUID (null-terminated string) + * * `pairing_file` - On success, will be set to point to a newly allocated IdevicePairingFile handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `client` must be a valid pointer to a handle allocated by this library + * `host_id` must be a valid null-terminated string + * `system_buid` must be a valid null-terminated string + * `pairing_file` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *lockdownd_pair(struct LockdowndClientHandle *client, + const char *host_id, + const char *system_buid, + const char *host_name, + struct IdevicePairingFile **pairing_file); + /** * Gets a value from lockdownd * @@ -2989,6 +3651,26 @@ enum IdeviceLoggerError idevice_init_logger(enum IdeviceLogLevel console_level, struct IdeviceFfiError *misagent_connect(struct IdeviceProviderHandle *provider, struct MisagentClientHandle **client); +/** + * Creates a new MisagentClient via RSD + * + * # Arguments + * * [`provider`] - An adapter created by this library + * * [`handshake`] - An RSD handshake from the same provider + * * [`client`] - On success, will be set to point to a newly allocated MisagentClient handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `handshake` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *misagent_connect_rsd(struct AdapterHandle *provider, + struct RsdHandshakeHandle *handshake, + struct MisagentClientHandle **client); + /** * Installs a provisioning profile on the device * @@ -3088,6 +3770,26 @@ void misagent_client_free(struct MisagentClientHandle *handle); struct IdeviceFfiError *image_mounter_connect(struct IdeviceProviderHandle *provider, struct ImageMounterHandle **client); +/** + * Creates a new ImageMounter via RSD + * + * # Arguments + * * [`provider`] - An adapter created by this library + * * [`handshake`] - An RSD handshake from the same provider + * * [`client`] - On success, will be set to point to a newly allocated ImageMounter handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `handshake` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *image_mounter_connect_rsd(struct AdapterHandle *provider, + struct RsdHandshakeHandle *handshake, + struct ImageMounterHandle **client); + /** * Creates a new ImageMounter client from an existing Idevice connection * @@ -3430,97 +4132,294 @@ struct IdeviceFfiError *image_mounter_mount_personalized_with_callback(struct Im void *context); /** - * Automatically creates and connects to Notification Proxy, returning a client handle + * Creates a new MobileActivationd client handle from a provider * * # Arguments - * * [`provider`] - An IdeviceProvider - * * [`client`] - On success, will be set to point to a newly allocated NotificationProxyClient handle + * * [`provider`] - An IdeviceProvider (not consumed, must remain valid for the lifetime of the handle) + * * [`client`] - On success, will be set to point to a newly allocated handle * * # Returns * An IdeviceFfiError on error, null on success * * # 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. + * The provider must remain valid for the lifetime of the returned handle. * `client` must be a valid, non-null pointer to a location where the handle will be stored */ -struct IdeviceFfiError *notification_proxy_connect(struct IdeviceProviderHandle *provider, - struct NotificationProxyClientHandle **client); +struct IdeviceFfiError *mobileactivationd_connect(struct IdeviceProviderHandle *provider, + struct MobileActivationdClientHandle **client); /** - * Creates a new NotificationProxyClient from an existing Idevice connection + * Gets the activation state of the device * * # Arguments - * * [`socket`] - An IdeviceSocket handle - * * [`client`] - On success, will be set to point to a newly allocated NotificationProxyClient handle + * * `client` - A valid MobileActivationd handle + * * `state` - On success, will be set to a newly allocated C string with the activation state * * # Returns * An IdeviceFfiError on error, null on success * * # Safety - * `socket` must be a valid pointer to a handle allocated by this library. The socket is consumed, - * and may not be used again. - * `client` must be a valid, non-null pointer to a location where the handle will be stored + * `client` must be a valid pointer to a handle allocated by this library + * The returned string must be freed with `idevice_string_free` */ -struct IdeviceFfiError *notification_proxy_new(struct IdeviceHandle *socket, - struct NotificationProxyClientHandle **client); +struct IdeviceFfiError *mobileactivationd_get_state(struct MobileActivationdClientHandle *client, + char **state); /** - * Posts a notification to the device + * Checks if the device is activated * * # Arguments - * * `client` - A valid NotificationProxyClient handle - * * `name` - C string containing the notification name + * * `client` - A valid MobileActivationd handle + * * `activated` - On success, will be set to true if the device is activated * * # Returns * An IdeviceFfiError on error, null on success * * # Safety * `client` must be a valid pointer to a handle allocated by this library - * `name` must be a valid null-terminated C string */ -struct IdeviceFfiError *notification_proxy_post(struct NotificationProxyClientHandle *client, - const char *name); +struct IdeviceFfiError *mobileactivationd_is_activated(struct MobileActivationdClientHandle *client, + bool *activated); /** - * Observes a specific notification + * Deactivates the device * * # Arguments - * * `client` - A valid NotificationProxyClient handle - * * `name` - C string containing the notification name to observe + * * `client` - A valid MobileActivationd handle * * # Returns * An IdeviceFfiError on error, null on success * * # Safety * `client` must be a valid pointer to a handle allocated by this library - * `name` must be a valid null-terminated C string */ -struct IdeviceFfiError *notification_proxy_observe(struct NotificationProxyClientHandle *client, - const char *name); +struct IdeviceFfiError *mobileactivationd_deactivate(struct MobileActivationdClientHandle *client); /** - * Observes multiple notifications at once + * Frees a MobileActivationd client handle * * # Arguments - * * `client` - A valid NotificationProxyClient handle - * * `names` - A null-terminated array of C strings containing notification names + * * [`handle`] - The handle to free * - * # Returns - * An IdeviceFfiError on error, null on success + * # Safety + * `handle` must be a valid pointer to the handle that was allocated by this library, + * or NULL (in which case this function does nothing) + */ +void mobileactivationd_client_free(struct MobileActivationdClientHandle *handle); + +/** + * Connects to the mobilebackup2 service via a provider * * # Safety - * `client` must be a valid pointer to a handle allocated by this library - * `names` must be a valid pointer to a null-terminated array of null-terminated C strings + * All pointer arguments must be valid and non-null */ -struct IdeviceFfiError *notification_proxy_observe_multiple(struct NotificationProxyClientHandle *client, - const char *const *names); +struct IdeviceFfiError *mobilebackup2_connect(struct IdeviceProviderHandle *provider, + struct MobileBackup2ClientHandle **client); /** - * Receives the next notification from the device + * Creates a new MobileBackup2Client via RSD * * # Arguments - * * `client` - A valid NotificationProxyClient handle - * * `name_out` - On success, will be set to a newly allocated C string containing the notification name + * * [`provider`] - An adapter created by this library + * * [`handshake`] - An RSD handshake from the same provider + * * [`client`] - On success, will be set to point to a newly allocated MobileBackup2Client handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `handshake` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *mobilebackup2_connect_rsd(struct AdapterHandle *provider, + struct RsdHandshakeHandle *handshake, + struct MobileBackup2ClientHandle **client); + +/** + * Creates a mobilebackup2 client from an existing connection (consumes the socket) + * + * # Safety + * `socket` is consumed and must not be used after this call + */ +struct IdeviceFfiError *mobilebackup2_new(struct IdeviceHandle *socket, + struct MobileBackup2ClientHandle **client); + +/** + * Frees a mobilebackup2 client handle + * + * # Safety + * `handle` must be valid or NULL + */ +void mobilebackup2_client_free(struct MobileBackup2ClientHandle *handle); + +/** + * Creates a backup of the device + * + * # Arguments + * * `client` - A valid MobileBackup2Client handle + * * `backup_root` - Path to the backup root directory (null-terminated UTF-8) + * * `source_identifier` - Source UDID (null-terminated UTF-8, or NULL for current device) + * * `options` - Optional plist dictionary of backup options (NULL for defaults) + * * `delegate` - Pointer to a populated Mobilebackup2BackupDelegateFFI struct + * * `out_response` - On success, receives the device response plist (caller must free). May be NULL. + * + * # Safety + * All non-null pointers must be valid. `delegate` must remain valid for the entire call. + */ +struct IdeviceFfiError *mobilebackup2_backup(struct MobileBackup2ClientHandle *client, + const char *backup_root, + const char *source_identifier, + plist_t options, + const struct Mobilebackup2BackupDelegateFFI *delegate, + plist_t *out_response); + +/** + * Restores a backup to the device + * + * # Safety + * All non-null pointers must be valid. `delegate` must remain valid for the entire call. + */ +struct IdeviceFfiError *mobilebackup2_restore(struct MobileBackup2ClientHandle *client, + const char *backup_root, + const char *source_identifier, + plist_t options, + const struct Mobilebackup2BackupDelegateFFI *delegate, + plist_t *out_response); + +/** + * Changes the backup password on the device + * + * # Safety + * All non-null pointers must be valid. + */ +struct IdeviceFfiError *mobilebackup2_change_password(struct MobileBackup2ClientHandle *client, + const char *backup_root, + const char *old_password, + const char *new_password, + const struct Mobilebackup2BackupDelegateFFI *delegate); + +/** + * Disconnects from the mobilebackup2 service + * + * # Safety + * `client` must be a valid handle + */ +struct IdeviceFfiError *mobilebackup2_disconnect(struct MobileBackup2ClientHandle *client); + +/** + * Automatically creates and connects to Notification Proxy, returning a client handle + * + * # Arguments + * * [`provider`] - An IdeviceProvider + * * [`client`] - On success, will be set to point to a newly allocated NotificationProxyClient handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *notification_proxy_connect(struct IdeviceProviderHandle *provider, + struct NotificationProxyClientHandle **client); + +/** + * Creates a new NotificationProxyClient via RSD + * + * # Arguments + * * [`provider`] - An adapter created by this library + * * [`handshake`] - An RSD handshake from the same provider + * * [`client`] - On success, will be set to point to a newly allocated NotificationProxyClient handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `handshake` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *notification_proxy_connect_rsd(struct AdapterHandle *provider, + struct RsdHandshakeHandle *handshake, + struct NotificationProxyClientHandle **client); + +/** + * Creates a new NotificationProxyClient from an existing Idevice connection + * + * # Arguments + * * [`socket`] - An IdeviceSocket handle + * * [`client`] - On success, will be set to point to a newly allocated NotificationProxyClient handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `socket` must be a valid pointer to a handle allocated by this library. The socket is consumed, + * and may not be used again. + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *notification_proxy_new(struct IdeviceHandle *socket, + struct NotificationProxyClientHandle **client); + +/** + * Posts a notification to the device + * + * # Arguments + * * `client` - A valid NotificationProxyClient handle + * * `name` - C string containing the notification name + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `client` must be a valid pointer to a handle allocated by this library + * `name` must be a valid null-terminated C string + */ +struct IdeviceFfiError *notification_proxy_post(struct NotificationProxyClientHandle *client, + const char *name); + +/** + * Observes a specific notification + * + * # Arguments + * * `client` - A valid NotificationProxyClient handle + * * `name` - C string containing the notification name to observe + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `client` must be a valid pointer to a handle allocated by this library + * `name` must be a valid null-terminated C string + */ +struct IdeviceFfiError *notification_proxy_observe(struct NotificationProxyClientHandle *client, + const char *name); + +/** + * Observes multiple notifications at once + * + * # Arguments + * * `client` - A valid NotificationProxyClient handle + * * `names` - A null-terminated array of C strings containing notification names + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `client` must be a valid pointer to a handle allocated by this library + * `names` must be a valid pointer to a null-terminated array of null-terminated C strings + */ +struct IdeviceFfiError *notification_proxy_observe_multiple(struct NotificationProxyClientHandle *client, + const char *const *names); + +/** + * Receives the next notification from the device + * + * # Arguments + * * `client` - A valid NotificationProxyClient handle + * * `name_out` - On success, will be set to a newly allocated C string containing the notification name * * # Returns * An IdeviceFfiError on error, null on success @@ -3587,6 +4486,26 @@ void notification_proxy_client_free(struct NotificationProxyClientHandle *handle struct IdeviceFfiError *os_trace_relay_connect(struct IdeviceProviderHandle *provider, struct OsTraceRelayClientHandle **client); +/** + * Creates a new OsTraceRelayClient via RSD + * + * # Arguments + * * [`provider`] - An adapter created by this library + * * [`handshake`] - An RSD handshake from the same provider + * * [`client`] - On success, will be set to point to a newly allocated OsTraceRelayClient handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `handshake` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *os_trace_relay_connect_rsd(struct AdapterHandle *provider, + struct RsdHandshakeHandle *handshake, + struct OsTraceRelayClientHandle **client); + /** * Frees the relay client * @@ -3663,83 +4582,284 @@ struct IdeviceFfiError *os_trace_relay_next(struct OsTraceRelayReceiverHandle *c * Frees a log received from the relay * * # Arguments - * * [`log`] - The log to free + * * [`log`] - The log to free + * + * # Returns + * 0 for success, an *mut IdeviceFfiError otherwise + * + * # Safety + * The log must be allocated by this library. It is consumed and must not be used again. + */ +void os_trace_relay_free_log(struct OsTraceLog *log); + +/** + * Reads a pairing file from the specified path + * + * # Arguments + * * [`path`] - Path to the pairing file + * * [`pairing_file`] - On success, will be set to point to a newly allocated pairing file instance + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `path` must be a valid null-terminated C string + * `pairing_file` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *idevice_pairing_file_read(const char *path, + struct IdevicePairingFile **pairing_file); + +/** + * Parses a pairing file from a byte buffer + * + * # Arguments + * * [`data`] - Pointer to the buffer containing pairing file data + * * [`size`] - Size of the buffer in bytes + * * [`pairing_file`] - On success, will be set to point to a newly allocated pairing file instance + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `data` must be a valid pointer to a buffer of at least `size` bytes + * `pairing_file` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *idevice_pairing_file_from_bytes(const uint8_t *data, + uintptr_t size, + struct IdevicePairingFile **pairing_file); + +/** + * Serializes a pairing file to XML format + * + * # Arguments + * * [`pairing_file`] - The pairing file to serialize + * * [`data`] - On success, will be set to point to a newly allocated buffer containing the serialized data + * * [`size`] - On success, will be set to the size of the allocated buffer + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `pairing_file` must be a valid, non-null pointer to a pairing file instance + * `data` must be a valid, non-null pointer to a location where the buffer pointer will be stored + * `size` must be a valid, non-null pointer to a location where the buffer size will be stored + */ +struct IdeviceFfiError *idevice_pairing_file_serialize(const struct IdevicePairingFile *pairing_file, + uint8_t **data, + uintptr_t *size); + +/** + * Frees a pairing file instance + * + * # Arguments + * * [`pairing_file`] - The pairing file to free + * + * # Safety + * `pairing_file` must be a valid pointer to a pairing file instance that was allocated by this library, + * or NULL (in which case this function does nothing) + */ +void idevice_pairing_file_free(struct IdevicePairingFile *pairing_file); + +/** + * Automatically creates and connects to pcapd, returning a client handle. + * Note that this service only works over USB or through RSD. + * + * # Arguments + * * [`provider`] - An IdeviceProvider + * * [`client`] - On success, will be set to point to a newly allocated PcapdClient handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *pcapd_connect(struct IdeviceProviderHandle *provider, + struct PcapdClientHandle **client); + +/** + * Creates a new PcapdClient via RSD + * + * # Arguments + * * [`provider`] - An adapter created by this library + * * [`handshake`] - An RSD handshake from the same provider + * * [`client`] - On success, will be set to point to a newly allocated PcapdClient handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `handshake` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *pcapd_connect_rsd(struct AdapterHandle *provider, + struct RsdHandshakeHandle *handshake, + struct PcapdClientHandle **client); + +/** + * Creates a new PcapdClient from an existing socket + * + * # Arguments + * * [`socket`] - An IdeviceSocket handle + * * [`client`] - On success, will be set to point to a newly allocated PcapdClient handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `socket` must be a valid pointer to a handle allocated by this library. The socket is consumed, + * and may not be used again. + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *pcapd_new(struct IdeviceHandle *socket, struct PcapdClientHandle **client); + +/** + * Reads the next packet from the pcapd service + * + * # Arguments + * * `client` - A valid PcapdClient handle + * * `packet` - On success, will be set to point to a newly allocated DevicePacketHandle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `client` must be a valid pointer to a handle allocated by this library + * The returned packet must be freed with `pcapd_device_packet_free` + */ +struct IdeviceFfiError *pcapd_next_packet(struct PcapdClientHandle *client, + struct DevicePacketHandle **packet); + +/** + * Frees a DevicePacketHandle + * + * # Arguments + * * [`handle`] - The handle to free + * + * # Safety + * `handle` must be a valid pointer to the handle that was allocated by this library, + * or NULL (in which case this function does nothing) + */ +void pcapd_device_packet_free(struct DevicePacketHandle *handle); + +/** + * Frees a PcapdClient handle + * + * # Arguments + * * [`handle`] - The handle to free + * + * # Safety + * `handle` must be a valid pointer to the handle that was allocated by this library, + * or NULL (in which case this function does nothing) + */ +void pcapd_client_free(struct PcapdClientHandle *handle); + +/** + * Automatically creates and connects to Preboard Service, returning a client handle + * + * # Arguments + * * [`provider`] - An IdeviceProvider + * * [`client`] - On success, will be set to point to a newly allocated PreboardServiceClient handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *preboard_service_connect(struct IdeviceProviderHandle *provider, + struct PreboardServiceClientHandle **client); + +/** + * Creates a new PreboardServiceClient via RSD + * + * # Arguments + * * [`provider`] - An adapter created by this library + * * [`handshake`] - An RSD handshake from the same provider + * * [`client`] - On success, will be set to point to a newly allocated PreboardServiceClient handle * * # Returns - * 0 for success, an *mut IdeviceFfiError otherwise + * An IdeviceFfiError on error, null on success * * # Safety - * The log must be allocated by this library. It is consumed and must not be used again. + * `provider` must be a valid pointer to a handle allocated by this library + * `handshake` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored */ -void os_trace_relay_free_log(struct OsTraceLog *log); +struct IdeviceFfiError *preboard_service_connect_rsd(struct AdapterHandle *provider, + struct RsdHandshakeHandle *handshake, + struct PreboardServiceClientHandle **client); /** - * Reads a pairing file from the specified path + * Creates a new PreboardServiceClient from an existing socket * * # Arguments - * * [`path`] - Path to the pairing file - * * [`pairing_file`] - On success, will be set to point to a newly allocated pairing file instance + * * [`socket`] - An IdeviceSocket handle + * * [`client`] - On success, will be set to point to a newly allocated PreboardServiceClient handle * * # Returns * An IdeviceFfiError on error, null on success * * # Safety - * `path` must be a valid null-terminated C string - * `pairing_file` must be a valid, non-null pointer to a location where the handle will be stored + * `socket` must be a valid pointer to a handle allocated by this library. The socket is consumed, + * and may not be used again. + * `client` must be a valid, non-null pointer to a location where the handle will be stored */ -struct IdeviceFfiError *idevice_pairing_file_read(const char *path, - struct IdevicePairingFile **pairing_file); +struct IdeviceFfiError *preboard_service_new(struct IdeviceHandle *socket, + struct PreboardServiceClientHandle **client); /** - * Parses a pairing file from a byte buffer + * Creates a stashbag on the device * * # Arguments - * * [`data`] - Pointer to the buffer containing pairing file data - * * [`size`] - Size of the buffer in bytes - * * [`pairing_file`] - On success, will be set to point to a newly allocated pairing file instance + * * `client` - A valid PreboardServiceClient handle + * * `manifest` - Pointer to the manifest data + * * `manifest_len` - Length of the manifest data * * # Returns * An IdeviceFfiError on error, null on success * * # Safety - * `data` must be a valid pointer to a buffer of at least `size` bytes - * `pairing_file` must be a valid, non-null pointer to a location where the handle will be stored + * `client` must be a valid pointer to a handle allocated by this library + * `manifest` must be a valid pointer to `manifest_len` bytes of data */ -struct IdeviceFfiError *idevice_pairing_file_from_bytes(const uint8_t *data, - uintptr_t size, - struct IdevicePairingFile **pairing_file); +struct IdeviceFfiError *preboard_service_create_stashbag(struct PreboardServiceClientHandle *client, + const uint8_t *manifest, + uintptr_t manifest_len); /** - * Serializes a pairing file to XML format + * Commits a stashbag on the device * * # Arguments - * * [`pairing_file`] - The pairing file to serialize - * * [`data`] - On success, will be set to point to a newly allocated buffer containing the serialized data - * * [`size`] - On success, will be set to the size of the allocated buffer + * * `client` - A valid PreboardServiceClient handle + * * `manifest` - Pointer to the manifest data + * * `manifest_len` - Length of the manifest data * * # Returns * An IdeviceFfiError on error, null on success * * # Safety - * `pairing_file` must be a valid, non-null pointer to a pairing file instance - * `data` must be a valid, non-null pointer to a location where the buffer pointer will be stored - * `size` must be a valid, non-null pointer to a location where the buffer size will be stored + * `client` must be a valid pointer to a handle allocated by this library + * `manifest` must be a valid pointer to `manifest_len` bytes of data */ -struct IdeviceFfiError *idevice_pairing_file_serialize(const struct IdevicePairingFile *pairing_file, - uint8_t **data, - uintptr_t *size); +struct IdeviceFfiError *preboard_service_commit_stashbag(struct PreboardServiceClientHandle *client, + const uint8_t *manifest, + uintptr_t manifest_len); /** - * Frees a pairing file instance + * Frees a PreboardServiceClient handle * * # Arguments - * * [`pairing_file`] - The pairing file to free + * * [`handle`] - The handle to free * * # Safety - * `pairing_file` must be a valid pointer to a pairing file instance that was allocated by this library, + * `handle` must be a valid pointer to the handle that was allocated by this library, * or NULL (in which case this function does nothing) */ -void idevice_pairing_file_free(struct IdevicePairingFile *pairing_file); +void preboard_service_client_free(struct PreboardServiceClientHandle *handle); /** * Creates a TCP provider for idevice @@ -3819,6 +4939,207 @@ struct IdeviceFfiError *usbmuxd_provider_new(struct UsbmuxdAddrHandle *addr, struct IdeviceFfiError *idevice_provider_get_pairing_file(struct IdeviceProviderHandle *provider, struct IdevicePairingFile **pairing_file); +/** + * Creates a new RestoreServiceClient from a ReadWrite stream + * + * # Arguments + * * [`socket`] - A ReadWriteOpaque handle (consumed) + * * [`client`] - On success, will be set to point to a newly allocated handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `socket` must be a valid pointer to a handle allocated by this library. The socket is consumed, + * and may not be used again. + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *restore_service_new(struct ReadWriteOpaque *socket, + struct RestoreServiceClientHandle **client); + +/** + * Creates a new RestoreServiceClient via RSD + * + * # Arguments + * * [`provider`] - An adapter created by this library + * * [`handshake`] - An RSD handshake from the same provider + * * [`client`] - On success, will be set to point to a newly allocated RestoreServiceClient handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `handshake` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *restore_service_connect_rsd(struct AdapterHandle *provider, + struct RsdHandshakeHandle *handshake, + struct RestoreServiceClientHandle **client); + +/** + * Enters recovery mode on the device + * + * # Arguments + * * `client` - A valid RestoreServiceClient handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `client` must be a valid pointer to a handle allocated by this library + */ +struct IdeviceFfiError *restore_service_enter_recovery(struct RestoreServiceClientHandle *client); + +/** + * Reboots the device + * + * # Arguments + * * `client` - A valid RestoreServiceClient handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `client` must be a valid pointer to a handle allocated by this library + */ +struct IdeviceFfiError *restore_service_reboot(struct RestoreServiceClientHandle *client); + +/** + * Gets preflight info from the device + * + * # Arguments + * * `client` - A valid RestoreServiceClient handle + * * `res` - Will be set to a pointer of a plist dictionary node on success + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `client` must be a valid pointer to a handle allocated by this library + */ +struct IdeviceFfiError *restore_service_get_preflightinfo(struct RestoreServiceClientHandle *client, + plist_t *res); + +/** + * Gets nonces from the device + * + * # Arguments + * * `client` - A valid RestoreServiceClient handle + * * `res` - Will be set to a pointer of a plist dictionary node on success + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `client` must be a valid pointer to a handle allocated by this library + */ +struct IdeviceFfiError *restore_service_get_nonces(struct RestoreServiceClientHandle *client, + plist_t *res); + +/** + * Gets app parameters from the device + * + * # Arguments + * * `client` - A valid RestoreServiceClient handle + * * `res` - Will be set to a pointer of a plist dictionary node on success + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `client` must be a valid pointer to a handle allocated by this library + */ +struct IdeviceFfiError *restore_service_get_app_parameters(struct RestoreServiceClientHandle *client, + plist_t *res); + +/** + * Restores the device language + * + * # Arguments + * * `client` - A valid RestoreServiceClient handle + * * `language` - The language to restore to + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `client` must be a valid pointer to a handle allocated by this library + * `language` must be a valid null-terminated C string + */ +struct IdeviceFfiError *restore_service_restore_lang(struct RestoreServiceClientHandle *client, + const char *language); + +/** + * Frees a RestoreServiceClient handle + * + * # Arguments + * * [`handle`] - The handle to free + * + * # Safety + * `handle` must be a valid pointer to the handle that was allocated by this library, + * or NULL (in which case this function does nothing) + */ +void restore_service_client_free(struct RestoreServiceClientHandle *handle); + +/** + * Generates a new RPPairing file with fresh Ed25519 keys. + * + * # Safety + * `hostname` must be a valid null-terminated C string. + * `out` must be valid and non-null. + */ +struct IdeviceFfiError *rp_pairing_file_generate(const char *hostname, + struct RpPairingFileHandle **out); + +/** + * Reads an RPPairing file from a path. + * + * # Safety + * `path` must be a valid null-terminated C string. + * `out` must be valid and non-null. + */ +struct IdeviceFfiError *rp_pairing_file_read(const char *path, struct RpPairingFileHandle **out); + +/** + * Parses an RPPairing file from plist bytes (XML or binary). + * + * # Safety + * `data` must point to `len` valid bytes. + * `out` must be valid and non-null. + */ +struct IdeviceFfiError *rp_pairing_file_from_bytes(const uint8_t *data, + uintptr_t len, + struct RpPairingFileHandle **out); + +/** + * Serializes an RPPairing file to XML plist bytes. + * + * The caller must free the returned bytes with `idevice_data_free(data, len)`. + * + * # Safety + * `handle`, `out_data`, and `out_len` must be valid and non-null. + */ +struct IdeviceFfiError *rp_pairing_file_to_bytes(struct RpPairingFileHandle *handle, + uint8_t **out_data, + uintptr_t *out_len); + +/** + * Writes an RPPairing file to a path. + * + * # Safety + * `handle` and `path` must be valid. + */ +struct IdeviceFfiError *rp_pairing_file_write(struct RpPairingFileHandle *handle, const char *path); + +/** + * Frees an RPPairing file handle. + * + * # Safety + * `handle` must be valid or NULL. + */ +void rp_pairing_file_free(struct RpPairingFileHandle *handle); + /** * Creates a new RSD handshake from a ReadWrite connection * @@ -3999,6 +5320,26 @@ void rsd_handshake_free(struct RsdHandshakeHandle *handle); struct IdeviceFfiError *screenshotr_connect(struct IdeviceProviderHandle *provider, struct ScreenshotrClientHandle **client); +/** + * Creates a new ScreenshotService via RSD + * + * # Arguments + * * [`provider`] - An adapter created by this library + * * [`handshake`] - An RSD handshake from the same provider + * * [`client`] - On success, will be set to point to a newly allocated ScreenshotrClient handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `handshake` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *screenshotr_connect_rsd(struct AdapterHandle *provider, + struct RsdHandshakeHandle *handshake, + struct ScreenshotrClientHandle **client); + /** * Takes a screenshot from the device * @@ -4058,6 +5399,26 @@ void screenshotr_client_free(struct ScreenshotrClientHandle *handle); struct IdeviceFfiError *springboard_services_connect(struct IdeviceProviderHandle *provider, struct SpringBoardServicesClientHandle **client); +/** + * Creates a new SpringBoardServicesClient via RSD + * + * # Arguments + * * [`provider`] - An adapter created by this library + * * [`handshake`] - An RSD handshake from the same provider + * * [`client`] - On success, will be set to point to a newly allocated SpringBoardServicesClient handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `handshake` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *springboard_services_connect_rsd(struct AdapterHandle *provider, + struct RsdHandshakeHandle *handshake, + struct SpringBoardServicesClientHandle **client); + /** * Creates a new SpringBoardServices client from an existing Idevice connection * @@ -4194,6 +5555,26 @@ void springboard_services_free(struct SpringBoardServicesClientHandle *handle); struct IdeviceFfiError *syslog_relay_connect_tcp(struct IdeviceProviderHandle *provider, struct SyslogRelayClientHandle **client); +/** + * Creates a new SyslogRelayClient via RSD + * + * # Arguments + * * [`provider`] - An adapter created by this library + * * [`handshake`] - An RSD handshake from the same provider + * * [`client`] - On success, will be set to point to a newly allocated SyslogRelayClient handle + * + * # Returns + * An IdeviceFfiError on error, null on success + * + * # Safety + * `provider` must be a valid pointer to a handle allocated by this library + * `handshake` must be a valid pointer to a handle allocated by this library + * `client` must be a valid, non-null pointer to a location where the handle will be stored + */ +struct IdeviceFfiError *syslog_relay_connect_rsd(struct AdapterHandle *provider, + struct RsdHandshakeHandle *handshake, + struct SyslogRelayClientHandle **client); + /** * Frees a handle * @@ -4262,6 +5643,73 @@ void idevice_free_tcp_feed_object(struct TcpFeedObject *object); */ void idevice_free_tcp_eat_object(struct TcpEatObject *object); +/** + * Creates a tunnel over USB via CoreDeviceProxy. + * No need to stop remoted. + * + * # Safety + * All pointer arguments must be valid and non-null. + */ +struct IdeviceFfiError *tunnel_create_usb(struct IdeviceProviderHandle *lockdown_provider, + struct AdapterHandle **out_adapter, + struct RsdHandshakeHandle **out_handshake); + +/** + * Pairs via USB CoreDeviceProxy tunnel (no SIGSTOP needed). + * + * For iOS, `pin_callback` can be NULL (defaults to "000000"). + * For Apple TV / Vision Pro, provide a callback returning the on-screen PIN. + * + * # Safety + * All pointer arguments must be valid and non-null (except `pin_callback`/`pin_context`). + */ +struct IdeviceFfiError *tunnel_pair_usb(struct IdeviceProviderHandle *lockdown_provider, + const char *hostname, + const char *(*pin_callback)(void *context), + void *pin_context, + struct RpPairingFileHandle **out_pairing_file); + +/** + * Creates a tunnel over the network via RemoteXPC. + * + * Use this when connecting to a device discovered via `_remoted._tcp` (RSD port). + * The connection goes: RSD → find tunnel service → RemoteXPC → RPPairing → tunnel. + * + * # Safety + * All pointer arguments must be valid and non-null (except `pin_callback`/`pin_context`). + * `pairing_file` is borrowed, not consumed. + */ +struct IdeviceFfiError *tunnel_create_remotexpc(const idevice_sockaddr *addr, + idevice_socklen_t addr_len, + const char *hostname, + struct RpPairingFileHandle *pairing_file, + const char *(*pin_callback)(void *context), + void *pin_context, + struct AdapterHandle **out_adapter, + struct RsdHandshakeHandle **out_handshake); + +/** + * Creates a tunnel over the network via raw RPPairing protocol. + * + * Use this when connecting to a device discovered via `_remotepairing._tcp`. + * The connection goes: direct TCP → RPPairing (JSON) → tunnel. + * + * This path only supports pair-verify (existing pairing file required). + * For initial pairing, use `tunnel_pair_usb`. + * + * # Safety + * All pointer arguments must be valid and non-null (except `pin_callback`/`pin_context`). + * `pairing_file` is borrowed, not consumed. + */ +struct IdeviceFfiError *tunnel_create_rppairing(const idevice_sockaddr *addr, + idevice_socklen_t addr_len, + const char *hostname, + struct RpPairingFileHandle *pairing_file, + const char *(*pin_callback)(void *context), + void *pin_context, + struct AdapterHandle **out_adapter, + struct RsdHandshakeHandle **out_handshake); + /** * Connects to a usbmuxd instance over TCP * @@ -4602,6 +6050,10 @@ uint8_t idevice_usbmuxd_device_get_connection_type(const struct UsbmuxdDeviceHan +// THIS FILE IS UNDER ITS ORIGINAL LICENSE FROM LIBIMOBILEDEVICE +// THIS IS NOT PART OF IDEVICE AND ITS LICENSE +// MORE INFORMATION CAN BE FOUND AT https://github.com/libimobiledevice/libplist + /** * @file plist/plist.h * @brief Main include of libplist diff --git a/StikJIT/idevice/ideviceinfo.m b/StikJIT/idevice/ideviceinfo.m index d1e7aeab..6921bde7 100644 --- a/StikJIT/idevice/ideviceinfo.m +++ b/StikJIT/idevice/ideviceinfo.m @@ -14,25 +14,16 @@ @import Foundation; NSError* makeError(int code, NSString* msg); -LockdowndClientHandle* ideviceinfo_c_init(IdeviceProviderHandle* g_provider, IdevicePairingFile* g_sess_pf, NSError** error) { +LockdowndClientHandle* ideviceinfo_c_init(AdapterHandle* adapter, RsdHandshakeHandle* handshake, NSError** error) { LockdowndClientHandle *g_client = NULL; - IdeviceFfiError *err = lockdownd_connect(g_provider, &g_client); + IdeviceFfiError *err = lockdownd_connect_rsd(adapter, handshake, &g_client); if (err) { *error = makeError(err->code, @(err->message)); - idevice_pairing_file_free(g_sess_pf); idevice_error_free(err); return NULL; } - err = lockdownd_start_session(g_client, g_sess_pf); - idevice_pairing_file_free(g_sess_pf); - if (err) { - *error = makeError(err->code, @(err->message)); - idevice_error_free(err); - lockdownd_client_free(g_client); - return NULL; - } - + // No session start needed - RSD tunnel handles authentication return g_client; } @@ -62,15 +53,13 @@ @implementation JITEnableContext(DeviceInfo) - (LockdowndClientHandle*)ideviceInfoInit:(NSError**)error { - [self ensureHeartbeatWithError:error]; - if (*error) { return nil; } - IdevicePairingFile *pf = [self getPairingFileWithError:error]; + [self ensureTunnelWithError:error]; if (*error) { return nil; } - return ideviceinfo_c_init(provider, pf, error); + return ideviceinfo_c_init(adapter, handshake, error); } - (char*)ideviceInfoGetXMLWithLockdownClient:(LockdowndClientHandle*)lockdownClient error:(NSError**)error { - [self ensureHeartbeatWithError:error]; + [self ensureTunnelWithError:error]; if (*error) { return NULL; } return ideviceinfo_c_get_xml(lockdownClient, error); } diff --git a/StikJIT/idevice/jit.h b/StikJIT/idevice/jit.h index d745c6db..e7a3480f 100644 --- a/StikJIT/idevice/jit.h +++ b/StikJIT/idevice/jit.h @@ -9,14 +9,15 @@ #ifndef JIT_H #define JIT_H #include "idevice.h" +#include typedef void (^LogFuncC)(const char* message, ...); typedef void (^DebugAppCallback)(int pid, struct DebugProxyHandle* debug_proxy, struct RemoteServerHandle* remote_server, dispatch_semaphore_t semaphore); -int debug_app(IdeviceProviderHandle* tcp_provider, const char *bundle_id, LogFuncC logger, DebugAppCallback callback); -int debug_app_pid(IdeviceProviderHandle* tcp_provider, int pid, LogFuncC logger, DebugAppCallback callback); -int launch_app_via_proxy(IdeviceProviderHandle* tcp_provider, const char *bundle_id, LogFuncC logger); +int debug_app(AdapterHandle* adapter, RsdHandshakeHandle* handshake, const char *bundle_id, LogFuncC logger, DebugAppCallback callback); +int debug_app_pid(AdapterHandle* adapter, RsdHandshakeHandle* handshake, int pid, LogFuncC logger, DebugAppCallback callback); +int launch_app_via_proxy(AdapterHandle* adapter, RsdHandshakeHandle* handshake, const char *bundle_id, LogFuncC logger); #endif /* JIT_H */ diff --git a/StikJIT/idevice/jit.m b/StikJIT/idevice/jit.m index aa357ee3..e86ef338 100644 --- a/StikJIT/idevice/jit.m +++ b/StikJIT/idevice/jit.m @@ -23,8 +23,6 @@ // MARK: - Shared debug session typedef struct { - AdapterHandle *adapter; - RsdHandshakeHandle *handshake; RemoteServerHandle *remote_server; DebugProxyHandle *debug_proxy; } DebugSession; @@ -32,40 +30,18 @@ static void debug_session_free(DebugSession *s) { if (s->debug_proxy) { debug_proxy_free(s->debug_proxy); s->debug_proxy = NULL; } if (s->remote_server) { remote_server_free(s->remote_server); s->remote_server = NULL; } - if (s->handshake) { rsd_handshake_free(s->handshake); s->handshake = NULL; } - if (s->adapter) { adapter_free(s->adapter); s->adapter = NULL; } } -// Connects to the device, performs the RSD handshake, and sets up the debug proxy. +// Connects to the device using the existing adapter+handshake and sets up the debug proxy. // Returns 0 on success; cleans up any partial state and returns 1 on failure. -static int connect_debug_session(IdeviceProviderHandle *tcp_provider, DebugSession *out) { +static int connect_debug_session(AdapterHandle *adapter, RsdHandshakeHandle *handshake, DebugSession *out) { memset(out, 0, sizeof(*out)); IdeviceFfiError *err = NULL; - CoreDeviceProxyHandle *core_device = NULL; - err = core_device_proxy_connect(tcp_provider, &core_device); + err = remote_server_connect_rsd(adapter, handshake, &out->remote_server); if (err) { idevice_error_free(err); return 1; } - uint16_t rsd_port = 0; - err = core_device_proxy_get_server_rsd_port(core_device, &rsd_port); - if (err) { idevice_error_free(err); core_device_proxy_free(core_device); return 1; } - - err = core_device_proxy_create_tcp_adapter(core_device, &out->adapter); - if (err) { idevice_error_free(err); core_device_proxy_free(core_device); return 1; } - core_device = NULL; // ownership transferred to adapter - - AdapterStreamHandle *stream = NULL; - err = adapter_connect(out->adapter, rsd_port, (ReadWriteOpaque **)&stream); - if (err) { idevice_error_free(err); debug_session_free(out); return 1; } - - err = rsd_handshake_new((ReadWriteOpaque *)stream, &out->handshake); - if (err) { idevice_error_free(err); adapter_close(stream); debug_session_free(out); return 1; } - stream = NULL; // consumed by handshake - - err = remote_server_connect_rsd(out->adapter, out->handshake, &out->remote_server); - if (err) { idevice_error_free(err); debug_session_free(out); return 1; } - - err = debug_proxy_connect_rsd(out->adapter, out->handshake, &out->debug_proxy); + err = debug_proxy_connect_rsd(adapter, handshake, &out->debug_proxy); if (err) { idevice_error_free(err); debug_session_free(out); return 1; } return 0; @@ -137,9 +113,9 @@ void runDebugServerCommand(int pid, // MARK: - Public entry points -int debug_app(IdeviceProviderHandle* tcp_provider, const char *bundle_id, LogFuncC logger, DebugAppCallback callback) { +int debug_app(AdapterHandle* adapter, RsdHandshakeHandle* handshake, const char *bundle_id, LogFuncC logger, DebugAppCallback callback) { DebugSession session; - if (connect_debug_session(tcp_provider, &session) != 0) return 1; + if (connect_debug_session(adapter, handshake, &session) != 0) return 1; ProcessControlHandle *process_control = NULL; IdeviceFfiError *err = process_control_new(session.remote_server, &process_control); @@ -166,9 +142,9 @@ int debug_app(IdeviceProviderHandle* tcp_provider, const char *bundle_id, LogFun return 0; } -int debug_app_pid(IdeviceProviderHandle* tcp_provider, int pid, LogFuncC logger, DebugAppCallback callback) { +int debug_app_pid(AdapterHandle* adapter, RsdHandshakeHandle* handshake, int pid, LogFuncC logger, DebugAppCallback callback) { DebugSession session; - if (connect_debug_session(tcp_provider, &session) != 0) return 1; + if (connect_debug_session(adapter, handshake, &session) != 0) return 1; runDebugServerCommand(pid, session.debug_proxy, session.remote_server, logger, callback); @@ -177,36 +153,14 @@ int debug_app_pid(IdeviceProviderHandle* tcp_provider, int pid, LogFuncC logger, return 0; } -int launch_app_via_proxy(IdeviceProviderHandle* tcp_provider, const char *bundle_id, LogFuncC logger) { +int launch_app_via_proxy(AdapterHandle* adapter, RsdHandshakeHandle* handshake, const char *bundle_id, LogFuncC logger) { IdeviceFfiError* err = NULL; - CoreDeviceProxyHandle *core_device = NULL; - AdapterHandle *adapter = NULL; - AdapterStreamHandle *stream = NULL; - RsdHandshakeHandle *handshake = NULL; RemoteServerHandle *remote_server = NULL; ProcessControlHandle *process_control = NULL; uint64_t pid = 0; int result = 1; - err = core_device_proxy_connect(tcp_provider, &core_device); - if (err) { idevice_error_free(err); goto cleanup; } - - uint16_t rsd_port = 0; - err = core_device_proxy_get_server_rsd_port(core_device, &rsd_port); - if (err) { idevice_error_free(err); goto cleanup; } - - err = core_device_proxy_create_tcp_adapter(core_device, &adapter); - if (err) { idevice_error_free(err); goto cleanup; } - core_device = NULL; // ownership transferred to adapter - - err = adapter_connect(adapter, rsd_port, (ReadWriteOpaque **)&stream); - if (err) { idevice_error_free(err); goto cleanup; } - - err = rsd_handshake_new((ReadWriteOpaque *)stream, &handshake); - if (err) { idevice_error_free(err); goto cleanup; } - stream = NULL; // consumed by handshake/adapter stack - err = remote_server_connect_rsd(adapter, handshake, &remote_server); if (err) { idevice_error_free(err); goto cleanup; } @@ -226,10 +180,6 @@ int launch_app_via_proxy(IdeviceProviderHandle* tcp_provider, const char *bundle cleanup: if (process_control) process_control_free(process_control); if (remote_server) remote_server_free(remote_server); - if (handshake) rsd_handshake_free(handshake); - if (stream) adapter_close(stream); - if (adapter) adapter_free(adapter); - if (core_device) core_device_proxy_free(core_device); return result; } @@ -238,32 +188,32 @@ @implementation JITEnableContext(JIT) - (BOOL)debugAppWithBundleID:(NSString*)bundleID logger:(LogFunc)logger jsCallback:(DebugAppCallback)jsCallback { NSError* err = nil; - [self ensureHeartbeatWithError:&err]; + [self ensureTunnelWithError:&err]; if (err) { logger(err.localizedDescription); return NO; } - return debug_app(provider, [bundleID UTF8String], [self createCLogger:logger], jsCallback) == 0; + return debug_app(adapter, handshake, [bundleID UTF8String], [self createCLogger:logger], jsCallback) == 0; } - (BOOL)debugAppWithPID:(int)pid logger:(LogFunc)logger jsCallback:(DebugAppCallback)jsCallback { NSError* err = nil; - [self ensureHeartbeatWithError:&err]; + [self ensureTunnelWithError:&err]; if (err) { logger(err.localizedDescription); return NO; } - return debug_app_pid(provider, pid, [self createCLogger:logger], jsCallback) == 0; + return debug_app_pid(adapter, handshake, pid, [self createCLogger:logger], jsCallback) == 0; } - (BOOL)launchAppWithoutDebug:(NSString*)bundleID logger:(LogFunc)logger { NSError* err = nil; - [self ensureHeartbeatWithError:&err]; + [self ensureTunnelWithError:&err]; if (err) { logger(err.localizedDescription); return NO; } - return launch_app_via_proxy(provider, [bundleID UTF8String], [self createCLogger:logger]) == 0; + return launch_app_via_proxy(adapter, handshake, [bundleID UTF8String], [self createCLogger:logger]) == 0; } @end diff --git a/StikJIT/idevice/libidevice_ffi.a b/StikJIT/idevice/libidevice_ffi.a index 81a63a31..f047881b 100644 Binary files a/StikJIT/idevice/libidevice_ffi.a and b/StikJIT/idevice/libidevice_ffi.a differ diff --git a/StikJIT/idevice/location_simulation.c b/StikJIT/idevice/location_simulation.c index 3e3e87e7..1658a4f7 100644 --- a/StikJIT/idevice/location_simulation.c +++ b/StikJIT/idevice/location_simulation.c @@ -13,9 +13,6 @@ #include #include -static IdevicePairingFile *g_pairing = NULL; -static IdeviceProviderHandle *g_provider = NULL; -static CoreDeviceProxyHandle *g_core_device = NULL; static AdapterHandle *g_adapter = NULL; static RsdHandshakeHandle *g_handshake = NULL; static RemoteServerHandle *g_remote_server = NULL; @@ -26,9 +23,6 @@ static void cleanup_on_error(void) { if (g_remote_server) { remote_server_free(g_remote_server); g_remote_server = NULL; } if (g_handshake) { rsd_handshake_free(g_handshake); g_handshake = NULL; } if (g_adapter) { adapter_free(g_adapter); g_adapter = NULL; } - if (g_core_device) { core_device_proxy_free(g_core_device); g_core_device = NULL; } - if (g_provider) { idevice_provider_free(g_provider); g_provider = NULL; } - if (g_pairing) { idevice_pairing_file_free(g_pairing); g_pairing = NULL; } } int simulate_location(const char *device_ip, @@ -37,7 +31,7 @@ int simulate_location(const char *device_ip, const char *pairing_file) { IdeviceFfiError *err = NULL; - + if (g_location_sim) { if ((err = location_simulation_set(g_location_sim, latitude, longitude))) { idevice_error_free(err); @@ -53,68 +47,28 @@ int simulate_location(const char *device_ip, return IPA_ERR_INVALID_IP; } - if (g_pairing) { - idevice_pairing_file_free(g_pairing); - g_pairing = NULL; - } - - if ((err = idevice_pairing_file_read(pairing_file, &g_pairing))) { + RpPairingFileHandle *rp_pairing = NULL; + if ((err = rp_pairing_file_read(pairing_file, &rp_pairing))) { idevice_error_free(err); return IPA_ERR_PAIRING_READ; } - if ((err = idevice_tcp_provider_new((struct sockaddr *)&addr, - g_pairing, - "LocationSimCLI", - &g_provider))) + if ((err = tunnel_create_rppairing( + (const idevice_sockaddr *)&addr, + sizeof(addr), + "StikDebugLocation", + rp_pairing, + NULL, + NULL, + &g_adapter, + &g_handshake))) { idevice_error_free(err); + rp_pairing_file_free(rp_pairing); cleanup_on_error(); return IPA_ERR_PROVIDER_CREATE; } - - if ((err = core_device_proxy_connect(g_provider, &g_core_device))) { - idevice_error_free(err); - cleanup_on_error(); - return IPA_ERR_CORE_DEVICE; - } - idevice_provider_free(g_provider); - g_provider = NULL; - - uint16_t rsd_port; - if ((err = core_device_proxy_get_server_rsd_port(g_core_device, - &rsd_port))) - { - idevice_error_free(err); - cleanup_on_error(); - return IPA_ERR_RSD_PORT; - } - - if ((err = core_device_proxy_create_tcp_adapter(g_core_device, - &g_adapter))) - { - idevice_error_free(err); - cleanup_on_error(); - return IPA_ERR_ADAPTER_CREATE; - } - // core_device_proxy_create_tcp_adapter takes ownership of g_core_device - // (Rust moves it into the adapter). Null the pointer so cleanup_on_error - // does not attempt a second free. - g_core_device = NULL; - - AdapterStreamHandle *stream = NULL; - if ((err = adapter_connect(g_adapter, rsd_port, (ReadWriteOpaque **)&stream))) { - idevice_error_free(err); - cleanup_on_error(); - return IPA_ERR_STREAM; - } - - if ((err = rsd_handshake_new((ReadWriteOpaque *)stream, &g_handshake))) { - idevice_error_free(err); - adapter_stream_close(stream); - cleanup_on_error(); - return IPA_ERR_HANDSHAKE; - } + rp_pairing_file_free(rp_pairing); if ((err = remote_server_connect_rsd(g_adapter, g_handshake, @@ -124,9 +78,6 @@ int simulate_location(const char *device_ip, cleanup_on_error(); return IPA_ERR_REMOTE_SERVER; } - // remote_server_connect_rsd takes ownership of g_adapter and g_handshake. - g_adapter = NULL; - g_handshake = NULL; if ((err = location_simulation_new(g_remote_server, &g_location_sim))) { diff --git a/StikJIT/idevice/mount.h b/StikJIT/idevice/mount.h index 2a09749a..f56c1f22 100644 --- a/StikJIT/idevice/mount.h +++ b/StikJIT/idevice/mount.h @@ -9,6 +9,6 @@ #define MOUNT_H #include "idevice.h" #include -size_t getMountedDeviceCount(IdeviceProviderHandle* provider, NSError** error); -int mountPersonalDDI(IdeviceProviderHandle* provider, IdevicePairingFile* pairingFile2, NSString* imagePath, NSString* trustcachePath, NSString* manifestPath, NSError** error); +size_t getMountedDeviceCount(AdapterHandle* adapter, RsdHandshakeHandle* handshake, NSError** error); +int mountPersonalDDI(AdapterHandle* adapter, RsdHandshakeHandle* handshake, NSString* imagePath, NSString* trustcachePath, NSString* manifestPath, NSError** error); #endif diff --git a/StikJIT/idevice/mount.m b/StikJIT/idevice/mount.m index 4366b7be..1897b36b 100644 --- a/StikJIT/idevice/mount.m +++ b/StikJIT/idevice/mount.m @@ -11,9 +11,9 @@ NSError* makeError(int code, NSString* msg); -size_t getMountedDeviceCount(IdeviceProviderHandle* provider, NSError** error) { +size_t getMountedDeviceCount(AdapterHandle* adapter, RsdHandshakeHandle* handshake, NSError** error) { ImageMounterHandle *client = NULL; - IdeviceFfiError *err = image_mounter_connect(provider, &client); + IdeviceFfiError *err = image_mounter_connect_rsd(adapter, handshake, &client); if (err) { *error = makeError(err->code, @(err->message)); idevice_error_free(err); @@ -37,34 +37,24 @@ size_t getMountedDeviceCount(IdeviceProviderHandle* provider, NSError** error) { return deviceLength; } -int mountPersonalDDI(IdeviceProviderHandle* provider, IdevicePairingFile* pairingFile2, NSString* imagePath, NSString* trustcachePath, NSString* manifestPath, NSError** error) { +int mountPersonalDDI(AdapterHandle* adapter, RsdHandshakeHandle* handshake, NSString* imagePath, NSString* trustcachePath, NSString* manifestPath, NSError** error) { NSData *image = [NSData dataWithContentsOfFile:imagePath]; NSData *trustcache = [NSData dataWithContentsOfFile:trustcachePath]; NSData *buildManifest = [NSData dataWithContentsOfFile:manifestPath]; if (!image || !trustcache || !buildManifest) { - idevice_pairing_file_free(pairingFile2); *error = makeError(1, @"Failed to read one or more files"); return 1; } + // Get UniqueChipID via lockdownd over RSD (no session start needed - tunnel handles auth) LockdowndClientHandle *lockdownClient = NULL; - IdeviceFfiError *err = lockdownd_connect(provider, &lockdownClient); + IdeviceFfiError *err = lockdownd_connect_rsd(adapter, handshake, &lockdownClient); if (err) { *error = makeError(6, @(err->message)); - idevice_pairing_file_free(pairingFile2); idevice_error_free(err); return 6; } - err = lockdownd_start_session(lockdownClient, pairingFile2); - idevice_pairing_file_free(pairingFile2); - if (err) { - *error = makeError(7, @(err->message)); - idevice_error_free(err); - lockdownd_client_free(lockdownClient); - return 7; - } - plist_t uniqueChipIDPlist = NULL; err = lockdownd_get_value(lockdownClient, "UniqueChipID", NULL, &uniqueChipIDPlist); lockdownd_client_free(lockdownClient); @@ -79,50 +69,33 @@ int mountPersonalDDI(IdeviceProviderHandle* provider, IdevicePairingFile* pairin plist_free(uniqueChipIDPlist); ImageMounterHandle *mounterClient = NULL; - err = image_mounter_connect(provider, &mounterClient); + err = image_mounter_connect_rsd(adapter, handshake, &mounterClient); if (err) { *error = makeError(9, @(err->message)); idevice_error_free(err); return 9; } - err = image_mounter_mount_personalized( - mounterClient, - provider, - [image bytes], - [image length], - [trustcache bytes], - [trustcache length], - [buildManifest bytes], - [buildManifest length], - NULL, - uniqueChipID - ); + // TODO: image_mounter_mount_personalized still requires an IdeviceProviderHandle. + // The FFI needs an RSD variant (e.g. image_mounter_mount_personalized_rsd) that + // takes an AdapterHandle instead. + *error = makeError(10, @"mount_personalized not yet available over RSD tunnels"); image_mounter_free(mounterClient); - - if (err) { - *error = makeError(10, @(err->message)); - idevice_error_free(err); - return 10; - } - - return 0; + return 10; } @implementation JITEnableContext(DDI) - (NSUInteger)getMountedDeviceCount:(NSError**)error { - [self ensureHeartbeatWithError:error]; + [self ensureTunnelWithError:error]; if (*error) { return 0; } - return getMountedDeviceCount(provider, error); + return getMountedDeviceCount(adapter, handshake, error); } - (NSInteger)mountPersonalDDIWithImagePath:(NSString*)imagePath trustcachePath:(NSString*)trustcachePath manifestPath:(NSString*)manifestPath error:(NSError**)error { - [self ensureHeartbeatWithError:error]; - if (*error) { return 0; } - IdevicePairingFile *pairing = [self getPairingFileWithError:error]; + [self ensureTunnelWithError:error]; if (*error) { return 0; } - return mountPersonalDDI(provider, pairing, imagePath, trustcachePath, manifestPath, error); + return mountPersonalDDI(adapter, handshake, imagePath, trustcachePath, manifestPath, error); } @end diff --git a/StikJIT/idevice/process.m b/StikJIT/idevice/process.m index d1397810..62393901 100644 --- a/StikJIT/idevice/process.m +++ b/StikJIT/idevice/process.m @@ -12,20 +12,17 @@ // MARK: - Shared AppService session typedef struct { - AdapterHandle *adapter; - RsdHandshakeHandle *handshake; AppServiceHandle *appService; } AppServiceSession; static void app_service_session_free(AppServiceSession *s) { if (s->appService) { app_service_free(s->appService); s->appService = NULL; } - if (s->handshake) { rsd_handshake_free(s->handshake); s->handshake = NULL; } - if (s->adapter) { adapter_free(s->adapter); s->adapter = NULL; } } -// Connects to the device via CoreDeviceProxy → Adapter → RSD → AppService. +// Connects to the device via the existing adapter+handshake → AppService. // Returns 0 on success; cleans up any partial state and returns 1 on failure. -static int connect_app_service(IdeviceProviderHandle *provider, +static int connect_app_service(AdapterHandle *adapter, + RsdHandshakeHandle *handshake, AppServiceSession *out, JITEnableContext *ctx, NSError **outError) @@ -33,62 +30,11 @@ static int connect_app_service(IdeviceProviderHandle *provider, memset(out, 0, sizeof(*out)); IdeviceFfiError *ffiError = NULL; - CoreDeviceProxyHandle *coreProxy = NULL; - ffiError = core_device_proxy_connect(provider, &coreProxy); - if (ffiError) { - *outError = [ctx errorWithStr:[NSString stringWithUTF8String:ffiError->message ?: "Failed to connect CoreDeviceProxy"] - code:ffiError->code]; - idevice_error_free(ffiError); - return 1; - } - - uint16_t rsdPort = 0; - ffiError = core_device_proxy_get_server_rsd_port(coreProxy, &rsdPort); - if (ffiError) { - *outError = [ctx errorWithStr:[NSString stringWithUTF8String:ffiError->message ?: "Unable to resolve RSD port"] - code:ffiError->code]; - idevice_error_free(ffiError); - core_device_proxy_free(coreProxy); - return 1; - } - - ffiError = core_device_proxy_create_tcp_adapter(coreProxy, &out->adapter); - if (ffiError) { - *outError = [ctx errorWithStr:[NSString stringWithUTF8String:ffiError->message ?: "Failed to create adapter"] - code:ffiError->code]; - idevice_error_free(ffiError); - core_device_proxy_free(coreProxy); - return 1; - } - coreProxy = NULL; // ownership transferred to adapter - - AdapterStreamHandle *stream = NULL; - ffiError = adapter_connect(out->adapter, rsdPort, (ReadWriteOpaque **)&stream); - if (ffiError) { - *outError = [ctx errorWithStr:[NSString stringWithUTF8String:ffiError->message ?: "Adapter connect failed"] - code:ffiError->code]; - idevice_error_free(ffiError); - app_service_session_free(out); - return 1; - } - - ffiError = rsd_handshake_new((ReadWriteOpaque *)stream, &out->handshake); - if (ffiError) { - *outError = [ctx errorWithStr:[NSString stringWithUTF8String:ffiError->message ?: "RSD handshake failed"] - code:ffiError->code]; - idevice_error_free(ffiError); - adapter_stream_close(stream); - app_service_session_free(out); - return 1; - } - stream = NULL; // consumed by handshake - - ffiError = app_service_connect_rsd(out->adapter, out->handshake, &out->appService); + ffiError = app_service_connect_rsd(adapter, handshake, &out->appService); if (ffiError) { *outError = [ctx errorWithStr:[NSString stringWithUTF8String:ffiError->message ?: "Unable to open AppService"] code:ffiError->code]; idevice_error_free(ffiError); - app_service_session_free(out); return 1; } @@ -100,11 +46,11 @@ static int connect_app_service(IdeviceProviderHandle *provider, @implementation JITEnableContext(Process) - (NSArray*)fetchProcessesViaAppServiceWithError:(NSError **)error { - [self ensureHeartbeatWithError:error]; + [self ensureTunnelWithError:error]; if (*error) { return nil; } AppServiceSession session; - if (connect_app_service(provider, &session, self, error) != 0) { return nil; } + if (connect_app_service(adapter, handshake, &session, self, error) != 0) { return nil; } ProcessTokenC *processes = NULL; uintptr_t count = 0; @@ -138,7 +84,7 @@ @implementation JITEnableContext(Process) } - (NSArray*)_fetchProcessListLocked:(NSError**)error { - [self ensureHeartbeatWithError:error]; + [self ensureTunnelWithError:error]; if (*error) { return nil; } return [self fetchProcessesViaAppServiceWithError:error]; } @@ -156,11 +102,11 @@ @implementation JITEnableContext(Process) } - (BOOL)killProcessWithPID:(int)pid error:(NSError **)error { - [self ensureHeartbeatWithError:error]; + [self ensureTunnelWithError:error]; if (*error) { return NO; } AppServiceSession session; - if (connect_app_service(provider, &session, self, error) != 0) { return NO; } + if (connect_app_service(adapter, handshake, &session, self, error) != 0) { return NO; } SignalResponseC *signalResponse = NULL; IdeviceFfiError *ffiError = app_service_send_signal(session.appService, (uint32_t)pid, SIGKILL, &signalResponse); diff --git a/StikJIT/idevice/profiles.h b/StikJIT/idevice/profiles.h index 00f2e9ff..fa65d22a 100644 --- a/StikJIT/idevice/profiles.h +++ b/StikJIT/idevice/profiles.h @@ -9,9 +9,9 @@ #define PROFILES_H #include "idevice.h" #include -NSArray* _Nullable fetchAppProfiles(IdeviceProviderHandle* _Nonnull provider, NSError* _Nullable * _Nullable error); -bool removeProfile(IdeviceProviderHandle* _Nonnull provider, NSString* _Nonnull uuid, NSError* _Nullable * _Nullable error); -bool addProfile(IdeviceProviderHandle* _Nonnull provider, NSData* _Nonnull profile, NSError* _Nullable * _Nullable error); +NSArray* _Nullable fetchAppProfiles(AdapterHandle* _Nonnull adapter, RsdHandshakeHandle* _Nonnull handshake, NSError* _Nullable * _Nullable error); +bool removeProfile(AdapterHandle* _Nonnull adapter, RsdHandshakeHandle* _Nonnull handshake, NSString* _Nonnull uuid, NSError* _Nullable * _Nullable error); +bool addProfile(AdapterHandle* _Nonnull adapter, RsdHandshakeHandle* _Nonnull handshake, NSData* _Nonnull profile, NSError* _Nullable * _Nullable error); @interface CMSDecoderHelper : NSObject // Decode CMS/PKCS7 data and return decoded payload and any embedded certs diff --git a/StikJIT/idevice/profiles.m b/StikJIT/idevice/profiles.m index 107f99fb..a88abfb9 100644 --- a/StikJIT/idevice/profiles.m +++ b/StikJIT/idevice/profiles.m @@ -14,9 +14,9 @@ } -NSArray* fetchAppProfiles(IdeviceProviderHandle* provider, NSError** error) { +NSArray* fetchAppProfiles(AdapterHandle* adapter, RsdHandshakeHandle* handshake, NSError** error) { MisagentClientHandle *misagentHandle = NULL; - IdeviceFfiError *err = misagent_connect(provider, &misagentHandle); + IdeviceFfiError *err = misagent_connect_rsd(adapter, handshake, &misagentHandle); if (err) { *error = makeError(err->code, @(err->message)); idevice_error_free(err); @@ -50,9 +50,9 @@ return ans; } -bool removeProfile(IdeviceProviderHandle* provider, NSString* uuid, NSError** error) { +bool removeProfile(AdapterHandle* adapter, RsdHandshakeHandle* handshake, NSString* uuid, NSError** error) { MisagentClientHandle *misagentHandle = NULL; - IdeviceFfiError * err = misagent_connect(provider, &misagentHandle); + IdeviceFfiError * err = misagent_connect_rsd(adapter, handshake, &misagentHandle); if (err) { *error = makeError(err->code, @(err->message)); idevice_error_free(err); @@ -71,9 +71,9 @@ bool removeProfile(IdeviceProviderHandle* provider, NSString* uuid, NSError** er return true; } -bool addProfile(IdeviceProviderHandle* provider, NSData* profile, NSError** error) { +bool addProfile(AdapterHandle* adapter, RsdHandshakeHandle* handshake, NSData* profile, NSError** error) { MisagentClientHandle *misagentHandle = NULL; - IdeviceFfiError * err = misagent_connect(provider, &misagentHandle); + IdeviceFfiError * err = misagent_connect_rsd(adapter, handshake, &misagentHandle); if (err) { *error = makeError(err->code, @(err->message)); idevice_error_free(err); @@ -141,29 +141,29 @@ + (NSData*)decodeCMSData:(NSData *)cmsData @implementation JITEnableContext(Profile) - (NSArray*)fetchAllProfiles:(NSError **)error { - [self ensureHeartbeatWithError:error]; + [self ensureTunnelWithError:error]; if(*error) { return nil; } - return fetchAppProfiles(provider, error); + return fetchAppProfiles(adapter, handshake, error); } - (BOOL)removeProfileWithUUID:(NSString*)uuid error:(NSError **)error { - [self ensureHeartbeatWithError:error]; + [self ensureTunnelWithError:error]; if(*error) { return NO; } - return removeProfile(provider, uuid, error); + return removeProfile(adapter, handshake, uuid, error); } - (BOOL)addProfile:(NSData*)profile error:(NSError **)error { - [self ensureHeartbeatWithError:error]; + [self ensureTunnelWithError:error]; if(*error) { return NO; } - return addProfile(provider, profile, error); + return addProfile(adapter, handshake, profile, error); } diff --git a/StikJIT/idevice/syslog.m b/StikJIT/idevice/syslog.m index 3e36b012..b4b0dca3 100644 --- a/StikJIT/idevice/syslog.m +++ b/StikJIT/idevice/syslog.m @@ -14,7 +14,7 @@ - (void)startSyslogRelayWithHandler:(SyslogLineHandler)lineHandler onError:(SyslogErrorHandler)errorHandler { NSError* error = nil; - [self ensureHeartbeatWithError:&error]; + [self ensureTunnelWithError:&error]; if(error) { errorHandler(error); return; @@ -33,7 +33,7 @@ - (void)startSyslogRelayWithHandler:(SyslogLineHandler)lineHandler if (!strongSelf) { return; } SyslogRelayClientHandle *client = NULL; - IdeviceFfiError *err = syslog_relay_connect_tcp(strongSelf->provider, &client); + IdeviceFfiError *err = syslog_relay_connect_rsd(strongSelf->adapter, strongSelf->handshake, &client); if (err != NULL) { NSString *message = err->message ? [NSString stringWithCString:err->message encoding:NSASCIIStringEncoding] : @"Failed to connect to syslog relay"; NSError *nsError = [strongSelf errorWithStr:message code:err->code];