Skip to content
This repository has been archived by the owner on Jan 31, 2024. It is now read-only.

Commit

Permalink
idevice: Allow partial reads in idevice_connection_receive_timeout() …
Browse files Browse the repository at this point in the history
…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.
  • Loading branch information
nikias committed Feb 1, 2021
1 parent 09f2332 commit de1d724
Showing 1 changed file with 9 additions and 6 deletions.
15 changes: 9 additions & 6 deletions src/idevice.c
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,7 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_send(idevice_connection_
}
}

static idevice_error_t socket_recv_to_idevice_error(int conn_error, uint32_t len, uint32_t received)
static inline idevice_error_t socket_recv_to_idevice_error(int conn_error, uint32_t len, uint32_t received)
{
if (conn_error < 0) {
switch (conn_error) {
Expand Down Expand Up @@ -669,25 +669,28 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_receive_timeout(idevice_
if (connection->ssl_data) {
uint32_t received = 0;
int do_select = 1;
idevice_error_t error = IDEVICE_E_SSL_ERROR;

while (received < len) {
#ifdef HAVE_OPENSSL
do_select = (SSL_pending(connection->ssl_data->session) == 0);
#endif
if (do_select) {
int conn_error = socket_check_fd((int)(long)connection->data, FDM_READ, timeout);
idevice_error_t error = socket_recv_to_idevice_error(conn_error, len, received);

error = socket_recv_to_idevice_error(conn_error, len, received);
switch (error) {
case IDEVICE_E_SUCCESS:
case IDEVICE_E_TIMEOUT:
break;
case IDEVICE_E_UNKNOWN_ERROR:
default:
debug_info("ERROR: socket_check_fd returned %d (%s)", conn_error, strerror(-conn_error));
return error;
}
}

if (error == IDEVICE_E_TIMEOUT) {
break;
}
#ifdef HAVE_OPENSSL
int r = SSL_read(connection->ssl_data->session, (void*)((char*)(data+received)), (int)len-received);
if (r > 0) {
Expand All @@ -711,8 +714,8 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_receive_timeout(idevice_

debug_info("SSL_read %d, received %d", len, received);
if (received < len) {
*recv_bytes = 0;
return IDEVICE_E_SSL_ERROR;
*recv_bytes = received;
return error;
}

*recv_bytes = received;
Expand Down

0 comments on commit de1d724

Please sign in to comment.