summaryrefslogtreecommitdiffstats
path: root/avahi-glib
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2005-08-12 19:09:50 +0000
committerLennart Poettering <lennart@poettering.net>2005-08-12 19:09:50 +0000
commit5d047523c87ba11aad8c384f7ffde25b4dd746ed (patch)
treeb160aa74a0c9e77db3bc9b864f503771adaa6758 /avahi-glib
parentf8c479234af6b676027df4fb6b38ce8e22949049 (diff)
implement new main loop abstraction layer
git-svn-id: file:///home/lennart/svn/public/avahi/trunk@305 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe
Diffstat (limited to 'avahi-glib')
-rw-r--r--avahi-glib/Makefile.am57
-rw-r--r--avahi-glib/glib-watch-test.c87
-rw-r--r--avahi-glib/glib-watch.c261
-rw-r--r--avahi-glib/glib-watch.h43
4 files changed, 448 insertions, 0 deletions
diff --git a/avahi-glib/Makefile.am b/avahi-glib/Makefile.am
new file mode 100644
index 0000000..6cfc46e
--- /dev/null
+++ b/avahi-glib/Makefile.am
@@ -0,0 +1,57 @@
+# $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 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 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.
+
+AM_CFLAGS=-I$(top_srcdir)
+
+# GLIB 2.0
+AM_CFLAGS+=$(GLIB20_CFLAGS)
+AM_LDADD=$(GLIB20_LIBS)
+
+# Import stuff from avahi-common
+COMMON_LDADD=../avahi-common/libavahi-common.la
+
+# This cool debug trap works on i386/gcc only
+AM_CFLAGS+='-DDEBUG_TRAP=__asm__("int $$3")'
+
+avahiincludedir=$(includedir)/avahi-glib
+
+avahiinclude_HEADERS = \
+ glib-watch.h
+
+lib_LTLIBRARIES = \
+ libavahi-glib.la
+
+noinst_PROGRAMS = \
+ glib-watch-test
+
+libavahi_glib_la_SOURCES = \
+ glib-watch.c glib-watch.h
+libavahi_glib_la_CFLAGS = $(AM_CFLAGS)
+libavahi_glib_la_LIBADD = $(AM_LDADD) $(COMMON_LDADD)
+
+glib_watch_test_SOURCES = \
+ glib-watch.c glib-watch.h \
+ glib-watch-test.c
+glib_watch_test_CFLAGS = $(AM_CFLAGS)
+glib_watch_test_LDADD = $(AM_LDADD) $(COMMON_LDADD)
+
+
+
+
+
diff --git a/avahi-glib/glib-watch-test.c b/avahi-glib/glib-watch-test.c
new file mode 100644
index 0000000..5072321
--- /dev/null
+++ b/avahi-glib/glib-watch-test.c
@@ -0,0 +1,87 @@
+/* $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.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include <avahi-common/watch.h>
+#include <avahi-common/timeval.h>
+#include "glib-watch.h"
+
+static AvahiPoll *api = NULL;
+static GMainLoop *loop = NULL;
+
+static void callback(AvahiWatch *w, int fd, AvahiWatchEvent event, void *userdata) {
+
+ if (event & AVAHI_WATCH_IN) {
+ ssize_t r;
+ char c;
+
+ if ((r = read(fd, &c, 1)) <= 0) {
+ fprintf(stderr, "read() failed: %s\n", r < 0 ? strerror(errno) : "EOF");
+ api->watch_free(w);
+ return;
+ }
+
+ printf("Read: %c\n", c >= 32 && c < 127 ? c : '.');
+ }
+}
+
+static void iteration(AvahiGLibPoll *p, void *userdata) {
+ struct timeval tv;
+ static int i = 0;
+
+ printf("Iteration %i\n", i++);
+
+ if (i > 100)
+ g_main_loop_quit(loop);
+
+ avahi_elapse_time(&tv, 1000, 0);
+ api->set_wakeup_time(api, &tv);
+}
+
+int main(int argc, char *argv[]) {
+ AvahiGLibPoll *s;
+ struct timeval tv;
+
+ s = avahi_glib_poll_new(NULL, iteration, NULL);
+ assert(s);
+
+ api = avahi_glib_poll_get(s);
+
+ api->watch_new(api, 0, AVAHI_WATCH_IN, callback, NULL);
+
+ avahi_elapse_time(&tv, 1000, 0);
+ api->set_wakeup_time(api, &tv);
+
+ loop = g_main_loop_new(NULL, FALSE);
+ g_main_loop_run(loop);
+ g_main_loop_unref(loop);
+
+ return 0;
+}
diff --git a/avahi-glib/glib-watch.c b/avahi-glib/glib-watch.c
new file mode 100644
index 0000000..7eab84b
--- /dev/null
+++ b/avahi-glib/glib-watch.c
@@ -0,0 +1,261 @@
+/* $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.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <avahi-common/llist.h>
+#include <avahi-common/malloc.h>
+
+#include "glib-watch.h"
+
+struct AvahiWatch {
+ AvahiGLibPoll *glib_poll;
+ int dead;
+ GPollFD pollfd;
+ int pollfd_added;
+ AvahiWatchCallback callback;
+ void *userdata;
+
+ AVAHI_LLIST_FIELDS(AvahiWatch, watches);
+};
+
+struct AvahiGLibPoll {
+ GSource source;
+ AvahiPoll api;
+ GMainContext *context;
+
+ struct timeval wakeup;
+ gboolean use_wakeup;
+ int req_cleanup;
+
+ AvahiGLibProcessCallback process_callback;
+ void *userdata;
+
+ AVAHI_LLIST_HEAD(AvahiWatch, watches);
+};
+
+static void destroy_watch(AvahiWatch *w) {
+ assert(w);
+
+ if (w->pollfd_added)
+ g_source_remove_poll(&w->glib_poll->source, &w->pollfd);
+
+ AVAHI_LLIST_REMOVE(AvahiWatch, watches, w->glib_poll->watches, w);
+
+ avahi_free(w);
+}
+
+static void cleanup(AvahiGLibPoll *g, int all) {
+ AvahiWatch *w, *next;
+ assert(g);
+
+ for (w = g->watches; w; w = next) {
+ next = w->watches_next;
+
+ if (all || w->dead)
+ destroy_watch(w);
+ }
+
+ g->req_cleanup = 0;
+}
+
+static AvahiWatch* watch_new(AvahiPoll *api, int fd, AvahiWatchEvent event, AvahiWatchCallback callback, void *userdata) {
+ AvahiWatch *w;
+ AvahiGLibPoll *g;
+
+ assert(api);
+ assert(fd >= 0);
+ assert(callback);
+
+ g = api->userdata;
+ assert(g);
+
+ if (!(w = avahi_new(AvahiWatch, 1)))
+ return NULL;
+
+ w->glib_poll = g;
+ w->pollfd.fd = fd;
+ w->pollfd.events =
+ (event & AVAHI_WATCH_IN ? G_IO_IN : 0) |
+ (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->callback = callback;
+ w->userdata = userdata;
+ w->dead = 0;
+
+ g_source_add_poll(&g->source, &w->pollfd);
+ w->pollfd_added = 1;
+
+ AVAHI_LLIST_PREPEND(AvahiWatch, watches, g->watches, w);
+
+ return w;
+}
+
+static void watch_update(AvahiWatch *w, AvahiWatchEvent events) {
+ assert(w);
+ assert(!w->dead);
+
+ w->pollfd.events = events;
+}
+
+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->dead = 1;
+ w->glib_poll->req_cleanup = 1;
+}
+
+static void set_wakeup_time(AvahiPoll *api, const struct timeval *tv) {
+ AvahiGLibPoll *g;
+
+ assert(api);
+ g = api->userdata;
+
+ if (tv) {
+ g->wakeup = *tv;
+ g->use_wakeup = 1;
+ } else
+ g->use_wakeup = 0;
+}
+
+static gboolean prepare_func(GSource *source, gint *timeout) {
+ AvahiGLibPoll *g = (AvahiGLibPoll*) source;
+
+ g_assert(g);
+ g_assert(timeout);
+
+ if (g->use_wakeup) {
+ GTimeVal now;
+ struct timeval tvnow;
+ AvahiUsec usec;
+
+ g_source_get_current_time(source, &now);
+ tvnow.tv_sec = now.tv_sec;
+ tvnow.tv_usec = now.tv_usec;
+
+ usec = avahi_timeval_diff(&g->wakeup, &tvnow);
+
+ if (usec <= 0)
+ return TRUE;
+
+ *timeout = (gint) (usec / 1000);
+ }
+
+ return FALSE;
+}
+
+static gboolean check_func(GSource *source) {
+ AvahiGLibPoll *g = (AvahiGLibPoll*) source;
+ AvahiWatch *w;
+
+ g_assert(g);
+
+ for (w = g->watches; w; w = w->watches_next)
+ if (w->pollfd.revents > 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+static gboolean dispatch_func(GSource *source, GSourceFunc callback, gpointer userdata) {
+ AvahiGLibPoll* g = (AvahiGLibPoll*) source;
+ AvahiWatch *w;
+
+ g_assert(g);
+
+ if (g->req_cleanup)
+ cleanup(g, 0);
+
+ if (g->process_callback)
+ g->process_callback(g, g->userdata);
+
+ for (w = g->watches; w; w = w->watches_next)
+ if (w->pollfd.revents > 0) {
+ assert(w->callback);
+ w->callback(w, w->pollfd.fd, w->pollfd.revents, w->userdata);
+ w->pollfd.revents = 0;
+ }
+
+ if (g->req_cleanup)
+ cleanup(g, 0);
+
+ return TRUE;
+}
+
+AvahiGLibPoll *avahi_glib_poll_new(GMainContext *context, AvahiGLibProcessCallback callback, void *userdata) {
+ AvahiGLibPoll *g;
+
+ static GSourceFuncs source_funcs = {
+ prepare_func,
+ check_func,
+ dispatch_func,
+ NULL,
+ NULL,
+ NULL
+ };
+
+ g = (AvahiGLibPoll*) g_source_new(&source_funcs, sizeof(AvahiGLibPoll));
+ 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_time = set_wakeup_time;
+
+ g->use_wakeup = 0;
+ g->process_callback = callback;
+ g->userdata = userdata;
+ g->req_cleanup = 0;
+
+ AVAHI_LLIST_HEAD_INIT(AvahiWatch, g->watches);
+
+ g_source_attach(&g->source, g->context);
+
+ return g;
+}
+
+void avahi_glib_poll_free(AvahiGLibPoll *g) {
+ GSource *s = &g->source;
+ assert(g);
+
+ cleanup(g, 1);
+
+ g_main_context_unref(g->context);
+ g_source_destroy(s);
+ g_source_unref(s);
+}
+
+AvahiPoll* avahi_glib_poll_get(AvahiGLibPoll *g) {
+ assert(g);
+
+ return &g->api;
+}
diff --git a/avahi-glib/glib-watch.h b/avahi-glib/glib-watch.h
new file mode 100644
index 0000000..9df58b5
--- /dev/null
+++ b/avahi-glib/glib-watch.h
@@ -0,0 +1,43 @@
+#ifndef fooglibwatchhfoo
+#define fooglibwatchhfoo
+
+/* $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 <avahi-common/cdecl.h>
+
+#include <glib.h>
+#include <avahi-common/watch.h>
+
+AVAHI_C_DECL_BEGIN
+
+typedef struct AvahiGLibPoll AvahiGLibPoll;
+
+typedef void (*AvahiGLibProcessCallback)(AvahiGLibPoll *g, void *userdata);
+
+AvahiGLibPoll *avahi_glib_poll_new(GMainContext *context, AvahiGLibProcessCallback callback, void *userdata);
+void avahi_glib_poll_free(AvahiGLibPoll *g);
+
+AvahiPoll* avahi_glib_poll_get(AvahiGLibPoll *g);
+
+AVAHI_C_DECL_END
+
+#endif