diff options
author | Nikias Bassen | 2009-05-18 22:29:39 +0200 |
---|---|---|
committer | Matt Colyer | 2009-05-18 18:47:20 -0700 |
commit | 8eaac0513bfb238edec22d46320669f5c9c76542 (patch) | |
tree | 2db842339bf525d67017525bcbd3f4d35181e5ca /src | |
parent | dca1758c4f9602fc240c6a7c9ae45839e154d15f (diff) | |
download | libimobiledevice-8eaac0513bfb238edec22d46320669f5c9c76542.tar.gz libimobiledevice-8eaac0513bfb238edec22d46320669f5c9c76542.tar.bz2 |
Make use of usbmuxd and remove libusb dependencies
Signed-off-by: Matt Colyer <matt@colyer.name>
Diffstat (limited to 'src')
-rw-r--r-- | src/AFC.c | 75 | ||||
-rw-r--r-- | src/AFC.h | 4 | ||||
-rw-r--r-- | src/Makefile.am | 7 | ||||
-rw-r--r-- | src/MobileSync.c | 25 | ||||
-rw-r--r-- | src/MobileSync.h | 3 | ||||
-rw-r--r-- | src/NotificationProxy.c | 47 | ||||
-rw-r--r-- | src/NotificationProxy.h | 3 | ||||
-rw-r--r-- | src/iphone.c | 295 | ||||
-rw-r--r-- | src/iphone.h | 17 | ||||
-rw-r--r-- | src/lockdown.c | 25 | ||||
-rw-r--r-- | src/lockdown.h | 4 | ||||
-rw-r--r-- | src/usbmux.c | 410 | ||||
-rw-r--r-- | src/usbmux.h | 58 |
13 files changed, 148 insertions, 825 deletions
@@ -20,7 +20,9 @@ */ #include <stdio.h> +#include <stdlib.h> #include <errno.h> +#include <unistd.h> #include "AFC.h" #include "utils.h" @@ -61,29 +63,28 @@ static void afc_unlock(iphone_afc_client_t client) * * @return A handle to the newly-connected client or NULL upon error. */ -iphone_error_t iphone_afc_new_client(iphone_device_t device, int src_port, int dst_port, iphone_afc_client_t * client) +iphone_error_t iphone_afc_new_client(iphone_device_t device, int dst_port, iphone_afc_client_t * client) { - int ret = IPHONE_E_SUCCESS; - //makes sure thread environment is available if (!g_thread_supported()) g_thread_init(NULL); - iphone_afc_client_t client_loc = (iphone_afc_client_t) malloc(sizeof(struct iphone_afc_client_int)); if (!device) return IPHONE_E_INVALID_ARG; // Attempt connection - client_loc->connection = NULL; - ret = iphone_mux_new_client(device, src_port, dst_port, &client_loc->connection); - if (IPHONE_E_SUCCESS != ret || !client_loc->connection) { - free(client_loc); - return ret; + int sfd = usbmuxd_connect(device->handle, dst_port); + if (sfd < 0) { + return IPHONE_E_UNKNOWN_ERROR; // ret; } + + iphone_afc_client_t client_loc = (iphone_afc_client_t) malloc(sizeof(struct iphone_afc_client_int)); + client_loc->sfd = sfd; + // Allocate a packet client_loc->afc_packet = (AFCPacket *) malloc(sizeof(AFCPacket)); if (!client_loc->afc_packet) { - iphone_mux_free_client(client_loc->connection); + usbmuxd_disconnect(client_loc->sfd); free(client_loc); return IPHONE_E_UNKNOWN_ERROR; } @@ -106,10 +107,10 @@ iphone_error_t iphone_afc_new_client(iphone_device_t device, int src_port, int d */ iphone_error_t iphone_afc_free_client(iphone_afc_client_t client) { - if (!client || !client->connection || !client->afc_packet) + if (!client || client->sfd < 0 || !client->afc_packet) return IPHONE_E_INVALID_ARG; - iphone_mux_free_client(client->connection); + usbmuxd_disconnect(client->sfd); free(client->afc_packet); if (client->mutex) { g_mutex_free(client->mutex); @@ -217,7 +218,7 @@ static int dispatch_AFC_packet(iphone_afc_client_t client, const char *data, int int bytes = 0, offset = 0; char *buffer; - if (!client || !client->connection || !client->afc_packet) + if (!client || client->sfd < 0 || !client->afc_packet) return 0; if (!data || !length) length = 0; @@ -248,7 +249,7 @@ static int dispatch_AFC_packet(iphone_afc_client_t client, const char *data, int return -1; } memcpy(buffer + sizeof(AFCPacket), data, offset); - iphone_mux_send(client->connection, buffer, client->afc_packet->this_length, (uint32_t*)&bytes); + usbmuxd_send(client->sfd, buffer, client->afc_packet->this_length, (uint32_t*)&bytes); free(buffer); if (bytes <= 0) { return bytes; @@ -259,7 +260,7 @@ static int dispatch_AFC_packet(iphone_afc_client_t client, const char *data, int log_debug_msg("Buffer: \n"); log_debug_buffer(data + offset, length - offset); - iphone_mux_send(client->connection, data + offset, length - offset, (uint32_t*)&bytes); + usbmuxd_send(client->sfd, data + offset, length - offset, (uint32_t*)&bytes); return bytes; } else { log_debug_msg("dispatch_AFC_packet doin things the old way\n"); @@ -273,7 +274,7 @@ static int dispatch_AFC_packet(iphone_afc_client_t client, const char *data, int } log_debug_buffer(buffer, client->afc_packet->this_length); log_debug_msg("\n"); - iphone_mux_send(client->connection, buffer, client->afc_packet->this_length, (uint32_t*)&bytes); + usbmuxd_send(client->sfd, buffer, client->afc_packet->this_length, (uint32_t*)&bytes); if (buffer) { free(buffer); @@ -307,7 +308,7 @@ static int receive_AFC_data(iphone_afc_client_t client, char **dump_here) client->afcerror = 0; // first, read the AFC header - iphone_mux_recv(client->connection, (char*)&header, sizeof(AFCPacket), (uint32_t*)&bytes); + usbmuxd_recv(client->sfd, (char*)&header, sizeof(AFCPacket), (uint32_t*)&bytes); if (bytes <= 0) { log_debug_msg("%s: Just didn't get enough.\n", __func__); *dump_here = NULL; @@ -359,24 +360,26 @@ static int receive_AFC_data(iphone_afc_client_t client, char **dump_here) } *dump_here = (char*)malloc(entire_len); - iphone_mux_recv(client->connection, *dump_here, this_len, (uint32_t*)&bytes); - if (bytes <= 0) { - free(*dump_here); - *dump_here = NULL; - log_debug_msg("%s: Did not get packet contents!\n", __func__); - return -1; - } else if ((uint32_t)bytes < this_len) { - free(*dump_here); - *dump_here = NULL; - log_debug_msg("%s: Could not receive this_len=%d bytes\n", __func__, this_len); - return -1; + if (this_len > 0) { + usbmuxd_recv(client->sfd, *dump_here, this_len, (uint32_t*)&bytes); + if (bytes <= 0) { + free(*dump_here); + *dump_here = NULL; + log_debug_msg("%s: Did not get packet contents!\n", __func__); + return -1; + } else if ((uint32_t)bytes < this_len) { + free(*dump_here); + *dump_here = NULL; + log_debug_msg("%s: Could not receive this_len=%d bytes\n", __func__, this_len); + return -1; + } } current_count = this_len; if (entire_len > this_len) { while (current_count < entire_len) { - iphone_mux_recv(client->connection, (*dump_here)+current_count, entire_len - current_count, (uint32_t*)&bytes); + usbmuxd_recv(client->sfd, (*dump_here)+current_count, entire_len - current_count, (uint32_t*)&bytes); if (bytes <= 0) { log_debug_msg("%s: Error receiving data (recv returned %d)\n", __func__, bytes); break; @@ -559,7 +562,7 @@ iphone_error_t iphone_afc_delete_file(iphone_afc_client_t client, const char *pa char *response = NULL; int bytes; - if (!client || !path || !client->afc_packet || !client->connection) + if (!client || !path || !client->afc_packet || client->sfd < 0) return IPHONE_E_INVALID_ARG; afc_lock(client); @@ -600,7 +603,7 @@ iphone_error_t iphone_afc_rename_file(iphone_afc_client_t client, const char *fr char *send = (char *) malloc(sizeof(char) * (strlen(from) + strlen(to) + 1 + sizeof(uint32_t))); int bytes = 0; - if (!client || !from || !to || !client->afc_packet || !client->connection) + if (!client || !from || !to || !client->afc_packet || client->sfd < 0) return IPHONE_E_INVALID_ARG; afc_lock(client); @@ -748,7 +751,7 @@ iphone_error_t iphone_afc_get_file_attr(iphone_afc_client_t client, const char * { iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; - if (!client || !client->connection || !client->afc_packet || !stbuf) + if (!client || client->sfd < 0 || !client->afc_packet || !stbuf) return IPHONE_E_INVALID_ARG; memset(stbuf, 0, sizeof(struct stat)); @@ -793,7 +796,7 @@ iphone_afc_open_file(iphone_afc_client_t client, const char *filename, int bytes = 0, length = 0; char *data = (char *) malloc(sizeof(char) * (8 + strlen(filename) + 1)); - if (!client || !client->connection || !client->afc_packet) + if (!client || client->sfd < 0|| !client->afc_packet) return IPHONE_E_INVALID_ARG; afc_lock(client); @@ -851,7 +854,7 @@ iphone_afc_read_file(iphone_afc_client_t client, iphone_afc_file_t file, char *d int current_count = 0, bytes_loc = 0; const int MAXIMUM_READ_SIZE = 1 << 16; - if (!client || !client->afc_packet || !client->connection || !file) + if (!client || !client->afc_packet || client->sfd < 0 || !file) return IPHONE_E_INVALID_ARG; log_debug_msg("afc_read_file called for length %i\n", length); @@ -926,7 +929,7 @@ iphone_afc_write_file(iphone_afc_client_t client, iphone_afc_file_t file, int bytes_loc = 0; char *out_buffer = NULL; - if (!client || !client->afc_packet || !client->connection || !file || !bytes) + if (!client || !client->afc_packet || client->sfd < 0 || !file || !bytes) return IPHONE_E_INVALID_ARG; afc_lock(client); @@ -1219,7 +1222,7 @@ iphone_error_t iphone_afc_truncate(iphone_afc_client_t client, const char *path, int bytes = 0; uint64_t size_requested = newsize; - if (!client || !path || !client->afc_packet || !client->connection) + if (!client || !path || !client->afc_packet || client->sfd < 0) return IPHONE_E_INVALID_ARG; afc_lock(client); @@ -19,7 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "usbmux.h" +#include "libiphone/libiphone.h" #include "iphone.h" #include <string.h> @@ -47,7 +47,7 @@ typedef struct __AFCToken { } AFCToken; struct iphone_afc_client_int { - iphone_umux_client_t connection; + int sfd; AFCPacket *afc_packet; int file_handle; int lock; diff --git a/src/Makefile.am b/src/Makefile.am index 2ae1943..5489684 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,11 +1,10 @@ INCLUDES = -I$(top_srcdir)/include -AM_CFLAGS = $(GLOBAL_CFLAGS) $(libusb_CFLAGS) $(libglib2_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libgthread2_CFLAGS) $(libplist_CFLAGS) $(LFS_CFLAGS) -AM_LDFLAGS = $(libusb_LIBS) $(libglib2_LIBS) $(libgnutls_LIBS) $(libtasn1_LIBS) $(libgthread2_LIBS) $(libplist_LIBS) +AM_CFLAGS = $(GLOBAL_CFLAGS) $(libusbmuxd_CFLAGS) $(libglib2_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libgthread2_CFLAGS) $(libplist_CFLAGS) $(LFS_CFLAGS) +AM_LDFLAGS = $(libglib2_LIBS) $(libgnutls_LIBS) $(libtasn1_LIBS) $(libgthread2_LIBS) $(libplist_LIBS) $(libusbmuxd_LIBS) lib_LTLIBRARIES = libiphone.la -libiphone_la_SOURCES = usbmux.c usbmux.h \ - iphone.c iphone.h \ +libiphone_la_SOURCES = iphone.c iphone.h \ lockdown.c lockdown.h\ AFC.c AFC.h\ NotificationProxy.c NotificationProxy.h\ diff --git a/src/MobileSync.c b/src/MobileSync.c index 58d0beb..7d6e947 100644 --- a/src/MobileSync.c +++ b/src/MobileSync.c @@ -22,29 +22,30 @@ #include "MobileSync.h" #include <plist/plist.h> #include <string.h> +#include <stdlib.h> #include <arpa/inet.h> #define MSYNC_VERSION_INT1 100 #define MSYNC_VERSION_INT2 100 -iphone_error_t iphone_msync_new_client(iphone_device_t device, int src_port, int dst_port, +iphone_error_t iphone_msync_new_client(iphone_device_t device, int dst_port, iphone_msync_client_t * client) { - if (!device || src_port == 0 || dst_port == 0 || !client || *client) + if (!device || dst_port == 0 || !client || *client) return IPHONE_E_INVALID_ARG; iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; - iphone_msync_client_t client_loc = (iphone_msync_client_t) malloc(sizeof(struct iphone_msync_client_int)); - // Attempt connection - client_loc->connection = NULL; - ret = iphone_mux_new_client(device, src_port, dst_port, &client_loc->connection); - if (IPHONE_E_SUCCESS != ret || !client_loc->connection) { - free(client_loc); + int sfd = usbmuxd_connect(device->handle, dst_port); + if (sfd < 0) { return ret; } + + iphone_msync_client_t client_loc = (iphone_msync_client_t) malloc(sizeof(struct iphone_msync_client_int)); + client_loc->sfd = sfd; + //perform handshake plist_t array = NULL; @@ -120,7 +121,7 @@ iphone_error_t iphone_msync_free_client(iphone_msync_client_t client) return IPHONE_E_INVALID_ARG; iphone_msync_stop_session(client); - return iphone_mux_free_client(client->connection); + return usbmuxd_disconnect(client->sfd); } /** Polls the iPhone for MobileSync data. @@ -138,14 +139,14 @@ iphone_error_t iphone_msync_recv(iphone_msync_client_t client, plist_t * plist) char *receive = NULL; uint32_t datalen = 0, bytes = 0, received_bytes = 0; - ret = iphone_mux_recv(client->connection, (char *) &datalen, sizeof(datalen), &bytes); + ret = usbmuxd_recv(client->sfd, (char *) &datalen, sizeof(datalen), &bytes); datalen = ntohl(datalen); receive = (char *) malloc(sizeof(char) * datalen); /* fill buffer and request more packets if needed */ while ((received_bytes < datalen) && (ret == IPHONE_E_SUCCESS)) { - ret = iphone_mux_recv(client->connection, receive + received_bytes, datalen - received_bytes, &bytes); + ret = usbmuxd_recv(client->sfd, receive + received_bytes, datalen - received_bytes, &bytes); received_bytes += bytes; } @@ -201,7 +202,7 @@ iphone_error_t iphone_msync_send(iphone_msync_client_t client, plist_t plist) memcpy(real_query, &length, sizeof(length)); memcpy(real_query + 4, content, ntohl(length)); - ret = iphone_mux_send(client->connection, real_query, ntohl(length) + sizeof(length), &bytes); + ret = usbmuxd_send(client->sfd, real_query, ntohl(length) + sizeof(length), (uint32_t*)&bytes); free(real_query); return ret; } diff --git a/src/MobileSync.h b/src/MobileSync.h index 7655b59..495e702 100644 --- a/src/MobileSync.h +++ b/src/MobileSync.h @@ -21,7 +21,6 @@ #ifndef MOBILESYNC_H #define MOBILESYNC_H -#include "usbmux.h" #include "iphone.h" #include "utils.h" @@ -30,7 +29,7 @@ struct iphone_msync_client_int { - iphone_umux_client_t connection; + int sfd; }; diff --git a/src/NotificationProxy.c b/src/NotificationProxy.c index d8bcc34..6fc048c 100644 --- a/src/NotificationProxy.c +++ b/src/NotificationProxy.c @@ -21,6 +21,7 @@ #include <string.h> #include <stdio.h> +#include <stdlib.h> #include <arpa/inet.h> #include <plist/plist.h> #include "NotificationProxy.h" @@ -79,9 +80,9 @@ static iphone_error_t np_plist_send(iphone_np_client_t client, plist_t dict) } nlen = htonl(length); - iphone_mux_send(client->connection, (const char*)&nlen, sizeof(nlen), (uint32_t*)&bytes); + usbmuxd_send(client->sfd, (const char*)&nlen, sizeof(nlen), (uint32_t*)&bytes); if (bytes == sizeof(nlen)) { - iphone_mux_send(client->connection, XML_content, length, (uint32_t*)&bytes); + usbmuxd_send(client->sfd, XML_content, length, (uint32_t*)&bytes); if (bytes > 0) { if ((uint32_t)bytes == length) { res = IPHONE_E_SUCCESS; @@ -107,26 +108,24 @@ static iphone_error_t np_plist_send(iphone_np_client_t client, plist_t dict) * * @return A handle to the newly-connected client or NULL upon error. */ -iphone_error_t iphone_np_new_client ( iphone_device_t device, int src_port, int dst_port, iphone_np_client_t *client ) +iphone_error_t iphone_np_new_client ( iphone_device_t device, int dst_port, iphone_np_client_t *client ) { - int ret = IPHONE_E_SUCCESS; - //makes sure thread environment is available if (!g_thread_supported()) g_thread_init(NULL); - iphone_np_client_t client_loc = (iphone_np_client_t) malloc(sizeof(struct iphone_np_client_int)); if (!device) return IPHONE_E_INVALID_ARG; // Attempt connection - client_loc->connection = NULL; - ret = iphone_mux_new_client(device, src_port, dst_port, &client_loc->connection); - if (IPHONE_E_SUCCESS != ret || !client_loc->connection) { - free(client_loc); - return ret; + int sfd = usbmuxd_connect(device->handle, dst_port); + if (sfd < 0) { + return IPHONE_E_UNKNOWN_ERROR; //ret; } + iphone_np_client_t client_loc = (iphone_np_client_t) malloc(sizeof(struct iphone_np_client_int)); + client_loc->sfd = sfd; + client_loc->mutex = g_mutex_new(); client_loc->notifier = NULL; @@ -144,13 +143,11 @@ iphone_error_t iphone_np_free_client ( iphone_np_client_t client ) if (!client) return IPHONE_E_INVALID_ARG; - if (client->connection) { - iphone_mux_free_client(client->connection); - client->connection = NULL; - if (client->notifier) { - log_debug_msg("joining np callback\n"); - g_thread_join(client->notifier); - } + usbmuxd_disconnect(client->sfd); + client->sfd = -1; + if (client->notifier) { + log_debug_msg("joining np callback\n"); + g_thread_join(client->notifier); } if (client->mutex) { g_mutex_free(client->mutex); @@ -295,13 +292,13 @@ iphone_error_t iphone_np_get_notification( iphone_np_client_t client, char **not char *XML_content = NULL; plist_t dict = NULL; - if (!client || !client->connection || *notification) { + if (!client || client->sfd < 0 || *notification) { return IPHONE_E_INVALID_ARG; } np_lock(client); - iphone_mux_recv_timeout(client->connection, (char*)&pktlen, sizeof(pktlen), &bytes, 500); + usbmuxd_recv_timeout(client->sfd, (char*)&pktlen, sizeof(pktlen), &bytes, 500); log_debug_msg("NotificationProxy: initial read=%i\n", bytes); if (bytes < 4) { log_debug_msg("NotificationProxy: no notification received!\n"); @@ -313,7 +310,7 @@ iphone_error_t iphone_np_get_notification( iphone_np_client_t client, char **not XML_content = (char*)malloc(pktlen); log_debug_msg("pointer %p\n", XML_content); - iphone_mux_recv_timeout(client->connection, XML_content, pktlen, &bytes, 1000); + usbmuxd_recv_timeout(client->sfd, XML_content, pktlen, &bytes, 1000); if (bytes <= 0) { res = IPHONE_E_UNKNOWN_ERROR; } else { @@ -393,7 +390,7 @@ gpointer iphone_np_notifier( gpointer arg ) if (!npt) return NULL; log_debug_msg("%s: starting callback.\n", __func__); - while (npt->client->connection) { + while (npt->client->sfd >= 0) { iphone_np_get_notification(npt->client, ¬ification); if (notification) { npt->cbfunc(notification); @@ -432,11 +429,11 @@ iphone_error_t iphone_np_set_notify_callback( iphone_np_client_t client, iphone_ np_lock(client); if (client->notifier) { log_debug_msg("%s: callback already set, removing\n"); - iphone_umux_client_t conn = client->connection; - client->connection = NULL; + int conn = client->sfd; + client->sfd = -1; g_thread_join(client->notifier); client->notifier = NULL; - client->connection = conn; + client->sfd = conn; } if (notify_cb) { diff --git a/src/NotificationProxy.h b/src/NotificationProxy.h index 3552b79..afae98a 100644 --- a/src/NotificationProxy.h +++ b/src/NotificationProxy.h @@ -19,13 +19,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libiphone/libiphone.h" -#include "usbmux.h" #include "iphone.h" #include <glib.h> struct iphone_np_client_int { - iphone_umux_client_t connection; + int sfd; GMutex *mutex; GThread *notifier; }; diff --git a/src/iphone.c b/src/iphone.c index 9dd3c07..9551173 100644 --- a/src/iphone.c +++ b/src/iphone.c @@ -19,200 +19,85 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "usbmux.h" #include "iphone.h" #include "utils.h" -#include <arpa/inet.h> -#include <usb.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <errno.h> +#include <libiphone/libiphone.h> /** - * This function sets the configuration of the given device to 3 - * and claims the interface 1. If usb_set_configuration fails, it detaches - * the kernel driver that blocks the device, and retries configuration. + * Retrieves a list of connected devices from usbmuxd and matches their + * UUID with the given UUID. If the given UUID is NULL then the first + * device reported by usbmuxd is used. * - * @param phone which device to configure - */ -static void iphone_config_usb_device(iphone_device_t phone) -{ - int ret; - int bytes; - unsigned char buf[512]; - - log_debug_msg("setting configuration... "); - ret = usb_set_configuration(phone->device, 3); - if (ret != 0) { - log_debug_msg("Hm, usb_set_configuration returned %d: %s, trying to fix:\n", ret, strerror(-ret)); - log_debug_msg("-> detaching kernel driver... "); - ret = - usb_detach_kernel_driver_np(phone->device, - phone->__device->config->interface->altsetting->bInterfaceNumber); - if (ret != 0) { - log_debug_msg("usb_detach_kernel_driver_np returned %d: %s\n", ret, strerror(-ret)); - } else { - log_debug_msg("done.\n"); - log_debug_msg("setting configuration again... "); - ret = usb_set_configuration(phone->device, 3); - if (ret != 0) { - log_debug_msg("Error: usb_set_configuration returned %d: %s\n", ret, strerror(-ret)); - } else { - log_debug_msg("done.\n"); - } - } - } else { - log_debug_msg("done.\n"); - } - - log_debug_msg("claiming interface... "); - ret = usb_claim_interface(phone->device, 1); - if (ret != 0) { - log_debug_msg("Error: usb_claim_interface returned %d: %s\n", ret, strerror(-ret)); - } else { - log_debug_msg("done.\n"); - } - - do { - bytes = usb_bulk_read(phone->device, BULKIN, (void *) &buf, 512, 800); - if (bytes > 0) { - log_debug_msg("iphone_config_usb_device: initial read returned %d bytes of data.\n", bytes); - log_debug_buffer(buf, bytes); - } - } while (bytes > 0); -} - -/** - * Given a USB bus and device number, returns a device handle to the iPhone on - * that bus. To aid compatibility with future devices, this function does not - * check the vendor and device IDs! To do that, you should use - * iphone_get_device() or a system-specific API (e.g. HAL). + * @param device Upon calling this function, a pointer to a location of type + * iphone_device_t, which must have the value NULL. On return, this location + * will be filled with a handle to the device. + * @param uuid The UUID to match. * - * @param bus_n The USB bus number. - * @param dev_n The USB device number. - * @param device A pointer to a iphone_device_t, which must be set to NULL upon - * calling iphone_get_specific_device, which will be filled with a device - * descriptor on return. * @return IPHONE_E_SUCCESS if ok, otherwise an error code. */ -iphone_error_t iphone_get_specific_device(unsigned int bus_n, int dev_n, iphone_device_t * device) +iphone_error_t iphone_get_device_by_uuid(iphone_device_t * device, const char *uuid) { - struct usb_bus *bus, *busses; - struct usb_device *dev; - usbmux_version_header *version; - int bytes = 0; - - //check we can actually write in device - if (!device || (device && *device)) - return IPHONE_E_INVALID_ARG; - - iphone_device_t phone = (iphone_device_t) malloc(sizeof(struct iphone_device_int)); + iphone_device_t phone; + uint32_t handle = 0; + usbmuxd_scan_result *dev_list = NULL; + int i; - // Initialize the struct - phone->device = NULL; - phone->__device = NULL; - phone->buffer = NULL; - - // Initialize libusb - usb_init(); - usb_find_busses(); - usb_find_devices(); - busses = usb_get_busses(); - - // Set the device configuration - for (bus = busses; bus; bus = bus->next) - if (strtoul(bus->dirname, NULL, 10) == bus_n) - for (dev = bus->devices; dev != NULL; dev = dev->next) - if (strtol(dev->filename, NULL, 10) == dev_n) { - phone->__device = dev; - phone->device = usb_open(phone->__device); - iphone_config_usb_device(phone); - goto found; + if (usbmuxd_scan(&dev_list) < 0) { + log_debug_msg("%s: usbmuxd_scan returned an error, is usbmuxd running?\n", __func__); + } + if (dev_list && dev_list[0].handle > 0) { + if (!uuid) { + // select first device found if no UUID specified + handle = dev_list[0].handle; + } else { + // otherwise walk through the list + for (i = 0; dev_list[i].handle > 0; i++) { + log_debug_msg("%s: device handle=%d, uuid=%s\n", __func__, dev_list[i].handle, dev_list[i].serial_number); + if (strcasecmp(uuid, dev_list[i].serial_number) == 0) { + handle = dev_list[i].handle; + break; } - - iphone_free_device(phone); - - log_debug_msg("iphone_get_specific_device: iPhone not found\n"); - return IPHONE_E_NO_DEVICE; - - found: - // Send the version command to the phone - version = version_header(); - bytes = usb_bulk_write(phone->device, BULKOUT, (char *) version, sizeof(*version), 800); - if (bytes < 20) { - log_debug_msg("get_iPhone(): libusb did NOT send enough!\n"); - if (bytes < 0) { - log_debug_msg("get_iPhone(): libusb gave me the error %d: %s (%s)\n", - bytes, usb_strerror(), strerror(-bytes)); + } } - } - // Read the phone's response - bytes = usb_bulk_read(phone->device, BULKIN, (char *) version, sizeof(*version), 800); + free(dev_list); - // Check for bad response - if (bytes < 20) { - free(version); - iphone_free_device(phone); - log_debug_msg("get_iPhone(): Invalid version message -- header too short.\n"); - if (bytes < 0) - log_debug_msg("get_iPhone(): libusb error message %d: %s (%s)\n", bytes, usb_strerror(), strerror(-bytes)); - return IPHONE_E_NOT_ENOUGH_DATA; - } - // Check for correct version - if (ntohl(version->major) == 1 && ntohl(version->minor) == 0) { - // We're all ready to roll. - log_debug_msg("get_iPhone() success\n"); - free(version); - *device = phone; - return IPHONE_E_SUCCESS; - } else { - // Bad header - log_debug_msg("get_iPhone(): Received a bad header/invalid version number.\n"); - log_debug_buffer((char *) version, sizeof(*version)); - iphone_free_device(phone); - free(version); - return IPHONE_E_BAD_HEADER; + if (handle > 0) { + phone = (iphone_device_t) malloc(sizeof(struct iphone_device_int)); + phone->handle = handle; + *device = phone; + return IPHONE_E_SUCCESS; + } } - // If it got to this point it's gotta be bad - log_debug_msg("get_iPhone(): Unknown error.\n"); - iphone_free_device(phone); - free(version); - return IPHONE_E_UNKNOWN_ERROR; // if it got to this point it's gotta be bad + return IPHONE_E_NO_DEVICE; } /** - * Scans all USB busses and devices for a known AFC-compatible device and - * returns a handle to the first such device it finds. Known devices include - * those with vendor ID 0x05ac and product ID between 0x1290 and 0x1293 - * inclusive. + * This function has the purpose to retrieve a handle to the first + * attached iPhone/iPod reported by usbmuxd. * - * This function is convenient, but on systems where higher-level abstractions - * (such as HAL) are available it may be preferable to use - * iphone_get_specific_device instead, because it can deal with multiple - * connected devices as well as devices not known to libiphone. - * - * @param device Upon calling this function, a pointer to a location of type + * @param Upon calling this function, a pointer to a location of type * iphone_device_t, which must have the value NULL. On return, this location * will be filled with a handle to the device. + * * @return IPHONE_E_SUCCESS if ok, otherwise an error code. */ iphone_error_t iphone_get_device(iphone_device_t * device) { - struct usb_bus *bus; - struct usb_device *dev; - - usb_init(); - usb_find_busses(); - usb_find_devices(); - - for (bus = usb_get_busses(); bus != NULL; bus = bus->next) - for (dev = bus->devices; dev != NULL; dev = dev->next) - if (dev->descriptor.idVendor == 0x05ac - && dev->descriptor.idProduct >= 0x1290 && dev->descriptor.idProduct <= 0x1293) - return iphone_get_specific_device(strtoul(bus->dirname, NULL, 10), strtol(dev->filename, NULL, 10), device); + return iphone_get_device_by_uuid(device, NULL); +} - return IPHONE_E_NO_DEVICE; +uint32_t iphone_get_device_handle(iphone_device_t device) +{ + if (device) { + return device->handle; + } else { + return 0; + } } /** Cleans up an iPhone structure, then frees the structure itself. @@ -226,88 +111,10 @@ iphone_error_t iphone_free_device(iphone_device_t device) if (!device) return IPHONE_E_INVALID_ARG; iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; - int bytes; - unsigned char buf[512]; - // read final package(s) - if (device->device != NULL) { - do { - bytes = usb_bulk_read(device->device, BULKIN, (void *) &buf, 512, 800); - if (bytes > 0) { - log_debug_msg("iphone_free_device: final read returned\n"); - log_debug_buffer(buf, bytes); - } - } while (bytes > 0); - } + ret = IPHONE_E_SUCCESS; - if (device->buffer) { - free(device->buffer); - } - if (device->device) { - usb_release_interface(device->device, 1); - usb_close(device->device); - ret = IPHONE_E_SUCCESS; - } free(device); return ret; } -/** Sends data to the phone - * This is a low-level (i.e. directly to phone) function. - * - * @param phone The iPhone to send data to - * @param data The data to send to the iPhone - * @param datalen The length of the data - * @return The number of bytes sent, or -1 on error or something. - */ -int send_to_phone(iphone_device_t phone, char *data, int datalen) -{ - if (!phone) - return -1; - int bytes = 0; - - if (!phone) - return -1; - log_debug_msg("send_to_phone: Attempting to send datalen = %i data = %p\n", datalen, data); - - bytes = usb_bulk_write(phone->device, BULKOUT, data, datalen, 800); - if (bytes < datalen) { - if (bytes < 0) - log_debug_msg("send_to_iphone(): libusb gave me the error %d: %s - %s\n", bytes, usb_strerror(), - strerror(-bytes)); - return -1; - } else { - return bytes; - } - /* Should not be reached */ - return -1; -} - -/** This function is a low-level (i.e. direct to iPhone) function. - * - * @param phone The iPhone to receive data from - * @param data Where to put data read - * @param datalen How much data to read in - * @param timeout How many milliseconds to wait for data - * - * @return How many bytes were read in, or -1 on error. - */ -int recv_from_phone(iphone_device_t phone, char *data, int datalen, int timeout) -{ - if (!phone) - return -1; - int bytes = 0; - - if (!phone) - return -1; - log_debug_msg("recv_from_phone(): attempting to receive %i bytes\n", datalen); - - bytes = usb_bulk_read(phone->device, BULKIN, data, datalen, timeout); - if (bytes < 0) { - log_debug_msg("recv_from_phone(): libusb gave me the error %d: %s (%s)\n", bytes, usb_strerror(), - strerror(-bytes)); - return -1; - } - - return bytes; -} diff --git a/src/iphone.h b/src/iphone.h index 15515e3..94d2f9f 100644 --- a/src/iphone.h +++ b/src/iphone.h @@ -22,24 +22,11 @@ #ifndef IPHONE_H #define IPHONE_H -#ifndef USBMUX_H -#include "usbmux.h" -#warning usbmux not included? -#endif - -#include <usb.h> -#include <libiphone/libiphone.h> - -#define BULKIN 0x85 -#define BULKOUT 0x04 +#include <stdint.h> struct iphone_device_int { char *buffer; - struct usb_dev_handle *device; - struct usb_device *__device; + uint32_t handle; }; -// Function definitions -int send_to_phone(iphone_device_t phone, char *data, int datalen); -int recv_from_phone(iphone_device_t phone, char *data, int datalen, int timeout); #endif diff --git a/src/lockdown.c b/src/lockdown.c index 5ade79a..28670de 100644 --- a/src/lockdown.c +++ b/src/lockdown.c @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "usbmux.h" #include "utils.h" #include "iphone.h" #include "lockdown.h" @@ -53,13 +52,15 @@ iphone_lckd_client_t new_lockdownd_client(iphone_device_t phone) { if (!phone) return NULL; - iphone_lckd_client_t control = (iphone_lckd_client_t) malloc(sizeof(struct iphone_lckd_client_int)); - if (IPHONE_E_SUCCESS != iphone_mux_new_client(phone, 0x0a00, 0xf27e, &control->connection)) { - free(control); + int sfd = usbmuxd_connect(phone->handle, 0xf27e); + if (sfd < 0) { + log_debug_msg("%s: could not connect to lockdownd (device handle %d)\n", __func__, phone->handle); return NULL; } + iphone_lckd_client_t control = (iphone_lckd_client_t) malloc(sizeof(struct iphone_lckd_client_int)); + control->sfd = sfd; control->ssl_session = (gnutls_session_t *) malloc(sizeof(gnutls_session_t)); control->in_SSL = 0; return control; @@ -167,13 +168,13 @@ iphone_error_t iphone_lckd_free_client(iphone_lckd_client_t client) iphone_lckd_stop_SSL_session(client); - if (client->connection) { + if (client->sfd > 0) { lockdownd_close(client); // IMO, read of final "sessionUpcall connection closed" packet // should come here instead of in iphone_free_device - ret = iphone_mux_free_client(client->connection); + ret = usbmuxd_disconnect(client->sfd); } free(client); @@ -197,7 +198,7 @@ iphone_error_t iphone_lckd_recv(iphone_lckd_client_t client, plist_t * plist) uint32_t datalen = 0, bytes = 0, received_bytes = 0; if (!client->in_SSL) - ret = iphone_mux_recv(client->connection, (char *) &datalen, sizeof(datalen), &bytes); + ret = usbmuxd_recv(client->sfd, (char *) &datalen, sizeof(datalen), &bytes); else { bytes = gnutls_record_recv(*client->ssl_session, &datalen, sizeof(datalen)); if (bytes > 0) @@ -210,7 +211,7 @@ iphone_error_t iphone_lckd_recv(iphone_lckd_client_t client, plist_t * plist) if (!client->in_SSL) { /* fill buffer and request more packets if needed */ while ((received_bytes < datalen) && (ret == IPHONE_E_SUCCESS)) { - ret = iphone_mux_recv(client->connection, receive + received_bytes, datalen - received_bytes, &bytes); + ret = usbmuxd_recv(client->sfd, receive + received_bytes, datalen - received_bytes, &bytes); //iphone_mux_recv(client->connection, receive + received_bytes, datalen - received_bytes, &bytes); received_bytes += bytes; } } else { @@ -271,7 +272,7 @@ iphone_error_t iphone_lckd_send(iphone_lckd_client_t client, plist_t plist) log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_send(): made the query, sending it along\n"); if (!client->in_SSL) - ret = iphone_mux_send(client->connection, real_query, ntohl(length) + sizeof(length), &bytes); + ret = usbmuxd_send(client->sfd, real_query, ntohl(length) + sizeof(length), (uint32_t*)&bytes); //iphone_mux_send(client->connection, real_query, ntohl(length) + sizeof(length), &bytes); else { gnutls_record_send(*client->ssl_session, real_query, ntohl(length) + sizeof(length)); ret = IPHONE_E_SUCCESS; @@ -465,7 +466,7 @@ iphone_error_t lockdownd_get_device_uid(iphone_lckd_client_t control, char **uid * * @note You most likely want lockdownd_init unless you are doing something special. * - * @return 1 on success and 0 on failure. + * @return IPHONE_E_SUCCESS on succes or an error value < 0 on failure. */ iphone_error_t lockdownd_get_device_public_key(iphone_lckd_client_t control, gnutls_datum_t * public_key) { @@ -1026,7 +1027,7 @@ ssize_t lockdownd_secuwrite(gnutls_transport_ptr_t transport, char *buffer, size control = (iphone_lckd_client_t) transport; log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_secuwrite() called\n"); log_dbg_msg(DBGMASK_LOCKDOWND, "pre-send\nlength = %zi\n", length); - iphone_mux_send(control->connection, buffer, length, &bytes); + usbmuxd_send(control->sfd, buffer, length, &bytes); log_dbg_msg(DBGMASK_LOCKDOWND, "post-send\nsent %i bytes\n", bytes); dump_debug_buffer("sslpacketwrite.out", buffer, length); @@ -1059,7 +1060,7 @@ ssize_t lockdownd_securead(gnutls_transport_ptr_t transport, char *buffer, size_ // repeat until we have the full data or an error occurs. do { - if ((res = iphone_mux_recv(control->connection, recv_buffer, this_len, &bytes)) != IPHONE_E_SUCCESS) { + if ((res = usbmuxd_recv(control->sfd, recv_buffer, this_len, &bytes)) != IPHONE_E_SUCCESS) { log_debug_msg("%s: ERROR: iphone_mux_recv returned %d\n", __func__, res); return res; } diff --git a/src/lockdown.h b/src/lockdown.h index 7485006..1f9d84c 100644 --- a/src/lockdown.h +++ b/src/lockdown.h @@ -22,8 +22,6 @@ #ifndef LOCKDOWND_H #define LOCKDOWND_H -#include "usbmux.h" - #include <gnutls/gnutls.h> #include <string.h> #include <libiphone/libiphone.h> @@ -32,7 +30,7 @@ struct iphone_lckd_client_int { - iphone_umux_client_t connection; + int sfd; gnutls_session_t *ssl_session; int in_SSL; char session_id[40]; diff --git a/src/usbmux.c b/src/usbmux.c deleted file mode 100644 index 7d74b4b..0000000 --- a/src/usbmux.c +++ /dev/null @@ -1,410 +0,0 @@ -/* - * usbmux.c - * Interprets the usb multiplexing protocol used by the iPhone. - * - * Copyright (c) 2008 Zach C. All Rights Reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <sys/types.h> -#include <arpa/inet.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "usbmux.h" -#include "utils.h" - -static iphone_umux_client_t *connlist = NULL; -static int clients = 0; - -/** Creates a USBMux packet for the given set of ports. - * - * @param s_port The source port for the connection. - * @param d_port The destination port for the connection. - * - * @return A USBMux packet - */ -usbmux_tcp_header *new_mux_packet(uint16_t s_port, uint16_t d_port) -{ - usbmux_tcp_header *conn = (usbmux_tcp_header *) malloc(sizeof(usbmux_tcp_header)); - conn->type = htonl(6); - conn->length = 28; - conn->sport = htons(s_port); - conn->dport = htons(d_port); - conn->scnt = 0; - conn->ocnt = 0; - conn->offset = 0x50; - conn->window = htons(0x0200); - conn->nullnull = 0x0000; - conn->length16 = 28; - return conn; -} - -/** Creates a USBMux header containing version information - * - * @return A USBMux header - */ -usbmux_version_header *version_header(void) -{ - usbmux_version_header *version = (usbmux_version_header *) malloc(sizeof(usbmux_version_header)); - version->type = 0; - version->length = htonl(20); - version->major = htonl(1); - version->minor = 0; - version->allnull = 0; - return version; -} - - -// Maintenance functions. - -/** Removes a connection from the list of connections made. - * The list of connections is necessary for buffering. - * - * @param connection The connection to delete from the tracking list. - */ -static void delete_connection(iphone_umux_client_t connection) -{ - iphone_umux_client_t *newlist = (iphone_umux_client_t *) malloc(sizeof(iphone_umux_client_t) * (clients - 1)); - int i = 0, j = 0; - for (i = 0; i < clients; i++) { - if (connlist[i] == connection) - continue; - else { - newlist[j] = connlist[i]; - j++; - } - } - free(connlist); - connlist = newlist; - clients--; - if (connection->recv_buffer) - free(connection->recv_buffer); - if (connection->header) - free(connection->header); - connection->r_len = 0; - free(connection); -} - -/** Adds a connection to the list of connections made. - * The connection list is necessary for buffering. - * - * @param connection The connection to add to the global list of connections. - */ - -static void add_connection(iphone_umux_client_t connection) -{ - iphone_umux_client_t *newlist = - (iphone_umux_client_t *) realloc(connlist, sizeof(iphone_umux_client_t) * (clients + 1)); - newlist[clients] = connection; - connlist = newlist; - clients++; -} - -/** Initializes a connection on phone, with source port s_port and destination port d_port - * - * @param device The iPhone to initialize a connection on. - * @param src_port The source port - * @param dst_port The destination port -- 0xf27e for lockdownd. - * @param client A mux TCP header for the connection which is used for tracking and data transfer. - * @return IPHONE_E_SUCCESS on success, an error code otherwise. - */ -iphone_error_t iphone_mux_new_client(iphone_device_t device, uint16_t src_port, uint16_t dst_port, - iphone_umux_client_t * client) -{ - if (!device || !src_port || !dst_port) - return IPHONE_E_INVALID_ARG; - - int bytes = 0; - // Initialize connection stuff - iphone_umux_client_t new_connection = (iphone_umux_client_t) malloc(sizeof(struct iphone_umux_client_int)); - new_connection->header = new_mux_packet(src_port, dst_port); - - // blargg - if (new_connection && new_connection->header) { - new_connection->header->tcp_flags = 0x02; - new_connection->header->length = htonl(new_connection->header->length); - new_connection->header->length16 = htons(new_connection->header->length16); - - if (send_to_phone(device, (char *) new_connection->header, sizeof(usbmux_tcp_header)) >= 0) { - usbmux_tcp_header *response; - response = (usbmux_tcp_header *) malloc(sizeof(usbmux_tcp_header)); - bytes = recv_from_phone(device, (char *) response, sizeof(*response), 3500); - if (response->tcp_flags != 0x12) { - free(response); - return IPHONE_E_UNKNOWN_ERROR; - } else { - free(response); - - log_debug_msg("mux_connect: connection success\n"); - new_connection->header->tcp_flags = 0x10; - new_connection->header->scnt = 1; - new_connection->header->ocnt = 1; - new_connection->phone = device; - new_connection->recv_buffer = NULL; - new_connection->r_len = 0; - add_connection(new_connection); - *client = new_connection; - return IPHONE_E_SUCCESS; - } - } else { - return IPHONE_E_NOT_ENOUGH_DATA; - } - } - // if we get to this point it's probably bad - return IPHONE_E_UNKNOWN_ERROR; -} - -/** Cleans up the given USBMux connection. - * @note Once a connection is closed it may not be used again. - * - * @param connection The connection to close. - * - * @return IPHONE_E_SUCCESS on success. - */ -iphone_error_t iphone_mux_free_client(iphone_umux_client_t client) -{ - if (!client || !client->phone) - return IPHONE_E_INVALID_ARG; - - client->header->tcp_flags = 0x04; - client->header->length = htonl(0x1C); - client->header->scnt = htonl(client->header->scnt); - client->header->ocnt = htonl(client->header->ocnt); - client->header->window = 0; - client->header->length16 = htons(0x1C); - int bytes = 0; - - bytes = usb_bulk_write(client->phone->device, BULKOUT, (char *) client->header, sizeof(usbmux_tcp_header), 800); - if (bytes < 0) - log_debug_msg("iphone_muxèfree_client(): when writing, libusb gave me the error: %s\n", usb_strerror()); - - bytes = usb_bulk_read(client->phone->device, BULKIN, (char *) client->header, sizeof(usbmux_tcp_header), 800); - if (bytes < 0) - log_debug_msg("get_iPhone(): when reading, libusb gave me the error: %s\n", usb_strerror()); - - delete_connection(client); - - return IPHONE_E_SUCCESS; -} - - -/** Sends the given data over the selected connection. - * - * @param phone The iPhone to send to. - * @param client The client we're sending data on. - * @param data A pointer to the data to send. - * @param datalen How much data we're sending. - * @param sent_bytes The number of bytes sent, minus the header (28) - * - * @return IPHONE_E_SUCCESS on success. - */ - -iphone_error_t iphone_mux_send(iphone_umux_client_t client, const char *data, uint32_t datalen, uint32_t * sent_bytes) -{ - if (!client->phone || !client || !data || datalen == 0 || !sent_bytes) - return IPHONE_E_INVALID_ARG; - // client->scnt and client->ocnt should already be in host notation... - // we don't need to change them juuuust yet. - *sent_bytes = 0; - log_debug_msg("mux_send(): client wants to send %i bytes\n", datalen); - char *buffer = (char *) malloc(sizeof(usbmux_tcp_header) + datalen + 2); // allow 2 bytes of safety padding - // Set the length and pre-emptively htonl/htons it - client->header->length = htonl(sizeof(usbmux_tcp_header) + datalen); - client->header->length16 = htons(sizeof(usbmux_tcp_header) + datalen); - - // Put scnt and ocnt into big-endian notation - client->header->scnt = htonl(client->header->scnt); - client->header->ocnt = htonl(client->header->ocnt); - // Concatenation of stuff in the buffer. - memcpy(buffer, client->header, sizeof(usbmux_tcp_header)); - memcpy(buffer + sizeof(usbmux_tcp_header), data, datalen); - - // We have a buffer full of data, we should now send it to the phone. - log_debug_msg("actually sending %zi bytes of data at %p\n", sizeof(usbmux_tcp_header) + datalen, buffer); - - - *sent_bytes = send_to_phone(client->phone, buffer, sizeof(usbmux_tcp_header) + datalen); - log_debug_msg("mux_send: sent %i bytes!\n", *sent_bytes); - // Now that we've sent it off, we can clean up after our sloppy selves. - dump_debug_buffer("packet", buffer, *sent_bytes); - if (buffer) - free(buffer); - // Re-calculate scnt and ocnt - client->header->scnt = ntohl(client->header->scnt) + datalen; - client->header->ocnt = ntohl(client->header->ocnt); - - // Revert lengths - client->header->length = ntohl(client->header->length); - client->header->length16 = ntohs(client->header->length16); - - // Now return the bytes. - if (*sent_bytes < sizeof(usbmux_tcp_header) + datalen) { - *sent_bytes = 0; - return IPHONE_E_NOT_ENOUGH_DATA; - } else { - *sent_bytes = *sent_bytes - 28; // actual length sent. :/ - } - - return IPHONE_E_SUCCESS; -} - -/** This is a higher-level USBMuxTCP-like function - * - * @param connection The connection to receive data on. - * @param data Where to put the data we receive. - * @param datalen How much data to read. - * @param recv_bytes Pointer to a uint32_t that will be set - * to the number of bytes received. - * @param timeout How many milliseconds to wait for data. - * - * @return IPHONE_E_SUCCESS on success, or and error value. - */ -iphone_error_t iphone_mux_recv_timeout(iphone_umux_client_t client, char *data, uint32_t datalen, uint32_t * recv_bytes, int timeout) -{ - - if (!client || !data || datalen == 0 || !recv_bytes) - return IPHONE_E_INVALID_ARG; - /* - * Order of operation: - * 1.) Check if the client has a pre-received buffer. - * 2.) If so, fill data with the buffer, as much as needed. - * a.) Return quickly if the buffer has enough - * b.) If the buffer is only part of the datalen, get the rest of datalen (and if we can't, just return) - * 3.) If not, receive directly from the phone. - * a.) Check incoming packet's ports. If proper, follow proper buffering and receiving operation. - * b.) If not, find the client the ports belong to and fill that client's buffer, then return mux_recv with the same args to try again. - */ - log_debug_msg("mux_recv: datalen == %i\n", datalen); - int bytes = 0, i = 0, complex = 0, offset = 0; - *recv_bytes = 0; - char *buffer = NULL; - usbmux_tcp_header *header = NULL; - - if (client->recv_buffer) { - if (client->r_len >= datalen) { - memcpy(data, client->recv_buffer, datalen); - if (client->r_len == datalen) { - // reset everything - free(client->recv_buffer); - client->r_len = 0; - client->recv_buffer = NULL; - } else { - buffer = (char *) malloc(sizeof(char) * (client->r_len - datalen)); - memcpy(buffer, client->recv_buffer + datalen, (client->r_len - datalen)); - client->r_len -= datalen; - free(client->recv_buffer); - client->recv_buffer = buffer; - } - - // Since we were able to fill the data straight from our buffer, we can just return datalen. See 2a above. - *recv_bytes = datalen; - return IPHONE_E_SUCCESS; - } else { - memcpy(data, client->recv_buffer, client->r_len); - free(client->recv_buffer); // don't need to deal with anymore, but... - client->recv_buffer = NULL; - offset = client->r_len; // see #2b, above - client->r_len = 0; - } - } // End of what to do if we have a pre-buffer. See #1 and #2 above. - - buffer = (char *) malloc(sizeof(char) * 131072); // make sure we get enough ;) - - // See #3. - bytes = recv_from_phone(client->phone, buffer, 131072, timeout); - if (bytes < 28) { - free(buffer); - log_debug_msg("mux_recv: Did not even get the header.\n"); - return IPHONE_E_NOT_ENOUGH_DATA; - } - - header = (usbmux_tcp_header *) buffer; - if (header->sport != client->header->dport || header->dport != client->header->sport) { - // Ooooops -- we got someone else's packet. - // We gotta stick it in their buffer. (Take that any old way you want ;) ) - for (i = 0; i < clients; i++) { - if (connlist[i]->header->sport == header->dport && connlist[i]->header->dport == header->sport) { - // we have a winner. - char *nfb = (char *) malloc(sizeof(char) * (connlist[i]->r_len + (bytes - 28))); - if (connlist[i]->recv_buffer && connlist[i]->r_len) { - memcpy(nfb, connlist[i]->recv_buffer, connlist[i]->r_len); - free(connlist[i]->recv_buffer); - } - connlist[i]->r_len += bytes - 28; - //connlist[i]->recv_buffer = (char*)realloc(connlist[i]->recv_buffer, sizeof(char) * client->r_len); // grow their buffer - connlist[i]->recv_buffer = nfb; - nfb = NULL; // A cookie for you if you can guess what "nfb" means. - complex = connlist[i]->r_len - (bytes - 28); - memcpy(connlist[i]->recv_buffer + complex, buffer + 28, bytes - 28); // paste into their buffer - connlist[i]->header->ocnt += bytes - 28; - } - } - // If it wasn't ours, it's been handled by this point... or forgotten. - // Free our buffer and continue. - free(buffer); - buffer = NULL; - return iphone_mux_recv(client, data, datalen, recv_bytes); // recurse back in to try again - } - // The packet was absolutely meant for us if it hits this point. - // The pre-buffer has been taken care of, so, again, if we're at this point we have to read from the phone. - - if ((bytes - 28) > datalen) { - // Copy what we need into the data, buffer the rest because we can. - memcpy(data + offset, buffer + 28, datalen); // data+offset: see #2b, above - complex = client->r_len + ((bytes - 28) - datalen); - client->recv_buffer = (char *) realloc(client->recv_buffer, (sizeof(char) * complex)); - client->r_len = complex; - complex = client->r_len - ((bytes - 28) - datalen); - memcpy(client->recv_buffer + complex, buffer + 28 + datalen, (bytes - 28) - datalen); - free(buffer); - client->header->ocnt += bytes - 28; - *recv_bytes = datalen; - return IPHONE_E_SUCCESS; - } else { - // Fill the data with what we have, and just return. - memcpy(data + offset, buffer + 28, bytes - 28); // data+offset: see #2b, above - client->header->ocnt += bytes - 28; - free(buffer); - *recv_bytes = bytes - 28; - return IPHONE_E_SUCCESS; - } - - // If we get to this point, 'tis probably bad. - log_debug_msg("mux_recv: Heisenbug: bytes and datalen not matching up\n"); - return IPHONE_E_UNKNOWN_ERROR; -} - -/** - * This function is just like 'iphone_mux_recv_timeout' but you do not need - * to specify a timeout. It simply calls iphone_mux_recv_timeout with a - * timeout value of 3500 milliseconds. - * - * @param connection The connection to receive data on. - * @param data Where to put the data we receive. - * @param datalen How much data to read. - * @param recv_bytes Pointer to a uint32_t that will be set - * to the number of bytes received. - * - * @return The return value of iphone_mux_recv_timeout. - * - * @see iphone_mux_recv_timeout - */ -iphone_error_t iphone_mux_recv(iphone_umux_client_t client, char *data, uint32_t datalen, uint32_t * recv_bytes) -{ - return iphone_mux_recv_timeout(client, data, datalen, recv_bytes, 3500); -} diff --git a/src/usbmux.h b/src/usbmux.h deleted file mode 100644 index bea83f7..0000000 --- a/src/usbmux.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * usbmux.h - * Defines structures and variables pertaining to the usb multiplexing. - * - * Copyright (c) 2008 Zach C. All Rights Reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <sys/types.h> -#include <stdlib.h> -#include <stdint.h> -#include "libiphone/libiphone.h" - -#ifndef USBMUX_H -#define USBMUX_H - -#ifndef IPHONE_H -#include "iphone.h" -#endif - -typedef struct { - uint32_t type, length; - uint16_t sport, dport; - uint32_t scnt, ocnt; - uint8_t offset, tcp_flags; - uint16_t window, nullnull, length16; -} usbmux_tcp_header; - -struct iphone_umux_client_int { - usbmux_tcp_header *header; - iphone_device_t phone; - char *recv_buffer; - int r_len; -}; - -usbmux_tcp_header *new_mux_packet(uint16_t s_port, uint16_t d_port); - -typedef struct { - uint32_t type, length, major, minor, allnull; -} usbmux_version_header; - -usbmux_version_header *version_header(void); - - -#endif |