diff options
| -rw-r--r-- | cython/heartbeat.pxi | 4 | ||||
| -rw-r--r-- | cython/imobiledevice.pyx | 6 | ||||
| -rw-r--r-- | cython/webinspector.pxi | 2 | ||||
| -rw-r--r-- | include/libimobiledevice/heartbeat.h | 16 | ||||
| -rw-r--r-- | include/libimobiledevice/libimobiledevice.h | 4 | ||||
| -rw-r--r-- | include/libimobiledevice/property_list_service.h | 3 | ||||
| -rw-r--r-- | include/libimobiledevice/service.h | 10 | ||||
| -rw-r--r-- | include/libimobiledevice/webinspector.h | 14 | ||||
| -rw-r--r-- | src/heartbeat.c | 4 | ||||
| -rw-r--r-- | src/idevice.c | 59 | ||||
| -rw-r--r-- | src/property_list_service.c | 116 | ||||
| -rw-r--r-- | src/service.c | 7 | ||||
| -rw-r--r-- | src/webinspector.c | 4 | ||||
| -rw-r--r-- | tools/idevicecrashreport.c | 2 |
14 files changed, 163 insertions, 88 deletions
diff --git a/cython/heartbeat.pxi b/cython/heartbeat.pxi index b48fb59..2f58909 100644 --- a/cython/heartbeat.pxi +++ b/cython/heartbeat.pxi | |||
| @@ -9,6 +9,8 @@ cdef extern from "libimobiledevice/heartbeat.h": | |||
| 9 | HEARTBEAT_E_PLIST_ERROR = -2 | 9 | HEARTBEAT_E_PLIST_ERROR = -2 |
| 10 | HEARTBEAT_E_MUX_ERROR = -3 | 10 | HEARTBEAT_E_MUX_ERROR = -3 |
| 11 | HEARTBEAT_E_SSL_ERROR = -4 | 11 | HEARTBEAT_E_SSL_ERROR = -4 |
| 12 | HEARTBEAT_E_NOT_ENOUGH_DATA = -5 | ||
| 13 | HEARTBEAT_E_TIMEOUT = -6 | ||
| 12 | HEARTBEAT_E_UNKNOWN_ERROR = -256 | 14 | HEARTBEAT_E_UNKNOWN_ERROR = -256 |
| 13 | 15 | ||
| 14 | heartbeat_error_t heartbeat_client_new(idevice_t device, lockdownd_service_descriptor_t descriptor, heartbeat_client_t * client) | 16 | heartbeat_error_t heartbeat_client_new(idevice_t device, lockdownd_service_descriptor_t descriptor, heartbeat_client_t * client) |
| @@ -26,6 +28,8 @@ cdef class HeartbeatError(BaseError): | |||
| 26 | HEARTBEAT_E_PLIST_ERROR: "Property list error", | 28 | HEARTBEAT_E_PLIST_ERROR: "Property list error", |
| 27 | HEARTBEAT_E_MUX_ERROR: "MUX error", | 29 | HEARTBEAT_E_MUX_ERROR: "MUX error", |
| 28 | HEARTBEAT_E_SSL_ERROR: "SSL Error", | 30 | HEARTBEAT_E_SSL_ERROR: "SSL Error", |
| 31 | HEARTBEAT_E_NOT_ENOUGH_DATA: 'Not enough data', | ||
| 32 | HEARTBEAT_E_TIMEOUT: 'Connection timeout', | ||
| 29 | HEARTBEAT_E_UNKNOWN_ERROR: "Unknown error" | 33 | HEARTBEAT_E_UNKNOWN_ERROR: "Unknown error" |
| 30 | } | 34 | } |
| 31 | BaseError.__init__(self, *args, **kwargs) | 35 | BaseError.__init__(self, *args, **kwargs) |
diff --git a/cython/imobiledevice.pyx b/cython/imobiledevice.pyx index bc861b3..141f67c 100644 --- a/cython/imobiledevice.pyx +++ b/cython/imobiledevice.pyx | |||
| @@ -38,8 +38,8 @@ cdef extern from "libimobiledevice/libimobiledevice.h": | |||
| 38 | IDEVICE_E_UNKNOWN_ERROR = -2 | 38 | IDEVICE_E_UNKNOWN_ERROR = -2 |
| 39 | IDEVICE_E_NO_DEVICE = -3 | 39 | IDEVICE_E_NO_DEVICE = -3 |
| 40 | IDEVICE_E_NOT_ENOUGH_DATA = -4 | 40 | IDEVICE_E_NOT_ENOUGH_DATA = -4 |
| 41 | IDEVICE_E_BAD_HEADER = -5 | ||
| 42 | IDEVICE_E_SSL_ERROR = -6 | 41 | IDEVICE_E_SSL_ERROR = -6 |
| 42 | IDEVICE_E_TIMEOUT = -7 | ||
| 43 | ctypedef void (*idevice_event_cb_t) (const_idevice_event_t event, void *user_data) | 43 | ctypedef void (*idevice_event_cb_t) (const_idevice_event_t event, void *user_data) |
| 44 | cdef extern idevice_error_t idevice_event_subscribe(idevice_event_cb_t callback, void *user_data) | 44 | cdef extern idevice_error_t idevice_event_subscribe(idevice_event_cb_t callback, void *user_data) |
| 45 | cdef extern idevice_error_t idevice_event_unsubscribe() | 45 | cdef extern idevice_error_t idevice_event_unsubscribe() |
| @@ -64,8 +64,8 @@ cdef class iDeviceError(BaseError): | |||
| 64 | IDEVICE_E_UNKNOWN_ERROR: 'Unknown error', | 64 | IDEVICE_E_UNKNOWN_ERROR: 'Unknown error', |
| 65 | IDEVICE_E_NO_DEVICE: 'No device', | 65 | IDEVICE_E_NO_DEVICE: 'No device', |
| 66 | IDEVICE_E_NOT_ENOUGH_DATA: 'Not enough data', | 66 | IDEVICE_E_NOT_ENOUGH_DATA: 'Not enough data', |
| 67 | IDEVICE_E_BAD_HEADER: 'Bad header', | 67 | IDEVICE_E_SSL_ERROR: 'SSL Error', |
| 68 | IDEVICE_E_SSL_ERROR: 'SSL Error' | 68 | IDEVICE_E_TIMEOUT: 'Connection timeout' |
| 69 | } | 69 | } |
| 70 | BaseError.__init__(self, *args, **kwargs) | 70 | BaseError.__init__(self, *args, **kwargs) |
| 71 | 71 | ||
diff --git a/cython/webinspector.pxi b/cython/webinspector.pxi index 4622ef5..eb9fba1 100644 --- a/cython/webinspector.pxi +++ b/cython/webinspector.pxi | |||
| @@ -26,6 +26,8 @@ cdef class WebinspectorError(BaseError): | |||
| 26 | WEBINSPECTOR_E_PLIST_ERROR: "Property list error", | 26 | WEBINSPECTOR_E_PLIST_ERROR: "Property list error", |
| 27 | WEBINSPECTOR_E_MUX_ERROR: "MUX error", | 27 | WEBINSPECTOR_E_MUX_ERROR: "MUX error", |
| 28 | WEBINSPECTOR_E_SSL_ERROR: "SSL Error", | 28 | WEBINSPECTOR_E_SSL_ERROR: "SSL Error", |
| 29 | WEBINSPECTOR_E_NOT_ENOUGH_DATA: 'Not enough data', | ||
| 30 | WEBINSPECTOR_E_TIMEOUT: 'Connection timeout', | ||
| 29 | WEBINSPECTOR_E_UNKNOWN_ERROR: "Unknown error" | 31 | WEBINSPECTOR_E_UNKNOWN_ERROR: "Unknown error" |
| 30 | } | 32 | } |
| 31 | BaseError.__init__(self, *args, **kwargs) | 33 | BaseError.__init__(self, *args, **kwargs) |
diff --git a/include/libimobiledevice/heartbeat.h b/include/libimobiledevice/heartbeat.h index 00734b5..1f5344a 100644 --- a/include/libimobiledevice/heartbeat.h +++ b/include/libimobiledevice/heartbeat.h | |||
| @@ -34,12 +34,14 @@ extern "C" { | |||
| 34 | 34 | ||
| 35 | /** Error Codes */ | 35 | /** Error Codes */ |
| 36 | typedef enum { | 36 | typedef enum { |
| 37 | HEARTBEAT_E_SUCCESS = 0, | 37 | HEARTBEAT_E_SUCCESS = 0, |
| 38 | HEARTBEAT_E_INVALID_ARG = -1, | 38 | HEARTBEAT_E_INVALID_ARG = -1, |
| 39 | HEARTBEAT_E_PLIST_ERROR = -2, | 39 | HEARTBEAT_E_PLIST_ERROR = -2, |
| 40 | HEARTBEAT_E_MUX_ERROR = -3, | 40 | HEARTBEAT_E_MUX_ERROR = -3, |
| 41 | HEARTBEAT_E_SSL_ERROR = -4, | 41 | HEARTBEAT_E_SSL_ERROR = -4, |
| 42 | HEARTBEAT_E_UNKNOWN_ERROR = -256 | 42 | HEARTBEAT_E_NOT_ENOUGH_DATA = -5, |
| 43 | HEARTBEAT_E_TIMEOUT = -6, | ||
| 44 | HEARTBEAT_E_UNKNOWN_ERROR = -256 | ||
| 43 | } heartbeat_error_t; | 45 | } heartbeat_error_t; |
| 44 | 46 | ||
| 45 | typedef struct heartbeat_client_private heartbeat_client_private; | 47 | typedef struct heartbeat_client_private heartbeat_client_private; |
| @@ -118,6 +120,8 @@ heartbeat_error_t heartbeat_receive(heartbeat_client_t client, plist_t * plist); | |||
| 118 | * | 120 | * |
| 119 | * @return HEARTBEAT_E_SUCCESS on success, | 121 | * @return HEARTBEAT_E_SUCCESS on success, |
| 120 | * HEARTBEAT_E_INVALID_ARG when client or *plist is NULL, | 122 | * HEARTBEAT_E_INVALID_ARG when client or *plist is NULL, |
| 123 | * HEARTBEAT_E_NOT_ENOUGH_DATA when not enough data | ||
| 124 | * received, HEARTBEAT_E_TIMEOUT when the connection times out, | ||
| 121 | * HEARTBEAT_E_PLIST_ERROR when the received data cannot be | 125 | * HEARTBEAT_E_PLIST_ERROR when the received data cannot be |
| 122 | * converted to a plist, HEARTBEAT_E_MUX_ERROR when a | 126 | * converted to a plist, HEARTBEAT_E_MUX_ERROR when a |
| 123 | * communication error occurs, or HEARTBEAT_E_UNKNOWN_ERROR | 127 | * communication error occurs, or HEARTBEAT_E_UNKNOWN_ERROR |
diff --git a/include/libimobiledevice/libimobiledevice.h b/include/libimobiledevice/libimobiledevice.h index 5ec1a6d..729bc89 100644 --- a/include/libimobiledevice/libimobiledevice.h +++ b/include/libimobiledevice/libimobiledevice.h | |||
| @@ -41,8 +41,8 @@ typedef enum { | |||
| 41 | IDEVICE_E_UNKNOWN_ERROR = -2, | 41 | IDEVICE_E_UNKNOWN_ERROR = -2, |
| 42 | IDEVICE_E_NO_DEVICE = -3, | 42 | IDEVICE_E_NO_DEVICE = -3, |
| 43 | IDEVICE_E_NOT_ENOUGH_DATA = -4, | 43 | IDEVICE_E_NOT_ENOUGH_DATA = -4, |
| 44 | IDEVICE_E_BAD_HEADER = -5, | 44 | IDEVICE_E_SSL_ERROR = -6, |
| 45 | IDEVICE_E_SSL_ERROR = -6 | 45 | IDEVICE_E_TIMEOUT = -7 |
| 46 | } idevice_error_t; | 46 | } idevice_error_t; |
| 47 | 47 | ||
| 48 | typedef struct idevice_private idevice_private; | 48 | typedef struct idevice_private idevice_private; |
diff --git a/include/libimobiledevice/property_list_service.h b/include/libimobiledevice/property_list_service.h index 5d5b835..aca966d 100644 --- a/include/libimobiledevice/property_list_service.h +++ b/include/libimobiledevice/property_list_service.h | |||
| @@ -38,6 +38,7 @@ typedef enum { | |||
| 38 | PROPERTY_LIST_SERVICE_E_MUX_ERROR = -3, | 38 | PROPERTY_LIST_SERVICE_E_MUX_ERROR = -3, |
| 39 | PROPERTY_LIST_SERVICE_E_SSL_ERROR = -4, | 39 | PROPERTY_LIST_SERVICE_E_SSL_ERROR = -4, |
| 40 | PROPERTY_LIST_SERVICE_E_RECEIVE_TIMEOUT = -5, | 40 | PROPERTY_LIST_SERVICE_E_RECEIVE_TIMEOUT = -5, |
| 41 | PROPERTY_LIST_SERVICE_E_NOT_ENOUGH_DATA = -6, | ||
| 41 | PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR = -256 | 42 | PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR = -256 |
| 42 | } property_list_service_error_t; | 43 | } property_list_service_error_t; |
| 43 | 44 | ||
| @@ -130,6 +131,8 @@ property_list_service_error_t property_list_service_receive_plist_with_timeout(p | |||
| 130 | * | 131 | * |
| 131 | * @return PROPERTY_LIST_SERVICE_E_SUCCESS on success, | 132 | * @return PROPERTY_LIST_SERVICE_E_SUCCESS on success, |
| 132 | * PROPERTY_LIST_SERVICE_E_INVALID_ARG when client or *plist is NULL, | 133 | * PROPERTY_LIST_SERVICE_E_INVALID_ARG when client or *plist is NULL, |
| 134 | * PROPERTY_LIST_SERVICE_E_NOT_ENOUGH_DATA when not enough data | ||
| 135 | * received, PROPERTY_LIST_SERVICE_E_RECEIVE_TIMEOUT when the connection times out, | ||
| 133 | * PROPERTY_LIST_SERVICE_E_PLIST_ERROR when the received data cannot be | 136 | * PROPERTY_LIST_SERVICE_E_PLIST_ERROR when the received data cannot be |
| 134 | * converted to a plist, PROPERTY_LIST_SERVICE_E_MUX_ERROR when a | 137 | * converted to a plist, PROPERTY_LIST_SERVICE_E_MUX_ERROR when a |
| 135 | * communication error occurs, or PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR when | 138 | * communication error occurs, or PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR when |
diff --git a/include/libimobiledevice/service.h b/include/libimobiledevice/service.h index 13c5df1..5c43e29 100644 --- a/include/libimobiledevice/service.h +++ b/include/libimobiledevice/service.h | |||
| @@ -37,6 +37,8 @@ typedef enum { | |||
| 37 | SERVICE_E_MUX_ERROR = -3, | 37 | SERVICE_E_MUX_ERROR = -3, |
| 38 | SERVICE_E_SSL_ERROR = -4, | 38 | SERVICE_E_SSL_ERROR = -4, |
| 39 | SERVICE_E_START_SERVICE_ERROR = -5, | 39 | SERVICE_E_START_SERVICE_ERROR = -5, |
| 40 | SERIVCE_E_NOT_ENOUGH_DATA = -6, | ||
| 41 | SERVICE_E_TIMEOUT = -7, | ||
| 40 | SERVICE_E_UNKNOWN_ERROR = -256 | 42 | SERVICE_E_UNKNOWN_ERROR = -256 |
| 41 | } service_error_t; | 43 | } service_error_t; |
| 42 | 44 | ||
| @@ -132,7 +134,9 @@ service_error_t service_receive_with_timeout(service_client_t client, char *data | |||
| 132 | * | 134 | * |
| 133 | * @return SERVICE_E_SUCCESS on success, | 135 | * @return SERVICE_E_SUCCESS on success, |
| 134 | * SERVICE_E_INVALID_ARG when one or more parameters are | 136 | * SERVICE_E_INVALID_ARG when one or more parameters are |
| 135 | * invalid, SERVICE_E_MUX_ERROR when a communication error | 137 | * invalid, SERIVCE_E_NOT_ENOUGH_DATA when not enough data |
| 138 | * received, SERVICE_E_TIMEOUT when the connection times out, | ||
| 139 | * SERVICE_E_MUX_ERROR when a communication error | ||
| 136 | * occurs, or SERVICE_E_UNKNOWN_ERROR when an unspecified | 140 | * occurs, or SERVICE_E_UNKNOWN_ERROR when an unspecified |
| 137 | * error occurs. | 141 | * error occurs. |
| 138 | */ | 142 | */ |
| @@ -146,7 +150,9 @@ service_error_t service_receive(service_client_t client, char *data, uint32_t si | |||
| 146 | * | 150 | * |
| 147 | * @return SERVICE_E_SUCCESS on success, | 151 | * @return SERVICE_E_SUCCESS on success, |
| 148 | * SERVICE_E_INVALID_ARG if client or client->connection is | 152 | * SERVICE_E_INVALID_ARG if client or client->connection is |
| 149 | * NULL, SERVICE_E_SSL_ERROR when SSL could not be enabled, | 153 | * NULL, SERIVCE_E_NOT_ENOUGH_DATA when not enough data |
| 154 | * received, SERVICE_E_TIMEOUT when the connection times out, | ||
| 155 | * SERVICE_E_SSL_ERROR when SSL could not be enabled, | ||
| 150 | * or SERVICE_E_UNKNOWN_ERROR otherwise. | 156 | * or SERVICE_E_UNKNOWN_ERROR otherwise. |
| 151 | */ | 157 | */ |
| 152 | service_error_t service_enable_ssl(service_client_t client); | 158 | service_error_t service_enable_ssl(service_client_t client); |
diff --git a/include/libimobiledevice/webinspector.h b/include/libimobiledevice/webinspector.h index d2a99c9..da0759c 100644 --- a/include/libimobiledevice/webinspector.h +++ b/include/libimobiledevice/webinspector.h | |||
| @@ -35,12 +35,14 @@ extern "C" { | |||
| 35 | 35 | ||
| 36 | /** Error Codes */ | 36 | /** Error Codes */ |
| 37 | typedef enum { | 37 | typedef enum { |
| 38 | WEBINSPECTOR_E_SUCCESS = 0, | 38 | WEBINSPECTOR_E_SUCCESS = 0, |
| 39 | WEBINSPECTOR_E_INVALID_ARG = -1, | 39 | WEBINSPECTOR_E_INVALID_ARG = -1, |
| 40 | WEBINSPECTOR_E_PLIST_ERROR = -2, | 40 | WEBINSPECTOR_E_PLIST_ERROR = -2, |
| 41 | WEBINSPECTOR_E_MUX_ERROR = -3, | 41 | WEBINSPECTOR_E_MUX_ERROR = -3, |
| 42 | WEBINSPECTOR_E_SSL_ERROR = -4, | 42 | WEBINSPECTOR_E_SSL_ERROR = -4, |
| 43 | WEBINSPECTOR_E_UNKNOWN_ERROR = -256 | 43 | WEBINSPECTOR_E_RECEIVE_TIMEOUT = -5, |
| 44 | WEBINSPECTOR_E_NOT_ENOUGH_DATA = -6, | ||
| 45 | WEBINSPECTOR_E_UNKNOWN_ERROR = -256 | ||
| 44 | } webinspector_error_t; | 46 | } webinspector_error_t; |
| 45 | 47 | ||
| 46 | typedef struct webinspector_client_private webinspector_client_private; | 48 | typedef struct webinspector_client_private webinspector_client_private; |
diff --git a/src/heartbeat.c b/src/heartbeat.c index fe7e63a..9a527cc 100644 --- a/src/heartbeat.c +++ b/src/heartbeat.c | |||
| @@ -52,6 +52,10 @@ static heartbeat_error_t heartbeat_error(property_list_service_error_t err) | |||
| 52 | return HEARTBEAT_E_MUX_ERROR; | 52 | return HEARTBEAT_E_MUX_ERROR; |
| 53 | case PROPERTY_LIST_SERVICE_E_SSL_ERROR: | 53 | case PROPERTY_LIST_SERVICE_E_SSL_ERROR: |
| 54 | return HEARTBEAT_E_SSL_ERROR; | 54 | return HEARTBEAT_E_SSL_ERROR; |
| 55 | case PROPERTY_LIST_SERVICE_E_NOT_ENOUGH_DATA: | ||
| 56 | return HEARTBEAT_E_NOT_ENOUGH_DATA; | ||
| 57 | case PROPERTY_LIST_SERVICE_E_RECEIVE_TIMEOUT: | ||
| 58 | return HEARTBEAT_E_TIMEOUT; | ||
| 55 | default: | 59 | default: |
| 56 | break; | 60 | break; |
| 57 | } | 61 | } |
diff --git a/src/idevice.c b/src/idevice.c index be29884..5d5c950 100644 --- a/src/idevice.c +++ b/src/idevice.c | |||
| @@ -43,6 +43,7 @@ | |||
| 43 | 43 | ||
| 44 | #include "idevice.h" | 44 | #include "idevice.h" |
| 45 | #include "common/userpref.h" | 45 | #include "common/userpref.h" |
| 46 | #include "common/socket.h" | ||
| 46 | #include "common/thread.h" | 47 | #include "common/thread.h" |
| 47 | #include "common/debug.h" | 48 | #include "common/debug.h" |
| 48 | 49 | ||
| @@ -381,6 +382,24 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_send(idevice_connection_ | |||
| 381 | return internal_connection_send(connection, data, len, sent_bytes); | 382 | return internal_connection_send(connection, data, len, sent_bytes); |
| 382 | } | 383 | } |
| 383 | 384 | ||
| 385 | static idevice_error_t socket_recv_to_idevice_error(int conn_error, uint32_t len, uint32_t received) | ||
| 386 | { | ||
| 387 | if (conn_error < 0) { | ||
| 388 | switch (conn_error) { | ||
| 389 | case -EAGAIN: | ||
| 390 | debug_info("ERROR: received partial data %d/%d (%s)", received, len, strerror(-conn_error)); | ||
| 391 | return IDEVICE_E_NOT_ENOUGH_DATA; | ||
| 392 | case -ETIMEDOUT: | ||
| 393 | debug_info("ERROR: received timeout (%s)", strerror(-conn_error)); | ||
| 394 | return IDEVICE_E_TIMEOUT; | ||
| 395 | default: | ||
| 396 | return IDEVICE_E_UNKNOWN_ERROR; | ||
| 397 | } | ||
| 398 | } | ||
| 399 | |||
| 400 | return IDEVICE_E_SUCCESS; | ||
| 401 | } | ||
| 402 | |||
| 384 | /** | 403 | /** |
| 385 | * Internally used function for receiving raw data over the given connection | 404 | * Internally used function for receiving raw data over the given connection |
| 386 | * using a timeout. | 405 | * using a timeout. |
| @@ -392,12 +411,14 @@ static idevice_error_t internal_connection_receive_timeout(idevice_connection_t | |||
| 392 | } | 411 | } |
| 393 | 412 | ||
| 394 | if (connection->type == CONNECTION_USBMUXD) { | 413 | if (connection->type == CONNECTION_USBMUXD) { |
| 395 | int res = usbmuxd_recv_timeout((int)(long)connection->data, data, len, recv_bytes, timeout); | 414 | int conn_error = usbmuxd_recv_timeout((int)(long)connection->data, data, len, recv_bytes, timeout); |
| 396 | if (res < 0) { | 415 | idevice_error_t error = socket_recv_to_idevice_error(conn_error, len, *recv_bytes); |
| 397 | debug_info("ERROR: usbmuxd_recv_timeout returned %d (%s)", res, strerror(errno)); | 416 | |
| 398 | return (res == -EAGAIN ? IDEVICE_E_NOT_ENOUGH_DATA : IDEVICE_E_UNKNOWN_ERROR); | 417 | if (error == IDEVICE_E_UNKNOWN_ERROR) { |
| 418 | debug_info("ERROR: usbmuxd_recv_timeout returned %d (%s)", conn_error, strerror(-conn_error)); | ||
| 399 | } | 419 | } |
| 400 | return IDEVICE_E_SUCCESS; | 420 | |
| 421 | return error; | ||
| 401 | } else { | 422 | } else { |
| 402 | debug_info("Unknown connection type %d", connection->type); | 423 | debug_info("Unknown connection type %d", connection->type); |
| 403 | } | 424 | } |
| @@ -406,13 +427,27 @@ static idevice_error_t internal_connection_receive_timeout(idevice_connection_t | |||
| 406 | 427 | ||
| 407 | LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_receive_timeout(idevice_connection_t connection, char *data, uint32_t len, uint32_t *recv_bytes, unsigned int timeout) | 428 | LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_receive_timeout(idevice_connection_t connection, char *data, uint32_t len, uint32_t *recv_bytes, unsigned int timeout) |
| 408 | { | 429 | { |
| 409 | if (!connection || (connection->ssl_data && !connection->ssl_data->session)) { | 430 | if (!connection || (connection->ssl_data && !connection->ssl_data->session) || len == 0) { |
| 410 | return IDEVICE_E_INVALID_ARG; | 431 | return IDEVICE_E_INVALID_ARG; |
| 411 | } | 432 | } |
| 412 | 433 | ||
| 413 | if (connection->ssl_data) { | 434 | if (connection->ssl_data) { |
| 414 | uint32_t received = 0; | 435 | uint32_t received = 0; |
| 436 | |||
| 415 | while (received < len) { | 437 | while (received < len) { |
| 438 | |||
| 439 | int conn_error = socket_check_fd((int)(long)connection->data, FDM_READ, timeout); | ||
| 440 | idevice_error_t error = socket_recv_to_idevice_error(conn_error, len, received); | ||
| 441 | |||
| 442 | switch (error) { | ||
| 443 | case IDEVICE_E_SUCCESS: | ||
| 444 | break; | ||
| 445 | case IDEVICE_E_UNKNOWN_ERROR: | ||
| 446 | debug_info("ERROR: socket_check_fd returned %d (%s)", conn_error, strerror(-conn_error)); | ||
| 447 | default: | ||
| 448 | return error; | ||
| 449 | } | ||
| 450 | |||
| 416 | #ifdef HAVE_OPENSSL | 451 | #ifdef HAVE_OPENSSL |
| 417 | int r = SSL_read(connection->ssl_data->session, (void*)((char*)(data+received)), (int)len-received); | 452 | int r = SSL_read(connection->ssl_data->session, (void*)((char*)(data+received)), (int)len-received); |
| 418 | #else | 453 | #else |
| @@ -424,13 +459,15 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_receive_timeout(idevice_ | |||
| 424 | break; | 459 | break; |
| 425 | } | 460 | } |
| 426 | } | 461 | } |
| 462 | |||
| 427 | debug_info("SSL_read %d, received %d", len, received); | 463 | debug_info("SSL_read %d, received %d", len, received); |
| 428 | if (received > 0) { | 464 | if (received < len) { |
| 429 | *recv_bytes = received; | 465 | *recv_bytes = 0; |
| 430 | return IDEVICE_E_SUCCESS; | 466 | return IDEVICE_E_SSL_ERROR; |
| 431 | } | 467 | } |
| 432 | *recv_bytes = 0; | 468 | |
| 433 | return IDEVICE_E_SSL_ERROR; | 469 | *recv_bytes = received; |
| 470 | return IDEVICE_E_SUCCESS; | ||
| 434 | } | 471 | } |
| 435 | return internal_connection_receive_timeout(connection, data, len, recv_bytes, timeout); | 472 | return internal_connection_receive_timeout(connection, data, len, recv_bytes, timeout); |
| 436 | } | 473 | } |
diff --git a/src/property_list_service.c b/src/property_list_service.c index f411699..a6e3e24 100644 --- a/src/property_list_service.c +++ b/src/property_list_service.c | |||
| @@ -48,6 +48,10 @@ static property_list_service_error_t service_to_property_list_service_error(serv | |||
| 48 | return PROPERTY_LIST_SERVICE_E_MUX_ERROR; | 48 | return PROPERTY_LIST_SERVICE_E_MUX_ERROR; |
| 49 | case SERVICE_E_SSL_ERROR: | 49 | case SERVICE_E_SSL_ERROR: |
| 50 | return PROPERTY_LIST_SERVICE_E_SSL_ERROR; | 50 | return PROPERTY_LIST_SERVICE_E_SSL_ERROR; |
| 51 | case SERIVCE_E_NOT_ENOUGH_DATA: | ||
| 52 | return PROPERTY_LIST_SERVICE_E_NOT_ENOUGH_DATA; | ||
| 53 | case SERVICE_E_TIMEOUT: | ||
| 54 | return PROPERTY_LIST_SERVICE_E_RECEIVE_TIMEOUT; | ||
| 51 | default: | 55 | default: |
| 52 | break; | 56 | break; |
| 53 | } | 57 | } |
| @@ -108,7 +112,7 @@ static property_list_service_error_t internal_plist_send(property_list_service_c | |||
| 108 | char *content = NULL; | 112 | char *content = NULL; |
| 109 | uint32_t length = 0; | 113 | uint32_t length = 0; |
| 110 | uint32_t nlen = 0; | 114 | uint32_t nlen = 0; |
| 111 | int bytes = 0; | 115 | uint32_t bytes = 0; |
| 112 | 116 | ||
| 113 | if (!client || (client && !client->parent) || !plist) { | 117 | if (!client || (client && !client->parent) || !plist) { |
| 114 | return PROPERTY_LIST_SERVICE_E_INVALID_ARG; | 118 | return PROPERTY_LIST_SERVICE_E_INVALID_ARG; |
| @@ -126,13 +130,13 @@ static property_list_service_error_t internal_plist_send(property_list_service_c | |||
| 126 | 130 | ||
| 127 | nlen = htobe32(length); | 131 | nlen = htobe32(length); |
| 128 | debug_info("sending %d bytes", length); | 132 | debug_info("sending %d bytes", length); |
| 129 | service_send(client->parent, (const char*)&nlen, sizeof(nlen), (uint32_t*)&bytes); | 133 | service_send(client->parent, (const char*)&nlen, sizeof(nlen), &bytes); |
| 130 | if (bytes == sizeof(nlen)) { | 134 | if (bytes == sizeof(nlen)) { |
| 131 | service_send(client->parent, content, length, (uint32_t*)&bytes); | 135 | service_send(client->parent, content, length, &bytes); |
| 132 | if (bytes > 0) { | 136 | if (bytes > 0) { |
| 133 | debug_info("sent %d bytes", bytes); | 137 | debug_info("sent %d bytes", bytes); |
| 134 | debug_plist(plist); | 138 | debug_plist(plist); |
| 135 | if ((uint32_t)bytes == length) { | 139 | if (bytes == length) { |
| 136 | res = PROPERTY_LIST_SERVICE_E_SUCCESS; | 140 | res = PROPERTY_LIST_SERVICE_E_SUCCESS; |
| 137 | } else { | 141 | } else { |
| 138 | debug_info("ERROR: Could not send all data (%d of %d)!", bytes, length); | 142 | debug_info("ERROR: Could not send all data (%d of %d)!", bytes, length); |
| @@ -145,7 +149,6 @@ static property_list_service_error_t internal_plist_send(property_list_service_c | |||
| 145 | } | 149 | } |
| 146 | 150 | ||
| 147 | free(content); | 151 | free(content); |
| 148 | |||
| 149 | return res; | 152 | return res; |
| 150 | } | 153 | } |
| 151 | 154 | ||
| @@ -170,6 +173,8 @@ LIBIMOBILEDEVICE_API property_list_service_error_t property_list_service_send_bi | |||
| 170 | * | 173 | * |
| 171 | * @return PROPERTY_LIST_SERVICE_E_SUCCESS on success, | 174 | * @return PROPERTY_LIST_SERVICE_E_SUCCESS on success, |
| 172 | * PROPERTY_LIST_SERVICE_E_INVALID_ARG when client or *plist is NULL, | 175 | * PROPERTY_LIST_SERVICE_E_INVALID_ARG when client or *plist is NULL, |
| 176 | * PROPERTY_LIST_SERVICE_E_NOT_ENOUGH_DATA when not enough data | ||
| 177 | * received, PROPERTY_LIST_SERVICE_E_RECEIVE_TIMEOUT when the connection times out, | ||
| 173 | * PROPERTY_LIST_SERVICE_E_PLIST_ERROR when the received data cannot be | 178 | * PROPERTY_LIST_SERVICE_E_PLIST_ERROR when the received data cannot be |
| 174 | * converted to a plist, PROPERTY_LIST_SERVICE_E_MUX_ERROR when a | 179 | * converted to a plist, PROPERTY_LIST_SERVICE_E_MUX_ERROR when a |
| 175 | * communication error occurs, or PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR | 180 | * communication error occurs, or PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR |
| @@ -187,65 +192,64 @@ static property_list_service_error_t internal_plist_receive_timeout(property_lis | |||
| 187 | 192 | ||
| 188 | *plist = NULL; | 193 | *plist = NULL; |
| 189 | service_error_t serr = service_receive_with_timeout(client->parent, (char*)&pktlen, sizeof(pktlen), &bytes, timeout); | 194 | service_error_t serr = service_receive_with_timeout(client->parent, (char*)&pktlen, sizeof(pktlen), &bytes, timeout); |
| 190 | if ((serr == SERVICE_E_SUCCESS) && (bytes == 0)) { | 195 | if (serr != SERVICE_E_SUCCESS) { |
| 191 | return PROPERTY_LIST_SERVICE_E_RECEIVE_TIMEOUT; | 196 | debug_info("initial read failed!"); |
| 197 | return service_to_property_list_service_error(serr); | ||
| 192 | } | 198 | } |
| 199 | |||
| 193 | debug_info("initial read=%i", bytes); | 200 | debug_info("initial read=%i", bytes); |
| 194 | if (bytes < 4) { | ||
| 195 | debug_info("initial read failed!"); | ||
| 196 | return PROPERTY_LIST_SERVICE_E_MUX_ERROR; | ||
| 197 | } else { | ||
| 198 | uint32_t curlen = 0; | ||
| 199 | char *content = NULL; | ||
| 200 | 201 | ||
| 201 | pktlen = be32toh(pktlen); | 202 | uint32_t curlen = 0; |
| 202 | debug_info("%d bytes following", pktlen); | 203 | char *content = NULL; |
| 203 | content = (char*)malloc(pktlen); | ||
| 204 | if (!content) { | ||
| 205 | debug_info("out of memory when allocating %d bytes", pktlen); | ||
| 206 | return PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR; | ||
| 207 | } | ||
| 208 | 204 | ||
| 209 | while (curlen < pktlen) { | 205 | pktlen = be32toh(pktlen); |
| 210 | service_receive(client->parent, content+curlen, pktlen-curlen, &bytes); | 206 | debug_info("%d bytes following", pktlen); |
| 211 | if (bytes <= 0) { | 207 | content = (char*)malloc(pktlen); |
| 212 | res = PROPERTY_LIST_SERVICE_E_MUX_ERROR; | 208 | if (!content) { |
| 213 | break; | 209 | debug_info("out of memory when allocating %d bytes", pktlen); |
| 214 | } | 210 | return PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR; |
| 215 | debug_info("received %d bytes", bytes); | 211 | } |
| 216 | curlen += bytes; | 212 | |
| 217 | } | 213 | while (curlen < pktlen) { |
| 218 | if (curlen < pktlen) { | 214 | serr = service_receive(client->parent, content+curlen, pktlen-curlen, &bytes); |
| 219 | debug_info("received incomplete packet (%d of %d bytes)", curlen, pktlen); | 215 | if (serr != SERVICE_E_SUCCESS) { |
| 220 | if (curlen > 0) { | 216 | res = service_to_property_list_service_error(serr); |
| 221 | debug_info("incomplete packet following:"); | 217 | break; |
| 222 | debug_buffer(content, curlen); | ||
| 223 | } | ||
| 224 | free(content); | ||
| 225 | return res; | ||
| 226 | } | ||
| 227 | if ((pktlen > 8) && !memcmp(content, "bplist00", 8)) { | ||
| 228 | plist_from_bin(content, pktlen, plist); | ||
| 229 | } else if ((pktlen > 5) && !memcmp(content, "<?xml", 5)) { | ||
| 230 | /* iOS 4.3+ hack: plist data might contain invalid characters, thus we convert those to spaces */ | ||
| 231 | for (bytes = 0; bytes < pktlen-1; bytes++) { | ||
| 232 | if ((content[bytes] >= 0) && (content[bytes] < 0x20) && (content[bytes] != 0x09) && (content[bytes] != 0x0a) && (content[bytes] != 0x0d)) | ||
| 233 | content[bytes] = 0x20; | ||
| 234 | } | ||
| 235 | plist_from_xml(content, pktlen, plist); | ||
| 236 | } else { | ||
| 237 | debug_info("WARNING: received unexpected non-plist content"); | ||
| 238 | debug_buffer(content, pktlen); | ||
| 239 | } | 218 | } |
| 240 | if (*plist) { | 219 | debug_info("received %d bytes", bytes); |
| 241 | debug_plist(*plist); | 220 | curlen += bytes; |
| 242 | res = PROPERTY_LIST_SERVICE_E_SUCCESS; | 221 | } |
| 243 | } else { | 222 | if (curlen < pktlen) { |
| 244 | res = PROPERTY_LIST_SERVICE_E_PLIST_ERROR; | 223 | debug_info("received incomplete packet (%d of %d bytes)", curlen, pktlen); |
| 224 | if (curlen > 0) { | ||
| 225 | debug_info("incomplete packet following:"); | ||
| 226 | debug_buffer(content, curlen); | ||
| 245 | } | 227 | } |
| 246 | free(content); | 228 | free(content); |
| 247 | content = NULL; | 229 | return res; |
| 248 | } | 230 | } |
| 231 | if ((pktlen > 8) && !memcmp(content, "bplist00", 8)) { | ||
| 232 | plist_from_bin(content, pktlen, plist); | ||
| 233 | } else if ((pktlen > 5) && !memcmp(content, "<?xml", 5)) { | ||
| 234 | /* iOS 4.3+ hack: plist data might contain invalid characters, thus we convert those to spaces */ | ||
| 235 | for (bytes = 0; bytes < pktlen-1; bytes++) { | ||
| 236 | if ((content[bytes] >= 0) && (content[bytes] < 0x20) && (content[bytes] != 0x09) && (content[bytes] != 0x0a) && (content[bytes] != 0x0d)) | ||
| 237 | content[bytes] = 0x20; | ||
| 238 | } | ||
| 239 | plist_from_xml(content, pktlen, plist); | ||
| 240 | } else { | ||
| 241 | debug_info("WARNING: received unexpected non-plist content"); | ||
| 242 | debug_buffer(content, pktlen); | ||
| 243 | } | ||
| 244 | if (*plist) { | ||
| 245 | debug_plist(*plist); | ||
| 246 | res = PROPERTY_LIST_SERVICE_E_SUCCESS; | ||
| 247 | } else { | ||
| 248 | res = PROPERTY_LIST_SERVICE_E_PLIST_ERROR; | ||
| 249 | } | ||
| 250 | free(content); | ||
| 251 | content = NULL; | ||
| 252 | |||
| 249 | return res; | 253 | return res; |
| 250 | } | 254 | } |
| 251 | 255 | ||
diff --git a/src/service.c b/src/service.c index 2dc42b2..57d987c 100644 --- a/src/service.c +++ b/src/service.c | |||
| @@ -46,6 +46,10 @@ static service_error_t idevice_to_service_error(idevice_error_t err) | |||
| 46 | return SERVICE_E_INVALID_ARG; | 46 | return SERVICE_E_INVALID_ARG; |
| 47 | case IDEVICE_E_SSL_ERROR: | 47 | case IDEVICE_E_SSL_ERROR: |
| 48 | return SERVICE_E_SSL_ERROR; | 48 | return SERVICE_E_SSL_ERROR; |
| 49 | case IDEVICE_E_NOT_ENOUGH_DATA: | ||
| 50 | return SERIVCE_E_NOT_ENOUGH_DATA; | ||
| 51 | case IDEVICE_E_TIMEOUT: | ||
| 52 | return SERVICE_E_TIMEOUT; | ||
| 49 | default: | 53 | default: |
| 50 | break; | 54 | break; |
| 51 | } | 55 | } |
| @@ -159,8 +163,9 @@ LIBIMOBILEDEVICE_API service_error_t service_receive_with_timeout(service_client | |||
| 159 | } | 163 | } |
| 160 | 164 | ||
| 161 | res = idevice_to_service_error(idevice_connection_receive_timeout(client->connection, data, size, (uint32_t*)&bytes, timeout)); | 165 | res = idevice_to_service_error(idevice_connection_receive_timeout(client->connection, data, size, (uint32_t*)&bytes, timeout)); |
| 162 | if (bytes <= 0) { | 166 | if (res != SERVICE_E_SUCCESS) { |
| 163 | debug_info("could not read data"); | 167 | debug_info("could not read data"); |
| 168 | return res; | ||
| 164 | } | 169 | } |
| 165 | if (received) { | 170 | if (received) { |
| 166 | *received = (uint32_t)bytes; | 171 | *received = (uint32_t)bytes; |
diff --git a/src/webinspector.c b/src/webinspector.c index c81f4c7..3360597 100644 --- a/src/webinspector.c +++ b/src/webinspector.c | |||
| @@ -52,6 +52,10 @@ static webinspector_error_t webinspector_error(property_list_service_error_t err | |||
| 52 | return WEBINSPECTOR_E_MUX_ERROR; | 52 | return WEBINSPECTOR_E_MUX_ERROR; |
| 53 | case PROPERTY_LIST_SERVICE_E_SSL_ERROR: | 53 | case PROPERTY_LIST_SERVICE_E_SSL_ERROR: |
| 54 | return WEBINSPECTOR_E_SSL_ERROR; | 54 | return WEBINSPECTOR_E_SSL_ERROR; |
| 55 | case PROPERTY_LIST_SERVICE_E_RECEIVE_TIMEOUT: | ||
| 56 | return WEBINSPECTOR_E_RECEIVE_TIMEOUT; | ||
| 57 | case PROPERTY_LIST_SERVICE_E_NOT_ENOUGH_DATA: | ||
| 58 | return WEBINSPECTOR_E_NOT_ENOUGH_DATA; | ||
| 55 | default: | 59 | default: |
| 56 | break; | 60 | break; |
| 57 | } | 61 | } |
diff --git a/tools/idevicecrashreport.c b/tools/idevicecrashreport.c index e05d506..6918d6b 100644 --- a/tools/idevicecrashreport.c +++ b/tools/idevicecrashreport.c | |||
| @@ -411,7 +411,7 @@ int main(int argc, char* argv[]) { | |||
| 411 | while ((strncmp(ping, "ping", 4) != 0) && (attempts < 10)) { | 411 | while ((strncmp(ping, "ping", 4) != 0) && (attempts < 10)) { |
| 412 | uint32_t bytes = 0; | 412 | uint32_t bytes = 0; |
| 413 | device_error = idevice_connection_receive_timeout(connection, ping, 4, &bytes, 2000); | 413 | device_error = idevice_connection_receive_timeout(connection, ping, 4, &bytes, 2000); |
| 414 | if ((bytes == 0) && (device_error == IDEVICE_E_SUCCESS)) { | 414 | if (device_error != IDEVICE_E_SUCCESS) { |
| 415 | attempts++; | 415 | attempts++; |
| 416 | continue; | 416 | continue; |
| 417 | } else if (device_error < 0) { | 417 | } else if (device_error < 0) { |
