mirror of
https://github.com/iDescriptor/iDescriptor.git
synced 2026-06-21 19:35:49 +08:00
respect env var "USBMUXD_PAIRING_FILES_LOCATION", fix get_pairing_files on macos, fix device cleanup bugs
This commit is contained in:
+23
-14
@@ -38,7 +38,27 @@ AppContext::AppContext(QObject *parent) : QObject{parent}
|
||||
void AppContext::cachePairedDevices()
|
||||
{
|
||||
|
||||
#ifndef __APPLE__
|
||||
m_pairingFileCache = core->get_pairing_files();
|
||||
#else
|
||||
QMap<QString, QString> maybeStalePairingFiles =
|
||||
SettingsManager::sharedInstance()->getAllIdeviceDefaultPairingFiles();
|
||||
|
||||
for (const QString &mac : maybeStalePairingFiles.keys()) {
|
||||
const QString path = maybeStalePairingFiles.value(mac);
|
||||
qDebug() << "Using pairing file" << path << "for MAC:" << mac
|
||||
<< "cached from settings";
|
||||
m_pairingFileCache[mac] = QVariant(path);
|
||||
}
|
||||
QMap<QString, QVariant> fresh = core->get_pairing_files();
|
||||
for (const QString &mac : fresh.keys()) {
|
||||
const QString path = fresh.value(mac).toString();
|
||||
qDebug() << "Using fresh pairing file" << path << "for MAC:" << mac
|
||||
<< "from backend";
|
||||
m_pairingFileCache[mac] = QVariant(path);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void AppContext::addDevice(iDescriptor::Uniq uniq,
|
||||
@@ -361,22 +381,11 @@ void AppContext::tryToConnectToNetworkDevice(const NetworkDevice &device)
|
||||
qDebug() << "No pairing file cached for device with MAC:"
|
||||
<< device.macAddress
|
||||
<< "Emitting noPairingFileForWirelessDevice event";
|
||||
emitNoPairingFileForWirelessDevice(device.macAddress);
|
||||
emit noPairingFileForWirelessDevice(device.macAddress);
|
||||
return;
|
||||
}
|
||||
core->init_wireless_device(device.address,
|
||||
LOCKDOWN_PATH + QString("/") + pairing_file,
|
||||
device.macAddress);
|
||||
}
|
||||
|
||||
void AppContext::emitNoPairingFileForWirelessDevice(const QString &udid)
|
||||
{
|
||||
emit noPairingFileForWirelessDevice(udid);
|
||||
}
|
||||
|
||||
void AppContext::emitInitStarted(const QString &macAddress)
|
||||
{
|
||||
emit initStarted(macAddress);
|
||||
core->init_wireless_device(device.address, pairing_file, device.macAddress);
|
||||
emit initStarted(device.macAddress);
|
||||
}
|
||||
|
||||
void AppContext::handlePairing(iDescriptor::Uniq uniq, bool timeout)
|
||||
|
||||
@@ -57,8 +57,6 @@ public:
|
||||
const DeviceSelection &getCurrentDeviceSelection() const;
|
||||
const iDescriptorDevice *
|
||||
getDeviceByMacAddress(const QString &macAddress) const;
|
||||
void emitNoPairingFileForWirelessDevice(const QString &udid);
|
||||
void emitInitStarted(const QString &macAddress);
|
||||
|
||||
private:
|
||||
QMap<QString, std::shared_ptr<iDescriptorDevice>> m_devices;
|
||||
|
||||
+1
-23
@@ -411,29 +411,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
|
||||
|
||||
return;
|
||||
}
|
||||
qDebug() << "Trying to add network device with MAC:"
|
||||
<< device.macAddress;
|
||||
|
||||
QString pairing_file =
|
||||
AppContext::sharedInstance()->getCachedPairingFile(
|
||||
device.macAddress);
|
||||
|
||||
if (pairing_file.isEmpty()) {
|
||||
qDebug() << "No pairing file cached for device with MAC:"
|
||||
<< device.macAddress
|
||||
<< "Emitting noPairingFileForWirelessDevice event";
|
||||
AppContext::sharedInstance()
|
||||
->emitNoPairingFileForWirelessDevice(device.macAddress);
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "Found cached pairing file for device with MAC:"
|
||||
<< device.macAddress << "IP:" << device.address
|
||||
<< "Initializing wireless connection";
|
||||
AppContext::sharedInstance()->core->init_wireless_device(
|
||||
device.address, LOCKDOWN_PATH + QString("/") + pairing_file,
|
||||
device.macAddress);
|
||||
AppContext::sharedInstance()->emitInitStarted(device.macAddress);
|
||||
AppContext::sharedInstance()->tryToConnectToNetworkDevice(device);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -165,9 +165,15 @@ NetworkDevicesToConnectWidget::NetworkDevicesToConnectWidget(QWidget *parent)
|
||||
|
||||
updateDeviceList();
|
||||
|
||||
// in case the backend fails to find pairing file
|
||||
connect(AppContext::sharedInstance()->core, &CXX::Core::no_pairing_file,
|
||||
this,
|
||||
&NetworkDevicesToConnectWidget::onNoPairingFileForWirelessDevice);
|
||||
|
||||
connect(AppContext::sharedInstance(),
|
||||
&AppContext::noPairingFileForWirelessDevice, this,
|
||||
&NetworkDevicesToConnectWidget::onNoPairingFileForWirelessDevice);
|
||||
|
||||
connect(AppContext::sharedInstance()->core, &CXX::Core::init_failed, this,
|
||||
&NetworkDevicesToConnectWidget::onDeviceInitFailed);
|
||||
connect(AppContext::sharedInstance(), &AppContext::initStarted, this,
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int kind; // 1 = connected, 2 = disconnected, 3 = pairing pending, 4 =
|
||||
// pairing failed
|
||||
char *udid;
|
||||
} IdeviceEvent;
|
||||
|
||||
typedef void (*IdeviceEventCallback)(const IdeviceEvent *event);
|
||||
|
||||
void idevice_event_subscribe(IdeviceEventCallback cb);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,14 +1,12 @@
|
||||
use crate::{APP_DEVICE_STATE, RUNTIME, VIDEO_STREAMS, afc, run_sync, utils};
|
||||
use cxx_qt::{CxxQtType, Threading};
|
||||
use cxx_qt_lib::{QByteArray, QMap, QMapPair_QString_QVariant, QString};
|
||||
use idevice::{
|
||||
afc::{AfcClient, opcode::AfcFopenMode},
|
||||
};
|
||||
use idevice::afc::{AfcClient, opcode::AfcFopenMode};
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
|
||||
use tokio::{
|
||||
io::{AsyncReadExt},
|
||||
io::AsyncReadExt,
|
||||
net::TcpListener,
|
||||
sync::{Mutex, oneshot},
|
||||
};
|
||||
@@ -239,11 +237,11 @@ impl qobject::HauseArrest {
|
||||
|
||||
fn start_video_stream(&self, file_path: &QString) -> QString {
|
||||
let afc_opt = self.rust().afc_handle.clone();
|
||||
|
||||
let Some(afc) = afc_opt else {
|
||||
eprintln!("HouseArrest: AfcClient not initialized");
|
||||
return QString::default();
|
||||
};
|
||||
|
||||
let Some(afc) = afc_opt else {
|
||||
eprintln!("HouseArrest: AfcClient not initialized");
|
||||
return QString::default();
|
||||
};
|
||||
|
||||
let udid_str = self.udid.to_string();
|
||||
let path_str = file_path.to_string();
|
||||
|
||||
+77
-62
@@ -18,8 +18,8 @@ use std::future::Future;
|
||||
use std::sync::mpsc;
|
||||
use std::thread;
|
||||
use tokio::runtime::{Builder, Runtime};
|
||||
use tokio::task::JoinHandle;
|
||||
use tokio::sync::oneshot;
|
||||
use tokio::task::JoinHandle;
|
||||
|
||||
use core::pin::Pin;
|
||||
use cxx_qt::Threading;
|
||||
@@ -27,16 +27,14 @@ use cxx_qt_lib::{QMap, QMapPair_QString_QVariant, QString, QVariant};
|
||||
|
||||
use crate::qobject::Core;
|
||||
use once_cell::sync::Lazy;
|
||||
use plist::{Value};
|
||||
mod afc_services;
|
||||
mod image_loader;
|
||||
mod service_manager;
|
||||
mod screenshot;
|
||||
mod utils;
|
||||
mod hause_arrest;
|
||||
use plist::Value;
|
||||
mod afc;
|
||||
mod afc_services;
|
||||
mod hause_arrest;
|
||||
mod io_manager;
|
||||
|
||||
mod screenshot;
|
||||
mod service_manager;
|
||||
mod utils;
|
||||
|
||||
const POSSIBLE_ROOT: &str = "../../../../";
|
||||
const APP_LABEL: &str = "iDescriptor";
|
||||
@@ -80,7 +78,6 @@ static RUNTIME: Lazy<Runtime> = Lazy::new(|| {
|
||||
static VIDEO_STREAMS: Lazy<std::sync::Mutex<HashMap<String, oneshot::Sender<()>>>> =
|
||||
Lazy::new(|| std::sync::Mutex::new(HashMap::new()));
|
||||
|
||||
|
||||
pub fn run_sync<F, R>(fut: F) -> R
|
||||
where
|
||||
F: Future<Output = R> + Send + 'static,
|
||||
@@ -145,7 +142,7 @@ mod qobject {
|
||||
pub struct RCore;
|
||||
|
||||
impl qobject::Core {
|
||||
fn init(self: Pin<&mut Self>) {
|
||||
fn init(self: Pin<&mut Self>) {
|
||||
self.listen();
|
||||
}
|
||||
|
||||
@@ -396,8 +393,11 @@ impl qobject::Core {
|
||||
emit_connected(qt_thread.clone(), udid).await;
|
||||
});
|
||||
}
|
||||
/* DISCONNECTED */
|
||||
Ok(UsbmuxdListenEvent::Disconnected(device_id)) => {
|
||||
if let Some(udid) = device_map.remove(&device_id) {
|
||||
clean_device_from_app_state(&udid).await;
|
||||
|
||||
let qt_thread = qt_t.clone();
|
||||
qt_thread
|
||||
.queue(move |Core_qobj| {
|
||||
@@ -506,8 +506,9 @@ impl qobject::Core {
|
||||
fn get_pairing_files(self: Pin<&mut Self>) -> QMap<QMapPair_QString_QVariant> {
|
||||
let mut map = QMap::<QMapPair_QString_QVariant>::default();
|
||||
|
||||
let paths =
|
||||
match std::fs::read_dir(get_lockdown_path()) {
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
{
|
||||
let paths = match std::fs::read_dir(utils::get_lockdown_path()) {
|
||||
Ok(iter) => iter
|
||||
.filter_map(|entry| {
|
||||
let entry = entry.ok()?;
|
||||
@@ -518,49 +519,75 @@ impl qobject::Core {
|
||||
Err(_) => Vec::new(),
|
||||
};
|
||||
|
||||
paths.into_iter().for_each(|path| {
|
||||
if let Ok(pf) = PairingFile::read_from_file(&path) {
|
||||
if let Some(fname) = path.file_name().and_then(|s| s.to_str()) {
|
||||
paths.into_iter().for_each(|path| {
|
||||
if let Ok(pf) = PairingFile::read_from_file(&path) {
|
||||
let abs = path.canonicalize().unwrap_or(path);
|
||||
let abs_str = abs.to_string_lossy().to_string();
|
||||
|
||||
map.insert(
|
||||
QString::from(pf.wifi_mac_address),
|
||||
QVariant::from(&QString::from(fname)),
|
||||
QVariant::from(&QString::from(abs_str)),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
let entries: Vec<(String, String)> = run_sync(async {
|
||||
let mut out = Vec::new();
|
||||
|
||||
if let Ok(mut uc) = UsbmuxdConnection::default().await {
|
||||
if let Ok(devs) = uc.get_devices().await {
|
||||
for dev in devs {
|
||||
if let Ok(pair_rec) = uc.get_pair_record(&dev.udid).await {
|
||||
out.push((
|
||||
pair_rec.wifi_mac_address.clone(),
|
||||
format!("{}.plist", dev.udid),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out
|
||||
});
|
||||
|
||||
let base = utils::get_lockdown_path();
|
||||
|
||||
// turn $UDID.plist into /var/db/lockdown/UDID.plist
|
||||
for (wifi_mac, file_name) in entries {
|
||||
let full_path = base.join(&file_name);
|
||||
let full_path_str = full_path.to_string_lossy().into_owned();
|
||||
|
||||
map.insert(
|
||||
QString::from(wifi_mac),
|
||||
QVariant::from(&QString::from(full_path_str)),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
map
|
||||
}
|
||||
fn remove_device(self: Pin<&mut Self>, udid: &QString) {
|
||||
let udid_str = udid.to_string();
|
||||
RUNTIME.spawn(async move {
|
||||
let mut state = APP_DEVICE_STATE.lock().await;
|
||||
if let Some(svc) = state.remove(&udid_str) {
|
||||
let streams = svc.video_streams.lock().await;
|
||||
for (_path, flag) in streams.iter() {
|
||||
flag.store(true, Ordering::Relaxed);
|
||||
}
|
||||
println!("Removed device with UDID {}", udid_str);
|
||||
} else {
|
||||
eprintln!(
|
||||
"Attempted to remove non-existent device with UDID {}",
|
||||
udid_str
|
||||
);
|
||||
}
|
||||
clean_device_from_app_state(&udid_str).await;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn get_lockdown_path() -> String {
|
||||
#[cfg(target_os = "linux")]
|
||||
return "/var/lib/lockdown".to_string();
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
return "/var/db/lockdown".to_string();
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
return std::env::var("PROGRAMDATA").unwrap_or_else(|_| "C:\\ProgramData".to_string())
|
||||
+ "/Apple/Lockdown";
|
||||
async fn clean_device_from_app_state(udid: &str) {
|
||||
let mut state = APP_DEVICE_STATE.lock().await;
|
||||
if let Some(svc) = state.remove(udid) {
|
||||
let streams = svc.video_streams.lock().await;
|
||||
for (_path, flag) in streams.iter() {
|
||||
flag.store(true, Ordering::Relaxed);
|
||||
}
|
||||
println!("Removed device with UDID {}", udid);
|
||||
} else {
|
||||
eprintln!("Attempted to remove non-existent device with UDID {}", udid);
|
||||
}
|
||||
}
|
||||
|
||||
//FIXME: dont spawn hb if init fails
|
||||
@@ -603,9 +630,7 @@ async fn init_idescriptor_device<
|
||||
}
|
||||
eprintln!("init_idescriptor_device: Lockdown session started.");
|
||||
|
||||
eprintln!(
|
||||
"init_idescriptor_device: Attempting to get default values from Lockdown."
|
||||
);
|
||||
eprintln!("init_idescriptor_device: Attempting to get default values from Lockdown.");
|
||||
let mut def_vals = match lc.get_value(None, None).await {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
@@ -627,9 +652,7 @@ async fn init_idescriptor_device<
|
||||
}
|
||||
|
||||
if is_wireless {
|
||||
eprintln!(
|
||||
"init_idescriptor_device: Attempting to connect to HeartbeatClient."
|
||||
);
|
||||
eprintln!("init_idescriptor_device: Attempting to connect to HeartbeatClient.");
|
||||
hb = match heartbeat::HeartbeatClient::connect(&provider_for_hb).await {
|
||||
Ok(h) => Some(h),
|
||||
Err(e) => {
|
||||
@@ -660,7 +683,7 @@ async fn init_idescriptor_device<
|
||||
eprintln!("heartbeat: get_marco failed (fail count: {fails}): {e:?}");
|
||||
if fails >= 3 {
|
||||
eprintln!("heartbeat: too many failures for giving up");
|
||||
APP_DEVICE_STATE.lock().await.remove(&udid_for_hb);
|
||||
clean_device_from_app_state(&udid_for_hb).await;
|
||||
|
||||
let udid_for_event = udid_for_hb.clone();
|
||||
let _ = qt_thread_for_hb.queue(move |Core_qobj| {
|
||||
@@ -682,7 +705,7 @@ async fn init_idescriptor_device<
|
||||
eprintln!("heartbeat: send_polo failed (fail count: {fails}): {e:?}");
|
||||
if fails >= 3 {
|
||||
eprintln!("heartbeat: too many failures for , giving up");
|
||||
APP_DEVICE_STATE.lock().await.remove(&udid_for_hb);
|
||||
clean_device_from_app_state(&udid_for_hb).await;
|
||||
|
||||
let udid_for_event = udid_for_hb.clone();
|
||||
let _ = qt_thread_for_hb.queue(move |Core_qobj| {
|
||||
@@ -699,11 +722,9 @@ async fn init_idescriptor_device<
|
||||
}
|
||||
eprintln!("heartbeat: Polo sent successfully.");
|
||||
interval += 5;
|
||||
// tokio::time::sleep(std::time::Duration::from_secs(interval + 5)).await;
|
||||
}
|
||||
|
||||
eprintln!("heartbeat: heartbeat task for ended.");
|
||||
// loop exits → task ends
|
||||
eprintln!("heartbeat: heartbeat task ended.");
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -729,9 +750,7 @@ async fn init_idescriptor_device<
|
||||
}
|
||||
};
|
||||
|
||||
eprintln!(
|
||||
"init_idescriptor_device: Attempting to connect to AFC client."
|
||||
);
|
||||
eprintln!("init_idescriptor_device: Attempting to connect to AFC client.");
|
||||
let mut afc_client = match AfcClient::connect(&provider).await {
|
||||
Ok(c) => c,
|
||||
Err(e) => {
|
||||
@@ -741,9 +760,7 @@ async fn init_idescriptor_device<
|
||||
};
|
||||
eprintln!("init_idescriptor_device: Connected to AfcClient.");
|
||||
|
||||
eprintln!(
|
||||
"init_idescriptor_device: Attempting to connect to DiagnosticsRelayClient."
|
||||
);
|
||||
eprintln!("init_idescriptor_device: Attempting to connect to DiagnosticsRelayClient.");
|
||||
let mut diag_relay = match DiagnosticsRelayClient::connect(&provider).await {
|
||||
Ok(c) => c,
|
||||
Err(e) => {
|
||||
@@ -754,7 +771,7 @@ async fn init_idescriptor_device<
|
||||
eprintln!("init_idescriptor_device: Connected to DiagnosticsRelayClient.");
|
||||
// afc_client.set_timeout(Some(5000)).await;
|
||||
|
||||
let afc2 = match AfcClient::new_afc2(&provider).await {
|
||||
let afc2 = match AfcClient::new_afc2(&provider).await {
|
||||
Ok(c) => Some(Arc::new(Mutex::new(c))),
|
||||
Err(e) => {
|
||||
eprintln!("AfcClient::new_afc2 failed: {e:?}");
|
||||
@@ -829,9 +846,7 @@ async fn init_idescriptor_device<
|
||||
|
||||
let mut buf = Vec::new();
|
||||
if def_vals.to_writer_xml(&mut buf).is_err() {
|
||||
eprintln!(
|
||||
"init_idescriptor_device: Failed to serialize default values to XML."
|
||||
);
|
||||
eprintln!("init_idescriptor_device: Failed to serialize default values to XML.");
|
||||
return None;
|
||||
}
|
||||
let info = String::from_utf8(buf).ok()?;
|
||||
|
||||
@@ -1,25 +1,23 @@
|
||||
use crate::{APP_DEVICE_STATE, RUNTIME, utils};
|
||||
use cxx_qt::Threading;
|
||||
use cxx_qt_lib::{
|
||||
QByteArray, QList, QMap, QMapPair_QString_QVariant, QString, QVariant,
|
||||
};
|
||||
use idevice::{
|
||||
IdeviceService, RsdService, amfi, dvt::{
|
||||
location_simulation::LocationSimulationClient, remote_server::RemoteServerClient
|
||||
}, installation_proxy::InstallationProxyClient, mobile_image_mounter::ImageMounter, provider::IdeviceProvider, rsd::RsdHandshake, simulate_location::LocationSimulationService, springboardservices::SpringBoardServicesClient,
|
||||
};
|
||||
use cxx_qt_lib::{QByteArray, QList, QMap, QMapPair_QString_QVariant, QString, QVariant};
|
||||
use idevice::afc::opcode::AfcFopenMode;
|
||||
use idevice::services::core_device_proxy::CoreDeviceProxy;
|
||||
use crate::{APP_DEVICE_STATE, RUNTIME, utils};
|
||||
use plist::{ Value};
|
||||
|
||||
use serde_json;
|
||||
use std::{
|
||||
io::{Read},
|
||||
pin::Pin,
|
||||
time::Duration,
|
||||
use idevice::{
|
||||
IdeviceService, RsdService, amfi,
|
||||
dvt::{location_simulation::LocationSimulationClient, remote_server::RemoteServerClient},
|
||||
installation_proxy::InstallationProxyClient,
|
||||
mobile_image_mounter::ImageMounter,
|
||||
provider::IdeviceProvider,
|
||||
rsd::RsdHandshake,
|
||||
simulate_location::LocationSimulationService,
|
||||
springboardservices::SpringBoardServicesClient,
|
||||
};
|
||||
use plist_macro::plist;
|
||||
use plist::Value;
|
||||
|
||||
use plist_macro::plist;
|
||||
use serde_json;
|
||||
use std::{io::Read, pin::Pin, time::Duration};
|
||||
|
||||
#[cxx_qt::bridge(namespace = "CXX")]
|
||||
mod qobject {
|
||||
@@ -64,7 +62,6 @@ mod qobject {
|
||||
#[qinvokable]
|
||||
fn set_location(&self, latitude: &QString, longitude: &QString) -> i32;
|
||||
|
||||
|
||||
#[qinvokable]
|
||||
fn fetch_app_icon(&self, bundle_id: QString);
|
||||
|
||||
@@ -72,7 +69,10 @@ mod qobject {
|
||||
fn cable_info_retrieved(self: Pin<&mut ServiceManager>, info: QString);
|
||||
|
||||
#[qsignal]
|
||||
fn mobilegestalt_info_retrieved(self: Pin<&mut ServiceManager>, info: QMap_QString_QVariant);
|
||||
fn mobilegestalt_info_retrieved(
|
||||
self: Pin<&mut ServiceManager>,
|
||||
info: QMap_QString_QVariant,
|
||||
);
|
||||
|
||||
#[qsignal]
|
||||
fn dev_image_mounted(self: Pin<&mut ServiceManager>, success: bool);
|
||||
@@ -81,24 +81,35 @@ mod qobject {
|
||||
fn developer_mode_option_revealed(self: Pin<&mut ServiceManager>, success: bool);
|
||||
|
||||
#[qsignal]
|
||||
fn mounted_image_retrieved(self: Pin<&mut ServiceManager>, sig: QByteArray, sig_length: u64);
|
||||
fn mounted_image_retrieved(
|
||||
self: Pin<&mut ServiceManager>,
|
||||
sig: QByteArray,
|
||||
sig_length: u64,
|
||||
);
|
||||
|
||||
#[qsignal]
|
||||
fn installed_apps_retrieved(self: Pin<&mut ServiceManager>, apps: &QMap_QString_QVariant);
|
||||
|
||||
#[qsignal]
|
||||
fn app_icon_loaded(self: Pin<&mut ServiceManager>, bundle_id: QString, icon_data: QByteArray);
|
||||
|
||||
fn app_icon_loaded(
|
||||
self: Pin<&mut ServiceManager>,
|
||||
bundle_id: QString,
|
||||
icon_data: QByteArray,
|
||||
);
|
||||
|
||||
#[qsignal]
|
||||
fn battery_info_updated(self: Pin<&mut ServiceManager>, info: &QString);
|
||||
|
||||
|
||||
#[qinvokable]
|
||||
fn fetch_disk_usage(&self, skip_gallery_usage: bool);
|
||||
|
||||
#[qsignal]
|
||||
fn disk_usage_retrieved(self: Pin<&mut ServiceManager>, success: bool, apps_usage: u64, gallery_usage: u64);
|
||||
fn disk_usage_retrieved(
|
||||
self: Pin<&mut ServiceManager>,
|
||||
success: bool,
|
||||
apps_usage: u64,
|
||||
gallery_usage: u64,
|
||||
);
|
||||
}
|
||||
|
||||
impl cxx_qt::Threading for ServiceManager {}
|
||||
@@ -130,28 +141,29 @@ impl cxx_qt::Constructor<(QString, u32)> for qobject::ServiceManager {
|
||||
RServiceManager {
|
||||
udid: args.0,
|
||||
ios_version: args.1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn initialize(self: Pin<&mut Self>, _arguments: Self::InitializeArguments) {
|
||||
let udid_for_log = self.get_udid().to_string();
|
||||
println!("ServiceServiceManager::ServiceManager::initialize called for UDID: {udid_for_log}");
|
||||
self.start_update_battery_info_interval();
|
||||
}
|
||||
fn initialize(self: Pin<&mut Self>, _arguments: Self::InitializeArguments) {
|
||||
let udid_for_log = self.get_udid().to_string();
|
||||
println!(
|
||||
"ServiceServiceManager::ServiceManager::initialize called for UDID: {udid_for_log}"
|
||||
);
|
||||
self.start_update_battery_info_interval();
|
||||
}
|
||||
}
|
||||
|
||||
impl qobject::ServiceManager {
|
||||
|
||||
pub fn start_update_battery_info_interval(self: Pin<&mut Self>) {
|
||||
let qt_thread = self.qt_thread();
|
||||
pub fn start_update_battery_info_interval(self: Pin<&mut Self>) {
|
||||
let qt_thread = self.qt_thread();
|
||||
let udid = self.get_udid().to_string();
|
||||
println!("Starting battery info update interval for device {udid}");
|
||||
RUNTIME.spawn(async move {
|
||||
let mut interval = tokio::time::interval(Duration::from_secs(30));
|
||||
|
||||
loop {
|
||||
interval.tick().await;
|
||||
|
||||
RUNTIME.spawn(async move {
|
||||
let mut interval = tokio::time::interval(Duration::from_secs(30));
|
||||
|
||||
loop {
|
||||
interval.tick().await;
|
||||
|
||||
let maybe_device = APP_DEVICE_STATE.lock().await.get(udid.as_str()).cloned();
|
||||
|
||||
let device = match maybe_device {
|
||||
@@ -162,21 +174,27 @@ impl qobject::ServiceManager {
|
||||
}
|
||||
};
|
||||
|
||||
println!("start_update_battery_info_interval: Fetching battery info for device {udid}");
|
||||
println!(
|
||||
"start_update_battery_info_interval: Fetching battery info for device {udid}"
|
||||
);
|
||||
|
||||
utils::get_battery_info(&mut *device.diag.lock().await).await.map(|info| {
|
||||
let mut buf = Vec::new();
|
||||
if Value::Dictionary(info).to_writer_xml(&mut buf).is_ok() {
|
||||
if let Ok(s) = String::from_utf8(buf) {
|
||||
qt_thread.queue(move |t| {
|
||||
t.battery_info_updated(&QString::from(s));
|
||||
}).ok();
|
||||
utils::get_battery_info(&mut *device.diag.lock().await)
|
||||
.await
|
||||
.map(|info| {
|
||||
let mut buf = Vec::new();
|
||||
if Value::Dictionary(info).to_writer_xml(&mut buf).is_ok() {
|
||||
if let Ok(s) = String::from_utf8(buf) {
|
||||
qt_thread
|
||||
.queue(move |t| {
|
||||
t.battery_info_updated(&QString::from(s));
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn get_udid(&self) -> &QString {
|
||||
use cxx_qt::CxxQtType;
|
||||
@@ -638,7 +656,6 @@ impl qobject::ServiceManager {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
fn fetch_app_icon(&self, bundle_id: QString) {
|
||||
let udid = self.get_udid().to_string();
|
||||
let qt_t = self.qt_thread();
|
||||
@@ -684,11 +701,10 @@ impl qobject::ServiceManager {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
fn set_location(&self, latitude: &QString, longitude: &QString) -> i32 {
|
||||
let udid = self.get_udid().to_string();
|
||||
let ios_version = self.get_ios_version();
|
||||
|
||||
|
||||
/*
|
||||
FIXME: use RUNTIME.spawn in the future
|
||||
*/
|
||||
@@ -866,16 +882,15 @@ async fn set_device_location_rsd(
|
||||
longitude: f64,
|
||||
) -> Result<(), idevice::IdeviceError> {
|
||||
let rsd_port = proxy.handshake.server_rsd_port;
|
||||
let adapter = proxy.create_software_tunnel()?;
|
||||
let mut adapter = adapter.to_async_handle();
|
||||
let stream = adapter.connect(rsd_port).await?;
|
||||
|
||||
let mut handshake = RsdHandshake::new(stream).await?;
|
||||
|
||||
let mut remote_server =
|
||||
RemoteServerClient::connect_rsd(&mut adapter, &mut handshake).await?;
|
||||
remote_server.read_message(0).await?;
|
||||
|
||||
let mut location_client = LocationSimulationClient::new(&mut remote_server).await?;
|
||||
location_client.set(latitude, longitude).await
|
||||
let adapter = proxy.create_software_tunnel()?;
|
||||
let mut adapter = adapter.to_async_handle();
|
||||
let stream = adapter.connect(rsd_port).await?;
|
||||
|
||||
let mut handshake = RsdHandshake::new(stream).await?;
|
||||
|
||||
let mut remote_server = RemoteServerClient::connect_rsd(&mut adapter, &mut handshake).await?;
|
||||
remote_server.read_message(0).await?;
|
||||
|
||||
let mut location_client = LocationSimulationClient::new(&mut remote_server).await?;
|
||||
location_client.set(latitude, longitude).await
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ use idevice::{
|
||||
use plist::Dictionary as PlistDictionary;
|
||||
use plist_macro::plist;
|
||||
use rusqlite::Connection;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub async fn get_battery_info(diag: &mut DiagnosticsRelayClient) -> Option<PlistDictionary> {
|
||||
match diag.ioregistry(None, None, Some("IOPMPowerSource")).await {
|
||||
@@ -118,3 +119,30 @@ pub fn query_gallery_usage(db_bytes: &mut Vec<u8>) -> Result<u64, rusqlite::Erro
|
||||
println!("Gallery usage calculated: {} bytes", size);
|
||||
Ok(size as u64)
|
||||
}
|
||||
|
||||
pub fn get_lockdown_path() -> PathBuf {
|
||||
if let Ok(val) = std::env::var("USBMUXD_PAIRING_FILES_LOCATION") {
|
||||
if !val.is_empty() {
|
||||
eprintln!("Pulling pairing files from USBMUXD_PAIRING_FILES_LOCATION: {val}");
|
||||
return PathBuf::from(val);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
PathBuf::from("/var/lib/lockdown")
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
PathBuf::from("/var/db/lockdown")
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
let base = std::env::var_os("PROGRAMDATA")
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(|| PathBuf::from(r"C:\ProgramData"));
|
||||
base.join("Apple").join("Lockdown")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user