summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2021-02-01 11:32:28 +0100
committerGravatar Nikias Bassen2021-02-01 11:32:28 +0100
commitde1d724d0b753f21267da41eb4802e4f844f1331 (patch)
treedf43ed6436bd9d9615044ae46f19c5729e7e4fd0
parent09f2332f7d4cd0cc8c4646a63d75a3f037e2b9b2 (diff)
downloadlibimobiledevice-de1d724d0b753f21267da41eb4802e4f844f1331.tar.gz
libimobiledevice-de1d724d0b753f21267da41eb4802e4f844f1331.tar.bz2
idevice: Allow partial reads in idevice_connection_receive_timeout() and handle timeouts more adequate
idevice_connection_receive_timeout(), when in SSL mode, was assuming it should always try to read the exact amount of data specified in `len` parameter. While this works with most protocols that have length fields or fixed sized headers/packets, some others (e.g. debugserver) break because it will request a read but doesn't know the size that is expected to be returned beforehand. This commit will handle timeouts better and return the number of bytes that were read in such cases (instead of returning 0 bytes read + error). Note that in the event of a timeout, IDEVICE_E_TIMEOUT will be returned even though actual data might have been read. The number of bytes read will be returned in recv_bytes.
-rw-r--r--src/idevice.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/src/idevice.c b/src/idevice.c
index c71c49b..071d7b9 100644
--- a/src/idevice.c
+++ b/src/idevice.c
@@ -610,7 +610,7 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_send(idevice_connection_
610 } 610 }
611} 611}
612 612
613static idevice_error_t socket_recv_to_idevice_error(int conn_error, uint32_t len, uint32_t received) 613static inline idevice_error_t socket_recv_to_idevice_error(int conn_error, uint32_t len, uint32_t received)
614{ 614{
615 if (conn_error < 0) { 615 if (conn_error < 0) {
616 switch (conn_error) { 616 switch (conn_error) {
@@ -669,6 +669,7 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_receive_timeout(idevice_
669 if (connection->ssl_data) { 669 if (connection->ssl_data) {
670 uint32_t received = 0; 670 uint32_t received = 0;
671 int do_select = 1; 671 int do_select = 1;
672 idevice_error_t error = IDEVICE_E_SSL_ERROR;
672 673
673 while (received < len) { 674 while (received < len) {
674#ifdef HAVE_OPENSSL 675#ifdef HAVE_OPENSSL
@@ -676,10 +677,10 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_receive_timeout(idevice_
676#endif 677#endif
677 if (do_select) { 678 if (do_select) {
678 int conn_error = socket_check_fd((int)(long)connection->data, FDM_READ, timeout); 679 int conn_error = socket_check_fd((int)(long)connection->data, FDM_READ, timeout);
679 idevice_error_t error = socket_recv_to_idevice_error(conn_error, len, received); 680 error = socket_recv_to_idevice_error(conn_error, len, received);
680
681 switch (error) { 681 switch (error) {
682 case IDEVICE_E_SUCCESS: 682 case IDEVICE_E_SUCCESS:
683 case IDEVICE_E_TIMEOUT:
683 break; 684 break;
684 case IDEVICE_E_UNKNOWN_ERROR: 685 case IDEVICE_E_UNKNOWN_ERROR:
685 default: 686 default:
@@ -687,7 +688,9 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_receive_timeout(idevice_
687 return error; 688 return error;
688 } 689 }
689 } 690 }
690 691 if (error == IDEVICE_E_TIMEOUT) {
692 break;
693 }
691#ifdef HAVE_OPENSSL 694#ifdef HAVE_OPENSSL
692 int r = SSL_read(connection->ssl_data->session, (void*)((char*)(data+received)), (int)len-received); 695 int r = SSL_read(connection->ssl_data->session, (void*)((char*)(data+received)), (int)len-received);
693 if (r > 0) { 696 if (r > 0) {
@@ -711,8 +714,8 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_receive_timeout(idevice_
711 714
712 debug_info("SSL_read %d, received %d", len, received); 715 debug_info("SSL_read %d, received %d", len, received);
713 if (received < len) { 716 if (received < len) {
714 *recv_bytes = 0; 717 *recv_bytes = received;
715 return IDEVICE_E_SSL_ERROR; 718 return error;
716 } 719 }
717 720
718 *recv_bytes = received; 721 *recv_bytes = received;