summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/AFC.c130
-rw-r--r--src/iphone.c25
-rw-r--r--src/lockdown.c84
-rw-r--r--src/usbmux.c48
4 files changed, 168 insertions, 119 deletions
diff --git a/src/AFC.c b/src/AFC.c
index 5866915..44dcee5 100644
--- a/src/AFC.c
+++ b/src/AFC.c
@@ -58,7 +58,7 @@ static void afc_unlock(iphone_afc_client_t client) { // just to be pretty
58 * 58 *
59 * @return A handle to the newly-connected client or NULL upon error. 59 * @return A handle to the newly-connected client or NULL upon error.
60 */ 60 */
61int iphone_afc_new_client ( iphone_device_t device, int src_port, int dst_port, iphone_afc_client_t *client ) { 61iphone_error_t iphone_afc_new_client ( iphone_device_t device, int src_port, int dst_port, iphone_afc_client_t *client ) {
62 int ret = IPHONE_E_SUCCESS; 62 int ret = IPHONE_E_SUCCESS;
63 iphone_afc_client_t client_loc = (iphone_afc_client_t)malloc(sizeof(struct iphone_afc_client_int)); 63 iphone_afc_client_t client_loc = (iphone_afc_client_t)malloc(sizeof(struct iphone_afc_client_int));
64 64
@@ -100,12 +100,14 @@ int iphone_afc_new_client ( iphone_device_t device, int src_port, int dst_port,
100 * 100 *
101 * @param client The client to disconnect. 101 * @param client The client to disconnect.
102 */ 102 */
103void iphone_afc_free_client ( iphone_afc_client_t client ) { 103iphone_error_t iphone_afc_free_client ( iphone_afc_client_t client ) {
104 if (!client || !client->connection || !client->afc_packet) return; 104 if (!client || !client->connection || !client->afc_packet)
105 return IPHONE_E_INVALID_ARG;
105 106
106 iphone_mux_free_client(client->connection); 107 iphone_mux_free_client(client->connection);
107 free(client->afc_packet); 108 free(client->afc_packet);
108 free(client); 109 free(client);
110 return IPHONE_E_SUCCESS;
109} 111}
110 112
111 113
@@ -324,11 +326,12 @@ static char **make_strings_list(char *tokens, int true_length) {
324 * @return A char ** list of files in that directory, terminated by an empty 326 * @return A char ** list of files in that directory, terminated by an empty
325 * string for now or NULL if there was an error. 327 * string for now or NULL if there was an error.
326 */ 328 */
327char **iphone_afc_get_dir_list ( iphone_afc_client_t client, const char *dir) { 329iphone_error_t iphone_afc_get_dir_list ( iphone_afc_client_t client, const char *dir, char ***list) {
328 int bytes = 0; 330 int bytes = 0;
329 char *data = NULL, **list = NULL; 331 char *data = NULL, **list_loc = NULL;
332 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
330 333
331 if (!client || !dir) return NULL; 334 if (!client || !dir || !list) return IPHONE_E_INVALID_ARG;
332 335
333 afc_lock(client); 336 afc_lock(client);
334 337
@@ -339,23 +342,25 @@ char **iphone_afc_get_dir_list ( iphone_afc_client_t client, const char *dir) {
339 bytes = dispatch_AFC_packet(client, dir, strlen(dir)); 342 bytes = dispatch_AFC_packet(client, dir, strlen(dir));
340 if (bytes <= 0) { 343 if (bytes <= 0) {
341 afc_unlock(client); 344 afc_unlock(client);
342 return NULL; 345 return IPHONE_E_NOT_ENOUGH_DATA;
343 } 346 }
344 347
345 // Receive the data 348 // Receive the data
346 bytes = receive_AFC_data(client, &data); 349 bytes = receive_AFC_data(client, &data);
347 if (bytes < 0 && !data) { 350 if (bytes < 0 && !data) {
348 afc_unlock(client); 351 afc_unlock(client);
349 return NULL; 352 return IPHONE_E_NOT_ENOUGH_DATA;
350 } 353 }
351 354
352 // Parse the data 355 // Parse the data
353 list = make_strings_list(data, bytes); 356 list_loc = make_strings_list(data, bytes);
357 if (list_loc) ret = IPHONE_E_SUCCESS;
354 if (data) free(data); 358 if (data) free(data);
355 359
356 afc_unlock(client); 360 afc_unlock(client);
361 *list = list_loc;
357 362
358 return list; 363 return ret;
359} 364}
360 365
361/** Get device info for a client connection to phone. (free space on disk, etc.) 366/** Get device info for a client connection to phone. (free space on disk, etc.)
@@ -365,11 +370,11 @@ char **iphone_afc_get_dir_list ( iphone_afc_client_t client, const char *dir) {
365 * @return A char ** list of parameters as given by AFC or NULL if there was an 370 * @return A char ** list of parameters as given by AFC or NULL if there was an
366 * error. 371 * error.
367 */ 372 */
368char **iphone_afc_get_devinfo ( iphone_afc_client_t client ) { 373iphone_error_t iphone_afc_get_devinfo ( iphone_afc_client_t client, char ***infos) {
369 int bytes = 0; 374 int bytes = 0;
370 char *data = NULL, **list = NULL; 375 char *data = NULL, **list = NULL;
371 376
372 if (!client) return NULL; 377 if (!client || !infos) return IPHONE_E_INVALID_ARG;
373 378
374 afc_lock(client); 379 afc_lock(client);
375 380
@@ -379,14 +384,14 @@ char **iphone_afc_get_devinfo ( iphone_afc_client_t client ) {
379 bytes = dispatch_AFC_packet(client, NULL, 0); 384 bytes = dispatch_AFC_packet(client, NULL, 0);
380 if (bytes < 0) { 385 if (bytes < 0) {
381 afc_unlock(client); 386 afc_unlock(client);
382 return NULL; 387 return IPHONE_E_NOT_ENOUGH_DATA;
383 } 388 }
384 389
385 // Receive the data 390 // Receive the data
386 bytes = receive_AFC_data(client, &data); 391 bytes = receive_AFC_data(client, &data);
387 if (bytes < 0 && !data) { 392 if (bytes < 0 && !data) {
388 afc_unlock(client); 393 afc_unlock(client);
389 return NULL; 394 return IPHONE_E_NOT_ENOUGH_DATA;
390 } 395 }
391 396
392 // Parse the data 397 // Parse the data
@@ -394,8 +399,8 @@ char **iphone_afc_get_devinfo ( iphone_afc_client_t client ) {
394 if (data) free(data); 399 if (data) free(data);
395 400
396 afc_unlock(client); 401 afc_unlock(client);
397 402 *infos = list;
398 return list; 403 return IPHONE_E_SUCCESS;
399} 404}
400 405
401/** Deletes a file. 406/** Deletes a file.
@@ -406,7 +411,7 @@ char **iphone_afc_get_devinfo ( iphone_afc_client_t client ) {
406 * @return IPHONE_E_SUCCESS if everythong went well, IPHONE_E_INVALID_ARG 411 * @return IPHONE_E_SUCCESS if everythong went well, IPHONE_E_INVALID_ARG
407 * if arguments are NULL or invalid, IPHONE_E_NOT_ENOUGH_DATA otherwise. 412 * if arguments are NULL or invalid, IPHONE_E_NOT_ENOUGH_DATA otherwise.
408 */ 413 */
409int iphone_afc_delete_file ( iphone_afc_client_t client, const char *path) { 414iphone_error_t iphone_afc_delete_file ( iphone_afc_client_t client, const char *path) {
410 char *response = NULL; 415 char *response = NULL;
411 int bytes; 416 int bytes;
412 417
@@ -445,7 +450,7 @@ int iphone_afc_delete_file ( iphone_afc_client_t client, const char *path) {
445 * @return IPHONE_E_SUCCESS if everythong went well, IPHONE_E_INVALID_ARG 450 * @return IPHONE_E_SUCCESS if everythong went well, IPHONE_E_INVALID_ARG
446 * if arguments are NULL or invalid, IPHONE_E_NOT_ENOUGH_DATA otherwise. 451 * if arguments are NULL or invalid, IPHONE_E_NOT_ENOUGH_DATA otherwise.
447 */ 452 */
448int iphone_afc_rename_file ( iphone_afc_client_t client, const char *from, const char *to) { 453iphone_error_t iphone_afc_rename_file ( iphone_afc_client_t client, const char *from, const char *to) {
449 char *response = NULL; 454 char *response = NULL;
450 char *send = (char*)malloc(sizeof(char) * (strlen(from) + strlen(to) + 1 + sizeof(uint32))); 455 char *send = (char*)malloc(sizeof(char) * (strlen(from) + strlen(to) + 1 + sizeof(uint32)));
451 int bytes = 0; 456 int bytes = 0;
@@ -488,7 +493,7 @@ int iphone_afc_rename_file ( iphone_afc_client_t client, const char *from, const
488 * @return IPHONE_E_SUCCESS if everythong went well, IPHONE_E_INVALID_ARG 493 * @return IPHONE_E_SUCCESS if everythong went well, IPHONE_E_INVALID_ARG
489 * if arguments are NULL or invalid, IPHONE_E_NOT_ENOUGH_DATA otherwise. 494 * if arguments are NULL or invalid, IPHONE_E_NOT_ENOUGH_DATA otherwise.
490 */ 495 */
491int iphone_afc_mkdir ( iphone_afc_client_t client, const char *dir) { 496iphone_error_t iphone_afc_mkdir ( iphone_afc_client_t client, const char *dir) {
492 int bytes = 0; 497 int bytes = 0;
493 char *response = NULL; 498 char *response = NULL;
494 499
@@ -586,7 +591,7 @@ iphone_afc_file_t afc_get_file_info(iphone_afc_client_t client, const char *path
586 * @return A pointer to an AFCFile struct containing the information received, 591 * @return A pointer to an AFCFile struct containing the information received,
587 * or NULL on failure. 592 * or NULL on failure.
588 */ 593 */
589int iphone_afc_get_file_attr ( iphone_afc_client_t client, const char *filename, struct stat *stbuf ) { 594iphone_error_t iphone_afc_get_file_attr ( iphone_afc_client_t client, const char *filename, struct stat *stbuf ) {
590 595
591 int ret = IPHONE_E_SUCCESS; 596 int ret = IPHONE_E_SUCCESS;
592 if (!client ||!client->connection || !client->afc_packet || !stbuf) return IPHONE_E_INVALID_ARG; 597 if (!client ||!client->connection || !client->afc_packet || !stbuf) return IPHONE_E_INVALID_ARG;
@@ -620,7 +625,7 @@ int iphone_afc_get_file_attr ( iphone_afc_client_t client, const char *filename,
620 * received by afc_get_file_info) as well as the handle to the file or 625 * received by afc_get_file_info) as well as the handle to the file or
621 * NULL in the case of failure. 626 * NULL in the case of failure.
622 */ 627 */
623int iphone_afc_open_file ( iphone_afc_client_t client, const char *filename, uint32_t file_mode, iphone_afc_file_t *file ) { 628iphone_error_t iphone_afc_open_file ( iphone_afc_client_t client, const char *filename, uint32_t file_mode, iphone_afc_file_t *file ) {
624 iphone_afc_file_t file_loc = NULL; 629 iphone_afc_file_t file_loc = NULL;
625 uint32 ag = 0; 630 uint32 ag = 0;
626 int bytes = 0, length = 0; 631 int bytes = 0, length = 0;
@@ -677,12 +682,12 @@ int iphone_afc_open_file ( iphone_afc_client_t client, const char *filename, uin
677 * 682 *
678 * @return The number of bytes read if successful. If there was an error -1. 683 * @return The number of bytes read if successful. If there was an error -1.
679 */ 684 */
680int iphone_afc_read_file ( iphone_afc_client_t client, iphone_afc_file_t file, char *data, int length) { 685iphone_error_t iphone_afc_read_file ( iphone_afc_client_t client, iphone_afc_file_t file, char *data, int length, uint32_t *bytes) {
681 char *input = NULL; 686 char *input = NULL;
682 int current_count = 0, bytes = 0; 687 int current_count = 0, bytes_loc = 0;
683 const int MAXIMUM_READ_SIZE = 1 << 16; 688 const int MAXIMUM_READ_SIZE = 1 << 16;
684 689
685 if (!client || !client->afc_packet || !client->connection || !file) return -1; 690 if (!client || !client->afc_packet || !client->connection || !file) return IPHONE_E_INVALID_ARG;
686 if (debug) fprintf(stderr, "afc_read_file called for length %i\n", length); 691 if (debug) fprintf(stderr, "afc_read_file called for length %i\n", length);
687 692
688 afc_lock(client); 693 afc_lock(client);
@@ -698,40 +703,41 @@ int iphone_afc_read_file ( iphone_afc_client_t client, iphone_afc_file_t file, c
698 packet->size = ((length - current_count) < MAXIMUM_READ_SIZE) ? (length - current_count) : MAXIMUM_READ_SIZE; 703 packet->size = ((length - current_count) < MAXIMUM_READ_SIZE) ? (length - current_count) : MAXIMUM_READ_SIZE;
699 client->afc_packet->operation = AFC_READ; 704 client->afc_packet->operation = AFC_READ;
700 client->afc_packet->entire_length = client->afc_packet->this_length = 0; 705 client->afc_packet->entire_length = client->afc_packet->this_length = 0;
701 bytes = dispatch_AFC_packet(client, (char*)packet, sizeof(AFCFilePacket)); 706 bytes_loc = dispatch_AFC_packet(client, (char*)packet, sizeof(AFCFilePacket));
702 free(packet); 707 free(packet);
703 708
704 if (bytes <= 0) { 709 if (bytes_loc <= 0) {
705 afc_unlock(client); 710 afc_unlock(client);
706 return -1; 711 return IPHONE_E_NOT_ENOUGH_DATA;
707 } 712 }
708 713
709 // Receive the data 714 // Receive the data
710 bytes = receive_AFC_data(client, &input); 715 bytes_loc = receive_AFC_data(client, &input);
711 if (debug) fprintf(stderr, "afc_read_file: bytes returned: %i\n", bytes); 716 if (debug) fprintf(stderr, "afc_read_file: bytes returned: %i\n", bytes_loc);
712 if (bytes < 0) { 717 if (bytes < 0) {
713 if (input) free(input); 718 if (input) free(input);
714 afc_unlock(client); 719 afc_unlock(client);
715 return -1; 720 return IPHONE_E_NOT_ENOUGH_DATA;
716 } else if (bytes == 0) { 721 } else if (bytes == 0) {
717 if (input) free(input); 722 if (input) free(input);
718 afc_unlock(client); 723 afc_unlock(client);
719 return current_count; 724 *bytes = current_count;
725 return IPHONE_E_SUCCESS; //FIXME check that's actually a success
720 } else { 726 } else {
721 if (input) { 727 if (input) {
722 if (debug) fprintf(stderr, "afc_read_file: %d\n", bytes); 728 if (debug) fprintf(stderr, "afc_read_file: %d\n", bytes_loc);
723 memcpy(data+current_count, input, (bytes > length) ? length : bytes); 729 memcpy(data+current_count, input, (bytes_loc > length) ? length : bytes_loc);
724 free(input); 730 free(input);
725 input = NULL; 731 input = NULL;
726 current_count += (bytes > length) ? length : bytes; 732 current_count += (bytes_loc > length) ? length : bytes_loc;
727 } 733 }
728 } 734 }
729 } 735 }
730 if (debug) fprintf(stderr, "afc_read_file: returning current_count as %i\n", current_count); 736 if (debug) fprintf(stderr, "afc_read_file: returning current_count as %i\n", current_count);
731 737
732 afc_unlock(client); 738 afc_unlock(client);
733 739 *bytes = current_count;
734 return current_count; 740 return IPHONE_E_SUCCESS;
735} 741}
736 742
737/** Writes a given number of bytes to a file. 743/** Writes a given number of bytes to a file.
@@ -744,13 +750,13 @@ int iphone_afc_read_file ( iphone_afc_client_t client, iphone_afc_file_t file, c
744 * @return The number of bytes written to the file, or a value less than 0 if 750 * @return The number of bytes written to the file, or a value less than 0 if
745 * none were written... 751 * none were written...
746 */ 752 */
747int iphone_afc_write_file ( iphone_afc_client_t client, iphone_afc_file_t file, const char *data, int length) { 753iphone_error_t iphone_afc_write_file ( iphone_afc_client_t client, iphone_afc_file_t file, const char *data, int length, uint32_t *bytes) {
748 char *acknowledgement = NULL; 754 char *acknowledgement = NULL;
749 const int MAXIMUM_WRITE_SIZE = 1 << 16; 755 const int MAXIMUM_WRITE_SIZE = 1 << 16;
750 uint32 zero = 0, bytes = 0, segments = (length / MAXIMUM_WRITE_SIZE), current_count = 0, i = 0; 756 uint32 zero = 0, bytes_loc = 0, segments = (length / MAXIMUM_WRITE_SIZE), current_count = 0, i = 0;
751 char *out_buffer = NULL; 757 char *out_buffer = NULL;
752 758
753 if (!client ||!client->afc_packet || !client->connection || !file) return -1; 759 if (!client ||!client->afc_packet || !client->connection || !file || !bytes_loc) return IPHONE_E_INVALID_ARG;
754 760
755 afc_lock(client); 761 afc_lock(client);
756 762
@@ -766,19 +772,19 @@ int iphone_afc_write_file ( iphone_afc_client_t client, iphone_afc_file_t file,
766 memcpy(out_buffer, (char*)&file->filehandle, sizeof(uint32)); 772 memcpy(out_buffer, (char*)&file->filehandle, sizeof(uint32));
767 memcpy(out_buffer+4, (char*)&zero, sizeof(uint32)); 773 memcpy(out_buffer+4, (char*)&zero, sizeof(uint32));
768 memcpy(out_buffer+8, data+current_count, MAXIMUM_WRITE_SIZE); 774 memcpy(out_buffer+8, data+current_count, MAXIMUM_WRITE_SIZE);
769 bytes = dispatch_AFC_packet(client, out_buffer, MAXIMUM_WRITE_SIZE + 8); 775 bytes_loc = dispatch_AFC_packet(client, out_buffer, MAXIMUM_WRITE_SIZE + 8);
770 if (bytes < 0) { 776 if (bytes_loc < 0) {
771 afc_unlock(client); 777 afc_unlock(client);
772 return bytes; 778 return IPHONE_E_NOT_ENOUGH_DATA;
773 } 779 }
774 free(out_buffer); 780 free(out_buffer);
775 out_buffer = NULL; 781 out_buffer = NULL;
776 782
777 current_count += bytes; 783 current_count += bytes_loc;
778 bytes = receive_AFC_data(client, &acknowledgement); 784 bytes_loc = receive_AFC_data(client, &acknowledgement);
779 if (bytes < 0) { 785 if (bytes_loc < 0) {
780 afc_unlock(client); 786 afc_unlock(client);
781 return current_count; 787 return IPHONE_E_NOT_ENOUGH_DATA;
782 } 788 }
783 } 789 }
784 790
@@ -786,7 +792,8 @@ int iphone_afc_write_file ( iphone_afc_client_t client, iphone_afc_file_t file,
786 // this length is fine because it's always sizeof(AFCPacket) + 8, but to be sure we do it again 792 // this length is fine because it's always sizeof(AFCPacket) + 8, but to be sure we do it again
787 if (current_count == length) { 793 if (current_count == length) {
788 afc_unlock(client); 794 afc_unlock(client);
789 return current_count; 795 *bytes = current_count;
796 return IPHONE_E_SUCCESS;
790 } 797 }
791 798
792 client->afc_packet->this_length = sizeof(AFCPacket) + 8; 799 client->afc_packet->this_length = sizeof(AFCPacket) + 8;
@@ -796,25 +803,26 @@ int iphone_afc_write_file ( iphone_afc_client_t client, iphone_afc_file_t file,
796 memcpy(out_buffer, (char*)&file->filehandle, sizeof(uint32)); 803 memcpy(out_buffer, (char*)&file->filehandle, sizeof(uint32));
797 memcpy(out_buffer+4, (char*)&zero, sizeof(uint32)); 804 memcpy(out_buffer+4, (char*)&zero, sizeof(uint32));
798 memcpy(out_buffer+8, data+current_count, (length - current_count)); 805 memcpy(out_buffer+8, data+current_count, (length - current_count));
799 bytes = dispatch_AFC_packet(client, out_buffer, (length - current_count) + 8); 806 bytes_loc = dispatch_AFC_packet(client, out_buffer, (length - current_count) + 8);
800 free(out_buffer); 807 free(out_buffer);
801 out_buffer = NULL; 808 out_buffer = NULL;
802 809
803 current_count += bytes; 810 current_count += bytes_loc;
804 811
805 if (bytes <= 0) { 812 if (bytes_loc <= 0) {
806 afc_unlock(client); 813 afc_unlock(client);
807 return current_count; 814 *bytes = current_count;
815 return IPHONE_E_SUCCESS;
808 } 816 }
809 817
810 zero = bytes; 818 zero = bytes_loc;
811 bytes = receive_AFC_data(client, &acknowledgement); 819 bytes_loc = receive_AFC_data(client, &acknowledgement);
812 afc_unlock(client); 820 afc_unlock(client);
813 if (bytes < 0) { 821 if (bytes_loc < 0) {
814 if (debug) fprintf(stderr, "afc_write_file: uh oh?\n"); 822 if (debug) fprintf(stderr, "afc_write_file: uh oh?\n");
815 } 823 }
816 824
817 return current_count; 825 return IPHONE_E_UNKNOWN_ERROR;
818} 826}
819 827
820/** Closes a file on the phone. 828/** Closes a file on the phone.
@@ -823,7 +831,8 @@ int iphone_afc_write_file ( iphone_afc_client_t client, iphone_afc_file_t file,
823 * @param file A pointer to an AFCFile struct containing the file handle of the 831 * @param file A pointer to an AFCFile struct containing the file handle of the
824 * file to close. 832 * file to close.
825 */ 833 */
826void iphone_afc_close_file ( iphone_afc_client_t client, iphone_afc_file_t file) { 834iphone_error_t iphone_afc_close_file ( iphone_afc_client_t client, iphone_afc_file_t file) {
835 if (!client || !file) return IPHONE_E_INVALID_ARG;
827 char *buffer = malloc(sizeof(char) * 8); 836 char *buffer = malloc(sizeof(char) * 8);
828 uint32 zero = 0; 837 uint32 zero = 0;
829 int bytes = 0; 838 int bytes = 0;
@@ -846,7 +855,7 @@ void iphone_afc_close_file ( iphone_afc_client_t client, iphone_afc_file_t file)
846 855
847 if (bytes <= 0) { 856 if (bytes <= 0) {
848 afc_unlock(client); 857 afc_unlock(client);
849 return; 858 return IPHONE_E_UNKNOWN_ERROR;
850 } 859 }
851 860
852 // Receive the response 861 // Receive the response
@@ -854,6 +863,7 @@ void iphone_afc_close_file ( iphone_afc_client_t client, iphone_afc_file_t file)
854 if (buffer) free(buffer); 863 if (buffer) free(buffer);
855 free(file); 864 free(file);
856 afc_unlock(client); 865 afc_unlock(client);
866 return IPHONE_E_SUCCESS;
857} 867}
858 868
859/** Seeks to a given position of a pre-opened file on the phone. 869/** Seeks to a given position of a pre-opened file on the phone.
@@ -865,7 +875,7 @@ void iphone_afc_close_file ( iphone_afc_client_t client, iphone_afc_file_t file)
865 * 875 *
866 * @return IPHONE_E_SUCCESS on success, IPHONE_E_NOT_ENOUGH_DATA on failure. 876 * @return IPHONE_E_SUCCESS on success, IPHONE_E_NOT_ENOUGH_DATA on failure.
867 */ 877 */
868int iphone_afc_seek_file ( iphone_afc_client_t client, iphone_afc_file_t file, int seekpos) { 878iphone_error_t iphone_afc_seek_file ( iphone_afc_client_t client, iphone_afc_file_t file, int seekpos) {
869 char *buffer = (char*)malloc(sizeof(char) * 24); 879 char *buffer = (char*)malloc(sizeof(char) * 24);
870 uint32 seekto = 0, bytes = 0, zero = 0; 880 uint32 seekto = 0, bytes = 0, zero = 0;
871 881
@@ -916,7 +926,7 @@ int iphone_afc_seek_file ( iphone_afc_client_t client, iphone_afc_file_t file, i
916 * @note This function is more akin to ftruncate than truncate, and truncate 926 * @note This function is more akin to ftruncate than truncate, and truncate
917 * calls would have to open the file before calling this, sadly. 927 * calls would have to open the file before calling this, sadly.
918 */ 928 */
919int iphone_afc_truncate_file ( iphone_afc_client_t client, iphone_afc_file_t file, uint32_t newsize) { 929iphone_error_t iphone_afc_truncate_file ( iphone_afc_client_t client, iphone_afc_file_t file, uint32_t newsize) {
920 char *buffer = (char*)malloc(sizeof(char) * 16); 930 char *buffer = (char*)malloc(sizeof(char) * 16);
921 uint32 bytes = 0, zero = 0; 931 uint32 bytes = 0, zero = 0;
922 932
diff --git a/src/iphone.c b/src/iphone.c
index 3d179de..f5bc206 100644
--- a/src/iphone.c
+++ b/src/iphone.c
@@ -34,7 +34,7 @@ extern int debug;
34 * @return A structure with data on the first iPhone it finds. (Or NULL, on 34 * @return A structure with data on the first iPhone it finds. (Or NULL, on
35 * error) 35 * error)
36 */ 36 */
37int iphone_get_device ( iphone_device_t *device ){ 37iphone_error_t iphone_get_device ( iphone_device_t *device ){
38 //check we can actually write in device 38 //check we can actually write in device
39 if (!device || (device && *device)) 39 if (!device || (device && *device))
40 return IPHONE_E_INVALID_ARG; 40 return IPHONE_E_INVALID_ARG;
@@ -102,7 +102,7 @@ int iphone_get_device ( iphone_device_t *device ){
102 iphone_free_device(phone); 102 iphone_free_device(phone);
103 if (debug) fprintf(stderr, "get_iPhone(): Invalid version message -- header too short.\n"); 103 if (debug) fprintf(stderr, "get_iPhone(): Invalid version message -- header too short.\n");
104 if (debug && bytes < 0) fprintf(stderr, "get_iPhone(): libusb error message %d: %s (%s)\n", 104 if (debug && bytes < 0) fprintf(stderr, "get_iPhone(): libusb error message %d: %s (%s)\n",
105 bytes, usb_strerror(), strerror(-bytes)); 105 bytes, usb_strerror(), strerror(-bytes));
106 return IPHONE_E_NOT_ENOUGH_DATA; 106 return IPHONE_E_NOT_ENOUGH_DATA;
107 } 107 }
108 108
@@ -134,14 +134,21 @@ int iphone_get_device ( iphone_device_t *device ){
134 * 134 *
135 * @param phone A pointer to an iPhone structure. 135 * @param phone A pointer to an iPhone structure.
136 */ 136 */
137void iphone_free_device ( iphone_device_t device ) { 137iphone_error_t iphone_free_device ( iphone_device_t device ) {
138 if (device->buffer) free(device->buffer); 138 if (!device) return IPHONE_E_INVALID_ARG;
139 if (device->device) { 139 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
140 usb_release_interface(device->device, 1); 140
141 usb_reset(device->device); 141 if (device->buffer) {
142 usb_close(device->device); 142 free(device->buffer);
143 if (device->device) {
144 usb_release_interface(device->device, 1);
145 usb_reset(device->device);
146 usb_close(device->device);
147 ret = IPHONE_E_SUCCESS;
148 }
149 free(device);
143 } 150 }
144 free(device); 151 return ret;
145} 152}
146 153
147/** Sends data to the phone 154/** Sends data to the phone
diff --git a/src/lockdown.c b/src/lockdown.c
index 179b0a9..a22b896 100644
--- a/src/lockdown.c
+++ b/src/lockdown.c
@@ -94,15 +94,18 @@ iphone_lckd_client_t new_lockdownd_client(iphone_device_t phone) {
94 * 94 *
95 * @param control The lockdown client 95 * @param control The lockdown client
96 */ 96 */
97void iphone_lckd_free_client( iphone_lckd_client_t client ) { 97iphone_error_t iphone_lckd_free_client( iphone_lckd_client_t client ) {
98 if (!client) return; 98 if (!client) return IPHONE_E_INVALID_ARG;
99 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
100
99 if (client->connection) { 101 if (client->connection) {
100 iphone_mux_free_client(client->connection); 102 ret = iphone_mux_free_client(client->connection);
101 } 103 }
102 104
103 if (client->ssl_session) gnutls_deinit(*client->ssl_session); 105 if (client->ssl_session) gnutls_deinit(*client->ssl_session);
104 free(client->ssl_session); 106 free(client->ssl_session);
105 free(client); 107 free(client);
108 return ret;
106} 109}
107 110
108/** Polls the iPhone for lockdownd data. 111/** Polls the iPhone for lockdownd data.
@@ -113,20 +116,28 @@ void iphone_lckd_free_client( iphone_lckd_client_t client ) {
113 * 116 *
114 * @return The number of bytes received 117 * @return The number of bytes received
115 */ 118 */
116int iphone_lckd_recv ( iphone_lckd_client_t client, char **dump_data ) { 119iphone_error_t iphone_lckd_recv ( iphone_lckd_client_t client, char **dump_data, uint32_t *recv_bytes ) {
117 if (!client) return 0; 120 if (!client || dump_data || !recv_bytes) return IPHONE_E_INVALID_ARG;
121 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
118 char *receive; 122 char *receive;
119 uint32 datalen = 0, bytes = 0; 123 uint32 datalen = 0, bytes = 0;
120 124
121 if (!client->in_SSL) bytes = iphone_mux_recv(client->connection, (char *)&datalen, sizeof(datalen)); 125 if (!client->in_SSL) ret = iphone_mux_recv(client->connection, (char *)&datalen, sizeof(datalen), &bytes);
122 else bytes = gnutls_record_recv(*client->ssl_session, &datalen, sizeof(datalen)); 126 else {
127 bytes = gnutls_record_recv(*client->ssl_session, &datalen, sizeof(datalen));
128 if (bytes > 0) ret = IPHONE_E_SUCCESS;
129 }
123 datalen = ntohl(datalen); 130 datalen = ntohl(datalen);
124 131
125 receive = (char*)malloc(sizeof(char) * datalen); 132 receive = (char*)malloc(sizeof(char) * datalen);
126 if (!client->in_SSL) bytes = iphone_mux_recv(client->connection, receive, datalen); 133 if (!client->in_SSL) ret = iphone_mux_recv(client->connection, receive, datalen, &bytes);
127 else bytes = gnutls_record_recv(*client->ssl_session, receive, datalen); 134 else {
135 bytes = gnutls_record_recv(*client->ssl_session, receive, datalen);
136 if (bytes > 0) ret = IPHONE_E_SUCCESS;
137 }
128 *dump_data = receive; 138 *dump_data = receive;
129 return bytes; 139 *recv_bytes = bytes;
140 return ret;
130} 141}
131 142
132/** Sends lockdownd data to the iPhone 143/** Sends lockdownd data to the iPhone
@@ -140,11 +151,12 @@ int iphone_lckd_recv ( iphone_lckd_client_t client, char **dump_data ) {
140 * 151 *
141 * @return The number of bytes sent 152 * @return The number of bytes sent
142 */ 153 */
143int iphone_lckd_send ( iphone_lckd_client_t client, char *raw_data, uint32_t length ) { 154iphone_error_t iphone_lckd_send ( iphone_lckd_client_t client, char *raw_data, uint32_t length, uint32_t *sent_bytes ) {
144 if (!client) return 0; 155 if (!client || !raw_data || length == 0 || !sent_bytes) return IPHONE_E_INVALID_ARG;
145 char *real_query; 156 char *real_query;
146 int bytes; 157 int bytes;
147 158 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
159
148 real_query = (char*)malloc(sizeof(char) * (length+4)); 160 real_query = (char*)malloc(sizeof(char) * (length+4));
149 length = htonl(length); 161 length = htonl(length);
150 memcpy(real_query, &length, sizeof(length)); 162 memcpy(real_query, &length, sizeof(length));
@@ -157,11 +169,15 @@ int iphone_lckd_send ( iphone_lckd_client_t client, char *raw_data, uint32_t len
157 packet = NULL; 169 packet = NULL;
158 } 170 }
159 171
160 if (!client->in_SSL) bytes = iphone_mux_send(client->connection, real_query, ntohl(length)+sizeof(length)); 172 if (!client->in_SSL) ret = iphone_mux_send(client->connection, real_query, ntohl(length)+sizeof(length), &bytes);
161 else gnutls_record_send(*client->ssl_session, real_query, ntohl(length)+sizeof(length)); 173 else {
174 gnutls_record_send(*client->ssl_session, real_query, ntohl(length)+sizeof(length));
175 ret = IPHONE_E_SUCCESS;
176 }
162 if (debug) printf("lockdownd_send(): sent it!\n"); 177 if (debug) printf("lockdownd_send(): sent it!\n");
163 free(real_query); 178 free(real_query);
164 return bytes; 179 *sent_bytes = bytes;
180 return ret;
165} 181}
166 182
167/** Initiates the handshake for the lockdown session. Part of the lockdownd handshake. 183/** Initiates the handshake for the lockdown session. Part of the lockdownd handshake.
@@ -307,11 +323,11 @@ int lockdownd_get_device_public_key(iphone_lckd_client_t control, char **public_
307 * 323 *
308 * @return 1 on success and 0 on failure 324 * @return 1 on success and 0 on failure
309 */ 325 */
310int iphone_lckd_new_client ( iphone_device_t device, iphone_lckd_client_t *client ) 326iphone_error_t iphone_lckd_new_client ( iphone_device_t device, iphone_lckd_client_t *client )
311{ 327{
312 if (!device || !client || (client && *client) ) 328 if (!device || !client || (client && *client) )
313 return IPHONE_E_INVALID_ARG; 329 return IPHONE_E_INVALID_ARG;
314 int ret = IPHONE_E_SUCCESS; 330 iphone_error_t ret = IPHONE_E_SUCCESS;
315 char *host_id = NULL; 331 char *host_id = NULL;
316 332
317 iphone_lckd_client_t client_loc = new_lockdownd_client( device ); 333 iphone_lckd_client_t client_loc = new_lockdownd_client( device );
@@ -815,14 +831,15 @@ ssize_t lockdownd_securead(gnutls_transport_ptr_t transport, char *buffer, size_
815 * 831 *
816 * @return The port number the service was started on or 0 on failure. 832 * @return The port number the service was started on or 0 on failure.
817 */ 833 */
818int iphone_lckd_start_service ( iphone_lckd_client_t client, const char *service ) { 834iphone_error_t iphone_lckd_start_service ( iphone_lckd_client_t client, const char *service, int *port ) {
819 if (!client) return 0; 835 if (!client || !service || !port) return IPHONE_E_INVALID_ARG;
820 836
821 char* host_id = get_host_id(); 837 char* host_id = get_host_id();
822 if (host_id && !client->in_SSL && !lockdownd_start_SSL_session(client, host_id)) return 0; 838 if (!host_id) return IPHONE_E_INVALID_CONF;
839 if (!client->in_SSL && !lockdownd_start_SSL_session(client, host_id)) return IPHONE_E_SSL_ERROR;
823 840
824 char *XML_query, **dictionary; 841 char *XML_query, **dictionary;
825 uint32 length, i = 0, port = 0; 842 uint32 length, i = 0, port_loc = 0;
826 uint8 result = 0; 843 uint8 result = 0;
827 844
828 free(host_id); 845 free(host_id);
@@ -832,9 +849,9 @@ int iphone_lckd_start_service ( iphone_lckd_client_t client, const char *service
832 xmlNode *dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); 849 xmlNode *dict = add_child_to_plist(plist, "dict", "\n", NULL, 0);
833 xmlNode *key; 850 xmlNode *key;
834 key = add_key_str_dict_element(plist, dict, "Request", "StartService", 1); 851 key = add_key_str_dict_element(plist, dict, "Request", "StartService", 1);
835 if (!key) { xmlFreeDoc(plist); return 0; } 852 if (!key) { xmlFreeDoc(plist); return IPHONE_E_UNKNOWN_ERROR; }
836 key = add_key_str_dict_element(plist, dict, "Service", service, 1); 853 key = add_key_str_dict_element(plist, dict, "Service", service, 1);
837 if (!key) { xmlFreeDoc(plist); return 0; } 854 if (!key) { xmlFreeDoc(plist); return IPHONE_E_UNKNOWN_ERROR; }
838 855
839 xmlDocDumpMemory(plist, (xmlChar **)&XML_query, &length); 856 xmlDocDumpMemory(plist, (xmlChar **)&XML_query, &length);
840 857
@@ -845,24 +862,24 @@ int iphone_lckd_start_service ( iphone_lckd_client_t client, const char *service
845 862
846 xmlFreeDoc(plist); 863 xmlFreeDoc(plist);
847 864
848 if (length <= 0) return 0; 865 if (length <= 0) return IPHONE_E_NOT_ENOUGH_DATA;
849 else { 866 else {
850 plist = xmlReadMemory(XML_query, length, NULL, NULL, 0); 867 plist = xmlReadMemory(XML_query, length, NULL, NULL, 0);
851 if (!plist) return 0; 868 if (!plist) return IPHONE_E_UNKNOWN_ERROR;
852 dict = xmlDocGetRootElement(plist); 869 dict = xmlDocGetRootElement(plist);
853 if (!dict) return 0; 870 if (!dict) return IPHONE_E_UNKNOWN_ERROR;
854 for (dict = dict->children; dict; dict = dict->next) { 871 for (dict = dict->children; dict; dict = dict->next) {
855 if (!xmlStrcmp(dict->name, "dict")) break; 872 if (!xmlStrcmp(dict->name, "dict")) break;
856 } 873 }
857 874
858 if (!dict) return 0; 875 if (!dict) return IPHONE_E_UNKNOWN_ERROR;
859 dictionary = read_dict_element_strings(dict); 876 dictionary = read_dict_element_strings(dict);
860 877
861 for (i = 0; dictionary[i]; i+=2) { 878 for (i = 0; dictionary[i]; i+=2) {
862 if (debug) printf("lockdownd_start_service() dictionary %s: %s\n", dictionary[i], dictionary[i+1]); 879 if (debug) printf("lockdownd_start_service() dictionary %s: %s\n", dictionary[i], dictionary[i+1]);
863 880
864 if (!xmlStrcmp(dictionary[i], "Port")) { 881 if (!xmlStrcmp(dictionary[i], "Port")) {
865 port = atoi(dictionary[i+1]); 882 port_loc = atoi(dictionary[i+1]);
866 if (debug) printf("lockdownd_start_service() atoi'd port: %i\n", port); 883 if (debug) printf("lockdownd_start_service() atoi'd port: %i\n", port);
867 } 884 }
868 885
@@ -882,9 +899,12 @@ int iphone_lckd_start_service ( iphone_lckd_client_t client, const char *service
882 free(XML_query); 899 free(XML_query);
883 xmlFreeDoc(plist); 900 xmlFreeDoc(plist);
884 free_dictionary(dictionary); 901 free_dictionary(dictionary);
885 if (port && result) return port; 902 if (port && result) {
886 else return 0; 903 *port = port_loc;
904 return IPHONE_E_SUCCESS;
905 }
906 else return IPHONE_E_UNKNOWN_ERROR;
887 } 907 }
888 908
889 return 0; 909 return IPHONE_E_UNKNOWN_ERROR;
890} 910}
diff --git a/src/usbmux.c b/src/usbmux.c
index 5e3f441..8d85245 100644
--- a/src/usbmux.c
+++ b/src/usbmux.c
@@ -116,7 +116,7 @@ void add_connection(iphone_umux_client_t connection) {
116 * @param client A mux TCP header for the connection which is used for tracking and data transfer. 116 * @param client A mux TCP header for the connection which is used for tracking and data transfer.
117 * @return IPHONE_E_SUCCESS on success, an error code otherwise. 117 * @return IPHONE_E_SUCCESS on success, an error code otherwise.
118 */ 118 */
119int iphone_mux_new_client ( iphone_device_t device, uint16_t src_port, uint16_t dst_port, iphone_umux_client_t *client ){ 119iphone_error_t iphone_mux_new_client ( iphone_device_t device, uint16_t src_port, uint16_t dst_port, iphone_umux_client_t *client ){
120 if (!device || !src_port || !dst_port) 120 if (!device || !src_port || !dst_port)
121 return IPHONE_E_INVALID_ARG; 121 return IPHONE_E_INVALID_ARG;
122 122
@@ -165,8 +165,10 @@ int iphone_mux_new_client ( iphone_device_t device, uint16_t src_port, uint16_t
165 * @note Once a connection is closed it may not be used again. 165 * @note Once a connection is closed it may not be used again.
166 * 166 *
167 * @param connection The connection to close. 167 * @param connection The connection to close.
168 *
169 * @return IPHONE_E_SUCCESS on success.
168 */ 170 */
169void iphone_mux_free_client ( iphone_umux_client_t client ) { 171iphone_error_t iphone_mux_free_client ( iphone_umux_client_t client ) {
170 if (!client || !client->phone) return; 172 if (!client || !client->phone) return;
171 173
172 client->header->tcp_flags = 0x04; 174 client->header->tcp_flags = 0x04;
@@ -183,6 +185,8 @@ void iphone_mux_free_client ( iphone_umux_client_t client ) {
183 printf("get_iPhone(): when reading, libusb gave me the error: %s\n", usb_strerror()); 185 printf("get_iPhone(): when reading, libusb gave me the error: %s\n", usb_strerror());
184 186
185 delete_connection(client); 187 delete_connection(client);
188
189 return IPHONE_E_SUCCESS;
186} 190}
187 191
188 192
@@ -192,15 +196,16 @@ void iphone_mux_free_client ( iphone_umux_client_t client ) {
192 * @param client The client we're sending data on. 196 * @param client The client we're sending data on.
193 * @param data A pointer to the data to send. 197 * @param data A pointer to the data to send.
194 * @param datalen How much data we're sending. 198 * @param datalen How much data we're sending.
199 * @param sent_bytes The number of bytes sent, minus the header (28)
195 * 200 *
196 * @return The number of bytes sent, minus the header (28), or -1 on error. 201 * @return IPHONE_E_SUCCESS on success.
197 */ 202 */
198 203
199int iphone_mux_send ( iphone_umux_client_t client, const char *data, uint32_t datalen ) { 204iphone_error_t iphone_mux_send ( iphone_umux_client_t client, const char *data, uint32_t datalen, uint32_t *sent_bytes ) {
200 if (!client->phone || !client || !data || datalen == 0) return -1; 205 if (!client->phone || !client || !data || datalen == 0 || !sent_bytes) return IPHONE_E_INVALID_ARG;
201 // client->scnt and client->ocnt should already be in host notation... 206 // client->scnt and client->ocnt should already be in host notation...
202 // we don't need to change them juuuust yet. 207 // we don't need to change them juuuust yet.
203 int bytes = 0; 208 *sent_bytes = 0;
204 if (debug) printf("mux_send(): client wants to send %i bytes\n", datalen); 209 if (debug) printf("mux_send(): client wants to send %i bytes\n", datalen);
205 char *buffer = (char*)malloc(sizeof(usbmux_tcp_header) + datalen + 2); // allow 2 bytes of safety padding 210 char *buffer = (char*)malloc(sizeof(usbmux_tcp_header) + datalen + 2); // allow 2 bytes of safety padding
206 // Set the length and pre-emptively htonl/htons it 211 // Set the length and pre-emptively htonl/htons it
@@ -218,12 +223,12 @@ int iphone_mux_send ( iphone_umux_client_t client, const char *data, uint32_t da
218 if (debug) printf("actually sending %zi bytes of data at %p\n", sizeof(usbmux_tcp_header)+datalen, buffer); 223 if (debug) printf("actually sending %zi bytes of data at %p\n", sizeof(usbmux_tcp_header)+datalen, buffer);
219 224
220 225
221 bytes = send_to_phone(client->phone, buffer, sizeof(usbmux_tcp_header)+datalen); 226 *sent_bytes = send_to_phone(client->phone, buffer, sizeof(usbmux_tcp_header)+datalen);
222 if (debug) printf("mux_send: sent %i bytes!\n", bytes); 227 if (debug) printf("mux_send: sent %i bytes!\n", *sent_bytes);
223 // Now that we've sent it off, we can clean up after our sloppy selves. 228 // Now that we've sent it off, we can clean up after our sloppy selves.
224 if (debug) { 229 if (debug) {
225 FILE *packet = fopen("packet", "a+"); 230 FILE *packet = fopen("packet", "a+");
226 fwrite(buffer, 1, bytes, packet); 231 fwrite(buffer, 1, *sent_bytes, packet);
227 fclose(packet); 232 fclose(packet);
228 printf("\n"); 233 printf("\n");
229 } 234 }
@@ -238,13 +243,14 @@ int iphone_mux_send ( iphone_umux_client_t client, const char *data, uint32_t da
238 client->header->length16 = ntohs(client->header->length16); 243 client->header->length16 = ntohs(client->header->length16);
239 244
240 // Now return the bytes. 245 // Now return the bytes.
241 if (bytes < sizeof(usbmux_tcp_header)+datalen) { 246 if (*sent_bytes < sizeof(usbmux_tcp_header)+datalen) {
242 return -1; // blah 247 *sent_bytes = 0;
248 return IPHONE_E_NOT_ENOUGH_DATA;
243 } else { 249 } else {
244 return bytes - 28; // actual length sent. :/ 250 *sent_bytes = *sent_bytes - 28; // actual length sent. :/
245 } 251 }
246 252
247 return bytes; // or something 253 return IPHONE_E_UNKNOWN_ERROR;
248} 254}
249 255
250/** This is a higher-level USBMuxTCP-like function 256/** This is a higher-level USBMuxTCP-like function
@@ -255,7 +261,10 @@ int iphone_mux_send ( iphone_umux_client_t client, const char *data, uint32_t da
255 * 261 *
256 * @return How many bytes were read, or -1 if something bad happens. 262 * @return How many bytes were read, or -1 if something bad happens.
257 */ 263 */
258int iphone_mux_recv ( iphone_umux_client_t client, char *data, uint32_t datalen ) { 264iphone_error_t iphone_mux_recv ( iphone_umux_client_t client, char *data, uint32_t datalen, uint32_t *recv_bytes ) {
265
266 if (!client || !data || datalen == 0 || !recv_bytes)
267 return IPHONE_E_INVALID_ARG;
259 /* 268 /*
260 * Order of operation: 269 * Order of operation:
261 * 1.) Check if the client has a pre-received buffer. 270 * 1.) Check if the client has a pre-received buffer.
@@ -268,6 +277,7 @@ int iphone_mux_recv ( iphone_umux_client_t client, char *data, uint32_t datalen
268 */ 277 */
269 if (debug) printf("mux_recv: datalen == %i\n", datalen); 278 if (debug) printf("mux_recv: datalen == %i\n", datalen);
270 int bytes = 0, i = 0, complex = 0, offset = 0; 279 int bytes = 0, i = 0, complex = 0, offset = 0;
280 *recv_bytes = 0;
271 char *buffer = NULL; 281 char *buffer = NULL;
272 usbmux_tcp_header *header = NULL; 282 usbmux_tcp_header *header = NULL;
273 283
@@ -304,7 +314,7 @@ int iphone_mux_recv ( iphone_umux_client_t client, char *data, uint32_t datalen
304 if (bytes < 28) { 314 if (bytes < 28) {
305 free(buffer); 315 free(buffer);
306 if (debug) printf("mux_recv: Did not even get the header.\n"); 316 if (debug) printf("mux_recv: Did not even get the header.\n");
307 return -1; 317 return IPHONE_E_NOT_ENOUGH_DATA;
308 } 318 }
309 319
310 header = (usbmux_tcp_header*)buffer; 320 header = (usbmux_tcp_header*)buffer;
@@ -332,7 +342,7 @@ int iphone_mux_recv ( iphone_umux_client_t client, char *data, uint32_t datalen
332 // Free our buffer and continue. 342 // Free our buffer and continue.
333 free(buffer); 343 free(buffer);
334 buffer = NULL; 344 buffer = NULL;
335 return iphone_mux_recv(client, data, datalen); // recurse back in to try again 345 return iphone_mux_recv(client, data, datalen, recv_bytes); // recurse back in to try again
336 } 346 }
337 347
338 // The packet was absolutely meant for us if it hits this point. 348 // The packet was absolutely meant for us if it hits this point.
@@ -348,13 +358,15 @@ int iphone_mux_recv ( iphone_umux_client_t client, char *data, uint32_t datalen
348 memcpy(client->recv_buffer+complex, buffer+28+datalen, (bytes-28) - datalen); 358 memcpy(client->recv_buffer+complex, buffer+28+datalen, (bytes-28) - datalen);
349 free(buffer); 359 free(buffer);
350 client->header->ocnt += bytes-28; 360 client->header->ocnt += bytes-28;
351 return datalen; 361 *recv_bytes = datalen;
362 return IPHONE_E_SUCCESS;
352 } else { 363 } else {
353 // Fill the data with what we have, and just return. 364 // Fill the data with what we have, and just return.
354 memcpy(data+offset, buffer+28, bytes-28); // data+offset: see #2b, above 365 memcpy(data+offset, buffer+28, bytes-28); // data+offset: see #2b, above
355 client->header->ocnt += bytes-28; 366 client->header->ocnt += bytes-28;
356 free(buffer); 367 free(buffer);
357 return (bytes-28); 368 *recv_bytes = bytes - 28;
369 return IPHONE_E_SUCCESS;
358 } 370 }
359 371
360 // If we get to this point, 'tis probably bad. 372 // If we get to this point, 'tis probably bad.