diff options
Diffstat (limited to 'cython/debugserver.pxi')
-rw-r--r-- | cython/debugserver.pxi | 252 |
1 files changed, 252 insertions, 0 deletions
diff --git a/cython/debugserver.pxi b/cython/debugserver.pxi new file mode 100644 index 0000000..a3b7d1e --- /dev/null +++ b/cython/debugserver.pxi | |||
@@ -0,0 +1,252 @@ | |||
1 | cdef extern from "libimobiledevice/debugserver.h": | ||
2 | cdef struct debugserver_client_private: | ||
3 | pass | ||
4 | ctypedef debugserver_client_private *debugserver_client_t | ||
5 | cdef struct debugserver_command_private: | ||
6 | pass | ||
7 | ctypedef debugserver_command_private *debugserver_command_t | ||
8 | ctypedef enum debugserver_error_t: | ||
9 | DEBUGSERVER_E_SUCCESS = 0 | ||
10 | DEBUGSERVER_E_INVALID_ARG = -1 | ||
11 | DEBUGSERVER_E_MUX_ERROR = -2 | ||
12 | DEBUGSERVER_E_SSL_ERROR = -3 | ||
13 | DEBUGSERVER_E_RESPONSE_ERROR = -4 | ||
14 | DEBUGSERVER_E_UNKNOWN_ERROR = -256 | ||
15 | |||
16 | debugserver_error_t debugserver_client_new(idevice_t device, lockdownd_service_descriptor_t service, debugserver_client_t * client) | ||
17 | debugserver_error_t debugserver_client_free(debugserver_client_t client) | ||
18 | |||
19 | debugserver_error_t debugserver_client_send(debugserver_client_t client, const char* data, uint32_t size, uint32_t *sent) | ||
20 | debugserver_error_t debugserver_client_send_command(debugserver_client_t client, debugserver_command_t command, char** response, size_t* response_size) | ||
21 | debugserver_error_t debugserver_client_receive(debugserver_client_t client, char *data, uint32_t size, uint32_t *received) | ||
22 | debugserver_error_t debugserver_client_receive_with_timeout(debugserver_client_t client, char *data, uint32_t size, uint32_t *received, unsigned int timeout) | ||
23 | debugserver_error_t debugserver_client_receive_response(debugserver_client_t client, char** response, size_t* response_size) | ||
24 | debugserver_error_t debugserver_client_set_argv(debugserver_client_t client, int argc, char* argv[], char** response) | ||
25 | debugserver_error_t debugserver_client_set_environment_hex_encoded(debugserver_client_t client, const char* env, char** response) | ||
26 | |||
27 | debugserver_error_t debugserver_command_new(const char* name, int argc, const char* argv[], debugserver_command_t* command) | ||
28 | debugserver_error_t debugserver_command_free(debugserver_command_t command) | ||
29 | void debugserver_encode_string(const char* buffer, char** encoded_buffer, uint32_t* encoded_length) | ||
30 | void debugserver_decode_string(const char *encoded_buffer, size_t encoded_length, char** buffer) | ||
31 | |||
32 | |||
33 | cdef class DebugServerError(BaseError): | ||
34 | def __init__(self, *args, **kwargs): | ||
35 | self._lookup_table = { | ||
36 | DEBUGSERVER_E_SUCCESS: "Success", | ||
37 | DEBUGSERVER_E_INVALID_ARG: "Invalid argument", | ||
38 | DEBUGSERVER_E_MUX_ERROR: "MUX error", | ||
39 | DEBUGSERVER_E_SSL_ERROR: "SSL error", | ||
40 | DEBUGSERVER_E_RESPONSE_ERROR: "Response error", | ||
41 | DEBUGSERVER_E_UNKNOWN_ERROR: "Unknown error", | ||
42 | } | ||
43 | BaseError.__init__(self, *args, **kwargs) | ||
44 | |||
45 | |||
46 | # from http://stackoverflow.com/a/17511714 | ||
47 | # https://github.com/libimobiledevice/libimobiledevice/pull/198 | ||
48 | from cpython cimport PY_MAJOR_VERSION | ||
49 | if PY_MAJOR_VERSION <= 2: | ||
50 | from cpython.string cimport PyString_AsString | ||
51 | else: | ||
52 | from cpython.bytes cimport PyBytes_AsString as PyString_AsString | ||
53 | cdef char ** to_cstring_array(list_str): | ||
54 | if not list_str: | ||
55 | return NULL | ||
56 | cdef char **ret = <char **>malloc(len(list_str) * sizeof(char *)) | ||
57 | for i in xrange(len(list_str)): | ||
58 | ret[i] = PyString_AsString(list_str[i]) | ||
59 | return ret | ||
60 | |||
61 | |||
62 | cdef class DebugServerCommand(Base): | ||
63 | cdef debugserver_command_t _c_command | ||
64 | |||
65 | def __init__(self, bytes name, int argc = 0, argv = None, *args, **kwargs): | ||
66 | cdef: | ||
67 | char* c_name = name | ||
68 | char** c_argv = to_cstring_array(argv) | ||
69 | |||
70 | try: | ||
71 | self.handle_error(debugserver_command_new(c_name, argc, c_argv, &self._c_command)) | ||
72 | except BaseError, e: | ||
73 | raise | ||
74 | finally: | ||
75 | free(c_argv) | ||
76 | |||
77 | def __enter__(self): | ||
78 | return self | ||
79 | |||
80 | def __exit__(self, type, value, traceback): | ||
81 | self.free() | ||
82 | |||
83 | cdef free(self): | ||
84 | cdef debugserver_error_t err | ||
85 | if self._c_command is not NULL: | ||
86 | err = debugserver_command_free(self._c_command) | ||
87 | self.handle_error(err) | ||
88 | |||
89 | cdef inline BaseError _error(self, int16_t ret): | ||
90 | return DebugServerError(ret) | ||
91 | |||
92 | |||
93 | cdef class DebugServerClient(BaseService): | ||
94 | __service_name__ = "com.apple.debugserver" | ||
95 | cdef debugserver_client_t _c_client | ||
96 | |||
97 | def __cinit__(self, iDevice device = None, LockdownServiceDescriptor descriptor = None, *args, **kwargs): | ||
98 | if (device is not None and descriptor is not None): | ||
99 | self.handle_error(debugserver_client_new(device._c_dev, descriptor._c_service_descriptor, &(self._c_client))) | ||
100 | |||
101 | def __dealloc__(self): | ||
102 | cdef debugserver_error_t err | ||
103 | if self._c_client is not NULL: | ||
104 | err = debugserver_client_free(self._c_client) | ||
105 | self.handle_error(err) | ||
106 | |||
107 | cdef BaseError _error(self, int16_t ret): | ||
108 | return DebugServerError(ret) | ||
109 | |||
110 | cpdef uint32_t send(self, bytes data): | ||
111 | cdef: | ||
112 | uint32_t bytes_send | ||
113 | char* c_data = data | ||
114 | try: | ||
115 | self.handle_error(debugserver_client_send(self._c_client, c_data, len(data), &bytes_send)) | ||
116 | except BaseError, e: | ||
117 | raise | ||
118 | |||
119 | return bytes_send | ||
120 | |||
121 | cpdef bytes send_command(self, DebugServerCommand command): | ||
122 | cdef: | ||
123 | char* c_response = NULL | ||
124 | bytes result | ||
125 | |||
126 | try: | ||
127 | self.handle_error(debugserver_client_send_command(self._c_client, command._c_command, &c_response, NULL)) | ||
128 | if c_response: | ||
129 | result = c_response | ||
130 | return result | ||
131 | else: | ||
132 | return None | ||
133 | except BaseError, e: | ||
134 | raise | ||
135 | finally: | ||
136 | free(c_response) | ||
137 | |||
138 | cpdef bytes receive(self, uint32_t size): | ||
139 | cdef: | ||
140 | uint32_t bytes_received | ||
141 | char* c_data = <char *>malloc(size) | ||
142 | bytes result | ||
143 | |||
144 | try: | ||
145 | self.handle_error(debugserver_client_receive(self._c_client, c_data, size, &bytes_received)) | ||
146 | result = c_data[:bytes_received] | ||
147 | return result | ||
148 | except BaseError, e: | ||
149 | raise | ||
150 | finally: | ||
151 | free(c_data) | ||
152 | |||
153 | cpdef bytes receive_with_timeout(self, uint32_t size, unsigned int timeout): | ||
154 | cdef: | ||
155 | uint32_t bytes_received | ||
156 | char* c_data = <char *>malloc(size) | ||
157 | bytes result | ||
158 | |||
159 | try: | ||
160 | self.handle_error(debugserver_client_receive_with_timeout(self._c_client, c_data, size, &bytes_received, timeout)) | ||
161 | result = c_data[:bytes_received] | ||
162 | return result | ||
163 | except BaseError, e: | ||
164 | raise | ||
165 | finally: | ||
166 | free(c_data) | ||
167 | |||
168 | cpdef bytes receive_response(self): | ||
169 | cdef: | ||
170 | char* c_response = NULL | ||
171 | bytes result | ||
172 | |||
173 | try: | ||
174 | self.handle_error(debugserver_client_receive_response(self._c_client, &c_response, NULL)) | ||
175 | if c_response: | ||
176 | result = c_response | ||
177 | return result | ||
178 | else: | ||
179 | return None | ||
180 | except BaseError, e: | ||
181 | raise | ||
182 | finally: | ||
183 | free(c_response) | ||
184 | |||
185 | cpdef bytes set_argv(self, int argc, argv): | ||
186 | cdef: | ||
187 | char** c_argv = to_cstring_array(argv) | ||
188 | char* c_response = NULL | ||
189 | bytes result | ||
190 | |||
191 | try: | ||
192 | self.handle_error(debugserver_client_set_argv(self._c_client, argc, c_argv, &c_response)) | ||
193 | if c_response: | ||
194 | result = c_response | ||
195 | return result | ||
196 | else: | ||
197 | return None | ||
198 | except BaseError, e: | ||
199 | raise | ||
200 | finally: | ||
201 | free(c_argv) | ||
202 | free(c_response) | ||
203 | |||
204 | cpdef bytes set_environment_hex_encoded(self, bytes env): | ||
205 | cdef: | ||
206 | char* c_env = env | ||
207 | char* c_response = NULL | ||
208 | bytes result | ||
209 | |||
210 | try: | ||
211 | self.handle_error(debugserver_client_set_environment_hex_encoded(self._c_client, c_env, &c_response)) | ||
212 | if c_response: | ||
213 | result = c_response | ||
214 | return result | ||
215 | else: | ||
216 | return None | ||
217 | except BaseError, e: | ||
218 | raise | ||
219 | finally: | ||
220 | free(c_response) | ||
221 | |||
222 | cpdef bytes encode_string(self, bytes buffer): | ||
223 | cdef: | ||
224 | char *c_buffer = buffer | ||
225 | uint32_t encoded_length = len(c_buffer) * 2 + 0x3 + 1 | ||
226 | char* c_encoded_buffer = <char *>malloc(encoded_length) | ||
227 | bytes result | ||
228 | |||
229 | try: | ||
230 | debugserver_encode_string(c_buffer, &c_encoded_buffer, &encoded_length) | ||
231 | result = c_encoded_buffer[:encoded_length] | ||
232 | return result | ||
233 | except BaseError, e: | ||
234 | raise | ||
235 | finally: | ||
236 | free(c_encoded_buffer) | ||
237 | |||
238 | cpdef bytes decode_string(self, bytes encoded_buffer): | ||
239 | cdef: | ||
240 | char* c_encoded_buffer = encoded_buffer | ||
241 | uint32_t encoded_length = len(c_encoded_buffer) | ||
242 | char *c_buffer = <char *>malloc(encoded_length) | ||
243 | bytes result | ||
244 | |||
245 | try: | ||
246 | debugserver_decode_string(c_encoded_buffer, encoded_length, &c_buffer) | ||
247 | result = c_buffer | ||
248 | return result | ||
249 | except BaseError, e: | ||
250 | raise | ||
251 | finally: | ||
252 | free(c_buffer) | ||