diff options
| author | kali <kali@leap.se> | 2012-08-22 07:49:19 +0900 | 
|---|---|---|
| committer | kali <kali@leap.se> | 2012-08-22 07:49:19 +0900 | 
| commit | 24f288b5214b814e2e7daa6ef41b226a27d96b81 (patch) | |
| tree | 51dff8de10f0276786c0c83a55932a7f8932f6e9 | |
| parent | 83ac2efaa10de68f7fd35189f6cf272b03d60a30 (diff) | |
bye bye conductor, watcher (after refactor)
| -rw-r--r-- | src/leap/eip/conductor.py | 305 | ||||
| -rw-r--r-- | src/leap/eip/vpnwatcher.py | 169 | 
2 files changed, 0 insertions, 474 deletions
| diff --git a/src/leap/eip/conductor.py b/src/leap/eip/conductor.py deleted file mode 100644 index f528d639..00000000 --- a/src/leap/eip/conductor.py +++ /dev/null @@ -1,305 +0,0 @@ -""" -stablishes a vpn connection and monitors its state -""" -from __future__ import (division, unicode_literals, print_function) -#import threading -from functools import partial -import logging - -from leap.util.coroutines import spawn_and_watch_process - -# XXX from leap.eip import config as eipconfig -# from leap.eip import exceptions as eip_exceptions - -from leap.eip.config import (get_config, build_ovpn_command, -                             check_or_create_default_vpnconf, -                             check_vpn_keys, -                             EIPNoPkexecAvailable, -                             EIPNoPolkitAuthAgentAvailable, -                             EIPInitNoProviderError, -                             EIPInitBadProviderError, -                             EIPInitNoKeyFileError, -                             EIPInitBadKeyFilePermError) -from leap.eip.vpnwatcher import EIPConnectionStatus, status_watcher -from leap.eip.vpnmanager import OpenVPNManager, ConnectionRefusedError - -logger = logging.getLogger(name=__name__) - - -# -# Openvpn related classes -# -# XXX deprecated! moved to eipconnection - - -class OpenVPNConnection(object): -    """ -    All related to invocation -    of the openvpn binary -    """ -    # Connection Methods - -    def __init__(self, config_file=None, -                 watcher_cb=None, debug=False): -        #XXX FIXME -        #change watcher_cb to line_observer -        """ -        :param config_file: configuration file to read from -        :param watcher_cb: callback to be \ -called for each line in watched stdout -        :param signal_map: dictionary of signal names and callables \ -to be triggered for each one of them. -        :type config_file: str -        :type watcher_cb: function -        :type signal_map: dict -        """ -        # XXX get host/port from config -        self.manager = OpenVPNManager() -        self.debug = debug -        #print('conductor:%s' % debug) - -        self.config_file = config_file -        self.watcher_cb = watcher_cb -        #self.signal_maps = signal_maps - -        self.subp = None -        self.watcher = None - -        self.server = None -        self.port = None -        self.proto = None - -        self.missing_pkexec = False -        self.missing_auth_agent = False -        self.bad_keyfile_perms = False -        self.missing_vpn_keyfile = False -        self.missing_provider = False -        self.bad_provider = False - -        self.command = None -        self.args = None - -        self.autostart = True -        self._get_or_create_config() -        self._check_vpn_keys() - -    def _set_autostart(self): -        config = self.config -        if config.has_option('openvpn', 'autostart'): -            autostart = config.getboolean('openvpn', -                                          'autostart') -            self.autostart = autostart -        else: -            if config.has_option('DEFAULT', 'autostart'): -                autostart = config.getboolean('DEFAULT', -                                              'autostart') -                self.autostart = autostart - -    def _set_ovpn_command(self): -        config = self.config -        if config.has_option('openvpn', 'command'): -            commandline = config.get('openvpn', 'command') - -            command_split = commandline.split(' ') -            command = command_split[0] -            if len(command_split) > 1: -                args = command_split[1:] -            else: -                args = [] - -            self.command = command -            self.args = args -        else: -        # no command in config, we build it up. -        # XXX check also for command-line --command flag -            try: -                command, args = build_ovpn_command(config, -                                                   debug=self.debug) -            except EIPNoPolkitAuthAgentAvailable: -                command = args = None -                self.missing_auth_agent = True -            except EIPNoPkexecAvailable: -                command = args = None -                self.missing_pkexec = True - -            # XXX if not command, signal error. -            self.command = command -            self.args = args - -    def _check_ovpn_config(self): -        """ -        checks if there is a default openvpn config. -        if not, it writes one with info from the provider -        definition file -        """ -        # TODO -        # - get --with-openvpn-config from opts -        try: -            check_or_create_default_vpnconf(self.config) -        except EIPInitNoProviderError: -            logger.error('missing default provider definition') -            self.missing_provider = True -        except EIPInitBadProviderError: -            logger.error('bad provider definition') -            self.bad_provider = True - -    def _get_or_create_config(self): -        """ -        retrieves the config options from defaults or -        home file, or config file passed in command line. -        populates command and args to be passed to subprocess. -        """ -        config = get_config(config_file=self.config_file) -        self.config = config - -        self._set_autostart() -        self._set_ovpn_command() -        self._check_ovpn_config() - -    def _check_vpn_keys(self): -        """ -        checks for correct permissions on vpn keys -        """ -        try: -            check_vpn_keys(self.config) -        except EIPInitNoKeyFileError: -            self.missing_vpn_keyfile = True -        except EIPInitBadKeyFilePermError: -            logger.error('error while checking vpn keys') -            self.bad_keyfile_perms = True - -    def _launch_openvpn(self): -        """ -        invocation of openvpn binaries in a subprocess. -        """ -        #XXX TODO: -        #deprecate watcher_cb, -        #use _only_ signal_maps instead - -        if self.watcher_cb is not None: -            linewrite_callback = self.watcher_cb -        else: -            #XXX get logger instead -            linewrite_callback = lambda line: print('watcher: %s' % line) - -        observers = (linewrite_callback, -                     partial(status_watcher, self.status)) -        subp, watcher = spawn_and_watch_process( -            self.command, -            self.args, -            observers=observers) -        self.subp = subp -        self.watcher = watcher - -        #conn_result = self.status.CONNECTED -        #return conn_result - -    def _try_connection(self): -        """ -        attempts to connect -        """ -        if self.command is None: -            raise EIPNoCommandError -        if self.subp is not None: -            print('cowardly refusing to launch subprocess again') -            return -        self._launch_openvpn() - -    def cleanup(self): -        """ -        terminates child subprocess -        """ -        if self.subp: -            self.subp.terminate() - - -class EIPConductor(OpenVPNConnection): -    """ -    Manages the execution of the OpenVPN process, auto starts, monitors the -    network connection, handles configuration, fixes leaky hosts, handles -    errors, etc. -    Preferences will be stored via the Storage API. (TBD) -    Status updates (connected, bandwidth, etc) are signaled to the GUI. -    """ - -    def __init__(self, *args, **kwargs): -        self.settingsfile = kwargs.get('settingsfile', None) -        self.logfile = kwargs.get('logfile', None) -        self.error_queue = [] -        self.desired_con_state = None  # ??? - -        status_signals = kwargs.pop('status_signals', None) -        self.status = EIPConnectionStatus(callbacks=status_signals) - -        super(EIPConductor, self).__init__(*args, **kwargs) - -    def connect(self): -        """ -        entry point for connection process -        """ -        self.manager.forget_errors() -        self._try_connection() -        # XXX should capture errors here? - -    def disconnect(self): -        """ -        disconnects client -        """ -        self._disconnect() -        self.status.change_to(self.status.DISCONNECTED) - -    def poll_connection_state(self): -        """ -        """ -        try: -            state = self.manager.get_connection_state() -        except ConnectionRefusedError: -            # connection refused. might be not ready yet. -            return -        if not state: -            return -        (ts, status_step, -         ok, ip, remote) = state -        self.status.set_vpn_state(status_step) -        status_step = self.status.get_readable_status() -        return (ts, status_step, ok, ip, remote) - -    def get_icon_name(self): -        """ -        get icon name from status object -        """ -        return self.status.get_state_icon() - -    # -    # private methods -    # - -    def _disconnect(self): -        """ -        private method for disconnecting -        """ -        if self.subp is not None: -            self.subp.terminate() -            self.subp = None -        # XXX signal state changes! :) - -    def _is_alive(self): -        """ -        don't know yet -        """ -        pass - -    def _connect(self): -        """ -        entry point for connection cascade methods. -        """ -        #conn_result = ConState.DISCONNECTED -        try: -            conn_result = self._try_connection() -        except UnrecoverableError as except_msg: -            logger.error("FATAL: %s" % unicode(except_msg)) -            conn_result = self.status.UNRECOVERABLE -        except Exception as except_msg: -            self.error_queue.append(except_msg) -            logger.error("Failed Connection: %s" % -                         unicode(except_msg)) diff --git a/src/leap/eip/vpnwatcher.py b/src/leap/eip/vpnwatcher.py deleted file mode 100644 index 09bd5811..00000000 --- a/src/leap/eip/vpnwatcher.py +++ /dev/null @@ -1,169 +0,0 @@ -"""generic watcher object that keeps track of connection status""" -# This should be deprecated in favor of daemon mode + management -# interface. But we can leave it here for debug purposes. - - -class EIPConnectionStatus(object): -    """ -    Keep track of client (gui) and openvpn -    states. - -    These are the OpenVPN states: -    CONNECTING    -- OpenVPN's initial state. -    WAIT          -- (Client only) Waiting for initial response -                     from server. -    AUTH          -- (Client only) Authenticating with server. -    GET_CONFIG    -- (Client only) Downloading configuration options -                     from server. -    ASSIGN_IP     -- Assigning IP address to virtual network -                     interface. -    ADD_ROUTES    -- Adding routes to system. -    CONNECTED     -- Initialization Sequence Completed. -    RECONNECTING  -- A restart has occurred. -    EXITING       -- A graceful exit is in progress. - -    We add some extra states: - -    DISCONNECTED  -- GUI initial state. -    UNRECOVERABLE -- An unrecoverable error has been raised -                     while invoking openvpn service. -    """ -    CONNECTING = 1 -    WAIT = 2 -    AUTH = 3 -    GET_CONFIG = 4 -    ASSIGN_IP = 5 -    ADD_ROUTES = 6 -    CONNECTED = 7 -    RECONNECTING = 8 -    EXITING = 9 - -    # gui specific states: -    UNRECOVERABLE = 11 -    DISCONNECTED = 0 - -    def __init__(self, callbacks=None): -        """ -        EIPConnectionStatus is initialized with a tuple -        of signals to be triggered. -        :param callbacks: a tuple of (callable) observers -        :type callbacks: tuple -        """ -        # (callbacks to connect to signals in Qt-land) -        self.current = self.DISCONNECTED -        self.previous = None -        self.callbacks = callbacks - -    def get_readable_status(self): -        # XXX DRY status / labels a little bit. -        # think we'll want to i18n this. -        human_status = { -            0: 'disconnected', -            1: 'connecting', -            2: 'waiting', -            3: 'authenticating', -            4: 'getting config', -            5: 'assigning ip', -            6: 'adding routes', -            7: 'connected', -            8: 'reconnecting', -            9: 'exiting', -            11: 'unrecoverable error', -        } -        return human_status[self.current] - -    def get_state_icon(self): -        """ -        returns the high level icon -        for each fine-grain openvpn state -        """ -        connecting = (self.CONNECTING, -                      self.WAIT, -                      self.AUTH, -                      self.GET_CONFIG, -                      self.ASSIGN_IP, -                      self.ADD_ROUTES) -        connected = (self.CONNECTED,) -        disconnected = (self.DISCONNECTED, -                        self.UNRECOVERABLE) - -        # this can be made smarter, -        # but it's like it'll change, -        # so +readability. - -        if self.current in connecting: -            return "connecting" -        if self.current in connected: -            return "connected" -        if self.current in disconnected: -            return "disconnected" - -    def set_vpn_state(self, status): -        """ -        accepts a state string from the management -        interface, and sets the internal state. -        :param status: openvpn STATE (uppercase). -        :type status: str -        """ -        if hasattr(self, status): -            self.change_to(getattr(self, status)) - -    def set_current(self, to): -        """ -        setter for the 'current' property -        :param to: destination state -        :type to: int -        """ -        self.current = to - -    def change_to(self, to): -        """ -        :param to: destination state -        :type to: int -        """ -        if to == self.current: -            return -        changed = False -        from_ = self.current -        self.current = to - -        # We can add transition restrictions -        # here to ensure no transitions are -        # allowed outside the fsm. - -        self.set_current(to) -        changed = True - -        #trigger signals (as callbacks) -        #print('current state: %s' % self.current) -        if changed: -            self.previous = from_ -            if self.callbacks: -                for cb in self.callbacks: -                    if callable(cb): -                        cb(self) - - -def status_watcher(cs, line): -    """ -    a wrapper that calls to ConnectionStatus object -    :param cs: a EIPConnectionStatus instance -    :type cs: EIPConnectionStatus object -    :param line: a single line of the watched output -    :type line: str -    """ -    #print('status watcher watching') - -    # from the mullvad code, should watch for -    # things like: -    # "Initialization Sequence Completed" -    # "With Errors" -    # "Tap-Win32" - -    if "Completed" in line: -        cs.change_to(cs.CONNECTED) -        return - -    if "Initial packet from" in line: -        cs.change_to(cs.CONNECTING) -        return | 
