[tor-commits] [oonib/master] Fix privilege shedding and daemonisation of oonibackend (#80)

art at torproject.org art at torproject.org
Mon May 30 13:44:56 UTC 2016


commit 5940999a49af50ff49aeabb1103543889c598312
Author: Arturo Filastò <arturo at filasto.net>
Date:   Mon May 30 15:24:07 2016 +0200

    Fix privilege shedding and daemonisation of oonibackend (#80)
    
    * Fix privilege shedding and daemonisation of oonibackend
    
    * Rewrite to use twistd
    
    * Launch tor only after we have forked
    
    * Set the UID of when starting tor
    
    This fixes #65
    
    * Add gitignore files and remove empty.txt files
    
    * Drop support for super old versions of txtorcon
    
    * Remove now unnecessary hacks to maintain backward compatibility
    
    * Fix permissions on temporary tor data directory
---
 bin/oonib               |  38 ++-----
 data/archive/.gitignore |   2 +
 data/archive/empty.txt  |   2 -
 data/decks/.gitignore   |   3 +
 data/inputs/.gitignore  |   3 +
 data/reports/.gitignore |   2 +
 data/tor/.gitignore     |   2 +
 data/tor/empty.txt      |   2 -
 oonib.conf.example      |   4 -
 oonib/config.py         |   2 +
 oonib/log.py            |  61 +----------
 oonib/onion.py          |  63 +++++------
 oonib/oonibackend.py    | 280 ++++++++++++++++++++++++++----------------------
 requirements.txt        |   2 +-
 setup.py                |   6 +-
 15 files changed, 213 insertions(+), 259 deletions(-)

diff --git a/bin/oonib b/bin/oonib
index 109c74e..ccbe246 100755
--- a/bin/oonib
+++ b/bin/oonib
@@ -2,55 +2,35 @@
 
 import sys
 import os
-from twisted.python import log, usage
-from twisted.internet import reactor
-from twisted.application import app
 
 # Hack to set the proper sys.path. Overcomes the export PYTHONPATH pain.
 sys.path[:] = map(os.path.abspath, sys.path)
 sys.path.insert(0, os.path.abspath(os.getcwd()))
 
-from oonib import errors as e
+from oonib import errors
 from oonib.config import config
-from oonib.log import LoggerFactory
-
 try:
     config.load()
-except e.ConfigFileNotSpecified:
+except errors.ConfigFileNotSpecified:
     print "Config file not specified!"
     print "Use -c to specify one!"
     config.usageOptions()
     sys.exit(1)
-except e.ConfigFileDoesNotExist, path:
+except errors.ConfigFileDoesNotExist, path:
     print "Config file \"%s\" does not exist!" % path
     sys.exit(2)
-except e.InvalidReportDirectory, path:
+except errors.InvalidReportDirectory, path:
     print "Invalid report directory: %s!" % path
     sys.exit(3)
-except e.InvalidArchiveDirectory, path:
+except errors.InvalidArchiveDirectory, path:
     print "Invalid archive directory: %s!" % path
     sys.exit(4)
-except e.InvalidInputDirectory, path:
+except errors.InvalidInputDirectory, path:
     print "Invalid input directory: %s" % path
     sys.exit(5)
-except e.InvalidDeckDirectory, path:
+except errors.InvalidDeckDirectory, path:
     print "Invalid deck directory: %s" % path
     sys.exit(6)
 
-if config.main.chroot:
-    sys.argv.append('--chroot')
-    sys.argv.append(config.chroot)
-
-if not config.main.nodaemon:
-    sys.argv.append('-y')
-
-from oonib.oonibackend import application
-
-from twisted.scripts._twistd_unix import UnixApplicationRunner
-class OBaseRunner(UnixApplicationRunner):
-    temporary_data_dir = None
-    def createOrGetApplication(self):
-        return application
-
-OBaseRunner.loggerFactory = LoggerFactory
-OBaseRunner(config.main).run()
+from oonib import oonibackend
+oonibackend.start()
diff --git a/data/archive/.gitignore b/data/archive/.gitignore
new file mode 100644
index 0000000..d6b7ef3
--- /dev/null
+++ b/data/archive/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/data/archive/empty.txt b/data/archive/empty.txt
deleted file mode 100644
index 9a166f9..0000000
--- a/data/archive/empty.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-In here will end up the archived reports.
-This file may be deleted at any time.
diff --git a/data/decks/.gitignore b/data/decks/.gitignore
new file mode 100644
index 0000000..514e47a
--- /dev/null
+++ b/data/decks/.gitignore
@@ -0,0 +1,3 @@
+*
+!.gitignore
+!README
diff --git a/data/inputs/.gitignore b/data/inputs/.gitignore
new file mode 100644
index 0000000..a0991ff
--- /dev/null
+++ b/data/inputs/.gitignore
@@ -0,0 +1,3 @@
+*
+!.gitignore
+!Makefile
diff --git a/data/reports/.gitignore b/data/reports/.gitignore
new file mode 100644
index 0000000..d6b7ef3
--- /dev/null
+++ b/data/reports/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/data/tor/.gitignore b/data/tor/.gitignore
new file mode 100644
index 0000000..d6b7ef3
--- /dev/null
+++ b/data/tor/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/data/tor/empty.txt b/data/tor/empty.txt
deleted file mode 100644
index ec3be8f..0000000
--- a/data/tor/empty.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-In here will end up all tor related files.
-This file may be deleted at any time.
diff --git a/oonib.conf.example b/oonib.conf.example
index 6f4c7f3..bcf8393 100644
--- a/oonib.conf.example
+++ b/oonib.conf.example
@@ -7,8 +7,6 @@ main:
     bouncer_file: data/bouncer.yaml
 
     logfile: null
-    database_uri: 'sqlite://oonib_test_db.db'
-    db_threadpool_size: 10
     tor_binary: null
     socks_port: 9055
     tor2webmode: false
@@ -21,9 +19,7 @@ main:
     euid: null
     uid: null
     gid: null
-    uuid: null
     no_save: true
-    profile: null
     debug: false
     stale_time: 3600
 
diff --git a/oonib/config.py b/oonib/config.py
index 31128a9..be29ec1 100644
--- a/oonib/config.py
+++ b/oonib/config.py
@@ -28,6 +28,8 @@ class Config(object):
             raise e.ConfigFileDoesNotExist(config_file)
 
         self.main = Storage(configuration['main'].items())
+        if self.main.logfile is None:
+            self.main.logfile = 'oonib.log'
 
         self.helpers = Storage()
         for name, helper in configuration['helpers'].items():
diff --git a/oonib/log.py b/oonib/log.py
index a79199e..c229f35 100644
--- a/oonib/log.py
+++ b/oonib/log.py
@@ -6,18 +6,14 @@
 Twisted logger for the ooni backend system.
 """
 
-import os
 import sys
 import codecs
 import logging
 import traceback
 
 from twisted.python import log as txlog
-from twisted.python import util
 from twisted.python.failure import Failure
-from twisted.python.logfile import DailyLogFile
 
-from oonib import otime
 from oonib.config import config
 
 # Get rid of the annoying "No route found for
@@ -47,56 +43,21 @@ def log_encode(logmsg):
                                                      repr(logmsg)))
 
 
-class LogWithNoPrefix(txlog.FileLogObserver):
-    def emit(self, eventDict):
-        text = txlog.textFromEventDict(eventDict)
-        if text is None:
-            return
-
-        util.untilConcludes(self.write, "%s\n" % text)
-        util.untilConcludes(self.flush)  # Hoorj!
-
-
-def start(application_name="oonib"):
-    daily_logfile = None
-
-    if not config.main.logfile:
-        logfile = 'oonib.log'
-    else:
-        logfile = config.main.logfile
-
-    log_folder = os.path.dirname(logfile)
-    log_filename = os.path.basename(logfile)
-
-    daily_logfile = DailyLogFile(log_filename, log_folder)
-
-    txlog.msg("Starting %s on %s (%s UTC)" % (application_name,
-                                              otime.prettyDateNow(),
-                                              otime.utcPrettyDateNow()))
-    txlog.msg("oonib version %s" % config.backend_version)
-    txlog.startLoggingWithObserver(LogWithNoPrefix(sys.stdout).emit)
-    txlog.addObserver(txlog.FileLogObserver(daily_logfile).emit)
-
-
-def stop():
-    print "Stopping OONI"
-
-
 def msg(msg, *arg, **kw):
-    print "%s" % log_encode(msg)
+    txlog.msg("%s" % log_encode(msg))
 
 
 def debug(msg, *arg, **kw):
     if config.main.get('debug'):
-        print "[D] %s" % log_encode(msg)
+        txlog.msg("[D] %s" % log_encode(msg))
 
 
 def warn(msg, *arg, **kw):
-    print "[W] %s" % log_encode(msg)
+    txlog.msg("[W] %s" % log_encode(msg))
 
 
 def err(msg, *arg, **kw):
-    print "[!] %s" % log_encode(msg)
+    txlog.err("[!] %s" % log_encode(msg))
 
 
 def exception(error):
@@ -109,17 +70,3 @@ def exception(error):
     else:
         exc_type, exc_value, exc_traceback = sys.exc_info()
         traceback.print_exception(exc_type, exc_value, exc_traceback)
-
-
-class LoggerFactory(object):
-    """
-    This is a logger factory to be used by oonib
-    """
-    def __init__(self, options):
-        pass
-
-    def start(self, application):
-        start("OONIB")
-
-    def stop(self):
-        txlog.msg("Stopping OONIB")
diff --git a/oonib/onion.py b/oonib/onion.py
index 0a7a155..9a5c2c3 100644
--- a/oonib/onion.py
+++ b/oonib/onion.py
@@ -1,31 +1,17 @@
+import pwd
 import tempfile
+
 from oonib import log
 from oonib.config import config
-from twisted.internet import reactor, endpoints, defer
+from twisted.internet import defer
 import os
 
 from random import randint
 import socket
 
-from txtorcon import TCPHiddenServiceEndpoint, TorConfig
+from txtorcon import TorConfig
 from txtorcon import launch_tor
 
-from txtorcon import __version__ as txtorcon_version
-if tuple(map(int, txtorcon_version.split('.'))) < (0, 9, 0):
-    """
-    Fix for bug in txtorcon versions < 0.9.0 where TCPHiddenServiceEndpoint
-    listens on all interfaces by default.
-    """
-    def create_listener(self, proto):
-        self._update_onion(self.hiddenservice.dir)
-        self.tcp_endpoint = endpoints.TCP4ServerEndpoint(self.reactor,
-                                                         self.listen_port,
-                                                         interface='127.0.0.1')
-        d = self.tcp_endpoint.listen(self.protocolfactory)
-        d.addCallback(self._add_attributes).addErrback(self._retry_local_port)
-        return d
-    TCPHiddenServiceEndpoint._create_listener =  create_listener
-
 def randomFreePort(addr="127.0.0.1"):
     """
     Args:
@@ -56,11 +42,15 @@ def txSetupFailed(failure):
 def _configTor():
     torconfig = TorConfig()
 
-    if config.main.socks_port:
-        torconfig.SocksPort = config.main.socks_port
-    if config.main.control_port:
-        torconfig.ControlPort = config.main.control_port
-    if config.main.tor2webmode:
+    if config.main.socks_port is None:
+        config.main.socks_port = int(randomFreePort())
+    torconfig.SocksPort = config.main.socks_port
+
+    if config.main.control_port is None:
+        config.main.control_port = int(randomFreePort())
+    torconfig.ControlPort = config.main.control_port
+
+    if config.main.tor2webmode is True:
         torconfig.Tor2webMode = 1
         torconfig.CircuitBuildTimeout = 60
     if config.main.tor_datadir is None:
@@ -68,26 +58,29 @@ def _configTor():
         log.warn("Option 'tor_datadir' in oonib.conf is unspecified!")
         log.warn("Using %s" % temporary_data_dir)
         torconfig.DataDirectory = temporary_data_dir
+        uid = -1
+        gid = -1
+        if config.main.uid is not None:
+            uid = config.main.uid
+        if config.main.gid is not None:
+            gid = config.main.gid
+        os.chown(temporary_data_dir, uid, gid)
     else:
         if os.path.exists(config.main.tor_datadir):
             torconfig.DataDirectory = os.path.abspath(config.main.tor_datadir)
         else:
             raise Exception("Could not find tor datadir")
 
+    if config.main.uid is not None:
+        try:
+            user = pwd.getpwuid(config.main.uid)[0]
+        except KeyError:
+            raise Exception("Invalid user ID")
+        torconfig.User = user
+
     tor_log_file = os.path.join(torconfig.DataDirectory, "tor.log")
     torconfig.Log = ["notice stdout", "notice file %s" % tor_log_file]
     torconfig.save()
-    if not hasattr(torconfig, 'ControlPort'):
-        control_port = int(randomFreePort())
-        torconfig.ControlPort = control_port
-        config.main.control_port = control_port
-
-    if not hasattr(torconfig, 'SocksPort'):
-        socks_port = int(randomFreePort())
-        torconfig.SocksPort = socks_port
-        config.main.socks_port = socks_port
-
-    torconfig.save()
     return torconfig
 
 # get_global_tor is a near-rip of that from txtorcon (so you can have some
@@ -110,7 +103,7 @@ def get_global_tor(reactor):
 
             # start Tor launching
             def updates(prog, tag, summary):
-                print("%d%%: %s" % (prog, summary))
+                log.msg("%d%%: %s" % (prog, summary))
             yield launch_tor(_global_tor_config, reactor,
                     progress_updates=updates,
                     tor_binary=config.main.tor_binary)
diff --git a/oonib/oonibackend.py b/oonib/oonibackend.py
index ebf3c52..a57bf92 100644
--- a/oonib/oonibackend.py
+++ b/oonib/oonibackend.py
@@ -7,7 +7,9 @@
 # In here we start all the test helpers that are required by ooniprobe and
 # start the report collector
 
-from distutils.version import LooseVersion
+import os
+import sys
+
 
 from oonib.api import ooniBackend, ooniBouncer
 from oonib.config import config
@@ -15,107 +17,22 @@ from oonib.onion import get_global_tor
 from oonib.testhelpers import dns_helpers, ssl_helpers
 from oonib.testhelpers import http_helpers, tcp_helpers
 
-import os
-
+from twisted.scripts import twistd
+from twisted.python import usage
 from twisted.application import internet, service
-from twisted.internet import reactor, endpoints, ssl, defer
+from twisted.internet import reactor, endpoints, ssl
 from twisted.names import dns
 
-from txtorcon import TCPHiddenServiceEndpoint, TorConfig
-from txtorcon import __version__ as txtorcon_version
-
-if config.main.uid and config.main.gid:
-    application = service.Application('oonibackend', uid=config.main.uid,
-                                      gid=config.main.gid)
-else:
-    application = service.Application('oonibackend')
-
-multiService = service.MultiService()
-
-if config.helpers['ssl'].port:
-    print "Starting SSL helper on %s" % config.helpers['ssl'].port
-    ssl_helper = internet.SSLServer(int(config.helpers['ssl'].port),
-                                    http_helpers.HTTPReturnJSONHeadersHelper(),
-                                    ssl_helpers.SSLContext(config))
-    multiService.addService(ssl_helper)
-    ssl_helper.startService()
-
-# Start the DNS Server related services
-if config.helpers['dns'].tcp_port:
-    print "Starting TCP DNS Helper on %s" % config.helpers['dns'].tcp_port
-    tcp_dns_helper = internet.TCPServer(int(config.helpers['dns'].tcp_port),
-                                        dns_helpers.DNSTestHelper())
-    multiService.addService(tcp_dns_helper)
-    tcp_dns_helper.startService()
-
-if config.helpers['dns'].udp_port:
-    print "Starting UDP DNS Helper on %s" % config.helpers['dns'].udp_port
-    udp_dns_factory = dns.DNSDatagramProtocol(dns_helpers.DNSTestHelper())
-    udp_dns_helper = internet.UDPServer(int(config.helpers['dns'].udp_port),
-                                        udp_dns_factory)
-    multiService.addService(udp_dns_helper)
-    udp_dns_helper.startService()
-
-if config.helpers['dns_discovery'].udp_port:
-    print ("Starting UDP DNS Discovery Helper on %s" %
-           config.helpers['dns_discovery'].udp_port)
-    udp_dns_discovery = internet.UDPServer(
-        int(config.helpers['dns_discovery'].udp_port),
-        dns.DNSDatagramProtocol(dns_helpers.DNSResolverDiscovery())
-    )
-    multiService.addService(udp_dns_discovery)
-
-if config.helpers['dns_discovery'].tcp_port:
-    print ("Starting TCP DNS Discovery Helper on %s" %
-           config.helpers['dns_discovery'].tcp_port)
-    tcp_dns_discovery = internet.TCPServer(
-        int(config.helpers['dns_discovery'].tcp_port),
-        dns_helpers.DNSResolverDiscovery()
-    )
-    multiService.addService(tcp_dns_discovery)
-    tcp_dns_discovery.startService()
-
-
-# XXX this needs to be ported
-# Start the OONI daphn3 backend
-if config.helpers['daphn3'].port:
-    print "Starting Daphn3 helper on %s" % config.helpers['daphn3'].port
-    daphn3_helper = internet.TCPServer(int(config.helpers['daphn3'].port),
-                                       tcp_helpers.Daphn3Server())
-    multiService.addService(daphn3_helper)
-    daphn3_helper.startService()
-
-
-if config.helpers['tcp-echo'].port:
-    print "Starting TCP echo helper on %s" % config.helpers['tcp-echo'].port
-    tcp_echo_helper = internet.TCPServer(int(config.helpers['tcp-echo'].port),
-                                         tcp_helpers.TCPEchoHelper())
-    multiService.addService(tcp_echo_helper)
-    tcp_echo_helper.startService()
-
-if config.helpers['http-return-json-headers'].port:
-    print ("Starting HTTP return request helper on %s" %
-           config.helpers['http-return-json-headers'].port)
-    http_return_request_helper = internet.TCPServer(
-        int(config.helpers['http-return-json-headers'].port),
-        http_helpers.HTTPReturnJSONHeadersHelper())
-    multiService.addService(http_return_request_helper)
-    http_return_request_helper.startService()
 
 def getHSEndpoint(endpoint_config):
+    from txtorcon import TCPHiddenServiceEndpoint
     hsdir = endpoint_config['hsdir']
     hsdir = os.path.expanduser(hsdir)
     hsdir = os.path.realpath(hsdir)
-    if LooseVersion(txtorcon_version) >= LooseVersion('0.10.0'):
-        return TCPHiddenServiceEndpoint(reactor,
-                                        get_global_tor(reactor),
-                                        80,
-                                        hidden_service_dir=hsdir)
-    else:
-        return TCPHiddenServiceEndpoint(reactor,
-                                        get_global_tor(reactor),
-                                        80,
-                                        data_dir=hsdir)
+    return TCPHiddenServiceEndpoint(reactor,
+                                    config=get_global_tor(reactor),
+                                    public_port=80,
+                                    hidden_service_dir=hsdir)
 
 def getTCPEndpoint(endpoint_config):
     return endpoints.TCP4ServerEndpoint(
@@ -159,35 +76,146 @@ def createService(endpoint, role, endpoint_config):
         endpoint, factory
     )
     service.setName("-".join([endpoint_config['type'], role]))
-    multiService.addService(service)
-    service.startService()
-
-# this is to ensure same behaviour with an old config file
-if config.main.tor_hidden_service and \
-        config.main.bouncer_endpoints is None and \
-        config.main.collector_endpoints is None:
-    base_dir = '.'
-    if config.main.tor_datadir is not None:
-        base_dir = config.main.tor_datadir
-    bouncer_hsdir   = os.path.join(base_dir, 'bouncer')
-    collector_hsdir = os.path.join(base_dir, 'collector')
-    config.main.bouncer_endpoints   = [ {'type': 'onion', 'hsdir':   bouncer_hsdir} ]
-    config.main.collector_endpoints = [ {'type': 'onion', 'hsdir': collector_hsdir} ]
-
-for endpoint_config in config.main.get('bouncer_endpoints', []):
-    if config.main.bouncer_file:
-        print "Starting bouncer with config %s" % endpoint_config
-        endpoint = getEndpoint(endpoint_config)
-        createService(endpoint, 'bouncer', endpoint_config)
-    else:
-        print "No bouncer configured"
-
-for endpoint_config in config.main.get('collector_endpoints', []):
-    print "Starting collector with config %s" % endpoint_config
-    endpoint = getEndpoint(endpoint_config)
-    createService(endpoint, 'collector', endpoint_config)
-
-for endpoint_config in config.helpers.web_connectivity.get('endpoints', []):
-    print "Starting web_connectivity helper with config %s" % endpoint_config
-    endpoint = getEndpoint(endpoint_config)
-    createService(endpoint, 'web_connectivity', endpoint_config)
+    return service
+
+class StartOONIBackendPlugin:
+    tapname = "oonibackend"
+    def makeService(self, so):
+        ooniBackendService = service.MultiService()
+
+        if config.helpers['ssl'].port:
+            print "Starting SSL helper on %s" % config.helpers['ssl'].port
+            ssl_helper = internet.SSLServer(int(config.helpers['ssl'].port),
+                                            http_helpers.HTTPReturnJSONHeadersHelper(),
+                                            ssl_helpers.SSLContext(config))
+            ooniBackendService.addService(ssl_helper)
+
+        # Start the DNS Server related services
+        if config.helpers['dns'].tcp_port:
+            print "Starting TCP DNS Helper on %s" % config.helpers['dns'].tcp_port
+            tcp_dns_helper = internet.TCPServer(int(config.helpers['dns'].tcp_port),
+                                                dns_helpers.DNSTestHelper())
+            ooniBackendService.addService(tcp_dns_helper)
+
+        if config.helpers['dns'].udp_port:
+            print "Starting UDP DNS Helper on %s" % config.helpers['dns'].udp_port
+            udp_dns_factory = dns.DNSDatagramProtocol(dns_helpers.DNSTestHelper())
+            udp_dns_helper = internet.UDPServer(int(config.helpers['dns'].udp_port),
+                                                udp_dns_factory)
+            ooniBackendService.addService(udp_dns_helper)
+
+        if config.helpers['dns_discovery'].udp_port:
+            print ("Starting UDP DNS Discovery Helper on %s" %
+                   config.helpers['dns_discovery'].udp_port)
+            udp_dns_discovery = internet.UDPServer(
+                int(config.helpers['dns_discovery'].udp_port),
+                dns.DNSDatagramProtocol(dns_helpers.DNSResolverDiscovery())
+            )
+            ooniBackendService.addService(udp_dns_discovery)
+
+        if config.helpers['dns_discovery'].tcp_port:
+            print ("Starting TCP DNS Discovery Helper on %s" %
+                   config.helpers['dns_discovery'].tcp_port)
+            tcp_dns_discovery = internet.TCPServer(
+                int(config.helpers['dns_discovery'].tcp_port),
+                dns_helpers.DNSResolverDiscovery()
+            )
+            ooniBackendService.addService(tcp_dns_discovery)
+
+        # XXX this needs to be ported
+        # Start the OONI daphn3 backend
+        if config.helpers['daphn3'].port:
+            print "Starting Daphn3 helper on %s" % config.helpers['daphn3'].port
+            daphn3_helper = internet.TCPServer(int(config.helpers['daphn3'].port),
+                                               tcp_helpers.Daphn3Server())
+            ooniBackendService.addService(daphn3_helper)
+
+        if config.helpers['tcp-echo'].port:
+            print "Starting TCP echo helper on %s" % config.helpers['tcp-echo'].port
+            tcp_echo_helper = internet.TCPServer(int(config.helpers['tcp-echo'].port),
+                                                 tcp_helpers.TCPEchoHelper())
+            ooniBackendService.addService(tcp_echo_helper)
+
+        if config.helpers['http-return-json-headers'].port:
+            print ("Starting HTTP return request helper on %s" %
+                   config.helpers['http-return-json-headers'].port)
+            http_return_request_helper = internet.TCPServer(
+                int(config.helpers['http-return-json-headers'].port),
+                http_helpers.HTTPReturnJSONHeadersHelper())
+            ooniBackendService.addService(http_return_request_helper)
+
+        # this is to ensure same behaviour with an old config file
+        if config.main.tor_hidden_service and \
+                config.main.bouncer_endpoints is None and \
+                config.main.collector_endpoints is None:
+            bouncer_hsdir   = os.path.join(config.main.tor_datadir, 'bouncer')
+            collector_hsdir = os.path.join(config.main.tor_datadir, 'collector')
+            config.main.bouncer_endpoints   = [ {'type': 'onion', 'hsdir':   bouncer_hsdir} ]
+            config.main.collector_endpoints = [ {'type': 'onion', 'hsdir': collector_hsdir} ]
+
+        for endpoint_config in config.main.get('bouncer_endpoints', []):
+            if config.main.bouncer_file:
+                print "Starting bouncer with config %s" % endpoint_config
+                endpoint = getEndpoint(endpoint_config)
+                bouncer_service = createService(endpoint, 'bouncer',
+                                                endpoint_config)
+                ooniBackendService.addService(bouncer_service)
+            else:
+                print "No bouncer configured"
+
+        for endpoint_config in config.main.get('collector_endpoints', []):
+            print "Starting collector with config %s" % endpoint_config
+            endpoint = getEndpoint(endpoint_config)
+            collector_service = createService(endpoint, 'collector',
+                                              endpoint_config)
+            ooniBackendService.addService(collector_service)
+
+        for endpoint_config in config.helpers.web_connectivity.get('endpoints', []):
+            print "Starting web_connectivity helper with config %s" % endpoint_config
+            endpoint = getEndpoint(endpoint_config)
+            web_connectivity_service = createService(endpoint,
+                                                     'web_connectivity',
+                                                     endpoint_config)
+            ooniBackendService.addService(web_connectivity_service)
+
+
+        return ooniBackendService
+
+class OONIBackendTwistdConfig(twistd.ServerOptions):
+    subCommands = [("StartOONIBackend", None, usage.Options, "node")]
+
+def start():
+    twistd_args = []
+
+    flags = [
+        'nodaemon',
+        'no_save'
+    ]
+    options = [
+        'pidfile',
+        'logfile',
+        'rundir',
+        'euid',
+        'gid',
+        'uid',
+        'umask'
+    ]
+    for option in options:
+        if config.main.get(option, None) is not None:
+            twistd_args.append('--%s' % option)
+            twistd_args.append(config.main.get(option))
+    for flag in flags:
+        if config.main.get(flag, None) is True:
+            twistd_args.append('--%s'% flag)
+
+    twistd_args.append('StartOONIBackend') # Point to our backend plugin
+    twistd_config = OONIBackendTwistdConfig()
+    try:
+        twistd_config.parseOptions(twistd_args)
+    except usage.error, ue:
+        print "Usage error from twistd"
+        sys.exit(7)
+
+    twistd_config.loadedPlugins = {'StartOONIBackend': StartOONIBackendPlugin()}
+    twistd.runApp(twistd_config)
+    return 0
diff --git a/requirements.txt b/requirements.txt
index b8c18a8..91a711a 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -6,7 +6,7 @@ Twisted>=13.2.0
 cyclone>=1.1
 ipaddr>=2.1.10
 pygeoip>=0.2.6
-txtorcon>=0.7
+txtorcon>=0.11.0
 pyOpenSSL>=0.13
 zope.component>=4.0.0
 zope.event>=4.0.0
diff --git a/setup.py b/setup.py
index 2113d21..39cb1f9 100644
--- a/setup.py
+++ b/setup.py
@@ -67,9 +67,9 @@ data_files = [
     (data_dir, ['oonib.conf.example']),
     (os.path.join(data_dir, 'decks'), ['data/decks/README']),
     (os.path.join(data_dir, 'inputs'), ['data/inputs/Makefile']),
-    (os.path.join(spool_dir, 'reports'), ['data/reports/empty.txt']),
-    (os.path.join(spool_dir, 'archive'), ['data/archive/empty.txt']),
-    (os.path.join(var_dir, 'tor'), ['data/tor/empty.txt']),
+    (os.path.join(spool_dir, 'reports'), ['data/reports/.gitignore']),
+    (os.path.join(spool_dir, 'archive'), ['data/archive/.gitignore']),
+    (os.path.join(var_dir, 'tor'), ['data/tor/.gitignore']),
     (var_dir, ['data/bouncer.yaml', 'data/policy.yaml'])
 ]
 





More information about the tor-commits mailing list