aboutsummaryrefslogtreecommitdiffstats
path: root/mdns.c
diff options
context:
space:
mode:
authorkraxel <kraxel>2006-01-24 16:36:21 +0000
committerkraxel <kraxel>2006-01-24 16:36:21 +0000
commit5874585e61bbeec0f63d741d8051da62dd6a8009 (patch)
tree98e15c88c4ca5bec5e4c7784f0ff5bb1adc671ef /mdns.c
parent27a809254346cb8cb6b814ffa125074806f97f00 (diff)
downloadxenwatch-5874585e61bbeec0f63d741d8051da62dd6a8009.tar.gz
- some experimental mdns bits
Diffstat (limited to 'mdns.c')
-rw-r--r--mdns.c187
1 files changed, 187 insertions, 0 deletions
diff --git a/mdns.c b/mdns.c
new file mode 100644
index 0000000..19e44ca
--- /dev/null
+++ b/mdns.c
@@ -0,0 +1,187 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <avahi-client/client.h>
+#include <avahi-client/lookup.h>
+#include <avahi-common/error.h>
+#include <avahi-common/timeval.h>
+#include <avahi-glib/glib-watch.h>
+#include <avahi-glib/glib-malloc.h>
+
+#include "list.h"
+#include "mdns.h"
+
+/* ---------------------------------------------------------------------- */
+
+static const char *revents[] = {
+ [ AVAHI_RESOLVER_FOUND ] = "FOUND",
+ [ AVAHI_RESOLVER_FAILURE ] = "FAILURE",
+};
+static const char *bevents[] = {
+ [ AVAHI_BROWSER_NEW ] = "NEW",
+ [ AVAHI_BROWSER_REMOVE ] = "REMOVE",
+ [ AVAHI_BROWSER_CACHE_EXHAUSTED ] = "CACHE_EXHAUSTED",
+ [ AVAHI_BROWSER_ALL_FOR_NOW ] = "ALL_FOR_NOW",
+ [ AVAHI_BROWSER_FAILURE ] = "FAILURE",
+};
+
+static const AvahiPoll *poll_api;
+static AvahiGLibPoll *glib_poll;
+static AvahiClient *client;
+
+struct mdns_entry {
+ const char *name;
+ const char *type;
+ const char *domain;
+ AvahiIfIndex interface;
+ AvahiProtocol protocol;
+
+ const char *address;
+ const char *hostname;
+ uint16_t port;
+
+ struct list_head next;
+};
+static LIST_HEAD(mdns_entries);
+
+/* ---------------------------------------------------------------------- */
+
+static void resolve_callback(AvahiServiceResolver *r,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiResolverEvent event,
+ const char *name,
+ const char *type,
+ const char *domain,
+ const char *host_name,
+ const AvahiAddress *address,
+ uint16_t port,
+ AvahiStringList *txt,
+ AvahiLookupResultFlags flags,
+ void* userdata)
+{
+ struct mdns_entry *e = userdata;
+ char a[AVAHI_ADDRESS_STR_MAX];
+
+ switch (event) {
+ case AVAHI_RESOLVER_FOUND:
+ avahi_address_snprint(a, sizeof(a), address);
+ e->address = strdup(a);
+ e->hostname = strdup(host_name);
+ e->port = port;
+ fprintf(stderr, "%s @ %s: %s | %s if #%d | %s:%d (%s)\n",
+ e->type, e->domain, e->name,
+ avahi_proto_to_string(e->protocol), e->interface,
+ e->address, e->port, e->hostname);
+ break;
+ default:
+ fprintf(stderr, "%s: %s (#%d)\n", __FUNCTION__,
+ revents[event], event);
+ break;
+ }
+ avahi_service_resolver_free(r);
+}
+
+static void browse_callback(AvahiServiceBrowser *b,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiBrowserEvent event,
+ const char *name,
+ const char *type,
+ const char *domain,
+ AvahiLookupResultFlags flags,
+ void* userdata)
+{
+ AvahiClient *c = userdata;
+ struct mdns_entry *e;
+
+ switch (event) {
+ case AVAHI_BROWSER_NEW:
+ e = malloc(sizeof(*e));
+ memset(e,0,sizeof(*e));
+ e->name = strdup(name);
+ e->type = strdup(type);
+ e->domain = strdup(domain);
+ e->interface = interface;
+ e->protocol = protocol;
+ list_add_tail(&e->next, &mdns_entries);
+ avahi_service_resolver_new(c, interface, protocol, name, type, domain,
+ AVAHI_PROTO_UNSPEC, 0, resolve_callback, e);
+ break;
+ case AVAHI_BROWSER_REMOVE:
+ fprintf(stderr, "%s: DEL: service '%s' of type '%s' in domain '%s'\n",
+ __FUNCTION__, name, type, domain);
+ break;
+ default:
+ fprintf(stderr, "%s: %s (#%d)\n", __FUNCTION__,
+ bevents[event], event);
+ break;
+ }
+}
+
+static void
+client_callback(AvahiClient *client, AvahiClientState state, void *userdata)
+{
+ switch (state) {
+ case AVAHI_CLIENT_FAILURE:
+ fprintf(stderr, "%s: error: connection lost\n", __FUNCTION__);
+ break;
+ default:
+ fprintf(stderr, "%s: state %d\n", __FUNCTION__, state);
+ break;
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+
+void mdns_fini(void)
+{
+ if (client) {
+ avahi_client_free(client);
+ client = NULL;
+ }
+ if (glib_poll) {
+ avahi_glib_poll_free(glib_poll);
+ glib_poll = NULL;
+ }
+}
+
+int mdns_init(void)
+{
+ int error;
+
+ /* Create the GLIB Adaptor */
+ avahi_set_allocator(avahi_glib_allocator());
+ glib_poll = avahi_glib_poll_new(NULL, G_PRIORITY_DEFAULT);
+ poll_api = avahi_glib_poll_get(glib_poll);
+ client = avahi_client_new(poll_api, AVAHI_CLIENT_NO_FAIL,
+ client_callback, NULL /* user data */,
+ &error);
+ if (client == NULL)
+ goto fail;
+ return 0;
+
+fail:
+ mdns_fini();
+ return -1;
+}
+
+int mdns_browse(const char *service, const char *domain)
+{
+ AvahiServiceBrowser *sb = NULL;
+
+ if (NULL == domain)
+ domain = avahi_client_get_domain_name(client);
+ sb = avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
+ service, domain, 0, browse_callback, client);
+ if (NULL == sb) {
+ fprintf(stderr, "%s: failed to create service browser: %s\n",
+ __FUNCTION__, avahi_strerror(avahi_client_errno(client)));
+ return -1;
+ }
+ return 0;
+}