diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/AFC.c | 68 | ||||
| -rw-r--r-- | src/AFC.h | 2 | ||||
| -rw-r--r-- | src/MobileSync.c | 14 | ||||
| -rw-r--r-- | src/MobileSync.h | 2 | ||||
| -rw-r--r-- | src/NotificationProxy.c | 28 | ||||
| -rw-r--r-- | src/NotificationProxy.h | 2 | ||||
| -rw-r--r-- | src/iphone.c | 374 | ||||
| -rw-r--r-- | src/iphone.h | 22 | ||||
| -rw-r--r-- | src/lockdown.c | 26 | ||||
| -rw-r--r-- | src/lockdown.h | 2 | ||||
| -rw-r--r-- | src/userpref.c | 6 | ||||
| -rw-r--r-- | src/userpref.h | 4 |
12 files changed, 403 insertions, 147 deletions
| @@ -68,18 +68,18 @@ afc_error_t afc_client_new(iphone_device_t device, int dst_port, afc_client_t * | |||
| 68 | return AFC_E_INVALID_ARGUMENT; | 68 | return AFC_E_INVALID_ARGUMENT; |
| 69 | 69 | ||
| 70 | /* attempt connection */ | 70 | /* attempt connection */ |
| 71 | int sfd = usbmuxd_connect(device->handle, dst_port); | 71 | iphone_connection_t connection = NULL; |
| 72 | if (sfd < 0) { | 72 | if (iphone_device_connect(device, dst_port, &connection) != IPHONE_E_SUCCESS) { |
| 73 | return AFC_E_MUX_ERROR; | 73 | return AFC_E_MUX_ERROR; |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | afc_client_t client_loc = (afc_client_t) malloc(sizeof(struct afc_client_int)); | 76 | afc_client_t client_loc = (afc_client_t) malloc(sizeof(struct afc_client_int)); |
| 77 | client_loc->sfd = sfd; | 77 | client_loc->connection = connection; |
| 78 | 78 | ||
| 79 | /* allocate a packet */ | 79 | /* allocate a packet */ |
| 80 | client_loc->afc_packet = (AFCPacket *) malloc(sizeof(AFCPacket)); | 80 | client_loc->afc_packet = (AFCPacket *) malloc(sizeof(AFCPacket)); |
| 81 | if (!client_loc->afc_packet) { | 81 | if (!client_loc->afc_packet) { |
| 82 | usbmuxd_disconnect(client_loc->sfd); | 82 | iphone_device_disconnect(client_loc->connection); |
| 83 | free(client_loc); | 83 | free(client_loc); |
| 84 | return AFC_E_NO_MEM; | 84 | return AFC_E_NO_MEM; |
| 85 | } | 85 | } |
| @@ -102,10 +102,10 @@ afc_error_t afc_client_new(iphone_device_t device, int dst_port, afc_client_t * | |||
| 102 | */ | 102 | */ |
| 103 | afc_error_t afc_client_free(afc_client_t client) | 103 | afc_error_t afc_client_free(afc_client_t client) |
| 104 | { | 104 | { |
| 105 | if (!client || client->sfd < 0 || !client->afc_packet) | 105 | if (!client || !client->connection || !client->afc_packet) |
| 106 | return AFC_E_INVALID_ARGUMENT; | 106 | return AFC_E_INVALID_ARGUMENT; |
| 107 | 107 | ||
| 108 | usbmuxd_disconnect(client->sfd); | 108 | iphone_device_disconnect(client->connection); |
| 109 | free(client->afc_packet); | 109 | free(client->afc_packet); |
| 110 | if (client->mutex) { | 110 | if (client->mutex) { |
| 111 | g_mutex_free(client->mutex); | 111 | g_mutex_free(client->mutex); |
| @@ -132,7 +132,7 @@ static int afc_dispatch_packet(afc_client_t client, const char *data, uint64_t l | |||
| 132 | int bytes = 0, offset = 0; | 132 | int bytes = 0, offset = 0; |
| 133 | char *buffer; | 133 | char *buffer; |
| 134 | 134 | ||
| 135 | if (!client || client->sfd < 0 || !client->afc_packet) | 135 | if (!client || !client->connection || !client->afc_packet) |
| 136 | return 0; | 136 | return 0; |
| 137 | 137 | ||
| 138 | if (!data || !length) | 138 | if (!data || !length) |
| @@ -164,7 +164,7 @@ static int afc_dispatch_packet(afc_client_t client, const char *data, uint64_t l | |||
| 164 | return -1; | 164 | return -1; |
| 165 | } | 165 | } |
| 166 | memcpy(buffer + sizeof(AFCPacket), data, offset); | 166 | memcpy(buffer + sizeof(AFCPacket), data, offset); |
| 167 | usbmuxd_send(client->sfd, buffer, client->afc_packet->this_length, (uint32_t*)&bytes); | 167 | iphone_device_send(client->connection, buffer, client->afc_packet->this_length, (uint32_t*)&bytes); |
| 168 | free(buffer); | 168 | free(buffer); |
| 169 | if (bytes <= 0) { | 169 | if (bytes <= 0) { |
| 170 | return bytes; | 170 | return bytes; |
| @@ -175,7 +175,7 @@ static int afc_dispatch_packet(afc_client_t client, const char *data, uint64_t l | |||
| 175 | log_debug_msg("%s: Buffer: \n", __func__); | 175 | log_debug_msg("%s: Buffer: \n", __func__); |
| 176 | log_debug_buffer(data + offset, length - offset); | 176 | log_debug_buffer(data + offset, length - offset); |
| 177 | 177 | ||
| 178 | usbmuxd_send(client->sfd, data + offset, length - offset, (uint32_t*)&bytes); | 178 | iphone_device_send(client->connection, data + offset, length - offset, (uint32_t*)&bytes); |
| 179 | return bytes; | 179 | return bytes; |
| 180 | } else { | 180 | } else { |
| 181 | log_debug_msg("%s: doin things the old way\n", __func__); | 181 | log_debug_msg("%s: doin things the old way\n", __func__); |
| @@ -188,7 +188,7 @@ static int afc_dispatch_packet(afc_client_t client, const char *data, uint64_t l | |||
| 188 | } | 188 | } |
| 189 | log_debug_buffer(buffer, client->afc_packet->this_length); | 189 | log_debug_buffer(buffer, client->afc_packet->this_length); |
| 190 | log_debug_msg("\n"); | 190 | log_debug_msg("\n"); |
| 191 | usbmuxd_send(client->sfd, buffer, client->afc_packet->this_length, (uint32_t*)&bytes); | 191 | iphone_device_send(client->connection, buffer, client->afc_packet->this_length, (uint32_t*)&bytes); |
| 192 | 192 | ||
| 193 | if (buffer) { | 193 | if (buffer) { |
| 194 | free(buffer); | 194 | free(buffer); |
| @@ -220,7 +220,7 @@ static afc_error_t afc_receive_data(afc_client_t client, char **dump_here, int * | |||
| 220 | *bytes = 0; | 220 | *bytes = 0; |
| 221 | 221 | ||
| 222 | /* first, read the AFC header */ | 222 | /* first, read the AFC header */ |
| 223 | usbmuxd_recv(client->sfd, (char*)&header, sizeof(AFCPacket), (uint32_t*)bytes); | 223 | iphone_device_recv(client->connection, (char*)&header, sizeof(AFCPacket), (uint32_t*)bytes); |
| 224 | if (*bytes <= 0) { | 224 | if (*bytes <= 0) { |
| 225 | log_debug_msg("%s: Just didn't get enough.\n", __func__); | 225 | log_debug_msg("%s: Just didn't get enough.\n", __func__); |
| 226 | *dump_here = NULL; | 226 | *dump_here = NULL; |
| @@ -273,7 +273,7 @@ static afc_error_t afc_receive_data(afc_client_t client, char **dump_here, int * | |||
| 273 | 273 | ||
| 274 | *dump_here = (char*)malloc(entire_len); | 274 | *dump_here = (char*)malloc(entire_len); |
| 275 | if (this_len > 0) { | 275 | if (this_len > 0) { |
| 276 | usbmuxd_recv(client->sfd, *dump_here, this_len, (uint32_t*)bytes); | 276 | iphone_device_recv(client->connection, *dump_here, this_len, (uint32_t*)bytes); |
| 277 | if (*bytes <= 0) { | 277 | if (*bytes <= 0) { |
| 278 | free(*dump_here); | 278 | free(*dump_here); |
| 279 | *dump_here = NULL; | 279 | *dump_here = NULL; |
| @@ -291,7 +291,7 @@ static afc_error_t afc_receive_data(afc_client_t client, char **dump_here, int * | |||
| 291 | 291 | ||
| 292 | if (entire_len > this_len) { | 292 | if (entire_len > this_len) { |
| 293 | while (current_count < entire_len) { | 293 | while (current_count < entire_len) { |
| 294 | usbmuxd_recv(client->sfd, (*dump_here)+current_count, entire_len - current_count, (uint32_t*)bytes); | 294 | iphone_device_recv(client->connection, (*dump_here)+current_count, entire_len - current_count, (uint32_t*)bytes); |
| 295 | if (*bytes <= 0) { | 295 | if (*bytes <= 0) { |
| 296 | log_debug_msg("%s: Error receiving data (recv returned %d)\n", __func__, *bytes); | 296 | log_debug_msg("%s: Error receiving data (recv returned %d)\n", __func__, *bytes); |
| 297 | break; | 297 | break; |
| @@ -468,26 +468,32 @@ afc_error_t afc_get_device_info(afc_client_t client, char ***infos) | |||
| 468 | return ret; | 468 | return ret; |
| 469 | } | 469 | } |
| 470 | 470 | ||
| 471 | /** Get a specific field of the device info for a client connection to phone. | 471 | /** Get a specific key of the device info list for a client connection. |
| 472 | * Known values are: Model, FSTotalBytes, FSFreeBytes and FSBlockSize. This is | 472 | * Known key values are: Model, FSTotalBytes, FSFreeBytes and FSBlockSize. |
| 473 | * a helper function for afc_get_device_info(). | 473 | * This is a helper function for afc_get_device_info(). |
| 474 | * | 474 | * |
| 475 | * @param client The client to get device info for. | 475 | * @param client The client to get device info for. |
| 476 | * @param field The field to get the information for | 476 | * @param key The key to get the value of. |
| 477 | * @param value The value for the key if successful or NULL otherwise. | ||
| 477 | * | 478 | * |
| 478 | * @return A char * or NULL if there was an error. | 479 | * @return AFC_E_SUCCESS on success or an AFC_E_* error value. |
| 479 | */ | 480 | */ |
| 480 | char * afc_get_device_info_field(afc_client_t client, const char *field) | 481 | afc_error_t afc_get_device_info_key(afc_client_t client, const char *key, char **value) |
| 481 | { | 482 | { |
| 482 | char *ret = NULL; | 483 | afc_error_t ret = AFC_E_INTERNAL_ERROR; |
| 483 | char **kvps, **ptr; | 484 | char **kvps, **ptr; |
| 484 | 485 | ||
| 485 | if (field == NULL || afc_get_device_info(client, &kvps) != AFC_E_SUCCESS) | 486 | *value = NULL; |
| 486 | return NULL; | 487 | if (key == NULL) |
| 488 | return AFC_E_INVALID_ARGUMENT; | ||
| 489 | |||
| 490 | ret = afc_get_device_info(client, &kvps); | ||
| 491 | if (ret != AFC_E_SUCCESS) | ||
| 492 | return ret; | ||
| 487 | 493 | ||
| 488 | for (ptr = kvps; *ptr; ptr++) { | 494 | for (ptr = kvps; *ptr; ptr++) { |
| 489 | if (!strcmp(*ptr, field)) { | 495 | if (!strcmp(*ptr, key)) { |
| 490 | ret = strdup(*(ptr+1)); | 496 | *value = strdup(*(ptr+1)); |
| 491 | break; | 497 | break; |
| 492 | } | 498 | } |
| 493 | } | 499 | } |
| @@ -511,7 +517,7 @@ afc_error_t afc_remove_path(afc_client_t client, const char *path) | |||
| 511 | int bytes; | 517 | int bytes; |
| 512 | afc_error_t ret = AFC_E_UNKNOWN_ERROR; | 518 | afc_error_t ret = AFC_E_UNKNOWN_ERROR; |
| 513 | 519 | ||
| 514 | if (!client || !path || !client->afc_packet || client->sfd < 0) | 520 | if (!client || !path || !client->afc_packet || !client->connection) |
| 515 | return AFC_E_INVALID_ARGUMENT; | 521 | return AFC_E_INVALID_ARGUMENT; |
| 516 | 522 | ||
| 517 | afc_lock(client); | 523 | afc_lock(client); |
| @@ -554,7 +560,7 @@ afc_error_t afc_rename_path(afc_client_t client, const char *from, const char *t | |||
| 554 | int bytes = 0; | 560 | int bytes = 0; |
| 555 | afc_error_t ret = AFC_E_UNKNOWN_ERROR; | 561 | afc_error_t ret = AFC_E_UNKNOWN_ERROR; |
| 556 | 562 | ||
| 557 | if (!client || !from || !to || !client->afc_packet || client->sfd < 0) | 563 | if (!client || !from || !to || !client->afc_packet || !client->connection) |
| 558 | return AFC_E_INVALID_ARGUMENT; | 564 | return AFC_E_INVALID_ARGUMENT; |
| 559 | 565 | ||
| 560 | afc_lock(client); | 566 | afc_lock(client); |
| @@ -681,7 +687,7 @@ afc_file_open(afc_client_t client, const char *filename, | |||
| 681 | // set handle to 0 so in case an error occurs, the handle is invalid | 687 | // set handle to 0 so in case an error occurs, the handle is invalid |
| 682 | *handle = 0; | 688 | *handle = 0; |
| 683 | 689 | ||
| 684 | if (!client || client->sfd < 0|| !client->afc_packet) | 690 | if (!client || !client->connection || !client->afc_packet) |
| 685 | return AFC_E_INVALID_ARGUMENT; | 691 | return AFC_E_INVALID_ARGUMENT; |
| 686 | 692 | ||
| 687 | afc_lock(client); | 693 | afc_lock(client); |
| @@ -736,7 +742,7 @@ afc_file_read(afc_client_t client, uint64_t handle, char *data, int length, uint | |||
| 736 | const int MAXIMUM_READ_SIZE = 1 << 16; | 742 | const int MAXIMUM_READ_SIZE = 1 << 16; |
| 737 | afc_error_t ret = AFC_E_SUCCESS; | 743 | afc_error_t ret = AFC_E_SUCCESS; |
| 738 | 744 | ||
| 739 | if (!client || !client->afc_packet || client->sfd < 0 || handle == 0) | 745 | if (!client || !client->afc_packet || !client->connection || handle == 0) |
| 740 | return AFC_E_INVALID_ARGUMENT; | 746 | return AFC_E_INVALID_ARGUMENT; |
| 741 | log_debug_msg("%s: called for length %i\n", __func__, length); | 747 | log_debug_msg("%s: called for length %i\n", __func__, length); |
| 742 | 748 | ||
| @@ -813,7 +819,7 @@ afc_file_write(afc_client_t client, uint64_t handle, | |||
| 813 | char *out_buffer = NULL; | 819 | char *out_buffer = NULL; |
| 814 | afc_error_t ret = AFC_E_SUCCESS; | 820 | afc_error_t ret = AFC_E_SUCCESS; |
| 815 | 821 | ||
| 816 | if (!client || !client->afc_packet || client->sfd < 0 || !bytes || (handle == 0)) | 822 | if (!client || !client->afc_packet || !client->connection || !bytes || (handle == 0)) |
| 817 | return AFC_E_INVALID_ARGUMENT; | 823 | return AFC_E_INVALID_ARGUMENT; |
| 818 | 824 | ||
| 819 | afc_lock(client); | 825 | afc_lock(client); |
| @@ -1133,7 +1139,7 @@ afc_error_t afc_truncate(afc_client_t client, const char *path, off_t newsize) | |||
| 1133 | uint64_t size_requested = newsize; | 1139 | uint64_t size_requested = newsize; |
| 1134 | afc_error_t ret = AFC_E_UNKNOWN_ERROR; | 1140 | afc_error_t ret = AFC_E_UNKNOWN_ERROR; |
| 1135 | 1141 | ||
| 1136 | if (!client || !path || !client->afc_packet || client->sfd < 0) | 1142 | if (!client || !path || !client->afc_packet || !client->connection) |
| 1137 | return AFC_E_INVALID_ARGUMENT; | 1143 | return AFC_E_INVALID_ARGUMENT; |
| 1138 | 1144 | ||
| 1139 | afc_lock(client); | 1145 | afc_lock(client); |
| @@ -1177,7 +1183,7 @@ afc_error_t afc_make_link(afc_client_t client, afc_link_type_t linktype, const c | |||
| 1177 | uint64_t type = linktype; | 1183 | uint64_t type = linktype; |
| 1178 | afc_error_t ret = AFC_E_UNKNOWN_ERROR; | 1184 | afc_error_t ret = AFC_E_UNKNOWN_ERROR; |
| 1179 | 1185 | ||
| 1180 | if (!client || !target || !linkname || !client->afc_packet || client->sfd < 0) | 1186 | if (!client || !target || !linkname || !client->afc_packet || !client->connection) |
| 1181 | return AFC_E_INVALID_ARGUMENT; | 1187 | return AFC_E_INVALID_ARGUMENT; |
| 1182 | 1188 | ||
| 1183 | afc_lock(client); | 1189 | afc_lock(client); |
| @@ -46,7 +46,7 @@ typedef struct __AFCToken { | |||
| 46 | } AFCToken; | 46 | } AFCToken; |
| 47 | 47 | ||
| 48 | struct afc_client_int { | 48 | struct afc_client_int { |
| 49 | int sfd; | 49 | iphone_connection_t connection; |
| 50 | AFCPacket *afc_packet; | 50 | AFCPacket *afc_packet; |
| 51 | int file_handle; | 51 | int file_handle; |
| 52 | int lock; | 52 | int lock; |
diff --git a/src/MobileSync.c b/src/MobileSync.c index 4463251..8a7d724 100644 --- a/src/MobileSync.c +++ b/src/MobileSync.c | |||
| @@ -40,13 +40,13 @@ mobilesync_error_t mobilesync_client_new(iphone_device_t device, int dst_port, | |||
| 40 | mobilesync_error_t ret = MOBILESYNC_E_UNKNOWN_ERROR; | 40 | mobilesync_error_t ret = MOBILESYNC_E_UNKNOWN_ERROR; |
| 41 | 41 | ||
| 42 | /* Attempt connection */ | 42 | /* Attempt connection */ |
| 43 | int sfd = usbmuxd_connect(device->handle, dst_port); | 43 | iphone_connection_t connection = NULL; |
| 44 | if (sfd < 0) { | 44 | if (iphone_device_connect(device, dst_port, &connection) != IPHONE_E_SUCCESS) { |
| 45 | return ret; | 45 | return ret; |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | mobilesync_client_t client_loc = (mobilesync_client_t) malloc(sizeof(struct mobilesync_client_int)); | 48 | mobilesync_client_t client_loc = (mobilesync_client_t) malloc(sizeof(struct mobilesync_client_int)); |
| 49 | client_loc->sfd = sfd; | 49 | client_loc->connection = connection; |
| 50 | 50 | ||
| 51 | /* perform handshake */ | 51 | /* perform handshake */ |
| 52 | plist_t array = NULL; | 52 | plist_t array = NULL; |
| @@ -126,7 +126,7 @@ mobilesync_error_t mobilesync_client_free(mobilesync_client_t client) | |||
| 126 | return IPHONE_E_INVALID_ARG; | 126 | return IPHONE_E_INVALID_ARG; |
| 127 | 127 | ||
| 128 | mobilesync_disconnect(client); | 128 | mobilesync_disconnect(client); |
| 129 | return (usbmuxd_disconnect(client->sfd) == 0 ? MOBILESYNC_E_SUCCESS: MOBILESYNC_E_MUX_ERROR); | 129 | return (iphone_device_disconnect(client->connection) == 0 ? MOBILESYNC_E_SUCCESS: MOBILESYNC_E_MUX_ERROR); |
| 130 | } | 130 | } |
| 131 | 131 | ||
| 132 | /** Polls the iPhone for MobileSync data. | 132 | /** Polls the iPhone for MobileSync data. |
| @@ -144,14 +144,14 @@ mobilesync_error_t mobilesync_recv(mobilesync_client_t client, plist_t * plist) | |||
| 144 | char *receive = NULL; | 144 | char *receive = NULL; |
| 145 | uint32_t datalen = 0, bytes = 0, received_bytes = 0; | 145 | uint32_t datalen = 0, bytes = 0, received_bytes = 0; |
| 146 | 146 | ||
| 147 | ret = usbmuxd_recv(client->sfd, (char *) &datalen, sizeof(datalen), &bytes); | 147 | ret = iphone_device_recv(client->connection, (char *) &datalen, sizeof(datalen), &bytes); |
| 148 | datalen = ntohl(datalen); | 148 | datalen = ntohl(datalen); |
| 149 | 149 | ||
| 150 | receive = (char *) malloc(sizeof(char) * datalen); | 150 | receive = (char *) malloc(sizeof(char) * datalen); |
| 151 | 151 | ||
| 152 | /* fill buffer and request more packets if needed */ | 152 | /* fill buffer and request more packets if needed */ |
| 153 | while ((received_bytes < datalen) && (ret == MOBILESYNC_E_SUCCESS)) { | 153 | while ((received_bytes < datalen) && (ret == MOBILESYNC_E_SUCCESS)) { |
| 154 | ret = usbmuxd_recv(client->sfd, receive + received_bytes, datalen - received_bytes, &bytes); | 154 | ret = iphone_device_recv(client->connection, receive + received_bytes, datalen - received_bytes, &bytes); |
| 155 | received_bytes += bytes; | 155 | received_bytes += bytes; |
| 156 | } | 156 | } |
| 157 | 157 | ||
| @@ -207,7 +207,7 @@ mobilesync_error_t mobilesync_send(mobilesync_client_t client, plist_t plist) | |||
| 207 | memcpy(real_query, &length, sizeof(length)); | 207 | memcpy(real_query, &length, sizeof(length)); |
| 208 | memcpy(real_query + 4, content, ntohl(length)); | 208 | memcpy(real_query + 4, content, ntohl(length)); |
| 209 | 209 | ||
| 210 | ret = usbmuxd_send(client->sfd, real_query, ntohl(length) + sizeof(length), (uint32_t*)&bytes); | 210 | ret = iphone_device_send(client->connection, real_query, ntohl(length) + sizeof(length), (uint32_t*)&bytes); |
| 211 | free(real_query); | 211 | free(real_query); |
| 212 | return (ret == 0 ? MOBILESYNC_E_SUCCESS: MOBILESYNC_E_MUX_ERROR); | 212 | return (ret == 0 ? MOBILESYNC_E_SUCCESS: MOBILESYNC_E_MUX_ERROR); |
| 213 | } | 213 | } |
diff --git a/src/MobileSync.h b/src/MobileSync.h index 6347399..605145f 100644 --- a/src/MobileSync.h +++ b/src/MobileSync.h | |||
| @@ -24,7 +24,7 @@ | |||
| 24 | #include "libiphone/mobilesync.h" | 24 | #include "libiphone/mobilesync.h" |
| 25 | 25 | ||
| 26 | struct mobilesync_client_int { | 26 | struct mobilesync_client_int { |
| 27 | int sfd; | 27 | iphone_connection_t connection; |
| 28 | }; | 28 | }; |
| 29 | 29 | ||
| 30 | #endif | 30 | #endif |
diff --git a/src/NotificationProxy.c b/src/NotificationProxy.c index e4735cc..da636ab 100644 --- a/src/NotificationProxy.c +++ b/src/NotificationProxy.c | |||
| @@ -83,9 +83,9 @@ static np_error_t np_plist_send(np_client_t client, plist_t dict) | |||
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | nlen = htonl(length); | 85 | nlen = htonl(length); |
| 86 | usbmuxd_send(client->sfd, (const char*)&nlen, sizeof(nlen), (uint32_t*)&bytes); | 86 | iphone_device_send(client->connection, (const char*)&nlen, sizeof(nlen), (uint32_t*)&bytes); |
| 87 | if (bytes == sizeof(nlen)) { | 87 | if (bytes == sizeof(nlen)) { |
| 88 | usbmuxd_send(client->sfd, XML_content, length, (uint32_t*)&bytes); | 88 | iphone_device_send(client->connection, XML_content, length, (uint32_t*)&bytes); |
| 89 | if (bytes > 0) { | 89 | if (bytes > 0) { |
| 90 | if ((uint32_t)bytes == length) { | 90 | if ((uint32_t)bytes == length) { |
| 91 | res = NP_E_SUCCESS; | 91 | res = NP_E_SUCCESS; |
| @@ -121,13 +121,13 @@ np_error_t np_client_new(iphone_device_t device, int dst_port, np_client_t *clie | |||
| 121 | return NP_E_INVALID_ARG; | 121 | return NP_E_INVALID_ARG; |
| 122 | 122 | ||
| 123 | /* Attempt connection */ | 123 | /* Attempt connection */ |
| 124 | int sfd = usbmuxd_connect(device->handle, dst_port); | 124 | iphone_connection_t connection = NULL; |
| 125 | if (sfd < 0) { | 125 | if (iphone_device_connect(device, dst_port, &connection) != IPHONE_E_SUCCESS) { |
| 126 | return NP_E_UNKNOWN_ERROR; | 126 | return NP_E_UNKNOWN_ERROR; |
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | np_client_t client_loc = (np_client_t) malloc(sizeof(struct np_client_int)); | 129 | np_client_t client_loc = (np_client_t) malloc(sizeof(struct np_client_int)); |
| 130 | client_loc->sfd = sfd; | 130 | client_loc->connection = connection; |
| 131 | 131 | ||
| 132 | client_loc->mutex = g_mutex_new(); | 132 | client_loc->mutex = g_mutex_new(); |
| 133 | 133 | ||
| @@ -146,8 +146,8 @@ np_error_t np_client_free(np_client_t client) | |||
| 146 | if (!client) | 146 | if (!client) |
| 147 | return NP_E_INVALID_ARG; | 147 | return NP_E_INVALID_ARG; |
| 148 | 148 | ||
| 149 | usbmuxd_disconnect(client->sfd); | 149 | iphone_device_disconnect(client->connection); |
| 150 | client->sfd = -1; | 150 | client->connection = NULL; |
| 151 | if (client->notifier) { | 151 | if (client->notifier) { |
| 152 | log_debug_msg("joining np callback\n"); | 152 | log_debug_msg("joining np callback\n"); |
| 153 | g_thread_join(client->notifier); | 153 | g_thread_join(client->notifier); |
| @@ -293,12 +293,12 @@ static int np_get_notification(np_client_t client, char **notification) | |||
| 293 | char *XML_content = NULL; | 293 | char *XML_content = NULL; |
| 294 | plist_t dict = NULL; | 294 | plist_t dict = NULL; |
| 295 | 295 | ||
| 296 | if (!client || client->sfd < 0 || *notification) | 296 | if (!client || !client->connection || *notification) |
| 297 | return -1; | 297 | return -1; |
| 298 | 298 | ||
| 299 | np_lock(client); | 299 | np_lock(client); |
| 300 | 300 | ||
| 301 | usbmuxd_recv_timeout(client->sfd, (char*)&pktlen, sizeof(pktlen), &bytes, 500); | 301 | iphone_device_recv_timeout(client->connection, (char*)&pktlen, sizeof(pktlen), &bytes, 500); |
| 302 | log_debug_msg("NotificationProxy: initial read=%i\n", bytes); | 302 | log_debug_msg("NotificationProxy: initial read=%i\n", bytes); |
| 303 | if (bytes < 4) { | 303 | if (bytes < 4) { |
| 304 | log_debug_msg("NotificationProxy: no notification received!\n"); | 304 | log_debug_msg("NotificationProxy: no notification received!\n"); |
| @@ -310,7 +310,7 @@ static int np_get_notification(np_client_t client, char **notification) | |||
| 310 | XML_content = (char*)malloc(pktlen); | 310 | XML_content = (char*)malloc(pktlen); |
| 311 | log_debug_msg("pointer %p\n", XML_content); | 311 | log_debug_msg("pointer %p\n", XML_content); |
| 312 | 312 | ||
| 313 | usbmuxd_recv_timeout(client->sfd, XML_content, pktlen, &bytes, 1000); | 313 | iphone_device_recv_timeout(client->connection, XML_content, pktlen, &bytes, 1000); |
| 314 | if (bytes <= 0) { | 314 | if (bytes <= 0) { |
| 315 | res = -1; | 315 | res = -1; |
| 316 | } else { | 316 | } else { |
| @@ -390,7 +390,7 @@ gpointer np_notifier( gpointer arg ) | |||
| 390 | if (!npt) return NULL; | 390 | if (!npt) return NULL; |
| 391 | 391 | ||
| 392 | log_debug_msg("%s: starting callback.\n", __func__); | 392 | log_debug_msg("%s: starting callback.\n", __func__); |
| 393 | while (npt->client->sfd >= 0) { | 393 | while (npt->client->connection) { |
| 394 | np_get_notification(npt->client, ¬ification); | 394 | np_get_notification(npt->client, ¬ification); |
| 395 | if (notification) { | 395 | if (notification) { |
| 396 | npt->cbfunc(notification); | 396 | npt->cbfunc(notification); |
| @@ -429,11 +429,11 @@ np_error_t np_set_notify_callback( np_client_t client, np_notify_cb_t notify_cb | |||
| 429 | np_lock(client); | 429 | np_lock(client); |
| 430 | if (client->notifier) { | 430 | if (client->notifier) { |
| 431 | log_debug_msg("%s: callback already set, removing\n"); | 431 | log_debug_msg("%s: callback already set, removing\n"); |
| 432 | int conn = client->sfd; | 432 | iphone_connection_t conn = client->connection; |
| 433 | client->sfd = -1; | 433 | client->connection = NULL; |
| 434 | g_thread_join(client->notifier); | 434 | g_thread_join(client->notifier); |
| 435 | client->notifier = NULL; | 435 | client->notifier = NULL; |
| 436 | client->sfd = conn; | 436 | client->connection = conn; |
| 437 | } | 437 | } |
| 438 | 438 | ||
| 439 | if (notify_cb) { | 439 | if (notify_cb) { |
diff --git a/src/NotificationProxy.h b/src/NotificationProxy.h index bc5be43..84f1f89 100644 --- a/src/NotificationProxy.h +++ b/src/NotificationProxy.h | |||
| @@ -26,7 +26,7 @@ | |||
| 26 | #include "libiphone/notification_proxy.h" | 26 | #include "libiphone/notification_proxy.h" |
| 27 | 27 | ||
| 28 | struct np_client_int { | 28 | struct np_client_int { |
| 29 | int sfd; | 29 | iphone_connection_t connection; |
| 30 | GMutex *mutex; | 30 | GMutex *mutex; |
| 31 | GThread *notifier; | 31 | GThread *notifier; |
| 32 | }; | 32 | }; |
diff --git a/src/iphone.c b/src/iphone.c index e694373..586b3bc 100644 --- a/src/iphone.c +++ b/src/iphone.c | |||
| @@ -1,8 +1,9 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * iphone.c | 2 | * iphone.c |
| 3 | * Functions for creating and initializing iPhone structures. | 3 | * Device discovery and communication interface. |
| 4 | * | 4 | * |
| 5 | * Copyright (c) 2008 Zach C. All Rights Reserved. | 5 | * Copyright (c) 2008 Zach C. All Rights Reserved. |
| 6 | * Copyright (c) 2009 Nikias Bassen. All Rights Reserved. | ||
| 6 | * | 7 | * |
| 7 | * This library is free software; you can redistribute it and/or | 8 | * This library is free software; you can redistribute it and/or |
| 8 | * modify it under the terms of the GNU Lesser General Public | 9 | * modify it under the terms of the GNU Lesser General Public |
| @@ -19,104 +20,161 @@ | |||
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 20 | */ | 21 | */ |
| 21 | 22 | ||
| 22 | #include <stdio.h> | ||
| 23 | #include <stdlib.h> | 23 | #include <stdlib.h> |
| 24 | #include <string.h> | 24 | #include <string.h> |
| 25 | #include <errno.h> | ||
| 25 | 26 | ||
| 27 | #include <usbmuxd.h> | ||
| 26 | #include "iphone.h" | 28 | #include "iphone.h" |
| 27 | #include "utils.h" | 29 | #include "utils.h" |
| 28 | 30 | ||
| 31 | static iphone_event_cb_t event_cb = NULL; | ||
| 32 | |||
| 33 | static void usbmux_event_cb(const usbmuxd_event_t *event, void *user_data) | ||
| 34 | { | ||
| 35 | iphone_event_t ev; | ||
| 36 | |||
| 37 | ev.event = event->event; | ||
| 38 | ev.uuid = event->device.uuid; | ||
| 39 | ev.conn_type = CONNECTION_USBMUXD; | ||
| 40 | |||
| 41 | if (event_cb) { | ||
| 42 | event_cb(&ev, user_data); | ||
| 43 | } | ||
| 44 | } | ||
| 45 | |||
| 29 | /** | 46 | /** |
| 30 | * Retrieves a list of connected devices from usbmuxd and matches their | 47 | * Register a callback function that will be called when device add/remove |
| 31 | * UUID with the given UUID. If the given UUID is NULL then the first | 48 | * events occur. |
| 32 | * device reported by usbmuxd is used. | ||
| 33 | * | 49 | * |
| 34 | * @param device Upon calling this function, a pointer to a location of type | 50 | * @param callback Callback function to call. |
| 35 | * iphone_device_t, which must have the value NULL. On return, this location | 51 | * @param user_data Application-specific data passed as parameter |
| 36 | * will be filled with a handle to the device. | 52 | * to the registered callback function. |
| 37 | * @param uuid The UUID to match. | ||
| 38 | * | 53 | * |
| 39 | * @return IPHONE_E_SUCCESS if ok, otherwise an error code. | 54 | * @return IPHONE_E_SUCCESS on success or an error value when an error occured. |
| 40 | */ | 55 | */ |
| 41 | iphone_error_t iphone_get_device_by_uuid(iphone_device_t * device, const char *uuid) | 56 | iphone_error_t iphone_event_subscribe(iphone_event_cb_t callback, void *user_data) |
| 42 | { | 57 | { |
| 43 | iphone_device_t phone; | 58 | event_cb = callback; |
| 44 | uint32_t handle = 0; | 59 | int res = usbmuxd_subscribe(usbmux_event_cb, user_data); |
| 45 | char *serial_number = malloc(41); | 60 | if (res != 0) { |
| 46 | usbmuxd_scan_result *dev_list = NULL; | 61 | event_cb = NULL; |
| 47 | int i; | 62 | log_debug_msg("%s: Error %d when subscribing usbmux event callback!\n", __func__, res); |
| 48 | 63 | return IPHONE_E_UNKNOWN_ERROR; | |
| 49 | if (usbmuxd_scan(&dev_list) < 0) { | ||
| 50 | log_debug_msg("%s: usbmuxd_scan returned an error, is usbmuxd running?\n", __func__); | ||
| 51 | } | ||
| 52 | if (dev_list && dev_list[0].handle > 0) { | ||
| 53 | if (!uuid) { | ||
| 54 | /* select first device found if no UUID specified */ | ||
| 55 | handle = dev_list[0].handle; | ||
| 56 | strcpy(serial_number, dev_list[0].serial_number); | ||
| 57 | } else { | ||
| 58 | /* otherwise walk through the list */ | ||
| 59 | for (i = 0; dev_list[i].handle > 0; i++) { | ||
| 60 | log_debug_msg("%s: device handle=%d, uuid=%s\n", __func__, dev_list[i].handle, dev_list[i].serial_number); | ||
| 61 | if (strcasecmp(uuid, dev_list[i].serial_number) == 0) { | ||
| 62 | handle = dev_list[i].handle; | ||
| 63 | strcpy(serial_number, dev_list[i].serial_number); | ||
| 64 | break; | ||
| 65 | } | ||
| 66 | } | ||
| 67 | } | ||
| 68 | free(dev_list); | ||
| 69 | |||
| 70 | if (handle > 0) { | ||
| 71 | phone = (iphone_device_t) malloc(sizeof(struct iphone_device_int)); | ||
| 72 | phone->handle = handle; | ||
| 73 | phone->serial_number = serial_number; | ||
| 74 | *device = phone; | ||
| 75 | return IPHONE_E_SUCCESS; | ||
| 76 | } | ||
| 77 | } | 64 | } |
| 65 | return IPHONE_E_SUCCESS; | ||
| 66 | } | ||
| 78 | 67 | ||
| 79 | return IPHONE_E_NO_DEVICE; | 68 | /** |
| 69 | * Release the event callback function that has been registered with | ||
| 70 | * iphone_event_subscribe(). | ||
| 71 | * | ||
| 72 | * @return IPHONE_E_SUCCESS on success or an error value when an error occured. | ||
| 73 | */ | ||
| 74 | iphone_error_t iphone_event_unsubscribe() | ||
| 75 | { | ||
| 76 | event_cb = NULL; | ||
| 77 | int res = usbmuxd_unsubscribe(); | ||
| 78 | if (res != 0) { | ||
| 79 | log_debug_msg("%s: Error %d when unsubscribing usbmux event callback!\n", __func__, res); | ||
| 80 | return IPHONE_E_UNKNOWN_ERROR; | ||
| 81 | } | ||
| 82 | return IPHONE_E_SUCCESS; | ||
| 80 | } | 83 | } |
| 81 | 84 | ||
| 82 | /** | 85 | /** |
| 83 | * This function has the purpose to retrieve a handle to the first | 86 | * Get a list of currently available devices. |
| 84 | * attached iPhone/iPod reported by usbmuxd. | ||
| 85 | * | 87 | * |
| 86 | * @param Upon calling this function, a pointer to a location of type | 88 | * @param devices List of uuids of devices that are currently available. |
| 87 | * iphone_device_t, which must have the value NULL. On return, this location | 89 | * This list is terminated by a NULL pointer. |
| 88 | * will be filled with a handle to the device. | 90 | * @param count Number of devices found. |
| 89 | * | 91 | * |
| 90 | * @return IPHONE_E_SUCCESS if ok, otherwise an error code. | 92 | * @return IPHONE_E_SUCCESS on success or an error value when an error occured. |
| 91 | */ | 93 | */ |
| 92 | iphone_error_t iphone_get_device(iphone_device_t * device) | 94 | iphone_error_t iphone_get_device_list(char ***devices, int *count) |
| 93 | { | 95 | { |
| 94 | return iphone_get_device_by_uuid(device, NULL); | 96 | usbmuxd_device_info_t *dev_list; |
| 97 | |||
| 98 | *devices = NULL; | ||
| 99 | *count = 0; | ||
| 100 | |||
| 101 | if (usbmuxd_get_device_list(&dev_list) < 0) { | ||
| 102 | log_debug_msg("%s: ERROR: usbmuxd is not running!\n", __func__); | ||
| 103 | return IPHONE_E_NO_DEVICE; | ||
| 104 | } | ||
| 105 | |||
| 106 | char **newlist = NULL; | ||
| 107 | int i, newcount = 0; | ||
| 108 | |||
| 109 | for (i = 0; dev_list[i].handle > 0; i++) { | ||
| 110 | newlist = realloc(*devices, sizeof(char*) * (newcount+1)); | ||
| 111 | newlist[newcount++] = strdup(dev_list[i].uuid); | ||
| 112 | *devices = newlist; | ||
| 113 | } | ||
| 114 | usbmuxd_device_list_free(&dev_list); | ||
| 115 | |||
| 116 | *count = newcount; | ||
| 117 | newlist = realloc(*devices, sizeof(char*) * (newcount+1)); | ||
| 118 | newlist[newcount] = NULL; | ||
| 119 | *devices = newlist; | ||
| 120 | |||
| 121 | return IPHONE_E_SUCCESS; | ||
| 95 | } | 122 | } |
| 96 | 123 | ||
| 97 | iphone_error_t iphone_device_get_handle(iphone_device_t device, uint32_t *handle) | 124 | /** |
| 125 | * Free a list of device uuids. | ||
| 126 | * | ||
| 127 | * @param devices List of uuids to free. | ||
| 128 | * | ||
| 129 | * @return Always returnes IPHONE_E_SUCCESS. | ||
| 130 | */ | ||
| 131 | iphone_error_t iphone_device_list_free(char **devices) | ||
| 98 | { | 132 | { |
| 99 | if (!device) | 133 | if (devices) { |
| 100 | return IPHONE_E_INVALID_ARG; | 134 | int i = 0; |
| 101 | 135 | while (devices[i++]) { | |
| 102 | *handle = device->handle; | 136 | free(devices[i]); |
| 137 | } | ||
| 138 | free(devices); | ||
| 139 | } | ||
| 103 | return IPHONE_E_SUCCESS; | 140 | return IPHONE_E_SUCCESS; |
| 104 | } | 141 | } |
| 105 | 142 | ||
| 106 | iphone_error_t iphone_device_get_uuid(iphone_device_t device, char **uuid) | 143 | /** |
| 144 | * Creates an iphone_device_t structure for the device specified by uuid, | ||
| 145 | * if the device is available. | ||
| 146 | * | ||
| 147 | * @note The resulting iphone_device_t structure has to be freed with | ||
| 148 | * iphone_device_free() if it is no longer used. | ||
| 149 | * | ||
| 150 | * @param device Upon calling this function, a pointer to a location of type | ||
| 151 | * iphone_device_t. On successful return, this location will be populated. | ||
| 152 | * @param uuid The UUID to match. | ||
| 153 | * | ||
| 154 | * @return IPHONE_E_SUCCESS if ok, otherwise an error code. | ||
| 155 | */ | ||
| 156 | iphone_error_t iphone_device_new(iphone_device_t * device, const char *uuid) | ||
| 107 | { | 157 | { |
| 108 | if (!device) | 158 | usbmuxd_device_info_t muxdev; |
| 109 | return IPHONE_E_INVALID_ARG; | 159 | int res = usbmuxd_get_device_by_uuid(uuid, &muxdev); |
| 160 | if (res > 0) { | ||
| 161 | iphone_device_t phone = (iphone_device_t) malloc(sizeof(struct iphone_device_int)); | ||
| 162 | phone->uuid = strdup(muxdev.uuid); | ||
| 163 | phone->conn_type = CONNECTION_USBMUXD; | ||
| 164 | phone->conn_data = (void*)muxdev.handle; | ||
| 165 | *device = phone; | ||
| 166 | return IPHONE_E_SUCCESS; | ||
| 167 | } | ||
| 168 | /* other connection types could follow here */ | ||
| 110 | 169 | ||
| 111 | *uuid = strdup(device->serial_number); | 170 | return IPHONE_E_NO_DEVICE; |
| 112 | return IPHONE_E_SUCCESS; | ||
| 113 | } | 171 | } |
| 114 | 172 | ||
| 115 | /** Cleans up an iPhone structure, then frees the structure itself. | 173 | /** Cleans up an iPhone structure, then frees the structure itself. |
| 116 | * This is a library-level function; deals directly with the iPhone to tear | 174 | * This is a library-level function; deals directly with the iPhone to tear |
| 117 | * down relations, but otherwise is mostly internal. | 175 | * down relations, but otherwise is mostly internal. |
| 118 | * | 176 | * |
| 119 | * @param phone A pointer to an iPhone structure. | 177 | * @param device A pointer to an iPhone structure. |
| 120 | */ | 178 | */ |
| 121 | iphone_error_t iphone_device_free(iphone_device_t device) | 179 | iphone_error_t iphone_device_free(iphone_device_t device) |
| 122 | { | 180 | { |
| @@ -126,8 +184,192 @@ iphone_error_t iphone_device_free(iphone_device_t device) | |||
| 126 | 184 | ||
| 127 | ret = IPHONE_E_SUCCESS; | 185 | ret = IPHONE_E_SUCCESS; |
| 128 | 186 | ||
| 129 | free(device->serial_number); | 187 | free(device->uuid); |
| 188 | |||
| 189 | if (device->conn_type == CONNECTION_USBMUXD) { | ||
| 190 | device->conn_data = 0; | ||
| 191 | } | ||
| 192 | if (device->conn_data) { | ||
| 193 | free(device->conn_data); | ||
| 194 | } | ||
| 130 | free(device); | 195 | free(device); |
| 131 | return ret; | 196 | return ret; |
| 132 | } | 197 | } |
| 133 | 198 | ||
| 199 | /** | ||
| 200 | * Set up a connection to the given device. | ||
| 201 | * | ||
| 202 | * @param device The device to connect to. | ||
| 203 | * @param dst_port The destination port to connect to. | ||
| 204 | * @param connection Pointer to an iphone_connection_t that will be filled | ||
| 205 | * with the necessary data of the connection. | ||
| 206 | * | ||
| 207 | * @return IPHONE_E_SUCCESS if ok, otherwise an error code. | ||
| 208 | */ | ||
| 209 | iphone_error_t iphone_device_connect(iphone_device_t device, uint16_t dst_port, iphone_connection_t *connection) | ||
| 210 | { | ||
| 211 | if (!device) { | ||
| 212 | return IPHONE_E_INVALID_ARG; | ||
| 213 | } | ||
| 214 | |||
| 215 | if (device->conn_type == CONNECTION_USBMUXD) { | ||
| 216 | int sfd = usbmuxd_connect((uint32_t)(device->conn_data), dst_port); | ||
| 217 | if (sfd < 0) { | ||
| 218 | log_debug_msg("%s: ERROR: Connecting to usbmuxd failed: %d (%s)\n", __func__, sfd, strerror(-sfd)); | ||
| 219 | return IPHONE_E_UNKNOWN_ERROR; | ||
| 220 | } | ||
| 221 | iphone_connection_t new_connection = (iphone_connection_t)malloc(sizeof(struct iphone_connection_int)); | ||
| 222 | new_connection->type = CONNECTION_USBMUXD; | ||
| 223 | new_connection->data = (void*)sfd; | ||
| 224 | *connection = new_connection; | ||
| 225 | return IPHONE_E_SUCCESS; | ||
| 226 | } else { | ||
| 227 | log_debug_msg("%s: Unknown connection type %d\n", __func__, device->conn_type); | ||
| 228 | } | ||
| 229 | |||
| 230 | return IPHONE_E_UNKNOWN_ERROR; | ||
| 231 | } | ||
| 232 | |||
| 233 | /** | ||
| 234 | * Disconnect from the device and clean up the connection structure. | ||
| 235 | * | ||
| 236 | * @param connection The connection to close. | ||
| 237 | * | ||
| 238 | * @return IPHONE_E_SUCCESS if ok, otherwise an error code. | ||
| 239 | */ | ||
| 240 | iphone_error_t iphone_device_disconnect(iphone_connection_t connection) | ||
| 241 | { | ||
| 242 | if (!connection) { | ||
| 243 | return IPHONE_E_INVALID_ARG; | ||
| 244 | } | ||
| 245 | iphone_error_t result = IPHONE_E_UNKNOWN_ERROR; | ||
| 246 | if (connection->type == CONNECTION_USBMUXD) { | ||
| 247 | usbmuxd_disconnect((int)(connection->data)); | ||
| 248 | result = IPHONE_E_SUCCESS; | ||
| 249 | } else { | ||
| 250 | log_debug_msg("%s: Unknown connection type %d\n", __func__, connection->type); | ||
| 251 | } | ||
| 252 | free(connection); | ||
| 253 | return result; | ||
| 254 | } | ||
| 255 | |||
| 256 | /** | ||
| 257 | * Send data to a device via the given connection. | ||
| 258 | * | ||
| 259 | * @param connection The connection to send data over. | ||
| 260 | * @param data Buffer with data to send. | ||
| 261 | * @param len Size of the buffer to send. | ||
| 262 | * @param sent_bytes Pointer to an uint32_t that will be filled | ||
| 263 | * with the number of bytes actually sent. | ||
| 264 | * | ||
| 265 | * @return IPHONE_E_SUCCESS if ok, otherwise an error code. | ||
| 266 | */ | ||
| 267 | iphone_error_t iphone_device_send(iphone_connection_t connection, const char *data, uint32_t len, uint32_t *sent_bytes) | ||
| 268 | { | ||
| 269 | if (!connection || !data) { | ||
| 270 | return IPHONE_E_INVALID_ARG; | ||
| 271 | } | ||
| 272 | |||
| 273 | if (connection->type == CONNECTION_USBMUXD) { | ||
| 274 | int res = usbmuxd_send((int)(connection->data), data, len, sent_bytes); | ||
| 275 | if (res < 0) { | ||
| 276 | log_debug_msg("%s: ERROR: usbmuxd_send returned %d (%s)\n", __func__, res, strerror(-res)); | ||
| 277 | return IPHONE_E_UNKNOWN_ERROR; | ||
| 278 | } | ||
| 279 | return IPHONE_E_SUCCESS; | ||
| 280 | } else { | ||
| 281 | log_debug_msg("%s: Unknown connection type %d\n", __func__, connection->type); | ||
| 282 | } | ||
| 283 | return IPHONE_E_UNKNOWN_ERROR; | ||
| 284 | } | ||
| 285 | |||
| 286 | /** | ||
| 287 | * Receive data from a device via the given connection. | ||
| 288 | * This function will return after the given timeout even if no data has been | ||
| 289 | * received. | ||
| 290 | * | ||
| 291 | * @param connection The connection to receive data from. | ||
| 292 | * @param data Buffer that will be filled with the received data. | ||
| 293 | * This buffer has to be large enough to hold len bytes. | ||
| 294 | * @param len Buffer size or number of bytes to receive. | ||
| 295 | * @param recv_bytes Number of bytes actually received. | ||
| 296 | * @param timeout Timeout in milliseconds after which this function should | ||
| 297 | * return even if no data has been received. | ||
| 298 | * | ||
| 299 | * @return IPHONE_E_SUCCESS if ok, otherwise an error code. | ||
| 300 | */ | ||
| 301 | iphone_error_t iphone_device_recv_timeout(iphone_connection_t connection, char *data, uint32_t len, uint32_t *recv_bytes, unsigned int timeout) | ||
| 302 | { | ||
| 303 | if (!connection) { | ||
| 304 | return IPHONE_E_INVALID_ARG; | ||
| 305 | } | ||
| 306 | |||
| 307 | if (connection->type == CONNECTION_USBMUXD) { | ||
| 308 | int res = usbmuxd_recv_timeout((int)(connection->data), data, len, recv_bytes, timeout); | ||
| 309 | if (res < 0) { | ||
| 310 | log_debug_msg("%s: ERROR: usbmuxd_recv_timeout returned %d (%s)\n", __func__, res, strerror(-res)); | ||
| 311 | return IPHONE_E_UNKNOWN_ERROR; | ||
| 312 | } | ||
| 313 | return IPHONE_E_SUCCESS; | ||
| 314 | } else { | ||
| 315 | log_debug_msg("%s: Unknown connection type %d\n", __func__, connection->type); | ||
| 316 | } | ||
| 317 | return IPHONE_E_UNKNOWN_ERROR; | ||
| 318 | } | ||
| 319 | |||
| 320 | /** | ||
| 321 | * Receive data from a device via the given connection. | ||
| 322 | * This function is like iphone_device_recv_timeout, but with a predefined | ||
| 323 | * reasonable timeout. | ||
| 324 | * | ||
| 325 | * @param connection The connection to receive data from. | ||
| 326 | * @param data Buffer that will be filled with the received data. | ||
| 327 | * This buffer has to be large enough to hold len bytes. | ||
| 328 | * @param len Buffer size or number of bytes to receive. | ||
| 329 | * @param recv_bytes Number of bytes actually received. | ||
| 330 | * | ||
| 331 | * @return IPHONE_E_SUCCESS if ok, otherwise an error code. | ||
| 332 | */ | ||
| 333 | iphone_error_t iphone_device_recv(iphone_connection_t connection, char *data, uint32_t len, uint32_t *recv_bytes) | ||
| 334 | { | ||
| 335 | if (!connection) { | ||
| 336 | return -EINVAL; | ||
| 337 | } | ||
| 338 | |||
| 339 | if (connection->type == CONNECTION_USBMUXD) { | ||
| 340 | int res = usbmuxd_recv((int)(connection->data), data, len, recv_bytes); | ||
| 341 | if (res < 0) { | ||
| 342 | log_debug_msg("%s: ERROR: usbmuxd_recv returned %d (%s)\n", __func__, res, strerror(-res)); | ||
| 343 | return IPHONE_E_UNKNOWN_ERROR; | ||
| 344 | } | ||
| 345 | |||
| 346 | return IPHONE_E_SUCCESS; | ||
| 347 | } else { | ||
| 348 | log_debug_msg("%s: Unknown connection type %d\n", __func__, connection->type); | ||
| 349 | } | ||
| 350 | return IPHONE_E_UNKNOWN_ERROR; | ||
| 351 | } | ||
| 352 | |||
| 353 | iphone_error_t iphone_device_get_handle(iphone_device_t device, uint32_t *handle) | ||
| 354 | { | ||
| 355 | if (!device) | ||
| 356 | return IPHONE_E_INVALID_ARG; | ||
| 357 | |||
| 358 | if (device->conn_type == CONNECTION_USBMUXD) { | ||
| 359 | *handle = (uint32_t)device->conn_data; | ||
| 360 | return IPHONE_E_SUCCESS; | ||
| 361 | } else { | ||
| 362 | log_debug_msg("%s: Unknown connection type %d\n", __func__, device->conn_type); | ||
| 363 | } | ||
| 364 | return IPHONE_E_UNKNOWN_ERROR; | ||
| 365 | } | ||
| 366 | |||
| 367 | iphone_error_t iphone_device_get_uuid(iphone_device_t device, char **uuid) | ||
| 368 | { | ||
| 369 | if (!device) | ||
| 370 | return IPHONE_E_INVALID_ARG; | ||
| 371 | |||
| 372 | *uuid = strdup(device->uuid); | ||
| 373 | return IPHONE_E_SUCCESS; | ||
| 374 | } | ||
| 375 | |||
diff --git a/src/iphone.h b/src/iphone.h index 6e14280..98b0ed8 100644 --- a/src/iphone.h +++ b/src/iphone.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * iphone.h | 2 | * iphone.h |
| 3 | * iPhone struct | 3 | * Device discovery and communication interface -- header file. |
| 4 | * | 4 | * |
| 5 | * Copyright (c) 2008 Zach C. All Rights Reserved. | 5 | * Copyright (c) 2008 Zach C. All Rights Reserved. |
| 6 | * | 6 | * |
| 7 | * This library is free software; you can redistribute it and/or | 7 | * This library is free software; you can redistribute it and/or |
| @@ -18,18 +18,24 @@ | |||
| 18 | * License along with this library; if not, write to the Free Software | 18 | * License along with this library; if not, write to the Free Software |
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 20 | */ | 20 | */ |
| 21 | |||
| 22 | #ifndef IPHONE_H | 21 | #ifndef IPHONE_H |
| 23 | #define IPHONE_H | 22 | #define IPHONE_H |
| 24 | 23 | ||
| 25 | #include <stdint.h> | ||
| 26 | |||
| 27 | #include "libiphone/libiphone.h" | 24 | #include "libiphone/libiphone.h" |
| 28 | 25 | ||
| 26 | enum connection_type { | ||
| 27 | CONNECTION_USBMUXD = 1 | ||
| 28 | }; | ||
| 29 | |||
| 30 | struct iphone_connection_int { | ||
| 31 | enum connection_type type; | ||
| 32 | void *data; | ||
| 33 | }; | ||
| 34 | |||
| 29 | struct iphone_device_int { | 35 | struct iphone_device_int { |
| 30 | char *buffer; | 36 | char *uuid; |
| 31 | uint32_t handle; | 37 | enum connection_type conn_type; |
| 32 | char *serial_number; | 38 | void *conn_data; |
| 33 | }; | 39 | }; |
| 34 | 40 | ||
| 35 | #endif | 41 | #endif |
diff --git a/src/lockdown.c b/src/lockdown.c index 7a2aa7d..a05b5db 100644 --- a/src/lockdown.c +++ b/src/lockdown.c | |||
| @@ -213,12 +213,14 @@ lockdownd_error_t lockdownd_client_free(lockdownd_client_t client) | |||
| 213 | 213 | ||
| 214 | lockdownd_stop_ssl_session(client); | 214 | lockdownd_stop_ssl_session(client); |
| 215 | 215 | ||
| 216 | if (client->sfd > 0) { | 216 | if (client->connection) { |
| 217 | lockdownd_goodbye(client); | 217 | lockdownd_goodbye(client); |
| 218 | 218 | ||
| 219 | // IMO, read of final "sessionUpcall connection closed" packet | 219 | // IMO, read of final "sessionUpcall connection closed" packet |
| 220 | // should come here instead of in iphone_free_device | 220 | // should come here instead of in iphone_free_device |
| 221 | ret = usbmuxd_disconnect(client->sfd); | 221 | if ((ret = iphone_device_disconnect(client->connection)) != IPHONE_E_SUCCESS) { |
| 222 | ret = LOCKDOWN_E_UNKNOWN_ERROR; | ||
| 223 | } | ||
| 222 | } | 224 | } |
| 223 | 225 | ||
| 224 | free(client); | 226 | free(client); |
| @@ -241,7 +243,7 @@ lockdownd_error_t lockdownd_recv(lockdownd_client_t client, plist_t *plist) | |||
| 241 | uint32_t datalen = 0, bytes = 0, received_bytes = 0; | 243 | uint32_t datalen = 0, bytes = 0, received_bytes = 0; |
| 242 | 244 | ||
| 243 | if (!client->in_SSL) | 245 | if (!client->in_SSL) |
| 244 | ret = usbmuxd_recv(client->sfd, (char *) &datalen, sizeof(datalen), &bytes); | 246 | ret = iphone_device_recv(client->connection, (char *) &datalen, sizeof(datalen), &bytes); |
| 245 | else { | 247 | else { |
| 246 | ssize_t res = gnutls_record_recv(*client->ssl_session, &datalen, sizeof(datalen)); | 248 | ssize_t res = gnutls_record_recv(*client->ssl_session, &datalen, sizeof(datalen)); |
| 247 | if (res < 0) { | 249 | if (res < 0) { |
| @@ -260,7 +262,7 @@ lockdownd_error_t lockdownd_recv(lockdownd_client_t client, plist_t *plist) | |||
| 260 | /* fill buffer and request more packets if needed */ | 262 | /* fill buffer and request more packets if needed */ |
| 261 | if (!client->in_SSL) { | 263 | if (!client->in_SSL) { |
| 262 | while ((received_bytes < datalen) && (ret == LOCKDOWN_E_SUCCESS)) { | 264 | while ((received_bytes < datalen) && (ret == LOCKDOWN_E_SUCCESS)) { |
| 263 | ret = usbmuxd_recv(client->sfd, receive + received_bytes, datalen - received_bytes, &bytes); | 265 | ret = iphone_device_recv(client->connection, receive + received_bytes, datalen - received_bytes, &bytes); |
| 264 | received_bytes += bytes; | 266 | received_bytes += bytes; |
| 265 | } | 267 | } |
| 266 | } else { | 268 | } else { |
| @@ -328,7 +330,7 @@ lockdownd_error_t lockdownd_send(lockdownd_client_t client, plist_t plist) | |||
| 328 | log_dbg_msg(DBGMASK_LOCKDOWND, "%s: made the query, sending it along\n", __func__); | 330 | log_dbg_msg(DBGMASK_LOCKDOWND, "%s: made the query, sending it along\n", __func__); |
| 329 | 331 | ||
| 330 | if (!client->in_SSL) | 332 | if (!client->in_SSL) |
| 331 | ret = usbmuxd_send(client->sfd, real_query, ntohl(length) + sizeof(length), (uint32_t*)&bytes); | 333 | ret = iphone_device_send(client->connection, real_query, ntohl(length) + sizeof(length), (uint32_t*)&bytes); |
| 332 | else { | 334 | else { |
| 333 | ssize_t res = gnutls_record_send(*client->ssl_session, real_query, ntohl(length) + sizeof(length)); | 335 | ssize_t res = gnutls_record_send(*client->ssl_session, real_query, ntohl(length) + sizeof(length)); |
| 334 | if (res < 0) { | 336 | if (res < 0) { |
| @@ -659,19 +661,19 @@ lockdownd_error_t lockdownd_get_device_name(lockdownd_client_t client, char **de | |||
| 659 | */ | 661 | */ |
| 660 | lockdownd_error_t lockdownd_client_new(iphone_device_t device, lockdownd_client_t *client) | 662 | lockdownd_error_t lockdownd_client_new(iphone_device_t device, lockdownd_client_t *client) |
| 661 | { | 663 | { |
| 662 | if (!device || !client) | 664 | if (!client) |
| 663 | return LOCKDOWN_E_INVALID_ARG; | 665 | return LOCKDOWN_E_INVALID_ARG; |
| 664 | lockdownd_error_t ret = LOCKDOWN_E_SUCCESS; | 666 | lockdownd_error_t ret = LOCKDOWN_E_SUCCESS; |
| 665 | char *host_id = NULL; | 667 | char *host_id = NULL; |
| 666 | 668 | ||
| 667 | int sfd = usbmuxd_connect(device->handle, 0xf27e); | 669 | iphone_connection_t connection; |
| 668 | if (sfd < 0) { | 670 | if (iphone_device_connect(device, 0xf27e, &connection) != IPHONE_E_SUCCESS) { |
| 669 | log_debug_msg("%s: could not connect to lockdownd (device handle %d)\n", __func__, device->handle); | 671 | log_debug_msg("%s: could not connect to lockdownd (device %s)\n", __func__, device->uuid); |
| 670 | return LOCKDOWN_E_MUX_ERROR; | 672 | return LOCKDOWN_E_MUX_ERROR; |
| 671 | } | 673 | } |
| 672 | 674 | ||
| 673 | lockdownd_client_t client_loc = (lockdownd_client_t) malloc(sizeof(struct lockdownd_client_int)); | 675 | lockdownd_client_t client_loc = (lockdownd_client_t) malloc(sizeof(struct lockdownd_client_int)); |
| 674 | client_loc->sfd = sfd; | 676 | client_loc->connection = connection; |
| 675 | client_loc->ssl_session = (gnutls_session_t *) malloc(sizeof(gnutls_session_t)); | 677 | client_loc->ssl_session = (gnutls_session_t *) malloc(sizeof(gnutls_session_t)); |
| 676 | client_loc->in_SSL = 0; | 678 | client_loc->in_SSL = 0; |
| 677 | 679 | ||
| @@ -1176,7 +1178,7 @@ ssize_t lockdownd_secuwrite(gnutls_transport_ptr_t transport, char *buffer, size | |||
| 1176 | client = (lockdownd_client_t) transport; | 1178 | client = (lockdownd_client_t) transport; |
| 1177 | log_dbg_msg(DBGMASK_LOCKDOWND, "%s: called\n", __func__); | 1179 | log_dbg_msg(DBGMASK_LOCKDOWND, "%s: called\n", __func__); |
| 1178 | log_dbg_msg(DBGMASK_LOCKDOWND, "%s: pre-send length = %zi\n", __func__, length); | 1180 | log_dbg_msg(DBGMASK_LOCKDOWND, "%s: pre-send length = %zi\n", __func__, length); |
| 1179 | usbmuxd_send(client->sfd, buffer, length, &bytes); | 1181 | iphone_device_send(client->connection, buffer, length, &bytes); |
| 1180 | log_dbg_msg(DBGMASK_LOCKDOWND, "%s: post-send sent %i bytes\n", __func__, bytes); | 1182 | log_dbg_msg(DBGMASK_LOCKDOWND, "%s: post-send sent %i bytes\n", __func__, bytes); |
| 1181 | return bytes; | 1183 | return bytes; |
| 1182 | } | 1184 | } |
| @@ -1205,7 +1207,7 @@ ssize_t lockdownd_securead(gnutls_transport_ptr_t transport, char *buffer, size_ | |||
| 1205 | 1207 | ||
| 1206 | // repeat until we have the full data or an error occurs. | 1208 | // repeat until we have the full data or an error occurs. |
| 1207 | do { | 1209 | do { |
| 1208 | if ((res = usbmuxd_recv(client->sfd, recv_buffer, this_len, (uint32_t*)&bytes)) != LOCKDOWN_E_SUCCESS) { | 1210 | if ((res = iphone_device_recv(client->connection, recv_buffer, this_len, (uint32_t*)&bytes)) != LOCKDOWN_E_SUCCESS) { |
| 1209 | log_debug_msg("%s: ERROR: usbmux_recv returned %d\n", __func__, res); | 1211 | log_debug_msg("%s: ERROR: usbmux_recv returned %d\n", __func__, res); |
| 1210 | return res; | 1212 | return res; |
| 1211 | } | 1213 | } |
diff --git a/src/lockdown.h b/src/lockdown.h index 1e193f6..19cf9f2 100644 --- a/src/lockdown.h +++ b/src/lockdown.h | |||
| @@ -28,7 +28,7 @@ | |||
| 28 | #include "libiphone/lockdown.h" | 28 | #include "libiphone/lockdown.h" |
| 29 | 29 | ||
| 30 | struct lockdownd_client_int { | 30 | struct lockdownd_client_int { |
| 31 | int sfd; | 31 | iphone_connection_t connection; |
| 32 | gnutls_session_t *ssl_session; | 32 | gnutls_session_t *ssl_session; |
| 33 | int in_SSL; | 33 | int in_SSL; |
| 34 | char session_id[40]; | 34 | char session_id[40]; |
diff --git a/src/userpref.c b/src/userpref.c index 9dd1a01..10c14a0 100644 --- a/src/userpref.c +++ b/src/userpref.c | |||
| @@ -88,7 +88,7 @@ static char *userpref_generate_host_id() | |||
| 88 | * | 88 | * |
| 89 | * @param host_id A null terminated string containing a valid HostID. | 89 | * @param host_id A null terminated string containing a valid HostID. |
| 90 | */ | 90 | */ |
| 91 | static int userpref_set_host_id(char *host_id) | 91 | static int userpref_set_host_id(const char *host_id) |
| 92 | { | 92 | { |
| 93 | GKeyFile *key_file; | 93 | GKeyFile *key_file; |
| 94 | gsize length; | 94 | gsize length; |
| @@ -164,7 +164,7 @@ void userpref_get_host_id(char **host_id) | |||
| 164 | * @return 1 if the iPhone has been connected previously to this configuration | 164 | * @return 1 if the iPhone has been connected previously to this configuration |
| 165 | * or 0 otherwise. | 165 | * or 0 otherwise. |
| 166 | */ | 166 | */ |
| 167 | int userpref_has_device_public_key(char *uuid) | 167 | int userpref_has_device_public_key(const char *uuid) |
| 168 | { | 168 | { |
| 169 | int ret = 0; | 169 | int ret = 0; |
| 170 | gchar *config_file; | 170 | gchar *config_file; |
| @@ -187,7 +187,7 @@ int userpref_has_device_public_key(char *uuid) | |||
| 187 | * @return 1 on success and 0 if no public key is given or if it has already | 187 | * @return 1 on success and 0 if no public key is given or if it has already |
| 188 | * been marked as connected previously. | 188 | * been marked as connected previously. |
| 189 | */ | 189 | */ |
| 190 | userpref_error_t userpref_set_device_public_key(char *uuid, gnutls_datum_t public_key) | 190 | userpref_error_t userpref_set_device_public_key(const char *uuid, gnutls_datum_t public_key) |
| 191 | { | 191 | { |
| 192 | if (NULL == public_key.data) | 192 | if (NULL == public_key.data) |
| 193 | return USERPREF_E_INVALID_ARG; | 193 | return USERPREF_E_INVALID_ARG; |
diff --git a/src/userpref.h b/src/userpref.h index 414c093..fcb8b62 100644 --- a/src/userpref.h +++ b/src/userpref.h | |||
| @@ -36,8 +36,8 @@ typedef int16_t userpref_error_t; | |||
| 36 | userpref_error_t userpref_get_keys_and_certs(gnutls_x509_privkey_t root_privkey, gnutls_x509_crt_t root_crt, gnutls_x509_privkey_t host_privkey, gnutls_x509_crt_t host_crt); | 36 | userpref_error_t userpref_get_keys_and_certs(gnutls_x509_privkey_t root_privkey, gnutls_x509_crt_t root_crt, gnutls_x509_privkey_t host_privkey, gnutls_x509_crt_t host_crt); |
| 37 | userpref_error_t userpref_set_keys_and_certs(gnutls_datum_t * root_key, gnutls_datum_t * root_cert, gnutls_datum_t * host_key, gnutls_datum_t * host_cert); | 37 | userpref_error_t userpref_set_keys_and_certs(gnutls_datum_t * root_key, gnutls_datum_t * root_cert, gnutls_datum_t * host_key, gnutls_datum_t * host_cert); |
| 38 | userpref_error_t userpref_get_certs_as_pem(gnutls_datum_t *pem_root_cert, gnutls_datum_t *pem_host_cert); | 38 | userpref_error_t userpref_get_certs_as_pem(gnutls_datum_t *pem_root_cert, gnutls_datum_t *pem_host_cert); |
| 39 | userpref_error_t userpref_set_device_public_key(char *uuid, gnutls_datum_t public_key); | 39 | userpref_error_t userpref_set_device_public_key(const char *uuid, gnutls_datum_t public_key); |
| 40 | int userpref_has_device_public_key(char *uuid); | 40 | int userpref_has_device_public_key(const char *uuid); |
| 41 | void userpref_get_host_id(char **host_id); | 41 | void userpref_get_host_id(char **host_id); |
| 42 | 42 | ||
| 43 | #endif | 43 | #endif |
