From 3fd7b55de96484e02accb991fb2c0c3ce0aa9883 Mon Sep 17 00:00:00 2001 From: antialias Date: Tue, 25 Sep 2012 17:37:48 -0400 Subject: First check for threaded network checks. TODO: tests. --- src/leap/base/constants.py | 2 ++ src/leap/base/network.py | 55 +++++++++++++++++++++++++++++++++++++++++ src/leap/baseapp/mainwindow.py | 3 +++ src/leap/baseapp/network.py | 56 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 116 insertions(+) create mode 100644 src/leap/base/network.py create mode 100644 src/leap/baseapp/network.py diff --git a/src/leap/base/constants.py b/src/leap/base/constants.py index 7a1415fb..8a76b6b4 100644 --- a/src/leap/base/constants.py +++ b/src/leap/base/constants.py @@ -28,3 +28,5 @@ DEFAULT_PROVIDER_DEFINITION = { u'version': u'0.1.0'} MAX_ICMP_PACKET_LOSS = 10 + +ROUTE_CHECK_INTERVAL = 120 diff --git a/src/leap/base/network.py b/src/leap/base/network.py new file mode 100644 index 00000000..58f903e1 --- /dev/null +++ b/src/leap/base/network.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +from __future__ import (print_function) + +from leap.base.checks import LeapNetworkChecker +from leap.base.constants import ROUTE_CHECK_INTERVAL +from leap.util.coroutines import (launch_thread, process_events) + +from time import sleep + +class NetworkChecker(object): + """ + Manages network checking thread that makes sure we have a working network + connection. + """ + def __init__(self, *args, **kwargs): + self.status_signals = kwargs.pop('status_signals', None) + self.watcher_cb = kwargs.pop('status_signals', None) + + def start(self): + self._launch_recurrent_network_checks((self.watcher_cb,)) + + def stop(self): + raise NotImplementedError + + def run_checks(self): + pass + + #private methods + + #here all the observers in fail_callbacks expect one positional argument, + #which is exception so we can try by passing a lambda with logger to + #check it works. + def _network_checks_thread(self, fail_callbacks): + print('fail_callbacks: %s' % fail_callbacks) + print(len(fail_callbacks)) + observer_dict = dict((( + observer, process_events(observer)) for observer in fail_callbacks)) + netchecker = LeapNetworkChecker() + while True: + try: + netchecker.check_internet_connection() + sleep(ROUTE_CHECK_INTERVAL) + except Exception as exc: + for obs in observer_dict: + observer_dict[obs].send(exc) + + + def _launch_recurrent_network_checks(fail_callbacks): + print(type(fail_callbacks)) + watcher = launch_thread( + network_checks_thread, + (fail_callbacks,)) + return watcher + + diff --git a/src/leap/baseapp/mainwindow.py b/src/leap/baseapp/mainwindow.py index 10b23d9a..7b2ecb1d 100644 --- a/src/leap/baseapp/mainwindow.py +++ b/src/leap/baseapp/mainwindow.py @@ -8,6 +8,7 @@ from PyQt4 import QtGui from leap.baseapp.eip import EIPConductorAppMixin from leap.baseapp.log import LogPaneMixin from leap.baseapp.systray import StatusAwareTrayIconMixin +from leap.baseapp.network import NetworkCheckerAppMixin from leap.baseapp.leap_app import MainWindowMixin logger = logging.getLogger(name=__name__) @@ -16,6 +17,7 @@ logger = logging.getLogger(name=__name__) class LeapWindow(QtGui.QMainWindow, MainWindowMixin, EIPConductorAppMixin, StatusAwareTrayIconMixin, + NetworkCheckerAppMixin, LogPaneMixin): """ main window for the leap app. @@ -36,6 +38,7 @@ class LeapWindow(QtGui.QMainWindow, self.createLogBrowser() EIPConductorAppMixin.__init__(self, opts=opts) StatusAwareTrayIconMixin.__init__(self) + NetworkCheckerAppMixin.__init__(self) MainWindowMixin.__init__(self) # bind signals diff --git a/src/leap/baseapp/network.py b/src/leap/baseapp/network.py new file mode 100644 index 00000000..42a42fcd --- /dev/null +++ b/src/leap/baseapp/network.py @@ -0,0 +1,56 @@ +from __future__ import print_function +import logging +import time +logger = logging.getLogger(name=__name__) + +from leap.base.network import NetworkChecker +from leap.baseapp.dialogs import ErrorDialog + + +class NetworkCheckerAppMixin(object): + """ + initialize an instance of the Network Checker, + which gathers error and passes them on. + """ + + def __init__(self, *args, **kwargs): + opts = kwargs.pop('opts', None) + config_file = getattr(opts, 'config_file', None) + + self.network_checker_started = False + + self.network_checker = NetworkChecker( + watcher_cb=self.newLogLine.emit, + status_signals=(self.statusChange.emit, ), + debug=self.debugmode) + + self.network_checker.run_checks() + self.error_check() + + def error_check(self): + """ + consumes the conductor error queue. + pops errors, and acts accordingly (launching user dialogs). + """ + logger.debug('error check') + + errq = self.conductor.error_queue + while errq.qsize() != 0: + logger.debug('%s errors left in conductor queue', errq.qsize()) + # we get exception and original traceback from queue + error, tb = errq.get() + + # redundant log, debugging the loop. + logger.error('%s: %s', error.__class__.__name__, error.message) + + if issubclass(error.__class__, eip_exceptions.EIPClientError): + self.handle_eip_error(error) + + else: + # deprecated form of raising exception. + raise error, None, tb + + if error.failfirst is True: + break + + -- cgit v1.2.3