summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomás Touceda <chiiph@leap.se>2013-03-07 19:05:11 -0300
committerTomás Touceda <chiiph@leap.se>2013-03-07 19:05:11 -0300
commit751638b4eb8208e1eaa1beaaed284da6b412bca7 (patch)
tree58a517d1f22a45a581fcca3ff2766663974de3fa
parent6d6600a495ef48e0f04cb78bedca8fb913bada2a (diff)
Change asserts for a custom leap_assert method
Also: - Make SRPAuth and the Bootstrappers be a QObject instead of a QThread so we can use them inside another more generic thread - Add a generic CheckerThread that runs checks or whatever operation as long as it returns a boolean value - Closes the whole application if the wizard is rejected at the first run - Do not fail when the config directory doesn't exist - Set the wizard pixmap logo as LEAP's logo - Improve wizard checks - Make SRPRegister play nice with the CheckerThread
-rw-r--r--src/leap/config/baseconfig.py3
-rw-r--r--src/leap/config/pluggableconfig.py4
-rw-r--r--src/leap/config/prefixers.py6
-rw-r--r--src/leap/config/providerconfig.py5
-rw-r--r--src/leap/crypto/srpauth.py108
-rw-r--r--src/leap/crypto/srpregister.py17
-rw-r--r--src/leap/gui/mainwindow.py91
-rw-r--r--src/leap/gui/ui/wizard.ui5
-rw-r--r--src/leap/gui/wizard.py91
-rw-r--r--src/leap/services/eip/eipbootstrapper.py101
-rw-r--r--src/leap/services/eip/eipconfig.py13
-rw-r--r--src/leap/services/eip/providerbootstrapper.py137
-rw-r--r--src/leap/services/eip/vpn.py15
-rw-r--r--src/leap/services/eip/vpnlaunchers.py24
-rw-r--r--src/leap/util/check.py61
-rw-r--r--src/leap/util/checkerthread.py110
16 files changed, 465 insertions, 326 deletions
diff --git a/src/leap/config/baseconfig.py b/src/leap/config/baseconfig.py
index d553255e..b80fd419 100644
--- a/src/leap/config/baseconfig.py
+++ b/src/leap/config/baseconfig.py
@@ -29,6 +29,7 @@ from abc import ABCMeta, abstractmethod
from leap.config.prefixers import get_platform_prefixer
from leap.config.pluggableconfig import PluggableConfig
+from leap.util.check import leap_assert
logger = logging.getLogger(__name__)
@@ -58,7 +59,7 @@ class BaseConfig:
@rtype: depends on the config structure, dict, str, array, int
@return: returns the value for the specified key in the config
"""
- assert self._config_checker, "Load the config first"
+ leap_assert(self._config_checker, "Load the config first")
return self._config_checker.config[key]
def get_path_prefix(self, standalone=False):
diff --git a/src/leap/config/pluggableconfig.py b/src/leap/config/pluggableconfig.py
index 64aa05cc..5ed83b3f 100644
--- a/src/leap/config/pluggableconfig.py
+++ b/src/leap/config/pluggableconfig.py
@@ -28,6 +28,8 @@ import urlparse
import jsonschema
#from leap.base.util.translations import LEAPTranslatable
+from leap.util.check import leap_assert
+
logger = logging.getLogger(__name__)
@@ -378,7 +380,7 @@ class PluggableConfig(object):
# XXX cleanup this!
if fromfile:
- assert os.path.exists(fromfile)
+ leap_assert(os.path.exists(fromfile))
if not format:
format = self.filename2format(fromfile)
diff --git a/src/leap/config/prefixers.py b/src/leap/config/prefixers.py
index a33e68aa..20d59b2d 100644
--- a/src/leap/config/prefixers.py
+++ b/src/leap/config/prefixers.py
@@ -24,6 +24,8 @@ import platform
from abc import ABCMeta, abstractmethod
from xdg import BaseDirectory
+from leap.util.check import leap_assert
+
class Prefixer:
"""
@@ -47,8 +49,8 @@ class Prefixer:
def get_platform_prefixer():
prefixer = globals()[platform.system() + "Prefixer"]
- assert prefixer, "Unimplemented platform prefixer: %s" % \
- (platform.system(),)
+ leap_assert(prefixer, "Unimplemented platform prefixer: %s" %
+ (platform.system(),))
return prefixer()
diff --git a/src/leap/config/providerconfig.py b/src/leap/config/providerconfig.py
index c3c2c298..55b33b98 100644
--- a/src/leap/config/providerconfig.py
+++ b/src/leap/config/providerconfig.py
@@ -23,6 +23,7 @@ import os
from leap.config.baseconfig import BaseConfig, LocalizedKey
from leap.config.provider_spec import leap_provider_spec
+from leap.util.check import leap_assert
logger = logging.getLogger(__name__)
@@ -95,8 +96,8 @@ class ProviderConfig(BaseConfig):
"cacert.pem")
if not about_to_download:
- assert os.path.exists(cert_path), \
- "You need to download the certificate first"
+ leap_assert(os.path.exists(cert_path),
+ "You need to download the certificate first")
logger.debug("Going to verify SSL against %s" % (cert_path,))
return cert_path
diff --git a/src/leap/crypto/srpauth.py b/src/leap/crypto/srpauth.py
index dbcc95cb..28e4f037 100644
--- a/src/leap/crypto/srpauth.py
+++ b/src/leap/crypto/srpauth.py
@@ -20,9 +20,11 @@ import srp
import binascii
import logging
-from PySide import QtCore
+from PySide import QtCore, QtGui
from leap.config.providerconfig import ProviderConfig
+from leap.util.check import leap_assert
+from leap.util.checkerthread import CheckerThread
logger = logging.getLogger(__name__)
@@ -34,7 +36,7 @@ class SRPAuthenticationError(Exception):
pass
-class SRPAuth(QtCore.QThread):
+class SRPAuth(QtCore.QObject):
"""
SRPAuth singleton
"""
@@ -55,7 +57,8 @@ class SRPAuth(QtCore.QThread):
@param server: Server to which we will authenticate
@type server: str
"""
- assert provider_config, "We need a provider config to authenticate"
+ leap_assert(provider_config,
+ "We need a provider config to authenticate")
self._provider_config = provider_config
@@ -277,15 +280,15 @@ class SRPAuth(QtCore.QThread):
@param password: password for this user
@type password: str
"""
- assert self.get_session_id() is None, "Already logged in"
+ leap_assert(self.get_session_id() is None, "Already logged in")
self._authentication_preprocessing(username, password)
salt, B = self._start_authentication(username, password)
M2 = self._process_challenge(salt, B, username)
self._verify_session(M2)
- assert self.get_session_id(), "Something went wrong because" + \
- " we don't have the auth cookie afterwards"
+ leap_assert(self.get_session_id(), "Something went wrong because"
+ " we don't have the auth cookie afterwards")
def logout(self):
"""
@@ -294,7 +297,8 @@ class SRPAuth(QtCore.QThread):
"""
logger.debug("Starting logout...")
- assert self.get_session_id(), "Cannot logout an unexisting session"
+ leap_assert(self.get_session_id(),
+ "Cannot logout an unexisting session")
logout_url = "%s/%s/%s/" % (self._provider_config.get_api_uri(),
self._provider_config.
@@ -344,7 +348,7 @@ class SRPAuth(QtCore.QThread):
"""
Creates a singleton instance if needed
"""
- QtCore.QThread.__init__(self)
+ QtCore.QObject.__init__(self)
# Check whether we already have an instance
if SRPAuth.__instance is None:
@@ -371,47 +375,47 @@ class SRPAuth(QtCore.QThread):
@type password: str
"""
- with QtCore.QMutexLocker(self._should_login_lock):
- self._should_login = self.DO_LOGIN
- self._username = username
- self._password = password
- # Detach the start call to Qt's event loop
- QtCore.QTimer.singleShot(0, self.start)
-
- def logout(self):
- """
- Logs out the current session.
- Expects a session_id to exists, might raise AssertionError
- """
- QtCore.QMutexLocker(self._should_login_lock)
- self._should_login = self.DO_LOGOUT
- # Detach the start call to Qt's event loop
- QtCore.QTimer.singleShot(0, self.start)
-
- def _runLogin(self, username, password):
try:
self.__instance.authenticate(username, password)
+
+ logger.debug("Successful login!")
self.authentication_finished.emit(True, "Succeeded")
+ return True
except Exception as e:
+ logger.error("Error logging in %s" % (e,))
self.authentication_finished.emit(False, "%s" % (e,))
+ return False
- def _runLogout(self):
+ def logout(self):
+ """
+ Logs out the current session.
+ Expects a session_id to exists, might raise AssertionError
+ """
try:
self.__instance.logout()
self.logout_finished.emit(True, "Succeeded")
+ return True
except Exception as e:
self.logout_finished.emit(False, "%s" % (e,))
-
- def run(self):
- QtCore.QMutexLocker(self._should_login_lock)
- if self._should_login == self.DO_LOGIN:
- self._runLogin(self._username, self._password)
- elif self._should_login == self.DO_LOGOUT:
- self._runLogout()
- self._should_login = self.DO_NOTHING
+ return False
if __name__ == "__main__":
+ import sys
+ from functools import partial
+ app = QtGui.QApplication(sys.argv)
+
+ import signal
+
+ def sigint_handler(*args, **kwargs):
+ logger.debug('SIGINT catched. shutting down...')
+ checker = args[0]
+ checker.set_should_quit()
+ QtGui.QApplication.quit()
+
+ def signal_tester(d):
+ print d
+
logger = logging.getLogger(name='leap')
logger.setLevel(logging.DEBUG)
console = logging.StreamHandler()
@@ -422,8 +426,23 @@ if __name__ == "__main__":
console.setFormatter(formatter)
logger.addHandler(console)
- provider = ProviderConfig()
+ checker = CheckerThread()
+
+ sigint = partial(sigint_handler, checker)
+ signal.signal(signal.SIGINT, sigint)
+ timer = QtCore.QTimer()
+ timer.start(500)
+ timer.timeout.connect(lambda: None)
+ app.connect(app, QtCore.SIGNAL("aboutToQuit()"),
+ checker.set_should_quit)
+ w = QtGui.QWidget()
+ w.resize(100, 100)
+ w.show()
+
+ checker.start()
+
+ provider = ProviderConfig()
if provider.load("leap/providers/bitmask.net/provider.json"):
# url = "%s/tickets" % (provider.get_api_uri(),)
# print url
@@ -431,9 +450,14 @@ if __name__ == "__main__":
# print res.content
# res.raise_for_status()
auth = SRPAuth(provider)
- auth.start()
- auth.authenticate("test2", "sarasaaaa")
- res = requests.session().get("%s/cert" % (provider.get_api_uri(),),
- verify=provider.get_ca_cert_path())
- print res.content
- auth.logout()
+ auth_instantiated = partial(auth.authenticate, "test2", "sarasaaaa")
+
+ checker.add_checks([auth_instantiated, auth.logout])
+
+ #auth.authenticate("test2", "sarasaaaa")
+ #res = requests.session().get("%s/cert" % (provider.get_api_uri(),),
+ #verify=provider.get_ca_cert_path())
+ #print res.content
+ #auth.logout()
+
+ sys.exit(app.exec_())
diff --git a/src/leap/crypto/srpregister.py b/src/leap/crypto/srpregister.py
index d9b2b22b..cf673e35 100644
--- a/src/leap/crypto/srpregister.py
+++ b/src/leap/crypto/srpregister.py
@@ -20,15 +20,17 @@ import binascii
import srp
import logging
+from PySide import QtCore
from urlparse import urlparse
from leap.config.providerconfig import ProviderConfig
from leap.crypto.constants import SIGNUP_TIMEOUT
+from leap.util.check import leap_assert, leap_assert_type
logger = logging.getLogger(__name__)
-class SRPRegister(object):
+class SRPRegister(QtCore.QObject):
"""
Registers a user to a specific provider using SRP
"""
@@ -37,6 +39,8 @@ class SRPRegister(object):
USER_VERIFIER_KEY = 'user[password_verifier]'
USER_SALT_KEY = 'user[password_salt]'
+ registration_finished = QtCore.Signal(bool, object)
+
def __init__(self,
provider_config=None,
register_path="users"):
@@ -49,10 +53,9 @@ class SRPRegister(object):
@param register_path: webapp path for registering users
@type register_path; str
"""
-
- assert provider_config, "Please provider a provider"
- assert isinstance(provider_config, ProviderConfig), \
- "We need a ProviderConfig instead of %r" % (provider_config,)
+ QtCore.QObject.__init__(self)
+ leap_assert(provider_config, "Please provider a provider")
+ leap_assert_type(provider_config, ProviderConfig)
self._provider_config = provider_config
@@ -131,7 +134,9 @@ class SRPRegister(object):
verify=self._provider_config.
get_ca_cert_path())
- return (req.ok, req)
+ self.registration_finished.emit(req.ok, req)
+
+ return req.ok
if __name__ == "__main__":
diff --git a/src/leap/gui/mainwindow.py b/src/leap/gui/mainwindow.py
index 1821e4a6..50a03fb9 100644
--- a/src/leap/gui/mainwindow.py
+++ b/src/leap/gui/mainwindow.py
@@ -31,6 +31,8 @@ from leap.services.eip.providerbootstrapper import ProviderBootstrapper
from leap.services.eip.eipbootstrapper import EIPBootstrapper
from leap.services.eip.eipconfig import EIPConfig
from leap.gui.wizard import Wizard
+from leap.util.check import leap_assert
+from leap.util.checkerthread import CheckerThread
logger = logging.getLogger(__name__)
@@ -44,6 +46,9 @@ class MainWindow(QtGui.QMainWindow):
LOGIN_INDEX = 0
EIP_STATUS_INDEX = 1
+ GEOMETRY_KEY = "Geometry"
+ WINDOWSTATE_KEY = "WindowState"
+
def __init__(self):
QtGui.QMainWindow.__init__(self)
@@ -69,6 +74,9 @@ class MainWindow(QtGui.QMainWindow):
# This is created once we have a valid provider config
self._srp_auth = None
+ self._checker_thread = CheckerThread()
+ self._checker_thread.start()
+
# This thread is always running, although it's quite
# lightweight when it's done setting up provider
# configuration and certificate.
@@ -110,11 +118,7 @@ class MainWindow(QtGui.QMainWindow):
QtCore.QCoreApplication.instance().connect(
QtCore.QCoreApplication.instance(),
QtCore.SIGNAL("aboutToQuit()"),
- self._provider_bootstrapper.set_should_quit)
- QtCore.QCoreApplication.instance().connect(
- QtCore.QCoreApplication.instance(),
- QtCore.SIGNAL("aboutToQuit()"),
- self._eip_bootstrapper.set_should_quit)
+ self._checker_thread.set_should_quit)
self.ui.action_sign_out.setEnabled(False)
self.ui.action_sign_out.triggered.connect(self._logout)
@@ -131,17 +135,26 @@ class MainWindow(QtGui.QMainWindow):
self._center_window()
self._wizard = None
+ self._wizard_firstrun = False
if self._first_run():
- self._wizard = Wizard()
+ self._wizard_firstrun = True
+ self._wizard = Wizard(self._checker_thread)
# Give this window time to finish init and then show the wizard
QtCore.QTimer.singleShot(1, self._launch_wizard)
- self._wizard.finished.connect(self._finish_init)
+ self._wizard.accepted.connect(self._finish_init)
+ self._wizard.rejected.connect(self._rejected_wizard)
+ else:
+ self._finish_init()
+
+ def _rejected_wizard(self):
+ if self._wizard_firstrun:
+ self.quit()
else:
self._finish_init()
def _launch_wizard(self):
if self._wizard is None:
- self._wizard = Wizard()
+ self._wizard = Wizard(self._checker_thread)
self._wizard.exec_()
def _finish_init(self):
@@ -187,14 +200,23 @@ class MainWindow(QtGui.QMainWindow):
"""
Centers the mainwindow based on the desktop geometry
"""
- app = QtGui.QApplication.instance()
- width = app.desktop().width()
- height = app.desktop().height()
- window_width = self.size().width()
- window_height = self.size().height()
- x = (width / 2.0) - (window_width / 2.0)
- y = (height / 2.0) - (window_height / 2.0)
- self.move(x, y)
+ settings = QtCore.QSettings()
+ geometry = settings.value(self.GEOMETRY_KEY, None)
+ state = settings.value(self.WINDOWSTATE_KEY, None)
+ if geometry is None:
+ app = QtGui.QApplication.instance()
+ width = app.desktop().width()
+ height = app.desktop().height()
+ window_width = self.size().width()
+ window_height = self.size().height()
+ x = (width / 2.0) - (window_width / 2.0)
+ y = (height / 2.0) - (window_height / 2.0)
+ self.move(x, y)
+ else:
+ self.restoreGeometry(geometry)
+
+ if state is not None:
+ self.restoreState(state)
def _about(self):
"""
@@ -236,6 +258,9 @@ class MainWindow(QtGui.QMainWindow):
self._toggle_visible()
e.ignore()
return
+ settings = QtCore.QSettings()
+ settings.setValue(self.GEOMETRY_KEY, self.saveGeometry())
+ settings.setValue(self.WINDOWSTATE_KEY, self.saveState())
QtGui.QMainWindow.closeEvent(self, e)
def _configured_providers(self):
@@ -244,10 +269,16 @@ class MainWindow(QtGui.QMainWindow):
@rtype: list
"""
- providers = os.listdir(
- os.path.join(self._provider_config.get_path_prefix(),
- "leap",
- "providers"))
+ providers = []
+ try:
+ providers = os.listdir(
+ os.path.join(self._provider_config.get_path_prefix(),
+ "leap",
+ "providers"))
+ except Exception as e:
+ logger.debug("Error listing providers, assume there are none. %r"
+ % (e,))
+
return providers
def _first_run(self):
@@ -303,8 +334,8 @@ class MainWindow(QtGui.QMainWindow):
"""
provider = self.ui.cmbProviders.currentText()
- self._provider_bootstrapper.start()
self._provider_bootstrapper.run_provider_select_checks(
+ self._checker_thread,
provider,
download_if_needed=True)
@@ -329,6 +360,7 @@ class MainWindow(QtGui.QMainWindow):
provider,
"provider.json")):
self._provider_bootstrapper.run_provider_setup_checks(
+ self._checker_thread,
self._provider_config,
download_if_needed=True)
else:
@@ -350,7 +382,7 @@ class MainWindow(QtGui.QMainWindow):
start the SRP authentication, and as the last step
bootstrapping the EIP service
"""
- assert self._provider_config, "We need a provider config"
+ leap_assert(self._provider_config, "We need a provider config")
username = self.ui.lnUser.text()
password = self.ui.lnPassword.text()
@@ -381,9 +413,7 @@ class MainWindow(QtGui.QMainWindow):
Once the provider configuration is loaded, this starts the SRP
authentication
"""
- assert self._provider_config, "We need a provider config!"
-
- self._provider_bootstrapper.set_should_quit()
+ leap_assert(self._provider_config, "We need a provider config!")
if data[self._provider_bootstrapper.PASSED_KEY]:
username = self.ui.lnUser.text()
@@ -431,14 +461,14 @@ class MainWindow(QtGui.QMainWindow):
"""
Starts the EIP bootstrapping sequence
"""
- assert self._eip_bootstrapper, "We need an eip bootstrapper!"
- assert self._provider_config, "We need a provider config"
+ leap_assert(self._eip_bootstrapper, "We need an eip bootstrapper!")
+ leap_assert(self._provider_config, "We need a provider config")
self._set_eip_status("Checking configuration, please wait...")
if self._provider_config.provides_eip():
- self._eip_bootstrapper.start()
self._eip_bootstrapper.run_eip_setup_checks(
+ self._checker_thread,
self._provider_config,
download_if_needed=True)
else:
@@ -503,10 +533,9 @@ class MainWindow(QtGui.QMainWindow):
Starts the VPN thread if the eip configuration is properly
loaded
"""
- assert self._eip_config, "We need an eip config!"
- assert self._provider_config, "We need a provider config!"
+ leap_assert(self._eip_config, "We need an eip config!")
+ leap_assert(self._provider_config, "We need a provider config!")
- self._eip_bootstrapper.set_should_quit()
if self._eip_config.loaded() or \
self._eip_config.load(os.path.join("leap",
"providers",
diff --git a/src/leap/gui/ui/wizard.ui b/src/leap/gui/ui/wizard.ui
index 86f8d458..2d9cb441 100644
--- a/src/leap/gui/ui/wizard.ui
+++ b/src/leap/gui/ui/wizard.ui
@@ -47,7 +47,7 @@
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;New we will guide you through some configuration that is needed before you can connect for the first time.&lt;/p&gt;&lt;p&gt;If you ever need to modify these options again, you can find the wizard in the &lt;span style=&quot; font-style:italic;&quot;&gt;'Settings'&lt;/span&gt; menu from the main window.&lt;/p&gt;&lt;p&gt;Do you want to &lt;span style=&quot; font-weight:600;&quot;&gt;sign up&lt;/span&gt; for a new account, or &lt;span style=&quot; font-weight:600;&quot;&gt;log in&lt;/span&gt; with an already existing username?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Now we will guide you through some configuration that is needed before you can connect for the first time.&lt;/p&gt;&lt;p&gt;If you ever need to modify these options again, you can find the wizard in the &lt;span style=&quot; font-style:italic;&quot;&gt;'Settings'&lt;/span&gt; menu from the main window.&lt;/p&gt;&lt;p&gt;Do you want to &lt;span style=&quot; font-weight:600;&quot;&gt;sign up&lt;/span&gt; for a new account, or &lt;span style=&quot; font-weight:600;&quot;&gt;log in&lt;/span&gt; with an already existing username?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
@@ -497,6 +497,9 @@
<property name="text">
<string/>
</property>
+ <property name="textFormat">
+ <enum>Qt::AutoText</enum>
+ </property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py
index 7dcc8dd6..bac74d1d 100644
--- a/src/leap/gui/wizard.py
+++ b/src/leap/gui/wizard.py
@@ -21,7 +21,8 @@ First run wizard
import os
import logging
-from PySide import QtCore, QtGui
+from PySide import QtGui
+from functools import partial
from ui_wizard import Ui_Wizard
from leap.config.providerconfig import ProviderConfig
@@ -45,15 +46,18 @@ class Wizard(QtGui.QWizard):
SETUP_EIP_PAGE = 5
FINISH_PATH = 6
- WEAK_PASSWORDS = ("1234", "12345", "123456",
+ WEAK_PASSWORDS = ("123456", "qweasd", "qwerty",
"password")
- def __init__(self):
+ def __init__(self, checker):
QtGui.QWizard.__init__(self)
self.ui = Ui_Wizard()
self.ui.setupUi(self)
+ self.setPixmap(QtGui.QWizard.LogoPixmap,
+ QtGui.QPixmap(":/images/leap-color-small.png"))
+
self.QUESTION_ICON = QtGui.QPixmap(":/images/Emblem-question.png")
self.ERROR_ICON = QtGui.QPixmap(":/images/Dialog-error.png")
self.OK_ICON = QtGui.QPixmap(":/images/Dialog-accept.png")
@@ -94,6 +98,9 @@ class Wizard(QtGui.QWizard):
self.ui.lblPassword.setEchoMode(QtGui.QLineEdit.Password)
self.ui.lblPassword2.setEchoMode(QtGui.QLineEdit.Password)
+ self.ui.lnProvider.textChanged.connect(
+ self._enable_check)
+
self.ui.lblUser.returnPressed.connect(
self._focus_password)
self.ui.lblPassword.returnPressed.connect(
@@ -105,15 +112,14 @@ class Wizard(QtGui.QWizard):
self._username = None
- def __del__(self):
- self._provider_bootstrapper.set_should_quit()
- self._eip_bootstrapper.set_should_quit()
- self._provider_bootstrapper.wait()
- self._eip_bootstrapper.wait()
+ self._checker_thread = checker
def get_username(self):
return self._username
+ def _enable_check(self, text):
+ self.ui.btnCheck.setEnabled(len(self.ui.lnProvider.text()) != 0)
+
def _focus_password(self):
"""
Focuses at the password lineedit for the registration page
@@ -151,13 +157,13 @@ class Wizard(QtGui.QWizard):
if message is not None and password != password2:
message = "Passwords don't match"
- if message is not None and len(password) < 4:
+ if message is None and len(password) < 6:
message = "Password too short"
- if message is not None and password in self.WEAK_PASSWORDS:
+ if message is None and password in self.WEAK_PASSWORDS:
message = "Password too easy"
- if message is not None and username == password:
+ if message is None and username == password:
message = "Password equal to username"
if message is not None:
@@ -172,10 +178,6 @@ class Wizard(QtGui.QWizard):
Performs the registration based on the values provided in the form
"""
self.ui.btnRegister.setEnabled(False)
- # See the disabled button
- while QtGui.QApplication.instance().hasPendingEvents():
- QtGui.QApplication.instance().processEvents()
- self.button(QtGui.QWizard.NextButton).setFocus()
username = self.ui.lblUser.text()
password = self.ui.lblPassword.text()
@@ -183,27 +185,32 @@ class Wizard(QtGui.QWizard):
if self._basic_password_checks(username, password, password2):
register = SRPRegister(provider_config=self._provider_config)
- ok, req = register.register_user(username, password)
- if ok:
- self._set_register_status("<b>User registration OK</b>")
- self._username = username
- self.ui.lblPassword2.clearFocus()
- # Detach this call to allow UI updates briefly
- QtCore.QTimer.singleShot(1,
- self.page(self.REGISTER_USER_PAGE)
- .set_completed)
- else:
- print req.content
- error_msg = "Unknown error"
- try:
- error_msg = req.json().get("errors").get("login")[0]
- except:
- logger.error("Unknown error: %r" % (req.content,))
- self._set_register_status(error_msg)
- self.ui.btnRegister.setEnabled(True)
+ register.registration_finished.connect(
+ self._registration_finished)
+ self._checker_thread.add_checks(
+ [partial(register.register_user, username, password)])
+ self._username = username
+ self._set_register_status("Starting registration...")
else:
self.ui.btnRegister.setEnabled(True)
+ def _registration_finished(self, ok, req):
+ if ok:
+ self._set_register_status("<font color='green'>"
+ "<b>User registration OK</b></font>")
+ self.ui.lblPassword2.clearFocus()
+ self.page(self.REGISTER_USER_PAGE).set_completed()
+ self.button(QtGui.QWizard.BackButton).setEnabled(False)
+ else:
+ self._username = None
+ error_msg = "Unknown error"
+ try:
+ error_msg = req.json().get("errors").get("login")[0]
+ except:
+ logger.error("Unknown error: %r" % (req.content,))
+ self._set_register_status(error_msg)
+ self.ui.btnRegister.setEnabled(True)
+
def _set_register_status(self, status):
"""
Sets the status label in the registration page to status
@@ -222,12 +229,16 @@ class Wizard(QtGui.QWizard):
Starts the checks for a given provider
"""
+ if len(self.ui.lnProvider.text()) == 0:
+ return
+
self.ui.grpCheckProvider.setVisible(True)
self.ui.btnCheck.setEnabled(False)
self._domain = self.ui.lnProvider.text()
- self._provider_bootstrapper.start()
- self._provider_bootstrapper.run_provider_select_checks(self._domain)
+ self._provider_bootstrapper.run_provider_select_checks(
+ self._checker_thread,
+ self._domain)
def _complete_task(self, data, label, complete=False, complete_page=-1):
"""
@@ -328,7 +339,6 @@ class Wizard(QtGui.QWizard):
"""
self._complete_task(data, self.ui.lblCheckApiCert,
True, self.SETUP_PROVIDER_PAGE)
- self._provider_bootstrapper.set_should_quit()
def _download_eip_config(self, data):
"""
@@ -351,7 +361,6 @@ class Wizard(QtGui.QWizard):
"""
self._complete_task(data, self.ui.lblDownloadClientCert,
True, self.SETUP_EIP_PAGE)
- self._eip_bootstrapper.set_should_quit()
def _current_id_changed(self, pageId):
"""
@@ -365,14 +374,16 @@ class Wizard(QtGui.QWizard):
self.ui.lblNameResolution.setPixmap(self.QUESTION_ICON)
self.ui.lblHTTPS.setPixmap(self.QUESTION_ICON)
self.ui.lblProviderInfo.setPixmap(self.QUESTION_ICON)
+ self._enable_check("")
if pageId == self.SETUP_PROVIDER_PAGE:
self._provider_bootstrapper.\
- run_provider_setup_checks(self._provider_config)
+ run_provider_setup_checks(self._checker_thread,
+ self._provider_config)
if pageId == self.SETUP_EIP_PAGE:
- self._eip_bootstrapper.start()
- self._eip_bootstrapper.run_eip_setup_checks(self._provider_config)
+ self._eip_bootstrapper.run_eip_setup_checks(self._checker_thread,
+ self._provider_config)
if pageId == self.PRESENT_PROVIDER_PAGE:
# TODO: get the right lang for these
diff --git a/src/leap/services/eip/eipbootstrapper.py b/src/leap/services/eip/eipbootstrapper.py
index 77d7020a..bd6ab715 100644
--- a/src/leap/services/eip/eipbootstrapper.py
+++ b/src/leap/services/eip/eipbootstrapper.py
@@ -28,11 +28,13 @@ from PySide import QtGui, QtCore
from leap.config.providerconfig import ProviderConfig
from leap.services.eip.eipconfig import EIPConfig
+from leap.util.check import leap_assert, leap_assert_type
+from leap.util.checkerthread import CheckerThread
logger = logging.getLogger(__name__)
-class EIPBootstrapper(QtCore.QThread):
+class EIPBootstrapper(QtCore.QObject):
"""
Sets up EIP for a provider a series of checks and emits signals
after they are passed.
@@ -50,13 +52,7 @@ class EIPBootstrapper(QtCore.QThread):
download_client_certificate = QtCore.Signal(dict)
def __init__(self):
- QtCore.QThread.__init__(self)
-
- self._checks = []
- self._checks_lock = QtCore.QMutex()
-
- self._should_quit = False
- self._should_quit_lock = QtCore.QMutex()
+ QtCore.QObject.__init__(self)
# **************************************************** #
# Dependency injection helpers, override this for more
@@ -69,35 +65,6 @@ class EIPBootstrapper(QtCore.QThread):
self._eip_config = None
self._download_if_needed = False
- def get_should_quit(self):
- """
- Returns wether this thread should quit
-
- @rtype: bool
- @return: True if the thread should terminate itself, Flase otherwise
- """
-
- QtCore.QMutexLocker(self._should_quit_lock)
- return self._should_quit
-
- def set_should_quit(self):
- """
- Sets the should_quit flag to True so that this thread
- terminates the first chance it gets
- """
- QtCore.QMutexLocker(self._should_quit_lock)
- self._should_quit = True
- self.wait()
-
- def start(self):
- """
- Starts the thread and resets the should_quit flag
- """
- with QtCore.QMutexLocker(self._should_quit_lock):
- self._should_quit = False
-
- QtCore.QThread.start(self)
-
def _download_config(self):
"""
Downloads the EIP config for the given provider
@@ -106,7 +73,8 @@ class EIPBootstrapper(QtCore.QThread):
@rtype: bool
"""
- assert self._provider_config, "We need a provider configuration!"
+ leap_assert(self._provider_config,
+ "We need a provider configuration!")
logger.debug("Downloading EIP config for %s" %
(self._provider_config.get_domain(),))
@@ -162,8 +130,8 @@ class EIPBootstrapper(QtCore.QThread):
@return: True if the checks passed, False otherwise
@rtype: bool
"""
- assert self._provider_config, "We need a provider configuration!"
- assert self._eip_config, "We need an eip configuration!"
+ leap_assert(self._provider_config, "We need a provider configuration!")
+ leap_assert(self._eip_config, "We need an eip configuration!")
logger.debug("Downloading EIP client certificate for %s" %
(self._provider_config.get_domain(),))
@@ -218,49 +186,25 @@ class EIPBootstrapper(QtCore.QThread):
return download_cert[self.PASSED_KEY]
- def run_eip_setup_checks(self, provider_config, download_if_needed=False):
+ def run_eip_setup_checks(self, checker,
+ provider_config,
+ download_if_needed=False):
"""
Starts the checks needed for a new eip setup
@param provider_config: Provider configuration
@type provider_config: ProviderConfig
"""
- assert provider_config, "We need a provider config!"
- assert isinstance(provider_config, ProviderConfig), "Expected " + \
- "ProviderConfig type, not %r" % (type(provider_config),)
+ leap_assert(provider_config, "We need a provider config!")
+ leap_assert_type(provider_config, ProviderConfig)
self._provider_config = provider_config
self._download_if_needed = download_if_needed
- QtCore.QMutexLocker(self._checks_lock)
- self._checks = [
+ checker.add_checks([
self._download_config,
self._download_client_certificates
- ]
-
- def run(self):
- """
- Main run loop for this thread. Executes the checks.
- """
- shouldContinue = False
- while True:
- if self.get_should_quit():
- logger.debug("Quitting provider bootstrap thread")
- return
- checkSomething = False
- with QtCore.QMutexLocker(self._checks_lock):
- if len(self._checks) > 0:
- check = self._checks.pop(0)
- shouldContinue = check()
- checkSomething = True
- if not shouldContinue:
- logger.debug("Something went wrong with the checks, "
-
- "clearing...")
- self._checks = []
- checkSomething = False
- if not checkSomething:
- self.usleep(self.IDLE_SLEEP_INTERVAL)
+ ])
if __name__ == "__main__":
@@ -272,8 +216,8 @@ if __name__ == "__main__":
def sigint_handler(*args, **kwargs):
logger.debug('SIGINT catched. shutting down...')
- bootstrapper_thread = args[0]
- bootstrapper_thread.set_should_quit()
+ checker = args[0]
+ checker.set_should_quit()
QtGui.QApplication.quit()
def signal_tester(d):
@@ -289,27 +233,28 @@ if __name__ == "__main__":
console.setFormatter(formatter)
logger.addHandler(console)
- eip_thread = EIPBootstrapper()
+ eip_checks = EIPBootstrapper()
+ checker = CheckerThread()
- sigint = partial(sigint_handler, eip_thread)
+ sigint = partial(sigint_handler, checker)
signal.signal(signal.SIGINT, sigint)
timer = QtCore.QTimer()
timer.start(500)
timer.timeout.connect(lambda: None)
app.connect(app, QtCore.SIGNAL("aboutToQuit()"),
- eip_thread.set_should_quit)
+ checker.set_should_quit)
w = QtGui.QWidget()
w.resize(100, 100)
w.show()
- eip_thread.start()
+ checker.start()
provider_config = ProviderConfig()
if provider_config.load(os.path.join("leap",
"providers",
"bitmask.net",
"provider.json")):
- eip_thread.run_eip_setup_checks(provider_config)
+ eip_checks.run_eip_setup_checks(checker, provider_config)
sys.exit(app.exec_())
diff --git a/src/leap/services/eip/eipconfig.py b/src/leap/services/eip/eipconfig.py
index ac06fef1..eab5bfd4 100644
--- a/src/leap/services/eip/eipconfig.py
+++ b/src/leap/services/eip/eipconfig.py
@@ -24,6 +24,7 @@ import logging
from leap.config.baseconfig import BaseConfig
from leap.config.providerconfig import ProviderConfig
from leap.services.eip.eipspec import eipservice_config_spec
+from leap.util.check import leap_assert, leap_assert_type
logger = logging.getLogger(__name__)
@@ -61,7 +62,7 @@ class EIPConfig(BaseConfig):
def get_gateway_ip(self, index=0):
gateways = self.get_gateways()
- assert len(gateways) > 0, "We don't have any gateway!"
+ leap_assert(len(gateways) > 0, "We don't have any gateway!")
if index > len(gateways):
index = 0
logger.warning("Provided an unknown gateway index %s, " +
@@ -75,10 +76,8 @@ class EIPConfig(BaseConfig):
Returns the path to the certificate used by openvpn
"""
- assert providerconfig, "We need a provider"
- assert isinstance(providerconfig, ProviderConfig), "The provider " + \
- "needs to be of type ProviderConfig instead of %s" % \
- (type(providerconfig),)
+ leap_assert(providerconfig, "We need a provider")
+ leap_assert_type(providerconfig, ProviderConfig)
cert_path = os.path.join(self.get_path_prefix(),
"leap",
@@ -89,8 +88,8 @@ class EIPConfig(BaseConfig):
"openvpn.pem")
if not about_to_download:
- assert os.path.exists(cert_path), \
- "You need to download the certificate first"
+ leap_assert(os.path.exists(cert_path),
+ "You need to download the certificate first")
logger.debug("Using OpenVPN cert %s" % (cert_path,))
return cert_path
diff --git a/src/leap/services/eip/providerbootstrapper.py b/src/leap/services/eip/providerbootstrapper.py
index babcd47b..ecdc4e07 100644
--- a/src/leap/services/eip/providerbootstrapper.py
+++ b/src/leap/services/eip/providerbootstrapper.py
@@ -29,11 +29,13 @@ from OpenSSL import crypto
from PySide import QtGui, QtCore
from leap.config.providerconfig import ProviderConfig
+from leap.util.check import leap_assert, leap_assert_type
+from leap.util.checkerthread import CheckerThread
logger = logging.getLogger(__name__)
-class ProviderBootstrapper(QtCore.QThread):
+class ProviderBootstrapper(QtCore.QObject):
"""
Given a provider URL performs a series of checks and emits signals
after they are passed.
@@ -56,13 +58,7 @@ class ProviderBootstrapper(QtCore.QThread):
check_api_certificate = QtCore.Signal(dict)
def __init__(self):
- QtCore.QThread.__init__(self)
-
- self._checks = []
- self._checks_lock = QtCore.QMutex()
-
- self._should_quit = False
- self._should_quit_lock = QtCore.QMutex()
+ QtCore.QObject.__init__(self)
# **************************************************** #
# Dependency injection helpers, override this for more
@@ -75,35 +71,6 @@ class ProviderBootstrapper(QtCore.QThread):
self._provider_config = None
self._download_if_needed = False
- def get_should_quit(self):
- """
- Returns wether this thread should quit
-
- @rtype: bool
- @return: True if the thread should terminate itself, Flase otherwise
- """
-
- QtCore.QMutexLocker(self._should_quit_lock)
- return self._should_quit
-
- def set_should_quit(self):
- """
- Sets the should_quit flag to True so that this thread
- terminates the first chance it gets
- """
- QtCore.QMutexLocker(self._should_quit_lock)
- self._should_quit = True
- self.wait()
-
- def start(self):
- """
- Starts the thread and resets the should_quit flag
- """
- with QtCore.QMutexLocker(self._should_quit_lock):
- self._should_quit = False
-
- QtCore.QThread.start(self)
-
def _should_proceed_provider(self):
"""
Returns False if provider.json already exists for the given
@@ -131,7 +98,7 @@ class ProviderBootstrapper(QtCore.QThread):
@rtype: bool
"""
- assert self._domain, "Cannot check DNS without a domain"
+ leap_assert(self._domain, "Cannot check DNS without a domain")
logger.debug("Checking name resolution for %s" % (self._domain))
@@ -162,7 +129,7 @@ class ProviderBootstrapper(QtCore.QThread):
@rtype: bool
"""
- assert self._domain, "Cannot check HTTPS without a domain"
+ leap_assert(self._domain, "Cannot check HTTPS without a domain")
logger.debug("Checking https for %s" % (self._domain))
@@ -193,7 +160,8 @@ class ProviderBootstrapper(QtCore.QThread):
@return: True if the checks passed, False otherwise
@rtype: bool
"""
- assert self._domain, "Cannot download provider info without a domain"
+ leap_assert(self._domain,
+ "Cannot download provider info without a domain")
logger.debug("Downloading provider info for %s" % (self._domain))
@@ -230,7 +198,8 @@ class ProviderBootstrapper(QtCore.QThread):
return download_data[self.PASSED_KEY]
- def run_provider_select_checks(self, domain, download_if_needed=False):
+ def run_provider_select_checks(self, checker,
+ domain, download_if_needed=False):
"""
Populates the check queue
@@ -243,17 +212,16 @@ class ProviderBootstrapper(QtCore.QThread):
@return: True if the checks passed, False otherwise
@rtype: bool
"""
- assert domain and len(domain) > 0, "We need a domain!"
+ leap_assert(domain and len(domain) > 0, "We need a domain!")
self._domain = domain
self._download_if_needed = download_if_needed
- QtCore.QMutexLocker(self._checks_lock)
- self._checks = [
+ checker.add_checks([
self._check_name_resolution,
self._check_https,
self._download_provider_info
- ]
+ ])
def _should_proceed_cert(self):
"""
@@ -262,7 +230,7 @@ class ProviderBootstrapper(QtCore.QThread):
@rtype: bool
"""
- assert self._provider_config, "We need a provider config!"
+ leap_assert(self._provider_config, "We need a provider config!")
if not self._download_if_needed:
return True
@@ -278,8 +246,8 @@ class ProviderBootstrapper(QtCore.QThread):
@rtype: bool
"""
- assert self._provider_config, "Cannot download the ca cert " + \
- "without a provider config!"
+ leap_assert(self._provider_config, "Cannot download the ca cert "
+ "without a provider config!")
logger.debug("Downloading ca cert for %s at %s" %
(self._domain, self._provider_config.get_ca_cert_uri()))
@@ -331,8 +299,8 @@ class ProviderBootstrapper(QtCore.QThread):
@return: True if the checks passed, False otherwise
@rtype: bool
"""
- assert self._provider_config, "Cannot check the ca cert " + \
- "without a provider config!"
+ leap_assert(self._provider_config, "Cannot check the ca cert "
+ "without a provider config!")
logger.debug("Checking ca fingerprint for %s and cert %s" %
(self._domain,
@@ -350,7 +318,7 @@ class ProviderBootstrapper(QtCore.QThread):
try:
parts = self._provider_config.get_ca_cert_fingerprint().split(":")
- assert len(parts) == 2, "Wrong fingerprint format"
+ leap_assert(len(parts) == 2, "Wrong fingerprint format")
method = parts[0].strip()
fingerprint = parts[1].strip()
@@ -358,13 +326,13 @@ class ProviderBootstrapper(QtCore.QThread):
with open(self._provider_config.get_ca_cert_path()) as f:
cert_data = f.read()
- assert len(cert_data) > 0, "Could not read certificate data"
+ leap_assert(len(cert_data) > 0, "Could not read certificate data")
x509 = crypto.load_certificate(crypto.FILETYPE_PEM, cert_data)
digest = x509.digest(method).replace(":", "").lower()
- assert digest == fingerprint, \
- "Downloaded certificate has a different fingerprint!"
+ leap_assert(digest == fingerprint,
+ "Downloaded certificate has a different fingerprint!")
check_ca_fingerprint_data[self.PASSED_KEY] = True
except Exception as e:
@@ -384,8 +352,8 @@ class ProviderBootstrapper(QtCore.QThread):
@return: True if the checks passed, False otherwise
@rtype: bool
"""
- assert self._provider_config, "Cannot check the ca cert " + \
- "without a provider config!"
+ leap_assert(self._provider_config, "Cannot check the ca cert "
+ "without a provider config!")
logger.debug("Checking api certificate for %s and cert %s" %
(self._provider_config.get_api_uri(),
@@ -418,7 +386,8 @@ class ProviderBootstrapper(QtCore.QThread):
return check_api_certificate_data[self.PASSED_KEY]
- def run_provider_setup_checks(self, provider_config,
+ def run_provider_setup_checks(self, checker,
+ provider_config,
download_if_needed=False):
"""
Starts the checks needed for a new provider setup
@@ -429,43 +398,17 @@ class ProviderBootstrapper(QtCore.QThread):
overwrite already downloaded data
@type download_if_needed: bool
"""
- assert provider_config, "We need a provider config!"
- assert isinstance(provider_config, ProviderConfig), "Expected " + \
- "ProviderConfig type, not %r" % (type(provider_config),)
+ leap_assert(provider_config, "We need a provider config!")
+ leap_assert_type(provider_config, ProviderConfig)
self._provider_config = provider_config
self._download_if_needed = download_if_needed
- QtCore.QMutexLocker(self._checks_lock)
- self._checks = [
+ checker.add_checks([
self._download_ca_cert,
self._check_ca_fingerprint,
self._check_api_certificate
- ]
-
- def run(self):
- """
- Main run loop for this thread. Executes the checks.
- """
- shouldContinue = False
- while True:
- if self.get_should_quit():
- logger.debug("Quitting provider bootstrap thread")
- return
- checkSomething = False
- with QtCore.QMutexLocker(self._checks_lock):
- if len(self._checks) > 0:
- check = self._checks.pop(0)
- shouldContinue = check()
- checkSomething = True
- if not shouldContinue:
- logger.debug("Something went wrong with the checks, "
- "clearing...")
- self._checks = []
- checkSomething = False
- if not checkSomething:
- self.usleep(self.IDLE_SLEEP_INTERVAL)
-
+ ])
if __name__ == "__main__":
import sys
@@ -476,8 +419,8 @@ if __name__ == "__main__":
def sigint_handler(*args, **kwargs):
logger.debug('SIGINT catched. shutting down...')
- bootstrapper_thread = args[0]
- bootstrapper_thread.set_should_quit()
+ bootstrapper_checks = args[0]
+ bootstrapper_checks.set_should_quit()
QtGui.QApplication.quit()
def signal_tester(d):
@@ -493,28 +436,32 @@ if __name__ == "__main__":
console.setFormatter(formatter)
logger.addHandler(console)
- bootstrapper_thread = ProviderBootstrapper()
+ bootstrapper_checks = ProviderBootstrapper()
+
+ checker = CheckerThread()
+ checker.start()
- sigint = partial(sigint_handler, bootstrapper_thread)
+ sigint = partial(sigint_handler, checker)
signal.signal(signal.SIGINT, sigint)
timer = QtCore.QTimer()
timer.start(500)
timer.timeout.connect(lambda: None)
app.connect(app, QtCore.SIGNAL("aboutToQuit()"),
- bootstrapper_thread.set_should_quit)
+ checker.set_should_quit)
w = QtGui.QWidget()
w.resize(100, 100)
w.show()
- bootstrapper_thread.start()
- bootstrapper_thread.run_provider_select_checks("bitmask.net")
+ bootstrapper_checks.run_provider_select_checks(checker,
+ "bitmask.net")
provider_config = ProviderConfig()
if provider_config.load(os.path.join("leap",
"providers",
"bitmask.net",
"provider.json")):
- bootstrapper_thread.run_provider_setup_checks(provider_config)
+ bootstrapper_checks.run_provider_setup_checks(checker,
+ provider_config)
sys.exit(app.exec_())
diff --git a/src/leap/services/eip/vpn.py b/src/leap/services/eip/vpn.py
index f117cdbc..88692442 100644
--- a/src/leap/services/eip/vpn.py
+++ b/src/leap/services/eip/vpn.py
@@ -29,6 +29,7 @@ from leap.config.providerconfig import ProviderConfig
from leap.services.eip.vpnlaunchers import get_platform_launcher
from leap.services.eip.eipconfig import EIPConfig
from leap.services.eip.udstelnet import UDSTelnet
+from leap.util.check import leap_assert, leap_assert_type
logger = logging.getLogger(__name__)
ON_POSIX = 'posix' in sys.builtin_module_names
@@ -123,13 +124,11 @@ class VPN(QtCore.QThread):
socket, or port otherwise
@type socket_port: str
"""
- assert eipconfig, "We need an eip config"
- assert isinstance(eipconfig, EIPConfig), "Expected EIPConfig " + \
- "object instead of %s" % (type(eipconfig),)
- assert providerconfig, "We need a provider config"
- assert isinstance(providerconfig, ProviderConfig), "Expected " + \
- "ProviderConfig object instead of %s" % (type(providerconfig),)
- assert not self._started, "Starting process more than once!"
+ leap_assert(eipconfig, "We need an eip config")
+ leap_assert_type(eipconfig, EIPConfig)
+ leap_assert(providerconfig, "We need a provider config")
+ leap_assert_type(providerconfig, ProviderConfig)
+ leap_assert(not self._started, "Starting process more than once!")
logger.debug("Starting VPN...")
@@ -202,7 +201,7 @@ class VPN(QtCore.QThread):
@return: response read
@rtype: list
"""
- assert self._tn, "We need a tn connection!"
+ leap_assert(self._tn, "We need a tn connection!")
try:
self._tn.write("%s\n" % (command,))
buf = self._tn.read_until(until, 2)
diff --git a/src/leap/services/eip/vpnlaunchers.py b/src/leap/services/eip/vpnlaunchers.py
index 68978248..00e9c966 100644
--- a/src/leap/services/eip/vpnlaunchers.py
+++ b/src/leap/services/eip/vpnlaunchers.py
@@ -29,6 +29,7 @@ from abc import ABCMeta, abstractmethod
from leap.config.providerconfig import ProviderConfig
from leap.services.eip.eipconfig import EIPConfig
+from leap.util.check import leap_assert, leap_assert_type
logger = logging.getLogger(__name__)
@@ -65,8 +66,8 @@ class VPNLauncher:
def get_platform_launcher():
launcher = globals()[platform.system() + "VPNLauncher"]
- assert launcher, "Unimplemented platform launcher: %s" % \
- (platform.system(),)
+ leap_assert(launcher, "Unimplemented platform launcher: %s" %
+ (platform.system(),))
return launcher()
@@ -165,17 +166,15 @@ class LinuxVPNLauncher(VPNLauncher):
@return: A VPN command ready to be launched
@rtype: list
"""
- assert eipconfig, "We need an eip config"
- assert isinstance(eipconfig, EIPConfig), "Expected EIPConfig " + \
- "object instead of %s" % (type(eipconfig),)
- assert providerconfig, "We need a provider config"
- assert isinstance(providerconfig, ProviderConfig), "Expected " + \
- "ProviderConfig object instead of %s" % (type(providerconfig),)
- assert socket_host, "We need a socket host!"
- assert socket_port, "We need a socket port!"
+ leap_assert(eipconfig, "We need an eip config")
+ leap_assert_type(eipconfig, EIPConfig)
+ leap_assert(providerconfig, "We need a provider config")
+ leap_assert_type(providerconfig, ProviderConfig)
+ leap_assert(socket_host, "We need a socket host!")
+ leap_assert(socket_port, "We need a socket port!")
openvpn_possibilities = which(self.OPENVPN_BIN)
- assert len(openvpn_possibilities) > 0, "We couldn't find openvpn"
+ leap_assert(len(openvpn_possibilities) > 0, "We couldn't find openvpn")
openvpn = openvpn_possibilities[0]
args = []
@@ -183,7 +182,8 @@ class LinuxVPNLauncher(VPNLauncher):
if _is_pkexec_in_system():
if _is_auth_agent_running():
pkexec_possibilities = which(self.PKEXEC_BIN)
- assert len(pkexec_possibilities) > 0, "We couldn't find pkexec"
+ leap_assert(len(pkexec_possibilities) > 0,
+ "We couldn't find pkexec")
args.append(openvpn)
openvpn = pkexec_possibilities[0]
else:
diff --git a/src/leap/util/check.py b/src/leap/util/check.py
new file mode 100644
index 00000000..9787341a
--- /dev/null
+++ b/src/leap/util/check.py
@@ -0,0 +1,61 @@
+# -*- coding: utf-8 -*-
+# check.py
+# Copyright (C) 2013 LEAP
+#
+# 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/>.
+
+"""
+Set of functions to help checking situations
+"""
+import logging
+import inspect
+import traceback
+
+
+logger = logging.getLogger(__name__)
+
+
+def leap_assert(condition, message=""):
+ """
+ Asserts the condition and displays the message if that's not
+ met. It also logs the error and its backtrace.
+
+ @param condition: condition to check
+ @type condition: bool
+ @param message: message to display if the condition isn't met
+ @type message: str
+ """
+ if not condition:
+ logger.error("Bug: %s" % (message,))
+ try:
+ frame = inspect.currentframe()
+ stack_trace = traceback.format_stack(frame)
+ logger.error(''.join(stack_trace))
+ except Exception as e:
+ logger.error("Bug in leap_assert: %r" % (e,))
+ assert condition, message
+
+
+def leap_assert_type(var, expectedType):
+ """
+ Helper assert check for a variable's expected type
+
+ @param var: variable to check
+ @type var: any
+ @param expectedType: type to check agains
+ @type expectedType: type
+ """
+ leap_assert(isinstance(var, expectedType),
+ "Expected type %r instead of %r" %
+ (expectedType, type(var)))
diff --git a/src/leap/util/checkerthread.py b/src/leap/util/checkerthread.py
new file mode 100644
index 00000000..681c33e1
--- /dev/null
+++ b/src/leap/util/checkerthread.py
@@ -0,0 +1,110 @@
+# -*- coding: utf-8 -*-
+# providerbootstrapper.py
+# Copyright (C) 2013 LEAP
+#
+# 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/>.
+
+"""
+Checker thread
+"""
+
+import logging
+
+from PySide import QtCore
+
+from leap.util.check import leap_assert_type
+
+logger = logging.getLogger(__name__)
+
+
+class CheckerThread(QtCore.QThread):
+ """
+ Generic checker thread that can perform any type of operation as
+ long as it returns a boolean value that identifies how the
+ execution went.
+ """
+
+ IDLE_SLEEP_INTERVAL = 1
+
+ def __init__(self):
+ QtCore.QThread.__init__(self)
+
+ self._checks = []
+ self._checks_lock = QtCore.QMutex()
+
+ self._should_quit = False
+ self._should_quit_lock = QtCore.QMutex()
+
+ def get_should_quit(self):
+ """
+ Returns wether this thread should quit
+
+ @rtype: bool
+ @return: True if the thread should terminate itself, Flase otherwise
+ """
+
+ QtCore.QMutexLocker(self._should_quit_lock)
+ return self._should_quit
+
+ def set_should_quit(self):
+ """
+ Sets the should_quit flag to True so that this thread
+ terminates the first chance it gets
+ """
+ QtCore.QMutexLocker(self._should_quit_lock)
+ self._should_quit = True
+ self.wait()
+
+ def start(self):
+ """
+ Starts the thread and resets the should_quit flag
+ """
+ with QtCore.QMutexLocker(self._should_quit_lock):
+ self._should_quit = False
+
+ QtCore.QThread.start(self)
+
+ def add_checks(self, checks):
+ """
+ Adds a list of checks to the ones being executed
+
+ @param checks: check functions to perform
+ @type checkes: list
+ """
+ with QtCore.QMutexLocker(self._checks_lock):
+ self._checks += checks
+
+ def run(self):
+ """
+ Main run loop for this thread. Executes the checks.
+ """
+ shouldContinue = False
+ while True:
+ if self.get_should_quit():
+ logger.debug("Quitting checker thread")
+ return
+ checkSomething = False
+ with QtCore.QMutexLocker(self._checks_lock):
+ if len(self._checks) > 0:
+ check = self._checks.pop(0)
+ shouldContinue = check()
+ leap_assert_type(shouldContinue, bool)
+ checkSomething = True
+ if not shouldContinue:
+ logger.debug("Something went wrong with the checks, "
+ "clearing...")
+ self._checks = []
+ checkSomething = False
+ if not checkSomething:
+ self.sleep(self.IDLE_SLEEP_INTERVAL)