[mdns] Make connection test optional and only do it for Airplay (fixes #602)

Some remotes don't respond as expected to the test. Retune will give connection
refused, because the test is made too quickly, before the service is running.

Even if we delay the test it won't work because Retune crashes.

Since the false mdns advertisements are only seen on Airplay, we only do the
test there.
This commit is contained in:
ejurgensen 2018-10-14 22:10:28 +02:00
parent 07e46d75c8
commit df7456dc39
6 changed files with 25 additions and 21 deletions

View File

@ -4,6 +4,12 @@
#include "misc.h" #include "misc.h"
enum mdns_options
{
// Test connection to device and only call back if successful
MDNS_CONNECTION_TEST = (1 << 1),
};
typedef void (* mdns_browse_cb)(const char *name, const char *type, const char *domain, const char *hostname, int family, const char *address, int port, struct keyval *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, struct keyval *txt);
/* /*
@ -54,10 +60,11 @@ mdns_cname(char *name);
* @in type Type of service to look for, e.g. "_raop._tcp" * @in type Type of service to look for, e.g. "_raop._tcp"
* @in family AF_INET to browse for ipv4 services, AF_INET6 for ipv6, * @in family AF_INET to browse for ipv4 services, AF_INET6 for ipv6,
AF_UNSPEC for both AF_UNSPEC for both
* @in flags See mdns_options (only supported by Avahi implementation)
* @in cb Callback when service state changes (e.g. appears/disappears) * @in cb Callback when service state changes (e.g. appears/disappears)
* @return 0 on success, -1 on error * @return 0 on success, -1 on error
*/ */
int int
mdns_browse(char *type, int family, mdns_browse_cb cb); mdns_browse(char *type, int family, mdns_browse_cb cb, enum mdns_options flags);
#endif /* !__MDNS_H__ */ #endif /* !__MDNS_H__ */

View File

@ -348,6 +348,7 @@ struct mdns_browser
char *type; char *type;
AvahiProtocol protocol; AvahiProtocol protocol;
mdns_browse_cb cb; mdns_browse_cb cb;
enum mdns_options flags;
struct mdns_browser *next; struct mdns_browser *next;
}; };
@ -567,7 +568,7 @@ connection_test(int family, const char *address, const char *address_log, int po
// a connection to the address // a connection to the address
// - see also https://lists.freedesktop.org/archives/avahi/2012-September/002183.html // - see also https://lists.freedesktop.org/archives/avahi/2012-September/002183.html
static int static int
address_check(AvahiProtocol proto, const char *hostname, const AvahiAddress *addr, int port) address_check(AvahiProtocol proto, const char *hostname, const AvahiAddress *addr, int port, enum mdns_options flags)
{ {
char address[AVAHI_ADDRESS_STR_MAX]; char address[AVAHI_ADDRESS_STR_MAX];
char address_log[AVAHI_ADDRESS_STR_MAX + 2]; char address_log[AVAHI_ADDRESS_STR_MAX + 2];
@ -588,6 +589,9 @@ address_check(AvahiProtocol proto, const char *hostname, const AvahiAddress *add
return -1; return -1;
} }
if (!(flags & MDNS_CONNECTION_TEST))
return 0; // All done
ret = connection_test(family, address, address_log, port); ret = connection_test(family, address, address_log, port);
if (ret < 0) if (ret < 0)
{ {
@ -633,7 +637,7 @@ browse_record_callback(AvahiRecordBrowser *b, AvahiIfIndex intf, AvahiProtocol p
DPRINTF(E_DBG, L_MDNS, "Avahi Record Browser (%s, proto %d): NEW record %s for service type '%s'\n", hostname, proto, address, rb_data->mb->type); DPRINTF(E_DBG, L_MDNS, "Avahi Record Browser (%s, proto %d): NEW record %s for service type '%s'\n", hostname, proto, address, rb_data->mb->type);
ret = address_check(proto, hostname, &addr, rb_data->port); ret = address_check(proto, hostname, &addr, rb_data->port, rb_data->mb->flags);
if (ret < 0) if (ret < 0)
return; return;
@ -714,7 +718,7 @@ browse_resolve_callback(AvahiServiceResolver *r, AvahiIfIndex intf, AvahiProtoco
// devices (e.g. ApEx 1 gen) will include multiple records, and we need to // devices (e.g. ApEx 1 gen) will include multiple records, and we need to
// filter out those records that won't work (notably link-local). The value of // filter out those records that won't work (notably link-local). The value of
// *addr given by browse_resolve_callback is just the first record. // *addr given by browse_resolve_callback is just the first record.
ret = address_check(proto, hostname, addr, port); ret = address_check(proto, hostname, addr, port, mb->flags);
if (ret < 0) if (ret < 0)
{ {
CHECK_NULL(L_MDNS, rb_data = calloc(1, sizeof(struct mdns_record_browser))); CHECK_NULL(L_MDNS, rb_data = calloc(1, sizeof(struct mdns_record_browser)));
@ -1156,22 +1160,18 @@ mdns_cname(char *name)
} }
int int
mdns_browse(char *type, int family, mdns_browse_cb cb) mdns_browse(char *type, int family, mdns_browse_cb cb, enum mdns_options flags)
{ {
struct mdns_browser *mb; struct mdns_browser *mb;
AvahiServiceBrowser *b; AvahiServiceBrowser *b;
DPRINTF(E_DBG, L_MDNS, "Adding service browser for type %s\n", type); DPRINTF(E_DBG, L_MDNS, "Adding service browser for type %s\n", type);
mb = calloc(1, sizeof(struct mdns_browser)); CHECK_NULL(L_MDNS, mb = calloc(1, sizeof(struct mdns_browser)));
if (!mb)
{
DPRINTF(E_LOG, L_MDNS, "Out of memory for new mdns browser\n");
return -1;
}
mb->protocol = avahi_af_to_proto(family); mb->protocol = avahi_af_to_proto(family);
mb->type = strdup(type); mb->type = strdup(type);
mb->flags = flags;
mb->cb = cb; mb->cb = cb;
mb->next = browser_list; mb->next = browser_list;

View File

@ -116,6 +116,7 @@ struct mdns_browser
struct mdns_resolver *resolvers; struct mdns_resolver *resolvers;
char *regtype; char *regtype;
/* references */ /* references */
enum mdns_options flags;
mdns_browse_cb cb; mdns_browse_cb cb;
DNSServiceProtocol protocol; DNSServiceProtocol protocol;
void *res_uuid; void *res_uuid;
@ -871,20 +872,16 @@ mdns_browse_callback(DNSServiceRef sdRef, DNSServiceFlags flags,
} }
int int
mdns_browse(char *regtype, int family, mdns_browse_cb cb) mdns_browse(char *regtype, int family, mdns_browse_cb cb, enum mdns_options flags)
{ {
struct mdns_browser *mb; struct mdns_browser *mb;
DNSServiceErrorType err; DNSServiceErrorType err;
DPRINTF(E_DBG, L_MDNS, "Adding service browser for type %s\n", regtype); DPRINTF(E_DBG, L_MDNS, "Adding service browser for type %s\n", regtype);
mb = calloc(1, sizeof(*mb)); CHECK_NULL(L_MDNS, mb = calloc(1, sizeof(*mb)));
if (!mb)
{
DPRINTF(E_LOG, L_MDNS, "Out of memory creating service browser.\n");
return -1;
}
mb->flags = flags;
mb->cb = cb; mb->cb = cb;
/* flags are ignored in DNS-SD implementation */ /* flags are ignored in DNS-SD implementation */

View File

@ -1774,7 +1774,7 @@ cast_init(void)
else else
family = AF_INET; family = AF_INET;
ret = mdns_browse("_googlecast._tcp", family, cast_device_cb); ret = mdns_browse("_googlecast._tcp", family, cast_device_cb, 0);
if (ret < 0) if (ret < 0)
{ {
DPRINTF(E_LOG, L_CAST, "Could not add mDNS browser for Chromecast devices\n"); DPRINTF(E_LOG, L_CAST, "Could not add mDNS browser for Chromecast devices\n");

View File

@ -5025,7 +5025,7 @@ raop_init(void)
else else
family = AF_INET; family = AF_INET;
ret = mdns_browse("_raop._tcp", family, raop_device_cb); ret = mdns_browse("_raop._tcp", family, raop_device_cb, MDNS_CONNECTION_TEST);
if (ret < 0) if (ret < 0)
{ {
DPRINTF(E_LOG, L_RAOP, "Could not add mDNS browser for AirPlay devices\n"); DPRINTF(E_LOG, L_RAOP, "Could not add mDNS browser for AirPlay devices\n");

View File

@ -818,7 +818,7 @@ remote_pairing_init(void)
#endif /* HAVE_EVENTFD */ #endif /* HAVE_EVENTFD */
// No ipv6 for remote at the moment // No ipv6 for remote at the moment
ret = mdns_browse("_touch-remote._tcp", AF_INET, touch_remote_cb); ret = mdns_browse("_touch-remote._tcp", AF_INET, touch_remote_cb, 0);
if (ret < 0) if (ret < 0)
{ {
DPRINTF(E_FATAL, L_REMOTE, "Could not browse for Remote services\n"); DPRINTF(E_FATAL, L_REMOTE, "Could not browse for Remote services\n");