From 365b6c9b208e483af751a43a9ccc8885553859ee Mon Sep 17 00:00:00 2001 From: Nikias Bassen Date: Fri, 27 Feb 2009 03:00:27 +0100 Subject: 1) Now, every device is only handled by one thread for bulk usb reading instead of one thread for each connection to the same device. 2) Removed usbmuxd_accept_thread and moved code into main() directly. --- main.c | 183 +++++++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 110 insertions(+), 73 deletions(-) diff --git a/main.c b/main.c index 9bcdece..5c67055 100644 --- a/main.c +++ b/main.c @@ -49,11 +49,13 @@ struct device_use_info { uint32_t device_id; iphone_device_t phone; int use_count; + pthread_t bulk_reader; + pthread_mutex_t mutex; /* mutex for mutual exclusion of calling the iphone_mux_send function * TODO: I don't know if we need really need this? */ pthread_mutex_t writer_mutex; /* mutex to keep the reader threads from reading partial packages */ - pthread_mutex_t reader_mutex; + //pthread_mutex_t reader_mutex; }; struct client_data { @@ -66,6 +68,7 @@ struct client_data { int reader_quit; int reader_dead; int handler_dead; + int connected; iphone_umux_client_t muxclient; struct device_use_info *duinfo; }; @@ -269,9 +272,9 @@ static int usbmuxd_handleConnectResult(struct client_data *cdata) } } else { result = 0; - pthread_mutex_lock(&cdata->duinfo->reader_mutex); + //pthread_mutex_lock(&cdata->duinfo->reader_mutex); err = iphone_mux_recv_timeout(cdata->muxclient, buffer, maxlen, &rlen, DEFAULT_TIMEOUT); - pthread_mutex_unlock(&cdata->duinfo->reader_mutex); + //pthread_mutex_unlock(&cdata->duinfo->reader_mutex); if (err != 0) { fprintf(stderr, "%s: encountered USB read error: %d\n", __func__, err); usbmuxd_send_result(cdata->socket, cdata->tag, -err); @@ -403,6 +406,46 @@ leave: return NULL; } +/** + * Thread performing usb_bulk_read from the connected device. + * One thread per device. Lives as long as the device is in use. + */ +static void *usbmuxd_bulk_reader_thread(void *arg) +{ + struct device_use_info *cur_dev; + + if (!arg) { + fprintf(stderr, "%s: Invalid client_data provided\n", __func__); + return NULL; + } + + cur_dev = (struct device_use_info*)arg; + + printf("%s: started\n", __func__); + + while (!quit_flag && cur_dev) { + + pthread_mutex_lock(&cur_dev->mutex); + if (cur_dev->use_count <= 0) { + pthread_mutex_unlock(&cur_dev->mutex); + break; + } + pthread_mutex_unlock(&cur_dev->mutex); + + //pthread_mutex_lock(&cur_dev->reader_mutex); + iphone_mux_pullbulk(cur_dev->phone); + //err = iphone_mux_get_error(cdata->muxclient); + //pthread_mutex_unlock(&cur_dev->reader_mutex); + //if (err != IPHONE_E_SUCCESS) { + // break; + //} + } + + printf("%s: terminated\n", __func__); + + return NULL; +} + /** * This thread is started when a new connection is accepted. * It performs the handshake, then waits for the connect packet and @@ -422,8 +465,8 @@ static void *usbmuxd_client_init_thread(void *arg) int found = 0; int res; int i; - int sent_result; - iphone_error_t err; +// int sent_result; +// iphone_error_t err; iphone_device_t phone; struct device_use_info *cur_dev = NULL; @@ -549,10 +592,12 @@ static void *usbmuxd_client_init_thread(void *arg) cur_dev->use_count = 1; cur_dev->device_id = c_req.device_id; cur_dev->phone = phone; - pthread_mutex_init(&cur_dev->reader_mutex, NULL); + pthread_mutex_init(&cur_dev->mutex, NULL); + //pthread_mutex_init(&cur_dev->reader_mutex, NULL); pthread_mutex_init(&cur_dev->writer_mutex, NULL); fprintf(stdout, "%s: device_use_count = %d\n", __func__, device_use_count); + pthread_create(&cur_dev->bulk_reader, NULL, usbmuxd_bulk_reader_thread, cur_dev); 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)); @@ -586,11 +631,12 @@ static void *usbmuxd_client_init_thread(void *arg) goto leave; } - sent_result = 0; + //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) { pthread_mutex_lock(&cur_dev->reader_mutex); @@ -606,14 +652,16 @@ static void *usbmuxd_client_init_thread(void *arg) //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(stdout, "%s: terminating\n", __func__); + //fprintf(stdout, "%s: terminating\n", __func__); // wait for handler thread to finish its work if (cdata->handler != 0) { pthread_join(cdata->handler, NULL); } + + fprintf(stdout, "%s: closing connection\n", __func__); // time to clean up if (cdata && cdata->muxclient) { // should be non-NULL @@ -621,16 +669,25 @@ static void *usbmuxd_client_init_thread(void *arg) } leave: + fprintf(stdout, "%s: terminating\n", __func__); + // this has to be freed only if it's not in use anymore as it closes // the USB connection if (cur_dev) { + pthread_mutex_lock(&cur_dev->mutex); if (cur_dev->use_count > 1) { + printf("%s: decreasing device use count\n", __func__); cur_dev->use_count--; + pthread_mutex_unlock(&cur_dev->mutex); } else { - iphone_free_device(cur_dev->phone); + printf("%s: last client disconnected, cleaning up\n", __func__); cur_dev->use_count = 0; - pthread_mutex_destroy(&cur_dev->reader_mutex); + pthread_mutex_unlock(&cur_dev->mutex); + pthread_join(cur_dev->bulk_reader, NULL); + iphone_free_device(cur_dev->phone); + //pthread_mutex_destroy(&cur_dev->reader_mutex); pthread_mutex_destroy(&cur_dev->writer_mutex); + pthread_mutex_destroy(&cur_dev->mutex); free(cur_dev); cur_dev = NULL; pthread_mutex_lock(&usbmux_mutex); @@ -683,30 +740,54 @@ static void clean_exit(int sig) } /** - * thread function that performs accept() and starts the required child - * threads to perform the rest of the communication stuff. + * main function. Initializes all stuff and then loops waiting in accept. */ -static void *usbmuxd_accept_thread(void *arg) +int main(int argc, char **argv) { + int foreground = 1; struct sockaddr_un c_addr; socklen_t len = sizeof(struct sockaddr_un); - struct client_data *cdata; + struct client_data *cdata = NULL; struct client_data **children = NULL; int children_capacity = DEFAULT_CHILDREN_CAPACITY; int i = 0; int result = 0; - int cnt; + int cnt = 0; + + fprintf(stdout, "usbmuxd: starting\n"); + + // TODO: Parameter checking. + + fsock = create_unix_socket(USBMUXD_SOCKET_FILE); + if (fsock < 0) { + fprintf(stderr, "Could not create socket, exiting\n"); + return -1; + } + + chmod(USBMUXD_SOCKET_FILE, 0666); + + if (!foreground) { + if (daemonize() < 0) { + exit(EXIT_FAILURE); + } + } + + // signal(SIGHUP, reload_conf); // none yet + signal(SIGINT, clean_exit); + signal(SIGQUIT, clean_exit); + signal(SIGTERM, clean_exit); + signal(SIGPIPE, SIG_IGN); // Reserve space for 10 clients which should be enough. If not, the // buffer gets enlarged later. children = (struct client_data**)malloc(sizeof(struct client_data*) * children_capacity); if (!children) { - fprintf(stderr, "%s: Out of memory when allocating memory for child threads. Terminating.\n", __func__); + fprintf(stderr, "usbmuxd: Out of memory when allocating memory for child threads. Terminating.\n"); exit(EXIT_FAILURE); } memset(children, 0, sizeof(struct client_data*) * children_capacity); - fprintf(stdout, "%s: waiting for connection\n", __func__); + fprintf(stdout, "usbmuxd: waiting for connection\n"); while (!quit_flag) { // Check the file descriptor before accepting a connection. // If no connection attempt is made, just repeat... @@ -718,7 +799,7 @@ static void *usbmuxd_accept_thread(void *arg) if (children[i]) { if (children[i]->dead != 0) { pthread_join(children[i]->thread, NULL); - fprintf(stdout, "%s: reclaimed client thread (fd=%d)\n", __func__, children[i]->socket); + fprintf(stdout, "usbmuxd: reclaimed client thread (fd=%d)\n", children[i]->socket); free(children[i]); children[i] = NULL; cnt++; @@ -737,7 +818,7 @@ static void *usbmuxd_accept_thread(void *arg) } continue; } else { - fprintf(stderr, "select error: %s\n", strerror(errno)); + fprintf(stderr, "usbmuxd: select error: %s\n", strerror(errno)); continue; } } @@ -746,7 +827,7 @@ static void *usbmuxd_accept_thread(void *arg) memset(cdata, 0, sizeof(struct client_data)); if (!cdata) { quit_flag = 1; - fprintf(stderr, "%s: Error: Out of memory! Terminating.\n", __func__); + fprintf(stderr, "usbmuxd: Error: Out of memory! Terminating.\n"); break; } @@ -756,12 +837,12 @@ static void *usbmuxd_accept_thread(void *arg) if (errno == EINTR) { continue; } else { - fprintf(stderr, "%s: Error in accept: %s\n", __func__, strerror(errno)); + fprintf(stderr, "usbmuxd: Error in accept: %s\n", strerror(errno)); continue; } } - fprintf(stdout, "%s: new client connected (fd=%d)\n", __func__, cdata->socket); + fprintf(stdout, "usbmuxd: new client connected (fd=%d)\n", cdata->socket); // create client thread: if (pthread_create(&cdata->thread, NULL, usbmuxd_client_init_thread, cdata) == 0) { @@ -773,22 +854,22 @@ static void *usbmuxd_accept_thread(void *arg) children_capacity++; children = realloc(children, sizeof(struct client_data*) * children_capacity); if (!children) { - fprintf(stderr, "%s: Out of memory when enlarging child thread buffer\n", __func__); + fprintf(stderr, "usbmuxd: Out of memory when enlarging child thread buffer\n"); } } children[i] = cdata; } else { - fprintf(stderr, "%s: Failed to create client_init_thread.\n", __func__); + fprintf(stderr, "usbmuxd: Failed to create client_init_thread.\n"); close(cdata->socket); free(cdata); cdata = NULL; } } - fprintf(stdout, "%s: terminating\n", __func__); + fprintf(stdout, "usbmuxd: terminating\n"); // preparing for shutdown: wait for child threads to terminate (if any) - fprintf(stdout, "%s: waiting for child threads to terminate...\n", __func__); + fprintf(stdout, "usbmuxd: waiting for child threads to terminate...\n"); for (i = 0; i < children_capacity; i++) { if (children[i] != NULL) { pthread_join(children[i]->thread, NULL); @@ -800,59 +881,15 @@ static void *usbmuxd_accept_thread(void *arg) free(children); children = NULL; - fprintf(stdout, "%s: terminated.\n", __func__); - - return NULL; -} -/** - * main function. - */ -int main(int argc, char **argv) -{ - int foreground = 1; - pthread_t acceptor; - - fprintf(stdout, "usbmuxd: starting\n"); - - // TODO: Parameter checking. - - fsock = create_unix_socket(USBMUXD_SOCKET_FILE); - if (fsock < 0) { - fprintf(stderr, "Could not create socket, exiting\n"); - return -1; - } - - chmod(USBMUXD_SOCKET_FILE, 0666); - - if (!foreground) { - if (daemonize() < 0) { - exit(EXIT_FAILURE); - } - } - - // signal(SIGHUP, reload_conf); // none yet - signal(SIGINT, clean_exit); - signal(SIGQUIT, clean_exit); - signal(SIGTERM, clean_exit); - signal(SIGPIPE, SIG_IGN); - - if (pthread_create(&acceptor, NULL, usbmuxd_accept_thread, NULL) != 0) { - fprintf(stderr, "Failed to create server thread.\n"); - close(fsock); - return -1; - } - - // Relax here. Just wait for the accept thread to terminate. - pthread_join(acceptor, NULL); - - fprintf(stdout, "usbmuxd: terminating\n"); if (fsock >= 0) { close(fsock); } unlink(USBMUXD_SOCKET_FILE); + fprintf(stdout, "usbmuxd: terminated\n"); + return 0; } -- cgit v1.1-32-gdbae