aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2008-12-30 19:24:39 +0100
committerMax Kellermann <max@duempel.org>2008-12-30 19:24:39 +0100
commit71e7ce5d8e3153342494685d60d7ff16d9b29101 (patch)
treeed9893562c16b7f8ab98a5c97bce79bcf1ae2267
parent03e650aa9e9a95575fccd51ec9f669abae52fe7e (diff)
downloadmpd-71e7ce5d8e3153342494685d60d7ff16d9b29101.tar.gz
mpd-71e7ce5d8e3153342494685d60d7ff16d9b29101.tar.xz
mpd-71e7ce5d8e3153342494685d60d7ff16d9b29101.zip
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.
-rw-r--r--configure.ac2
-rw-r--r--src/Makefile.am2
-rw-r--r--src/client.c139
-rw-r--r--src/client.h1
-rw-r--r--src/ioops.c87
-rw-r--r--src/ioops.h59
-rw-r--r--src/listen.c44
-rw-r--r--src/listen.h7
-rw-r--r--src/main.c50
-rw-r--r--src/main_notify.c36
-rw-r--r--src/main_notify.h3
-rw-r--r--src/zeroconf-avahi.c241
-rw-r--r--src/zeroconf-bonjour.c71
13 files changed, 174 insertions, 568 deletions
diff --git a/configure.ac b/configure.ac
index dfcd15832..c05e2f4e8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -909,7 +909,7 @@ esac
if test x$with_zeroconf != xno; then
if test x$with_zeroconf = xavahi || test x$with_zeroconf = xauto; then
- PKG_CHECK_MODULES([AVAHI], [avahi-client],
+ PKG_CHECK_MODULES([AVAHI], [avahi-client avahi-glib],
[found_avahi=1;AC_DEFINE([HAVE_AVAHI], 1, [Define to enable Avahi Zeroconf support])]
MPD_LIBS="$MPD_LIBS $AVAHI_LIBS" MPD_CFLAGS="$MPD_CFLAGS $AVAHI_CFLAGS",
[found_avahi=0])
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 <assert.h>
-#include <stddef.h>
-
-/* 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 <sys/select.h>
-
-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 <sys/select.h>
-
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 <assert.h>
#include <glib.h>
#include <string.h>
-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 <glib.h>
@@ -31,148 +30,18 @@
#include <avahi-common/malloc.h>
#include <avahi-common/error.h>
+#include <avahi-glib/glib-watch.h>
+
#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 <glib.h>
@@ -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;