From e1751b8c02822da3881b41a8e07a36665a163130 Mon Sep 17 00:00:00 2001 From: Nikias Bassen Date: Sun, 12 Apr 2009 13:09:25 +0200 Subject: better error handling, some cleanup, and changed confusing struct/variable naming. --- iphone.c | 49 ++++++++++++++---------- iphone.h | 3 +- main.c | 128 +++++++++++++++++++++++++++------------------------------------ 3 files changed, 86 insertions(+), 94 deletions(-) diff --git a/iphone.c b/iphone.c index ad9dafd..5cceb95 100644 --- a/iphone.c +++ b/iphone.c @@ -114,7 +114,13 @@ static int clients = 0; /** */ -int toto_debug = 1; +int toto_debug = 0; + +void iphone_set_debug(int e) +{ + toto_debug = e; +} + void log_debug_msg(const char *format, ...) { #ifndef STRIP_DEBUG_CODE @@ -518,13 +524,11 @@ int send_to_phone(iphone_device_t phone, char *data, int datalen) */ int recv_from_phone_timeout(iphone_device_t phone, char *data, int datalen, int timeoutmillis) { - if (!phone) - return -1; int bytes = 0; if (!phone) - return -1; - log_debug_msg("recv_from_phone(): attempting to receive %i bytes\n", datalen); + return -EINVAL; + //log_debug_msg("recv_from_phone(): attempting to receive %i bytes\n", datalen); bytes = usb_bulk_read(phone->device, BULKIN, data, datalen, timeoutmillis); if (bytes < 0) { @@ -534,6 +538,7 @@ int recv_from_phone_timeout(iphone_device_t phone, char *data, int datalen, int if (bytes == -ETIMEDOUT) { // ignore this. it just means timeout reached before we // picked up any data. no problem. + return 0; } else { fprintf(stderr, "recv_from_phone(): libusb gave me the error %d: %s (%s)\n", bytes, usb_strerror(), @@ -541,7 +546,7 @@ int recv_from_phone_timeout(iphone_device_t phone, char *data, int datalen, int log_debug_msg("recv_from_phone(): libusb gave me the error %d: %s (%s)\n", bytes, usb_strerror(), strerror(-bytes)); } - return -1; + return bytes; } #ifdef DEBUG @@ -736,7 +741,7 @@ iphone_error_t iphone_mux_new_client(iphone_device_t device, uint16_t src_port, 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)); + log_debug_msg("%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; @@ -842,7 +847,7 @@ iphone_error_t iphone_mux_send(iphone_umux_client_t client, const char *data, ui 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)); + log_debug_msg("%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) @@ -907,9 +912,9 @@ uint32 append_receive_buffer(iphone_umux_client_t client, char* packet) // falls on our responsibility because we are the ones reading in // feedback. if (client->header->scnt == 0 && client->header->ocnt == 0 ) { - fprintf(stdout, "client is still waiting for handshake.\n"); + log_debug_msg("client is still waiting for handshake.\n"); if (header->tcp_flags == (TCP_SYN | TCP_ACK)) { - fprintf(stdout, "yes, got syn+ack ; replying with ack.\n"); + log_debug_msg("yes, got syn+ack ; replying with ack.\n"); client->header->tcp_flags = TCP_ACK; client->header->length = sizeof(usbmux_tcp_header); client->header->length16 = sizeof(usbmux_tcp_header); @@ -918,9 +923,9 @@ uint32 append_receive_buffer(iphone_umux_client_t client, char* packet) 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)); + log_debug_msg("%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__); + log_debug_msg("%s: error when pushing to usb...\n", __func__); } // need to revert some of the fields back to host notation. ntoh_header(client->header); @@ -929,7 +934,7 @@ uint32 append_receive_buffer(iphone_umux_client_t client, char* packet) client->error = IPHONE_E_ECONNABORTED; // woah... this connection failed us. // TODO: somehow signal that this stream is a no-go. - fprintf(stderr, "WOAH! client failed to get proper syn+ack.\n"); + log_debug_msg("WOAH! client failed to get proper syn+ack.\n"); } } @@ -1002,7 +1007,7 @@ uint32 append_receive_buffer(iphone_umux_client_t client, char* packet) // ensure there is enough space, either by first malloc or realloc if (datalen > 0) { - fprintf(stderr, "%s: putting %d bytes into client's recv_buffer\n", __func__, datalen); + log_debug_msg("%s: putting %d bytes into client's recv_buffer\n", __func__, datalen); if (client->r_len == 0) dobroadcast = 1; if (client->recv_buffer == NULL) { @@ -1061,13 +1066,14 @@ iphone_umux_client_t find_client(usbmux_tcp_header* recv_header) /** pull in a big USB bulk packet and distribute it to queues appropriately. */ -void iphone_mux_pullbulk(iphone_device_t phone) +int iphone_mux_pullbulk(iphone_device_t phone) { if (!phone) { fprintf(stderr, "iphone_mux_pullbulk: invalid argument\n"); - return; + return -EINVAL; } + int res = 0; static const int DEFAULT_CAPACITY = 128*1024; if (phone->usbReceive.buffer == NULL) { phone->usbReceive.capacity = DEFAULT_CAPACITY; @@ -1080,6 +1086,7 @@ void iphone_mux_pullbulk(iphone_device_t phone) // pull in content, note that the amount we can pull is capacity minus leftover int readlen = recv_from_phone_timeout(phone, cursor, phone->usbReceive.capacity - phone->usbReceive.leftover, 5000); if (readlen < 0) { + res = readlen; //fprintf(stderr, "recv_from_phone_timeout gave us an error.\n"); readlen = 0; } @@ -1099,24 +1106,24 @@ void iphone_mux_pullbulk(iphone_device_t phone) if (phone->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)); + log_debug_msg("%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); if (phone->usbReceive.leftover < packetlen) { - printf("%s: not enough data to construct a full packet\n", __func__); + fprintf(stderr, "%s: not enough data to construct a full packet\n", __func__); break; } // ok... find the client this packet will get stuffed to. iphone_umux_client_t client = find_client(header); if (client == NULL) { - fprintf(stderr, "WARNING: client for packet cannot be found. dropping packet.\n"); + log_debug_msg("WARNING: client for packet cannot be found. dropping packet.\n"); } else { // stuff the data - fprintf(stderr, "%s: found client, calling append_receive_buffer\n", __func__); + log_debug_msg("%s: found client, calling append_receive_buffer\n", __func__); append_receive_buffer(client, cursor); } @@ -1141,6 +1148,8 @@ void iphone_mux_pullbulk(iphone_device_t phone) phone->usbReceive.buffer = newbuff; phone->usbReceive.capacity = DEFAULT_CAPACITY; } + + return res; } /** diff --git a/iphone.h b/iphone.h index e132cd5..fcef32a 100644 --- a/iphone.h +++ b/iphone.h @@ -50,6 +50,7 @@ #define IPHONE_E_ETIMEDOUT -ETIMEDOUT #define IPHONE_E_ECONNREFUSED -ECONNREFUSED +void iphone_set_debug(int e); typedef int16_t iphone_error_t; @@ -72,7 +73,7 @@ iphone_error_t iphone_mux_send(iphone_umux_client_t client, const char *data, ui iphone_error_t iphone_mux_recv(iphone_umux_client_t client, char *data, uint32_t datalen, uint32_t * recv_bytes); iphone_error_t iphone_mux_recv_timeout(iphone_umux_client_t client, char *data, uint32_t datalen, uint32_t * recv_bytes, int timeout); -void iphone_mux_pullbulk(iphone_device_t phone); +int iphone_mux_pullbulk(iphone_device_t phone); iphone_error_t iphone_mux_get_error(iphone_umux_client_t client); diff --git a/main.c b/main.c index c0bb340..6b1b6ce 100644 --- a/main.c +++ b/main.c @@ -55,7 +55,7 @@ static int verbose = DEBUG_LEVEL; static int foreground = 0; static int exit_on_no_devices = 0; -struct device_use_info { +struct device_info { uint32_t device_id; iphone_device_t phone; int use_count; @@ -78,11 +78,11 @@ struct client_data { int handler_dead; int connected; iphone_umux_client_t muxclient; - struct device_use_info *duinfo; + struct device_info *dev; }; -static struct device_use_info **device_use_list = NULL; -static int device_use_count = 0; +static struct device_info **devices = NULL; +static int device_count = 0; static pthread_mutex_t usbmux_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t usb_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -223,7 +223,7 @@ static void *usbmuxd_client_reader_thread(void *arg) cdata->reader_dead = 0; - if (verbose >= 2) fprintf(stderr, "%s[%d:%d]: started\n", __func__, cdata->duinfo->device_id, cdata->duinfo->use_count); + if (verbose >= 2) fprintf(stderr, "%s[%d:%d]: started\n", __func__, cdata->dev->device_id, cdata->dev->use_count); while (!quit_flag && !cdata->reader_quit) { result = check_fd(cdata->socket, FD_WRITE, DEFAULT_TIMEOUT); @@ -237,7 +237,7 @@ static void *usbmuxd_client_reader_thread(void *arg) rlen = 0; err = iphone_mux_recv_timeout(cdata->muxclient, rbuffer, rbuffersize, &rlen, DEFAULT_TIMEOUT); if (err != 0) { - if (verbose >= 2) fprintf(stderr, "%s[%d:%d]: encountered USB read error: %d\n", __func__, cdata->duinfo->device_id, cdata->duinfo->use_count, err); + if (verbose >= 2) fprintf(stderr, "%s[%d:%d]: encountered USB read error: %d\n", __func__, cdata->dev->device_id, cdata->dev->use_count, err); break; } @@ -261,7 +261,7 @@ static void *usbmuxd_client_reader_thread(void *arg) fsync(cdata->socket); } - if (verbose >= 2) fprintf(stderr, "%s[%d:%d]: terminated\n", __func__, cdata->duinfo->device_id, cdata->duinfo->use_count); + if (verbose >= 2) fprintf(stderr, "%s[%d:%d]: terminated\n", __func__, cdata->dev->device_id, cdata->dev->use_count); cdata->reader_dead = 1; @@ -358,7 +358,7 @@ static void *usbmuxd_client_handler_thread(void *arg) cdata = (struct client_data*)arg; - if (verbose >= 2) fprintf(stderr, "%s[%d:%d]: started\n", __func__, cdata->duinfo->device_id,cdata->duinfo->use_count); + if (verbose >= 2) fprintf(stderr, "%s[%d:%d]: started\n", __func__, cdata->dev->device_id,cdata->dev->use_count); if (usbmuxd_handleConnectResult(cdata)) { if (verbose >= 3) fprintf(stderr, "handleConnectResult: Error\n"); @@ -391,20 +391,20 @@ static void *usbmuxd_client_handler_thread(void *arg) break; } if (len < 0) { - if (verbose >= 2) fprintf(stderr, "%s[%d:%d]: Error: recv: %s\n", __func__, cdata->duinfo->device_id, cdata->duinfo->use_count, strerror(errno)); + if (verbose >= 2) fprintf(stderr, "%s[%d:%d]: Error: recv: %s\n", __func__, cdata->dev->device_id, cdata->dev->use_count, strerror(errno)); break; } cursor = buffer; - pthread_mutex_lock(&cdata->duinfo->writer_mutex); + pthread_mutex_lock(&cdata->dev->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) { - if (verbose >= 2) fprintf(stderr, "%s[%d:%d]: USB write error: %d\n", __func__, cdata->duinfo->device_id, cdata->duinfo->use_count, err); + if (verbose >= 2) fprintf(stderr, "%s[%d:%d]: USB write error: %d\n", __func__, cdata->dev->device_id, cdata->dev->use_count, err); len = -1; break; } @@ -414,7 +414,7 @@ static void *usbmuxd_client_handler_thread(void *arg) // advance cursor appropiately. cursor += wlen; } while ((len > 0) && !quit_flag); - pthread_mutex_unlock(&cdata->duinfo->writer_mutex); + pthread_mutex_unlock(&cdata->dev->writer_mutex); if (len < 0) { break; } @@ -422,7 +422,7 @@ static void *usbmuxd_client_handler_thread(void *arg) leave: // cleanup - if (verbose >= 3) fprintf(stderr, "%s[%d:%d]: terminating\n", __func__, cdata->duinfo->device_id, cdata->duinfo->use_count); + if (verbose >= 3) fprintf(stderr, "%s[%d:%d]: terminating\n", __func__, cdata->dev->device_id, cdata->dev->use_count); if (cdata->reader != 0) { cdata->reader_quit = 1; pthread_join(cdata->reader, NULL); @@ -430,7 +430,7 @@ leave: cdata->handler_dead = 1; - if (verbose >= 3) fprintf(stderr, "%s[%d:%d]: terminated\n", __func__, cdata->duinfo->device_id, cdata->duinfo->use_count); + if (verbose >= 3) fprintf(stderr, "%s[%d:%d]: terminated\n", __func__, cdata->dev->device_id, cdata->dev->use_count); return NULL; } @@ -440,14 +440,15 @@ leave: */ static void *usbmuxd_bulk_reader_thread(void *arg) { - struct device_use_info *cur_dev; + struct device_info *cur_dev; + int err; if (!arg) { if (verbose >= 3) fprintf(stderr, "%s: Invalid client_data provided\n", __func__); return NULL; } - cur_dev = (struct device_use_info*)arg; + cur_dev = (struct device_info*)arg; if (verbose >= 5) fprintf(stderr, "%s: started\n", __func__); @@ -460,11 +461,10 @@ static void *usbmuxd_bulk_reader_thread(void *arg) } pthread_mutex_unlock(&cur_dev->mutex); - iphone_mux_pullbulk(cur_dev->phone); - //err = iphone_mux_get_error(cdata->muxclient); - //if (err != IPHONE_E_SUCCESS) { - // break; - //} + if ((err = iphone_mux_pullbulk(cur_dev->phone)) < 0) { + if (verbose >= 1) fprintf(stderr, "%s: error %d when reading from device\n", __func__, err); + break; + } } if (verbose >= 0) fprintf(stderr, "%s: terminated\n", __func__); @@ -495,7 +495,7 @@ static void *usbmuxd_client_init_thread(void *arg) // iphone_error_t err; iphone_device_t phone = NULL; - struct device_use_info *cur_dev = NULL; + struct device_info *cur_dev = NULL; if (!arg) { if (verbose >= 1) fprintf(stderr, "%s: invalid client_data provided!\n", __func__); @@ -608,13 +608,13 @@ connect: phone = NULL; cur_dev = NULL; // first check if we already have an open connection - if (device_use_list) { + if (devices) { pthread_mutex_lock(&usbmux_mutex); - for (i = 0; i < device_use_count; i++) { - if (device_use_list[i]) { - if (device_use_list[i]->device_id == c_req->device_id) { - device_use_list[i]->use_count++; - cur_dev = device_use_list[i]; + for (i = 0; i < device_count; i++) { + if (devices[i]) { + if (devices[i]->device_id == c_req->device_id) { + devices[i]->use_count++; + cur_dev = devices[i]; phone = cur_dev->phone; break; } @@ -635,10 +635,11 @@ connect: } pthread_mutex_unlock(&usb_mutex); - // add to device list + // create device object + pthread_mutex_lock(&usbmux_mutex); if (verbose >= 3) fprintf(stderr, "%s: add to device list\n", __func__); - cur_dev = (struct device_use_info*)malloc(sizeof(struct device_use_info)); - memset(cur_dev, 0, sizeof(struct device_use_info)); + cur_dev = (struct device_info*)malloc(sizeof(struct device_info)); + memset(cur_dev, 0, sizeof(struct device_info)); cur_dev->use_count = 1; cur_dev->device_id = c_req->device_id; cur_dev->phone = phone; @@ -646,13 +647,13 @@ connect: pthread_mutex_init(&cur_dev->mutex, NULL); pthread_mutex_init(&cur_dev->writer_mutex, NULL); - if (verbose >= 3) fprintf(stderr, "%s: device_use_count = %d\n", __func__, device_use_count); + if (verbose >= 3) fprintf(stderr, "%s: device_count = %d\n", __func__, device_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) { - device_use_list[device_use_count] = cur_dev; - device_use_count++; + // add to list of devices + devices = (struct device_info**)realloc(devices, sizeof(struct device_info*) * (device_count+1)); + if (devices) { + devices[device_count] = cur_dev; + devices++; } pthread_mutex_unlock(&usbmux_mutex); } else { @@ -671,43 +672,22 @@ connect: } // start bulk reader thread (once per device) + pthread_mutex_lock(&cur_dev->mutex); if (cur_dev->bulk_reader == 0) { pthread_create(&cur_dev->bulk_reader, NULL, usbmuxd_bulk_reader_thread, cur_dev); } + pthread_mutex_unlock(&cur_dev->mutex); // start connection handler thread cdata->handler_dead = 0; cdata->tag = c_req->header.tag; - cdata->duinfo = cur_dev; + cdata->dev = cur_dev; if (pthread_create(&cdata->handler, NULL, usbmuxd_client_handler_thread, cdata) != 0) { if (verbose >= 3) fprintf(stderr, "%s: could not create usbmuxd_client_handler_thread!\n", __func__); cdata->handler = 0; goto leave; } - //sent_result = 0; - - // TODO: wait for connect result? - // if connect failed, don't run this loop: - - /* - // start reading data from the connected device - while (!quit_flag && !cdata->handler_dead) { - iphone_mux_pullbulk(cur_dev->phone); - err = iphone_mux_get_error(cdata->muxclient); - if (err != IPHONE_E_SUCCESS) { - break; - } - } - - if (!sent_result) { - //fprintf(stderr, "Sending error message %d tag %d\n", err, c_req.header.tag); - err = iphone_mux_get_error(cdata->muxclient); - //usbmuxd_send_result(cdata->socket, c_req.header.tag, err); - }*/ - - //fprintf(stderr, "%s: terminating\n", __func__); - // wait for handler thread to finish its work if (cdata->handler != 0) { pthread_join(cdata->handler, NULL); @@ -754,23 +734,23 @@ leave: free(cur_dev); cur_dev = NULL; pthread_mutex_lock(&usbmux_mutex); - if (device_use_count > 1) { - struct device_use_info **newlist; + if (device_count > 1) { + struct device_info **newlist; int j; - newlist = (struct device_use_info**)malloc(sizeof(struct device_use_info*) * device_use_count-1); - for (i = 0; i < device_use_count; i++) { - if (device_use_list[i] != NULL) { - newlist[j++] = device_use_list[i]; + newlist = (struct device_info**)malloc(sizeof(struct device_info*) * device_count-1); + for (i = 0; i < device_count; i++) { + if (devices[i] != NULL) { + newlist[j++] = devices[i]; } } - free(device_use_list); - device_use_list = newlist; - device_use_count--; + free(devices); + devices = newlist; + device_count--; } else { - free(device_use_list); - device_use_list = NULL; - device_use_count = 0; + free(devices); + devices = NULL; + device_count = 0; } pthread_mutex_unlock(&usbmux_mutex); } @@ -1013,6 +993,8 @@ int main(int argc, char **argv) chmod(USBMUXD_SOCKET_FILE, 0666); + if (verbose >= 3) iphone_set_debug(1); + if (!foreground) { if (daemonize() < 0) { fprintf(stderr, "usbmuxd: FATAL: Could not daemonize!\n"); -- cgit v1.1-32-gdbae