summaryrefslogtreecommitdiffstats
path: root/src/usbmux.c
diff options
context:
space:
mode:
authorGravatar Jonathan Beck2008-08-19 23:58:20 +0200
committerGravatar Jonathan Beck2008-08-31 19:27:20 +0200
commitad65cefa1c041bbd4792e3dc4f4afc7b07026930 (patch)
tree76c73d5372cc7152ec20fb809b6da71f3dd896df /src/usbmux.c
parent21d5d4ac4b4bd419e0d8752147464984497c98ec (diff)
downloadlibimobiledevice-ad65cefa1c041bbd4792e3dc4f4afc7b07026930.tar.gz
libimobiledevice-ad65cefa1c041bbd4792e3dc4f4afc7b07026930.tar.bz2
migrate usbmux.c.
Diffstat (limited to 'src/usbmux.c')
-rw-r--r--src/usbmux.c170
1 files changed, 89 insertions, 81 deletions
diff --git a/src/usbmux.c b/src/usbmux.c
index a4a859a..48cb963 100644
--- a/src/usbmux.c
+++ b/src/usbmux.c
@@ -29,8 +29,8 @@
extern int debug;
-static usbmux_connection **connlist = NULL;
-static int connections = 0;
+static iphone_umux_client_t *connlist = NULL;
+static int clients = 0;
/** Creates a USBMux packet for the given set of ports.
*
@@ -76,10 +76,10 @@ usbmux_version_header *version_header() {
*
* @param connection The connection to delete from the tracking list.
*/
-void delete_connection(usbmux_connection *connection) {
- usbmux_connection **newlist = (usbmux_connection**)malloc(sizeof(usbmux_connection*) * (connections - 1));
+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 < connections; i++) {
+ for (i = 0; i < clients; i++) {
if (connlist[i] == connection) continue;
else {
newlist[j] = connlist[i];
@@ -88,7 +88,7 @@ void delete_connection(usbmux_connection *connection) {
}
free(connlist);
connlist = newlist;
- connections--;
+ clients--;
if (connection->recv_buffer) free(connection->recv_buffer);
if (connection->header) free(connection->header);
connection->r_len = 0;
@@ -101,59 +101,64 @@ void delete_connection(usbmux_connection *connection) {
* @param connection The connection to add to the global list of connections.
*/
-void add_connection(usbmux_connection *connection) {
- usbmux_connection **newlist = (usbmux_connection**)realloc(connlist, sizeof(usbmux_connection*) * (connections+1));
- newlist[connections] = connection;
+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;
- connections++;
+ clients++;
}
/** Initializes a connection on phone, with source port s_port and destination port d_port
*
- * @param phone The iPhone to initialize a connection on.
- * @param s_port The source port
- * @param d_port The destination port -- 0xf27e for lockdownd.
- *
- * @return A mux TCP header for the connection which is used for tracking and data transfer.
- */
-usbmux_connection *mux_connect(iphone_device_t phone, uint16 s_port, uint16 d_port) {
- if (!phone || !s_port || !d_port) return NULL;
+ * @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.
+ */
+int 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
- usbmux_connection *new_connection = (usbmux_connection*)malloc(sizeof(usbmux_connection));
- new_connection->header = new_mux_packet(s_port, d_port);
+ 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(phone, (char*)new_connection->header, sizeof(usbmux_tcp_header)) >= 0) {
+ 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(phone, (char*)response, sizeof(*response));
+ bytes = recv_from_phone(device, (char*)response, sizeof(*response));
if (response->tcp_flags != 0x12) {
free(response);
- return NULL;
+ return IPHONE_E_UNKNOWN_ERROR;
} else {
free(response);
+
if (debug) printf("mux_connect: connection success\n");
new_connection->header->tcp_flags = 0x10;
new_connection->header->scnt = 1;
new_connection->header->ocnt = 1;
- new_connection->phone = phone;
+ new_connection->phone = device;
new_connection->recv_buffer = NULL;
new_connection->r_len = 0;
add_connection(new_connection);
- return new_connection;
+ *client = new_connection;
+ return IPHONE_E_SUCCESS;
}
} else {
- return NULL;
+ return IPHONE_E_NOT_ENOUGH_DATA;
}
}
// if we get to this point it's probably bad
- return NULL;
+ return IPHONE_E_UNKNOWN_ERROR;
}
/** Cleans up the given USBMux connection.
@@ -161,56 +166,59 @@ usbmux_connection *mux_connect(iphone_device_t phone, uint16 s_port, uint16 d_po
*
* @param connection The connection to close.
*/
-void mux_close_connection(usbmux_connection *connection) {
- if (!connection || !connection->phone) return;
+void iphone_mux_free_client ( iphone_umux_client_t client ) {
+ if (!client || !client->phone) return;
- connection->header->tcp_flags = 0x04;
- connection->header->scnt = htonl(connection->header->scnt);
- connection->header->ocnt = htonl(connection->header->ocnt);
+ client->header->tcp_flags = 0x04;
+ client->header->scnt = htonl(client->header->scnt);
+ client->header->ocnt = htonl(client->header->ocnt);
int bytes = 0;
- bytes = usb_bulk_write(connection->phone->device, BULKOUT, (char*)connection->header, sizeof(usbmux_tcp_header), 800);
+ bytes = usb_bulk_write(client->phone->device, BULKOUT, (char*)client->header, sizeof(usbmux_tcp_header), 800);
if(debug && bytes < 0)
printf("mux_close_connection(): when writing, libusb gave me the error: %s\n", usb_strerror());
- bytes = usb_bulk_read(connection->phone->device, BULKIN, (char*)connection->header, sizeof(usbmux_tcp_header), 800);
+ bytes = usb_bulk_read(client->phone->device, BULKIN, (char*)client->header, sizeof(usbmux_tcp_header), 800);
if(debug && bytes < 0)
printf("get_iPhone(): when reading, libusb gave me the error: %s\n", usb_strerror());
- delete_connection(connection);
+ delete_connection(client);
}
+
/** Sends the given data over the selected connection.
- *
- * @param connection The connection we're sending data on.
+ *
+ * @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.
*
* @return The number of bytes sent, minus the header (28), or -1 on error.
*/
-int mux_send(usbmux_connection *connection, const char *data, uint32 datalen) {
- if (!connection->phone || !connection || !data || datalen == 0) return -1;
- // connection->scnt and connection->ocnt should already be in host notation...
+
+int iphone_mux_send ( iphone_umux_client_t client, const char *data, uint32_t datalen ) {
+ if (!client->phone || !client || !data || datalen == 0) return -1;
+ // client->scnt and client->ocnt should already be in host notation...
// we don't need to change them juuuust yet.
int bytes = 0;
if (debug) printf("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
- connection->header->length = htonl(sizeof(usbmux_tcp_header) + datalen);
- connection->header->length16 = htons(sizeof(usbmux_tcp_header) + datalen);
+ 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
- connection->header->scnt = htonl(connection->header->scnt);
- connection->header->ocnt = htonl(connection->header->ocnt);
+ client->header->scnt = htonl(client->header->scnt);
+ client->header->ocnt = htonl(client->header->ocnt);
// Concatenation of stuff in the buffer.
- memcpy(buffer, connection->header, sizeof(usbmux_tcp_header));
+ 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.
if (debug) printf("actually sending %zi bytes of data at %p\n", sizeof(usbmux_tcp_header)+datalen, buffer);
- bytes = send_to_phone(connection->phone, buffer, sizeof(usbmux_tcp_header)+datalen);
+ bytes = send_to_phone(client->phone, buffer, sizeof(usbmux_tcp_header)+datalen);
if (debug) printf("mux_send: sent %i bytes!\n", bytes);
// Now that we've sent it off, we can clean up after our sloppy selves.
if (debug) {
@@ -222,12 +230,12 @@ int mux_send(usbmux_connection *connection, const char *data, uint32 datalen) {
if (buffer) free(buffer);
// Re-calculate scnt and ocnt
- connection->header->scnt = ntohl(connection->header->scnt) + datalen;
- connection->header->ocnt = ntohl(connection->header->ocnt);
+ client->header->scnt = ntohl(client->header->scnt) + datalen;
+ client->header->ocnt = ntohl(client->header->ocnt);
// Revert lengths
- connection->header->length = ntohl(connection->header->length);
- connection->header->length16 = ntohs(connection->header->length16);
+ client->header->length = ntohl(client->header->length);
+ client->header->length16 = ntohs(client->header->length16);
// Now return the bytes.
if (bytes < sizeof(usbmux_tcp_header)+datalen) {
@@ -247,52 +255,52 @@ int mux_send(usbmux_connection *connection, const char *data, uint32 datalen) {
*
* @return How many bytes were read, or -1 if something bad happens.
*/
-int mux_recv(usbmux_connection *connection, char *data, uint32 datalen) {
+int iphone_mux_recv ( iphone_umux_client_t client, char *data, uint32_t datalen ) {
/*
* Order of operation:
- * 1.) Check if the connection has a pre-received buffer.
+ * 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 connection the ports belong to and fill that connection's buffer, then return mux_recv with the same args to try again.
+ * 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.
*/
if (debug) printf("mux_recv: datalen == %i\n", datalen);
int bytes = 0, i = 0, complex = 0, offset = 0;
char *buffer = NULL;
usbmux_tcp_header *header = NULL;
- if (connection->recv_buffer) {
- if (connection->r_len >= datalen) {
- memcpy(data, connection->recv_buffer, datalen);
- if (connection->r_len == datalen) {
+ if (client->recv_buffer) {
+ if (client->r_len >= datalen) {
+ memcpy(data, client->recv_buffer, datalen);
+ if (client->r_len == datalen) {
// reset everything
- free(connection->recv_buffer);
- connection->r_len = 0;
- connection->recv_buffer = NULL;
+ free(client->recv_buffer);
+ client->r_len = 0;
+ client->recv_buffer = NULL;
} else {
- buffer = (char*)malloc(sizeof(char) * (connection->r_len - datalen));
- memcpy(buffer, connection->recv_buffer+datalen, (connection->r_len - datalen));
- connection->r_len -= datalen;
- free(connection->recv_buffer);
- connection->recv_buffer = buffer;
+ 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.
return datalen;
} else {
- memcpy(data, connection->recv_buffer, connection->r_len);
- free(connection->recv_buffer); // don't need to deal with anymore, but...
- offset = connection->r_len; // see #2b, above
- connection->r_len = 0;
+ memcpy(data, client->recv_buffer, client->r_len);
+ free(client->recv_buffer); // don't need to deal with anymore, but...
+ 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(connection->phone, buffer, 131072);
+ bytes = recv_from_phone(client->phone, buffer, 131072);
if (bytes < 28) {
free(buffer);
if (debug) printf("mux_recv: Did not even get the header.\n");
@@ -300,10 +308,10 @@ int mux_recv(usbmux_connection *connection, char *data, uint32 datalen) {
}
header = (usbmux_tcp_header*)buffer;
- if (header->sport != connection->header->dport || header->dport != connection->header->sport) {
+ 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 < connections; i++) {
+ 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)));
@@ -312,7 +320,7 @@ int mux_recv(usbmux_connection *connection, char *data, uint32 datalen) {
free(connlist[i]->recv_buffer);
}
connlist[i]->r_len += bytes - 28;
- //connlist[i]->recv_buffer = (char*)realloc(connlist[i]->recv_buffer, sizeof(char) * connection->r_len); // grow their buffer
+ //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);
@@ -324,7 +332,7 @@ int mux_recv(usbmux_connection *connection, char *data, uint32 datalen) {
// Free our buffer and continue.
free(buffer);
buffer = NULL;
- return mux_recv(connection, data, datalen); // recurse back in to try again
+ return mux_recv(client, data, datalen); // recurse back in to try again
}
// The packet was absolutely meant for us if it hits this point.
@@ -333,18 +341,18 @@ int mux_recv(usbmux_connection *connection, char *data, uint32 datalen) {
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 = connection->r_len + (bytes-28) - datalen;
- connection->recv_buffer = (char*)realloc(connection->recv_buffer, (sizeof(char) * complex));
- connection->r_len = complex;
- complex = connection->r_len - (bytes-28) - datalen;
- memcpy(connection->recv_buffer+complex, buffer+28+datalen, (bytes-28) - datalen);
+ 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);
- connection->header->ocnt += bytes-28;
+ client->header->ocnt += bytes-28;
return datalen;
} else {
// Fill the data with what we have, and just return.
memcpy(data+offset, buffer+28, bytes-28); // data+offset: see #2b, above
- connection->header->ocnt += bytes-28;
+ client->header->ocnt += bytes-28;
free(buffer);
return (bytes-28);
}