Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 121 additions & 7 deletions StikJIT/StikJITApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,77 @@

import SwiftUI
import em_proxy
import UniformTypeIdentifiers

@main
struct HeartbeatApp: App {
@State private var isLoading = true
@State private var isPairing = false
@State private var heartBeat = false
@State private var error: Int32? = nil

init() {
let fixMethod = class_getInstanceMethod(UIDocumentPickerViewController.self, #selector(UIDocumentPickerViewController.fix_init(forOpeningContentTypes:asCopy:)))!
let origMethod = class_getInstanceMethod(UIDocumentPickerViewController.self, #selector(UIDocumentPickerViewController.init(forOpeningContentTypes:asCopy:)))!
method_exchangeImplementations(origMethod, fixMethod)
}

var body: some Scene {
WindowGroup {
if isLoading {
LoadingView()
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
withAnimation(.easeInOut(duration: 1.0)) {
isLoading = false
}
}
startProxy()
if FileManager.default.fileExists(atPath: URL.documentsDirectory.appendingPathComponent("pairingFile.plist").path) {
Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { timer in
if heartBeat {
isLoading = false
timer.invalidate()
} else {
if let error {
if error == InvalidHostID.rawValue {
isPairing = true
} else {
startHeartbeatInBackground()
}
self.error = nil
}
}
}

startHeartbeatInBackground()
} else {
isLoading = false
}
}
.fileImporter(isPresented: $isPairing, allowedContentTypes: [UTType(filenameExtension: "mobiledevicepairing", conformingTo: .data)!, .propertyList]) {result in
switch result {

case .success(let url):
let fileManager = FileManager.default
let accessing = url.startAccessingSecurityScopedResource()

if fileManager.fileExists(atPath: url.path) {
do {
if fileManager.fileExists(atPath: URL.documentsDirectory.appendingPathComponent("pairingFile.plist").path) {
try fileManager.removeItem(at: URL.documentsDirectory.appendingPathComponent("pairingFile.plist"))
}

try fileManager.copyItem(at: url, to: URL.documentsDirectory.appendingPathComponent("pairingFile.plist"))
print("File copied successfully!")
startHeartbeatInBackground()
} catch {
print("Error copying file: \(error)")
}
} else {
print("Source file does not exist.")
}

if accessing {
url.stopAccessingSecurityScopedResource()
}
case .failure(_):
print("Failed")
}
}
} else {
Expand All @@ -50,16 +103,57 @@ struct HeartbeatApp: App {
}
}
}

func startHeartbeatInBackground() {
let heartBeat = Thread {
let cCompletionHandler: @convention(block) (Int32, UnsafePointer<CChar>?) -> Void = { result, messagePointer in
let message: String? = messagePointer != nil ? String(cString: messagePointer!) : nil

if result == 0 {
print("Heartbeat started successfully: \(message ?? "")")

self.heartBeat = true
} else {
print("Error: \(result == InvalidHostID.rawValue ? "Invalid host ID, Please Selecr New Pairing File" : message ?? "") (Code: \(result))")

showAlert(title: "HeartBeat Error", message: "\(message ?? "") (\(result))", showOk: true) { _ in
self.error = result
}
}
}

startHeartbeat(cCompletionHandler)
}

heartBeat.qualityOfService = .background
heartBeat.name = "HeartBeat"
heartBeat.start()
}

}


func startHeartbeatInBackground() {
let heartBeat = Thread {
startHeartbeat()
let cCompletionHandler: @convention(block) (Int32, UnsafePointer<CChar>?) -> Void = { result, messagePointer in
let message: String? = messagePointer != nil ? String(cString: messagePointer!) : nil

if result == 0 {
print("Heartbeat started successfully: \(message ?? "")")
} else {
print("Error: \(message ?? "") (Code: \(result))")

showAlert(title: "HeartBeat Error", message: "\(message ?? "") (\(result))", showOk: true) { _ in
startHeartbeatInBackground()
}
}
}

startHeartbeat(cCompletionHandler)
}

heartBeat.qualityOfService = .background
heartBeat.name = "HeartBeat"
heartBeat.name = "Heartbeat"
heartBeat.start()
}

Expand Down Expand Up @@ -106,3 +200,23 @@ struct LoadingView: View {
}
}
}

