use crate::{Idevice, IdeviceError, IdeviceService, obf};
#[derive(Debug)]
pub struct DiagnosticsRelayClient {
pub idevice: Idevice,
}
impl IdeviceService for DiagnosticsRelayClient {
fn service_name() -> std::borrow::Cow<'static, str> {
obf!("com.apple.mobile.diagnostics_relay")
}
async fn from_stream(idevice: Idevice) -> Result<Self, crate::IdeviceError> {
Ok(Self::new(idevice))
}
}
impl DiagnosticsRelayClient {
pub fn new(idevice: Idevice) -> Self {
Self { idevice }
}
pub async fn ioregistry(
&mut self,
current_plane: Option<&str>,
entry_name: Option<&str>,
entry_class: Option<&str>,
) -> Result<Option<plist::Dictionary>, IdeviceError> {
let req = crate::plist!({
"Request": "IORegistry",
"CurrentPlane":? current_plane,
"EntryName":? entry_name,
"EntryClass":? entry_class,
});
self.idevice.send_plist(req).await?;
let mut res = self.idevice.read_plist().await?;
match res.get("Status").and_then(|x| x.as_string()) {
Some("Success") => {}
_ => {
return Err(IdeviceError::UnexpectedResponse(
"missing or non-Success Status in IORegistry response".into(),
));
}
}
let res = res
.remove("Diagnostics")
.and_then(|x| x.into_dictionary())
.and_then(|mut x| x.remove("IORegistry"))
.and_then(|x| x.into_dictionary());
Ok(res)
}
pub async fn mobilegestalt(
&mut self,
keys: Option<Vec<String>>,
) -> Result<Option<plist::Dictionary>, IdeviceError> {
let req = crate::plist!({
"Request": "MobileGestalt",
"MobileGestaltKeys":? keys,
});
self.idevice.send_plist(req).await?;
let mut res = self.idevice.read_plist().await?;
match res.get("Status").and_then(|x| x.as_string()) {
Some("Success") => {}
_ => {
return Err(IdeviceError::UnexpectedResponse(
"missing or non-Success Status in MobileGestalt response".into(),
));
}
}
let res = res.remove("Diagnostics").and_then(|x| x.into_dictionary());
Ok(res)
}
pub async fn gasguage(&mut self) -> Result<Option<plist::Dictionary>, IdeviceError> {
let req = crate::plist!({
"Request": "GasGauge"
});
self.idevice.send_plist(req).await?;
let mut res = self.idevice.read_plist().await?;
match res.get("Status").and_then(|x| x.as_string()) {
Some("Success") => {}
_ => {
return Err(IdeviceError::UnexpectedResponse(
"missing or non-Success Status in GasGauge response".into(),
));
}
}
let res = res.remove("Diagnostics").and_then(|x| x.into_dictionary());
Ok(res)
}
pub async fn nand(&mut self) -> Result<Option<plist::Dictionary>, IdeviceError> {
let req = crate::plist!({
"Request": "NAND"
});
self.idevice.send_plist(req).await?;
let mut res = self.idevice.read_plist().await?;
match res.get("Status").and_then(|x| x.as_string()) {
Some("Success") => {}
_ => {
return Err(IdeviceError::UnexpectedResponse(
"missing or non-Success Status in NAND response".into(),
));
}
}
let res = res.remove("Diagnostics").and_then(|x| x.into_dictionary());
Ok(res)
}
pub async fn all(&mut self) -> Result<Option<plist::Dictionary>, IdeviceError> {
let req = crate::plist!({
"Request": "All"
});
self.idevice.send_plist(req).await?;
let mut res = self.idevice.read_plist().await?;
match res.get("Status").and_then(|x| x.as_string()) {
Some("Success") => {}
_ => {
return Err(IdeviceError::UnexpectedResponse(
"missing or non-Success Status in All diagnostics response".into(),
));
}
}
let res = res.remove("Diagnostics").and_then(|x| x.into_dictionary());
Ok(res)
}
pub async fn restart(&mut self) -> Result<(), IdeviceError> {
let req = crate::plist!({
"Request": "Restart",
});
self.idevice.send_plist(req).await?;
let res = self.idevice.read_plist().await?;
match res.get("Status").and_then(|x| x.as_string()) {
Some("Success") => Ok(()),
_ => Err(IdeviceError::UnexpectedResponse(
"missing or non-Success Status in Restart response".into(),
)),
}
}
pub async fn shutdown(&mut self) -> Result<(), IdeviceError> {
let req = crate::plist!({
"Request": "Shutdown"
});
self.idevice.send_plist(req).await?;
let res = self.idevice.read_plist().await?;
match res.get("Status").and_then(|x| x.as_string()) {
Some("Success") => Ok(()),
_ => Err(IdeviceError::UnexpectedResponse(
"missing or non-Success Status in Shutdown response".into(),
)),
}
}
pub async fn sleep(&mut self) -> Result<(), IdeviceError> {
let req = crate::plist!({
"Request": "Sleep"
});
self.idevice.send_plist(req).await?;
let res = self.idevice.read_plist().await?;
match res.get("Status").and_then(|x| x.as_string()) {
Some("Success") => Ok(()),
_ => Err(IdeviceError::UnexpectedResponse(
"missing or non-Success Status in Sleep response".into(),
)),
}
}
pub async fn wifi(&mut self) -> Result<Option<plist::Dictionary>, IdeviceError> {
let req = crate::plist!({
"Request": "WiFi"
});
self.idevice.send_plist(req).await?;
let mut res = self.idevice.read_plist().await?;
match res.get("Status").and_then(|x| x.as_string()) {
Some("Success") => {}
_ => {
return Err(IdeviceError::UnexpectedResponse(
"missing or non-Success Status in WiFi response".into(),
));
}
}
let res = res.remove("Diagnostics").and_then(|x| x.into_dictionary());
Ok(res)
}
pub async fn goodbye(&mut self) -> Result<(), IdeviceError> {
let req = crate::plist!({
"Request": "Goodbye"
});
self.idevice.send_plist(req).await?;
let res = self.idevice.read_plist().await?;
match res.get("Status").and_then(|x| x.as_string()) {
Some("Success") => Ok(()),
Some("UnknownRequest") => Err(IdeviceError::UnexpectedResponse(
"Goodbye request returned UnknownRequest".into(),
)),
_ => Err(IdeviceError::UnexpectedResponse(
"missing or non-Success Status in Goodbye response".into(),
)),
}
}
}
#[cfg(feature = "rsd")]
impl crate::RsdService for DiagnosticsRelayClient {
fn rsd_service_name() -> std::borrow::Cow<'static, str> {
crate::obf!("com.apple.mobile.diagnostics_relay.shim.remote")
}
async fn from_stream(stream: Box<dyn crate::ReadWrite>) -> Result<Self, crate::IdeviceError> {
let mut idevice = crate::Idevice::new(stream, "");
idevice.rsd_checkin().await?;
Ok(Self::new(idevice))
}
}