From a4f38e2018c50e3db14df31d300b2b39c9a43147 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Tue, 15 Sep 2015 11:05:56 +0200 Subject: [PATCH 1/5] zeroconf: Make stype argument required --- mopidy/http/actor.py | 6 ++++-- mopidy/mpd/actor.py | 3 ++- mopidy/zeroconf.py | 6 +++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/mopidy/http/actor.py b/mopidy/http/actor.py index 5fe29134..8b4835da 100644 --- a/mopidy/http/actor.py +++ b/mopidy/http/actor.py @@ -57,10 +57,12 @@ class HttpFrontend(pykka.ThreadingActor, CoreListener): if self.zeroconf_name: self.zeroconf_http = zeroconf.Zeroconf( - stype='_http._tcp', name=self.zeroconf_name, + name=self.zeroconf_name, + stype='_http._tcp', port=self.port) self.zeroconf_mopidy_http = zeroconf.Zeroconf( - stype='_mopidy-http._tcp', name=self.zeroconf_name, + name=self.zeroconf_name, + stype='_mopidy-http._tcp', port=self.port) self.zeroconf_http.publish() self.zeroconf_mopidy_http.publish() diff --git a/mopidy/mpd/actor.py b/mopidy/mpd/actor.py index 8eb59c1f..69d165ca 100644 --- a/mopidy/mpd/actor.py +++ b/mopidy/mpd/actor.py @@ -45,7 +45,8 @@ class MpdFrontend(pykka.ThreadingActor, CoreListener): def on_start(self): if self.zeroconf_name: self.zeroconf_service = zeroconf.Zeroconf( - stype='_mpd._tcp', name=self.zeroconf_name, + name=self.zeroconf_name, + stype='_mpd._tcp', port=self.port) self.zeroconf_service.publish() diff --git a/mopidy/zeroconf.py b/mopidy/zeroconf.py index ddd155b6..b5dd4f5d 100644 --- a/mopidy/zeroconf.py +++ b/mopidy/zeroconf.py @@ -37,8 +37,8 @@ class Zeroconf(object): Currently, this only works on Linux using Avahi via D-Bus. :param str name: human readable name of the service, e.g. 'MPD on neptune' - :param int port: TCP port of the service, e.g. 6600 :param str stype: service type, e.g. '_mpd._tcp' + :param int port: TCP port of the service, e.g. 6600 :param str domain: local network domain name, defaults to '' :param str host: interface to advertise the service on, defaults to all interfaces @@ -47,9 +47,9 @@ class Zeroconf(object): :type text: list of str """ - def __init__(self, name, port, stype=None, domain=None, text=None): + def __init__(self, name, stype, port, domain=None, text=None): self.group = None - self.stype = stype or '_http._tcp' + self.stype = stype self.domain = domain or '' self.port = port self.text = text or [] From 684ea80f58a64469889c71b99a58f6db07da1d5d Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Tue, 15 Sep 2015 11:14:32 +0200 Subject: [PATCH 2/5] zeroconf: Move bus and server setup to init --- mopidy/zeroconf.py | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/mopidy/zeroconf.py b/mopidy/zeroconf.py index b5dd4f5d..57d3f62d 100644 --- a/mopidy/zeroconf.py +++ b/mopidy/zeroconf.py @@ -54,6 +54,17 @@ class Zeroconf(object): self.port = port self.text = text or [] + self.bus = None + self.server = None + self.group = None + try: + self.bus = dbus.SystemBus() + self.server = dbus.Interface( + self.bus.get_object('org.freedesktop.Avahi', '/'), + 'org.freedesktop.Avahi.Server') + except dbus.exceptions.DBusException as e: + logger.debug('%s: Server failed: %s', self, e) + template = string.Template(name) self.name = template.safe_substitute( hostname=socket.getfqdn(), port=self.port) @@ -78,21 +89,23 @@ class Zeroconf(object): logger.debug('%s: dbus not installed; publish failed.', self) return False - try: - bus = dbus.SystemBus() + if not self.bus: + logger.debug('%s: Bus not available; publish failed.', self) + return False - if not bus.name_has_owner('org.freedesktop.Avahi'): + if not self.server: + logger.debug('%s: Server not available; publish failed.', self) + return False + + try: + if not self.bus.name_has_owner('org.freedesktop.Avahi'): logger.debug( '%s: Avahi service not running; publish failed.', self) return False - server = dbus.Interface( - bus.get_object('org.freedesktop.Avahi', '/'), - 'org.freedesktop.Avahi.Server') - self.group = dbus.Interface( - bus.get_object( - 'org.freedesktop.Avahi', server.EntryGroupNew()), + self.bus.get_object( + 'org.freedesktop.Avahi', self.server.EntryGroupNew()), 'org.freedesktop.Avahi.EntryGroup') self.group.AddService( From dbafe746625af9736e5b4482b27f6d4b579d749f Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Tue, 15 Sep 2015 11:22:55 +0200 Subject: [PATCH 3/5] zeroconf: Use Avahi's host management by default Fixes #1283 --- mopidy/zeroconf.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/mopidy/zeroconf.py b/mopidy/zeroconf.py index 57d3f62d..64a9b111 100644 --- a/mopidy/zeroconf.py +++ b/mopidy/zeroconf.py @@ -40,18 +40,17 @@ class Zeroconf(object): :param str stype: service type, e.g. '_mpd._tcp' :param int port: TCP port of the service, e.g. 6600 :param str domain: local network domain name, defaults to '' - :param str host: interface to advertise the service on, defaults to all - interfaces + :param str host: interface to advertise the service on, defaults to '' :param text: extra information depending on ``stype``, defaults to empty list :type text: list of str """ - def __init__(self, name, stype, port, domain=None, text=None): - self.group = None + def __init__(self, name, stype, port, domain='', host='', text=None): self.stype = stype - self.domain = domain or '' self.port = port + self.domain = domain + self.host = host self.text = text or [] self.bus = None @@ -65,10 +64,9 @@ class Zeroconf(object): except dbus.exceptions.DBusException as e: logger.debug('%s: Server failed: %s', self, e) - template = string.Template(name) - self.name = template.safe_substitute( - hostname=socket.getfqdn(), port=self.port) - self.host = '%s.local' % socket.getfqdn() + self.display_hostname = '%s.local' % socket.getfqdn() + self.name = string.Template(name).safe_substitute( + hostname=self.display_hostname, port=port) def __str__(self): return 'Zeroconf service %s at [%s]:%d' % ( @@ -110,7 +108,8 @@ class Zeroconf(object): self.group.AddService( _AVAHI_IF_UNSPEC, _AVAHI_PROTO_UNSPEC, - dbus.UInt32(_AVAHI_PUBLISHFLAGS_NONE), self.name, self.stype, + dbus.UInt32(_AVAHI_PUBLISHFLAGS_NONE), + self.name, self.stype, self.domain, self.host, dbus.UInt16(self.port), _convert_text_list_to_dbus_format(self.text)) From 6ad235564e51f16080246d7d6028daffbc5d6ec7 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Tue, 15 Sep 2015 11:25:17 +0200 Subject: [PATCH 4/5] zeroconf: Display Avahi server's hostname --- mopidy/zeroconf.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/mopidy/zeroconf.py b/mopidy/zeroconf.py index 64a9b111..4ca49b69 100644 --- a/mopidy/zeroconf.py +++ b/mopidy/zeroconf.py @@ -1,7 +1,6 @@ from __future__ import absolute_import, unicode_literals import logging -import socket import string logger = logging.getLogger(__name__) @@ -64,13 +63,13 @@ class Zeroconf(object): except dbus.exceptions.DBusException as e: logger.debug('%s: Server failed: %s', self, e) - self.display_hostname = '%s.local' % socket.getfqdn() + self.display_hostname = '%s' % self.server.GetHostName() self.name = string.Template(name).safe_substitute( hostname=self.display_hostname, port=port) def __str__(self): - return 'Zeroconf service %s at [%s]:%d' % ( - self.stype, self.host, self.port) + return 'Zeroconf service "%s" (%s at [%s]:%d)' % ( + self.name, self.stype, self.host, self.port) def publish(self): """Publish the service. From ae3b236e6866ccd84b268213dc9de2f72eb8b06f Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Tue, 15 Sep 2015 11:28:07 +0200 Subject: [PATCH 5/5] docs: Add Zeroconf changes to changelog --- docs/changelog.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index 92780e13..0d23a608 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -16,6 +16,16 @@ Local - Made :confval:`local/data_dir` really deprecated. This change breaks older versions of Mopidy-Local-SQLite and Mopidy-Local-Images. +Zeroconf +-------- + +- Require ``stype`` argument to :class:`mopidy.zeroconf.Zeroconf`. + +- Use Avahi's interface selection by default. (Fixes: :issue:`1283`) + +- Use Avahi server's hostname instead of ``socket.getfqdn()`` in service + display name. + Cleanups --------