summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cython/heartbeat.pxi4
-rw-r--r--cython/imobiledevice.pyx6
-rw-r--r--cython/webinspector.pxi2
-rw-r--r--include/libimobiledevice/heartbeat.h16
-rw-r--r--include/libimobiledevice/libimobiledevice.h4
-rw-r--r--include/libimobiledevice/property_list_service.h3
-rw-r--r--include/libimobiledevice/service.h10
-rw-r--r--include/libimobiledevice/webinspector.h14
-rw-r--r--src/heartbeat.c4
-rw-r--r--src/idevice.c59
-rw-r--r--src/property_list_service.c116
-rw-r--r--src/service.c7
-rw-r--r--src/webinspector.c4
-rw-r--r--tools/idevicecrashreport.c2
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 */
36typedef enum { 36typedef 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
45typedef struct heartbeat_client_private heartbeat_client_private; 47typedef 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
48typedef struct idevice_private idevice_private; 48typedef 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 */
152service_error_t service_enable_ssl(service_client_t client); 158service_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 */
37typedef enum { 37typedef 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
46typedef struct webinspector_client_private webinspector_client_private; 48typedef 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
385static 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
407LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_receive_timeout(idevice_connection_t connection, char *data, uint32_t len, uint32_t *recv_bytes, unsigned int timeout) 428LIBIMOBILEDEVICE_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) {