From 71e7ce5d8e3153342494685d60d7ff16d9b29101 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 30 Dec 2008 19:24:39 +0100 Subject: main: use the GLib main loop This is a rather huge patch, which unfortunately cannot be splitted. Instead of using our custom ioops.h library, convert everything to use the GLib main loop. --- src/Makefile.am | 2 - src/client.c | 139 ++++++++++++++-------------- src/client.h | 1 - src/ioops.c | 87 ------------------ src/ioops.h | 59 ------------ src/listen.c | 44 +++++---- src/listen.h | 7 -- src/main.c | 50 ++++++---- src/main_notify.c | 36 +++----- src/main_notify.h | 3 + src/zeroconf-avahi.c | 241 +++---------------------------------------------- src/zeroconf-bonjour.c | 71 ++++----------- 12 files changed, 173 insertions(+), 567 deletions(-) delete mode 100644 src/ioops.c delete mode 100644 src/ioops.h (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 6a8894cbe..62dede538 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -78,7 +78,6 @@ mpd_headers = \ strset.h \ utils.h \ volume.h \ - ioops.h \ zeroconf.h zeroconf-internal.h \ locate.h \ stored_playlist.h \ @@ -120,7 +119,6 @@ mpd_SOURCES = \ input_stream.c \ input_file.c \ client.c \ - ioops.c \ list.c \ listen.c \ log.c \ diff --git a/src/client.c b/src/client.c index c5d7d75bc..77fd6c895 100644 --- a/src/client.c +++ b/src/client.c @@ -22,7 +22,6 @@ #include "listen.h" #include "permission.h" #include "utils.h" -#include "ioops.h" #include "main_notify.h" #include "dlist.h" #include "idle.h" @@ -78,6 +77,8 @@ struct client { size_t bufferPos; int fd; /* file descriptor; -1 if expired */ + GIOChannel *channel; + unsigned permission; /** the uid of the client process, or -1 if unknown */ @@ -134,12 +135,20 @@ void client_set_permission(struct client *client, unsigned permission) static inline void client_set_expired(struct client *client) { + if (client->channel != NULL) { + g_io_channel_unref(client->channel); + client->channel = NULL; + } + if (client->fd >= 0) { xclose(client->fd); client->fd = -1; } } +static gboolean +client_in_event(GIOChannel *source, GIOCondition condition, gpointer data); + static void client_init(struct client *client, int fd) { static unsigned int next_client_num; @@ -152,6 +161,10 @@ static void client_init(struct client *client, int fd) client->bufferPos = 0; client->fd = fd; set_nonblocking(fd); + + client->channel = g_io_channel_unix_new(client->fd); + g_io_add_watch(client->channel, G_IO_IN, client_in_event, client); + client->lastTime = time(NULL); client->cmd_list = NULL; client->deferred_send = g_queue_new(); @@ -436,91 +449,81 @@ static int client_read(struct client *client) return COMMAND_RETURN_CLOSE; } -static void client_manager_register_read_fd(fd_set * fds, int *fdmax) +static gboolean +client_out_event(G_GNUC_UNUSED GIOChannel *source, + G_GNUC_UNUSED GIOCondition condition, + gpointer data); + +static gboolean +client_in_event(G_GNUC_UNUSED GIOChannel *source, + G_GNUC_UNUSED GIOCondition condition, + gpointer data) { - struct client *client; + struct client *client = data; + int ret; - FD_ZERO(fds); - addListenSocketsToFdSet(fds, fdmax); + if (client_is_expired(client)) + return false; - list_for_each_entry(client, &clients, siblings) { - if (!client_is_expired(client) && - g_queue_is_empty(client->deferred_send)) { - FD_SET(client->fd, fds); - if (*fdmax < client->fd) - *fdmax = client->fd; - } - } -} + client->lastTime = time(NULL); -static void client_manager_register_write_fd(fd_set * fds, int *fdmax) -{ - struct client *client; + ret = client_read(client); + switch (ret) { + case COMMAND_RETURN_KILL: + client_close(client); + g_main_loop_quit(NULL); + return false; - FD_ZERO(fds); + case COMMAND_RETURN_CLOSE: + client_close(client); + return false; + } - list_for_each_entry(client, &clients, siblings) { - if (client->fd >= 0 && !client_is_expired(client) - && !g_queue_is_empty(client->deferred_send)) { - FD_SET(client->fd, fds); - if (*fdmax < client->fd) - *fdmax = client->fd; - } + if (client_is_expired(client)) { + client_close(client); + return false; } -} -int client_manager_io(void) -{ - fd_set rfds; - fd_set wfds; - fd_set efds; - struct client *client, *n; - int ret; - int fdmax = 0; + if (!g_queue_is_empty(client->deferred_send)) { + /* deferred buffers exist: schedule write */ + g_io_add_watch(client->channel, G_IO_OUT, + client_out_event, client); + return false; + } - FD_ZERO( &efds ); - client_manager_register_read_fd(&rfds, &fdmax); - client_manager_register_write_fd(&wfds, &fdmax); + /* read more */ + return true; +} - registered_IO_add_fds(&fdmax, &rfds, &wfds, &efds); +static gboolean +client_out_event(G_GNUC_UNUSED GIOChannel *source, + G_GNUC_UNUSED GIOCondition condition, + gpointer data) +{ + struct client *client = data; - main_notify_lock(); - ret = select(fdmax + 1, &rfds, &wfds, &efds, NULL); - main_notify_unlock(); + if (client_is_expired(client)) + return false; - if (ret < 0) { - if (errno == EINTR) - return 0; + client_write_deferred(client); - g_error("select() failed: %s", strerror(errno)); + if (client_is_expired(client)) { + client_close(client); + return false; } - registered_IO_consume_fds(&ret, &rfds, &wfds, &efds); - - getConnections(&rfds); - - list_for_each_entry_safe(client, n, &clients, siblings) { - if (FD_ISSET(client->fd, &rfds)) { - ret = client_read(client); - if (ret == COMMAND_RETURN_KILL) - return COMMAND_RETURN_KILL; - if (ret == COMMAND_RETURN_CLOSE) { - client_close(client); - continue; - } - - assert(!client_is_expired(client)); + client->lastTime = time(NULL); - client->lastTime = time(NULL); - } - if (!client_is_expired(client) && - FD_ISSET(client->fd, &wfds)) { - client_write_deferred(client); - client->lastTime = time(NULL); - } + if (g_queue_is_empty(client->deferred_send)) { + /* done sending deferred buffers exist: schedule + read */ + g_io_add_watch(client->channel, G_IO_IN, + client_in_event, client); + return false; } - return 0; + /* write more */ + return true; } void client_manager_init(void) diff --git a/src/client.h b/src/client.h index e58b629bd..dabd1c576 100644 --- a/src/client.h +++ b/src/client.h @@ -29,7 +29,6 @@ struct sockaddr; void client_manager_init(void); void client_manager_deinit(void); -int client_manager_io(void); void client_manager_expire(void); void client_new(int fd, const struct sockaddr *addr, int uid); diff --git a/src/ioops.c b/src/ioops.c deleted file mode 100644 index 8c3ff9fba..000000000 --- a/src/ioops.c +++ /dev/null @@ -1,87 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * 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 of the License, or - * (at your option) any later version. - * - * 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 - */ - -#include "ioops.h" - -#include -#include - -/* Eventually the listener protocol will use this, too */ - -/* - * functions and variables in this file are only used by a single thread and - * thus do not need to be thread-safe - */ - -/* List of registered external IO handlers */ -static struct ioOps *ioList; - -/* Add fds for all registered IO handlers */ -void registered_IO_add_fds(int *fdmax, - fd_set * rfds, fd_set * wfds, fd_set * efds) -{ - struct ioOps *o = ioList; - - while (o) { - struct ioOps *current = o; - int fdnum; - - assert(current->fdset); - fdnum = current->fdset(rfds, wfds, efds); - if (*fdmax < fdnum) - *fdmax = fdnum; - o = o->next; - } -} - -/* Consume fds for all registered IO handlers */ -void registered_IO_consume_fds(int *selret, - fd_set * rfds, fd_set * wfds, fd_set * efds) -{ - struct ioOps *o = ioList; - - while (o) { - struct ioOps *current = o; - - assert(current->consume); - *selret = current->consume(*selret, rfds, wfds, efds); - o = o->next; - } -} - -void registerIO(struct ioOps *ops) -{ - assert(ops != NULL); - - ops->next = ioList; - ioList = ops; - ops->prev = NULL; - if (ops->next) - ops->next->prev = ops; -} - -void deregisterIO(struct ioOps *ops) -{ - assert(ops != NULL); - - if (ioList == ops) - ioList = ops->next; - else if (ops->prev != NULL) - ops->prev->next = ops->next; -} - diff --git a/src/ioops.h b/src/ioops.h deleted file mode 100644 index 7a568e403..000000000 --- a/src/ioops.h +++ /dev/null @@ -1,59 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * 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 of the License, or - * (at your option) any later version. - * - * 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 - */ - -#ifndef MPD_IOOPS_H -#define MPD_IOOPS_H - -#include - -struct ioOps { - struct ioOps *prev, *next; - - /* - * Called before each 'select' statement. - * To register for IO, call FD_SET for each required queue - * Return the highest fd number you registered - */ - int (*fdset) (fd_set * rfds, fd_set * wfds, fd_set * efds); - - /* - * Called after each 'select' statement. - * fdCount is the number of fds total in all sets. It may be 0. - * For each fd you registered for in (fdset), you should FD_CLR it from the - * appropriate queue(s). - * Return the total number of fds left in all sets (Ie, return fdCount - * minus the number of times you called FD_CLR). - */ - int (*consume) (int fdCount, fd_set * rfds, fd_set * wfds, - fd_set * efds); -}; - -/* Call this to register your io operation handler struct */ -void registerIO(struct ioOps *ops); - -/* Call this to deregister your io operation handler struct */ -void deregisterIO(struct ioOps *ops); - -/* Add fds for all registered IO handlers */ -void registered_IO_add_fds(int *fdmax, - fd_set * rfds, fd_set * wfds, fd_set * efds); - -/* Consume fds for all registered IO handlers */ -void registered_IO_consume_fds(int *selret, - fd_set * rfds, fd_set * wfds, fd_set * efds); -#endif diff --git a/src/listen.c b/src/listen.c index e1cb325cf..94c965f28 100644 --- a/src/listen.c +++ b/src/listen.c @@ -55,6 +55,9 @@ static int *listenSockets; static int numberOfListenSockets; int boundPort; +static gboolean +listen_in_event(GIOChannel *source, GIOCondition condition, gpointer data); + static int establishListen(int pf, const struct sockaddr *addrp, socklen_t addrlen) { @@ -63,6 +66,7 @@ static int establishListen(int pf, const struct sockaddr *addrp, #ifdef HAVE_STRUCT_UCRED int passcred = 1; #endif + GIOChannel *channel; if ((sock = socket(pf, SOCK_STREAM, 0)) < 0) g_error("socket < 0"); @@ -90,6 +94,11 @@ static int establishListen(int pf, const struct sockaddr *addrp, listenSockets[numberOfListenSockets - 1] = sock; + channel = g_io_channel_unix_new(sock); + g_io_add_watch(channel, G_IO_IN, + listen_in_event, GINT_TO_POINTER(sock)); + g_io_channel_unref(channel); + return 0; } @@ -223,17 +232,6 @@ void listenOnPort(void) } while ((param = getNextConfigParam(CONF_BIND_TO_ADDRESS, param))); } -void addListenSocketsToFdSet(fd_set * fds, int *fdmax) -{ - int i; - - for (i = 0; i < numberOfListenSockets; i++) { - FD_SET(listenSockets[i], fds); - if (listenSockets[i] > *fdmax) - *fdmax = listenSockets[i]; - } -} - void closeAllListenSockets(void) { int i; @@ -266,21 +264,21 @@ static int get_remote_uid(int fd) #endif } -void getConnections(fd_set * fds) +static gboolean +listen_in_event(G_GNUC_UNUSED GIOChannel *source, + G_GNUC_UNUSED GIOCondition condition, + gpointer data) { - int i; - int fd = 0; + int listen_fd = GPOINTER_TO_INT(data), fd; struct sockaddr sockAddr; socklen_t socklen = sizeof(sockAddr); - for (i = 0; i < numberOfListenSockets; i++) { - if (FD_ISSET(listenSockets[i], fds)) { - if ((fd = accept(listenSockets[i], &sockAddr, &socklen)) - >= 0) { - client_new(fd, &sockAddr, get_remote_uid(fd)); - } else if (fd < 0 && errno != EINTR) { - g_warning("Problems accept()'ing"); - } - } + fd = accept(listen_fd, &sockAddr, &socklen); + if (fd >= 0) { + client_new(fd, &sockAddr, get_remote_uid(fd)); + } else if (fd < 0 && errno != EINTR) { + g_warning("Problems accept()'ing"); } + + return true; } diff --git a/src/listen.h b/src/listen.h index 625cb006c..f89c4f030 100644 --- a/src/listen.h +++ b/src/listen.h @@ -19,17 +19,10 @@ #ifndef MPD_LISTEN_H #define MPD_LISTEN_H -#include - extern int boundPort; void listenOnPort(void); -void getConnections(fd_set * fds); - void closeAllListenSockets(void); -/* fdmax should be initialized to something */ -void addListenSocketsToFdSet(fd_set * fds, int *fdmax); - #endif diff --git a/src/main.c b/src/main.c index 580f4bf8b..a33650ae0 100644 --- a/src/main.c +++ b/src/main.c @@ -180,9 +180,34 @@ static void killFromPidFile(void) #endif } +static gboolean +timer_save_state_file(G_GNUC_UNUSED gpointer data) +{ + g_debug("Saving state file"); + write_state_file(); + return true; +} + +void +main_notify_triggered(void) +{ + unsigned flags; + + syncPlayerAndPlaylist(); + client_manager_expire(); + reap_update_task(); + + /* send "idle" notificaions to all subscribed + clients */ + flags = idle_get(); + if (flags != 0) + client_manager_idle_add(flags); +} + int main(int argc, char *argv[]) { Options options; + GMainLoop *main_loop; clock_t start; GTimer *save_state_timer; @@ -216,6 +241,8 @@ int main(int argc, char *argv[]) changeToUser(); + main_loop = g_main_loop_new(NULL, FALSE); + path_global_init(); mapper_init(); initPermissions(); @@ -258,26 +285,15 @@ int main(int argc, char *argv[]) save_state_timer = g_timer_new(); - while (COMMAND_RETURN_KILL != client_manager_io() && - COMMAND_RETURN_KILL != handlePendingSignals()) { - unsigned flags; + g_timeout_add(5 * 60 * 1000, timer_save_state_file, NULL); - syncPlayerAndPlaylist(); - client_manager_expire(); - reap_update_task(); + /* run the main loop */ - /* send "idle" notificaions to all subscribed - clients */ - flags = idle_get(); - if (flags != 0) - client_manager_idle_add(flags); + g_main_loop_run(main_loop); - if (g_timer_elapsed(save_state_timer, NULL) >= 5 * 60) { - g_debug("Saving state file"); - write_state_file(); - g_timer_start(save_state_timer); - } - } + /* cleanup */ + + g_main_loop_unref(main_loop); g_timer_destroy(save_state_timer); diff --git a/src/main_notify.c b/src/main_notify.c index f821f76aa..e9552efbc 100644 --- a/src/main_notify.c +++ b/src/main_notify.c @@ -20,25 +20,15 @@ #include "main_notify.h" #include "utils.h" -#include "ioops.h" #include "log.h" #include #include #include -static struct ioOps main_notify_IO; static int main_pipe[2]; GThread *main_task; -static int ioops_fdset(fd_set * rfds, - G_GNUC_UNUSED fd_set * wfds, - G_GNUC_UNUSED fd_set * efds) -{ - FD_SET(main_pipe[0], rfds); - return main_pipe[0]; -} - static void consume_pipe(void) { char buffer[256]; @@ -48,20 +38,20 @@ static void consume_pipe(void) FATAL("error reading from pipe: %s\n", strerror(errno)); } -static int ioops_consume(int fd_count, fd_set * rfds, - G_GNUC_UNUSED fd_set * wfds, - G_GNUC_UNUSED fd_set * efds) +static gboolean +main_notify_event(G_GNUC_UNUSED GIOChannel *source, + G_GNUC_UNUSED GIOCondition condition, + G_GNUC_UNUSED gpointer data) { - if (FD_ISSET(main_pipe[0], rfds)) { - consume_pipe(); - FD_CLR(main_pipe[0], rfds); - fd_count--; - } - return fd_count; + consume_pipe(); + main_notify_triggered(); + return true; } void init_main_notify(void) { + GIOChannel *channel; + main_task = g_thread_self(); if (pipe(main_pipe) < 0) @@ -69,15 +59,15 @@ void init_main_notify(void) if (set_nonblocking(main_pipe[1]) < 0) g_error("Couldn't set non-blocking I/O: %s", strerror(errno)); - main_notify_IO.fdset = ioops_fdset; - main_notify_IO.consume = ioops_consume; - registerIO(&main_notify_IO); + channel = g_io_channel_unix_new(main_pipe[0]); + g_io_add_watch(channel, G_IO_IN, main_notify_event, NULL); + g_io_channel_unref(channel); + main_task = g_thread_self(); } void deinit_main_notify(void) { - deregisterIO(&main_notify_IO); xclose(main_pipe[0]); xclose(main_pipe[1]); } diff --git a/src/main_notify.h b/src/main_notify.h index 26aad41a0..3b87cb1ab 100644 --- a/src/main_notify.h +++ b/src/main_notify.h @@ -37,4 +37,7 @@ void main_notify_lock(void); void main_notify_unlock(void); +void +main_notify_triggered(void); + #endif /* MAIN_NOTIFY_H */ diff --git a/src/zeroconf-avahi.c b/src/zeroconf-avahi.c index 688e2ab24..b522d8feb 100644 --- a/src/zeroconf-avahi.c +++ b/src/zeroconf-avahi.c @@ -19,7 +19,6 @@ #include "zeroconf-internal.h" #include "listen.h" #include "utils.h" -#include "ioops.h" #include @@ -31,148 +30,18 @@ #include #include +#include + #undef G_LOG_DOMAIN #define G_LOG_DOMAIN "avahi" -static struct ioOps zeroConfIo; - static char *avahiName; static int avahiRunning; -static AvahiPoll avahiPoll; +static AvahiGLibPoll *avahi_glib_poll; +static const AvahiPoll *avahi_poll; static AvahiClient *avahiClient; static AvahiEntryGroup *avahiGroup; -static int avahiFdset(fd_set * rfds, fd_set * wfds, fd_set * efds); -static int avahiFdconsume(int fdCount, fd_set * rfds, fd_set * wfds, - fd_set * efds); - -struct AvahiWatch { - struct AvahiWatch *prev; - struct AvahiWatch *next; - int fd; - AvahiWatchEvent requestedEvent; - AvahiWatchEvent observedEvent; - AvahiWatchCallback callback; - void *userdata; -}; - -struct AvahiTimeout { - struct AvahiTimeout *prev; - struct AvahiTimeout *next; - struct timeval expiry; - int enabled; - AvahiTimeoutCallback callback; - void *userdata; -}; - -static AvahiWatch *avahiWatchList; -static AvahiTimeout *avahiTimeoutList; - -static AvahiWatch *avahiWatchNew(G_GNUC_UNUSED const AvahiPoll * api, int fd, - AvahiWatchEvent event, - AvahiWatchCallback callback, void *userdata) -{ - struct AvahiWatch *newWatch = xmalloc(sizeof(struct AvahiWatch)); - - newWatch->fd = fd; - newWatch->requestedEvent = event; - newWatch->observedEvent = 0; - newWatch->callback = callback; - newWatch->userdata = userdata; - - /* Insert at front of list */ - newWatch->next = avahiWatchList; - avahiWatchList = newWatch; - newWatch->prev = NULL; - if (newWatch->next) - newWatch->next->prev = newWatch; - - return newWatch; -} - -static void avahiWatchUpdate(AvahiWatch * w, AvahiWatchEvent event) -{ - assert(w != NULL); - w->requestedEvent = event; -} - -static AvahiWatchEvent avahiWatchGetEvents(AvahiWatch * w) -{ - assert(w != NULL); - return w->observedEvent; -} - -static void avahiWatchFree(AvahiWatch * w) -{ - assert(w != NULL); - - if (avahiWatchList == w) - avahiWatchList = w->next; - else if (w->prev != NULL) - w->prev->next = w->next; - - free(w); -} - -static void avahiCheckExpiry(AvahiTimeout * t) -{ - assert(t != NULL); - if (t->enabled) { - struct timeval now; - gettimeofday(&now, NULL); - if (timercmp(&now, &(t->expiry), >)) { - t->enabled = 0; - t->callback(t, t->userdata); - } - } -} - -static void avahiTimeoutUpdate(AvahiTimeout * t, const struct timeval *tv) -{ - assert(t != NULL); - if (tv) { - t->enabled = 1; - t->expiry.tv_sec = tv->tv_sec; - t->expiry.tv_usec = tv->tv_usec; - } else { - t->enabled = 0; - } -} - -static void avahiTimeoutFree(AvahiTimeout * t) -{ - assert(t != NULL); - - if (avahiTimeoutList == t) - avahiTimeoutList = t->next; - else if (t->prev != NULL) - t->prev->next = t->next; - - free(t); -} - -static AvahiTimeout *avahiTimeoutNew(G_GNUC_UNUSED const AvahiPoll * api, - const struct timeval *tv, - AvahiTimeoutCallback callback, - void *userdata) -{ - struct AvahiTimeout *newTimeout = xmalloc(sizeof(struct AvahiTimeout)); - - newTimeout->callback = callback; - newTimeout->userdata = userdata; - - avahiTimeoutUpdate(newTimeout, tv); - - /* Insert at front of list */ - newTimeout->next = avahiTimeoutList; - avahiTimeoutList = newTimeout; - newTimeout->prev = NULL; - if (newTimeout->next) - newTimeout->next->prev = newTimeout; - - return newTimeout; -} - static void avahiRegisterService(AvahiClient * c); /* Callback when the EntryGroup changes state */ @@ -297,7 +166,7 @@ static void avahiClientCallback(AvahiClient * c, AvahiClientState state, if (avahiClient) avahi_client_free(avahiClient); avahiClient = - avahi_client_new(&avahiPoll, + avahi_client_new(avahi_poll, AVAHI_CLIENT_NO_FAIL, avahiClientCallback, NULL, &reason); @@ -342,84 +211,6 @@ static void avahiClientCallback(AvahiClient * c, AvahiClientState state, } } -static int avahiFdset(fd_set * rfds, fd_set * wfds, fd_set * efds) -{ - AvahiWatch *w; - int maxfd = -1; - if (!avahiRunning) - return maxfd; - for (w = avahiWatchList; w != NULL; w = w->next) { - if (w->requestedEvent & AVAHI_WATCH_IN) { - FD_SET(w->fd, rfds); - } - if (w->requestedEvent & AVAHI_WATCH_OUT) { - FD_SET(w->fd, wfds); - } - if (w->requestedEvent & AVAHI_WATCH_ERR) { - FD_SET(w->fd, efds); - } - if (w->requestedEvent & AVAHI_WATCH_HUP) { - g_warning("No support for HUP events! (ignoring)"); - } - - if (w->fd > maxfd) - maxfd = w->fd; - } - return maxfd; -} - -static int avahiFdconsume(int fdCount, fd_set * rfds, fd_set * wfds, - fd_set * efds) -{ - int retval = fdCount; - AvahiTimeout *t; - AvahiWatch *w = avahiWatchList; - - while (w != NULL && retval > 0) { - AvahiWatch *current = w; - current->observedEvent = 0; - if (FD_ISSET(current->fd, rfds)) { - current->observedEvent |= AVAHI_WATCH_IN; - FD_CLR(current->fd, rfds); - retval--; - } - if (FD_ISSET(current->fd, wfds)) { - current->observedEvent |= AVAHI_WATCH_OUT; - FD_CLR(current->fd, wfds); - retval--; - } - if (FD_ISSET(current->fd, efds)) { - current->observedEvent |= AVAHI_WATCH_ERR; - FD_CLR(current->fd, efds); - retval--; - } - - /* Advance to the next one right now, in case the callback - * removes itself - */ - w = w->next; - - if (current->observedEvent && avahiRunning) { - current->callback(current, current->fd, - current->observedEvent, - current->userdata); - } - } - - t = avahiTimeoutList; - while (t != NULL && avahiRunning) { - AvahiTimeout *current = t; - - /* Advance to the next one right now, in case the callback - * removes itself - */ - t = t->next; - avahiCheckExpiry(current); - } - - return retval; -} - void init_avahi(const char *serviceName) { int error; @@ -432,16 +223,10 @@ void init_avahi(const char *serviceName) avahiRunning = 1; - avahiPoll.userdata = NULL; - avahiPoll.watch_new = avahiWatchNew; - avahiPoll.watch_update = avahiWatchUpdate; - avahiPoll.watch_get_events = avahiWatchGetEvents; - avahiPoll.watch_free = avahiWatchFree; - avahiPoll.timeout_new = avahiTimeoutNew; - avahiPoll.timeout_update = avahiTimeoutUpdate; - avahiPoll.timeout_free = avahiTimeoutFree; + avahi_glib_poll = avahi_glib_poll_new(NULL, G_PRIORITY_DEFAULT); + avahi_poll = avahi_glib_poll_get(avahi_glib_poll); - avahiClient = avahi_client_new(&avahiPoll, AVAHI_CLIENT_NO_FAIL, + avahiClient = avahi_client_new(avahi_poll, AVAHI_CLIENT_NO_FAIL, avahiClientCallback, NULL, &error); if (!avahiClient) { @@ -450,10 +235,6 @@ void init_avahi(const char *serviceName) goto fail; } - zeroConfIo.fdset = avahiFdset; - zeroConfIo.consume = avahiFdconsume; - registerIO(&zeroConfIo); - return; fail: @@ -463,7 +244,6 @@ fail: void avahi_finish(void) { g_debug("Shutting down interface"); - deregisterIO(&zeroConfIo); if (avahiGroup) { avahi_entry_group_free(avahiGroup); @@ -475,6 +255,11 @@ void avahi_finish(void) avahiClient = NULL; } + if (avahi_glib_poll != NULL) { + avahi_glib_poll_free(avahi_glib_poll); + avahi_glib_poll = NULL; + } + avahi_free(avahiName); avahiName = NULL; } diff --git a/src/zeroconf-bonjour.c b/src/zeroconf-bonjour.c index 27260ee99..bd613c056 100644 --- a/src/zeroconf-bonjour.c +++ b/src/zeroconf-bonjour.c @@ -18,7 +18,6 @@ #include "zeroconf-internal.h" #include "listen.h" -#include "ioops.h" #include @@ -27,51 +26,8 @@ #undef G_LOG_DOMAIN #define G_LOG_DOMAIN "bonjour" -static struct ioOps zeroConfIo; - static DNSServiceRef dnsReference; - -static int -dnsRegisterFdset(fd_set *rfds, G_GNUC_UNUSED fd_set *wfds, - G_GNUC_UNUSED fd_set *efds) -{ - int fd; - - if (dnsReference == NULL) - return -1; - - fd = DNSServiceRefSockFD(dnsReference); - if (fd == -1) - return -1; - - FD_SET(fd, rfds); - - return fd; -} - -static int -dnsRegisterFdconsume(int fdCount, fd_set *rfds, - G_GNUC_UNUSED fd_set *wfds, G_GNUC_UNUSED fd_set *efds) -{ - int fd; - - if (dnsReference == NULL) - return -1; - - fd = DNSServiceRefSockFD(dnsReference); - if (fd == -1) - return -1; - - if (FD_ISSET(fd, rfds)) { - FD_CLR(fd, rfds); - - DNSServiceProcessResult(dnsReference); - - return fdCount - 1; - } - - return fdCount; -} +static GIOChannel *bonjour_channel; static void dnsRegisterCallback(G_GNUC_UNUSED DNSServiceRef sdRef, @@ -84,14 +40,22 @@ dnsRegisterCallback(G_GNUC_UNUSED DNSServiceRef sdRef, if (errorCode != kDNSServiceErr_NoError) { g_warning("Failed to register zeroconf service."); - DNSServiceRefDeallocate(dnsReference); - dnsReference = NULL; - deregisterIO(&zeroConfIo); + bonjour_finish(); } else { g_debug("Registered zeroconf service with name '%s'", name); } } +static gboolean +bonjour_channel_event(G_GNUC_UNUSED GIOChannel *source, + G_GNUC_UNUSED GIOCondition condition, + G_GNUC_UNUSED gpointer data) +{ + DNSServiceProcessResult(dnsReference); + + return dnsReference != NULL; +} + void init_zeroconf_osx(const char *serviceName) { DNSServiceErrorType error = DNSServiceRegister(&dnsReference, @@ -112,14 +76,17 @@ void init_zeroconf_osx(const char *serviceName) return; } - zeroConfIo.fdset = dnsRegisterFdset; - zeroConfIo.consume = dnsRegisterFdconsume; - registerIO(&zeroConfIo); + bonjour_channel = g_io_channel_unix_new(DNSServiceRefSockFD(dnsReference)); + g_io_add_watch(bonjour_channel, G_IO_IN, bonjour_channel_event, NULL); } void bonjour_finish(void) { - deregisterIO(&zeroConfIo); + if (bonjour_channel != NULL) { + g_io_channel_unref(bonjour_channel); + bonjour_channel = NULL; + } + if (dnsReference != NULL) { DNSServiceRefDeallocate(dnsReference); dnsReference = NULL; -- cgit v1.2.3