summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--setup.py4
-rw-r--r--src/leap/bitmask/core/_web.py59
-rw-r--r--src/leap/bitmask/core/configurable.py1
-rw-r--r--src/leap/bitmask/core/service.py7
4 files changed, 60 insertions, 11 deletions
diff --git a/setup.py b/setup.py
index cf9a600..da61958 100644
--- a/setup.py
+++ b/setup.py
@@ -28,11 +28,13 @@ if platform.system() == "Windows":
mail_deps = ['leap.soledad.client', 'gnupg']
gui_deps = ['vext.pyqt5', 'leap.bitmask_js']
+tor_deps = ['txtorcon']
extras = {
'mail': mail_deps,
'gui': gui_deps,
'backend': mail_deps,
- 'all': mail_deps + gui_deps
+ 'all': mail_deps + gui_deps,
+ 'tor': tor_deps
}
diff --git a/src/leap/bitmask/core/_web.py b/src/leap/bitmask/core/_web.py
index 1798e7f..715356d 100644
--- a/src/leap/bitmask/core/_web.py
+++ b/src/leap/bitmask/core/_web.py
@@ -26,6 +26,7 @@ import pkg_resources
from twisted.internet import reactor
from twisted.application import service
+from twisted.internet import endpoints
from twisted.web.resource import Resource
from twisted.web.server import Site, NOT_DONE_YET
from twisted.web.static import File
@@ -39,6 +40,11 @@ try:
except ImportError:
HAS_WEB_UI = False
+try:
+ import txtorcon
+except Exception:
+ pass
+
log = Logger()
@@ -46,12 +52,16 @@ class HTTPDispatcherService(service.Service):
"""
A Dispatcher for BitmaskCore exposing a REST API.
+ If the leap.bitmask_js package is available in the search path, it will
+ serve the UI under this same service too.
"""
- def __init__(self, core, port=7070, debug=False):
+ def __init__(self, core, port=7070, debug=False, onion=False):
self._core = core
self.port = port
self.debug = debug
+ self.onion = onion
+ self.uri = ''
def startService(self):
if HAS_WEB_UI:
@@ -67,14 +77,49 @@ class HTTPDispatcherService(service.Service):
api = Api(CommandDispatcher(self._core))
root.putChild(u'API', api)
- site = Site(root)
- self.site = site
+ factory = Site(root)
+ self.site = factory
+
+ if self.onion:
+ try:
+ import txtorcon
+ except ImportError:
+ log.error('onion is enabled, but could not find txtorcon')
+ return
+ self._start_onion_service(factory)
- # TODO use endpoints instead
- self.listener = reactor.listenTCP(self.port, site,
- interface='127.0.0.1')
+ else:
+ interface = '127.0.0.1'
+ endpoint = endpoints.TCP4ServerEndpoint(
+ reactor, self.port, interface=interface)
+ self.uri = 'https://%s:%s' % (interface, self.port)
+ endpoint.listen(factory)
+ # TODO this should be set in a callback to the listen call
self.running = True
+ def _start_onion_service(self, factory):
+
+ def progress(percent, tag, message):
+ bar = int(percent / 10)
+ log.debug('[%s%s] %s' % ('#' * bar, '.' * (10 - bar), message))
+
+ def setup_complete(port):
+ port = txtorcon.IHiddenService(port)
+ self.uri = "http://%s" % (port.getHost().onion_uri)
+ log.info('I have set up a hidden service, advertised at: %s'
+ % self.uri)
+ log.info('locally listening on %s' % port.local_address.getHost())
+
+ def setup_failed(args):
+ log.error('onion service setup FAILED: %r' % args)
+
+ endpoint = endpoints.serverFromString(reactor, 'onion:80')
+ txtorcon.IProgressProvider(endpoint).add_progress_listener(progress)
+ d = endpoint.listen(factory)
+ d.addCallback(setup_complete)
+ d.addErrback(setup_failed)
+ return d
+
def stopService(self):
self.site.stopFactory()
self.listener.stopListening()
@@ -82,7 +127,7 @@ class HTTPDispatcherService(service.Service):
def do_status(self):
status = 'running' if self.running else 'disabled'
- return {'web': status}
+ return {'web': status, 'uri': self.uri}
class Api(Resource):
diff --git a/src/leap/bitmask/core/configurable.py b/src/leap/bitmask/core/configurable.py
index 8bd2ecf..f305cc3 100644
--- a/src/leap/bitmask/core/configurable.py
+++ b/src/leap/bitmask/core/configurable.py
@@ -103,5 +103,6 @@ mail = True
eip = True
zmq = True
web = True
+onion = False
websockets = False
"""
diff --git a/src/leap/bitmask/core/service.py b/src/leap/bitmask/core/service.py
index b6447dd..9fde788 100644
--- a/src/leap/bitmask/core/service.py
+++ b/src/leap/bitmask/core/service.py
@@ -74,7 +74,8 @@ class BitmaskBackend(configurable.ConfigurableService):
on_start(self._init_zmq)
if enabled('web'):
- on_start(self._init_web)
+ onion = enabled('onion')
+ on_start(self._init_web, onion=onion)
if enabled('websockets'):
on_start(self._init_websockets)
@@ -151,9 +152,9 @@ class BitmaskBackend(configurable.ConfigurableService):
zs = _zmq.ZMQServerService(self)
zs.setServiceParent(self)
- def _init_web(self):
+ def _init_web(self, onion=False):
service = _web.HTTPDispatcherService
- self._maybe_init_service('web', service, self)
+ self._maybe_init_service('web', service, self, onion=onion)
def _init_websockets(self):
from leap.bitmask.core import websocket