Implement diagnosticsservice

This commit is contained in:
Jackson Coxson
2025-08-15 20:19:37 -06:00
parent e881d6ef07
commit ef7811b3a6
6 changed files with 211 additions and 1 deletions

View File

@@ -42,6 +42,7 @@ reqwest = { version = "0.12", features = [
], optional = true, default-features = false }
rand = { version = "0.9", optional = true }
futures = { version = "0.3", optional = true }
async-stream = { version = "0.3.6", optional = true }
sha2 = { version = "0.10", optional = true, features = ["oid"] }
@@ -96,7 +97,7 @@ tunnel_tcp_stack = [
tss = ["dep:uuid", "dep:reqwest"]
tunneld = ["dep:serde_json", "dep:json", "dep:reqwest"]
usbmuxd = ["tokio/net"]
xpc = ["dep:indexmap", "dep:uuid"]
xpc = ["dep:indexmap", "dep:uuid", "dep:async-stream"]
full = [
"afc",
"amfi",

View File

@@ -0,0 +1,72 @@
// Jackson Coxson
use std::pin::Pin;
use futures::Stream;
use log::warn;
use crate::{IdeviceError, ReadWrite, RsdService, obf};
impl RsdService for DiagnostisServiceClient<Box<dyn ReadWrite>> {
fn rsd_service_name() -> std::borrow::Cow<'static, str> {
obf!("com.apple.coredevice.diagnosticsservice")
}
async fn from_stream(stream: Box<dyn ReadWrite>) -> Result<Self, IdeviceError> {
Ok(Self {
inner: super::CoreDeviceServiceClient::new(stream).await?,
})
}
}
pub struct DiagnostisServiceClient<R: ReadWrite> {
inner: super::CoreDeviceServiceClient<R>,
}
pub struct SysdiagnoseResponse<'a> {
pub preferred_filename: String,
pub stream: Pin<Box<dyn Stream<Item = Result<Vec<u8>, IdeviceError>> + 'a>>,
pub expected_length: usize,
}
impl<R: ReadWrite> DiagnostisServiceClient<R> {
pub async fn capture_sysdiagnose<'a>(
&'a mut self,
dry_run: bool,
) -> Result<SysdiagnoseResponse<'a>, IdeviceError> {
let req = crate::plist!({
"options": {
"collectFullLogs": true
},
"isDryRun": dry_run
})
.into_dictionary()
.unwrap();
let res = self
.inner
.invoke("com.apple.coredevice.feature.capturesysdiagnose", Some(req))
.await?;
if let Some(len) = res
.as_dictionary()
.and_then(|x| x.get("fileTransfer"))
.and_then(|x| x.as_dictionary())
.and_then(|x| x.get("expectedLength"))
.and_then(|x| x.as_unsigned_integer())
&& let Some(name) = res
.as_dictionary()
.and_then(|x| x.get("preferredFilename"))
.and_then(|x| x.as_string())
{
Ok(SysdiagnoseResponse {
stream: Box::pin(self.inner.inner.iter_file_chunks(len as usize, 0)),
preferred_filename: name.to_string(),
expected_length: len as usize,
})
} else {
warn!("Did not get expected responses from RemoteXPC");
Err(IdeviceError::UnexpectedResponse)
}
}
}

View File

@@ -9,7 +9,9 @@ use crate::{
};
mod app_service;
mod diagnosticsservice;
pub use app_service::*;
pub use diagnosticsservice::*;
const CORE_SERVICE_VERSION: &str = "443.18";