public func showAlert(title: String, message: String, showOk: Bool, completion: @escaping (Bool) -> Void) {
DispatchQueue.main.async {
if let mainWindow = UIApplication.shared.windows.last {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)

if showOk {
let okAction = UIAlertAction(title: "OK", style: .default) { _ in
completion(true)
}

alert.addAction(okAction)
} else {
completion(false)
}

mainWindow.rootViewController?.present(alert, animated: true, completion: nil)
}
}
}
9 changes: 8 additions & 1 deletion StikJIT/Views/HomeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@
//

import SwiftUI
import UniformTypeIdentifiers

extension UIDocumentPickerViewController {
@objc func fix_init(forOpeningContentTypes contentTypes: [UTType], asCopy: Bool) -> UIDocumentPickerViewController {
return fix_init(forOpeningContentTypes: contentTypes, asCopy: true)
}
}

struct HomeView: View {
@AppStorage("username") private var username = "User"
Expand Down Expand Up @@ -61,7 +68,7 @@ struct HomeView: View {
.onReceive(timer) { _ in
refreshBackground()
}
.fileImporter(isPresented: $isShowingPairingFilePicker, allowedContentTypes: [.item]) {result in
.fileImporter(isPresented: $isShowingPairingFilePicker, allowedContentTypes: [UTType(filenameExtension: "mobiledevicepairing", conformingTo: .data)!, .propertyList]) {result in
switch result {

case .success(let url):
Expand Down
3 changes: 2 additions & 1 deletion StikJIT/Views/SettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//

import SwiftUI
import UniformTypeIdentifiers

struct SettingsView: View {
@AppStorage("username") private var username = "User"
Expand Down Expand Up @@ -111,7 +112,7 @@ struct SettingsView: View {
.font(.bodyFont)
.accentColor(.accentColor)
}
.fileImporter(isPresented: $isShowingPairingFilePicker, allowedContentTypes: [.item]) {result in
.fileImporter(isPresented: $isShowingPairingFilePicker, allowedContentTypes: [UTType(filenameExtension: "mobiledevicepairing", conformingTo: .data)!, .propertyList]) {result in
switch result {

case .success(let url):
Expand Down
9 changes: 8 additions & 1 deletion StikJIT/idevice/heartbeat.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
#include <CoreFoundation/CoreFoundation.h>
#include <limits.h>

void startHeartbeat() {
typedef void (^HeartbeatCompletionHandler)(int result, const char *message);

void startHeartbeat(HeartbeatCompletionHandler completion) {
printf("DEBUG: Initializing logger...\n");
idevice_init_logger(Debug, Disabled, NULL);

Expand Down Expand Up @@ -43,6 +45,7 @@ void startHeartbeat() {
IdeviceErrorCode err = idevice_pairing_file_read(pairingFilePath, &pairing_file);
if (err != IdeviceSuccess) {
fprintf(stderr, "DEBUG: Failed to read pairing file: %d\n", err);
completion(err, "Failed to read pairing file");
return;
}
printf("DEBUG: Pairing file read successfully.\n");
Expand All @@ -54,6 +57,7 @@ void startHeartbeat() {
if (err != IdeviceSuccess) {
fprintf(stderr, "DEBUG: Failed to create TCP provider: %d\n", err);
idevice_pairing_file_free(pairing_file);
completion(err, "Failed to create TCP provider");
return;
}
printf("DEBUG: TCP provider created successfully.\n");
Expand All @@ -62,12 +66,15 @@ void startHeartbeat() {
HeartbeatClientHandle *client = NULL;
err = heartbeat_connect_tcp(provider, &client);
if (err != IdeviceSuccess) {
completion(err, "Failed to connect to Heartbeat");
fprintf(stderr, "DEBUG: Failed to connect to installation proxy: %d\n", err);
return;
}
tcp_provider_free(provider);
printf("DEBUG: Connected to installation proxy successfully.\n");

completion(0, "Heartbeat Completed");

u_int64_t current_interval = 15;
while (1) {
u_int64_t new_interval = 0;
Expand Down
4 changes: 3 additions & 1 deletion StikJIT/idevice/heartbeat.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#ifndef HEARTBEAT_H
#define HEARTBEAT_H

void startHeartbeat();
typedef void (^HeartbeatCompletionHandler)(int result, const char *message);

void startHeartbeat(HeartbeatCompletionHandler completion);

#endif /* HEARTBEAT_H */