Add event avahi binding
authorVolker Lendecke <vl@samba.org>
Fri, 20 Mar 2009 13:55:05 +0000 (14:55 +0100)
committerKarolin Seeger <kseeger@samba.org>
Fri, 27 Mar 2009 13:15:52 +0000 (14:15 +0100)
(cherry picked from commit cb18c1686b3cd20f0535458f8cee24a772560350)

source/Makefile.in
source/configure.in
source/include/proto.h
source/lib/avahi.c [new file with mode: 0644]

index b8d5567e901865666457ffd87d73427ce00249d6..0500d73de4bc9c98b142674af078fdd5f8e72e49 100644 (file)
@@ -251,6 +251,8 @@ AFS_OBJ = lib/afs.o
 
 AFS_SETTOKEN_OBJ = lib/afs_settoken.o
 
+AVAHI_OBJ = @AVAHI_OBJ@
+
 SERVER_MUTEX_OBJ = lib/server_mutex.o
 
 PASSCHANGE_OBJ = libsmb/passchange.o
@@ -689,7 +691,7 @@ SMBD_OBJ_BASE = $(PARAM_WITHOUT_REG_OBJ) $(SMBD_OBJ_SRV) $(LIBSMB_OBJ) \
                $(LOCKING_OBJ) $(PASSDB_OBJ) $(PRINTING_OBJ) $(PROFILE_OBJ) \
                $(LIB_OBJ) $(PRINTBACKEND_OBJ) $(OPLOCK_OBJ) \
                $(NOTIFY_OBJ) $(GROUPDB_OBJ) $(AUTH_OBJ) \
