summaryrefslogtreecommitdiff
path: root/src/leap/bitmask/backend
diff options
context:
space:
mode:
authorKali Kaneko <kali@leap.se>2015-08-31 14:54:52 -0400
committerKali Kaneko <kali@leap.se>2015-08-31 14:54:52 -0400
commitf4547479fc050f338845f4f546d8dd7c0e4512eb (patch)
tree0f737c7f102674230f5467ecaf17720e1d28f6eb /src/leap/bitmask/backend
parentdd43dad4b150adb66e571a56a8a5c053dec858d0 (diff)
parentfd27f48a35736d8ba186c423a7de15ffee5143dd (diff)
Merge tag '0.9.0rc2' into debian/experimental
Tag leap.bitmask version 0.9.0rc2
Diffstat (limited to 'src/leap/bitmask/backend')
-rw-r--r--src/leap/bitmask/backend/api.py1
-rw-r--r--src/leap/bitmask/backend/backend.py135
-rw-r--r--src/leap/bitmask/backend/backend_proxy.py242
-rw-r--r--src/leap/bitmask/backend/components.py119
-rw-r--r--src/leap/bitmask/backend/leapbackend.py5
-rw-r--r--src/leap/bitmask/backend/leapsignaler.py1
-rw-r--r--src/leap/bitmask/backend/settings.py31
-rw-r--r--src/leap/bitmask/backend/signaler.py4
-rw-r--r--src/leap/bitmask/backend/signaler_qt.py4
-rw-r--r--src/leap/bitmask/backend/utils.py4
10 files changed, 276 insertions, 270 deletions
diff --git a/src/leap/bitmask/backend/api.py b/src/leap/bitmask/backend/api.py
index 3f6c0ad1..48aa2090 100644
--- a/src/leap/bitmask/backend/api.py
+++ b/src/leap/bitmask/backend/api.py
@@ -146,6 +146,7 @@ SIGNALS = (
"srp_password_change_badpw",
"srp_password_change_error",
"srp_password_change_ok",
+ "srp_registration_disabled",
"srp_registration_failed",
"srp_registration_finished",
"srp_registration_taken",
diff --git a/src/leap/bitmask/backend/backend.py b/src/leap/bitmask/backend/backend.py
index cff731ba..4a98d146 100644
--- a/src/leap/bitmask/backend/backend.py
+++ b/src/leap/bitmask/backend/backend.py
@@ -17,17 +17,15 @@
# FIXME this is missing module documentation. It would be fine to say a couple
# of lines about the whole backend architecture.
-# TODO use txzmq bindings instead.
-
import json
import os
-import threading
import time
import psutil
-from twisted.internet import defer, reactor, threads
+from twisted.internet import defer, reactor, threads, task
+import txzmq
import zmq
try:
from zmq.auth.thread import ThreadAuthenticator
@@ -35,51 +33,50 @@ except ImportError:
pass
from leap.bitmask.backend.api import API, PING_REQUEST
+from leap.bitmask.backend.signaler import Signaler
from leap.bitmask.backend.utils import get_backend_certificates
from leap.bitmask.config import flags
-from leap.bitmask.backend.signaler import Signaler
+from leap.bitmask.logs.utils import get_logger
-import logging
-logger = logging.getLogger(__name__)
+logger = get_logger()
-class Backend(object):
+class TxZmqREPConnection(object):
"""
- Backend server.
- Receives signals from backend_proxy and emit signals if needed.
+ A twisted based zmq rep connection.
"""
- # XXX we might want to make this configurable per-platform,
- # and use the most performant socket type on each one.
- if flags.ZMQ_HAS_CURVE:
- # XXX this should not be hardcoded. Make it configurable.
- PORT = '5556'
- BIND_ADDR = "tcp://127.0.0.1:%s" % PORT
- else:
- SOCKET_FILE = "/tmp/bitmask.socket.0"
- BIND_ADDR = "ipc://%s" % SOCKET_FILE
- PING_INTERVAL = 2 # secs
+ def __init__(self, server_address, process_request):
+ """
+ Initialize the connection.
- def __init__(self, frontend_pid=None):
+ :param server_address: The address of the backend zmq server.
+ :type server: str
+ :param process_request: A callable used to process incoming requests.
+ :type process_request: callable(messageParts)
"""
- Backend constructor, create needed instances.
+ self._server_address = server_address
+ self._process_request = process_request
+ self._zmq_factory = None
+ self._zmq_connection = None
+ self._init_txzmq()
+
+ def _init_txzmq(self):
"""
- self._signaler = Signaler()
+ Configure the txzmq components and connection.
+ """
+ self._zmq_factory = txzmq.ZmqFactory()
+ self._zmq_factory.registerForShutdown()
+ self._zmq_connection = txzmq.ZmqREPConnection(self._zmq_factory)
- self._frontend_pid = frontend_pid
+ context = self._zmq_factory.context
+ socket = self._zmq_connection.socket
- self._do_work = threading.Event() # used to stop the worker thread.
- self._zmq_socket = None
+ def _gotMessage(messageId, messageParts):
+ self._zmq_connection.reply(messageId, "OK")
+ self._process_request(messageParts)
- self._ongoing_defers = []
- self._init_zmq()
-
- def _init_zmq(self):
- """
- Configure the zmq components and connection.
- """
- context = zmq.Context()
- socket = context.socket(zmq.REP)
+ self._zmq_connection.gotMessage = _gotMessage
if flags.ZMQ_HAS_CURVE:
# Start an authenticator for this context.
@@ -95,37 +92,39 @@ class Backend(object):
socket.curve_secretkey = secret
socket.curve_server = True # must come before bind
- socket.bind(self.BIND_ADDR)
- if not flags.ZMQ_HAS_CURVE:
- os.chmod(self.SOCKET_FILE, 0600)
+ proto, addr = self._server_address.split('://') # tcp/ipc, ip/socket
+ socket.bind(self._server_address)
+ if proto == 'ipc':
+ os.chmod(addr, 0600)
- self._zmq_socket = socket
- def _worker(self):
- """
- Receive requests and send it to process.
+class Backend(object):
+ """
+ Backend server.
+ Receives signals from backend_proxy and emit signals if needed.
+ """
+ # XXX we might want to make this configurable per-platform,
+ # and use the most performant socket type on each one.
+ if flags.ZMQ_HAS_CURVE:
+ # XXX this should not be hardcoded. Make it configurable.
+ PORT = '5556'
+ BIND_ADDR = "tcp://127.0.0.1:%s" % PORT
+ else:
+ SOCKET_FILE = "/tmp/bitmask.socket.0"
+ BIND_ADDR = "ipc://%s" % SOCKET_FILE
- Note: we use a simple while since is less resource consuming than a
- Twisted's LoopingCall.
+ PING_INTERVAL = 2 # secs
+
+ def __init__(self, frontend_pid=None):
"""
- pid = self._frontend_pid
- check_wait = 0
- while self._do_work.is_set():
- # Wait for next request from client
- try:
- request = self._zmq_socket.recv(zmq.NOBLOCK)
- self._zmq_socket.send("OK")
- # logger.debug("Received request: '{0}'".format(request))
- self._process_request(request)
- except zmq.ZMQError as e:
- if e.errno != zmq.EAGAIN:
- raise
- time.sleep(0.01)
-
- check_wait += 0.01
- if pid is not None and check_wait > self.PING_INTERVAL:
- check_wait = 0
- self._check_frontend_alive()
+ Backend constructor, create needed instances.
+ """
+ self._signaler = Signaler()
+ self._frontend_pid = frontend_pid
+ self._frontend_checker = None
+ self._ongoing_defers = []
+ self._zmq_connection = TxZmqREPConnection(
+ self.BIND_ADDR, self._process_request)
def _check_frontend_alive(self):
"""
@@ -160,25 +159,27 @@ class Backend(object):
for d in self._ongoing_defers:
d.cancel()
+ logger.debug("Stopping the Twisted reactor...")
reactor.stop()
- logger.debug("Twisted reactor stopped.")
def run(self):
"""
Start the ZMQ server and run the loop to handle requests.
"""
self._signaler.start()
- self._do_work.set()
- threads.deferToThread(self._worker)
+ self._frontend_checker = task.LoopingCall(self._check_frontend_alive)
+ self._frontend_checker.start(self.PING_INTERVAL)
+ logger.debug("Starting Twisted reactor.")
reactor.run()
+ logger.debug("Finished Twisted reactor.")
def stop(self):
"""
Stop the server and the zmq request parse loop.
"""
- logger.debug("STOP received.")
+ logger.debug("Stopping the backend...")
self._signaler.stop()
- self._do_work.clear()
+ self._frontend_checker.stop()
threads.deferToThread(self._stop_reactor)
def _process_request(self, request_json):
diff --git a/src/leap/bitmask/backend/backend_proxy.py b/src/leap/bitmask/backend/backend_proxy.py
index b2f79a70..30b7c5d1 100644
--- a/src/leap/bitmask/backend/backend_proxy.py
+++ b/src/leap/bitmask/backend/backend_proxy.py
@@ -21,48 +21,57 @@ to the backend.
# XXX should document the relationship to the API here.
import functools
-import Queue
import threading
-import time
import zmq
+from zmq.eventloop import ioloop
+from zmq.eventloop import zmqstream
+
+from taskthread import TimerTask
from leap.bitmask.backend.api import API, STOP_REQUEST, PING_REQUEST
+from leap.bitmask.backend.settings import Settings
from leap.bitmask.backend.utils import generate_zmq_certificates_if_needed
from leap.bitmask.backend.utils import get_backend_certificates
from leap.bitmask.config import flags
+from leap.bitmask.logs.utils import get_logger
-import logging
-logger = logging.getLogger(__name__)
+logger = get_logger()
-class BackendProxy(object):
+class ZmqREQConnection(threading.Thread):
"""
- The BackendProxy handles calls from the GUI and forwards (through ZMQ)
- to the backend.
+ A threaded zmq req connection.
"""
- if flags.ZMQ_HAS_CURVE:
- PORT = '5556'
- SERVER = "tcp://localhost:%s" % PORT
- else:
- SERVER = "ipc:///tmp/bitmask.socket.0"
-
- POLL_TIMEOUT = 4000 # ms
- POLL_TRIES = 3
-
- PING_INTERVAL = 2 # secs
-
- def __init__(self):
- generate_zmq_certificates_if_needed()
+ def __init__(self, server_address, on_recv):
+ """
+ Initialize the connection.
- self._socket = None
+ :param server_address: The address of the backend zmq server.
+ :type server: str
+ :param on_recv: The callback to be executed when a message is
+ received.
+ :type on_recv: callable(msg)
+ """
+ threading.Thread.__init__(self)
+ self._server_address = server_address
+ self._on_recv = on_recv
+ self._stream = None
+ self._init_zmq()
- # initialize ZMQ stuff:
+ def _init_zmq(self):
+ """
+ Configure the zmq components and connection.
+ """
+ logger.debug("Setting up ZMQ connection to server...")
context = zmq.Context()
- logger.debug("Connecting to server...")
socket = context.socket(zmq.REQ)
+ # we use zmq's eventloop in order to asynchronously send requests
+ loop = ioloop.ZMQIOLoop.current()
+ self._stream = zmqstream.ZMQStream(socket, loop)
+
if flags.ZMQ_HAS_CURVE:
# public, secret = zmq.curve_keypair()
client_keys = zmq.curve_keypair()
@@ -76,66 +85,128 @@ class BackendProxy(object):
socket.setsockopt(zmq.RCVTIMEO, 1000)
socket.setsockopt(zmq.LINGER, 0) # Terminate early
- socket.connect(self.SERVER)
- self._socket = socket
- self._ping_at = 0
+ self._stream.on_recv(self._on_recv)
+
+ def run(self):
+ """
+ Run the threaded stream connection loop.
+ """
+ self._stream.socket.connect(self._server_address)
+ logger.debug("Starting ZMQ loop.")
+ self._stream.io_loop.start()
+ logger.debug("Finished ZMQ loop.")
+
+ def stop(self):
+ """
+ Stop the threaded connection loop.
+ """
+ self._stream.io_loop.stop()
+
+ def send(self, *args, **kwargs):
+ """
+ Send a message through this connection.
+ """
+ # Important note: calling send on the zmqstream from another
+ # thread doesn’t properly tell the IOLoop thread that there’s an
+ # event to process. This could cuase small delays if the IOLoop is
+ # already processing lots of events, but it can cause the message
+ # to never send if the zmq socket is the only one it’s handling.
+ #
+ # Because of that, we want ZmqREQConnection.send to hand off the
+ # stream.send to the IOLoop’s thread via IOLoop.add_callback:
+ self._stream.io_loop.add_callback(
+ lambda: self._stream.send(*args, **kwargs))
+
+
+class BackendProxy(object):
+ """
+ The BackendProxy handles calls from the GUI and forwards (through ZMQ)
+ to the backend.
+ """
+
+ if flags.ZMQ_HAS_CURVE:
+ PORT = '5556'
+ SERVER = "tcp://localhost:%s" % PORT
+ else:
+ SERVER = "ipc:///tmp/bitmask.socket.0"
+
+ PING_INTERVAL = 2 # secs
+
+ def __init__(self):
+ """
+ Initialize the backend proxy.
+ """
+ generate_zmq_certificates_if_needed()
+ self._do_work = threading.Event()
+ self._work_lock = threading.Lock()
+ self._connection = ZmqREQConnection(self.SERVER, self._set_online)
+ self._heartbeat = TimerTask(self._ping, delay=self.PING_INTERVAL)
+ self._ping_event = threading.Event()
self.online = False
+ self.settings = Settings()
- self._call_queue = Queue.Queue()
- self._worker_caller = threading.Thread(target=self._worker)
+ def _set_online(self, _):
+ """
+ Mark the backend as being online.
- def start(self):
- self._worker_caller.start()
+ This is used as the zmq connection's on_recv callback, and so it is
+ passed the received message as a parameter. Because we currently don't
+ use that message, we just ignore it for now.
+ """
+ self.online = True
+ # the following event is used when checking whether the backend is
+ # online
+ self._ping_event.set()
+
+ def _set_offline(self):
+ """
+ Mark the backend as being offline.
+ """
+ self.online = False
def check_online(self):
"""
Return whether the backend is accessible or not.
You don't need to do `run` in order to use this.
-
:rtype: bool
"""
- # we use a small timeout in order to response quickly if the backend is
- # offline
- self._send_request(PING_REQUEST, retry=False, timeout=500)
- self._socket.close()
+ logger.debug("Checking whether backend is online...")
+ self._send_request(PING_REQUEST)
+ # self._ping_event will eventually be set by the zmq connection's
+ # on_recv callback, so we use a small timeout in order to response
+ # quickly if the backend is offline
+ if not self._ping_event.wait(0.5):
+ logger.warning("Backend is offline!")
+ self._set_offline()
return self.online
- def _worker(self):
+ def start(self):
"""
- Worker loop that processes the Queue of pending requests to do.
+ Start the backend proxy.
"""
- while True:
- try:
- request = self._call_queue.get(block=False)
- # break the loop after sending the 'stop' action to the
- # backend.
- if request == STOP_REQUEST:
- break
-
- self._send_request(request)
- except Queue.Empty:
- pass
- time.sleep(0.01)
- self._ping()
+ logger.debug("Starting backend proxy...")
+ self._do_work.set()
+ self._connection.start()
+ self.check_online()
+ self._heartbeat.start()
- logger.debug("BackendProxy worker stopped.")
-
- def _reset_ping(self):
+ def _stop(self):
"""
- Reset the ping timeout counter.
- This is called for every ping and request.
+ Stop the backend proxy.
"""
- self._ping_at = time.time() + self.PING_INTERVAL
+ with self._work_lock: # avoid sending after connection was closed
+ self._do_work.clear()
+ self._heartbeat.stop()
+ self._connection.stop()
+ logger.debug("BackendProxy worker stopped.")
def _ping(self):
"""
Heartbeat helper.
Sends a PING request just to know that the server is alive.
"""
- if time.time() > self._ping_at:
- self._send_request(PING_REQUEST)
- self._reset_ping()
+ self._send_request(PING_REQUEST)
def _api_call(self, *args, **kwargs):
"""
@@ -159,6 +230,8 @@ class BackendProxy(object):
'arguments': kwargs,
}
+ request_json = None
+
try:
request_json = zmq.utils.jsonapi.dumps(request)
except Exception as e:
@@ -169,12 +242,12 @@ class BackendProxy(object):
raise
# queue the call in order to handle the request in a thread safe way.
- self._call_queue.put(request_json)
+ self._send_request(request_json)
if api_method == STOP_REQUEST:
- self._call_queue.put(STOP_REQUEST)
+ self._stop()
- def _send_request(self, request, retry=True, timeout=None):
+ def _send_request(self, request):
"""
Send the given request to the server.
This is used from a thread safe loop in order to avoid sending a
@@ -182,49 +255,10 @@ class BackendProxy(object):
:param request: the request to send.
:type request: str
- :param retry: whether we should retry or not in case of timeout.
- :type retry: bool
- :param timeout: a custom timeout (milliseconds) to wait for a response.
- :type timeout: int
"""
- # logger.debug("Sending request to backend: {0}".format(request))
- self._socket.send(request)
-
- poll = zmq.Poller()
- poll.register(self._socket, zmq.POLLIN)
-
- reply = None
-
- tries = 0
- if not retry:
- tries = self.POLL_TRIES + 1 # this means: no retries left
-
- if timeout is None:
- timeout = self.POLL_TIMEOUT
-
- while True:
- socks = dict(poll.poll(timeout))
- if socks.get(self._socket) == zmq.POLLIN:
- reply = self._socket.recv()
- break
-
- tries += 1
- if tries < self.POLL_TRIES:
- logger.warning('Retrying receive... {0}/{1}'.format(
- tries, self.POLL_TRIES))
- else:
- break
-
- if reply is None:
- msg = "Timeout error contacting backend."
- logger.critical(msg)
- self.online = False
- else:
- # msg = "Received reply for '{0}' -> '{1}'".format(request, reply)
- # logger.debug(msg)
- self.online = True
- # request received, no ping needed for other interval.
- self._reset_ping()
+ with self._work_lock: # avoid sending after connection was closed
+ if self._do_work.is_set():
+ self._connection.send(request)
def __getattribute__(self, name):
"""
diff --git a/src/leap/bitmask/backend/components.py b/src/leap/bitmask/backend/components.py
index 4b63af84..5f34d290 100644
--- a/src/leap/bitmask/backend/components.py
+++ b/src/leap/bitmask/backend/components.py
@@ -17,13 +17,14 @@
"""
Backend components
"""
-import logging
+# TODO [ ] Get rid of all this deferToThread mess, or at least contain
+# all of it into its own threadpool.
+
import os
import socket
import time
from functools import partial
-from threading import Condition
from twisted.internet import threads, defer
from twisted.python import log
@@ -35,9 +36,10 @@ from leap.bitmask.backend.settings import Settings, GATEWAY_AUTOMATIC
from leap.bitmask.config.providerconfig import ProviderConfig
from leap.bitmask.crypto.srpauth import SRPAuth
from leap.bitmask.crypto.srpregister import SRPRegister
+from leap.bitmask.logs.utils import get_logger
from leap.bitmask.platform_init import IS_LINUX
-from leap.bitmask.provider.providerbootstrapper import ProviderBootstrapper
from leap.bitmask.provider.pinned import PinnedProviders
+from leap.bitmask.provider.providerbootstrapper import ProviderBootstrapper
from leap.bitmask.services import get_supported
from leap.bitmask.services.eip import eipconfig
from leap.bitmask.services.eip import get_openvpn_management
@@ -59,11 +61,11 @@ from leap.bitmask.util.privilege_policies import LinuxPolicyChecker
from leap.common import certs as leap_certs
from leap.keymanager import openpgp
-from leap.keymanager.errors import KeyAddressMismatch, KeyFingerprintMismatch
-from leap.soledad.client import NoStorageSecret, PassphraseTooShort
+from leap.soledad.client.secrets import PassphraseTooShort
+from leap.soledad.client.secrets import NoStorageSecret
-logger = logging.getLogger(__name__)
+logger = get_logger()
class ILEAPComponent(zope.interface.Interface):
@@ -626,7 +628,9 @@ class EIP(object):
# this only works for selecting the first gateway, as we're
# currently doing.
ccodes = gateway_selector.get_gateways_country_code()
- gateway_ccode = ccodes[gateways[0]]
+ gateway_ccode = '' # '' instead of None due to needed signal argument
+ if ccodes is not None:
+ gateway_ccode = ccodes[gateways[0]]
self._signaler.signal(self._signaler.eip_get_gateway_country_code,
gateway_ccode)
@@ -777,8 +781,8 @@ class Soledad(object):
"""
provider_config = ProviderConfig.get_provider_config(domain)
if provider_config is not None:
- self._soledad_defer = threads.deferToThread(
- self._soledad_bootstrapper.run_soledad_setup_checks,
+ sb = self._soledad_bootstrapper
+ self._soledad_defer = sb.run_soledad_setup_checks(
provider_config, username, password,
download_if_needed=True)
self._soledad_defer.addCallback(self._set_proxies_cb)
@@ -814,8 +818,9 @@ class Soledad(object):
Signaler.soledad_offline_finished
Signaler.soledad_offline_failed
"""
- self._soledad_bootstrapper.load_offline_soledad(
+ d = self._soledad_bootstrapper.load_offline_soledad(
username, password, uuid)
+ d.addCallback(self._set_proxies_cb)
def cancel_bootstrap(self):
"""
@@ -825,7 +830,6 @@ class Soledad(object):
logger.debug("Cancelling soledad defer.")
self._soledad_defer.cancel()
self._soledad_defer = None
- zope.proxy.setProxiedObject(self._soledad_proxy, None)
def close(self):
"""
@@ -906,52 +910,6 @@ class Keymanager(object):
# NOTE: This feature is disabled right now since is dangerous
return
- new_key = ''
- signal = None
- try:
- with open(filename, 'r') as keys_file:
- new_key = keys_file.read()
- except IOError as e:
- logger.error("IOError importing key. {0!r}".format(e))
- signal = self._signaler.keymanager_import_ioerror
- self._signaler.signal(signal)
- return
-
- keymanager = self._keymanager_proxy
- try:
- # NOTE: parse_openpgp_ascii_key is not in keymanager anymore
- # the API for that will need some thinking
- public_key, private_key = keymanager.parse_openpgp_ascii_key(
- new_key)
- except (KeyAddressMismatch, KeyFingerprintMismatch) as e:
- logger.error(repr(e))
- signal = self._signaler.keymanager_import_datamismatch
- self._signaler.signal(signal)
- return
-
- if public_key is None or private_key is None:
- signal = self._signaler.keymanager_import_missingkey
- self._signaler.signal(signal)
- return
-
- current_public_key = keymanager.get_key(username, openpgp.OpenPGPKey)
- if public_key.address != current_public_key.address:
- logger.error("The key does not match the ID")
- signal = self._signaler.keymanager_import_addressmismatch
- self._signaler.signal(signal)
- return
-
- keymanager.delete_key(self._key)
- keymanager.delete_key(self._key_priv)
- keymanager.put_key(public_key)
- keymanager.put_key(private_key)
- keymanager.send_key(openpgp.OpenPGPKey)
-
- logger.debug('Import ok')
- signal = self._signaler.keymanager_import_ok
-
- self._signaler.signal(signal)
-
def export_keys(self, username, filename):
"""
Export the given username's keys to a file.
@@ -963,35 +921,50 @@ class Keymanager(object):
"""
keymanager = self._keymanager_proxy
- public_key = keymanager.get_key(username, openpgp.OpenPGPKey)
- private_key = keymanager.get_key(username, openpgp.OpenPGPKey,
- private=True)
- try:
+ def export(keys):
+ public_key, private_key = keys
+ # XXX: This is blocking. We could use writeToFD, but is POSIX only
+ # https://twistedmatrix.com/documents/current/api/twisted.internet.fdesc.html#writeToFD
with open(filename, 'w') as keys_file:
keys_file.write(public_key.key_data)
keys_file.write(private_key.key_data)
logger.debug('Export ok')
self._signaler.signal(self._signaler.keymanager_export_ok)
- except IOError as e:
- logger.error("IOError exporting key. {0!r}".format(e))
+
+ def log_error(failure):
+ logger.error(
+ "Error exporting key. {0!r}".format(failure.value))
self._signaler.signal(self._signaler.keymanager_export_error)
+ dpub = keymanager.get_key(username, openpgp.OpenPGPKey)
+ dpriv = keymanager.get_key(username, openpgp.OpenPGPKey,
+ private=True)
+ d = defer.gatherResults([dpub, dpriv])
+ d.addCallback(export)
+ d.addErrback(log_error)
+
def list_keys(self):
"""
List all the keys stored in the local DB.
"""
- keys = self._keymanager_proxy.get_all_keys()
- self._signaler.signal(self._signaler.keymanager_keys_list, keys)
+ d = self._keymanager_proxy.get_all_keys()
+ d.addCallback(
+ lambda keys:
+ self._signaler.signal(self._signaler.keymanager_keys_list, keys))
def get_key_details(self, username):
"""
List all the keys stored in the local DB.
"""
- public_key = self._keymanager_proxy.get_key(username,
- openpgp.OpenPGPKey)
- details = (public_key.key_id, public_key.fingerprint)
- self._signaler.signal(self._signaler.keymanager_key_details, details)
+ def signal_details(public_key):
+ details = (public_key.key_id, public_key.fingerprint)
+ self._signaler.signal(self._signaler.keymanager_key_details,
+ details)
+
+ d = self._keymanager_proxy.get_key(username,
+ openpgp.OpenPGPKey)
+ d.addCallback(signal_details)
class Mail(object):
@@ -1070,12 +1043,10 @@ class Mail(object):
"""
Stop imap and wait until the service is stopped to signal that is done.
"""
- cv = Condition()
- cv.acquire()
- threads.deferToThread(self._imap_controller.stop_imap_service, cv)
+ # FIXME just get a fucking deferred and signal as a callback, with
+ # timeout and cancellability
+ threads.deferToThread(self._imap_controller.stop_imap_service)
logger.debug('Waiting for imap service to stop.')
- cv.wait(self.SERVICE_STOP_TIMEOUT)
- logger.debug('IMAP stopped')
self._signaler.signal(self._signaler.imap_stopped)
def stop_imap_service(self):
diff --git a/src/leap/bitmask/backend/leapbackend.py b/src/leap/bitmask/backend/leapbackend.py
index 3b023563..cf45c4f8 100644
--- a/src/leap/bitmask/backend/leapbackend.py
+++ b/src/leap/bitmask/backend/leapbackend.py
@@ -17,16 +17,15 @@
"""
Backend for everything
"""
-import logging
-
import zope.interface
import zope.proxy
from leap.bitmask.backend import components
from leap.bitmask.backend.backend import Backend
from leap.bitmask.backend.settings import Settings
+from leap.bitmask.logs.utils import get_logger
-logger = logging.getLogger(__name__)
+logger = get_logger()
ERROR_KEY = "error"
PASSED_KEY = "passed"
diff --git a/src/leap/bitmask/backend/leapsignaler.py b/src/leap/bitmask/backend/leapsignaler.py
index c0fdffdc..1ac51f5e 100644
--- a/src/leap/bitmask/backend/leapsignaler.py
+++ b/src/leap/bitmask/backend/leapsignaler.py
@@ -109,6 +109,7 @@ class LeapSignaler(SignalerQt):
srp_password_change_badpw = QtCore.Signal()
srp_password_change_error = QtCore.Signal()
srp_password_change_ok = QtCore.Signal()
+ srp_registration_disabled = QtCore.Signal()
srp_registration_failed = QtCore.Signal()
srp_registration_finished = QtCore.Signal()
srp_registration_taken = QtCore.Signal()
diff --git a/src/leap/bitmask/backend/settings.py b/src/leap/bitmask/backend/settings.py
index 5cb4c616..dedfc13d 100644
--- a/src/leap/bitmask/backend/settings.py
+++ b/src/leap/bitmask/backend/settings.py
@@ -18,13 +18,13 @@
Backend settings
"""
import ConfigParser
-import logging
import os
+from leap.bitmask.logs.utils import get_logger
from leap.bitmask.util import get_path_prefix
from leap.common.check import leap_assert, leap_assert_type
-logger = logging.getLogger(__name__)
+logger = get_logger()
# We need this one available for the default decorator
GATEWAY_AUTOMATIC = "Automatic"
@@ -122,37 +122,36 @@ class Settings(object):
self._settings.set(provider, self.GATEWAY_KEY, gateway)
self._save()
- def get_uuid(self, username):
+ def get_uuid(self, full_user_id):
"""
Gets the uuid for a given username.
- :param username: the full user identifier in the form user@provider
- :type username: basestring
+ :param full_user_id: the full user identifier in the form user@provider
+ :type full_user_id: basestring
"""
- leap_assert("@" in username,
+ leap_assert("@" in full_user_id,
"Expected username in the form user@provider")
- user, provider = username.split('@')
+ username, provider = full_user_id.split('@')
+ return self._get_value(provider, full_user_id, "")
- return self._get_value(provider, username, "")
-
- def set_uuid(self, username, value):
+ def set_uuid(self, full_user_id, value):
"""
Sets the uuid for a given username.
- :param username: the full user identifier in the form user@provider
- :type username: str or unicode
+ :param full_user_id: the full user identifier in the form user@provider
+ :type full_user_id: str or unicode
:param value: the uuid to save or None to remove it
:type value: str or unicode or None
"""
- leap_assert("@" in username,
+ leap_assert("@" in full_user_id,
"Expected username in the form user@provider")
- user, provider = username.split('@')
+ user, provider = full_user_id.split('@')
if value is None:
- self._settings.remove_option(provider, username)
+ self._settings.remove_option(provider, full_user_id)
else:
leap_assert(len(value) > 0, "We cannot save an empty uuid")
self._add_section(provider)
- self._settings.set(provider, username, value)
+ self._settings.set(provider, full_user_id, value)
self._save()
diff --git a/src/leap/bitmask/backend/signaler.py b/src/leap/bitmask/backend/signaler.py
index aec2f606..c5335eb8 100644
--- a/src/leap/bitmask/backend/signaler.py
+++ b/src/leap/bitmask/backend/signaler.py
@@ -27,9 +27,9 @@ import zmq
from leap.bitmask.backend.api import SIGNALS
from leap.bitmask.backend.utils import get_frontend_certificates
from leap.bitmask.config import flags
+from leap.bitmask.logs.utils import get_logger
-import logging
-logger = logging.getLogger(__name__)
+logger = get_logger()
class Signaler(object):
diff --git a/src/leap/bitmask/backend/signaler_qt.py b/src/leap/bitmask/backend/signaler_qt.py
index b7f48d21..e3244934 100644
--- a/src/leap/bitmask/backend/signaler_qt.py
+++ b/src/leap/bitmask/backend/signaler_qt.py
@@ -33,9 +33,9 @@ except ImportError:
from leap.bitmask.backend.api import SIGNALS
from leap.bitmask.backend.utils import get_frontend_certificates
from leap.bitmask.config import flags
+from leap.bitmask.logs.utils import get_logger
-import logging
-logger = logging.getLogger(__name__)
+logger = get_logger()
class SignalerQt(QtCore.QObject):
diff --git a/src/leap/bitmask/backend/utils.py b/src/leap/bitmask/backend/utils.py
index b2674330..3b5effc5 100644
--- a/src/leap/bitmask/backend/utils.py
+++ b/src/leap/bitmask/backend/utils.py
@@ -17,7 +17,6 @@
"""
Backend utilities to handle ZMQ certificates.
"""
-import logging
import os
import shutil
import stat
@@ -30,11 +29,12 @@ except ImportError:
pass
from leap.bitmask.config import flags
+from leap.bitmask.logs.utils import get_logger
from leap.bitmask.util import get_path_prefix
from leap.common.files import mkdir_p
from leap.common.check import leap_assert
-logger = logging.getLogger(__name__)
+logger = get_logger()
KEYS_DIR = os.path.join(get_path_prefix(), 'leap', 'zmq_certificates')