summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/webinspector.c165
-rw-r--r--src/webinspector.h2
2 files changed, 125 insertions, 42 deletions
diff --git a/src/webinspector.c b/src/webinspector.c
index d7c86d0..c042df9 100644
--- a/src/webinspector.c
+++ b/src/webinspector.c
@@ -149,27 +149,56 @@ webinspector_error_t webinspector_client_free(webinspector_client_t client)
webinspector_error_t webinspector_send(webinspector_client_t client, plist_t plist)
{
webinspector_error_t res = WEBINSPECTOR_E_UNKNOWN_ERROR;
- char * buf = NULL;
- uint32_t length = 0;
- plist_to_bin(plist, &buf, &length);
- if (!buf || length == 0) {
+ uint32_t offset = 0;
+ int is_final_message = 0;
+
+ char *packet = NULL;
+ uint32_t packet_length = 0;
+
+ debug_info("Sending webinspector message...");
+ debug_plist(plist);
+
+ /* convert plist to packet */
+ plist_to_bin(plist, &packet, &packet_length);
+ if (!packet || packet_length == 0) {
debug_info("Error converting plist to binary.");
return res;
}
- plist_t outplist = plist_new_dict();
- plist_dict_insert_item(outplist, "WIRFinalMessageKey", plist_new_data(buf, length));
- free(buf);
+ do {
+ /* determine if we need to send partial messages */
+ if (packet_length < WEBINSPECTOR_PARTIAL_PACKET_CHUNK_SIZE) {
+ is_final_message = 1;
+ } else {
+ /* send partial packet */
+ is_final_message = 0;
+ }
- debug_plist(outplist);
+ plist_t outplist = plist_new_dict();
+ if (!is_final_message) {
+ /* split packet into partial chunks */
+ plist_dict_insert_item(outplist, "WIRPartialMessageKey", plist_new_data(packet + offset, WEBINSPECTOR_PARTIAL_PACKET_CHUNK_SIZE));
+ offset += WEBINSPECTOR_PARTIAL_PACKET_CHUNK_SIZE;
+ packet_length -= WEBINSPECTOR_PARTIAL_PACKET_CHUNK_SIZE;
+ } else {
+ /* send final chunk */
+ plist_dict_insert_item(outplist, "WIRFinalMessageKey", plist_new_data(packet + offset, packet_length));
+ offset += packet_length;
+ packet_length -= packet_length;
+ }
- res = webinspector_error(property_list_service_send_binary_plist(client->parent, outplist));
- plist_free(outplist);
- if (res != WEBINSPECTOR_E_SUCCESS) {
- debug_info("Sending plist failed with error %d", res);
- return res;
- }
+ res = webinspector_error(property_list_service_send_binary_plist(client->parent, outplist));
+ plist_free(outplist);
+ outplist = NULL;
+ if (res != WEBINSPECTOR_E_SUCCESS) {
+ debug_info("Sending plist failed with error %d", res);
+ return res;
+ }
+ } while(packet_length > 0);
+
+ free(packet);
+ packet = NULL;
return res;
}
@@ -206,40 +235,92 @@ webinspector_error_t webinspector_receive(webinspector_client_t client, plist_t
webinspector_error_t webinspector_receive_with_timeout(webinspector_client_t client, plist_t * plist, uint32_t timeout_ms)
{
webinspector_error_t res = WEBINSPECTOR_E_UNKNOWN_ERROR;
- plist_t outplist = NULL;
+ plist_t message = NULL;
+ plist_t key = NULL;
- res = webinspector_error(property_list_service_receive_plist_with_timeout(client->parent, &outplist, timeout_ms));
- if (res != WEBINSPECTOR_E_SUCCESS || !outplist) {
- debug_info("Could not receive plist, error %d", res);
- plist_free(outplist);
- return WEBINSPECTOR_E_MUX_ERROR;
- }
+ int is_final_message = 1;
- plist_t inplistdata = plist_dict_get_item(outplist, "WIRFinalMessageKey");
- if (!inplistdata) {
- debug_info("Could not find the internal message plist.");
- plist_free(outplist);
- return WEBINSPECTOR_E_PLIST_ERROR;
- }
+ char* buffer = NULL;
+ uint64_t length = 0;
- char * buf;
- uint64_t length64;
- plist_get_data_val(inplistdata, &buf, &length64);
- plist_free(outplist);
- if (!buf || length64 == 0 || length64 > 0xFFFFFFFF) {
- debug_info("Error getting the inner plist binary data.");
- free(buf);
- return WEBINSPECTOR_E_PLIST_ERROR;
- }
+ char* packet = NULL;
+ char* newpacket = NULL;
+ uint64_t packet_length = 0;
+
+ debug_info("Receiving webinspector message...");
- plist_from_bin(buf, (uint32_t) length64, plist);
- free(buf);
- if (!*plist) {
- debug_info("Error restoring the inner plist.");
- return WEBINSPECTOR_E_PLIST_ERROR;
+ do {
+ /* receive message */
+ res = webinspector_error(property_list_service_receive_plist_with_timeout(client->parent, &message, timeout_ms));
+ if (res != WEBINSPECTOR_E_SUCCESS || !message) {
+ debug_info("Could not receive message, error %d", res);
+ plist_free(message);
+ return WEBINSPECTOR_E_MUX_ERROR;
+ }
+
+ /* get message key */
+ key = plist_dict_get_item(message, "WIRFinalMessageKey");
+ if (!key) {
+ key = plist_dict_get_item(message, "WIRPartialMessageKey");
+ if (!key) {
+ debug_info("ERROR: Unable to read message key.");
+ plist_free(message);
+ return WEBINSPECTOR_E_PLIST_ERROR;
+ }
+ is_final_message = 0;
+ } else {
+ is_final_message = 1;
+ }
+
+ /* read partial data */
+ plist_get_data_val(key, &buffer, &length);
+ if (!buffer || length == 0 || length > 0xFFFFFFFF) {
+ debug_info("ERROR: Unable to get the inner plist binary data.");
+ free(packet);
+ free(buffer);
+ return WEBINSPECTOR_E_PLIST_ERROR;
+ }
+
+ /* (re)allocate packet data */
+ if (!packet) {
+ packet = (char*)malloc(length * sizeof(char));
+ } else {
+ newpacket = (char*)realloc(packet, (packet_length + length) * sizeof(char));
+ packet = newpacket;
+ }
+
+ /* copy partial data into final packet data */
+ memcpy(packet + packet_length, buffer, length);
+
+ /* cleanup buffer */
+ free(buffer);
+ buffer = NULL;
+
+ if (message) {
+ plist_free(message);
+ message = NULL;
+ }
+
+ /* adjust packet length */
+ packet_length += length;
+ length = 0;
+ } while(!is_final_message);
+
+ /* read final message */
+ if (packet_length) {
+ plist_from_bin(packet, (uint32_t)packet_length, plist);
+ if (!*plist) {
+ debug_info("Error restoring the final plist.");
+ free(packet);
+ return WEBINSPECTOR_E_PLIST_ERROR;
+ }
+
+ debug_plist(*plist);
}
- debug_plist(*plist);
+ if (packet) {
+ free(packet);
+ }
return res;
}
diff --git a/src/webinspector.h b/src/webinspector.h
index ab04a70..3c8e695 100644
--- a/src/webinspector.h
+++ b/src/webinspector.h
@@ -25,6 +25,8 @@
#include "libimobiledevice/webinspector.h"
#include "property_list_service.h"
+#define WEBINSPECTOR_PARTIAL_PACKET_CHUNK_SIZE 8096
+
struct webinspector_client_private {
property_list_service_client_t parent;
};