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)
149webinspector_error_t webinspector_send(webinspector_client_t client, plist_t plist) 149webinspector_error_t webinspector_send(webinspector_client_t client, plist_t plist)
150{ 150{
151 webinspector_error_t res = WEBINSPECTOR_E_UNKNOWN_ERROR; 151 webinspector_error_t res = WEBINSPECTOR_E_UNKNOWN_ERROR;
152 char * buf = NULL;
153 uint32_t length = 0;
154 152
155 plist_to_bin(plist, &buf, &length); 153 uint32_t offset = 0;
156 if (!buf || length == 0) { 154 int is_final_message = 0;
155
156 char *packet = NULL;
157 uint32_t packet_length = 0;
158
159 debug_info("Sending webinspector message...");
160 debug_plist(plist);
161
162 /* convert plist to packet */
163 plist_to_bin(plist, &packet, &packet_length);
164 if (!packet || packet_length == 0) {
157 debug_info("Error converting plist to binary."); 165 debug_info("Error converting plist to binary.");
158 return res; 166 return res;
159 } 167 }
160 168
161 plist_t outplist = plist_new_dict(); 169 do {
162 plist_dict_insert_item(outplist, "WIRFinalMessageKey", plist_new_data(buf, length)); 170 /* determine if we need to send partial messages */
163 free(buf); 171 if (packet_length < WEBINSPECTOR_PARTIAL_PACKET_CHUNK_SIZE) {
172 is_final_message = 1;
173 } else {
174 /* send partial packet */
175 is_final_message = 0;
176 }
164 177
165 debug_plist(outplist); 178 plist_t outplist = plist_new_dict();
179 if (!is_final_message) {
180 /* split packet into partial chunks */
181 plist_dict_insert_item(outplist, "WIRPartialMessageKey", plist_new_data(packet + offset, WEBINSPECTOR_PARTIAL_PACKET_CHUNK_SIZE));
182 offset += WEBINSPECTOR_PARTIAL_PACKET_CHUNK_SIZE;
183 packet_length -= WEBINSPECTOR_PARTIAL_PACKET_CHUNK_SIZE;
184 } else {
185 /* send final chunk */
186 plist_dict_insert_item(outplist, "WIRFinalMessageKey", plist_new_data(packet + offset, packet_length));
187 offset += packet_length;
188 packet_length -= packet_length;
189 }
166 190
167 res = webinspector_error(property_list_service_send_binary_plist(client->parent, outplist)); 191 res = webinspector_error(property_list_service_send_binary_plist(client->parent, outplist));
168 plist_free(outplist); 192 plist_free(outplist);
169 if (res != WEBINSPECTOR_E_SUCCESS) { 193 outplist = NULL;
170 debug_info("Sending plist failed with error %d", res); 194 if (res != WEBINSPECTOR_E_SUCCESS) {
171 return res; 195 debug_info("Sending plist failed with error %d", res);
172 } 196 return res;
197 }
198 } while(packet_length > 0);
199
200 free(packet);
201 packet = NULL;
173 202
174 return res; 203 return res;
175} 204}
@@ -206,40 +235,92 @@ webinspector_error_t webinspector_receive(webinspector_client_t client, plist_t
206webinspector_error_t webinspector_receive_with_timeout(webinspector_client_t client, plist_t * plist, uint32_t timeout_ms) 235webinspector_error_t webinspector_receive_with_timeout(webinspector_client_t client, plist_t * plist, uint32_t timeout_ms)
207{ 236{
208 webinspector_error_t res = WEBINSPECTOR_E_UNKNOWN_ERROR; 237 webinspector_error_t res = WEBINSPECTOR_E_UNKNOWN_ERROR;
209 plist_t outplist = NULL; 238 plist_t message = NULL;
239 plist_t key = NULL;
210 240
211 res = webinspector_error(property_list_service_receive_plist_with_timeout(client->parent, &outplist, timeout_ms)); 241 int is_final_message = 1;
212 if (res != WEBINSPECTOR_E_SUCCESS || !outplist) {
213 debug_info("Could not receive plist, error %d", res);
214 plist_free(outplist);
215 return WEBINSPECTOR_E_MUX_ERROR;
216 }
217 242
218 plist_t inplistdata = plist_dict_get_item(outplist, "WIRFinalMessageKey"); 243 char* buffer = NULL;
219 if (!inplistdata) { 244 uint64_t length = 0;
220 debug_info("Could not find the internal message plist.");
221 plist_free(outplist);
222 return WEBINSPECTOR_E_PLIST_ERROR;
223 }
224 245
225 char * buf; 246 char* packet = NULL;
226 uint64_t length64; 247 char* newpacket = NULL;
227 plist_get_data_val(inplistdata, &buf, &length64); 248 uint64_t packet_length = 0;
228 plist_free(outplist); 249
229 if (!buf || length64 == 0 || length64 > 0xFFFFFFFF) { 250 debug_info("Receiving webinspector message...");
230 debug_info("Error getting the inner plist binary data.");
231 free(buf);
232 return WEBINSPECTOR_E_PLIST_ERROR;
233 }
234 251
235 plist_from_bin(buf, (uint32_t) length64, plist); 252 do {
236 free(buf); 253 /* receive message */
237 if (!*plist) { 254 res = webinspector_error(property_list_service_receive_plist_with_timeout(client->parent, &message, timeout_ms));
238 debug_info("Error restoring the inner plist."); 255 if (res != WEBINSPECTOR_E_SUCCESS || !message) {
239 return WEBINSPECTOR_E_PLIST_ERROR; 256 debug_info("Could not receive message, error %d", res);
257 plist_free(message);
258 return WEBINSPECTOR_E_MUX_ERROR;
259 }
260
261 /* get message key */
262 key = plist_dict_get_item(message, "WIRFinalMessageKey");
263 if (!key) {
264 key = plist_dict_get_item(message, "WIRPartialMessageKey");
265 if (!key) {
266 debug_info("ERROR: Unable to read message key.");
267 plist_free(message);
268 return WEBINSPECTOR_E_PLIST_ERROR;
269 }
270 is_final_message = 0;
271 } else {
272 is_final_message = 1;
273 }
274
275 /* read partial data */
276 plist_get_data_val(key, &buffer, &length);
277 if (!buffer || length == 0 || length > 0xFFFFFFFF) {
278 debug_info("ERROR: Unable to get the inner plist binary data.");
279 free(packet);
280 free(buffer);
281 return WEBINSPECTOR_E_PLIST_ERROR;
282 }
283
284 /* (re)allocate packet data */
285 if (!packet) {
286 packet = (char*)malloc(length * sizeof(char));
287 } else {
288 newpacket = (char*)realloc(packet, (packet_length + length) * sizeof(char));
289 packet = newpacket;
290 }
291
292 /* copy partial data into final packet data */
293 memcpy(packet + packet_length, buffer, length);
294
295 /* cleanup buffer */
296 free(buffer);
297 buffer = NULL;
298
299 if (message) {
300 plist_free(message);
301 message = NULL;
302 }
303
304 /* adjust packet length */
305 packet_length += length;
306 length = 0;
307 } while(!is_final_message);
308
309 /* read final message */
310 if (packet_length) {
311 plist_from_bin(packet, (uint32_t)packet_length, plist);
312 if (!*plist) {
313 debug_info("Error restoring the final plist.");
314 free(packet);
315 return WEBINSPECTOR_E_PLIST_ERROR;
316 }
317
318 debug_plist(*plist);
240 } 319 }
241 320
242 debug_plist(*plist); 321 if (packet) {
322 free(packet);
323 }
243 324
244 return res; 325 return res;
245} 326}
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 @@
25#include "libimobiledevice/webinspector.h" 25#include "libimobiledevice/webinspector.h"
26#include "property_list_service.h" 26#include "property_list_service.h"
27 27
28#define WEBINSPECTOR_PARTIAL_PACKET_CHUNK_SIZE 8096
29
28struct webinspector_client_private { 30struct webinspector_client_private {
29 property_list_service_client_t parent; 31 property_list_service_client_t parent;
30}; 32};