Skip to content

Commit c780843

Browse files
authored
Replace lockdown code with rppairing (#354)
1 parent f8697a0 commit c780843

25 files changed

Lines changed: 1786 additions & 648 deletions

StikJIT/StikJIT-Bridging-Header.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
#include "idevice/JITEnableContext.h"
66
#import "Utilities/ProcessInspectorBridge.h"
77
#include "idevice/idevice.h"
8-
#include "idevice/heartbeat.h"
98
#include "JSSupport/JSSupport.h"
109
#include "idevice/ideviceinfo.h"
1110
#include "idevice/location_simulation.h"

StikJIT/StikJITApp.swift

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -117,17 +117,17 @@ class DNSChecker: ObservableObject {
117117

118118
// MARK: - Main App
119119

120-
// Global state variable for the heartbeat response.
121-
var pubHeartBeat = false
122-
private var heartbeatStartPending = false
123-
private var heartbeatStartInProgress = false
124-
private var heartbeatPendingShowUI = true
120+
// Global state variable for the tunnel connection.
121+
var pubTunnelConnected = false
122+
private var tunnelStartPending = false
123+
private var tunnelStartInProgress = false
124+
private var tunnelPendingShowUI = true
125125

126126
@main
127127
struct HeartbeatApp: App {
128128
@StateObject private var mount = MountingProgress.shared
129129
@Environment(\.scenePhase) private var scenePhase // Observe scene lifecycle
130-
@State private var shouldAttemptHeartbeatRestart = false
130+
@State private var shouldAttemptTunnelReconnect = false
131131

132132
init() {
133133
registerAdvancedOptionsDefault()
@@ -144,11 +144,11 @@ struct HeartbeatApp: App {
144144
private func handleScenePhaseChange(_ newPhase: ScenePhase) {
145145
switch newPhase {
146146
case .background:
147-
shouldAttemptHeartbeatRestart = true
147+
shouldAttemptTunnelReconnect = true
148148
case .active:
149-
if shouldAttemptHeartbeatRestart {
150-
shouldAttemptHeartbeatRestart = false
151-
startHeartbeatInBackground(showErrorUI: false)
149+
if shouldAttemptTunnelReconnect {
150+
shouldAttemptTunnelReconnect = false
151+
startTunnelInBackground(showErrorUI: false)
152152
}
153153
default:
154154
break
@@ -270,42 +270,42 @@ class MountingProgress: ObservableObject {
270270

271271
func isPairing() -> Bool {
272272
let pairingpath = URL.documentsDirectory.appendingPathComponent("pairingFile.plist").path
273-
var pairingFile: IdevicePairingFile?
274-
let err = idevice_pairing_file_read(pairingpath, &pairingFile)
273+
var pairingFile: RpPairingFileHandle?
274+
let err = rp_pairing_file_read(pairingpath, &pairingFile)
275275
if err != nil { return false }
276-
idevice_pairing_file_free(pairingFile)
276+
rp_pairing_file_free(pairingFile)
277277
return true
278278
}
279279

280-
func startHeartbeatInBackground(showErrorUI: Bool = true) {
281-
assert(Thread.isMainThread, "startHeartbeatInBackground must be called on the main thread")
280+
func startTunnelInBackground(showErrorUI: Bool = true) {
281+
assert(Thread.isMainThread, "startTunnelInBackground must be called on the main thread")
282282
let pairingFileURL = URL.documentsDirectory.appendingPathComponent("pairingFile.plist")
283-
283+
284284
guard FileManager.default.fileExists(atPath: pairingFileURL.path) else {
285-
heartbeatStartPending = false
286-
heartbeatPendingShowUI = true
285+
tunnelStartPending = false
286+
tunnelPendingShowUI = true
287287
return
288288
}
289-
290-
guard !heartbeatStartInProgress else {
289+
290+
guard !tunnelStartInProgress else {
291291
return
292292
}
293-
294-
heartbeatStartPending = false
295-
heartbeatPendingShowUI = true
296-
heartbeatStartInProgress = true
297-
293+
294+
tunnelStartPending = false
295+
tunnelPendingShowUI = true
296+
tunnelStartInProgress = true
297+
298298
DispatchQueue.global(qos: .userInteractive).async {
299299
defer {
300300
DispatchQueue.main.async {
301-
heartbeatStartInProgress = false
301+
tunnelStartInProgress = false
302302
}
303303
}
304304
do {
305-
try JITEnableContext.shared.startHeartbeat()
306-
LogManager.shared.addInfoLog("Heartbeat started successfully")
307-
pubHeartBeat = true
308-
305+
try JITEnableContext.shared.startTunnel()
306+
LogManager.shared.addInfoLog("Tunnel connected successfully")
307+
pubTunnelConnected = true
308+
309309
DispatchQueue.main.async {
310310
let trustcachePath = URL.documentsDirectory.appendingPathComponent("DDI/Image.dmg.trustcache").path
311311
guard FileManager.default.fileExists(atPath: trustcachePath),
@@ -326,7 +326,7 @@ func startHeartbeatInBackground(showErrorUI: Bool = true) {
326326
} catch {
327327
LogManager.shared.addErrorLog("Failed to remove invalid pairing file: \(error.localizedDescription)")
328328
}
329-
329+
330330
showAlert(
331331
title: "Invalid Pairing File",
332332
message: "The pairing file is invalid or expired. Please select a new pairing file.",
@@ -338,14 +338,14 @@ func startHeartbeatInBackground(showErrorUI: Bool = true) {
338338
}
339339
} else {
340340
showAlert(
341-
title: "Heartbeat Error",
341+
title: "Connection Error",
342342
message: "\(error.localizedDescription)\n\nMake sure Wi‑Fi and LocalDevVPN are connected and that the device is reachable.",
343343
showOk: false,
344344
showTryAgain: true
345345
) { shouldTryAgain in
346346
if shouldTryAgain {
347347
DispatchQueue.main.async {
348-
startHeartbeatInBackground()
348+
startTunnelInBackground()
349349
}
350350
}
351351
}

StikJIT/Utilities/DeviceInfoManager.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ final class DeviceInfoManager: ObservableObject {
3030
busy = true
3131
Task.detached {
3232
do {
33-
try JITEnableContext.shared.ensureHeartbeat()
33+
try JITEnableContext.shared.ensureTunnel()
3434
} catch {
3535
await MainActor.run {
3636
self.error = ("Initialization Failed", error.localizedDescription)

StikJIT/Utilities/Intents.swift

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ struct InstalledAppQuery: EntityStringQuery {
3838
}
3939

4040
func suggestedEntities() async throws -> [InstalledAppEntity] {
41-
await ensureHeartbeat()
41+
await ensureTunnel()
4242
let allApps = (try? JITEnableContext.shared.getAppList()) ?? [:]
4343
return allApps.map { InstalledAppEntity(id: $0.key, displayName: $0.value) }
4444
.sorted { $0.displayName.localizedCaseInsensitiveCompare($1.displayName) == .orderedAscending }
@@ -94,7 +94,7 @@ struct RunningProcessEntity: AppEntity {
9494
struct RunningProcessQuery: EntityStringQuery {
9595
func entities(for identifiers: [String]) async throws -> [RunningProcessEntity] {
9696
// Always fetch fresh so PIDs are current
97-
await ensureHeartbeat()
97+
await ensureTunnel()
9898
let all = try fetchProcessEntities()
9999
let idSet = Set(identifiers)
100100
return all.filter { idSet.contains($0.id) }
@@ -112,7 +112,7 @@ struct RunningProcessQuery: EntityStringQuery {
112112
}
113113

114114
func suggestedEntities() async throws -> [RunningProcessEntity] {
115-
await ensureHeartbeat()
115+
await ensureTunnel()
116116
return try fetchProcessEntities()
117117
}
118118

@@ -172,7 +172,7 @@ struct EnableJITIntent: AppIntent, ForegroundContinuableIntent {
172172
return .result(value: "Select an app to enable JIT for.")
173173
}
174174

175-
await ensureHeartbeat()
175+
await ensureTunnel()
176176

177177
var scriptData: Data? = nil
178178
var scriptName: String? = nil
@@ -250,9 +250,9 @@ struct KillProcessIntent: AppIntent {
250250
if let pid {
251251
targetPID = pid
252252
targetName = "PID \(pid)"
253-
await ensureHeartbeat()
253+
await ensureTunnel()
254254
} else if let process {
255-
await ensureHeartbeat()
255+
await ensureTunnel()
256256

257257
// Always re-resolve to get the current PID — the stored one may be stale
258258
guard let resolved = process.resolveCurrentPID() else {
@@ -313,12 +313,12 @@ struct StikDebugShortcuts: AppShortcutsProvider {
313313
}
314314
}
315315

316-
// MARK: - Shared Heartbeat Helper
316+
// MARK: - Shared Tunnel Helper
317317

318-
func ensureHeartbeat() async {
318+
func ensureTunnel() async {
319319
await MainActor.run {
320-
pubHeartBeat = false
321-
startHeartbeatInBackground(showErrorUI: false)
320+
pubTunnelConnected = false
321+
startTunnelInBackground(showErrorUI: false)
322322
}
323323
try? await Task.sleep(nanoseconds: 1_000_000_000)
324324
}

StikJIT/Utilities/mountDDI.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@
77

88
import Foundation
99

10-
typealias IdevicePairingFile = OpaquePointer
11-
typealias TcpProviderHandle = OpaquePointer
12-
typealias CoreDeviceProxyHandle = OpaquePointer
10+
typealias RpPairingFileHandle = OpaquePointer
1311
typealias AdapterHandle = OpaquePointer
12+
typealias RsdHandshakeHandle = OpaquePointer
1413
typealias ImageMounterHandle = OpaquePointer
1514
typealias LockdowndClientHandle = OpaquePointer
1615

StikJIT/Views/HomeView.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ struct HomeView: View {
4040
startJITInBackground(bundleID: selectedBundle)
4141
}, showDoneButton: false, onImportPairingFile: { isShowingPairingFilePicker = true })
4242
.onAppear {
43-
startHeartbeatInBackground()
43+
startTunnelInBackground()
4444
MountingProgress.shared.checkforMounted()
4545
viewDidAppeared = true
4646
if let config = pendingJITEnableConfiguration {
@@ -94,8 +94,8 @@ struct HomeView: View {
9494
}
9595
case "kill-process":
9696
if let pidStr = components?.queryItems?.first(where: { $0.name == "pid" })?.value, let pid = Int(pidStr) {
97-
pubHeartBeat = false
98-
startHeartbeatInBackground(showErrorUI: false)
97+
pubTunnelConnected = false
98+
startTunnelInBackground(showErrorUI: false)
9999
DispatchQueue.global(qos: .userInitiated).async {
100100
sleep(1)
101101
do {
@@ -133,10 +133,10 @@ struct HomeView: View {
133133
try fileManager.removeItem(at: dest)
134134
}
135135
try fileManager.copyItem(at: url, to: dest)
136-
pubHeartBeat = false
137-
startHeartbeatInBackground()
136+
pubTunnelConnected = false
137+
startTunnelInBackground()
138138
NotificationCenter.default.post(name: .pairingFileImported, object: nil)
139-
// Dismiss any existing heartbeat error alert
139+
// Dismiss any existing connection error alert
140140
if let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
141141
let root = scene.windows.first?.rootViewController {
142142
var top = root
@@ -268,8 +268,8 @@ struct HomeView: View {
268268
BackgroundLocationManager.shared.requestStart()
269269

270270
if triggeredByURLScheme {
271-
pubHeartBeat = false
272-
startHeartbeatInBackground(showErrorUI: false)
271+
pubTunnelConnected = false
272+
startTunnelInBackground(showErrorUI: false)
273273
}
274274

275275
DispatchQueue.global(qos: .background).async {

StikJIT/Views/SettingsView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ struct SettingsView: View {
224224

225225
RunLoop.current.add(progressTimer, forMode: .common)
226226
DispatchQueue.main.async {
227-
startHeartbeatInBackground()
227+
startTunnelInBackground()
228228
}
229229

230230
} catch { }

StikJIT/idevice/JITEnableContext.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,35 +8,35 @@
88
@import UIKit;
99
#include "idevice.h"
1010
#include "jit.h"
11-
#include "heartbeat.h"
1211
#include "mount.h"
1312

14-
typedef void (^HeartbeatCompletionHandler)(int result, NSString *message);
1513
typedef void (^LogFuncC)(const char* message, ...);
1614
typedef void (^LogFunc)(NSString *message);
1715
typedef void (^SyslogLineHandler)(NSString *line);
1816
typedef void (^SyslogErrorHandler)(NSError *error);
1917

2018
@interface JITEnableContext : NSObject {
19+
// tunnel
20+
@protected AdapterHandle *adapter;
21+
@protected RsdHandshakeHandle *handshake;
22+
2123
// process
2224
@protected dispatch_queue_t processInspectorQueue;
23-
@protected IdeviceProviderHandle* provider;
24-
25+
2526
// syslog
2627
@protected dispatch_queue_t syslogQueue;
2728
@protected BOOL syslogStreaming;
2829
@protected SyslogRelayClientHandle *syslogClient;
2930
@protected SyslogLineHandler syslogLineHandler;
3031
@protected SyslogErrorHandler syslogErrorHandler;
31-
32+
3233
// ideviceInfo
3334
@protected LockdowndClientHandle * g_client;
3435
}
3536
@property (class, readonly)JITEnableContext* shared;
36-
- (IdevicePairingFile*)getPairingFileWithError:(NSError**)error;
37-
- (IdeviceProviderHandle*)getTcpProviderHandle;
38-
- (BOOL)ensureHeartbeatWithError:(NSError**)err;
39-
- (BOOL)startHeartbeat:(NSError**)err;
37+
- (RpPairingFileHandle*)getPairingFileWithError:(NSError**)error;
38+
- (BOOL)ensureTunnelWithError:(NSError**)err;
39+
- (BOOL)startTunnel:(NSError**)err;
4040

4141
@end
4242

0 commit comments

Comments
 (0)