summaryrefslogtreecommitdiffstats
path: root/src/debugserver.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/debugserver.c')
-rw-r--r--src/debugserver.c259
1 files changed, 139 insertions, 120 deletions
diff --git a/src/debugserver.c b/src/debugserver.c
index b6a8b62..74ade8a 100644
--- a/src/debugserver.c
+++ b/src/debugserver.c
@@ -64,7 +64,7 @@ static debugserver_error_t debugserver_error(service_error_t err)
return DEBUGSERVER_E_UNKNOWN_ERROR;
}
-LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_new(idevice_t device, lockdownd_service_descriptor_t service, debugserver_client_t* client)
+debugserver_error_t debugserver_client_new(idevice_t device, lockdownd_service_descriptor_t service, debugserver_client_t* client)
{
*client = NULL;
@@ -89,6 +89,8 @@ LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_new(idevice_t device
debugserver_client_t client_loc = (debugserver_client_t) malloc(sizeof(struct debugserver_client_private));
client_loc->parent = parent;
client_loc->noack_mode = 0;
+ client_loc->cancel_receive = NULL;
+ client_loc->receive_loop_timeout = 1000;
*client = client_loc;
@@ -96,7 +98,7 @@ LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_new(idevice_t device
return DEBUGSERVER_E_SUCCESS;
}
-LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_start_service(idevice_t device, debugserver_client_t * client, const char* label)
+debugserver_error_t debugserver_client_start_service(idevice_t device, debugserver_client_t * client, const char* label)
{
debugserver_error_t err = DEBUGSERVER_E_UNKNOWN_ERROR;
service_client_factory_start_service(device, DEBUGSERVER_SECURE_SERVICE_NAME, (void**)client, label, SERVICE_CONSTRUCTOR(debugserver_client_new), &err);
@@ -107,7 +109,7 @@ LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_start_service(idevic
return err;
}
-LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_free(debugserver_client_t client)
+debugserver_error_t debugserver_client_free(debugserver_client_t client)
{
if (!client)
return DEBUGSERVER_E_INVALID_ARG;
@@ -119,7 +121,7 @@ LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_free(debugserver_cli
return err;
}
-LIBIMOBILEDEVICE_API 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(debugserver_client_t client, const char* data, uint32_t size, uint32_t *sent)
{
debugserver_error_t res = DEBUGSERVER_E_UNKNOWN_ERROR;
int bytes = 0;
@@ -140,7 +142,7 @@ LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_send(debugserver_cli
return res;
}
-LIBIMOBILEDEVICE_API 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_with_timeout(debugserver_client_t client, char* data, uint32_t size, uint32_t *received, unsigned int timeout)
{
debugserver_error_t res = DEBUGSERVER_E_UNKNOWN_ERROR;
int bytes = 0;
@@ -150,7 +152,7 @@ LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_receive_with_timeout
}
res = debugserver_error(service_receive_with_timeout(client->parent, data, size, (uint32_t*)&bytes, timeout));
- if (bytes <= 0) {
+ if (bytes <= 0 && res != DEBUGSERVER_E_TIMEOUT) {
debug_info("Could not read data, error %d", res);
}
if (received) {
@@ -160,12 +162,17 @@ LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_receive_with_timeout
return (bytes > 0) ? DEBUGSERVER_E_SUCCESS : res;
}
-LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_receive(debugserver_client_t client, char* data, uint32_t size, uint32_t *received)
+debugserver_error_t debugserver_client_receive(debugserver_client_t client, char* data, uint32_t size, uint32_t *received)
{
- return debugserver_client_receive_with_timeout(client, data, size, received, 1000);
+ debugserver_error_t res = DEBUGSERVER_E_UNKNOWN_ERROR;
+ do {
+ /* Is this allowed to return DEBUGSERVER_E_TIMEOUT and also set data and received? */
+ res = debugserver_client_receive_with_timeout(client, data, size, received, client->receive_loop_timeout);
+ } while (res == DEBUGSERVER_E_TIMEOUT && client->cancel_receive != NULL && !client->cancel_receive());
+ return res;
}
-LIBIMOBILEDEVICE_API debugserver_error_t debugserver_command_new(const char* name, int argc, char* argv[], debugserver_command_t* command)
+debugserver_error_t debugserver_command_new(const char* name, int argc, char* argv[], debugserver_command_t* command)
{
int i;
debugserver_command_t tmp = (debugserver_command_t) malloc(sizeof(struct debugserver_command_private));
@@ -190,7 +197,7 @@ LIBIMOBILEDEVICE_API debugserver_error_t debugserver_command_new(const char* nam
return DEBUGSERVER_E_SUCCESS;
}
-LIBIMOBILEDEVICE_API debugserver_error_t debugserver_command_free(debugserver_command_t command)
+debugserver_error_t debugserver_command_free(debugserver_command_t command)
{
int i;
debugserver_error_t res = DEBUGSERVER_E_UNKNOWN_ERROR;
@@ -232,10 +239,10 @@ static char debugserver_int2hex(int x)
return hexchars[x];
}
-#define DEBUGSERVER_HEX_ENCODE_FIRST_BYTE(byte) debugserver_int2hex((byte >> 0x4) & 0xf)
-#define DEBUGSERVER_HEX_ENCODE_SECOND_BYTE(byte) debugserver_int2hex(byte & 0xf)
-#define DEBUGSERVER_HEX_DECODE_FIRST_BYTE(byte) ((byte >> 0x4) & 0xf)
-#define DEBUGSERVER_HEX_DECODE_SECOND_BYTE(byte) (byte & 0xf)
+#define DEBUGSERVER_HEX_ENCODE_FIRST_BYTE(byte) debugserver_int2hex(((byte) >> 0x4) & 0xf)
+#define DEBUGSERVER_HEX_ENCODE_SECOND_BYTE(byte) debugserver_int2hex((byte) & 0xf)
+#define DEBUGSERVER_HEX_DECODE_FIRST_BYTE(byte) (((byte) >> 0x4) & 0xf)
+#define DEBUGSERVER_HEX_DECODE_SECOND_BYTE(byte) ((byte) & 0xf)
static uint32_t debugserver_get_checksum_for_buffer(const char* buffer, uint32_t size)
{
@@ -268,7 +275,7 @@ static int debugserver_response_is_checksum_valid(const char* response, uint32_t
return 1;
}
-LIBIMOBILEDEVICE_API void debugserver_encode_string(const char* buffer, char** encoded_buffer, uint32_t* encoded_length)
+void debugserver_encode_string(const char* buffer, char** encoded_buffer, uint32_t* encoded_length)
{
uint32_t position;
uint32_t index;
@@ -284,7 +291,7 @@ LIBIMOBILEDEVICE_API void debugserver_encode_string(const char* buffer, char** e
}
}
-LIBIMOBILEDEVICE_API void debugserver_decode_string(const char *encoded_buffer, size_t encoded_length, char** buffer)
+void debugserver_decode_string(const char *encoded_buffer, size_t encoded_length, char** buffer)
{
*buffer = malloc(sizeof(char) * ((encoded_length / 2)+1));
char* t = *buffer;
@@ -343,7 +350,7 @@ static debugserver_error_t debugserver_client_send_noack(debugserver_client_t cl
return debugserver_client_send(client, "-", sizeof(char), NULL);
}
-LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_set_ack_mode(debugserver_client_t client, int enabled)
+debugserver_error_t debugserver_client_set_ack_mode(debugserver_client_t client, int enabled)
{
if (!client)
return DEBUGSERVER_E_INVALID_ARG;
@@ -355,130 +362,137 @@ LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_set_ack_mode(debugse
return DEBUGSERVER_E_SUCCESS;
}
-static int debugserver_client_receive_internal_check(debugserver_client_t client, char* received_char)
+debugserver_error_t debugserver_client_set_receive_params(debugserver_client_t client, int (*cancel_receive)(), int receive_loop_timeout)
+{
+ if (!client)
+ return DEBUGSERVER_E_INVALID_ARG;
+
+ client->cancel_receive = cancel_receive;
+ client->receive_loop_timeout = receive_loop_timeout;
+
+ debug_info("receive params: cancel_receive %s, receive_loop_timeout %dms", (client->cancel_receive == NULL ? "unset": "set"), client->receive_loop_timeout);
+
+ return DEBUGSERVER_E_SUCCESS;
+}
+
+static debugserver_error_t debugserver_client_receive_internal_char(debugserver_client_t client, char* received_char)
{
debugserver_error_t res = DEBUGSERVER_E_SUCCESS;
- int did_receive_char = 0;
- char buffer = 0;
uint32_t bytes = 0;
/* we loop here as we expect an answer */
- res = debugserver_client_receive_with_timeout(client, &buffer, sizeof(char), &bytes, 1000);
- if (res == DEBUGSERVER_E_SUCCESS && received_char[0] != 0) {
- if (memcmp(&buffer, received_char, sizeof(char)) == 0) {
- did_receive_char = 1;
- }
- } else {
- did_receive_char = 0;
+ res = debugserver_client_receive(client, received_char, sizeof(char), &bytes);
+ if (res != DEBUGSERVER_E_SUCCESS) {
+ return res;
}
-
- if (!did_receive_char) {
- memcpy(received_char, &buffer, sizeof(char));
+ if (bytes != 1) {
+ debug_info("received %d bytes when asking for %d!", bytes, sizeof(char));
+ return DEBUGSERVER_E_UNKNOWN_ERROR;
}
-
- return did_receive_char;
+ return res;
}
-LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_receive_response(debugserver_client_t client, char** response, size_t* response_size)
+debugserver_error_t debugserver_client_receive_response(debugserver_client_t client, char** response, size_t* response_size)
{
debugserver_error_t res = DEBUGSERVER_E_SUCCESS;
- int should_receive = 1;
+ char data = '\0';
int skip_prefix = 0;
- char* command_prefix = strdup("$");
- char* buffer = NULL;
+ char* buffer = malloc(1024);
uint32_t buffer_size = 0;
- uint32_t buffer_capacity = 0;
+ uint32_t buffer_capacity = 1024;
if (response)
*response = NULL;
if (!client->noack_mode) {
- char ack[2] = {'+', '\0'};
- debug_info("attempting to receive ACK %c", *ack);
- should_receive = debugserver_client_receive_internal_check(client, ack);
- debug_info("received char: %c", *ack);
- if (strncmp(ack, command_prefix, sizeof(char)) == 0) {
- should_receive = 1;
+ debug_info("attempting to receive ACK (+)");
+ res = debugserver_client_receive_internal_char(client, &data);
+ if (res != DEBUGSERVER_E_SUCCESS) {
+ goto cleanup;
+ }
+ if (data == '+') {
+ debug_info("received ACK (+)");
+ } else if (data == '$') {
+ debug_info("received prefix ($)");
+ buffer[0] = '$';
+ buffer_size = 1;
skip_prefix = 1;
- buffer = malloc(1024);
- buffer_capacity = 1024;
- strcpy(buffer, command_prefix);
- buffer_size += sizeof(char);
- debug_info("received ACK");
+ } else {
+ debug_info("unrecognized response when looking for ACK: %c", data);
+ goto cleanup;
}
}
- debug_info("should_receive: %d, skip_prefix: %d", should_receive, skip_prefix);
-
- if (should_receive && !skip_prefix) {
- debug_info("attempting to receive prefix");
- should_receive = debugserver_client_receive_internal_check(client, command_prefix);
- debug_info("received command_prefix: %c", *command_prefix);
- if (should_receive) {
- if (buffer) {
- strcpy(buffer, command_prefix);
- } else {
- buffer = malloc(1024);
- buffer_capacity = 1024;
- strcpy(buffer, command_prefix);
- buffer_size += sizeof(char);
- }
+ debug_info("skip_prefix: %d", skip_prefix);
+
+ if (!skip_prefix) {
+ debug_info("attempting to receive prefix ($)");
+ res = debugserver_client_receive_internal_char(client, &data);
+ if (res != DEBUGSERVER_E_SUCCESS) {
+ goto cleanup;
+ }
+ if (data == '$') {
+ debug_info("received prefix ($)");
+ buffer[0] = '$';
+ buffer_size = 1;
+ } else {
+ debug_info("unrecognized response when looking for prefix: %c", data);
+ goto cleanup;
}
}
- debug_info("buffer: %*s, should_receive: %d, skip_prefix: %d", buffer_size, buffer, should_receive, skip_prefix);
+ uint32_t checksum_length = DEBUGSERVER_CHECKSUM_HASH_LENGTH;
+ int receiving_checksum_response = 0;
+ debug_info("attempting to read up response until checksum");
- if (should_receive) {
- uint32_t checksum_length = DEBUGSERVER_CHECKSUM_HASH_LENGTH;
- int receiving_checksum_response = 0;
- debug_info("attempting to read up response until checksum");
-
- while ((checksum_length > 0)) {
- char data[2] = {'#', '\0'};
- if (debugserver_client_receive_internal_check(client, data)) {
- receiving_checksum_response = 1;
- }
- if (receiving_checksum_response) {
- checksum_length--;
- }
- if (buffer_size + 1 >= buffer_capacity) {
- char* newbuffer = realloc(buffer, buffer_capacity+1024);
- if (!newbuffer) {
- return DEBUGSERVER_E_UNKNOWN_ERROR;
- }
- buffer = newbuffer;
- buffer[buffer_capacity] = '\0';
- buffer_capacity += 1024;
- }
- strcat(buffer, data);
- buffer_size += sizeof(char);
+ while ((checksum_length > 0)) {
+ res = debugserver_client_receive_internal_char(client, &data);
+ if (res != DEBUGSERVER_E_SUCCESS) {
+ goto cleanup;
}
- debug_info("validating response checksum...");
- if (client->noack_mode || debugserver_response_is_checksum_valid(buffer, buffer_size)) {
- if (response) {
- /* assemble response string */
- uint32_t resp_size = sizeof(char) * (buffer_size - DEBUGSERVER_CHECKSUM_HASH_LENGTH - 1);
- *response = (char*)malloc(resp_size + 1);
- memcpy(*response, buffer + 1, resp_size);
- (*response)[resp_size] = '\0';
- if (response_size) *response_size = resp_size;
- }
- if (!client->noack_mode) {
- /* confirm valid command */
- debugserver_client_send_ack(client);
- }
- } else {
- /* response was invalid */
- res = DEBUGSERVER_E_RESPONSE_ERROR;
- if (!client->noack_mode) {
- /* report invalid command */
- debugserver_client_send_noack(client);
+ if (data == '#') {
+ receiving_checksum_response = 1;
+ }
+ if (receiving_checksum_response) {
+ checksum_length--;
+ }
+ if (buffer_size + 1 >= buffer_capacity) {
+ char* newbuffer = realloc(buffer, buffer_capacity+1024);
+ if (!newbuffer) {
+ return DEBUGSERVER_E_UNKNOWN_ERROR;
}
+ buffer = newbuffer;
+ buffer_capacity += 1024;
+ }
+ buffer[buffer_size] = data;
+ buffer_size += sizeof(char);
+ }
+ debug_info("validating response checksum...");
+ if (client->noack_mode || debugserver_response_is_checksum_valid(buffer, buffer_size)) {
+ if (response) {
+ /* assemble response string */
+ uint32_t resp_size = sizeof(char) * (buffer_size - DEBUGSERVER_CHECKSUM_HASH_LENGTH - 1);
+ *response = (char*)malloc(resp_size + 1);
+ memcpy(*response, buffer + 1, resp_size);
+ (*response)[resp_size] = '\0';
+ if (response_size) *response_size = resp_size;
+ }
+ if (!client->noack_mode) {
+ /* confirm valid command */
+ debugserver_client_send_ack(client);
+ }
+ } else {
+ /* response was invalid */
+ res = DEBUGSERVER_E_RESPONSE_ERROR;
+ if (!client->noack_mode) {
+ /* report invalid command */
+ debugserver_client_send_noack(client);
}
}
+cleanup:
if (response) {
debug_info("response: %s", *response);
}
@@ -486,13 +500,10 @@ LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_receive_response(deb
if (buffer)
free(buffer);
- if (command_prefix)
- free(command_prefix);
-
return res;
}
-LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_send_command(debugserver_client_t client, debugserver_command_t command, char** response, size_t* response_size)
+debugserver_error_t debugserver_client_send_command(debugserver_client_t client, debugserver_command_t command, char** response, size_t* response_size)
{
debugserver_error_t res = DEBUGSERVER_E_SUCCESS;
int i;
@@ -548,7 +559,7 @@ cleanup:
return res;
}
-LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_set_environment_hex_encoded(debugserver_client_t client, const char* env, char** response)
+debugserver_error_t debugserver_client_set_environment_hex_encoded(debugserver_client_t client, const char* env, char** response)
{
if (!client || !env)
return DEBUGSERVER_E_INVALID_ARG;
@@ -567,21 +578,25 @@ LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_set_environment_hex_
return result;
}
-LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_set_argv(debugserver_client_t client, int argc, char* argv[], char** response)
+debugserver_error_t debugserver_client_set_argv(debugserver_client_t client, int argc, char* argv[], char** response)
{
if (!client || !argc)
return DEBUGSERVER_E_INVALID_ARG;
debugserver_error_t result = DEBUGSERVER_E_UNKNOWN_ERROR;
char *pkt = NULL;
- int pkt_len = 0;
+ size_t pkt_len = 0;
int i = 0;
/* calculate total length */
while (i < argc && argv && argv[i]) {
char *prefix = NULL;
- asprintf(&prefix, ",%d,%d,", (int)strlen(argv[i]) * 2, i);
- pkt_len += (int)strlen(prefix) + (int)strlen(argv[i]) * 2;
+ int ret = asprintf(&prefix, ",%zu,%d,", strlen(argv[i]) * 2, i);
+ if (ret < 0 || prefix == NULL) {
+ debug_info("asprintf failed, out of memory?");
+ return DEBUGSERVER_E_UNKNOWN_ERROR;
+ }
+ pkt_len += strlen(prefix) + strlen(argv[i]) * 2;
free(prefix);
i++;
}
@@ -598,10 +613,14 @@ LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_set_argv(debugserver
char *prefix = NULL;
char *m = NULL;
- int arg_len = strlen(argv[i]);
- int arg_hexlen = arg_len * 2;
+ size_t arg_len = strlen(argv[i]);
+ size_t arg_hexlen = arg_len * 2;
- asprintf(&prefix, ",%d,%d,", arg_hexlen, i);
+ int ret = asprintf(&prefix, ",%zu,%d,", arg_hexlen, i);
+ if (ret < 0 || prefix == NULL) {
+ debug_info("asprintf failed, out of memory?");
+ return DEBUGSERVER_E_UNKNOWN_ERROR;
+ }
m = (char *) malloc(arg_hexlen);
char *p = m;