]> git.meshlink.io Git - catta/commitdiff
* add new priority parameter to avahi_glib_poll_new()
authorLennart Poettering <lennart@poettering.net>
Sun, 14 Aug 2005 22:11:35 +0000 (22:11 +0000)
committerLennart Poettering <lennart@poettering.net>
Sun, 14 Aug 2005 22:11:35 +0000 (22:11 +0000)
* beef up AvahiPoll a little to contain real timeout events
* cleanups in avahi-client
* drop glib dependency
* port to AvahiPoll system
* put some "const"s and "static"s in to make gcc shut up
* change all uses of malloc/free to avahi_malloc/avahi_new/avahi_free

git-svn-id: file:///home/lennart/svn/public/avahi/trunk@324 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe

19 files changed:
avahi-client/Makefile.am
avahi-client/browser.c
avahi-client/client-test.c
avahi-client/client.c
avahi-client/client.h
avahi-client/dbus-watch-glue.c [new file with mode: 0644]
avahi-client/dbus-watch-glue.h [new file with mode: 0644]
avahi-client/entrygroup.c
avahi-client/internal.h
avahi-common/simple-watch.c
avahi-common/watch-test.c
avahi-common/watch.h
avahi-core/avahi-test.c
avahi-core/conformance-test.c
avahi-core/timeeventq.c
avahi-daemon/main.c
avahi-glib/glib-watch-test.c
avahi-glib/glib-watch.c
avahi-glib/glib-watch.h

index 2c80e8468f341f65813364ead0c1bd0da06dc7d9..4b755fc87179d3350b34721b84ad4bc8a8559198 100644 (file)
@@ -35,6 +35,7 @@ avahi_clientinclude_HEADERS = \
 
 noinst_HEADERS = \
        internal.h
+       dbus-watch-glue.h
 
 noinst_PROGRAMS = \
        client-test
@@ -45,11 +46,15 @@ lib_LTLIBRARIES = \
 libavahi_client_la_SOURCES = \
        client.c client.h \
        entrygroup.c \
-       browser.c
+       browser.c \
+       dbus-watch-glue.c
+
+libavahi_client_la_CFLAGS = $(AM_CFLAGS)
+libavahi_client_la_LIBADD = $(AM_LDADD)
 
 client_test_SOURCES = \
        client-test.c
 client_test_CFLAGS = $(AM_CFLAGS)
-client_test_LDADD = $(AM_LDADD) libavahi-client.la ../avahi-common/libavahi-common.la
+client_test_LDADD = $(AM_LDADD) libavahi-client.la ../avahi-common/libavahi-common.la ../avahi-glib/libavahi-glib.la
 
 endif
index a20b5d251224c08fc5ca9c347fc034b2e8ec22f3..e994d2af54d40bab604bba0eb01547e6a7edf9db 100644 (file)
 #include <config.h>
 #endif
 
-#include <avahi-client/client.h>
-#include <avahi-common/dbus.h>
-#include <avahi-common/llist.h>
-#include <avahi-common/error.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <dbus/dbus.h>
 #include <dbus/dbus-glib-lowlevel.h>
 
-#include <stdlib.h>
+#include <avahi-client/client.h>
+#include <avahi-common/dbus.h>
+#include <avahi-common/llist.h>
+#include <avahi-common/error.h>
+#include <avahi-common/malloc.h>
 
 #include "client.h"
 #include "internal.h"
 
 /* AvahiDomainBrowser */
 
