Skip to content

Commit

Permalink
serve and auto publishes DNS Service Discovery records
Browse files Browse the repository at this point in the history
On Avahi/dbus systems (Linux/FreeBSD), running web servers are
announced to the local network over DNS-SD so clients can more
easily find these services. IPv6 annonce used with the `-6` switch.

Will just give up if the required system python bindings are not
present and will not make a fuzz about it.
  • Loading branch information
da2x committed Oct 10, 2015
1 parent 359a581 commit 4572f4c
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 2 deletions.
3 changes: 3 additions & 0 deletions CHANGES.txt
Expand Up @@ -3,6 +3,9 @@ New in master

Features
--------
* ``serve`` and ``auto`` publishes DNS Service Discovery records
to the local network announcing they’re running web servers.


Bugfixes
--------
Expand Down
7 changes: 6 additions & 1 deletion nikola/plugins/command/auto/__init__.py
Expand Up @@ -63,7 +63,7 @@


from nikola.plugin_categories import Command
from nikola.utils import req_missing, get_logger, get_theme_path, STDERR_HANDLER
from nikola.utils import dns_sd, req_missing, get_logger, get_theme_path, STDERR_HANDLER
LRJS_PATH = os.path.join(os.path.dirname(__file__), 'livereload.js')
error_signal = signal('error')
refresh_signal = signal('refresh')
Expand All @@ -85,6 +85,8 @@ class CommandAuto(Command):
logger = None
has_server = True
doc_purpose = "builds and serves a site; automatically detects site changes, rebuilds, and optionally refreshes a browser"
dns_sd = None

cmd_options = [
{
'name': 'port',
Expand Down Expand Up @@ -233,9 +235,12 @@ def __call__(self, environ, start_response):
webbrowser.open('http://{0}:{1}'.format(host, port))

try:
self.dns_sd = dns_sd(port, (options['ipv6'] or '::' in host))
ws.serve_forever()
except KeyboardInterrupt:
self.logger.info("Server is shutting down.")
if self.dns_sd:
self.dns_sd.Reset()
# This is a hack, but something is locking up in a futex
# and exit() doesn't work.
os.kill(os.getpid(), 15)
Expand Down
6 changes: 5 additions & 1 deletion nikola/plugins/command/serve.py
Expand Up @@ -45,7 +45,7 @@


from nikola.plugin_categories import Command
from nikola.utils import get_logger, STDERR_HANDLER
from nikola.utils import dns_sd, get_logger, STDERR_HANDLER


class IPv6Server(HTTPServer):
Expand All @@ -61,6 +61,7 @@ class CommandServe(Command):
doc_usage = "[options]"
doc_purpose = "start the test webserver"
logger = None
dns_sd = None

cmd_options = (
{
Expand Down Expand Up @@ -150,9 +151,12 @@ def _execute(self, options, args):
raise e
else:
try:
self.dns_sd = dns_sd(options['port'], (options['ipv6'] or '::' in options['address']))
httpd.serve_forever()
except KeyboardInterrupt:
self.logger.info("Server is shutting down.")
if self.dns_sd:
self.dns_sd.Reset()
return 130


Expand Down
22 changes: 22 additions & 0 deletions nikola/utils.py
Expand Up @@ -1813,6 +1813,28 @@ def color_hsl_adjust_hex(hexstr, adjust_h=None, adjust_s=None, adjust_l=None):
return husl.husl_to_hex(h, s, l)


def dns_sd(port, inet6):
"""Optimistically publish a HTTP service to the local network over DNS-SD. (Linux/FreeBSD only.)"""
try:
import avahi
import dbus
inet = avahi.PROTO_INET6 if inet6 else avahi.PROTO_INET
bus = dbus.SystemBus()
bus_server = dbus.Interface(bus.get_object(avahi.DBUS_NAME,
avahi.DBUS_PATH_SERVER),
avahi.DBUS_INTERFACE_SERVER)
bus_group = dbus.Interface(bus.get_object(avahi.DBUS_NAME,
bus_server.EntryGroupNew()),
avahi.DBUS_INTERFACE_ENTRY_GROUP)
bus_group.AddService(avahi.IF_UNSPEC, inet, dbus.UInt32(0),
'Nikola Server', '_http._tcp', '', '',
dbus.UInt16(port), '')
bus_group.Commit()
return bus_group # remember to bus_group.Reset() to unpublish
except:
return None


# Stolen from textwrap in Python 3.4.3.
def indent(text, prefix, predicate=None):
"""Add 'prefix' to the beginning of selected lines in 'text'.
Expand Down

0 comments on commit 4572f4c

Please sign in to comment.