summaryrefslogtreecommitdiffstats
path: root/usbmuxd/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'usbmuxd/main.c')
-rw-r--r--usbmuxd/main.c201
1 files changed, 201 insertions, 0 deletions
diff --git a/usbmuxd/main.c b/usbmuxd/main.c
new file mode 100644
index 0000000..d39b416
--- /dev/null
+++ b/usbmuxd/main.c
@@ -0,0 +1,201 @@
+/*
+ usbmuxd - iPhone/iPod Touch USB multiplex server daemon
+
+Copyright (C) 2009 Hector Martin "marcan" <hector@marcansoft.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 or version 3.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+#define _BSD_SOURCE
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include "log.h"
+#include "usb.h"
+#include "device.h"
+#include "client.h"
+
+static const char *socket_path = "/tmp/usbmuxd"; //TODO: CHANGEME
+int should_exit;
+
+struct sigaction sa_old;
+
+int create_socket(void) {
+ struct sockaddr_un bind_addr;
+ int listenfd;
+
+ if(unlink(socket_path) == -1 && errno != ENOENT) {
+ usbmuxd_log(LL_FATAL, "unlink(%s) failed: %s", socket_path, strerror(errno));
+ return -1;
+ }
+
+ listenfd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (listenfd == -1) {
+ usbmuxd_log(LL_FATAL, "socket() failed: %s", strerror(errno));
+ return -1;
+ }
+
+ bzero(&bind_addr, sizeof(bind_addr));
+ bind_addr.sun_family = AF_UNIX;
+ strcpy(bind_addr.sun_path, socket_path);
+ if (bind(listenfd, (struct sockaddr*)&bind_addr, sizeof(bind_addr)) != 0) {
+ usbmuxd_log(LL_FATAL, "bind() failed: %s", strerror(errno));
+ return -1;
+ }
+
+ // Start listening
+ if (listen(listenfd, 5) != 0) {
+ usbmuxd_log(LL_FATAL, "listen() failed: %s", strerror(errno));
+ return -1;
+ }
+
+ return listenfd;
+}
+
+void handle_signal(int sig)
+{
+ if(sig == SIGINT) {
+ usbmuxd_log(LL_NOTICE,"Caught SIGINT");
+ } else {
+ usbmuxd_log(LL_NOTICE,"Caught unknown signal %d", sig);
+ }
+ should_exit = 1;
+ sigaction(SIGINT, &sa_old, NULL);
+}
+
+void set_signal_handlers(void)
+{
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(struct sigaction));
+ sa.sa_handler = handle_signal;
+ sigaction(SIGINT, &sa, &sa_old);
+}
+
+int main_loop(int listenfd)
+{
+ int to, cnt, i, dto;
+ struct fdlist pollfds;
+
+ while(!should_exit) {
+ usbmuxd_log(LL_FLOOD, "main_loop iteration");
+ to = usb_get_timeout();
+ usbmuxd_log(LL_FLOOD, "USB timeout is %d ms", to);
+ dto = device_get_timeout();
+ usbmuxd_log(LL_FLOOD, "Device timeout is %d ms", to);
+ if(dto < to)
+ to = dto;
+
+ fdlist_create(&pollfds);
+ fdlist_add(&pollfds, FD_LISTEN, listenfd, POLLIN);
+ usb_get_fds(&pollfds);
+ client_get_fds(&pollfds);
+ usbmuxd_log(LL_FLOOD, "fd count is %d", pollfds.count);
+
+ cnt = poll(pollfds.fds, pollfds.count, to);
+ usbmuxd_log(LL_FLOOD, "poll() returned %d", cnt);
+
+ if(cnt == -1) {
+ if(errno == EINTR && should_exit) {
+ usbmuxd_log(LL_INFO, "event processing interrupted");
+ fdlist_free(&pollfds);
+ return 0;
+ }
+ } else if(cnt == 0) {
+ if(usb_process() < 0) {
+ usbmuxd_log(LL_FATAL, "usb_process() failed");
+ fdlist_free(&pollfds);
+ return -1;
+ }
+ device_check_timeouts();
+ } else {
+ int done_usb = 0;
+ for(i=0; i<pollfds.count; i++) {
+ if(pollfds.fds[i].revents) {
+ if(!done_usb && pollfds.owners[i] == FD_USB) {
+ if(usb_process() < 0) {
+ usbmuxd_log(LL_FATAL, "usb_process() failed");
+ fdlist_free(&pollfds);
+ return -1;
+ }
+ done_usb = 1;
+ }
+ if(pollfds.owners[i] == FD_LISTEN) {
+ if(client_accept(listenfd) < 0) {
+ usbmuxd_log(LL_FATAL, "client_accept() failed");
+ fdlist_free(&pollfds);
+ return -1;
+ }
+ }
+ if(pollfds.owners[i] == FD_CLIENT) {
+ client_process(pollfds.fds[i].fd, pollfds.fds[i].revents);
+ }
+ }
+ }
+ }
+ fdlist_free(&pollfds);
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ int listenfd;
+ int res;
+
+ usbmuxd_log(LL_NOTICE, "usbmux v0.1 starting up");
+ should_exit = 0;
+
+ set_signal_handlers();
+
+ usbmuxd_log(LL_INFO, "Creating socket");
+ listenfd = create_socket();
+ if(listenfd < 0)
+ return 1;
+
+ client_init();
+ device_init();
+ usbmuxd_log(LL_INFO, "Initializing USB");
+ if((res = usb_init()) < 0)
+ return 2;
+ usbmuxd_log(LL_INFO, "%d device%s detected", res, (res==1)?"":"s");
+
+ usbmuxd_log(LL_NOTICE, "Initialization complete");
+
+ res = main_loop(listenfd);
+ if(res < 0)
+ usbmuxd_log(LL_FATAL, "main_loop failed");
+
+ usbmuxd_log(LL_NOTICE, "usbmux shutting down");
+ device_kill_connections();
+ usb_shutdown();
+ device_shutdown();
+ client_shutdown();
+ usbmuxd_log(LL_NOTICE, "Shutdown complete");
+
+ if(res < 0)
+ return -res;
+ return 0;
+}