-AvahiDomainBrowser* avahi_domain_browser_new (AvahiClient *client, AvahiIfIndex interface, AvahiProtocol protocol, char *domain, AvahiDomainBrowserType btype, AvahiDomainBrowserCallback callback, void *user_data)
+AvahiDomainBrowser* avahi_domain_browser_new (AvahiClient *client, AvahiIfIndex interface, AvahiProtocol protocol, const char *domain, AvahiDomainBrowserType btype, AvahiDomainBrowserCallback callback, void *user_data)
 {
     AvahiDomainBrowser *tmp = NULL;
     DBusMessage *message = NULL, *reply;
@@ -70,7 +70,7 @@ AvahiDomainBrowser* avahi_domain_browser_new (AvahiClient *client, AvahiIfIndex
     if (dbus_error_is_set (&error) || path == NULL)
         goto dbus_error;
 
-    tmp = malloc (sizeof (AvahiDomainBrowser));
+    tmp = avahi_new (AvahiDomainBrowser, 1);
     tmp->client = client;
     tmp->callback = callback;
     tmp->user_data = user_data;
@@ -107,12 +107,12 @@ avahi_domain_browser_free (AvahiDomainBrowser *b)
 
     AVAHI_LLIST_REMOVE(AvahiDomainBrowser, domain_browsers, client->domain_browsers, b);
 
-    free (b);
+    avahi_free (b);
 
     return avahi_client_set_errno (client, AVAHI_OK);
 }
 
-char*
+const char*
 avahi_domain_browser_path (AvahiDomainBrowser *b)
 {
     return b->path;
@@ -161,7 +161,7 @@ out:
 }
 
 /* AvahiServiceTypeBrowser */
-AvahiServiceTypeBrowser* avahi_service_type_browser_new (AvahiClient *client, AvahiIfIndex interface, AvahiProtocol protocol, char *domain, AvahiServiceTypeBrowserCallback callback, void *user_data)
+AvahiServiceTypeBrowser* avahi_service_type_browser_new (AvahiClient *client, AvahiIfIndex interface, AvahiProtocol protocol, const char *domain, AvahiServiceTypeBrowserCallback callback, void *user_data)
 {
     AvahiServiceTypeBrowser *tmp = NULL;
     DBusMessage *message = NULL, *reply;
@@ -192,7 +192,7 @@ AvahiServiceTypeBrowser* avahi_service_type_browser_new (AvahiClient *client, Av
     if (dbus_error_is_set (&error) || path == NULL)
         goto dbus_error;
 
-    tmp = malloc (sizeof (AvahiServiceTypeBrowser));
+    tmp = avahi_new(AvahiServiceTypeBrowser, 1);
     tmp->client = client;
     tmp->callback = callback;
     tmp->user_data = user_data;
@@ -229,12 +229,12 @@ avahi_service_type_browser_free (AvahiServiceTypeBrowser *b)
 
     AVAHI_LLIST_REMOVE(AvahiServiceTypeBrowser, service_type_browsers, b->client->service_type_browsers, b);
 
-    free (b);
+    avahi_free (b);
 
     return avahi_client_set_errno (client, AVAHI_OK);
 }
 
-char*
+const char*
 avahi_service_type_browser_path (AvahiServiceTypeBrowser *b)
 {
     return b->path;
@@ -288,7 +288,7 @@ out:
 
 /* AvahiServiceBrowser */
 
-AvahiServiceBrowser* avahi_service_browser_new (AvahiClient *client, AvahiIfIndex interface, AvahiProtocol protocol, char *type, char *domain, AvahiServiceBrowserCallback callback, void *user_data)
+AvahiServiceBrowser* avahi_service_browser_new (AvahiClient *client, AvahiIfIndex interface, AvahiProtocol protocol, const char *type, const char *domain, AvahiServiceBrowserCallback callback, void *user_data)
 {
     AvahiServiceBrowser *tmp = NULL;
     DBusMessage *message = NULL, *reply;
@@ -322,7 +322,7 @@ AvahiServiceBrowser* avahi_service_browser_new (AvahiClient *client, AvahiIfInde
     if (dbus_error_is_set (&error) || path == NULL)
         goto dbus_error;
 
-    tmp = malloc (sizeof (AvahiServiceBrowser));
+    tmp = avahi_new(AvahiServiceBrowser, 1);
     tmp->client = client;
     tmp->callback = callback;
     tmp->user_data = user_data;
@@ -359,12 +359,12 @@ avahi_service_browser_free (AvahiServiceBrowser *b)
 
     AVAHI_LLIST_REMOVE(AvahiServiceBrowser, service_browsers, b->client->service_browsers, b);
 
-    free (b);
+    avahi_free (b);
 
     return avahi_client_set_errno (client, AVAHI_OK);
 }
 
-char*
+const char*
 avahi_service_browser_path (AvahiServiceBrowser *b)
 {
     return b->path;
index 352ee58ee54923fe9b9a2402c3a4167dd549c4b6..2189467a25a4cb6ba4b25ef68622b13d67cfe92e 100644 (file)
 
 #include <avahi-client/client.h>
 #include <avahi-common/error.h>
+#include <avahi-glib/glib-watch.h>
+#include <avahi-glib/glib-malloc.h>
 #include <stdio.h>
 #include <glib.h>
 
-void
+static void
 avahi_client_callback (AvahiClient *c, AvahiClientState state, void *user_data)
 {
     printf ("XXX: Callback on client, state -> %d, data -> %s\n", state, (char*)user_data);
 }
 
-void
+static void
 avahi_entry_group_callback (AvahiEntryGroup *g, AvahiEntryGroupState state, void *user_data)
 {
     printf ("XXX: Callback on %s, state -> %d, data -> %s\n", avahi_entry_group_path (g), state, (char*)user_data);
 }
 
-void
-avahi_domain_browser_callback (AvahiDomainBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, char *domain, void *user_data)
+static void
+avahi_domain_browser_callback (AvahiDomainBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *domain, void *user_data)
 {
     printf ("XXX: Callback on %s, interface (%d), protocol (%d), event (%d), domain (%s), data (%s)\n", avahi_domain_browser_path (b), interface, protocol, event, domain, (char*)user_data);
 }
 
-void
-avahi_service_browser_callback (AvahiServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, char *name, char *type, char *domain, void *user_data)
+static void
+avahi_service_browser_callback (AvahiServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, void *user_data)
 {
     printf ("XXX: Callback on %s, interface (%d), protocol (%d), event (%d), name (%s), type (%s), domain (%s), data (%s)\n", avahi_service_browser_path (b), interface, protocol, event, name, type, domain, (char*)user_data);
 }
 
-void
-avahi_service_type_browser_callback (AvahiServiceTypeBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, char *type, char *domain, void *user_data)
+static void
+avahi_service_type_browser_callback (AvahiServiceTypeBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *type, const char *domain, void *user_data)
 {
     printf ("XXX: Callback on %s, interface (%d), protocol (%d), event (%d), type (%s), domain (%s), data (%s)\n", avahi_service_type_browser_path (b), interface, protocol, event, type, domain, (char*)user_data);
 }
 
-gboolean
+static gboolean
 test_free_domain_browser (gpointer data)
 {
-    printf ("XXX: freeing domain browser\n");
     AvahiServiceBrowser *b = data;
+    printf ("XXX: freeing domain browser\n");
     avahi_service_browser_free (b);
     return FALSE;
 }
 
-gboolean
+static gboolean
 test_free_entry_group (gpointer data)
 {
-    printf ("XXX: freeing entry group\n");
     AvahiEntryGroup *g = data;
+    printf ("XXX: freeing entry group\n");
     avahi_entry_group_free (g);
     return FALSE;
 }
@@ -85,11 +87,15 @@ main (int argc, char *argv[])
     AvahiDomainBrowser *domain;
     AvahiServiceBrowser *sb;
     AvahiServiceTypeBrowser *st;
+    AvahiGLibPoll *glib_poll;
     char *ret;
 
+    avahi_set_allocator(avahi_glib_allocator());
+
+    glib_poll = avahi_glib_poll_new(NULL, G_PRIORITY_DEFAULT);
     loop = g_main_loop_new (NULL, FALSE);
     
-    avahi = avahi_client_new (avahi_client_callback, "omghai2u");
+    avahi = avahi_client_new (avahi_glib_poll_get(glib_poll), avahi_client_callback, "omghai2u");
 
     g_assert (avahi != NULL);
 
index ad649462b24f9f8c5091c7c95b5c54490d15d3d7..7edc469faafca9b4cbe1505678979a4f1e347454 100644 (file)
 #include <avahi-common/dbus.h>
 #include <avahi-common/llist.h>
 #include <avahi-common/error.h>
+#include <avahi-common/malloc.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 
 #include <dbus/dbus.h>
-#include <dbus/dbus-glib-lowlevel.h>
 
 #include <stdlib.h>
 
+#include "dbus-watch-glue.h"
 #include "client.h"
 #include "internal.h"
 
@@ -58,7 +59,7 @@ void avahi_client_state_change (AvahiClient *client, int state)
     client->callback (client, state, client->user_data);
 }
 
-void
+static void
 avahi_client_state_request_callback (DBusPendingCall *call, void *data)
 {
     AvahiClient *client = data;
@@ -87,7 +88,7 @@ avahi_client_state_request_callback (DBusPendingCall *call, void *data)
     dbus_pending_call_unref (call);
 }
 
-void
+static void
 avahi_client_schedule_state_request (AvahiClient *client)
 {
     DBusMessage *message;
@@ -116,7 +117,7 @@ filter_func (DBusConnection *bus, DBusMessage *message, void *data)
     dbus_error_init (&error);
 
     if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
-        gchar *name, *old, *new;
+        char *name, *old, *new;
         dbus_message_get_args(message, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &old, DBUS_TYPE_STRING, &new, DBUS_TYPE_INVALID);
         
         if (dbus_error_is_set (&error)) {
@@ -181,14 +182,14 @@ out:
 }
 
 AvahiClient *
-avahi_client_new (AvahiClientCallback callback, void *user_data)
+avahi_client_new (const AvahiPoll *poll_api, AvahiClientCallback callback, void *user_data)
 {
     AvahiClient *tmp = NULL;
     DBusError error;
 
     dbus_error_init (&error);
 
-    if (!(tmp = malloc(sizeof(AvahiClient))))
+    if (!(tmp = avahi_new(AvahiClient, 1)))
         goto fail;
 
     AVAHI_LLIST_HEAD_INIT(AvahiEntryGroup, tmp->groups);
@@ -196,14 +197,18 @@ avahi_client_new (AvahiClientCallback callback, void *user_data)
     AVAHI_LLIST_HEAD_INIT(AvahiServiceBrowser, tmp->service_browsers);
     AVAHI_LLIST_HEAD_INIT(AvahiServiceTypeBrowser, tmp->service_type_browsers);
     
+    tmp->poll_api = poll_api;
     tmp->bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
 
     if (dbus_error_is_set (&error)) {
         goto fail;
     }
 
-    dbus_connection_setup_with_g_main (tmp->bus, NULL);
-    dbus_connection_set_exit_on_disconnect (tmp->bus, FALSE);
+/*     dbus_connection_setup_with_g_main (tmp->bus, NULL); */
+/*     dbus_connection_set_exit_on_disconnect (tmp->bus, FALSE); */
+
+    if (avahi_dbus_connection_glue(tmp->bus, poll_api) < 0)
+        goto fail;
 
     if (!dbus_connection_add_filter (tmp->bus, filter_func, tmp, NULL))
     {
@@ -243,7 +248,7 @@ avahi_client_new (AvahiClientCallback callback, void *user_data)
     return tmp;
 
 fail:
-    free (tmp);
+    avahi_free (tmp);
 
     if (dbus_error_is_set(&error))
         dbus_error_free(&error);
@@ -252,7 +257,7 @@ fail:
 }
 
 static char*
-avahi_client_get_string_reply_and_block (AvahiClient *client, char *method, char *param)
+avahi_client_get_string_reply_and_block (AvahiClient *client, const char *method, const char *param)
 {
     DBusMessage *message;
     DBusMessage *reply;
@@ -303,7 +308,7 @@ avahi_client_get_string_reply_and_block (AvahiClient *client, char *method, char
         return NULL;
     }
 
-    new = strdup (ret);
+    new = avahi_strdup (ret);
 
     avahi_client_set_errno (client, AVAHI_OK);
     return new;
index 16e9998ce534e0233aa9b5397ea58aa54b74be12..de6f207207bb56af868126ab6154e061921fe17a 100644 (file)
@@ -28,6 +28,7 @@
 #include <avahi-common/address.h>
 #include <avahi-common/strlst.h>
 #include <avahi-common/defs.h>
+#include <avahi-common/watch.h>
 
 /** \file client.h Definitions and functions for the client API over D-Bus */
 
@@ -58,16 +59,16 @@ typedef void (*AvahiClientCallback) (AvahiClient *s, AvahiClientState state, voi
 typedef void (*AvahiEntryGroupCallback) (AvahiEntryGroup *g, AvahiEntryGroupState state, void* userdata);
 
 /** The function prototype for the callback of an AvahiDomainBrowser */
-typedef void (*AvahiDomainBrowserCallback) (AvahiDomainBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, char *domain, void *user_data);
+typedef void (*AvahiDomainBrowserCallback) (AvahiDomainBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *domain, void *user_data);
 
 /** The function prototype for the callback of an AvahiServiceBrowser */
-typedef void (*AvahiServiceBrowserCallback) (AvahiServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, char *name, char *type, char *domain, void *user_data);
+typedef void (*AvahiServiceBrowserCallback) (AvahiServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, void *user_data);
 
 /** The function prototype for the callback of an AvahiServiceTypeBrowser */
-typedef void (*AvahiServiceTypeBrowserCallback) (AvahiServiceTypeBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, char *type, char *domain, void *user_data);
+typedef void (*AvahiServiceTypeBrowserCallback) (AvahiServiceTypeBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *type, const char *domain, void *user_data);
 
 /** Creates a new client instance */
-AvahiClient* avahi_client_new (AvahiClientCallback callback, void *user_data);
+AvahiClient* avahi_client_new (const AvahiPoll *poll_api, AvahiClientCallback callback, void *user_data);
 
 /** Get the version of the server */
 char* avahi_client_get_version_string (AvahiClient*);
@@ -118,19 +119,19 @@ avahi_entry_group_add_service (AvahiEntryGroup *group,
                                AvahiStringList *txt);
 
 /** Get the D-Bus path of an AvahiEntryGroup object, for debugging purposes only. */
-char* avahi_entry_group_path (AvahiEntryGroup *);
+const char* avahi_entry_group_path (AvahiEntryGroup *);
 
 /** Browse for domains on the local network */
 AvahiDomainBrowser* avahi_domain_browser_new (AvahiClient *client,
                                               AvahiIfIndex interface,
                                               AvahiProtocol protocol,
-                                              char *domain,
+                                              const char *domain,
                                               AvahiDomainBrowserType btype,
                                               AvahiDomainBrowserCallback callback,
                                               void *user_data);
 
 /** Get the D-Bus path of an AvahiDomainBrowser object, for debugging purposes only. */
-char* avahi_domain_browser_path (AvahiDomainBrowser *);
+const char* avahi_domain_browser_path (AvahiDomainBrowser *);
 
 /** Cleans up and frees an AvahiDomainBrowser object */
 int avahi_domain_browser_free (AvahiDomainBrowser *);
@@ -140,12 +141,12 @@ AvahiServiceTypeBrowser* avahi_service_type_browser_new (
                 AvahiClient *client,
                 AvahiIfIndex interface,
                 AvahiProtocol protocol,
-                char *domain,
+                const char *domain,
                 AvahiServiceTypeBrowserCallback callback,
                 void *user_data);
 
 /** Get the D-Bus path of an AvahiServiceTypeBrowser object, for debugging purposes only. */
-char* avahi_service_type_browser_path (AvahiServiceTypeBrowser *);
+const char* avahi_service_type_browser_path (AvahiServiceTypeBrowser *);
 
 /** Cleans up and frees an AvahiServiceTypeBrowser object */
 int avahi_service_type_browser_free (AvahiServiceTypeBrowser *);
@@ -155,13 +156,13 @@ AvahiServiceBrowser* avahi_service_browser_new (
                 AvahiClient *client,
                 AvahiIfIndex interface,
                 AvahiProtocol protocol,
-                char *type,
-                char *domain,
+                const char *type,
+                const char *domain,
                 AvahiServiceBrowserCallback callback,
                 void *user_data);
 
 /** Get the D-Bus path of an AvahiServiceBrowser object, for debugging purposes only. */
-char* avahi_service_browser_path (AvahiServiceBrowser *);
+const char* avahi_service_browser_path (AvahiServiceBrowser *);
 
 /* Cleans up and frees an AvahiServiceBrowser object */
 int avahi_service_browser_free (AvahiServiceBrowser *);
diff --git a/avahi-client/dbus-watch-glue.c b/avahi-client/dbus-watch-glue.c
new file mode 100644 (file)
index 0000000..025aeac
--- /dev/null
@@ -0,0 +1,234 @@
+/* $Id$ */
+
+/***
+  This file is part of avahi.
+  avahi is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as
+  published by the Free Software Foundation; either version 2.1 of the
+  License, or (at your option) any later version.
+  avahi 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 Lesser General
+  Public License for more details.
+  You should have received a copy of the GNU Lesser General Public
+  License along with avahi; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  USA.
+***/
+
+#include <assert.h>
+
+#include <avahi-common/malloc.h>
+
+#include "dbus-watch-glue.h"
+
+static AvahiWatchEvent translate_dbus_to_avahi(unsigned int f) {
+    AvahiWatchEvent e = 0;
+
+    if (f & DBUS_WATCH_READABLE)
+        e |= AVAHI_WATCH_IN;
+    if (f & DBUS_WATCH_WRITABLE)
+        e |= AVAHI_WATCH_OUT;
+    if (f & DBUS_WATCH_ERROR)
+        e |= AVAHI_WATCH_ERR;
+    if (f & DBUS_WATCH_HANGUP)
+        e |= AVAHI_WATCH_HUP;
+
+    return e;
+}
+
+static unsigned int translate_avahi_to_dbus(AvahiWatchEvent e) {
+    unsigned int f = 0;
+
+    if (e & AVAHI_WATCH_IN)
+        f |= DBUS_WATCH_READABLE;
+    if (e & AVAHI_WATCH_OUT)
+        f |= DBUS_WATCH_WRITABLE;
+    if (e & AVAHI_WATCH_ERR)
+        f |= DBUS_WATCH_ERROR;
+    if (e & AVAHI_WATCH_HUP)
+        f |= DBUS_WATCH_HANGUP;
+
+    return f;
+}
+
+static void watch_callback(AvahiWatch *avahi_watch, int fd, AvahiWatchEvent events, void *userdata) {
+    DBusWatch *dbus_watch = userdata;
+    assert(avahi_watch);
+    assert(dbus_watch);
+
+    dbus_watch_handle(dbus_watch, translate_avahi_to_dbus(events));
+    /* Ignore the return value */
+}
+
+static dbus_bool_t update_watch(const AvahiPoll *poll_api, DBusWatch *dbus_watch) {
+    AvahiWatch *avahi_watch;
+    dbus_bool_t b;
+    
+    assert(dbus_watch);
+
+    avahi_watch = dbus_watch_get_data(dbus_watch);
+
+    b = dbus_watch_get_enabled(dbus_watch);
+    
+    if (b && !avahi_watch) {
+
+        if (!(avahi_watch = poll_api->watch_new(
+                  poll_api,
+                  dbus_watch_get_fd(dbus_watch),
+                  translate_dbus_to_avahi(dbus_watch_get_flags(dbus_watch)),
+                  watch_callback,
+                  dbus_watch)))
+            return FALSE;
+
+        dbus_watch_set_data(dbus_watch, avahi_watch, (DBusFreeFunction) poll_api->watch_free);
+        
+    } else if (!b && avahi_watch) {
+        
+        poll_api->watch_free(avahi_watch);
+        dbus_watch_set_data(dbus_watch, NULL, NULL);
+
+    } else if (avahi_watch) {
+        
+        /* Update flags */
+        poll_api->watch_update(avahi_watch, dbus_watch_get_flags(dbus_watch));
+    }
+
+    return TRUE;
+}
+
+static dbus_bool_t add_watch(DBusWatch *dbus_watch, void *userdata) {
+    const AvahiPoll *poll_api = (const AvahiPoll*) userdata;
+    
+    assert(dbus_watch);
+    assert(poll_api);
+
+    return update_watch(poll_api, dbus_watch);
+}
+
+static void remove_watch(DBusWatch *dbus_watch, void *userdata) {
+    const AvahiPoll *poll_api = (const AvahiPoll*) userdata;
+    AvahiWatch *avahi_watch;
+    
+    assert(dbus_watch);
+    assert(poll_api);
+
+    avahi_watch = dbus_watch_get_data(dbus_watch);
+    poll_api->watch_free(avahi_watch);
+    dbus_watch_set_data(dbus_watch, NULL, NULL);
+}
+
+static void watch_toggled(DBusWatch *dbus_watch, void *userdata) {
+    const AvahiPoll *poll_api = (const AvahiPoll*) userdata;
+    
+    assert(dbus_watch);
+    assert(poll_api);
+
+    update_watch(poll_api, dbus_watch);
+}
+
+typedef struct TimeoutData {
+    const AvahiPoll *poll_api;
+    AvahiTimeout *avahi_timeout;
+    DBusTimeout *dbus_timeout;
+} TimeoutData;
+
+static void update_timeout(TimeoutData *timeout) {
+    assert(timeout);
+    
+    if (dbus_timeout_get_enabled(timeout->dbus_timeout)) {
+        struct timeval tv;
+        avahi_elapse_time(&tv, dbus_timeout_get_interval(timeout->dbus_timeout), 0);
+        timeout->poll_api->timeout_update(timeout->
+                                      avahi_timeout, &tv);
+    } else
+        timeout->poll_api->timeout_update(timeout->avahi_timeout, NULL);
+
+}
+
+static void timeout_callback(AvahiTimeout *avahi_timeout, void *userdata) {
+    TimeoutData *timeout = userdata;
+    
+    assert(avahi_timeout);
+    assert(timeout);
+
+    dbus_timeout_handle(timeout->dbus_timeout);
+    /* Ignore the return value */
+    
+    update_timeout(timeout);
+}
+
+static dbus_bool_t add_timeout(DBusTimeout *dbus_timeout, void *userdata) {
+    TimeoutData *timeout;
+    const AvahiPoll *poll_api = (const AvahiPoll*) userdata;
+    struct timeval tv;
+    dbus_bool_t b;
+
+    assert(dbus_timeout);
+    assert(poll_api);
+
+    if (!(timeout = avahi_new(TimeoutData, 1)))
+        return FALSE;
+
+    timeout->dbus_timeout = dbus_timeout;
+    timeout->poll_api = poll_api;
+
+    if ((b = dbus_timeout_get_enabled(dbus_timeout)))
+        avahi_elapse_time(&tv, dbus_timeout_get_interval(dbus_timeout), 0);
+    
+    if (!(timeout->avahi_timeout = poll_api->timeout_new(
+              poll_api,
+              b ? &tv : NULL,
+              timeout_callback,
+              dbus_timeout))) {
+        avahi_free(timeout);
+        return FALSE;
+    }
+
+    dbus_timeout_set_data(dbus_timeout, timeout, NULL);
+    return TRUE;
+}
+
+static void remove_timeout(DBusTimeout *dbus_timeout, void *userdata) {
+    TimeoutData *timeout;
+    const AvahiPoll *poll_api = (const AvahiPoll*) userdata;
+
+    assert(dbus_timeout);
+    assert(poll_api);
+
+    timeout = dbus_timeout_get_data(dbus_timeout);
+    assert(timeout);
+
+    poll_api->timeout_free(timeout->avahi_timeout);
+    avahi_free(timeout);
+    dbus_timeout_set_data(dbus_timeout, NULL, NULL);
+}
+
+static void timeout_toggled(DBusTimeout *dbus_timeout, void *userdata) {
+    TimeoutData *timeout;
+    const AvahiPoll *poll_api = (const AvahiPoll*) userdata;
+
+    assert(dbus_timeout);
+    assert(poll_api);
+
+    timeout = dbus_timeout_get_data(dbus_timeout);
+    assert(timeout);
+
+    update_timeout(timeout);
+}
+
+int avahi_dbus_connection_glue(DBusConnection *c, const AvahiPoll *poll_api) {
+    assert(c);
+    assert(poll_api);
+
+    if (!(dbus_connection_set_watch_functions(c, add_watch, remove_watch, watch_toggled, (void*) poll_api, NULL)))
+        return -1;
+
+    if (!(dbus_connection_set_timeout_functions(c, add_timeout, remove_timeout, timeout_toggled, (void*) poll_api, NULL)))
+        return -1;
+
+    return 0;
+}
diff --git a/avahi-client/dbus-watch-glue.h b/avahi-client/dbus-watch-glue.h
new file mode 100644 (file)
index 0000000..e815b45
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef foodbuswatchgluehfoo
+#define foodbuswatchgluehfoo
+
+/* $Id$ */
+
+/***
+  This file is part of avahi.
+  avahi is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as
+  published by the Free Software Foundation; either version 2.1 of the
+  License, or (at your option) any later version.
+  avahi 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 Lesser General
+  Public License for more details.
+  You should have received a copy of the GNU Lesser General Public
+  License along with avahi; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  USA.
+***/
+
+#include <dbus/dbus.h>
+
+#include <avahi-common/watch.h>
+
+int avahi_dbus_connection_glue(DBusConnection *c, const AvahiPoll *poll_api);
+
+#endif
index 93c3fd62890c3e2d97cd8c48357fe1400ffa8dd7..633575579bd0940ee05da797203e2bf2ed3751e7 100644 (file)
 #include <config.h>
 #endif
 
-#include <avahi-client/client.h>
-#include <avahi-common/dbus.h>
-#include <avahi-common/llist.h>
-#include <avahi-common/error.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 
 #include <dbus/dbus.h>
-#include <dbus/dbus-glib-lowlevel.h>
 
-#include <stdlib.h>
+#include <avahi-client/client.h>
+#include <avahi-common/dbus.h>
+#include <avahi-common/llist.h>
+#include <avahi-common/error.h>
+#include <avahi-common/malloc.h>
 
 #include "client.h"
 #include "internal.h"
@@ -88,11 +87,11 @@ avahi_entry_group_new (AvahiClient *client, AvahiEntryGroupCallback callback, vo
         goto fail;
     }
 
-    tmp = malloc (sizeof (AvahiEntryGroup));
+    tmp = avahi_new(AvahiEntryGroup, 1);
 
     tmp->client = client;
 
-    tmp->path = strdup (path);
+    tmp->path = avahi_strdup (path);
     tmp->callback = callback;
     tmp->user_data = user_data;
 
@@ -104,7 +103,7 @@ avahi_entry_group_new (AvahiClient *client, AvahiEntryGroupCallback callback, vo
     return tmp;
 
 fail:
-    if (tmp) free (tmp);
+    if (tmp) avahi_free (tmp);
     if (message) dbus_message_unref (message);
     return NULL;
 }
@@ -128,7 +127,7 @@ avahi_entry_group_free (AvahiEntryGroup *group)
     
     AVAHI_LLIST_REMOVE(AvahiEntryGroup, groups, client->groups, group);
 
-    free (group);
+    avahi_free (group);
 
     return avahi_client_set_errno (client, AVAHI_OK);
 }
@@ -252,7 +251,7 @@ avahi_entry_group_add_service (AvahiEntryGroup *group,
     /* Assemble the AvahiStringList into an Array of Array of Bytes to send over dbus */
     for (p = txt; p != NULL; p = p->next) {
         DBusMessageIter sub2;
-        const guint8 *data = p->text;
+        const uint8_t *data = p->text;
 
         dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "y", &sub2);
         dbus_message_iter_append_fixed_array(&sub2, DBUS_TYPE_BYTE, &data, p->size);
@@ -267,7 +266,7 @@ avahi_entry_group_add_service (AvahiEntryGroup *group,
 }
 
 /* XXX: debug function */
-char* avahi_entry_group_path (AvahiEntryGroup *group)
+const char* avahi_entry_group_path (AvahiEntryGroup *group)
 {
     if (group != NULL) return group->path;
     else return NULL;
index d37958e201636a1310aad287baf77e417ff6044d..6058e20b47a8276a58fd026314bf1ef444ea003b 100644 (file)
@@ -27,6 +27,7 @@
 
 struct _AvahiClient
 {
+    const AvahiPoll *poll_api;
     DBusConnection *bus;
     int error;
     AvahiClientCallback callback;
index 5e03fe44219d60921b347e99bd614356b037264d..c3ed86ff362c15ca25b17661a43deac3dfe035ad 100644 (file)
 struct AvahiWatch {
     AvahiSimplePoll *simple_poll;
     int dead;
+
     int idx;
     struct pollfd pollfd;
+    
     AvahiWatchCallback callback;
     void *userdata;
 
     AVAHI_LLIST_FIELDS(AvahiWatch, watches);
 };
 
+struct AvahiTimeout {
+    AvahiSimplePoll *simple_poll;
+    int dead;
+
+    int enabled;
+    struct timeval expiry;
+    
+    AvahiTimeoutCallback callback;
+    void  *userdata;
+    
+    AVAHI_LLIST_FIELDS(AvahiTimeout, timeouts);
+};
+
 struct AvahiSimplePoll {
     AvahiPoll api;
     AvahiPollFunc poll_func;
@@ -51,16 +66,13 @@ struct AvahiSimplePoll {
     struct pollfd* pollfds;
     int n_pollfds, max_pollfds, rebuild_pollfds;
 
-    struct timeval wakeup;
-    AvahiWakeupCallback wakeup_callback;
-    void *wakeup_userdata;
-
-    int req_cleanup;
-    
+    int watch_req_cleanup, timeout_req_cleanup;
     int quit;
+    int events_valid;
 
     int n_watches;
     AVAHI_LLIST_HEAD(AvahiWatch, watches);
+    AVAHI_LLIST_HEAD(AvahiTimeout, timeouts);
 };
 
 static AvahiWatch* watch_new(const AvahiPoll *api, int fd, AvahiWatchEvent event, AvahiWatchCallback callback, void *userdata) {
@@ -78,11 +90,13 @@ static AvahiWatch* watch_new(const AvahiPoll *api, int fd, AvahiWatchEvent event
         return NULL;
     
     w->simple_poll = s;
+    w->dead = 0;
+
     w->pollfd.fd = fd;
     w->pollfd.events = event;
+
     w->callback = callback;
     w->userdata = userdata;
-    w->dead = 0;
 
     if (s->n_pollfds < s->max_pollfds) {
         /* If there's space for this pollfd, go on and allocate it */
@@ -114,6 +128,16 @@ static void watch_update(AvahiWatch *w, AvahiWatchEvent events) {
         w->simple_poll->rebuild_pollfds = 1;
 }
 
+static AvahiWatchEvent watch_get_events(AvahiWatch *w) {
+    assert(w);
+    assert(!w->dead);
+
+    if (w->idx != -1 && w->simple_poll->events_valid)
+        return w->simple_poll->pollfds[w->idx].revents;
+
+    return 0;
+}
+
 static void remove_pollfd(AvahiWatch *w) {
     assert(w);
 
@@ -140,27 +164,7 @@ static void watch_free(AvahiWatch *w) {
     
     w->dead = 1;
     w->simple_poll->n_watches --;
-    w->simple_poll->req_cleanup = 1;
-}
-
-static void set_wakeup(const AvahiPoll *api, const struct timeval *tv, AvahiWakeupCallback callback, void *userdata) {
-    AvahiSimplePoll *s;
-
-    assert(api);
-    s = api->userdata;
-
-    if (callback) {
-        if (tv)
-            s->wakeup = *tv;
-        else {
-            s->wakeup.tv_sec = 0;
-            s->wakeup.tv_usec = 0;
-        }
-        
-        s->wakeup_callback = callback;
-        s->wakeup_userdata = userdata;
-    } else
-        s->wakeup_callback = NULL;
+    w->simple_poll->watch_req_cleanup = 1;
 }
 
 static void destroy_watch(AvahiWatch *w) {
@@ -175,7 +179,7 @@ static void destroy_watch(AvahiWatch *w) {
     avahi_free(w);
 }
 
-static void cleanup(AvahiSimplePoll *s, int all) {
+static void cleanup_watches(AvahiSimplePoll *s, int all) {
     AvahiWatch *w, *next;
     assert(s);
 
@@ -186,7 +190,73 @@ static void cleanup(AvahiSimplePoll *s, int all) {
             destroy_watch(w);
     }
 
-    s->req_cleanup = 0;
+    s->timeout_req_cleanup = 0;
+}
+
+static AvahiTimeout* timeout_new(const AvahiPoll *api, const struct timeval *tv, AvahiTimeoutCallback callback, void *userdata) {
+    AvahiTimeout *t;
+    AvahiSimplePoll *s;
+    
+    assert(api);
+    assert(callback);
+
+    s = api->userdata;
+    assert(s);
+
+    if (!(t = avahi_new(AvahiTimeout, 1)))
+        return NULL;
+    
+    t->simple_poll = s;
+    t->dead = 0;
+
+    if ((t->enabled = !!tv))
+        t->expiry = *tv;
+        
+    t->callback = callback;
+    t->userdata = userdata;
+
+    AVAHI_LLIST_PREPEND(AvahiTimeout, timeouts, s->timeouts, t);
+
+    return t;
+}
+
+static void timeout_update(AvahiTimeout *t, const struct timeval *tv) {
+    assert(t);
+    assert(!t->dead);
+    
+    if ((t->enabled = !!tv))
+        t->expiry = *tv;
+}
+
+static void timeout_free(AvahiTimeout *t) {
+    assert(t);
+    assert(!t->dead);
+
+    t->dead = 1;
+    t->simple_poll->timeout_req_cleanup = 1;
+}
+
+
+static void destroy_timeout(AvahiTimeout *t) {
+    assert(t);
+
+    AVAHI_LLIST_REMOVE(AvahiTimeout, timeouts, t->simple_poll->timeouts, t);
+
+    avahi_free(t);
+}
+
+static void cleanup_timeouts(AvahiSimplePoll *s, int all) {
+    AvahiTimeout *t, *next;
+    assert(s);
+
+    for (t = s->timeouts; t; t = next) {
+        next = t->timeouts_next;
+
+        if (all || t->dead)
+            destroy_timeout(t);
+    }
+
+    s->timeout_req_cleanup = 0;
 }
 
 AvahiSimplePoll *avahi_simple_poll_new(void) {
@@ -196,21 +266,30 @@ AvahiSimplePoll *avahi_simple_poll_new(void) {
         return NULL;
     
     s->api.userdata = s;
+
     s->api.watch_new = watch_new;
     s->api.watch_free = watch_free;
     s->api.watch_update = watch_update;
-    s->api.set_wakeup = set_wakeup;
+    s->api.watch_get_events = watch_get_events;
+
+    s->api.timeout_new = timeout_new;
+    s->api.timeout_free = timeout_free;
+    s->api.timeout_update = timeout_update;
+    
     s->pollfds = NULL;
     s->max_pollfds = s->n_pollfds = 0;
-    s->wakeup_callback = NULL;
     s->rebuild_pollfds = 0;
     s->quit = 0;
     s->n_watches = 0;
-    s->req_cleanup = 0;
+    s->events_valid = 0;
+    
+    s->watch_req_cleanup = 0;
+    s->timeout_req_cleanup = 0;
 
     avahi_simple_poll_set_func(s, NULL);
 
     AVAHI_LLIST_HEAD_INIT(AvahiWatch, s->watches);
+    AVAHI_LLIST_HEAD_INIT(AvahiTimeout, s->timeouts);
 
     return s;
 }
@@ -218,8 +297,8 @@ AvahiSimplePoll *avahi_simple_poll_new(void) {
 void avahi_simple_poll_free(AvahiSimplePoll *s) {
     assert(s);
 
-    cleanup(s, 1);
-    
+    cleanup_timeouts(s, 1);
+    cleanup_watches(s, 1);
     assert(s->n_watches == 0);
     
     avahi_free(s->pollfds);
@@ -253,39 +332,49 @@ static int rebuild(AvahiSimplePoll *s) {
     }
 
     s->n_pollfds = idx;
-    
+    s->events_valid = 0;
     s->rebuild_pollfds = 0;
 
     return 0;
 }
 
-static int start_wakeup_callback(AvahiSimplePoll *s) {
-    AvahiWakeupCallback callback;
-    void *userdata;
-
+static AvahiTimeout* find_next_timeout(AvahiSimplePoll *s) {
+    AvahiTimeout *t, *n = NULL;
     assert(s);
 
-    /* Reset the wakeup functions, but allow changing of the two
-       values from the callback function */
+    for (t = s->timeouts; t; t = t->timeouts_next) {
+        
+        if (t->dead || !t->enabled)
+            continue;
+        
+        if (!n || avahi_timeval_compare(&t->expiry, &n->expiry) < 0)
+            n = t;
+    }
 
-    callback = s->wakeup_callback;
-    userdata = s->wakeup_userdata;
-    s->wakeup_callback = NULL;
-    s->wakeup_userdata = NULL;
+    return n;
+}
 
-    assert(callback);
-    
-    callback(&s->api, userdata);
+static int start_timeout_callback(AvahiTimeout *t) {
+    assert(t);
+    assert(!t->dead);
+    assert(t->enabled);
+
+    t->enabled = 0;
+    t->callback(t, t->userdata);
     return 0;
 }
 
 int avahi_simple_poll_iterate(AvahiSimplePoll *s, int timeout) {
     int r;
+    AvahiTimeout *next_timeout;
     assert(s);
 
     /* Cleanup things first */
-    if (s->req_cleanup)
-        cleanup(s, 0);
+    if (s->watch_req_cleanup)
+        cleanup_watches(s, 0);
+
+    if (s->timeout_req_cleanup)
+        cleanup_timeouts(s, 0);
 
     /* Check whether a quit was requested */
     if (s->quit)
@@ -296,19 +385,23 @@ int avahi_simple_poll_iterate(AvahiSimplePoll *s, int timeout) {
         if (rebuild(s) < 0)
             return -1;
 
+
     /* Calculate the wakeup time */
-    if (s->wakeup_callback) {
+    if ((next_timeout = find_next_timeout(s))) {
         struct timeval now;
         int t;
         AvahiUsec usec;
 
         gettimeofday(&now, NULL);
-        usec = avahi_timeval_diff(&s->wakeup, &now);
+        usec = avahi_timeval_diff(&next_timeout->expiry, &now);
 
-        if (usec <= 0)
+        if (usec <= 0) {
             /* Timeout elapsed */
 
-            return start_wakeup_callback(s);
+            /* The events poll() returned in the last call are now no longer valid */
+            s->events_valid = 0;
+            return start_timeout_callback(next_timeout);
+        }
 
         /* Calculate sleep time. We add 1ms because otherwise we'd
          * wake up too early most of the time */
@@ -321,15 +414,18 @@ int avahi_simple_poll_iterate(AvahiSimplePoll *s, int timeout) {
     if ((r = s->poll_func(s->pollfds, s->n_pollfds, timeout)) < 0)
         return -1;
 
+    /* The pollf events are now valid again */
+    s->events_valid = 1;
+
     /* Check whether the wakeup time has been reached now */
-    if (s->wakeup_callback) {
+    if (next_timeout) {
         struct timeval now;
         
         gettimeofday(&now, NULL);
 
-        if (avahi_timeval_compare(&s->wakeup, &now) <= 0)
+        if (avahi_timeval_compare(&next_timeout->expiry, &now) <= 0)
             /* Time elapsed */
-            return start_wakeup_callback(s);
+            return start_timeout_callback(next_timeout);
     }
     
     if (r > 0) {
index a9e3e0285c8d0fca272f059607fed6c820855afb..ffb214982da3ca6eb4b496738fcedd20a7aea78a 100644 (file)
@@ -52,7 +52,7 @@ static void callback(AvahiWatch *w, int fd, AvahiWatchEvent event, void *userdat
     }
 }
 
-static void wakeup(AvahiPoll *_api, void *userdata) {
+static void wakeup(AvahiTimeout *t, void *userdata) {
     static int i = 0;
     struct timeval tv;
 
@@ -62,7 +62,7 @@ static void wakeup(AvahiPoll *_api, void *userdata) {
         avahi_simple_poll_quit(simple_poll);
     else {
         avahi_elapse_time(&tv, 1000, 0);
-        api->set_wakeup(api, &tv, wakeup, NULL);
+        api->timeout_update(t, &tv);
     }
 }
 
@@ -75,7 +75,7 @@ int main(int argc, char *argv[]) {
     api->watch_new(api, 0, AVAHI_WATCH_IN, callback, NULL);
 
     avahi_elapse_time(&tv, 1000, 0);
-    api->set_wakeup(api, &tv, wakeup, NULL);
+    api->timeout_new(api, &tv, wakeup, NULL);
 
     /* Our main loop */
     for (;;)
index 75f53b36db2a1bad0a982a5ee53c6db4818416f9..7bab4f8fb8140f309787d06fa3303dea15ddd118 100644 (file)
@@ -36,6 +36,9 @@ AVAHI_C_DECL_BEGIN
 /** An I/O watch object */
 typedef struct AvahiWatch AvahiWatch;
 
+/** An I/O watch object */
+typedef struct AvahiTimeout AvahiTimeout;
+
 /** An event polling abstraction object */
 typedef struct AvahiPoll AvahiPoll;
 
@@ -50,8 +53,8 @@ typedef enum {
 /** Called whenever an I/O event happens  on an I/O watch */
 typedef void (*AvahiWatchCallback)(AvahiWatch *w, int fd, AvahiWatchEvent event, void *userdata);
 
-/** Called when the wakeup time is reached */
-typedef void (*AvahiWakeupCallback)(AvahiPoll *api, void *userdata);
+/** Called when the timeout is reached */
+typedef void (*AvahiTimeoutCallback)(AvahiTimeout *t, void *userdata);
 
 /** Defines an abstracted event polling API. This may be used to
  connect Avahi to other main loops. This is losely based on Unix
@@ -60,7 +63,7 @@ typedef void (*AvahiWakeupCallback)(AvahiPoll *api, void *userdata);
  to define a single wakeup time.*/
 struct AvahiPoll {
 
-    /** Some abstract user data usable by the implementor of the API */
+    /** Some abstract user data usable by the provider of the API */
     void* userdata; 
 
     /** Create a new watch for the specified file descriptor and for
@@ -68,17 +71,28 @@ struct AvahiPoll {
      * whenever any of the events happens. */
     AvahiWatch* (*watch_new)(const AvahiPoll *api, int fd, AvahiWatchEvent event, AvahiWatchCallback callback, void *userdata);
 
-    /** Update the events to wait for. */
+    /** Update the events to wait for. It is safe to call this function from an AvahiWatchCallback */
     void (*watch_update)(AvahiWatch *w, AvahiWatchEvent event);
 
-    /** Free a watch */
+    /** Return the events that happened. It is safe to call this function from an AvahiWatchCallback  */
+    AvahiWatchEvent (*watch_get_events)(AvahiWatch *w);
+
+    /** Free a watch. It is safe to call this function from an AvahiWatchCallback */
     void (*watch_free)(AvahiWatch *w);
 
     /** Set a wakeup time for the polling loop. The API will call the
-    callback function when the absolute time *tv is reached. If *tv is
-    NULL, the callback will be called in the next main loop
-    iteration. If callback is NULL the wakeup time is disabled. */
-    void (*set_wakeup)(const AvahiPoll *api, const struct timeval *tv, AvahiWakeupCallback callback, void *userdata);
+    callback function when the absolute time *tv is reached. If tv is
+    NULL, the timeout is disabled. After the timeout expired the
+    callback function will be called and the timeout is disabled. You
+    can reenable it by calling timeout_update()  */
+    AvahiTimeout* (*timeout_new)(const AvahiPoll *api, const struct timeval *tv, AvahiTimeoutCallback callback, void *userdata);
+
+    /** Update the absolute expiration time for a timeout, If tv is
+     * null, the timeout is disabled. It is safe to call this function from an AvahiTimeoutCallback */
+    void (*timeout_update)(AvahiTimeout *, const struct timeval *tv);
+    
+    /** Free a timeout. It is safe to call this function from an AvahiTimeoutCallback */
+    void (*timeout_free)(AvahiTimeout *t);
 };
 
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
index 27131853990515c932a267e8b60afcd33f82210d..375fb7d64a80343750906402e39112c07c7af658 100644 (file)
@@ -226,7 +226,7 @@ int main(int argc, char *argv[]) {
     int error;
 
     avahi_set_allocator(avahi_glib_allocator());
-    glib_poll = avahi_glib_poll_new(NULL);
+    glib_poll = avahi_glib_poll_new(NULL, G_PRIORITY_DEFAULT);
     
     avahi_server_config_init(&config);
 /*     config.host_name = g_strdup("test"); */
index b786e855268a0b538c9e9be5acfeb069dd1fda19..fab9b5641414e58eca822760d495bba8426b5f49 100644 (file)
@@ -109,7 +109,7 @@ int main(int argc, char *argv[]) {
 
     avahi_set_allocator(avahi_glib_allocator());
 
-    glib_poll = avahi_glib_poll_new(NULL);
+    glib_poll = avahi_glib_poll_new(NULL, G_PRIORITY_DEFAULT);
     
     avahi = avahi_server_new(avahi_glib_poll_get(glib_poll), NULL, server_callback, NULL, &error);
     
index bb9a5cd4e6c439c579c4745fcb77a4ee313d9e69..5e24ba33b4481f8e31cc647d244d88eff56594c8 100644 (file)
@@ -44,6 +44,7 @@ struct AvahiTimeEvent {
 struct AvahiTimeEventQueue {
     const AvahiPoll *poll_api;
     AvahiPrioQueue *prioq;
+    AvahiTimeout *timeout;
 };
 
 static int compare(const void* _a, const void* _b) {
@@ -58,19 +59,17 @@ static int compare(const void* _a, const void* _b) {
     return avahi_timeval_compare(&a->last_run, &b->last_run);
 }
 
-static void expiration_event(AvahiPoll *poll_api, void *userdata);
-
-static void update_wakeup(AvahiTimeEventQueue *q) {
+static void update_timeout(AvahiTimeEventQueue *q) {
+    AvahiTimeEvent *e;
     assert(q);
 
-    if (q->prioq->root) {
-        AvahiTimeEvent *e = q->prioq->root->data;
-        q->poll_api->set_wakeup(q->poll_api, &e->expiry, expiration_event, q);
-    } else
-        q->poll_api->set_wakeup(q->poll_api, NULL, NULL, NULL);
+    if ((e = avahi_time_event_queue_root(q)))
+        q->poll_api->timeout_update(q->timeout, &e->expiry);
+    else
+        q->poll_api->timeout_update(q->timeout, NULL);
 }
 
-void expiration_event(AvahiPoll *poll_api, void *userdata) {
+static void expiration_event(AvahiTimeout *timeout, void *userdata) {
     struct timeval now;
     AvahiTimeEventQueue *q = userdata;
     AvahiTimeEvent *e;
@@ -92,7 +91,7 @@ void expiration_event(AvahiPoll *poll_api, void *userdata) {
         }
     }
 
-    update_wakeup(q);
+    update_timeout(q);
 }
 
 static void fix_expiry_time(AvahiTimeEvent *e) {
@@ -113,27 +112,39 @@ AvahiTimeEventQueue* avahi_time_event_queue_new(const AvahiPoll *poll_api) {
         goto oom;
     }
 
+    q->poll_api = poll_api;
+
     if (!(q->prioq = avahi_prio_queue_new(compare)))
         goto oom;
 
-    q->poll_api = poll_api;
+    if (!(q->timeout = poll_api->timeout_new(poll_api, NULL, expiration_event, q))) 
+        goto oom;
+    
     return q;
 
 oom:
 
-    if (q)
+    if (q) {
         avahi_free(q);
+
+        if (q->prioq)
+            avahi_prio_queue_free(q->prioq);
+    }
     
     return NULL;
 }
 
 void avahi_time_event_queue_free(AvahiTimeEventQueue *q) {
+    AvahiTimeEvent *e;
+    
     assert(q);
 
-    while (q->prioq->root)
-        avahi_time_event_free(q->prioq->root->data);
+    while ((e = avahi_time_event_queue_root(q)))
+        avahi_time_event_free(e);
     avahi_prio_queue_free(q->prioq);
 
+    q->poll_api->timeout_free(q->timeout);
+    
     avahi_free(q);
 }
 
@@ -175,7 +186,7 @@ AvahiTimeEvent* avahi_time_event_new(
         return NULL;
     }
 
-    update_wakeup(q);
+    update_timeout(q);
     return e;
 }
 
@@ -188,7 +199,7 @@ void avahi_time_event_free(AvahiTimeEvent *e) {
     avahi_prio_queue_remove(q->prioq, e->node);
     avahi_free(e);
 
-    update_wakeup(q);
+    update_timeout(q);
 }
 
 void avahi_time_event_update(AvahiTimeEvent *e, const struct timeval *timeval) {
@@ -199,7 +210,7 @@ void avahi_time_event_update(AvahiTimeEvent *e, const struct timeval *timeval) {
     fix_expiry_time(e);
     avahi_prio_queue_shuffle(e->queue->prioq, e->node);
     
-    update_wakeup(e->queue);
+    update_timeout(e->queue);
 }
 
 AvahiTimeEvent* avahi_time_event_queue_root(AvahiTimeEventQueue *q) {
index e9030aae713dd049b846d6a8fdd4065d1d0a991d..04a632b60fafb96f34a34dbd99d3d082fabb5ddd 100644 (file)
@@ -604,7 +604,7 @@ static gint run_server(DaemonConfig *c) {
 
     g_assert(c);
 
-    poll_api = avahi_glib_poll_new(NULL);
+    poll_api = avahi_glib_poll_new(NULL, G_PRIORITY_DEFAULT);
     loop = g_main_loop_new(NULL, FALSE);
 
     if (daemon_signal_init(SIGINT, SIGQUIT, SIGHUP, SIGTERM, SIGUSR1, 0) < 0) {
index 17b334d8ab7381358cd5f6d89789a12fae492aea..73114d1d79c139011a23f6b412af482ff87d0c2b 100644 (file)
@@ -52,7 +52,7 @@ static void callback(AvahiWatch *w, int fd, AvahiWatchEvent event, void *userdat
     }
 }
 
-static void wakeup(AvahiPoll *_api, void *userdata) {
+static void wakeup(AvahiTimeout *t, void *userdata) {
     struct timeval tv;
     static int i = 0;
 
@@ -62,26 +62,28 @@ static void wakeup(AvahiPoll *_api, void *userdata) {
         g_main_loop_quit(loop);
 
     avahi_elapse_time(&tv, 1000, 0);
-    api->set_wakeup(api, &tv, wakeup, NULL);
+    api->timeout_update(t, &tv);
 }
 
 int main(int argc, char *argv[]) {
-    AvahiGLibPoll *s;
+    AvahiGLibPoll *g;
     struct timeval tv;
     
-    s = avahi_glib_poll_new(NULL);
-    assert(s);
+    g = avahi_glib_poll_new(NULL, G_PRIORITY_DEFAULT);
+    assert(g);
 
-    api = avahi_glib_poll_get(s);
+    api = avahi_glib_poll_get(g);
 
     api->watch_new(api, 0, AVAHI_WATCH_IN, callback, NULL);
 
     avahi_elapse_time(&tv, 1000, 0);
-    api->set_wakeup(api, &tv, wakeup, NULL);
+    api->timeout_new(api, &tv, wakeup, NULL);
 
     loop = g_main_loop_new(NULL, FALSE);
     g_main_loop_run(loop);
     g_main_loop_unref(loop);
+
+    avahi_glib_poll_free(g);
     
     return 0;
 }
index f099e5a187904039666fb303a11c1261d1c6d614..e6def467050da96cbe02bfb918cc57613261aecb 100644 (file)
 struct AvahiWatch {
     AvahiGLibPoll *glib_poll;
     int dead;
+    
     GPollFD pollfd;
     int pollfd_added;
+    
     AvahiWatchCallback callback;
     void *userdata;
 
     AVAHI_LLIST_FIELDS(AvahiWatch, watches);
 };
 
+struct AvahiTimeout {
+    AvahiGLibPoll *glib_poll;
+    gboolean dead;
+
+    gboolean enabled;
+    struct timeval expiry;
+
+    AvahiTimeoutCallback callback;
+    void  *userdata;
+    
+    AVAHI_LLIST_FIELDS(AvahiTimeout, timeouts);
+};
+
 struct AvahiGLibPoll {
     GSource source;
     AvahiPoll api;
     GMainContext *context;
 
-    struct timeval wakeup;
-    AvahiWakeupCallback wakeup_callback;
-    void *wakeup_userdata;
-    
-    int req_cleanup;
+    gboolean timeout_req_cleanup;
+    gboolean watch_req_cleanup;
     
-     AVAHI_LLIST_HEAD(AvahiWatch, watches);
+    AVAHI_LLIST_HEAD(AvahiWatch, watches);
+    AVAHI_LLIST_HEAD(AvahiTimeout, timeouts);
 };
 
 static void destroy_watch(AvahiWatch *w) {
@@ -64,7 +77,7 @@ static void destroy_watch(AvahiWatch *w) {
     avahi_free(w);
 }
 
-static void cleanup(AvahiGLibPoll *g, int all) {
+static void cleanup_watches(AvahiGLibPoll *g, int all) {
     AvahiWatch *w, *next;
     assert(g);
 
@@ -75,7 +88,7 @@ static void cleanup(AvahiGLibPoll *g, int all) {
             destroy_watch(w);
     }
 
-    g->req_cleanup = 0;
+    g->watch_req_cleanup = 0;
 }
 
 static AvahiWatch* watch_new(const AvahiPoll *api, int fd, AvahiWatchEvent event, AvahiWatchCallback callback, void *userdata) {
@@ -99,13 +112,13 @@ static AvahiWatch* watch_new(const AvahiPoll *api, int fd, AvahiWatchEvent event
         (event & AVAHI_WATCH_OUT ? G_IO_OUT : 0) |
         (event & AVAHI_WATCH_ERR ? G_IO_ERR : 0) |
         (event & AVAHI_WATCH_HUP ? G_IO_HUP : 0);
-        ;
+    w->pollfd.revents = 0;
     w->callback = callback;
     w->userdata = userdata;
-    w->dead = 0;
+    w->dead = FALSE;
 
     g_source_add_poll(&g->source, &w->pollfd);
-    w->pollfd_added = 1;
+    w->pollfd_added = TRUE;
 
     AVAHI_LLIST_PREPEND(AvahiWatch, watches, g->watches, w);
 
@@ -119,68 +132,129 @@ static void watch_update(AvahiWatch *w, AvahiWatchEvent events) {
     w->pollfd.events = events;
 }
 
+static AvahiWatchEvent watch_get_events(AvahiWatch *w) {
+    assert(w);
+    assert(!w->dead);
+
+    return w->pollfd.revents;
+}
+
 static void watch_free(AvahiWatch *w) {
     assert(w);
     assert(!w->dead);
 
     if (w->pollfd_added) {
         g_source_remove_poll(&w->glib_poll->source, &w->pollfd);
-        w->pollfd_added = 0;
+        w->pollfd_added = TRUE;
     }
     
-    w->dead = 1;
-    w->glib_poll->req_cleanup = 1;
+    w->dead = TRUE;
+    w->glib_poll->timeout_req_cleanup = TRUE;
 }
 
-static void set_wakeup(const AvahiPoll *api, const struct timeval *tv, AvahiWakeupCallback callback, void *userdata) {
+static AvahiTimeout* timeout_new(const AvahiPoll *api, const struct timeval *tv, AvahiTimeoutCallback callback, void *userdata) {
+    AvahiTimeout *t;
     AvahiGLibPoll *g;
-
+    
     assert(api);
+    assert(callback);
+
     g = api->userdata;
+    assert(g);
 
-    if (callback) {
-        if (tv) 
-            g->wakeup = *tv;
-        else {
-            g->wakeup.tv_sec = 0;
-            g->wakeup.tv_usec = 0;
-        }
-            
-        g->wakeup_callback = callback;
-        g->wakeup_userdata = userdata;
-    } else
-        g->wakeup_callback = NULL;
+    if (!(t = avahi_new(AvahiTimeout, 1)))
+        return NULL;
+    
+    t->glib_poll = g;
+    t->dead = FALSE;
+
+    if ((t->enabled = !!tv))
+        t->expiry = *tv;
+        
+    t->callback = callback;
+    t->userdata = userdata;
+
+    AVAHI_LLIST_PREPEND(AvahiTimeout, timeouts, g->timeouts, t);
+
+    return t;
 }
 
-static void start_wakeup_callback(AvahiGLibPoll *g) {
-    AvahiWakeupCallback callback;
-    void *userdata;
+static void timeout_update(AvahiTimeout *t, const struct timeval *tv) {
+    assert(t);
+    assert(!t->dead);
+    
+    if ((t->enabled = !!tv))
+        t->expiry = *tv;
+}
+
+static void timeout_free(AvahiTimeout *t) {
+    assert(t);
+    assert(!t->dead);
+
+    t->dead = TRUE;
+    t->glib_poll->timeout_req_cleanup = TRUE;
+}
+
+static void destroy_timeout(AvahiTimeout *t) {
+    assert(t);
 
+    AVAHI_LLIST_REMOVE(AvahiTimeout, timeouts, t->glib_poll->timeouts, t);
+    avahi_free(t);
+}
+
+static void cleanup_timeouts(AvahiGLibPoll *g, int all) {
+    AvahiTimeout *t, *next;
     assert(g);
 
-    /* Reset the wakeup functions, but allow changing of the two
-       values from the callback function */
+    for (t = g->timeouts; t; t = next) {
+        next = t->timeouts_next;
 
-    callback = g->wakeup_callback;
-    userdata = g->wakeup_userdata;
-    g->wakeup_callback = NULL;
-    g->wakeup_userdata = NULL;
+        if (all || t->dead)
+            destroy_timeout(t);
+    }
 
-    assert(callback);
-    
-    callback(&g->api, userdata);
+    g->timeout_req_cleanup = FALSE;
+}
+
+static AvahiTimeout* find_next_timeout(AvahiGLibPoll *g) {
+    AvahiTimeout *t, *n = NULL;
+    assert(g);
+
+    for (t = g->timeouts; t; t = t->timeouts_next) {
+        
+        if (t->dead || !t->enabled)
+            continue;
+        
+        if (!n || avahi_timeval_compare(&t->expiry, &n->expiry) < 0)
+            n = t;
+    }
+
+    return n;
+}
+
+static void start_timeout_callback(AvahiTimeout *t) {
+    assert(t);
+    assert(!t->dead);
+    assert(t->enabled);
+
+    t->enabled = 0;
+    t->callback(t, t->userdata);
 }
 
 static gboolean prepare_func(GSource *source, gint *timeout) {
     AvahiGLibPoll *g = (AvahiGLibPoll*) source;
+    AvahiTimeout *next_timeout;
 
     g_assert(g);
     g_assert(timeout);
 
-    if (g->req_cleanup)
-        cleanup(g, 0);
+    if (g->watch_req_cleanup)
+        cleanup_watches(g, 0);
+
+    if (g->timeout_req_cleanup)
+        cleanup_timeouts(g, 0);
     
-    if (g->wakeup_callback) {
+    if ((next_timeout = find_next_timeout(g))) {
         GTimeVal now;
         struct timeval tvnow;
         AvahiUsec usec;
@@ -189,7 +263,7 @@ static gboolean prepare_func(GSource *source, gint *timeout) {
         tvnow.tv_sec = now.tv_sec;
         tvnow.tv_usec = now.tv_usec;
     
-        usec = avahi_timeval_diff(&g->wakeup, &tvnow);
+        usec = avahi_timeval_diff(&next_timeout->expiry, &tvnow);
 
         if (usec <= 0)
             return TRUE;
@@ -203,17 +277,18 @@ static gboolean prepare_func(GSource *source, gint *timeout) {
 static gboolean check_func(GSource *source) {
     AvahiGLibPoll *g = (AvahiGLibPoll*) source;
     AvahiWatch *w;
+    AvahiTimeout *next_timeout;
 
     g_assert(g);
 
-    if (g->wakeup_callback) {
+    if ((next_timeout = find_next_timeout(g))) {
         GTimeVal now;
         struct timeval tvnow;
         g_source_get_current_time(source, &now);
         tvnow.tv_sec = now.tv_sec;
         tvnow.tv_usec = now.tv_usec;
         
-        if (avahi_timeval_compare(&g->wakeup, &tvnow) < 0)
+        if (avahi_timeval_compare(&next_timeout->expiry, &tvnow) < 0)
             return TRUE;
     }
 
@@ -227,18 +302,19 @@ static gboolean check_func(GSource *source) {
 static gboolean dispatch_func(GSource *source, GSourceFunc callback, gpointer userdata) {
     AvahiGLibPoll* g = (AvahiGLibPoll*) source;
     AvahiWatch *w;
+    AvahiTimeout *next_timeout;
     
     g_assert(g);
 
-    if (g->wakeup_callback) {
+    if ((next_timeout = find_next_timeout(g))) {
         GTimeVal now;
         struct timeval tvnow;
         g_source_get_current_time(source, &now);
         tvnow.tv_sec = now.tv_sec;
         tvnow.tv_usec = now.tv_usec;
         
-        if (avahi_timeval_compare(&g->wakeup, &tvnow) < 0) {
-            start_wakeup_callback(g);
+        if (avahi_timeval_compare(&next_timeout->expiry, &tvnow) < 0) {
+            start_timeout_callback(next_timeout);
             return TRUE;
         }
     }
@@ -254,7 +330,7 @@ static gboolean dispatch_func(GSource *source, GSourceFunc callback, gpointer us
     return TRUE;
 }
 
-AvahiGLibPoll *avahi_glib_poll_new(GMainContext *context) {
+AvahiGLibPoll *avahi_glib_poll_new(GMainContext *context, gint priority) {
     AvahiGLibPoll *g;
     
     static GSourceFuncs source_funcs = {
@@ -270,17 +346,24 @@ AvahiGLibPoll *avahi_glib_poll_new(GMainContext *context) {
     g_main_context_ref(g->context = context ? context : g_main_context_default());
 
     g->api.userdata = g;
+    
     g->api.watch_new = watch_new;
     g->api.watch_free = watch_free;
     g->api.watch_update = watch_update;
-    g->api.set_wakeup = set_wakeup;
+    g->api.watch_get_events = watch_get_events;
+    
+    g->api.timeout_new = timeout_new;
+    g->api.timeout_free = timeout_free;
+    g->api.timeout_update = timeout_update;
 
-    g->wakeup_callback = NULL;
-    g->req_cleanup = 0;
+    g->watch_req_cleanup = FALSE;
+    g->timeout_req_cleanup = FALSE;
     
     AVAHI_LLIST_HEAD_INIT(AvahiWatch, g->watches);
+    AVAHI_LLIST_HEAD_INIT(AvahiTimeout, g->timeouts);
     
     g_source_attach(&g->source, g->context);
+    g_source_set_priority(&g->source, priority);
 
     return g;
 }
@@ -289,14 +372,12 @@ void avahi_glib_poll_free(AvahiGLibPoll *g) {
     GSource *s = &g->source;
     assert(g);
 
-/*     g_message("BEFORE"); */
-    cleanup(g, 1);
+    cleanup_watches(g, 1);
+    cleanup_timeouts(g, 1);
 
-/*     g_message("MIDDLE"); */
     g_main_context_unref(g->context);
     g_source_destroy(s);
     g_source_unref(s);
-/*     g_message("AFTER"); */
 }
 
 const AvahiPoll* avahi_glib_poll_get(AvahiGLibPoll *g) {
index 4fa8a3bf058377ebeee93e8a33fbf3d62195b482..0833bdc07943c43e0a97c8512c991cfc5dd2ff07 100644 (file)
 AVAHI_C_DECL_BEGIN
 #endif
 
-/** GLib main loop adapter */
+/** GLib main loop adapter. You can safely cast this into a GSource */
 typedef struct AvahiGLibPoll AvahiGLibPoll;
 
 /** Create a new GLib main loop adapter attached to the specified
  context. If context is NULL, the default main loop context is
  used. You can attach as many AvahiGLibPoll objects to the same context
- as you want. */
-AvahiGLibPoll *avahi_glib_poll_new(GMainContext *context);
+ as you want. priority takes on of GLib's G_PRIORITY constants. */
+AvahiGLibPoll *avahi_glib_poll_new(GMainContext *context, gint priority);
 
 /** Free  GLib main loop adapter */
 void avahi_glib_poll_free(AvahiGLibPoll *g);