summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--main.c183
1 files 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 {
49 uint32_t device_id; 49 uint32_t device_id;
50 iphone_device_t phone; 50 iphone_device_t phone;
51 int use_count; 51 int use_count;
52 pthread_t bulk_reader;
53 pthread_mutex_t mutex;
52 /* mutex for mutual exclusion of calling the iphone_mux_send function 54 /* mutex for mutual exclusion of calling the iphone_mux_send function
53 * TODO: I don't know if we need really need this? */ 55 * TODO: I don't know if we need really need this? */
54 pthread_mutex_t writer_mutex; 56 pthread_mutex_t writer_mutex;
55 /* mutex to keep the reader threads from reading partial packages */ 57 /* mutex to keep the reader threads from reading partial packages */
56 pthread_mutex_t reader_mutex; 58 //pthread_mutex_t reader_mutex;
57}; 59};
58 60
59struct client_data { 61struct client_data {
@@ -66,6 +68,7 @@ struct client_data {
66 int reader_quit; 68 int reader_quit;
67 int reader_dead; 69 int reader_dead;
68 int handler_dead; 70 int handler_dead;
71 int connected;
69 iphone_umux_client_t muxclient; 72 iphone_umux_client_t muxclient;
70 struct device_use_info *duinfo; 73 struct device_use_info *duinfo;
71}; 74};
@@ -269,9 +272,9 @@ static int usbmuxd_handleConnectResult(struct client_data *cdata)
269 } 272 }
270 } else { 273 } else {
271 result = 0; 274 result = 0;
272 pthread_mutex_lock(&cdata->duinfo->reader_mutex); 275 //pthread_mutex_lock(&cdata->duinfo->reader_mutex);
273 err = iphone_mux_recv_timeout(cdata->muxclient, buffer, maxlen, &rlen, DEFAULT_TIMEOUT); 276 err = iphone_mux_recv_timeout(cdata->muxclient, buffer, maxlen, &rlen, DEFAULT_TIMEOUT);
274 pthread_mutex_unlock(&cdata->duinfo->reader_mutex); 277 //pthread_mutex_unlock(&cdata->duinfo->reader_mutex);
275 if (err != 0) { 278 if (err != 0) {
276 fprintf(stderr, "%s: encountered USB read error: %d\n", __func__, err); 279 fprintf(stderr, "%s: encountered USB read error: %d\n", __func__, err);
277 usbmuxd_send_result(cdata->socket, cdata->tag, -err); 280 usbmuxd_send_result(cdata->socket, cdata->tag, -err);
@@ -404,6 +407,46 @@ leave:
404} 407}
405 408
406/** 409/**
410 * Thread performing usb_bulk_read from the connected device.
411 * One thread per device. Lives as long as the device is in use.
412 */
413static void *usbmuxd_bulk_reader_thread(void *arg)
414{
415 struct device_use_info *cur_dev;
416
417 if (!arg) {
418 fprintf(stderr, "%s: Invalid client_data provided\n", __func__);
419 return NULL;
420 }
421
422 cur_dev = (struct device_use_info*)arg;
423
424 printf("%s: started\n", __func__);
425
426 while (!quit_flag && cur_dev) {
427
428 pthread_mutex_lock(&cur_dev->mutex);
429 if (cur_dev->use_count <= 0) {
430 pthread_mutex_unlock(&cur_dev->mutex);
431 break;
432 }
433 pthread_mutex_unlock(&cur_dev->mutex);
434
435 //pthread_mutex_lock(&cur_dev->reader_mutex);
436 iphone_mux_pullbulk(cur_dev->phone);
437 //err = iphone_mux_get_error(cdata->muxclient);
438 //pthread_mutex_unlock(&cur_dev->reader_mutex);
439 //if (err != IPHONE_E_SUCCESS) {
440 // break;
441 //}
442 }
443
444 printf("%s: terminated\n", __func__);
445
446 return NULL;
447}
448
449/**
407 * This thread is started when a new connection is accepted. 450 * This thread is started when a new connection is accepted.
408 * It performs the handshake, then waits for the connect packet and 451 * It performs the handshake, then waits for the connect packet and
409 * on success it starts the usbmuxd_client_handler thread. 452 * on success it starts the usbmuxd_client_handler thread.
@@ -422,8 +465,8 @@ static void *usbmuxd_client_init_thread(void *arg)
422 int found = 0; 465 int found = 0;
423 int res; 466 int res;
424 int i; 467 int i;
425 int sent_result; 468// int sent_result;
426 iphone_error_t err; 469// iphone_error_t err;
427 470
428 iphone_device_t phone; 471 iphone_device_t phone;
429 struct device_use_info *cur_dev = NULL; 472 struct device_use_info *cur_dev = NULL;
@@ -549,10 +592,12 @@ static void *usbmuxd_client_init_thread(void *arg)
549 cur_dev->use_count = 1; 592 cur_dev->use_count = 1;
550 cur_dev->device_id = c_req.device_id; 593 cur_dev->device_id = c_req.device_id;
551 cur_dev->phone = phone; 594 cur_dev->phone = phone;
552 pthread_mutex_init(&cur_dev->reader_mutex, NULL); 595 pthread_mutex_init(&cur_dev->mutex, NULL);
596 //pthread_mutex_init(&cur_dev->reader_mutex, NULL);
553 pthread_mutex_init(&cur_dev->writer_mutex, NULL); 597 pthread_mutex_init(&cur_dev->writer_mutex, NULL);
554 598
555 fprintf(stdout, "%s: device_use_count = %d\n", __func__, device_use_count); 599 fprintf(stdout, "%s: device_use_count = %d\n", __func__, device_use_count);
600 pthread_create(&cur_dev->bulk_reader, NULL, usbmuxd_bulk_reader_thread, cur_dev);
556 601
557 pthread_mutex_lock(&usbmux_mutex); 602 pthread_mutex_lock(&usbmux_mutex);
558 device_use_list = (struct device_use_info**)realloc(device_use_list, sizeof(struct device_use_info*) * (device_use_count+1)); 603 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)
586 goto leave; 631 goto leave;
587 } 632 }
588 633
589 sent_result = 0; 634 //sent_result = 0;
590 635
591 // TODO: wait for connect result? 636 // TODO: wait for connect result?
592 // if connect failed, don't run this loop: 637 // if connect failed, don't run this loop:
593 638
639 /*
594 // start reading data from the connected device 640 // start reading data from the connected device
595 while (!quit_flag && !cdata->handler_dead) { 641 while (!quit_flag && !cdata->handler_dead) {
596 pthread_mutex_lock(&cur_dev->reader_mutex); 642 pthread_mutex_lock(&cur_dev->reader_mutex);
@@ -606,14 +652,16 @@ static void *usbmuxd_client_init_thread(void *arg)
606 //fprintf(stderr, "Sending error message %d tag %d\n", err, c_req.header.tag); 652 //fprintf(stderr, "Sending error message %d tag %d\n", err, c_req.header.tag);
607 err = iphone_mux_get_error(cdata->muxclient); 653 err = iphone_mux_get_error(cdata->muxclient);
608 //usbmuxd_send_result(cdata->socket, c_req.header.tag, err); 654 //usbmuxd_send_result(cdata->socket, c_req.header.tag, err);
609 } 655 }*/
610 656
611 fprintf(stdout, "%s: terminating\n", __func__); 657 //fprintf(stdout, "%s: terminating\n", __func__);
612 658
613 // wait for handler thread to finish its work 659 // wait for handler thread to finish its work
614 if (cdata->handler != 0) { 660 if (cdata->handler != 0) {
615 pthread_join(cdata->handler, NULL); 661 pthread_join(cdata->handler, NULL);
616 } 662 }
663
664 fprintf(stdout, "%s: closing connection\n", __func__);
617 665
618 // time to clean up 666 // time to clean up
619 if (cdata && cdata->muxclient) { // should be non-NULL 667 if (cdata && cdata->muxclient) { // should be non-NULL
@@ -621,16 +669,25 @@ static void *usbmuxd_client_init_thread(void *arg)
621 } 669 }
622 670
623leave: 671leave:
672 fprintf(stdout, "%s: terminating\n", __func__);
673
624 // this has to be freed only if it's not in use anymore as it closes 674 // this has to be freed only if it's not in use anymore as it closes
625 // the USB connection 675 // the USB connection
626 if (cur_dev) { 676 if (cur_dev) {
677 pthread_mutex_lock(&cur_dev->mutex);
627 if (cur_dev->use_count > 1) { 678 if (cur_dev->use_count > 1) {
679 printf("%s: decreasing device use count\n", __func__);
628 cur_dev->use_count--; 680 cur_dev->use_count--;
681 pthread_mutex_unlock(&cur_dev->mutex);
629 } else { 682 } else {
630 iphone_free_device(cur_dev->phone); 683 printf("%s: last client disconnected, cleaning up\n", __func__);
631 cur_dev->use_count = 0; 684 cur_dev->use_count = 0;
632 pthread_mutex_destroy(&cur_dev->reader_mutex); 685 pthread_mutex_unlock(&cur_dev->mutex);
686 pthread_join(cur_dev->bulk_reader, NULL);
687 iphone_free_device(cur_dev->phone);
688 //pthread_mutex_destroy(&cur_dev->reader_mutex);
633 pthread_mutex_destroy(&cur_dev->writer_mutex); 689 pthread_mutex_destroy(&cur_dev->writer_mutex);
690 pthread_mutex_destroy(&cur_dev->mutex);
634 free(cur_dev); 691 free(cur_dev);
635 cur_dev = NULL; 692 cur_dev = NULL;
636 pthread_mutex_lock(&usbmux_mutex); 693 pthread_mutex_lock(&usbmux_mutex);
@@ -683,30 +740,54 @@ static void clean_exit(int sig)
683} 740}
684 741
685/** 742/**
686 * thread function that performs accept() and starts the required child 743 * main function. Initializes all stuff and then loops waiting in accept.
687 * threads to perform the rest of the communication stuff.
688 */ 744 */
689static void *usbmuxd_accept_thread(void *arg) 745int main(int argc, char **argv)
690{ 746{
747 int foreground = 1;
691 struct sockaddr_un c_addr; 748 struct sockaddr_un c_addr;
692 socklen_t len = sizeof(struct sockaddr_un); 749 socklen_t len = sizeof(struct sockaddr_un);
693 struct client_data *cdata; 750 struct client_data *cdata = NULL;
694 struct client_data **children = NULL; 751 struct client_data **children = NULL;
695 int children_capacity = DEFAULT_CHILDREN_CAPACITY; 752 int children_capacity = DEFAULT_CHILDREN_CAPACITY;
696 int i = 0; 753 int i = 0;
697 int result = 0; 754 int result = 0;
698 int cnt; 755 int cnt = 0;
756
757 fprintf(stdout, "usbmuxd: starting\n");
758
759 // TODO: Parameter checking.
760
761 fsock = create_unix_socket(USBMUXD_SOCKET_FILE);
762 if (fsock < 0) {
763 fprintf(stderr, "Could not create socket, exiting\n");
764 return -1;
765 }
766
767 chmod(USBMUXD_SOCKET_FILE, 0666);
768
769 if (!foreground) {
770 if (daemonize() < 0) {
771 exit(EXIT_FAILURE);
772 }
773 }
774
775 // signal(SIGHUP, reload_conf); // none yet
776 signal(SIGINT, clean_exit);
777 signal(SIGQUIT, clean_exit);
778 signal(SIGTERM, clean_exit);
779 signal(SIGPIPE, SIG_IGN);
699 780
700 // Reserve space for 10 clients which should be enough. If not, the 781 // Reserve space for 10 clients which should be enough. If not, the
701 // buffer gets enlarged later. 782 // buffer gets enlarged later.
702 children = (struct client_data**)malloc(sizeof(struct client_data*) * children_capacity); 783 children = (struct client_data**)malloc(sizeof(struct client_data*) * children_capacity);
703 if (!children) { 784 if (!children) {
704 fprintf(stderr, "%s: Out of memory when allocating memory for child threads. Terminating.\n", __func__); 785 fprintf(stderr, "usbmuxd: Out of memory when allocating memory for child threads. Terminating.\n");
705 exit(EXIT_FAILURE); 786 exit(EXIT_FAILURE);
706 } 787 }
707 memset(children, 0, sizeof(struct client_data*) * children_capacity); 788 memset(children, 0, sizeof(struct client_data*) * children_capacity);
708 789
709 fprintf(stdout, "%s: waiting for connection\n", __func__); 790 fprintf(stdout, "usbmuxd: waiting for connection\n");
710 while (!quit_flag) { 791 while (!quit_flag) {
711 // Check the file descriptor before accepting a connection. 792 // Check the file descriptor before accepting a connection.
712 // If no connection attempt is made, just repeat... 793 // If no connection attempt is made, just repeat...
@@ -718,7 +799,7 @@ static void *usbmuxd_accept_thread(void *arg)
718 if (children[i]) { 799 if (children[i]) {
719 if (children[i]->dead != 0) { 800 if (children[i]->dead != 0) {
720 pthread_join(children[i]->thread, NULL); 801 pthread_join(children[i]->thread, NULL);
721 fprintf(stdout, "%s: reclaimed client thread (fd=%d)\n", __func__, children[i]->socket); 802 fprintf(stdout, "usbmuxd: reclaimed client thread (fd=%d)\n", children[i]->socket);
722 free(children[i]); 803 free(children[i]);
723 children[i] = NULL; 804 children[i] = NULL;
724 cnt++; 805 cnt++;
@@ -737,7 +818,7 @@ static void *usbmuxd_accept_thread(void *arg)
737 } 818 }
738 continue; 819 continue;
739 } else { 820 } else {
740 fprintf(stderr, "select error: %s\n", strerror(errno)); 821 fprintf(stderr, "usbmuxd: select error: %s\n", strerror(errno));
741 continue; 822 continue;
742 } 823 }
743 } 824 }
@@ -746,7 +827,7 @@ static void *usbmuxd_accept_thread(void *arg)
746 memset(cdata, 0, sizeof(struct client_data)); 827 memset(cdata, 0, sizeof(struct client_data));
747 if (!cdata) { 828 if (!cdata) {
748 quit_flag = 1; 829 quit_flag = 1;
749 fprintf(stderr, "%s: Error: Out of memory! Terminating.\n", __func__); 830 fprintf(stderr, "usbmuxd: Error: Out of memory! Terminating.\n");
750 break; 831 break;
751 } 832 }
752 833
@@ -756,12 +837,12 @@ static void *usbmuxd_accept_thread(void *arg)
756 if (errno == EINTR) { 837 if (errno == EINTR) {
757 continue; 838 continue;
758 } else { 839 } else {
759 fprintf(stderr, "%s: Error in accept: %s\n", __func__, strerror(errno)); 840 fprintf(stderr, "usbmuxd: Error in accept: %s\n", strerror(errno));
760 continue; 841 continue;
761 } 842 }
762 } 843 }
763 844
764 fprintf(stdout, "%s: new client connected (fd=%d)\n", __func__, cdata->socket); 845 fprintf(stdout, "usbmuxd: new client connected (fd=%d)\n", cdata->socket);
765 846
766 // create client thread: 847 // create client thread:
767 if (pthread_create(&cdata->thread, NULL, usbmuxd_client_init_thread, cdata) == 0) { 848 if (pthread_create(&cdata->thread, NULL, usbmuxd_client_init_thread, cdata) == 0) {
@@ -773,22 +854,22 @@ static void *usbmuxd_accept_thread(void *arg)
773 children_capacity++; 854 children_capacity++;
774 children = realloc(children, sizeof(struct client_data*) * children_capacity); 855 children = realloc(children, sizeof(struct client_data*) * children_capacity);
775 if (!children) { 856 if (!children) {
776 fprintf(stderr, "%s: Out of memory when enlarging child thread buffer\n", __func__); 857 fprintf(stderr, "usbmuxd: Out of memory when enlarging child thread buffer\n");
777 } 858 }
778 } 859 }
779 children[i] = cdata; 860 children[i] = cdata;
780 } else { 861 } else {
781 fprintf(stderr, "%s: Failed to create client_init_thread.\n", __func__); 862 fprintf(stderr, "usbmuxd: Failed to create client_init_thread.\n");
782 close(cdata->socket); 863 close(cdata->socket);
783 free(cdata); 864 free(cdata);
784 cdata = NULL; 865 cdata = NULL;
785 } 866 }
786 } 867 }
787 868
788 fprintf(stdout, "%s: terminating\n", __func__); 869 fprintf(stdout, "usbmuxd: terminating\n");
789 870
790 // preparing for shutdown: wait for child threads to terminate (if any) 871 // preparing for shutdown: wait for child threads to terminate (if any)
791 fprintf(stdout, "%s: waiting for child threads to terminate...\n", __func__); 872 fprintf(stdout, "usbmuxd: waiting for child threads to terminate...\n");
792 for (i = 0; i < children_capacity; i++) { 873 for (i = 0; i < children_capacity; i++) {
793 if (children[i] != NULL) { 874 if (children[i] != NULL) {
794 pthread_join(children[i]->thread, NULL); 875 pthread_join(children[i]->thread, NULL);
@@ -800,59 +881,15 @@ static void *usbmuxd_accept_thread(void *arg)
800 free(children); 881 free(children);
801 children = NULL; 882 children = NULL;
802 883
803 fprintf(stdout, "%s: terminated.\n", __func__);
804
805 return NULL;
806}
807 884
808/**
809 * main function.
810 */
811int main(int argc, char **argv)
812{
813 int foreground = 1;
814 pthread_t acceptor;
815
816 fprintf(stdout, "usbmuxd: starting\n");
817
818 // TODO: Parameter checking.
819
820 fsock = create_unix_socket(USBMUXD_SOCKET_FILE);
821 if (fsock < 0) {
822 fprintf(stderr, "Could not create socket, exiting\n");
823 return -1;
824 }
825
826 chmod(USBMUXD_SOCKET_FILE, 0666);
827
828 if (!foreground) {
829 if (daemonize() < 0) {
830 exit(EXIT_FAILURE);
831 }
832 }
833
834 // signal(SIGHUP, reload_conf); // none yet
835 signal(SIGINT, clean_exit);
836 signal(SIGQUIT, clean_exit);
837 signal(SIGTERM, clean_exit);
838 signal(SIGPIPE, SIG_IGN);
839
840 if (pthread_create(&acceptor, NULL, usbmuxd_accept_thread, NULL) != 0) {
841 fprintf(stderr, "Failed to create server thread.\n");
842 close(fsock);
843 return -1;
844 }
845
846 // Relax here. Just wait for the accept thread to terminate.
847 pthread_join(acceptor, NULL);
848
849 fprintf(stdout, "usbmuxd: terminating\n");
850 if (fsock >= 0) { 885 if (fsock >= 0) {
851 close(fsock); 886 close(fsock);
852 } 887 }
853 888
854 unlink(USBMUXD_SOCKET_FILE); 889 unlink(USBMUXD_SOCKET_FILE);
855 890
891 fprintf(stdout, "usbmuxd: terminated\n");
892
856 return 0; 893 return 0;
857} 894}
858 895