From 4bd09cba62f355ca83cc0e96d00950e21aec9482 Mon Sep 17 00:00:00 2001 From: Julien BLACHE Date: Sat, 8 May 2010 08:36:28 +0200 Subject: [PATCH] Browse and resolve mDNS services on both IPv4 and IPv6 --- src/mdns_avahi.c | 61 ++++++++++++++++++++++++++++++++++---------- src/mdns_avahi.h | 2 +- src/player.c | 5 +++- src/remote_pairing.c | 5 +++- 4 files changed, 57 insertions(+), 16 deletions(-) diff --git a/src/mdns_avahi.c b/src/mdns_avahi.c index 2d3f22bf..149b1314 100644 --- a/src/mdns_avahi.c +++ b/src/mdns_avahi.c @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -335,6 +336,7 @@ browse_resolve_callback(AvahiServiceResolver *r, AvahiIfIndex intf, AvahiProtoco { struct mdns_browser *mb; char address[AVAHI_ADDRESS_STR_MAX]; + int family; mb = (struct mdns_browser *)userdata; @@ -346,12 +348,30 @@ browse_resolve_callback(AvahiServiceResolver *r, AvahiIfIndex intf, AvahiProtoco break; case AVAHI_RESOLVER_FOUND: - DPRINTF(E_DBG, L_MDNS, "Avahi Resolver: resolved service '%s' type '%s'\n", name, type); + DPRINTF(E_DBG, L_MDNS, "Avahi Resolver: resolved service '%s' type '%s' proto %d\n", name, type, proto); avahi_address_snprint(address, sizeof(address), addr); + switch (proto) + { + case AVAHI_PROTO_INET: + family = AF_INET; + break; + + case AVAHI_PROTO_INET6: + family = AF_INET6; + break; + + default: + DPRINTF(E_INFO, L_MDNS, "Avahi Resolver: unknown protocol %d\n", proto); + + family = -1; + break; + } + /* Execute callback (mb->cb) with all the data */ - mb->cb(name, type, domain, hostname, address, port, txt); + if (family != -1) + mb->cb(name, type, domain, hostname, family, address, port, txt); break; } @@ -364,6 +384,7 @@ browse_callback(AvahiServiceBrowser *b, AvahiIfIndex intf, AvahiProtocol proto, { struct mdns_browser *mb; AvahiServiceResolver *res; + int family; mb = (struct mdns_browser *)userdata; @@ -375,8 +396,7 @@ browse_callback(AvahiServiceBrowser *b, AvahiIfIndex intf, AvahiProtocol proto, avahi_service_browser_free(b); - /* Restrict service browsing to IPv4 for now, until evhttp gets support for IPv6 */ - b = avahi_service_browser_new(mdns_client, AVAHI_IF_UNSPEC, AVAHI_PROTO_INET, mb->type, NULL, 0, browse_callback, mb); + b = avahi_service_browser_new(mdns_client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, mb->type, NULL, 0, browse_callback, mb); if (!b) { DPRINTF(E_LOG, L_MDNS, "Failed to recreate service browser (service type %s): %s\n", mb->type, @@ -385,10 +405,9 @@ browse_callback(AvahiServiceBrowser *b, AvahiIfIndex intf, AvahiProtocol proto, return; case AVAHI_BROWSER_NEW: - DPRINTF(E_DBG, L_MDNS, "Avahi Browser: NEW service '%s' type '%s'\n", name, type); + DPRINTF(E_DBG, L_MDNS, "Avahi Browser: NEW service '%s' type '%s' proto %d\n", name, type, proto); - /* Restrict resolution to IPv4 until evhttp gets support for IPv6 */ - res = avahi_service_resolver_new(mdns_client, intf, proto, name, type, domain, AVAHI_PROTO_INET, 0, browse_resolve_callback, mb); + res = avahi_service_resolver_new(mdns_client, intf, proto, name, type, domain, proto, 0, browse_resolve_callback, mb); if (!res) DPRINTF(E_LOG, L_MDNS, "Failed to create service resolver: %s\n", avahi_strerror(avahi_client_errno(mdns_client))); @@ -397,9 +416,27 @@ browse_callback(AvahiServiceBrowser *b, AvahiIfIndex intf, AvahiProtocol proto, break; case AVAHI_BROWSER_REMOVE: - DPRINTF(E_DBG, L_MDNS, "Avahi Browser: REMOVE service '%s' type '%s'\n", name, type); + DPRINTF(E_DBG, L_MDNS, "Avahi Browser: REMOVE service '%s' type '%s' proto %d\n", name, type, proto); - mb->cb(name, type, domain, NULL, NULL, -1, NULL); + switch (proto) + { + case AVAHI_PROTO_INET: + family = AF_INET; + break; + + case AVAHI_PROTO_INET6: + family = AF_INET6; + break; + + default: + DPRINTF(E_INFO, L_MDNS, "Avahi Browser: unknown protocol %d\n", proto); + + family = -1; + break; + } + + if (family != -1) + mb->cb(name, type, domain, NULL, family, NULL, -1, NULL); break; case AVAHI_BROWSER_ALL_FOR_NOW: @@ -510,8 +547,7 @@ client_callback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UNUSED void * for (mb = browser_list; mb; mb = mb->next) { - /* Restrict service browsing to IPv4 for now, until evhttp gets support for IPv6 */ - b = avahi_service_browser_new(mdns_client, AVAHI_IF_UNSPEC, AVAHI_PROTO_INET, mb->type, NULL, 0, browse_callback, mb); + b = avahi_service_browser_new(mdns_client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, mb->type, NULL, 0, browse_callback, mb); if (!b) { DPRINTF(E_LOG, L_MDNS, "Failed to recreate service browser (service type %s): %s\n", mb->type, @@ -688,8 +724,7 @@ mdns_browse(char *type, mdns_browse_cb cb) mb->next = browser_list; browser_list = mb; - /* Restrict service browsing to IPv4 for now, until evhttp gets support for IPv6 */ - b = avahi_service_browser_new(mdns_client, AVAHI_IF_UNSPEC, AVAHI_PROTO_INET, type, NULL, 0, browse_callback, mb); + b = avahi_service_browser_new(mdns_client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, type, NULL, 0, browse_callback, mb); if (!b) { DPRINTF(E_LOG, L_MDNS, "Failed to create service browser: %s\n", diff --git a/src/mdns_avahi.h b/src/mdns_avahi.h index a2b3c800..5dd22cad 100644 --- a/src/mdns_avahi.h +++ b/src/mdns_avahi.h @@ -4,7 +4,7 @@ #include -typedef void (* mdns_browse_cb)(const char *name, const char *type, const char *domain, const char *hostname, const char *address, int port, AvahiStringList *txt); +typedef void (* mdns_browse_cb)(const char *name, const char *type, const char *domain, const char *hostname, int family, const char *address, int port, AvahiStringList *txt); /* mDNS interface functions */ /* Call only from the main thread */ diff --git a/src/player.c b/src/player.c index e81eef23..5c56b58e 100644 --- a/src/player.c +++ b/src/player.c @@ -2748,7 +2748,7 @@ player_queue_clear(void) /* Thread: main (mdns) */ static void -raop_device_cb(const char *name, const char *type, const char *domain, const char *hostname, const char *address, int port, AvahiStringList *txt) +raop_device_cb(const char *name, const char *type, const char *domain, const char *hostname, int family, const char *address, int port, AvahiStringList *txt) { AvahiStringList *p; struct raop_device *rd; @@ -2762,6 +2762,9 @@ raop_device_cb(const char *name, const char *type, const char *domain, const cha int has_password; int ret; + if (family != AF_INET) + return; + ret = safe_hextou64(name, &id); if (ret < 0) { diff --git a/src/remote_pairing.c b/src/remote_pairing.c index f7eb2c14..18dffbc0 100644 --- a/src/remote_pairing.c +++ b/src/remote_pairing.c @@ -447,7 +447,7 @@ remote_pairing_read_pin(char *path) /* Thread: main (mdns) */ static void -touch_remote_cb(const char *name, const char *type, const char *domain, const char *hostname, const char *address, int port, AvahiStringList *txt) +touch_remote_cb(const char *name, const char *type, const char *domain, const char *hostname, int family, const char *address, int port, AvahiStringList *txt) { AvahiStringList *p; char *devname; @@ -457,6 +457,9 @@ touch_remote_cb(const char *name, const char *type, const char *domain, const ch size_t valsz; int ret; + if (family != AF_INET) + return; + if (port < 0) { /* If Remote stops advertising itself, the pairing either succeeded or