import time from PyQt4 import QtCore from leap.baseapp.dialogs import ErrorDialog from leap.baseapp import constants from leap.eip import exceptions as eip_exceptions from leap.eip.eipconnection import EIPConnection class EIPConductorApp(object): """ initializes an instance of EIPConnection, gathers errors, and passes status-change signals from Qt land along to the conductor. Connects the eip connect/disconnect logic to the switches in the app (buttons/menu items). """ def __init__(self, *args, **kwargs): opts = kwargs.pop('opts') config_file = getattr(opts, 'config_file', None) self.eip_service_started = False # conductor (eip connection) is in charge of all # vpn-related configuration / monitoring. # we pass a tuple of signals that will be # triggered when status changes. self.conductor = EIPConnection( watcher_cb=self.newLogLine.emit, config_file=config_file, status_signals=(self.statusChange.emit, ), debug=self.debugmode) # XXX remove skip download when sample service is ready self.conductor.run_checks(skip_download=True) self.error_check() # XXX should receive "ready" signal # it is called from LeapWindow now. #if self.conductor.autostart: #self.start_or_stopVPN() if self.debugmode: self.startStopButton.clicked.connect( lambda: self.start_or_stopVPN()) def error_check(self): # XXX refactor (by #504) if self.conductor.missing_definition is True: dialog = ErrorDialog() dialog.criticalMessage( 'The default ' 'definition.json file cannot be found', 'error') if self.conductor.missing_provider is True: dialog = ErrorDialog() dialog.criticalMessage( 'Missing provider. Add a remote_ip entry ' 'under section [provider] in eip.cfg', 'error') if self.conductor.missing_vpn_keyfile is True: dialog = ErrorDialog() dialog.criticalMessage( 'Could not find the vpn keys file', 'error') # ... btw, review pending. # os.kill of subprocess fails if we have # some of this errors. if self.conductor.bad_provider is True: dialog = ErrorDialog() dialog.criticalMessage( 'Bad provider entry. Check that remote_ip entry ' 'has an IP under section [provider] in eip.cfg', 'error') if self.conductor.bad_keyfile_perms is True: dialog = ErrorDialog() dialog.criticalMessage( 'The vpn keys file has bad permissions', 'error') if self.conductor.missing_auth_agent is True: dialog = ErrorDialog() dialog.warningMessage( 'We could not find any authentication ' 'agent in your system.
' 'Make sure you have ' 'polkit-gnome-authentication-agent-1 ' 'running and try again.', 'error') if self.conductor.missing_pkexec is True: dialog = ErrorDialog() dialog.warningMessage( 'We could not find pkexec in your ' 'system.
Do you want to try ' 'setuid workaround? ' '(DOES NOTHING YET)', 'error') @QtCore.pyqtSlot() def statusUpdate(self): """ polls status and updates ui with real time info about transferred bytes / connection state. right now is triggered by a timer tick (timer controlled by StatusAwareTrayIcon class) """ # TODO I guess it's too expensive to poll # continously. move to signal events instead. # (i.e., subscribe to connection status changes # from openvpn manager) if not self.eip_service_started: return if self.conductor.with_errors: #XXX how to wait on pkexec??? #something better that this workaround, plz!! time.sleep(2) print('errors. disconnect.') self.start_or_stopVPN() # is stop state = self.conductor.poll_connection_state() if not state: return ts, con_status, ok, ip, remote = state self.set_statusbarMessage(con_status) self.setIconToolTip() ts = time.strftime("%a %b %d %X", ts) if self.debugmode: self.updateTS.setText(ts) self.status_label.setText(con_status) self.ip_label.setText(ip) self.remote_label.setText(remote) # status i/o status = self.conductor.get_status_io() if status and self.debugmode: #XXX move this to systray menu indicators ts, (tun_read, tun_write, tcp_read, tcp_write, auth_read) = status ts = time.strftime("%a %b %d %X", ts) self.updateTS.setText(ts) self.tun_read_bytes.setText(tun_read) self.tun_write_bytes.setText(tun_write) @QtCore.pyqtSlot() def start_or_stopVPN(self): """ stub for running child process with vpn """ if self.eip_service_started is False: try: self.conductor.connect() # XXX move this to error queue except eip_exceptions.EIPNoCommandError: dialog = ErrorDialog() dialog.warningMessage( 'No suitable openvpn command found. ' '
(Might be a permissions problem)', 'error') if self.debugmode: self.startStopButton.setText('&Disconnect') self.eip_service_started = True # XXX what is optimum polling interval? # too little is overkill, too much # will miss transition states.. # XXX decouple! (timer is init by icons class). # should bring it here? # to its own class? self.timer.start(constants.TIMER_MILLISECONDS) return if self.eip_service_started is True: self.conductor.disconnect() if self.debugmode: self.startStopButton.setText('&Connect') self.eip_service_started = False self.timer.stop() return