1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
// jkcoxson
use std::os::raw::c_char;
use crate::services::lockdownd::LockdowndService;
use crate::{bindings as unsafe_bindings, error::ServiceError, idevice::Device};
pub struct ServiceClient<'a> {
pub(crate) pointer: unsafe_bindings::service_client_t,
phantom: std::marker::PhantomData<&'a Device>,
}
impl ServiceClient<'_> {
/// Creates a new service on the device
/// This is useful for services that don't have abstractions and need to be handled manually
/// # Arguments
/// * `device` - The device to create the service with
/// * `descriptor` - The lockdown service to jump off of
///
/// ***Verified:*** False
pub fn new(device: &Device, descriptor: LockdowndService) -> Result<Self, ServiceError> {
let mut pointer = std::ptr::null_mut();
let result = unsafe {
unsafe_bindings::service_client_new(device.pointer, descriptor.pointer, &mut pointer)
}
.into();
if result != ServiceError::Success {
return Err(result);
}
Ok(ServiceClient {
pointer,
phantom: std::marker::PhantomData,
})
}
/// Starts a factory service on the device
/// # Arguments
/// * `device` - The device to create the service with
/// * `service_name` - The name of the service to start
/// * `label` - The label to use for the service
///
/// ***Verified:*** False
pub fn factory_start_service(
device: &Device,
service_name: impl Into<String>,
label: impl Into<String>,
) -> Result<(Self, i32), ServiceError> {
let mut pointer = std::ptr::null_mut();
let mut error_code = 0;
let result = unsafe {
unsafe_bindings::service_client_factory_start_service(
device.pointer,
service_name.into().as_ptr() as *const c_char,
&mut pointer,
label.into().as_ptr() as *const c_char,
None,
&mut error_code,
)
}
.into();
if result != ServiceError::Success {
return Err(result);
}
let pointer = pointer as unsafe_bindings::service_client_t;
Ok((
ServiceClient {
pointer,
phantom: std::marker::PhantomData,
},
error_code,
))
}
/// Send data to the service
/// # Arguments
/// * `data` - The data to send
/// # Returns
/// The number of bytes sent
///
/// ***Verified:*** False
pub fn send(&self, data: Vec<c_char>) -> Result<u32, ServiceError> {
let mut sent = 0;
let result = unsafe {
unsafe_bindings::service_send(
self.pointer,
data.as_ptr() as *const c_char,
data.len() as u32,
&mut sent,
)
}
.into();
if result != ServiceError::Success {
return Err(result);
}
Ok(sent)
}
/// Receives data from the service, blocking until the amount of data is received
/// # Arguments
/// * `size` - The size of the buffer to receive
/// # Returns
/// The received data as a vector of bytes
///
/// ***Verified:*** False
pub fn receive(&self, size: u32) -> Result<Vec<c_char>, ServiceError> {
let mut data = Vec::new();
let mut received = 0;
let result = unsafe {
unsafe_bindings::service_receive(
self.pointer,
data.as_mut_ptr() as *mut c_char,
size,
&mut received,
)
}
.into();
if result != ServiceError::Success {
return Err(result);
}
Ok(data)
}
/// Receives data from the service, blocking until the amount of data is received or the timeout is reached
/// # Arguments
/// * `size` - The size of the buffer to receive
/// * `timeout` - The timeout in milliseconds
/// # Returns
/// The received data as a vector of bytes
///
/// ***Verified:*** False
pub fn receive_with_timeout(
&self,
size: u32,
timeout: u32,
) -> Result<Vec<c_char>, ServiceError> {
let mut data = Vec::new();
let mut received = 0;
let result = unsafe {
unsafe_bindings::service_receive_with_timeout(
self.pointer,
data.as_mut_ptr() as *mut c_char,
size,
&mut received,
timeout,
)
}
.into();
if result != ServiceError::Success {
return Err(result);
}
Ok(data)
}
/// Toggles on the SSL for the communication between device and service
///
/// ***Verified:*** False
pub fn enable_ssl(&self) -> Result<(), ServiceError> {
let result = unsafe { unsafe_bindings::service_enable_ssl(self.pointer) }.into();
if result != ServiceError::Success {
return Err(result);
}
Ok(())
}
/// Toggles off the SSL for the communication between device and service
///
/// ***Verified:*** False
pub fn disable_ssl(&self) -> Result<(), ServiceError> {
let result = unsafe { unsafe_bindings::service_disable_ssl(self.pointer) }.into();
if result != ServiceError::Success {
return Err(result);
}
Ok(())
}
/// A hack for bypassing SSL
///
/// ***Verified:*** False
pub fn disable_bypass_ssl(&self, bypass: u8) -> Result<(), ServiceError> {
let result =
unsafe { unsafe_bindings::service_disable_bypass_ssl(self.pointer, bypass) }.into();
if result != ServiceError::Success {
return Err(result);
}
Ok(())
}
}
impl Drop for ServiceClient<'_> {
fn drop(&mut self) {
unsafe {
unsafe_bindings::service_client_free(self.pointer);
}
}
}