summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md3
-rw-r--r--configure.ac4
-rw-r--r--src/Makefile.am2
-rw-r--r--src/client.c43
-rw-r--r--src/conf.c2
-rw-r--r--src/device.c69
-rw-r--r--src/preflight.c15
-rw-r--r--src/usb.c2
-rw-r--r--src/utils.c248
-rw-r--r--src/utils.h43
10 files changed, 74 insertions, 357 deletions
diff --git a/README.md b/README.md
index cf85997..f21a607 100644
--- a/README.md
+++ b/README.md
@@ -45,6 +45,7 @@ sudo apt-get install \
45 libplist-dev \ 45 libplist-dev \
46 libusbmuxd-dev \ 46 libusbmuxd-dev \
47 libimobiledevice-dev \ 47 libimobiledevice-dev \
48 libimobiledevice-glue-dev \
48 libusb-1.0-0-dev \ 49 libusb-1.0-0-dev \
49 udev 50 udev
50``` 51```
@@ -152,4 +153,4 @@ iPadOS, tvOS, watchOS, and macOS are trademarks of Apple Inc.
152usbmuxd is an independent software application and has not been 153usbmuxd is an independent software application and has not been
153authorized, sponsored, or otherwise approved by Apple Inc. 154authorized, sponsored, or otherwise approved by Apple Inc.
154 155
155README Updated on: 2020-06-13 156README Updated on: 2021-08-30
diff --git a/configure.ac b/configure.ac
index 7a70be9..b751cc2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -18,7 +18,7 @@ LT_INIT
18PKG_CHECK_MODULES(libusb, libusb-1.0 >= 1.0.9) 18PKG_CHECK_MODULES(libusb, libusb-1.0 >= 1.0.9)
19PKG_CHECK_MODULES(libplist, libplist-2.0 >= 2.2.0) 19PKG_CHECK_MODULES(libplist, libplist-2.0 >= 2.2.0)
20PKG_CHECK_MODULES(libimobiledevice, libimobiledevice-1.0 >= 1.3.0, have_limd=yes, have_limd=no) 20PKG_CHECK_MODULES(libimobiledevice, libimobiledevice-1.0 >= 1.3.0, have_limd=yes, have_limd=no)
21AC_CHECK_LIB(pthread, [pthread_create, pthread_mutex_lock], [AC_SUBST(libpthread_LIBS,[-lpthread])], [AC_MSG_ERROR([libpthread is required to build usbmuxd])]) 21PKG_CHECK_MODULES(limd_glue, libimobiledevice-glue-1.0 >= 1.0.0)
22 22
23AC_ARG_WITH([preflight], 23AC_ARG_WITH([preflight],
24 [AS_HELP_STRING([--without-preflight], 24 [AS_HELP_STRING([--without-preflight],
@@ -106,7 +106,7 @@ AC_TYPE_UINT8_T
106AC_SEARCH_LIBS([clock_gettime],[rt posix4]) 106AC_SEARCH_LIBS([clock_gettime],[rt posix4])
107 107
108# Checks for library functions. 108# Checks for library functions.
109AC_CHECK_FUNCS([strcasecmp strdup strerror strndup stpcpy malloc realloc]) 109AC_CHECK_FUNCS([strcasecmp strdup strerror strndup malloc realloc])
110AC_CHECK_FUNCS([ppoll clock_gettime localtime_r]) 110AC_CHECK_FUNCS([ppoll clock_gettime localtime_r])
111 111
112# Check for operating system 112# Check for operating system
diff --git a/src/Makefile.am b/src/Makefile.am
index 328b700..8a96e46 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -6,11 +6,13 @@ AM_CFLAGS = \
6 $(GLOBAL_CFLAGS) \ 6 $(GLOBAL_CFLAGS) \
7 $(libplist_CFLAGS) \ 7 $(libplist_CFLAGS) \
8 $(libusb_CFLAGS) \ 8 $(libusb_CFLAGS) \
9 $(limd_glue_CFLAGS) \
9 $(libimobiledevice_CFLAGS) 10 $(libimobiledevice_CFLAGS)
10 11
11AM_LDFLAGS = \ 12AM_LDFLAGS = \
12 $(libplist_LIBS) \ 13 $(libplist_LIBS) \
13 $(libusb_LIBS) \ 14 $(libusb_LIBS) \
15 $(limd_glue_LIBS) \
14 $(libimobiledevice_LIBS) \ 16 $(libimobiledevice_LIBS) \
15 $(libpthread_LIBS) 17 $(libpthread_LIBS)
16 18
diff --git a/src/client.c b/src/client.c
index 7395046..75a526d 100644
--- a/src/client.c
+++ b/src/client.c
@@ -34,10 +34,11 @@
34#include <netinet/tcp.h> 34#include <netinet/tcp.h>
35#include <sys/un.h> 35#include <sys/un.h>
36#include <arpa/inet.h> 36#include <arpa/inet.h>
37#include <pthread.h>
38#include <fcntl.h> 37#include <fcntl.h>
39 38
40#include <plist/plist.h> 39#include <plist/plist.h>
40#include <libimobiledevice-glue/collection.h>
41#include <libimobiledevice-glue/thread.h>
41 42
42#include "log.h" 43#include "log.h"
43#include "usb.h" 44#include "usb.h"
@@ -75,7 +76,7 @@ struct mux_client {
75}; 76};
76 77
77static struct collection client_list; 78static struct collection client_list;
78pthread_mutex_t client_list_mutex; 79mutex_t client_list_mutex;
79static uint32_t client_number = 0; 80static uint32_t client_number = 0;
80 81
81#ifdef SO_PEERCRED 82#ifdef SO_PEERCRED
@@ -224,10 +225,10 @@ int client_accept(int listenfd)
224 client->events = POLLIN; 225 client->events = POLLIN;
225 client->info = NULL; 226 client->info = NULL;
226 227
227 pthread_mutex_lock(&client_list_mutex); 228 mutex_lock(&client_list_mutex);
228 client->number = client_number++; 229 client->number = client_number++;
229 collection_add(&client_list, client); 230 collection_add(&client_list, client);
230 pthread_mutex_unlock(&client_list_mutex); 231 mutex_unlock(&client_list_mutex);
231 232
232#ifdef SO_PEERCRED 233#ifdef SO_PEERCRED
233 if (log_level >= LL_INFO) { 234 if (log_level >= LL_INFO) {
@@ -252,7 +253,7 @@ int client_accept(int listenfd)
252void client_close(struct mux_client *client) 253void client_close(struct mux_client *client)
253{ 254{
254 int found = 0; 255 int found = 0;
255 pthread_mutex_lock(&client_list_mutex); 256 mutex_lock(&client_list_mutex);
256 FOREACH(struct mux_client *lc, &client_list) { 257 FOREACH(struct mux_client *lc, &client_list) {
257 if (client == lc) { 258 if (client == lc) {
258 found = 1; 259 found = 1;
@@ -262,7 +263,7 @@ void client_close(struct mux_client *client)
262 if (!found) { 263 if (!found) {
263 // in case we get called again but client was already freed 264 // in case we get called again but client was already freed
264 usbmuxd_log(LL_DEBUG, "%s: ignoring for non-existing client %p", __func__, client); 265 usbmuxd_log(LL_DEBUG, "%s: ignoring for non-existing client %p", __func__, client);
265 pthread_mutex_unlock(&client_list_mutex); 266 mutex_unlock(&client_list_mutex);
266 return; 267 return;
267 } 268 }
268#ifdef SO_PEERCRED 269#ifdef SO_PEERCRED
@@ -293,17 +294,17 @@ void client_close(struct mux_client *client)
293 plist_free(client->info); 294 plist_free(client->info);
294 295
295 collection_remove(&client_list, client); 296 collection_remove(&client_list, client);
296 pthread_mutex_unlock(&client_list_mutex); 297 mutex_unlock(&client_list_mutex);
297 free(client); 298 free(client);
298} 299}
299 300
300void client_get_fds(struct fdlist *list) 301void client_get_fds(struct fdlist *list)
301{ 302{
302 pthread_mutex_lock(&client_list_mutex); 303 mutex_lock(&client_list_mutex);
303 FOREACH(struct mux_client *client, &client_list) { 304 FOREACH(struct mux_client *client, &client_list) {
304 fdlist_add(list, FD_CLIENT, client->fd, client->events); 305 fdlist_add(list, FD_CLIENT, client->fd, client->events);
305 } ENDFOREACH 306 } ENDFOREACH
306 pthread_mutex_unlock(&client_list_mutex); 307 mutex_unlock(&client_list_mutex);
307} 308}
308 309
309static int output_buffer_add_message(struct mux_client *client, uint32_t tag, enum usbmuxd_msgtype msg, void *payload, int payload_length) 310static int output_buffer_add_message(struct mux_client *client, uint32_t tag, enum usbmuxd_msgtype msg, void *payload, int payload_length)
@@ -442,7 +443,7 @@ static int send_listener_list(struct mux_client *client, uint32_t tag)
442 plist_t dict = plist_new_dict(); 443 plist_t dict = plist_new_dict();
443 plist_t listeners = plist_new_array(); 444 plist_t listeners = plist_new_array();
444 445
445 pthread_mutex_lock(&client_list_mutex); 446 mutex_lock(&client_list_mutex);
446 FOREACH(struct mux_client *lc, &client_list) { 447 FOREACH(struct mux_client *lc, &client_list) {
447 if (lc->state == CLIENT_LISTEN) { 448 if (lc->state == CLIENT_LISTEN) {
448 plist_t n = NULL; 449 plist_t n = NULL;
@@ -489,7 +490,7 @@ static int send_listener_list(struct mux_client *client, uint32_t tag)
489 plist_array_append_item(listeners, l); 490 plist_array_append_item(listeners, l);
490 } 491 }
491 } ENDFOREACH 492 } ENDFOREACH
492 pthread_mutex_unlock(&client_list_mutex); 493 mutex_unlock(&client_list_mutex);
493 494
494 plist_dict_set_item(dict, "ListenerList", listeners); 495 plist_dict_set_item(dict, "ListenerList", listeners);
495 res = send_plist(client, tag, dict); 496 res = send_plist(client, tag, dict);
@@ -975,14 +976,14 @@ static void input_buffer_process(struct mux_client *client)
975void client_process(int fd, short events) 976void client_process(int fd, short events)
976{ 977{
977 struct mux_client *client = NULL; 978 struct mux_client *client = NULL;
978 pthread_mutex_lock(&client_list_mutex); 979 mutex_lock(&client_list_mutex);
979 FOREACH(struct mux_client *lc, &client_list) { 980 FOREACH(struct mux_client *lc, &client_list) {
980 if(lc->fd == fd) { 981 if(lc->fd == fd) {
981 client = lc; 982 client = lc;
982 break; 983 break;
983 } 984 }
984 } ENDFOREACH 985 } ENDFOREACH
985 pthread_mutex_unlock(&client_list_mutex); 986 mutex_unlock(&client_list_mutex);
986 987
987 if(!client) { 988 if(!client) {
988 usbmuxd_log(LL_INFO, "client_process: fd %d not found in client list", fd); 989 usbmuxd_log(LL_INFO, "client_process: fd %d not found in client list", fd);
@@ -1004,45 +1005,45 @@ void client_process(int fd, short events)
1004 1005
1005void client_device_add(struct device_info *dev) 1006void client_device_add(struct device_info *dev)
1006{ 1007{
1007 pthread_mutex_lock(&client_list_mutex); 1008 mutex_lock(&client_list_mutex);
1008 usbmuxd_log(LL_DEBUG, "client_device_add: id %d, location 0x%x, serial %s", dev->id, dev->location, dev->serial); 1009 usbmuxd_log(LL_DEBUG, "client_device_add: id %d, location 0x%x, serial %s", dev->id, dev->location, dev->serial);
1009 device_set_visible(dev->id); 1010 device_set_visible(dev->id);
1010 FOREACH(struct mux_client *client, &client_list) { 1011 FOREACH(struct mux_client *client, &client_list) {
1011 if(client->state == CLIENT_LISTEN) 1012 if(client->state == CLIENT_LISTEN)
1012 send_device_add(client, dev); 1013 send_device_add(client, dev);
1013 } ENDFOREACH 1014 } ENDFOREACH
1014 pthread_mutex_unlock(&client_list_mutex); 1015 mutex_unlock(&client_list_mutex);
1015} 1016}
1016 1017
1017void client_device_remove(int device_id) 1018void client_device_remove(int device_id)
1018{ 1019{
1019 pthread_mutex_lock(&client_list_mutex); 1020 mutex_lock(&client_list_mutex);
1020 uint32_t id = device_id; 1021 uint32_t id = device_id;
1021 usbmuxd_log(LL_DEBUG, "client_device_remove: id %d", device_id); 1022 usbmuxd_log(LL_DEBUG, "client_device_remove: id %d", device_id);
1022 FOREACH(struct mux_client *client, &client_list) { 1023 FOREACH(struct mux_client *client, &client_list) {
1023 if(client->state == CLIENT_LISTEN) 1024 if(client->state == CLIENT_LISTEN)
1024 send_device_remove(client, id); 1025 send_device_remove(client, id);
1025 } ENDFOREACH 1026 } ENDFOREACH
1026 pthread_mutex_unlock(&client_list_mutex); 1027 mutex_unlock(&client_list_mutex);
1027} 1028}
1028 1029
1029void client_device_paired(int device_id) 1030void client_device_paired(int device_id)
1030{ 1031{
1031 pthread_mutex_lock(&client_list_mutex); 1032 mutex_lock(&client_list_mutex);
1032 uint32_t id = device_id; 1033 uint32_t id = device_id;
1033 usbmuxd_log(LL_DEBUG, "client_device_paired: id %d", device_id); 1034 usbmuxd_log(LL_DEBUG, "client_device_paired: id %d", device_id);
1034 FOREACH(struct mux_client *client, &client_list) { 1035 FOREACH(struct mux_client *client, &client_list) {
1035 if (client->state == CLIENT_LISTEN) 1036 if (client->state == CLIENT_LISTEN)
1036 send_device_paired(client, id); 1037 send_device_paired(client, id);
1037 } ENDFOREACH 1038 } ENDFOREACH
1038 pthread_mutex_unlock(&client_list_mutex); 1039 mutex_unlock(&client_list_mutex);
1039} 1040}
1040 1041
1041void client_init(void) 1042void client_init(void)
1042{ 1043{
1043 usbmuxd_log(LL_DEBUG, "client_init"); 1044 usbmuxd_log(LL_DEBUG, "client_init");
1044 collection_init(&client_list); 1045 collection_init(&client_list);
1045 pthread_mutex_init(&client_list_mutex, NULL); 1046 mutex_init(&client_list_mutex);
1046} 1047}
1047 1048
1048void client_shutdown(void) 1049void client_shutdown(void)
@@ -1051,6 +1052,6 @@ void client_shutdown(void)
1051 FOREACH(struct mux_client *client, &client_list) { 1052 FOREACH(struct mux_client *client, &client_list) {
1052 client_close(client); 1053 client_close(client);
1053 } ENDFOREACH 1054 } ENDFOREACH
1054 pthread_mutex_destroy(&client_list_mutex); 1055 mutex_destroy(&client_list_mutex);
1055 collection_free(&client_list); 1056 collection_free(&client_list);
1056} 1057}
diff --git a/src/conf.c b/src/conf.c
index 609d246..84f4326 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -39,6 +39,8 @@
39#include <shlobj.h> 39#include <shlobj.h>
40#endif 40#endif
41 41
42#include <libimobiledevice-glue/utils.h>
43
42#include "conf.h" 44#include "conf.h"
43#include "utils.h" 45#include "utils.h"
44#include "log.h" 46#include "log.h"
diff --git a/src/device.c b/src/device.c
index aac40b1..0928021 100644
--- a/src/device.c
+++ b/src/device.c
@@ -32,8 +32,11 @@
32#include <string.h> 32#include <string.h>
33#include <stdint.h> 33#include <stdint.h>
34#include <inttypes.h> 34#include <inttypes.h>
35#include <pthread.h>
36#include <unistd.h> 35#include <unistd.h>
36
37#include <libimobiledevice-glue/collection.h>
38#include <libimobiledevice-glue/thread.h>
39
37#include "device.h" 40#include "device.h"
38#include "client.h" 41#include "client.h"
39#include "preflight.h" 42#include "preflight.h"
@@ -127,19 +130,19 @@ struct mux_device
127}; 130};
128 131
129static struct collection device_list; 132static struct collection device_list;
130pthread_mutex_t device_list_mutex; 133mutex_t device_list_mutex;
131 134
132static struct mux_device* get_mux_device_for_id(int device_id) 135static struct mux_device* get_mux_device_for_id(int device_id)
133{ 136{
134 struct mux_device *dev = NULL; 137 struct mux_device *dev = NULL;
135 pthread_mutex_lock(&device_list_mutex); 138 mutex_lock(&device_list_mutex);
136 FOREACH(struct mux_device *cdev, &device_list) { 139 FOREACH(struct mux_device *cdev, &device_list) {
137 if(cdev->id == device_id) { 140 if(cdev->id == device_id) {
138 dev = cdev; 141 dev = cdev;
139 break; 142 break;
140 } 143 }
141 } ENDFOREACH 144 } ENDFOREACH
142 pthread_mutex_unlock(&device_list_mutex); 145 mutex_unlock(&device_list_mutex);
143 146
144 return dev; 147 return dev;
145} 148}
@@ -166,7 +169,7 @@ static int get_next_device_id(void)
166{ 169{
167 while(1) { 170 while(1) {
168 int ok = 1; 171 int ok = 1;
169 pthread_mutex_lock(&device_list_mutex); 172 mutex_lock(&device_list_mutex);
170 FOREACH(struct mux_device *dev, &device_list) { 173 FOREACH(struct mux_device *dev, &device_list) {
171 if(dev->id == next_device_id) { 174 if(dev->id == next_device_id) {
172 next_device_id++; 175 next_device_id++;
@@ -174,7 +177,7 @@ static int get_next_device_id(void)
174 break; 177 break;
175 } 178 }
176 } ENDFOREACH 179 } ENDFOREACH
177 pthread_mutex_unlock(&device_list_mutex); 180 mutex_unlock(&device_list_mutex);
178 if(ok) 181 if(ok)
179 return next_device_id++; 182 return next_device_id++;
180 } 183 }
@@ -464,9 +467,9 @@ static int send_tcp_ack(struct mux_connection *conn)
464 */ 467 */
465void device_client_process(int device_id, struct mux_client *client, short events) 468void device_client_process(int device_id, struct mux_client *client, short events)
466{ 469{
467 pthread_mutex_lock(&device_list_mutex); 470 mutex_lock(&device_list_mutex);
468 struct mux_connection *conn = get_mux_connection(device_id, client); 471 struct mux_connection *conn = get_mux_connection(device_id, client);
469 pthread_mutex_unlock(&device_list_mutex); 472 mutex_unlock(&device_list_mutex);
470 if(!conn) { 473 if(!conn) {
471 usbmuxd_log(LL_WARNING, "Could not find connection for device %d client %p", device_id, client); 474 usbmuxd_log(LL_WARNING, "Could not find connection for device %d client %p", device_id, client);
472 return; 475 return;
@@ -566,9 +569,9 @@ static void device_version_input(struct mux_device *dev, struct version_header *
566 vh->minor = ntohl(vh->minor); 569 vh->minor = ntohl(vh->minor);
567 if(vh->major != 2 && vh->major != 1) { 570 if(vh->major != 2 && vh->major != 1) {
568 usbmuxd_log(LL_ERROR, "Device %d has unknown version %d.%d", dev->id, vh->major, vh->minor); 571 usbmuxd_log(LL_ERROR, "Device %d has unknown version %d.%d", dev->id, vh->major, vh->minor);
569 pthread_mutex_lock(&device_list_mutex); 572 mutex_lock(&device_list_mutex);
570 collection_remove(&device_list, dev); 573 collection_remove(&device_list, dev);
571 pthread_mutex_unlock(&device_list_mutex); 574 mutex_unlock(&device_list_mutex);
572 free(dev); 575 free(dev);
573 return; 576 return;
574 } 577 }
@@ -726,14 +729,14 @@ static void device_tcp_input(struct mux_device *dev, struct tcphdr *th, unsigned
726void device_data_input(struct usb_device *usbdev, unsigned char *buffer, uint32_t length) 729void device_data_input(struct usb_device *usbdev, unsigned char *buffer, uint32_t length)
727{ 730{
728 struct mux_device *dev = NULL; 731 struct mux_device *dev = NULL;
729 pthread_mutex_lock(&device_list_mutex); 732 mutex_lock(&device_list_mutex);
730 FOREACH(struct mux_device *tdev, &device_list) { 733 FOREACH(struct mux_device *tdev, &device_list) {
731 if(tdev->usbdev == usbdev) { 734 if(tdev->usbdev == usbdev) {
732 dev = tdev; 735 dev = tdev;
733 break; 736 break;
734 } 737 }
735 } ENDFOREACH 738 } ENDFOREACH
736 pthread_mutex_unlock(&device_list_mutex); 739 mutex_unlock(&device_list_mutex);
737 if(!dev) { 740 if(!dev) {
738 usbmuxd_log(LL_WARNING, "Cannot find device entry for RX input from USB device %p on location 0x%x", usbdev, usb_get_location(usbdev)); 741 usbmuxd_log(LL_WARNING, "Cannot find device entry for RX input from USB device %p on location 0x%x", usbdev, usb_get_location(usbdev));
739 return; 742 return;
@@ -850,15 +853,15 @@ int device_add(struct usb_device *usbdev)
850 free(dev); 853 free(dev);
851 return res; 854 return res;
852 } 855 }
853 pthread_mutex_lock(&device_list_mutex); 856 mutex_lock(&device_list_mutex);
854 collection_add(&device_list, dev); 857 collection_add(&device_list, dev);
855 pthread_mutex_unlock(&device_list_mutex); 858 mutex_unlock(&device_list_mutex);
856 return 0; 859 return 0;
857} 860}
858 861
859void device_remove(struct usb_device *usbdev) 862void device_remove(struct usb_device *usbdev)
860{ 863{
861 pthread_mutex_lock(&device_list_mutex); 864 mutex_lock(&device_list_mutex);
862 FOREACH(struct mux_device *dev, &device_list) { 865 FOREACH(struct mux_device *dev, &device_list) {
863 if(dev->usbdev == usbdev) { 866 if(dev->usbdev == usbdev) {
864 usbmuxd_log(LL_NOTICE, "Removed device %d on location 0x%x", dev->id, usb_get_location(usbdev)); 867 usbmuxd_log(LL_NOTICE, "Removed device %d on location 0x%x", dev->id, usb_get_location(usbdev));
@@ -874,48 +877,48 @@ void device_remove(struct usb_device *usbdev)
874 preflight_device_remove_cb(dev->preflight_cb_data); 877 preflight_device_remove_cb(dev->preflight_cb_data);
875 } 878 }
876 collection_remove(&device_list, dev); 879 collection_remove(&device_list, dev);
877 pthread_mutex_unlock(&device_list_mutex); 880 mutex_unlock(&device_list_mutex);
878 free(dev->pktbuf); 881 free(dev->pktbuf);
879 free(dev); 882 free(dev);
880 return; 883 return;
881 } 884 }
882 } ENDFOREACH 885 } ENDFOREACH
883 pthread_mutex_unlock(&device_list_mutex); 886 mutex_unlock(&device_list_mutex);
884 887
885 usbmuxd_log(LL_WARNING, "Cannot find device entry while removing USB device %p on location 0x%x", usbdev, usb_get_location(usbdev)); 888 usbmuxd_log(LL_WARNING, "Cannot find device entry while removing USB device %p on location 0x%x", usbdev, usb_get_location(usbdev));
886} 889}
887 890
888void device_set_visible(int device_id) 891void device_set_visible(int device_id)
889{ 892{
890 pthread_mutex_lock(&device_list_mutex); 893 mutex_lock(&device_list_mutex);
891 FOREACH(struct mux_device *dev, &device_list) { 894 FOREACH(struct mux_device *dev, &device_list) {
892 if(dev->id == device_id) { 895 if(dev->id == device_id) {
893 dev->visible = 1; 896 dev->visible = 1;
894 break; 897 break;
895 } 898 }
896 } ENDFOREACH 899 } ENDFOREACH
897 pthread_mutex_unlock(&device_list_mutex); 900 mutex_unlock(&device_list_mutex);
898} 901}
899 902
900void device_set_preflight_cb_data(int device_id, void* data) 903void device_set_preflight_cb_data(int device_id, void* data)
901{ 904{
902 pthread_mutex_lock(&device_list_mutex); 905 mutex_lock(&device_list_mutex);
903 FOREACH(struct mux_device *dev, &device_list) { 906 FOREACH(struct mux_device *dev, &device_list) {
904 if(dev->id == device_id) { 907 if(dev->id == device_id) {
905 dev->preflight_cb_data = data; 908 dev->preflight_cb_data = data;
906 break; 909 break;
907 } 910 }
908 } ENDFOREACH 911 } ENDFOREACH
909 pthread_mutex_unlock(&device_list_mutex); 912 mutex_unlock(&device_list_mutex);
910} 913}
911 914
912int device_get_count(int include_hidden) 915int device_get_count(int include_hidden)
913{ 916{
914 int count = 0; 917 int count = 0;
915 struct collection dev_list = {NULL, 0}; 918 struct collection dev_list = {NULL, 0};
916 pthread_mutex_lock(&device_list_mutex); 919 mutex_lock(&device_list_mutex);
917 collection_copy(&dev_list, &device_list); 920 collection_copy(&dev_list, &device_list);
918 pthread_mutex_unlock(&device_list_mutex); 921 mutex_unlock(&device_list_mutex);
919 922
920 FOREACH(struct mux_device *dev, &dev_list) { 923 FOREACH(struct mux_device *dev, &dev_list) {
921 if((dev->state == MUXDEV_ACTIVE) && (include_hidden || dev->visible)) 924 if((dev->state == MUXDEV_ACTIVE) && (include_hidden || dev->visible))
@@ -930,9 +933,9 @@ int device_get_list(int include_hidden, struct device_info **devices)
930{ 933{
931 int count = 0; 934 int count = 0;
932 struct collection dev_list = {NULL, 0}; 935 struct collection dev_list = {NULL, 0};
933 pthread_mutex_lock(&device_list_mutex); 936 mutex_lock(&device_list_mutex);
934 collection_copy(&dev_list, &device_list); 937 collection_copy(&dev_list, &device_list);
935 pthread_mutex_unlock(&device_list_mutex); 938 mutex_unlock(&device_list_mutex);
936 939
937 *devices = malloc(sizeof(struct device_info) * dev_list.capacity); 940 *devices = malloc(sizeof(struct device_info) * dev_list.capacity);
938 struct device_info *p = *devices; 941 struct device_info *p = *devices;
@@ -957,7 +960,7 @@ int device_get_list(int include_hidden, struct device_info **devices)
957int device_get_timeout(void) 960int device_get_timeout(void)
958{ 961{
959 uint64_t oldest = (uint64_t)-1LL; 962 uint64_t oldest = (uint64_t)-1LL;
960 pthread_mutex_lock(&device_list_mutex); 963 mutex_lock(&device_list_mutex);
961 FOREACH(struct mux_device *dev, &device_list) { 964 FOREACH(struct mux_device *dev, &device_list) {
962 if(dev->state == MUXDEV_ACTIVE) { 965 if(dev->state == MUXDEV_ACTIVE) {
963 FOREACH(struct mux_connection *conn, &dev->connections) { 966 FOREACH(struct mux_connection *conn, &dev->connections) {
@@ -966,7 +969,7 @@ int device_get_timeout(void)
966 } ENDFOREACH 969 } ENDFOREACH
967 } 970 }
968 } ENDFOREACH 971 } ENDFOREACH
969 pthread_mutex_unlock(&device_list_mutex); 972 mutex_unlock(&device_list_mutex);
970 uint64_t ct = mstime64(); 973 uint64_t ct = mstime64();
971 if((int64_t)oldest == -1LL) 974 if((int64_t)oldest == -1LL)
972 return 100000; //meh 975 return 100000; //meh
@@ -978,7 +981,7 @@ int device_get_timeout(void)
978void device_check_timeouts(void) 981void device_check_timeouts(void)
979{ 982{
980 uint64_t ct = mstime64(); 983 uint64_t ct = mstime64();
981 pthread_mutex_lock(&device_list_mutex); 984 mutex_lock(&device_list_mutex);
982 FOREACH(struct mux_device *dev, &device_list) { 985 FOREACH(struct mux_device *dev, &device_list) {
983 if(dev->state == MUXDEV_ACTIVE) { 986 if(dev->state == MUXDEV_ACTIVE) {
984 FOREACH(struct mux_connection *conn, &dev->connections) { 987 FOREACH(struct mux_connection *conn, &dev->connections) {
@@ -991,14 +994,14 @@ void device_check_timeouts(void)
991 } ENDFOREACH 994 } ENDFOREACH
992 } 995 }
993 } ENDFOREACH 996 } ENDFOREACH
994 pthread_mutex_unlock(&device_list_mutex); 997 mutex_unlock(&device_list_mutex);
995} 998}
996 999
997void device_init(void) 1000void device_init(void)
998{ 1001{
999 usbmuxd_log(LL_DEBUG, "device_init"); 1002 usbmuxd_log(LL_DEBUG, "device_init");
1000 collection_init(&device_list); 1003 collection_init(&device_list);
1001 pthread_mutex_init(&device_list_mutex, NULL); 1004 mutex_init(&device_list_mutex);
1002 next_device_id = 1; 1005 next_device_id = 1;
1003} 1006}
1004 1007
@@ -1019,7 +1022,7 @@ void device_kill_connections(void)
1019void device_shutdown(void) 1022void device_shutdown(void)
1020{ 1023{
1021 usbmuxd_log(LL_DEBUG, "device_shutdown"); 1024 usbmuxd_log(LL_DEBUG, "device_shutdown");
1022 pthread_mutex_lock(&device_list_mutex); 1025 mutex_lock(&device_list_mutex);
1023 FOREACH(struct mux_device *dev, &device_list) { 1026 FOREACH(struct mux_device *dev, &device_list) {
1024 FOREACH(struct mux_connection *conn, &dev->connections) { 1027 FOREACH(struct mux_connection *conn, &dev->connections) {
1025 connection_teardown(conn); 1028 connection_teardown(conn);
@@ -1028,7 +1031,7 @@ void device_shutdown(void)
1028 collection_remove(&device_list, dev); 1031 collection_remove(&device_list, dev);
1029 free(dev); 1032 free(dev);
1030 } ENDFOREACH 1033 } ENDFOREACH
1031 pthread_mutex_unlock(&device_list_mutex); 1034 mutex_unlock(&device_list_mutex);
1032 pthread_mutex_destroy(&device_list_mutex); 1035 mutex_destroy(&device_list_mutex);
1033 collection_free(&device_list); 1036 collection_free(&device_list);
1034} 1037}
diff --git a/src/preflight.c b/src/preflight.c
index 6a303c2..5902f5d 100644
--- a/src/preflight.c
+++ b/src/preflight.c
@@ -26,8 +26,6 @@
26#include <unistd.h> 26#include <unistd.h>
27#include <errno.h> 27#include <errno.h>
28 28
29#include <pthread.h>
30
31#include <sys/time.h> 29#include <sys/time.h>
32 30
33#ifdef HAVE_LIBIMOBILEDEVICE 31#ifdef HAVE_LIBIMOBILEDEVICE
@@ -36,6 +34,8 @@
36#include <libimobiledevice/notification_proxy.h> 34#include <libimobiledevice/notification_proxy.h>
37#endif 35#endif
38 36
37#include <libimobiledevice-glue/thread.h>
38
39#include "preflight.h" 39#include "preflight.h"
40#include "device.h" 40#include "device.h"
41#include "client.h" 41#include "client.h"
@@ -389,18 +389,15 @@ void preflight_worker_device_add(struct device_info* info)
389 infocopy->serial = strdup(info->serial); 389 infocopy->serial = strdup(info->serial);
390 } 390 }
391 391
392 pthread_t th; 392 THREAD_T th;
393 pthread_attr_t attr; 393 int perr = thread_new(&th, preflight_worker_handle_device_add, infocopy);
394
395 pthread_attr_init(&attr);
396 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
397
398 int perr = pthread_create(&th, &attr, preflight_worker_handle_device_add, infocopy);
399 if (perr != 0) { 394 if (perr != 0) {
400 free((char*)infocopy->serial); 395 free((char*)infocopy->serial);
401 free(infocopy); 396 free(infocopy);
402 usbmuxd_log(LL_ERROR, "ERROR: failed to start preflight worker thread for device %s: %s (%d). Invoking client_device_add() directly but things might not work as expected.", info->serial, strerror(perr), perr); 397 usbmuxd_log(LL_ERROR, "ERROR: failed to start preflight worker thread for device %s: %s (%d). Invoking client_device_add() directly but things might not work as expected.", info->serial, strerror(perr), perr);
403 client_device_add(info); 398 client_device_add(info);
399 } else {
400 thread_detach(th);
404 } 401 }
405#else 402#else
406 client_device_add(info); 403 client_device_add(info);
diff --git a/src/usb.c b/src/usb.c
index 9c30055..388b6f3 100644
--- a/src/usb.c
+++ b/src/usb.c
@@ -31,6 +31,8 @@
31 31
32#include <libusb.h> 32#include <libusb.h>
33 33
34#include <libimobiledevice-glue/collection.h>
35
34#include "usb.h" 36#include "usb.h"
35#include "log.h" 37#include "log.h"
36#include "device.h" 38#include "device.h"
diff --git a/src/utils.c b/src/utils.c
index 206c684..2cc5675 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -76,254 +76,6 @@ void fdlist_reset(struct fdlist *list)
76 list->count = 0; 76 list->count = 0;
77} 77}
78 78
79#define CAPACITY_STEP 8
80
81void collection_init(struct collection *col)
82{
83 col->list = malloc(sizeof(void *) * CAPACITY_STEP);
84 memset(col->list, 0, sizeof(void *) * CAPACITY_STEP);
85 col->capacity = CAPACITY_STEP;
86}
87
88void collection_free(struct collection *col)
89{
90 free(col->list);
91 col->list = NULL;
92 col->capacity = 0;
93}
94
95void collection_add(struct collection *col, void *element)
96{
97 int i;
98 for(i=0; i<col->capacity; i++) {
99 if(!col->list[i]) {
100 col->list[i] = element;
101 return;
102 }
103 }
104 col->list = realloc(col->list, sizeof(void*) * (col->capacity + CAPACITY_STEP));
105 memset(&col->list[col->capacity], 0, sizeof(void *) * CAPACITY_STEP);
106 col->list[col->capacity] = element;
107 col->capacity += CAPACITY_STEP;
108}
109
110void collection_remove(struct collection *col, void *element)
111{
112 int i;
113 for(i=0; i<col->capacity; i++) {
114 if(col->list[i] == element) {
115 col->list[i] = NULL;
116 return;
117 }
118 }
119 util_error("collection_remove: element %p not present in collection %p (cap %d)", element, col, col->capacity);
120}
121
122int collection_count(struct collection *col)
123{
124 int i, cnt = 0;
125 for(i=0; i<col->capacity; i++) {
126 if(col->list[i])
127 cnt++;
128 }
129 return cnt;
130}
131
132void collection_copy(struct collection *dest, struct collection *src)
133{
134 if (!dest || !src) return;
135 dest->capacity = src->capacity;
136 dest->list = malloc(sizeof(void*) * src->capacity);
137 memcpy(dest->list, src->list, sizeof(void*) * src->capacity);
138}
139
140#ifndef HAVE_STPCPY
141/**
142 * Copy characters from one string into another
143 *
144 * @note: The strings should not overlap, as the behavior is undefined.
145 *
146 * @s1: The source string.
147 * @s2: The destination string.
148 *
149 * @return a pointer to the terminating `\0' character of @s1,
150 * or NULL if @s1 or @s2 is NULL.
151 */
152char *stpcpy(char * s1, const char * s2)
153{
154 if (s1 == NULL || s2 == NULL)
155 return NULL;
156
157 strcpy(s1, s2);
158
159 return s1 + strlen(s2);
160}
161#endif
162
163/**
164 * Concatenate strings into a newly allocated string
165 *
166 * @note: Specify NULL for the last string in the varargs list
167 *
168 * @str: The first string in the list
169 * @...: Subsequent strings. Use NULL for the last item.
170 *
171 * @return a newly allocated string, or NULL if @str is NULL. This will also
172 * return NULL and set errno to ENOMEM if memory is exhausted.
173 */
174char *string_concat(const char *str, ...)
175{
176 size_t len;
177 va_list args;
178 char *s;
179 char *result;
180 char *dest;
181
182 if (!str)
183 return NULL;
184
185 /* Compute final length */
186
187 len = strlen(str) + 1; /* plus 1 for the null terminator */
188
189 va_start(args, str);
190 s = va_arg(args, char *);
191 while (s) {
192 len += strlen(s);
193 s = va_arg(args, char*);
194 }
195 va_end(args);
196
197 /* Concat each string */
198
199 result = malloc(len);
200 if (!result)
201 return NULL; /* errno remains set */
202
203 dest = result;
204
205 dest = stpcpy(dest, str);
206
207 va_start(args, str);
208 s = va_arg(args, char *);
209 while (s) {
210 dest = stpcpy(dest, s);
211 s = va_arg(args, char *);
212 }
213 va_end(args);
214
215 return result;
216}
217
218int buffer_read_from_filename(const char *filename, char **buffer, uint64_t *length)
219{
220 FILE *f;
221 uint64_t size;
222
223 *length = 0;
224
225 f = fopen(filename, "rb");
226 if (!f) {
227 return 0;
228 }
229
230 fseek(f, 0, SEEK_END);
231 size = ftell(f);
232 rewind(f);
233
234 if (size == 0) {
235 fclose(f);
236 return 0;
237 }
238
239 *buffer = (char*)malloc(sizeof(char)*(size+1));
240
241 if (!buffer) {
242 return 0;
243 }
244
245 int ret = 1;
246 if (fread(*buffer, sizeof(char), size, f) != size) {
247 usbmuxd_log(LL_ERROR, "%s: ERROR: couldn't read %d bytes from %s", __func__, (int)size, filename);
248 free(*buffer);
249 ret = 0;
250 errno = EIO;
251 }
252 fclose(f);
253
254 *length = size;
255 return ret;
256}
257
258int buffer_write_to_filename(const char *filename, const char *buffer, uint64_t length)
259{
260 FILE *f;
261
262 f = fopen(filename, "wb");
263 if (f) {
264 size_t written = fwrite(buffer, sizeof(char), length, f);
265 fclose(f);
266
267 if (written == length) {
268 return 1;
269 }
270 else {
271 // Not all data could be written.
272 errno = EIO;
273 return 0;
274 }
275 }
276 else {
277 // Failed to open the file, let the caller know.
278 return 0;
279 }
280}
281
282int plist_read_from_filename(plist_t *plist, const char *filename)
283{
284 char *buffer = NULL;
285 uint64_t length;
286
287 if (!filename)
288 return 0;
289
290 if (!buffer_read_from_filename(filename, &buffer, &length)) {
291 return 0;
292 }
293
294 if ((length > 8) && (memcmp(buffer, "bplist00", 8) == 0)) {
295 plist_from_bin(buffer, length, plist);
296 } else {
297 plist_from_xml(buffer, length, plist);
298 }
299
300 free(buffer);
301
302 return 1;
303}
304
305int plist_write_to_filename(plist_t plist, const char *filename, enum plist_format_t format)
306{
307 char *buffer = NULL;
308 uint32_t length;
309
310 if (!plist || !filename)
311 return 0;
312
313 if (format == PLIST_FORMAT_XML)
314 plist_to_xml(plist, &buffer, &length);
315 else if (format == PLIST_FORMAT_BINARY)
316 plist_to_bin(plist, &buffer, &length);
317 else
318 return 0;
319
320 int res = buffer_write_to_filename(filename, buffer, length);
321
322 free(buffer);
323
324 return res;
325}
326
327#ifndef HAVE_CLOCK_GETTIME 79#ifndef HAVE_CLOCK_GETTIME
328typedef int clockid_t; 80typedef int clockid_t;
329#define CLOCK_MONOTONIC 1 81#define CLOCK_MONOTONIC 1
diff --git a/src/utils.h b/src/utils.h
index b5cab3f..ce3b2e0 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -43,49 +43,6 @@ void fdlist_add(struct fdlist *list, enum fdowner owner, int fd, short events);
43void fdlist_free(struct fdlist *list); 43void fdlist_free(struct fdlist *list);
44void fdlist_reset(struct fdlist *list); 44void fdlist_reset(struct fdlist *list);
45 45
46struct collection {
47 void **list;
48 int capacity;
49};
50
51void collection_init(struct collection *col);
52void collection_add(struct collection *col, void *element);
53void collection_remove(struct collection *col, void *element);
54int collection_count(struct collection *col);
55void collection_free(struct collection *col);
56void collection_copy(struct collection *dest, struct collection *src);
57
58#define MERGE_(a,b) a ## _ ## b
59#define LABEL_(a,b) MERGE_(a, b)
60#define UNIQUE_VAR(a) LABEL_(a, __LINE__)
61
62#define FOREACH(var, col) \
63 do { \
64 int UNIQUE_VAR(_iter); \
65 for(UNIQUE_VAR(_iter)=0; UNIQUE_VAR(_iter)<(col)->capacity; UNIQUE_VAR(_iter)++) { \
66 if(!(col)->list[UNIQUE_VAR(_iter)]) continue; \
67 var = (col)->list[UNIQUE_VAR(_iter)];
68
69#define ENDFOREACH \
70 } \
71 } while(0);
72
73#ifndef HAVE_STPCPY
74char *stpcpy(char * s1, const char * s2);
75#endif
76char *string_concat(const char *str, ...);
77
78int buffer_read_from_filename(const char *filename, char **buffer, uint64_t *length);
79int buffer_write_to_filename(const char *filename, const char *buffer, uint64_t length);
80
81enum plist_format_t {
82 PLIST_FORMAT_XML,
83 PLIST_FORMAT_BINARY
84};
85
86int plist_read_from_filename(plist_t *plist, const char *filename);
87int plist_write_to_filename(plist_t plist, const char *filename, enum plist_format_t format);
88
89uint64_t mstime64(void); 46uint64_t mstime64(void);
90void get_tick_count(struct timeval * tv); 47void get_tick_count(struct timeval * tv);
91 48