fix: handle legacy and cryptex DDI service discovery

This commit is contained in:
CelloSerenity 2026-10-14 23:26:00 -04:00
parent cd5e609387
commit 734361bb9d
3 changed files with 54 additions and 49 deletions

View file

@ -39,7 +39,8 @@ private enum IdeviceBridge {
}
let code = Int(ffiError.pointee.code)
let message = string(from: ffiError.pointee.message) ?? fallback
let detail = string(from: ffiError.pointee.message) ?? fallback
let message = detail == fallback ? fallback : "\(fallback): \(detail)"
idevice_error_free(ffiError)
return makeError(domain: domain, code: code, message: message)
}
@ -264,45 +265,50 @@ private enum IdeviceBridge {
extension JITEnableContext {
func isDeveloperDiskImageMounted() throws -> Bool {
try IdeviceBridge.withTunnelHandles(for: self) { adapter, handshake in
var installed: UnsafeMutablePointer<InstalledCryptexC>?
let ffiError = cryptexd_installed_ddi(adapter, handshake, &installed)
let queryError = ffiError.map {
IdeviceBridge.consumeFFIError($0, fallback: "Failed to query installed DDI cryptex")
}
defer { cryptexd_free_installed_cryptex(installed) }
if installed != nil {
return true
var cryptexQuerySucceeded = false
var cryptexQueryError: NSError?
if DeveloperDiskImageService.usesCryptexDDI {
var installed: UnsafeMutablePointer<InstalledCryptexC>?
defer { cryptexd_free_installed_cryptex(installed) }
if let ffiError = cryptexd_installed_ddi(adapter, handshake, &installed) {
cryptexQueryError = IdeviceBridge.consumeFFIError(ffiError, fallback: "Failed to query installed DDI cryptex")
} else {
cryptexQuerySucceeded = true
if installed != nil {
return true
}
}
}
let legacyMounted = (try? IdeviceBridge.withConnectedClient(
fallback: "Failed to connect to image mounter",
missingClientMessage: "Image mounter client was not created",
connect: { image_mounter_connect_rsd(adapter, handshake, $0) },
cleanup: { image_mounter_free($0) }
) { client in
var devices: UnsafeMutablePointer<plist_t?>?
var deviceCount = 0
if let error = image_mounter_copy_devices(client, &devices, &deviceCount) {
throw IdeviceBridge.consumeFFIError(error, fallback: "Failed to fetch mounted devices")
}
if let devices {
for index in 0..<deviceCount {
plist_free(devices[index])
do {
return try IdeviceBridge.withConnectedClient(
fallback: "Failed to connect to image mounter",
missingClientMessage: "Image mounter client was not created",
connect: { image_mounter_connect_rsd(adapter, handshake, $0) },
cleanup: { image_mounter_free($0) }
) { client in
var devices: UnsafeMutablePointer<plist_t?>?
var deviceCount = 0
if let error = image_mounter_copy_devices(client, &devices, &deviceCount) {
throw IdeviceBridge.consumeFFIError(error, fallback: "Failed to fetch mounted devices")
}
idevice_data_free(
UnsafeMutableRawPointer(devices).assumingMemoryBound(to: UInt8.self),
UInt(deviceCount * MemoryLayout<plist_t?>.stride)
)
if let devices {
for index in 0..<deviceCount {
plist_free(devices[index])
}
idevice_data_free(
UnsafeMutableRawPointer(devices).assumingMemoryBound(to: UInt8.self),
UInt(deviceCount * MemoryLayout<plist_t?>.stride)
)
}
return deviceCount > 0
}
return deviceCount > 0
}) ?? false
if legacyMounted {
return true
} catch {
if cryptexQuerySucceeded {
return false
}
throw cryptexQueryError ?? (error as NSError)
}
if let queryError {
throw queryError
}
return false
}
}

View file

@ -117,7 +117,8 @@ final class JITEnableContext {
guard let ffiError else {
return makeError(fallback)
}
let message = nsString(from: ffiError.pointee.message, fallback: fallback)
let detail = nsString(from: ffiError.pointee.message, fallback: fallback)
let message = detail == fallback ? fallback : "\(fallback): \(detail)"
let error = makeError(message, code: Int(ffiError.pointee.code))
idevice_error_free(ffiError)
return error
@ -457,22 +458,19 @@ final class JITEnableContext {
private func withConnectedRemoteServer<T>(
_ body: (OpaquePointer) throws -> T
) throws -> T {
try ensureTunnel()
guard let adapter, let handshake else {
throw makeError("Tunnel is not connected")
}
try withFreshDebugTunnel(hostname: "StikDebugRemoteServer") { adapter, handshake in
var remoteServer: OpaquePointer?
if let ffiError = remote_server_connect_rsd(adapter, handshake, &remoteServer) {
throw error(from: ffiError, fallback: "Failed to connect remote server")
}
var remoteServer: OpaquePointer?
if let ffiError = remote_server_connect_rsd(adapter, handshake, &remoteServer) {
throw error(from: ffiError, fallback: "Failed to connect remote server")
}
guard let remoteServer else {
throw makeError("Remote server handle was not created")
}
guard let remoteServer else {
throw makeError("Remote server handle was not created")
defer { remote_server_free(remoteServer) }
return try body(remoteServer)
}
defer { remote_server_free(remoteServer) }
return try body(remoteServer)
}
private func withProcessControl<T>(

View file

@ -27,6 +27,7 @@ func checkMountStatus() -> MountCheckResult {
do {
return try JITEnableContext.shared.isDeveloperDiskImageMounted() ? .mounted : .notMounted
} catch {
LogManager.shared.addErrorLog("Failed to check DDI mount status: \(error.localizedDescription)")
return .unreachable
}
}