-               $(LIBMSRPC_OBJ) $(LIBMSRPC_GEN_OBJ) \
+               $(LIBMSRPC_OBJ) $(LIBMSRPC_GEN_OBJ) $(AVAHI_OBJ) \
                $(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(LIBADS_SERVER_OBJ) \
                $(REG_FULL_OBJ) $(POPT_LIB_OBJ) $(BUILDOPT_OBJ) \
                $(SMBLDAP_OBJ) $(LDB_OBJ) $(LIBNET_OBJ) @LIBWBCLIENT_STATIC@ \
@@ -1329,7 +1331,7 @@ bin/smbd@EXEEXT@: $(BINARY_PREREQS) $(SMBD_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARE
        @echo Linking $@
        @$(CC) $(FLAGS) -o $@ $(SMBD_OBJ) $(LDFLAGS) $(LDAP_LIBS) \
                $(KRB5LIBS) $(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) \
-               $(ACL_LIBS) $(PASSDB_LIBS) $(LIBS) $(DNSSD_LIBS) \
+               $(ACL_LIBS) $(PASSDB_LIBS) $(LIBS) $(DNSSD_LIBS) $(AVAHI_LIBS) \
                $(POPT_LIBS) @SMBD_LIBS@ $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) \
                $(WINBIND_LIBS)
 
@@ -1514,7 +1516,7 @@ bin/pdbtest@EXEEXT@: $(BINARY_PREREQS) $(PDBTEST_OBJ) @BUILD_POPT@ @LIBTALLOC_SH
 
 bin/vfstest@EXEEXT@: $(BINARY_PREREQS) $(VFSTEST_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@
        @echo Linking $@
-       @$(CC) $(FLAGS) -o $@ $(VFSTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) \
+       @$(CC) $(FLAGS) -o $@ $(VFSTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(AVAHI_LIBS) \
                $(TERMLIBS) $(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) $(DNSSD_LIBS) \
                $(ACL_LIBS) $(LIBS) $(POPT_LIBS) $(KRB5LIBS) $(LDAP_LIBS) \
                @SMBD_LIBS@ $(NSCD_LIBS) $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) \
index 86fd40dc92ce318ce3333e6452bda0b045b7f1b2..6905203fa82a5413b9eb407e8f079c8e4082c5d6 100644 (file)
@@ -6227,12 +6227,12 @@ if test x"$enable_avahi" != x"no"; then
     if test x"$have_avahi_support" = x"yes"; then
        AC_DEFINE(WITH_AVAHI_SUPPORT, 1,
                [Whether to enable avahi support])
+       AC_SUBST(AVAHI_OBJ, lib/avahi.o)
     else
        if test x"$enable_avahi" = x"yes"; then
            AC_MSG_ERROR(avahi support not available)
        fi
     fi
-
 fi
 
 #################################################
index c2b318ee0dba7b26043c483ed7c723d3b4d9b301..e7cb2ca83e7f732fc0956df4320aa7ba007246e1 100644 (file)
@@ -9751,4 +9751,9 @@ NTSTATUS idmap_sid_to_gid(const char *domname, DOM_SID *sid, gid_t *gid);
 
 NTSTATUS nss_info_template_init( void );
 
+/* The following definitions come from lib/avahi.c */
+
+struct AvahiPoll *tevent_avahi_poll(TALLOC_CTX *mem_ctx,
+                                   struct event_context *ev);
+
 #endif /*  _PROTO_H_  */
diff --git a/source/lib/avahi.c b/source/lib/avahi.c
new file mode 100644 (file)
index 0000000..bdc58cb
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+   Unix SMB/CIFS implementation.
+   Connect avahi to lib/tevents
+   Copyright (C) Volker Lendecke 2009
+
+   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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+
+#include <avahi-common/watch.h>
+
+struct avahi_poll_context {
+       struct event_context *ev;
+       AvahiWatch **watches;
+       AvahiTimeout **timeouts;
+};
+
+struct AvahiWatch {
+       struct avahi_poll_context *ctx;
+       struct fd_event *fde;
+       int fd;
+       AvahiWatchEvent latest_event;
+       AvahiWatchCallback callback;
+       void *userdata;
+};
+
+struct AvahiTimeout {
+       struct avahi_poll_context *ctx;
+       struct timed_event *te;
+       AvahiTimeoutCallback callback;
+       void *userdata;
+};
+
+static uint16_t avahi_flags_map_to_tevent(AvahiWatchEvent event)
+{
+       return ((event & AVAHI_WATCH_IN) ? EVENT_FD_READ : 0)
+               | ((event & AVAHI_WATCH_OUT) ? EVENT_FD_WRITE : 0);
+}
+
+static void avahi_fd_handler(struct event_context *ev,
+                            struct fd_event *fde, uint16_t flags,
+                            void *private_data);
+
+static AvahiWatch *avahi_watch_new(const AvahiPoll *api, int fd,
+                                  AvahiWatchEvent event,
+                                  AvahiWatchCallback callback,
+                                  void *userdata)
+{
+       struct avahi_poll_context *ctx = talloc_get_type_abort(
+               api->userdata, struct avahi_poll_context);
+       int num_watches = talloc_get_size(ctx->watches)/sizeof(*ctx->watches);
+       AvahiWatch **tmp, *watch_ctx;
+
+       tmp = talloc_realloc(ctx, ctx->watches, AvahiWatch *, num_watches + 1);
+       if (tmp == NULL) {
+               return NULL;
+       }
+       ctx->watches = tmp;
+
+       watch_ctx = talloc(tmp, AvahiWatch);
+       if (watch_ctx == NULL) {
+               goto fail;
+       }
+       ctx->watches[num_watches] = watch_ctx;
+
+       watch_ctx->ctx = ctx;
+       watch_ctx->fde = event_add_fd(ctx->ev, watch_ctx, fd,
+                                     avahi_flags_map_to_tevent(event),
+                                     avahi_fd_handler, watch_ctx);
+       if (watch_ctx->fde == NULL) {
+               goto fail;
+       }
+       watch_ctx->callback = callback;
+       watch_ctx->userdata = userdata;
+       return watch_ctx;
+
+ fail:
+       TALLOC_FREE(watch_ctx);
+       ctx->watches = talloc_realloc(ctx, ctx->watches, AvahiWatch *,
+                                     num_watches);
+       return NULL;
+}
+
+static void avahi_fd_handler(struct event_context *ev,
+                            struct fd_event *fde, uint16_t flags,
+                            void *private_data)
+{
+       AvahiWatch *watch_ctx = talloc_get_type_abort(private_data, AvahiWatch);
+
+       watch_ctx->latest_event =
+               ((flags & EVENT_FD_READ) ? AVAHI_WATCH_IN : 0)
+               | ((flags & EVENT_FD_WRITE) ? AVAHI_WATCH_OUT : 0);
+
+       watch_ctx->callback(watch_ctx, watch_ctx->fd, watch_ctx->latest_event,
+                           watch_ctx->userdata);
+}
+
+static void avahi_watch_update(AvahiWatch *w, AvahiWatchEvent event)
+{
+       if (event & AVAHI_WATCH_IN) {
+               event_fd_set_readable(w->fde);
+       } else {
+               event_fd_set_not_readable(w->fde);
+       }
+       if (event & AVAHI_WATCH_OUT) {
+               event_fd_set_writeable(w->fde);
+       } else {
+               event_fd_set_not_writeable(w->fde);
+       }
+}
+
+static AvahiWatchEvent avahi_watch_get_events(AvahiWatch *w)
+{
+       return w->latest_event;
+}
+
+static void avahi_watch_free(AvahiWatch *w)
+{
+       int i, num_watches;
+       AvahiWatch **watches = w->ctx->watches;
+       struct avahi_poll_context *ctx;
+
+       num_watches = talloc_get_size(watches) / sizeof(*watches);
+
+       for (i=0; i<num_watches; i++) {
+               if (w == watches[i]) {
+                       break;
+               }
+       }
+       if (i == num_watches) {
+               return;
+       }
+       ctx = w->ctx;
+       TALLOC_FREE(w);
+       memmove(&watches[i], &watches[i+1],
+               sizeof(*watches) * (num_watches - i - 1));
+       ctx->watches = talloc_realloc(ctx, watches, AvahiWatch *,
+                                     num_watches - 1);
+}
+
+static void avahi_timeout_handler(struct event_context *ev,
+                                 struct timed_event *te,
+                                 struct timeval current_time,
+                                 void *private_data);
+
+static AvahiTimeout *avahi_timeout_new(const AvahiPoll *api,
+                                      const struct timeval *tv,
+                                      AvahiTimeoutCallback callback,
+                                      void *userdata)
+{
+       struct avahi_poll_context *ctx = talloc_get_type_abort(
+               api->userdata, struct avahi_poll_context);
+       int num_timeouts = talloc_get_size(ctx->timeouts)/sizeof(*ctx->timeouts);
+       AvahiTimeout **tmp, *timeout_ctx;
+
+       tmp = talloc_realloc(ctx, ctx->timeouts, AvahiTimeout *,
+                            num_timeouts + 1);
+       if (tmp == NULL) {
+               return NULL;
+       }
+       ctx->timeouts = tmp;
+
+       timeout_ctx = talloc(tmp, AvahiTimeout);
+       if (timeout_ctx == NULL) {
+               goto fail;
+       }
+       ctx->timeouts[num_timeouts] = timeout_ctx;
+
+       timeout_ctx->ctx = ctx;
+       if (tv == NULL) {
+               timeout_ctx->te = NULL;
+       } else {
+               timeout_ctx->te = event_add_timed(ctx->ev, timeout_ctx,
+                                                 *tv, avahi_timeout_handler,
+                                                 timeout_ctx);
+               if (timeout_ctx->te == NULL) {
+                       goto fail;
+               }
+       }
+       timeout_ctx->callback = callback;
+       timeout_ctx->userdata = userdata;
+       return timeout_ctx;
+
+ fail:
+       TALLOC_FREE(timeout_ctx);
+       ctx->timeouts = talloc_realloc(ctx, ctx->timeouts, AvahiTimeout *,
+                                      num_timeouts);
+       return NULL;
+}
+
+static void avahi_timeout_handler(struct event_context *ev,
+                                 struct timed_event *te,
+                                 struct timeval current_time,
+                                 void *private_data)
+{
+       AvahiTimeout *timeout_ctx = talloc_get_type_abort(
+               private_data, AvahiTimeout);
+
+       TALLOC_FREE(timeout_ctx->te);
+       timeout_ctx->callback(timeout_ctx, timeout_ctx->userdata);
+}
+
+static void avahi_timeout_update(AvahiTimeout *t, const struct timeval *tv)
+{
+       TALLOC_FREE(t->te);
+
+       t->te = event_add_timed(t->ctx->ev, t, *tv, avahi_timeout_handler, t);
+       /*
+        * No failure mode defined here
+        */
+       SMB_ASSERT(t->te != NULL);
+}
+
+static void avahi_timeout_free(AvahiTimeout *t)
+{
+       int i, num_timeouts;
+       AvahiTimeout **timeouts = t->ctx->timeouts;
+       struct avahi_poll_context *ctx;
+
+       num_timeouts = talloc_get_size(timeouts)/sizeof(*timeouts);
+
+       for (i=0; i<num_timeouts; i++) {
+               if (t == timeouts[i]) {
+                       break;
+               }
+       }
+       if (i == num_timeouts) {
+               return;
+       }
+       ctx = t->ctx;
+       TALLOC_FREE(t);
+       memmove(&timeouts[i], &timeouts[i+1],
+               sizeof(*timeouts) * (num_timeouts - i - 1));
+       ctx->timeouts = talloc_realloc(ctx, timeouts, AvahiTimeout *,
+                                      num_timeouts - 1);
+}
+
+struct AvahiPoll *tevent_avahi_poll(TALLOC_CTX *mem_ctx,
+                                   struct event_context *ev)
+{
+       struct AvahiPoll *result;
+       struct avahi_poll_context *ctx;
+
+       result = talloc(mem_ctx, struct AvahiPoll);
+       if (result == NULL) {
+               return result;
+       }
+       ctx = talloc_zero(result, struct avahi_poll_context);
+       if (ctx == NULL) {
+               TALLOC_FREE(result);
+               return NULL;
+       }
+       ctx->ev = ev;
+
+       result->watch_new               = avahi_watch_new;
+       result->watch_update            = avahi_watch_update;
+       result->watch_get_events        = avahi_watch_get_events;
+       result->watch_free              = avahi_watch_free;
+       result->timeout_new             = avahi_timeout_new;
+       result->timeout_update          = avahi_timeout_update;
+       result->timeout_free            = avahi_timeout_free;
+       result->userdata                = ctx;
+
+       return result;
+}