From c86c7b572949af76becd113230bc1784aadb1eb0 Mon Sep 17 00:00:00 2001 From: Hao Zhou Date: Tue, 9 Dec 2014 11:16:40 +0800 Subject: cython: Add DebugServerClient class to communicate with debugserver --- cython/Makefile.am | 3 +- cython/debugserver.pxi | 247 +++++++++++++++++++++++++++++++++++++++++++++++ cython/imobiledevice.pyx | 1 + 3 files changed, 250 insertions(+), 1 deletion(-) create mode 100644 cython/debugserver.pxi diff --git a/cython/Makefile.am b/cython/Makefile.am index 0261bfa..94ff728 100644 --- a/cython/Makefile.am +++ b/cython/Makefile.am @@ -24,7 +24,8 @@ PXIINCLUDES = \ misagent.pxi \ house_arrest.pxi \ restore.pxi \ - mobile_image_mounter.pxi + mobile_image_mounter.pxi \ + debugserver.pxi CLEANFILES = \ *.pyc \ diff --git a/cython/debugserver.pxi b/cython/debugserver.pxi new file mode 100644 index 0000000..ddbe066 --- /dev/null +++ b/cython/debugserver.pxi @@ -0,0 +1,247 @@ +cdef extern from "libimobiledevice/debugserver.h": + cdef struct debugserver_client_private: + pass + ctypedef debugserver_client_private *debugserver_client_t + cdef struct debugserver_command_private: + pass + ctypedef debugserver_command_private *debugserver_command_t + ctypedef enum debugserver_error_t: + DEBUGSERVER_E_SUCCESS = 0 + DEBUGSERVER_E_INVALID_ARG = -1 + DEBUGSERVER_E_MUX_ERROR = -2 + DEBUGSERVER_E_SSL_ERROR = -3 + DEBUGSERVER_E_RESPONSE_ERROR = -4 + DEBUGSERVER_E_UNKNOWN_ERROR = -256 + + debugserver_error_t debugserver_client_new(idevice_t device, lockdownd_service_descriptor_t service, debugserver_client_t * client) + debugserver_error_t debugserver_client_free(debugserver_client_t client) + + debugserver_error_t debugserver_client_send(debugserver_client_t client, const char* data, uint32_t size, uint32_t *sent) + debugserver_error_t debugserver_client_send_command(debugserver_client_t client, debugserver_command_t command, char** response) + debugserver_error_t debugserver_client_receive(debugserver_client_t client, char *data, uint32_t size, uint32_t *received) + debugserver_error_t debugserver_client_receive_with_timeout(debugserver_client_t client, char *data, uint32_t size, uint32_t *received, unsigned int timeout) + debugserver_error_t debugserver_client_receive_response(debugserver_client_t client, char** response) + debugserver_error_t debugserver_client_set_argv(debugserver_client_t client, int argc, char* argv[], char** response) + debugserver_error_t debugserver_client_set_environment_hex_encoded(debugserver_client_t client, const char* env, char** response) + + debugserver_error_t debugserver_command_new(const char* name, int argc, const char* argv[], debugserver_command_t* command) + debugserver_error_t debugserver_command_free(debugserver_command_t command) + void debugserver_encode_string(const char* buffer, char** encoded_buffer, uint32_t* encoded_length) + void debugserver_decode_string(const char *encoded_buffer, size_t encoded_length, char** buffer) + + +cdef class DebugServerError(BaseError): + def __init__(self, *args, **kwargs): + self._lookup_table = { + DEBUGSERVER_E_SUCCESS: "Success", + DEBUGSERVER_E_INVALID_ARG: "Invalid argument", + DEBUGSERVER_E_MUX_ERROR: "MUX error", + DEBUGSERVER_E_SSL_ERROR: "SSL error", + DEBUGSERVER_E_RESPONSE_ERROR: "Response error", + DEBUGSERVER_E_UNKNOWN_ERROR: "Unknown error", + } + BaseError.__init__(self, *args, **kwargs) + + +# from http://stackoverflow.com/a/17511714 +from cpython.string cimport PyString_AsString +cdef char ** to_cstring_array(list_str): + if not list_str: + return NULL + cdef char **ret = malloc(len(list_str) * sizeof(char *)) + for i in xrange(len(list_str)): + ret[i] = PyString_AsString(list_str[i]) + return ret + + +cdef class DebugServerCommand(Base): + cdef debugserver_command_t _c_command + + def __init__(self, bytes name, int argc = 0, argv = None, *args, **kwargs): + cdef: + char* c_name = name + char** c_argv = to_cstring_array(argv) + + try: + self.handle_error(debugserver_command_new(c_name, argc, c_argv, &self._c_command)) + except BaseError, e: + raise + finally: + free(c_argv) + + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + self.free() + + cdef free(self): + cdef debugserver_error_t err + if self._c_command is not NULL: + err = debugserver_command_free(self._c_command) + self.handle_error(err) + + cdef inline BaseError _error(self, int16_t ret): + return DebugServerError(ret) + + +cdef class DebugServerClient(BaseService): + __service_name__ = "com.apple.debugserver" + cdef debugserver_client_t _c_client + + def __cinit__(self, iDevice device = None, LockdownServiceDescriptor descriptor = None, *args, **kwargs): + if (device is not None and descriptor is not None): + self.handle_error(debugserver_client_new(device._c_dev, descriptor._c_service_descriptor, &(self._c_client))) + + def __dealloc__(self): + cdef debugserver_error_t err + if self._c_client is not NULL: + err = debugserver_client_free(self._c_client) + self.handle_error(err) + + cdef BaseError _error(self, int16_t ret): + return DebugServerError(ret) + + cpdef uint32_t send(self, bytes data): + cdef: + uint32_t bytes_send + char* c_data = data + try: + self.handle_error(debugserver_client_send(self._c_client, c_data, len(data), &bytes_send)) + except BaseError, e: + raise + + return bytes_send + + cpdef bytes send_command(self, DebugServerCommand command): + cdef: + char* c_response = NULL + bytes result + + try: + self.handle_error(debugserver_client_send_command(self._c_client, command._c_command, &c_response)) + if c_response: + result = c_response + return result + else: + return None + except BaseError, e: + raise + finally: + free(c_response) + + cpdef bytes receive(self, uint32_t size): + cdef: + uint32_t bytes_received + char* c_data = malloc(size) + bytes result + + try: + self.handle_error(debugserver_client_receive(self._c_client, c_data, size, &bytes_received)) + result = c_data[:bytes_received] + return result + except BaseError, e: + raise + finally: + free(c_data) + + cpdef bytes receive_with_timeout(self, uint32_t size, unsigned int timeout): + cdef: + uint32_t bytes_received + char* c_data = malloc(size) + bytes result + + try: + self.handle_error(debugserver_client_receive_with_timeout(self._c_client, c_data, size, &bytes_received, timeout)) + result = c_data[:bytes_received] + return result + except BaseError, e: + raise + finally: + free(c_data) + + cpdef bytes receive_response(self): + cdef: + char* c_response = NULL + bytes result + + try: + self.handle_error(debugserver_client_receive_response(self._c_client, &c_response)) + if c_response: + result = c_response + return result + else: + return None + except BaseError, e: + raise + finally: + free(c_response) + + cpdef bytes set_argv(self, int argc, argv): + cdef: + char** c_argv = to_cstring_array(argv) + char* c_response = NULL + bytes result + + try: + self.handle_error(debugserver_client_set_argv(self._c_client, argc, c_argv, &c_response)) + if c_response: + result = c_response + return result + else: + return None + except BaseError, e: + raise + finally: + free(c_argv) + free(c_response) + + cpdef bytes set_environment_hex_encoded(self, bytes env): + cdef: + char* c_env = env + char* c_response = NULL + bytes result + + try: + self.handle_error(debugserver_client_set_environment_hex_encoded(self._c_client, c_env, &c_response)) + if c_response: + result = c_response + return result + else: + return None + except BaseError, e: + raise + finally: + free(c_response) + + cpdef bytes encode_string(self, bytes buffer): + cdef: + char *c_buffer = buffer + uint32_t encoded_length = len(c_buffer) * 2 + 0x3 + 1 + char* c_encoded_buffer = malloc(encoded_length) + bytes result + + try: + debugserver_encode_string(c_buffer, &c_encoded_buffer, &encoded_length) + result = c_encoded_buffer[:encoded_length] + return result + except BaseError, e: + raise + finally: + free(c_encoded_buffer) + + cpdef bytes decode_string(self, bytes encoded_buffer): + cdef: + char* c_encoded_buffer = encoded_buffer + uint32_t encoded_length = len(c_encoded_buffer) + char *c_buffer = malloc(encoded_length) + bytes result + + try: + debugserver_decode_string(c_encoded_buffer, encoded_length, &c_buffer) + result = c_buffer + return result + except BaseError, e: + raise + finally: + free(c_buffer) diff --git a/cython/imobiledevice.pyx b/cython/imobiledevice.pyx index 607ff2f..e011223 100644 --- a/cython/imobiledevice.pyx +++ b/cython/imobiledevice.pyx @@ -256,3 +256,4 @@ include "diagnostics_relay.pxi" include "misagent.pxi" include "house_arrest.pxi" include "restore.pxi" +include "debugserver.pxi" -- cgit v1.1-32-gdbae