idevice/services/
companion_proxy.rs1use log::warn;
4
5use crate::{Idevice, IdeviceError, IdeviceService, RsdService, obf};
6
7pub struct CompanionProxy {
8 idevice: Idevice,
9}
10
11pub struct CompanionProxyStream {
12 proxy: CompanionProxy,
13}
14
15impl IdeviceService for CompanionProxy {
16 fn service_name() -> std::borrow::Cow<'static, str> {
17 obf!("com.apple.companion_proxy")
18 }
19
20 async fn from_stream(idevice: Idevice) -> Result<Self, crate::IdeviceError> {
21 Ok(Self::new(idevice))
22 }
23}
24
25impl RsdService for CompanionProxy {
26 fn rsd_service_name() -> std::borrow::Cow<'static, str> {
27 obf!("com.apple.companion_proxy.shim.remote")
28 }
29
30 async fn from_stream(stream: Box<dyn crate::ReadWrite>) -> Result<Self, crate::IdeviceError> {
31 let mut idevice = Idevice::new(stream, "");
32 idevice.rsd_checkin().await?;
33 Ok(Self::new(idevice))
34 }
35}
36
37impl CompanionProxy {
38 pub fn new(idevice: Idevice) -> Self {
39 Self { idevice }
40 }
41
42 pub async fn get_device_registry(&mut self) -> Result<Vec<String>, IdeviceError> {
43 let command = crate::plist!({
44 "Command": "GetDeviceRegistry"
45 });
46
47 self.idevice.send_plist(command).await?;
48 let res = self.idevice.read_plist().await?;
49 let list = match res.get("PairedDevicesArray").and_then(|x| x.as_array()) {
50 Some(l) => l,
51 None => {
52 warn!("Didn't get PairedDevicesArray array");
53 return Err(IdeviceError::UnexpectedResponse);
54 }
55 };
56
57 let mut res = Vec::new();
58 for l in list {
59 if let plist::Value::String(l) = l {
60 res.push(l.to_owned());
61 }
62 }
63
64 Ok(res)
65 }
66
67 pub async fn listen_for_devices(mut self) -> Result<CompanionProxyStream, IdeviceError> {
68 let command = crate::plist!({
69 "Command": "StartListeningForDevices"
70 });
71 self.idevice.send_plist(command).await?;
72
73 Ok(CompanionProxyStream { proxy: self })
74 }
75
76 pub async fn get_value(
77 &mut self,
78 udid: impl Into<String>,
79 key: impl Into<String>,
80 ) -> Result<plist::Value, IdeviceError> {
81 let udid = udid.into();
82 let key = key.into();
83 let command = crate::plist!({
84 "Command": "GetValueFromRegistry",
85 "GetValueGizmoUDIDKey": udid,
86 "GetValueKeyKey": key.clone()
87 });
88 self.idevice.send_plist(command).await?;
89 let mut res = self.idevice.read_plist().await?;
90 if let Some(v) = res
91 .remove("RetrievedValueDictionary")
92 .and_then(|x| x.into_dictionary())
93 .and_then(|mut x| x.remove(&key))
94 {
95 Ok(v)
96 } else {
97 Err(IdeviceError::NotFound)
98 }
99 }
100
101 pub async fn start_forwarding_service_port(
102 &mut self,
103 port: u16,
104 service_name: Option<&str>,
105 options: Option<plist::Dictionary>,
106 ) -> Result<u16, IdeviceError> {
107 let command = crate::plist!({
108 "Command": "StartForwardingServicePort",
109 "GizmoRemotePortNumber": port,
110 "IsServiceLowPriority": false,
111 "PreferWifi": false,
112 "ForwardedServiceName":? service_name,
113 :<? options,
114 });
115 self.idevice.send_plist(command).await?;
116 let res = self.idevice.read_plist().await?;
117 if let Some(p) = res
118 .get("CompanionProxyServicePort")
119 .and_then(|x| x.as_unsigned_integer())
120 {
121 Ok(p as u16)
122 } else {
123 Err(IdeviceError::UnexpectedResponse)
124 }
125 }
126
127 pub async fn stop_forwarding_service_port(&mut self, port: u16) -> Result<(), IdeviceError> {
128 let command = crate::plist!({
129 "Command": "StopForwardingServicePort",
130 "GizmoRemotePortNumber": port
131 });
132
133 self.idevice.send_plist(command).await?;
134 let res = self.idevice.read_plist().await?;
135 if let Some(c) = res.get("Command").and_then(|x| x.as_string())
136 && (c == "ComandSuccess" || c == "CommandSuccess")
137 {
139 Ok(())
140 } else {
141 Err(IdeviceError::UnexpectedResponse)
142 }
143 }
144}
145
146impl CompanionProxyStream {
147 pub async fn next(&mut self) -> Result<plist::Dictionary, IdeviceError> {
148 self.proxy.idevice.read_plist().await
149 }
150}