summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2009-02-25 18:09:19 +0100
committerGravatar Nikias Bassen2009-02-25 18:09:19 +0100
commit6e2946da89ce8c44ac2b78e49c8fc934974d021d (patch)
tree33c63b8b7a008695df606190195b9baf4a59f350
parent97e6c8b7bb89c7f08ad46050598c15a55ea3f436 (diff)
downloadusbmuxd-6e2946da89ce8c44ac2b78e49c8fc934974d021d.tar.gz
usbmuxd-6e2946da89ce8c44ac2b78e49c8fc934974d021d.tar.bz2
big endian fix and some improvements, now multi-client capable
-rw-r--r--iphone.c162
-rw-r--r--usbmuxd.c61
2 files changed, 175 insertions, 48 deletions
diff --git a/iphone.c b/iphone.c
index 9035be9..bf0d5de 100644
--- a/iphone.c
+++ b/iphone.c
@@ -132,6 +132,61 @@ void log_debug_msg(const char *format, ...)
#endif
}
+#ifdef DEBUG
+/**
+ * for debugging purposes.
+ */
+static void print_buffer(const char *data, const int length)
+{
+ int i;
+ int j;
+ unsigned char c;
+
+ for(i=0; i<length; i+=16) {
+ printf("%04x: ", i);
+ for (j=0;j<16;j++) {
+ if (i+j >= length) {
+ printf(" ");
+ continue;
+ }
+ printf("%02hhx ", *(data+i+j));
+ }
+ printf(" | ");
+ for(j=0;j<16;j++) {
+ if (i+j >= length)
+ break;
+ c = *(data+i+j);
+ if ((c < 32) || (c > 127)) {
+ printf(".");
+ continue;
+ }
+ printf("%c", c);
+ }
+ printf("\n");
+ }
+ printf("\n");
+}
+#endif
+
+void hton_header(usbmux_tcp_header *hdr)
+{
+ if (hdr) {
+ hdr->length = htonl(hdr->length);
+ hdr->scnt = htonl(hdr->scnt);
+ hdr->ocnt = htonl(hdr->ocnt);
+ hdr->length16 = htons(hdr->length16);
+ }
+}
+
+void ntoh_header(usbmux_tcp_header *hdr)
+{
+ if (hdr) {
+ hdr->length = ntohl(hdr->length);
+ hdr->scnt = ntohl(hdr->scnt);
+ hdr->ocnt = ntohl(hdr->ocnt);
+ hdr->length16 = ntohs(hdr->length16);
+ }
+}
/** Creates a USBMux header containing version information
*
@@ -392,6 +447,12 @@ int send_to_phone(iphone_device_t phone, char *data, int datalen)
int timeout = 1000;
int retrycount = 0;
int bytes = 0;
+
+#ifdef DEBUG
+ printf("===============================\n%s: trying to send\n", __func__);
+ print_buffer(data, datalen);
+ printf("===============================\n");
+#endif
do {
if (retrycount > 3) {
fprintf(stderr, "EPIC FAIL! aborting on retry count overload.\n");
@@ -426,6 +487,14 @@ int send_to_phone(iphone_device_t phone, char *data, int datalen)
}
while(0); // fall out
+#ifdef DEBUG
+ if (bytes > 0) {
+ printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
+ printf("%s: sent to phone\n", __func__);
+ print_buffer(data, bytes);
+ printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
+ }
+#endif
return bytes;
}
@@ -459,6 +528,15 @@ int recv_from_phone_timeout(iphone_device_t phone, char *data, int datalen, int
return -1;
}
+#ifdef DEBUG
+ if (bytes > 0) {
+ printf("<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
+ printf("%s: received from phone:\n", __func__);
+ print_buffer(data, bytes);
+ printf("<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
+ }
+#endif
+
return bytes;
}
@@ -621,8 +699,8 @@ iphone_error_t iphone_mux_new_client(iphone_device_t device, uint16_t src_port,
// send TCP syn
if (new_connection && new_connection->header) {
new_connection->header->tcp_flags = TCP_SYN;
- new_connection->header->length = htonl(new_connection->header->length);
- new_connection->header->length16 = htons(new_connection->header->length16);
+ new_connection->header->length = new_connection->header->length;
+ new_connection->header->length16 = new_connection->header->length16;
new_connection->header->scnt = 0;
new_connection->header->ocnt = 0;
new_connection->phone = device;
@@ -635,6 +713,8 @@ iphone_error_t iphone_mux_new_client(iphone_device_t device, uint16_t src_port,
new_connection->wr_window = 0;
add_connection(new_connection);
new_connection->error = IPHONE_E_SUCCESS;
+ hton_header(new_connection->header);
+ printf("%s: send_to_phone (%d --> %d)\n", __func__, ntohs(new_connection->header->sport), ntohs(new_connection->header->dport));
if (send_to_phone(device, (char *) new_connection->header, sizeof(usbmux_tcp_header)) >= 0) {
*client = new_connection;
return IPHONE_E_SUCCESS;
@@ -661,11 +741,10 @@ iphone_error_t iphone_mux_free_client(iphone_umux_client_t client)
pthread_mutex_lock(&client->mutex);
client->header->tcp_flags = TCP_FIN;
- client->header->length = htonl(0x1C);
- client->header->scnt = htonl(client->header->scnt);
- client->header->ocnt = htonl(client->header->ocnt);
+ client->header->length = 0x1C;
client->header->window = 0;
- client->header->length16 = htons(0x1C);
+ client->header->length16 = 0x1C;
+ hton_header(client->header);
int bytes = 0;
bytes = usb_bulk_write(client->phone->device, BULKOUT, (char *) client->header, sizeof(usbmux_tcp_header), 800);
@@ -731,31 +810,29 @@ iphone_error_t iphone_mux_send(iphone_umux_client_t client, const char *data, ui
// client->scnt and client->ocnt should already be in host notation...
// we don't need to change them juuuust yet.
char *buffer = (char *) malloc(blocksize + 2); // allow 2 bytes of safety padding
- // Set the length and pre-emptively htonl/htons it
- client->header->length = htonl(blocksize);
- client->header->length16 = htons(blocksize);
+ // Set the length
+ client->header->length = blocksize;
+ client->header->length16 = blocksize;
- // Put scnt and ocnt into big-endian notation
- client->header->scnt = htonl(client->header->scnt);
- client->header->ocnt = htonl(client->header->ocnt);
+ // Put header into big-endian notation
+ hton_header(client->header);
// Concatenation of stuff in the buffer.
memcpy(buffer, client->header, sizeof(usbmux_tcp_header));
memcpy(buffer + sizeof(usbmux_tcp_header), data, datalen);
+ printf("%s: send_to_phone(%d --> %d)\n", __func__, ntohs(client->header->sport), ntohs(client->header->dport));
sendresult = send_to_phone(client->phone, buffer, blocksize);
// Now that we've sent it off, we can clean up after our sloppy selves.
if (buffer)
free(buffer);
+ // revert header fields that have been swapped before trying to send
+ ntoh_header(client->header);
+
// update counts ONLY if the send succeeded.
if (sendresult == blocksize) {
- // 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);
-
+ // Re-calculate scnt
+ client->header->scnt += datalen;
client->wr_window -= blocksize;
}
@@ -812,20 +889,19 @@ uint32 append_receive_buffer(iphone_umux_client_t client, char* packet)
if (header->tcp_flags == (TCP_SYN | TCP_ACK)) {
fprintf(stdout, "yes, got syn+ack ; replying with ack.\n");
client->header->tcp_flags = TCP_ACK;
- client->header->length = htonl(sizeof(usbmux_tcp_header));
- client->header->length16 = htons(sizeof(usbmux_tcp_header));
- client->header->scnt = htonl(client->header->scnt + 1);
+ client->header->length = sizeof(usbmux_tcp_header);
+ client->header->length16 = sizeof(usbmux_tcp_header);
+ client->header->scnt += 1;
client->header->ocnt = header->ocnt;
+ hton_header(client->header);
// push it to USB
// TODO: need to check for error in the send here.... :(
+ printf("%s: send_to_phone (%d --> %d)\n", __func__, ntohs(client->header->sport), ntohs(client->header->dport));
if (send_to_phone(client->phone, (char *)client->header, sizeof(usbmux_tcp_header)) <= 0) {
fprintf(stdout, "%s: error when pushing to usb...\n", __func__);
}
// need to revert some of the fields back to host notation.
- client->header->scnt = ntohl(client->header->scnt);
- client->header->ocnt = ntohl(client->header->ocnt);
- client->header->length = ntohl(client->header->length);
- client->header->length16 = ntohs(client->header->length16);
+ ntoh_header(client->header);
}
else {
client->error = IPHONE_E_ECONNABORTED;
@@ -843,7 +919,33 @@ uint32 append_receive_buffer(iphone_umux_client_t client, char* packet)
// larger number.
if (header->tcp_flags & TCP_RST) {
client->error = IPHONE_E_ECONNRESET;
- fprintf(stderr, "peer sent connection reset. setting error: %d\n", client->error);
+
+ if (datalen > 0) {
+ char e_msg[128];
+ e_msg[0] = 0;
+ if (datalen > 1) {
+ memcpy(e_msg, data+1, datalen-1);
+ e_msg[datalen-1] = 0;
+ }
+ // fetch the message
+ switch(data[0]) {
+ case 0:
+ // this is not an error, it's just a status message.
+ fprintf(stdout, "received status message: %s\n", e_msg);
+ datalen = 0;
+ break;
+ case 1:
+ fprintf(stderr, "received error message: %s\n", e_msg);
+ datalen = 0;
+ break;
+ default:
+ fprintf(stderr, "received unknown message (type 0x%02x): %s\n", data[0], e_msg);
+ //datalen = 0; // <-- we let this commented out for testing
+ break;
+ }
+ } else {
+ fprintf(stderr, "peer sent connection reset. setting error: %d\n", client->error);
+ }
}
// the packet's ocnt tells us how much of our data the device has received.
@@ -954,7 +1056,7 @@ void iphone_mux_pullbulk(iphone_device_t phone)
readlen = 0;
}
if (readlen > 0) {
- //fprintf(stdout, "recv_from_phone_timeout pulled an extra %d bytes\n", readlen);
+ //fprintf(stdout, "recv_from_phone_timeout pulled an extra %d bytes\n", readlen);
}
// the amount of content we have to work with is the remainder plus
@@ -968,7 +1070,9 @@ void iphone_mux_pullbulk(iphone_device_t phone)
// check if there's even sufficient data to decode a header
if (usbReceive.leftover < HEADERLEN) break;
usbmux_tcp_header *header = (usbmux_tcp_header *) cursor;
-
+
+ printf("%s: recv_from_phone_timeout (%d --> %d)\n", __func__, ntohs(header->sport), ntohs(header->dport));
+
// now that we have a header, check if there is sufficient data
// to construct a full packet, including its data
uint32 packetlen = ntohl(header->length);
diff --git a/usbmuxd.c b/usbmuxd.c
index 8f2a6e9..0f4339c 100644
--- a/usbmuxd.c
+++ b/usbmuxd.c
@@ -47,6 +47,12 @@
static int quit_flag = 0;
static int fsock = -1;
+struct device_use_info {
+ uint32_t device_id;
+ iphone_device_t phone;
+ int use_count;
+};
+
struct client_data {
volatile int dead;
int socket;
@@ -58,12 +64,7 @@ struct client_data {
int reader_dead;
int handler_dead;
iphone_umux_client_t muxclient;
-};
-
-struct device_use_info {
- uint32_t device_id;
- iphone_device_t phone;
- int use_count;
+ struct device_use_info *duinfo;
};
static struct device_use_info **device_use_list = NULL;
@@ -71,6 +72,18 @@ static int device_use_count = 0;
static pthread_mutex_t usbmux_mutex = PTHREAD_MUTEX_INITIALIZER;
/**
+ * mutex for mutual exclusion of calling the iphone_mux_send function
+ * TODO: I don't know if we really need this?
+ */
+static pthread_mutex_t writer_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/**
+ * mutex to keep the reader threads from reading partial packages
+ */
+static pthread_mutex_t reader_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+#ifdef DEBUG
+/**
* for debugging purposes.
*/
static void print_buffer(const char *data, const int length)
@@ -103,6 +116,7 @@ static void print_buffer(const char *data, const int length)
}
printf("\n");
}
+#endif
/**
* Read incoming usbmuxd packet. If the packet is larger than
@@ -192,7 +206,7 @@ static void *usbmuxd_client_reader_thread(void *arg)
cdata->reader_dead = 0;
- fprintf(stdout, "%s: started\n", __func__);
+ fprintf(stdout, "%s[%d:%d]: started\n", __func__, cdata->duinfo->device_id, cdata->duinfo->use_count);
while (!quit_flag && !cdata->reader_quit) {
result = check_fd(cdata->socket, fdwrite, DEFAULT_TIMEOUT);
@@ -204,9 +218,11 @@ static void *usbmuxd_client_reader_thread(void *arg)
}
rlen = 0;
+ //pthread_mutex_lock(&usbmux_mutex);
err = iphone_mux_recv_timeout(cdata->muxclient, rbuffer, rbuffersize, &rlen, DEFAULT_TIMEOUT);
+ //pthread_mutex_unlock(&usbmux_mutex);
if (err != 0) {
- fprintf(stderr, "%s: encountered USB read error: %d\n", __func__, err);
+ fprintf(stderr, "%s[%d:%d]: encountered USB read error: %d\n", __func__, cdata->duinfo->device_id, cdata->duinfo->use_count, err);
break;
}
@@ -221,7 +237,7 @@ static void *usbmuxd_client_reader_thread(void *arg)
fsync(cdata->socket);
}
- fprintf(stdout, "%s: terminated\n", __func__);
+ fprintf(stdout, "%s[%d:%d]: terminated\n", __func__, cdata->duinfo->device_id, cdata->duinfo->use_count);
cdata->reader_dead = 1;
@@ -268,7 +284,6 @@ static int usbmuxd_handleConnectResult(struct client_data *cdata)
return err;
} else {
if (rlen > 0) {
- //print_buffer(buffer, rlen);
if ((buffer[0] == 1) && (rlen > 20) && !memcmp(buffer+1, "handleConnectResult:", 20)) {
// hm... we got an error message!
buffer[rlen] = 0;
@@ -319,7 +334,7 @@ static void *usbmuxd_client_handler_thread(void *arg)
cdata = (struct client_data*)arg;
- fprintf(stdout, "%s: started\n", __func__);
+ fprintf(stdout, "%s[%d:%d]: started\n", __func__, cdata->duinfo->device_id,cdata->duinfo->use_count);
if (usbmuxd_handleConnectResult(cdata)) {
goto leave;
@@ -349,18 +364,20 @@ static void *usbmuxd_client_handler_thread(void *arg)
break;
}
if (len < 0) {
- fprintf(stderr, "%s: Error: recv: %s\n", __func__, strerror(errno));
+ fprintf(stderr, "%s[%d:%d]: Error: recv: %s\n", __func__, cdata->duinfo->device_id, cdata->duinfo->use_count, strerror(errno));
break;
}
cursor = buffer;
+
+ pthread_mutex_lock(&writer_mutex);
do {
wlen = 0;
err = iphone_mux_send(cdata->muxclient, cursor, len, &wlen);
if (err == IPHONE_E_TIMEOUT) {
// some kind of timeout... just be patient and retry.
} else if (err != IPHONE_E_SUCCESS) {
- fprintf(stderr, "%s: USB write error: %d\n", __func__, err);
+ fprintf(stderr, "%s[%d:%d]: USB write error: %d\n", __func__, cdata->duinfo->device_id, cdata->duinfo->use_count, err);
len = -1;
break;
}
@@ -370,6 +387,7 @@ static void *usbmuxd_client_handler_thread(void *arg)
// advance cursor appropiately.
cursor += wlen;
} while ((len > 0) && !quit_flag);
+ pthread_mutex_unlock(&writer_mutex);
if (len < 0) {
break;
}
@@ -377,7 +395,7 @@ static void *usbmuxd_client_handler_thread(void *arg)
leave:
// cleanup
- fprintf(stdout, "%s: terminating\n", __func__);
+ fprintf(stdout, "%s[%d:%d]: terminating\n", __func__, cdata->duinfo->device_id, cdata->duinfo->use_count);
if (cdata->reader != 0) {
cdata->reader_quit = 1;
pthread_join(cdata->reader, NULL);
@@ -385,7 +403,7 @@ leave:
cdata->handler_dead = 1;
- fprintf(stdout, "%s: terminated\n", __func__);
+ fprintf(stdout, "%s[%d:%d]: terminated\n", __func__, cdata->duinfo->device_id, cdata->duinfo->use_count);
return NULL;
}
@@ -472,7 +490,9 @@ static void *usbmuxd_client_init_thread(void *arg)
//pthread_mutex_unlock(&usbmux_mutex);
}
+#ifdef DEBUG
print_buffer((char*)&dev_info_req, sizeof(dev_info_req));
+#endif
// send it
if (send_buf(cdata->socket, &dev_info_req, sizeof(dev_info_req)) <= 0) {
@@ -534,6 +554,8 @@ static void *usbmuxd_client_init_thread(void *arg)
cur_dev->device_id = c_req.device_id;
cur_dev->phone = phone;
+ fprintf(stdout, "%s: device_use_count = %d\n", __func__, device_use_count);
+
pthread_mutex_lock(&usbmux_mutex);
device_use_list = (struct device_use_info**)realloc(device_use_list, sizeof(struct device_use_info*) * (device_use_count+1));
if (device_use_list) {
@@ -559,6 +581,7 @@ static void *usbmuxd_client_init_thread(void *arg)
// start connection handler thread
cdata->handler_dead = 0;
cdata->tag = c_req.header.tag;
+ cdata->duinfo = cur_dev;
if (pthread_create(&cdata->handler, NULL, usbmuxd_client_handler_thread, cdata) != 0) {
fprintf(stderr, "%s: could not create usbmuxd_client_handler_thread!\n", __func__);
cdata->handler = 0;
@@ -569,13 +592,12 @@ static void *usbmuxd_client_init_thread(void *arg)
// start reading data from the connected device
while (!quit_flag && !cdata->handler_dead) {
+ pthread_mutex_lock(&reader_mutex);
iphone_mux_pullbulk(cur_dev->phone);
err = iphone_mux_get_error(cdata->muxclient);
+ pthread_mutex_unlock(&reader_mutex);
if (err != IPHONE_E_SUCCESS) {
break;
- /*} else if (!sent_result) {
- usbmuxd_send_result(cdata->socket, c_req.header.tag, 0);
- sent_result = 1;*/
}
}
@@ -630,6 +652,7 @@ leave:
}
cdata->dead = 1;
+ close(cdata->socket);
fprintf(stdout, "%s: terminated\n", __func__);
@@ -684,7 +707,7 @@ static void *usbmuxd_accept_thread(void *arg)
while (!quit_flag) {
// Check the file descriptor before accepting a connection.
// If no connection attempt is made, just repeat...
- result = check_fd(fsock, fdread, DEFAULT_TIMEOUT);
+ result = check_fd(fsock, fdread, 1000);
if (result <= 0) {
if (result == 0) {
// cleanup