Skip to content
This repository was archived by the owner on May 28, 2022. It is now read-only.

Zeroconf support for headless server #648

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ before_install:
- sudo apt-get -qq install gstreamer0.10-plugins-bad gstreamer0.10-plugins-ugly
- sudo apt-get -qq install gstreamer0.10-pulseaudio
- sudo apt-get -qq install gstreamer0.10-alsa
- sudo apt-get -qq install python-avahi
- python -c 'import avahi'
- python -c 'import dbus'
# command to install dependencies, e.g. pip install -r requirements.txt --use-mirrors
install:
- pip install -r dev_requirements.txt --use-mirrors
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ oauth<1.1
simplejson<3.4
tabulate==0.7.2
yapsy<1.11
zeroconf<=0.15.1
56 changes: 56 additions & 0 deletions src/freeseer/framework/announcer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

# freeseer - vga/presentation capture software
#
# Copyright (C) 2014 Free and Open Source Software Learning Centre
# http://fosslc.org
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

# For support, questions, suggestions or any other inquiries, visit:
# http://wiki.github.com/Freeseer/freeseer/

import avahi
import dbus


class ServiceAnnouncer:
"""ServiceAnnouncer publishes Freeseer service over Zeroconf/Avahi protocol"""
def __init__(self, name, service, port, txt):
"""
Args:
name - instance name i.e Freeseer Host
service - service type i.e _freeseer._tcp
port - port number
txt - List containing strings of information you wish to include.
"""
bus = dbus.SystemBus()
server = dbus.Interface(bus.get_object(avahi.DBUS_NAME, avahi.DBUS_PATH_SERVER), avahi.DBUS_INTERFACE_SERVER)
self.group = dbus.Interface(bus.get_object(avahi.DBUS_NAME, server.EntryGroupNew()), avahi.DBUS_INTERFACE_ENTRY_GROUP)
self.service = service
self.name = name
self.port = port
self.txt = txt

def advertise(self):
"""Announces Freeseer service over Zeroconf/Avahi"""
self.group.AddService(avahi.IF_UNSPEC, avahi.PROTO_INET, 0,
self.name, self.service, '', '', self.port,
avahi.string_array_to_txt_array(self.txt))
self.group.Commit()

def unpublish(self):
"""Removes service from Zeroconf/Avahi"""
self.group.Reset()
64 changes: 64 additions & 0 deletions src/freeseer/framework/listener.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

# freeseer - vga/presentation capture software
#
# Copyright (C) 2014 Free and Open Source Software Learning Centre
# http://fosslc.org
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

# For support, questions, suggestions or any other inquiries, visit:
# http://wiki.github.com/Freeseer/freeseer/

import socket
from time import sleep

from zeroconf import ServiceBrowser, Zeroconf


class Listener(object):

def __init__(self):
self.servers = {}

def removeService(self, zeroconf, type, name):
"""Updates dictionary of available freeseer servers"""
info = zeroconf.getServiceInfo(type, name)
ipaddr = socket.inet_ntoa(info.getAddress())
port = info.getPort()
del self.servers[(ipaddr, port)]

def addService(self, zeroconf, type, name):
"""Updates dictionary of available freeseer servers"""
info = zeroconf.getServiceInfo(type, name)
if info:
ipaddr = socket.inet_ntoa(info.getAddress())
port = info.getPort()
self.servers[(ipaddr, port)] = {
'name': name,
'type': type,
}


def search(timeout):
results = []
zeroconf = Zeroconf(socket.gethostbyname(socket.gethostname()))
listener = Listener()
ServiceBrowser(zeroconf, '_freeseer._tcp.local.', listener)
sleep(timeout)
for (ipaddr, port), value in listener.servers.iteritems():
results.append('{}\t{}:{}'.format(value['name'].split('.')[0], ipaddr, port))
zeroconf.close()
return results
28 changes: 27 additions & 1 deletion src/freeseer/frontend/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import signal
import sys
import textwrap
from time import sleep

import pygst
import yapsy
Expand Down Expand Up @@ -70,6 +71,7 @@ def setup_parser():
setup_parser_report(subparsers)
setup_parser_upload(subparsers)
setup_parser_server(subparsers)
setup_parser_browse(subparsers)
return parser


Expand Down Expand Up @@ -155,7 +157,13 @@ def setup_parser_upload_youtube(subparsers):
def setup_parser_server(subparsers):
"""Setup server command parser"""
parser = subparsers.add_parser("server", help="Setup a freeseer restful server")
parser.add_argument("-f", "--filename", type=unicode, help="file to load recordings")
parser.add_argument("--filename", type=unicode, help="file to load recordings")


def setup_parser_browse(subparsers):
"""Setup browse command parser"""
parsers = subparsers.add_parser('browse', help='Search for freeseer servers on the network')
parsers.add_argument('-t', '--timeout', help='Poll for freeseer servers continually', type=int)


def parse_args(parser, parse_args=None):
Expand Down Expand Up @@ -272,6 +280,13 @@ def parse_args(parser, parse_args=None):
else:
launch_server()

elif args.app == 'browse':
if args.timeout:
timeout = args.timeout
launch_browser(timeout)
else:
launch_browser()


def launch_recordapp():
"""Launch the Recording GUI if no arguments are passed"""
Expand Down Expand Up @@ -341,3 +356,14 @@ def launch_server(storage_file="recording_storage"):
import freeseer.frontend.controller.server as server

server.start_server(storage_file)


def launch_browser(timeout=5):
"""Search for Freeseer hosts on client's network"""
import freeseer.framework.listener as listener

print('Searching for Freeseer Hosts\n')
results = listener.search(max(timeout, 5))
print('Results:')
print('\n'.join(results))
sleep(0.1) # workaround hack. Without sleep(0.1) exception is thrown on shutdown on my ubuntu vm.
16 changes: 14 additions & 2 deletions src/freeseer/frontend/controller/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,33 @@
# http://wiki.github.com/Freeseer/freeseer/

import functools
import signal
import sys

from flask import jsonify

from freeseer.frontend.controller import app
from freeseer.framework.announcer import ServiceAnnouncer


def start_server(storage_file):
def start_server(storage_file, port=7079):
"""Starts the restapi server.

Args:
storage_file - name of storage file to which you are saving recordings
port - the port you wish to broadcast your server on.
"""

app.storage_file_path = storage_file
app.run()
app.service_announcer = ServiceAnnouncer('Freeseer Host', '_freeseer._tcp', port, [])
app.service_announcer.advertise()
signal.signal(signal.SIGTERM, remove)
app.run('::0.0.0.0', port)


def remove(signal, frame):
app.service_announcer.remove_service()
sys.exit(0)


def http_response(status_code):
Expand Down