summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKali Kaneko <kali@leap.se>2013-06-24 02:57:26 +0900
committerKali Kaneko <kali@leap.se>2013-06-24 04:10:20 +0900
commit19c90e02a65d1d6fe30e6915cd2a9440878aef83 (patch)
tree54dec824b6951ec81c7ddb414948a11294d9729d
parent63bc283c90a80ddc030e24fcc38c533b1e7c551d (diff)
Improve OpenVPN Process Control
* Disable toggle button until we get "connected" status. #2956 * Catch abnormal termination and update UI accordingly. #2890
-rw-r--r--src/leap/gui/mainwindow.py54
-rw-r--r--src/leap/gui/statuspanel.py1
-rw-r--r--src/leap/gui/ui/statuspanel.ui3
-rw-r--r--src/leap/services/eip/vpnprocess.py30
4 files changed, 78 insertions, 10 deletions
diff --git a/src/leap/gui/mainwindow.py b/src/leap/gui/mainwindow.py
index b0bf8a44..94343292 100644
--- a/src/leap/gui/mainwindow.py
+++ b/src/leap/gui/mainwindow.py
@@ -90,6 +90,9 @@ class MainWindow(QtGui.QMainWindow):
new_updates = QtCore.Signal(object)
raise_window = QtCore.Signal([])
+ # We use this flag to detect abnormal terminations
+ user_stopped_eip = False
+
def __init__(self, quit_callback,
standalone=False, bypass_checks=False):
"""
@@ -951,6 +954,7 @@ class MainWindow(QtGui.QMainWindow):
Starts EIP
"""
self._status_panel.eip_pre_up()
+ self.user_stopped_eip = False
provider_config = self._get_best_provider_config()
try:
@@ -1007,8 +1011,6 @@ class MainWindow(QtGui.QMainWindow):
else:
self._already_started_eip = True
- #self._status_panel.set_startstop_enabled(True)
-
def _set_eipstatus_off(self):
"""
Sets eip status to off
@@ -1016,11 +1018,16 @@ class MainWindow(QtGui.QMainWindow):
self._status_panel.set_eip_status(self.tr("OFF"), error=True)
self._status_panel.set_startstop_enabled(True)
- def _stop_eip(self):
+ def _stop_eip(self, abnormal=False):
"""
Stops vpn process and makes gui adjustments to reflect
the change of state.
+
+ :param abnormal: whether this was an abnormal termination.
+ :type abnormal: bool
+ ""
"""
+ self.user_stopped_eip = True
self._vpn.terminate()
self._status_panel.set_eip_status(self.tr("OFF"))
@@ -1036,6 +1043,8 @@ class MainWindow(QtGui.QMainWindow):
self._status_panel.set_provider(
"%s@%s" % (self._logged_user,
self._get_best_provider_config().get_domain()))
+ if abnormal:
+ self._status_panel.set_startstop_enabled(True)
def _get_best_provider_config(self):
"""
@@ -1188,10 +1197,43 @@ class MainWindow(QtGui.QMainWindow):
self._vpn.process_finished
Triggered when the EIP/VPN process finishes to set the UI
- accordingly
+ accordingly.
"""
- logger.debug("Finished VPN with exitCode %s" % (exitCode,))
- self._stop_eip()
+ logger.info("VPN process finished with exitCode %s..."
+ % (exitCode,))
+
+ # Ideally we would have the right exit code here,
+ # but the use of different wrappers (pkexec, cocoasudo) swallows
+ # the openvpn exit code so we get zero exit in some cases where we
+ # shouldn't. As a workaround we just use a flag to indicate
+ # a purposeful switch off, and mark everything else as unexpected.
+
+ # In the near future we should trigger a native notification from here,
+ # since the user really really wants to know she is unprotected asap.
+ # And the right thing to do will be to fail-close.
+
+ # TODO we should have a way of parsing the latest lines in the vpn
+ # log buffer so we can have a more precise idea of which type
+ # of error did we have (server side, local problem, etc)
+ abnormal = True
+
+ # XXX check if these exitCodes are pkexec/cocoasudo specific
+ if exitCode in (126, 127):
+ self._status_panel.set_global_status(
+ self.tr("Encrypted Internet could not be launched "
+ "because you did not authenticate properly."),
+ error=True)
+ self._vpn.killit()
+ elif exitCode != 0 or not self.user_stopped_eip:
+ self._status_panel.set_global_status(
+ self.tr("Encrypted Internet finished in an "
+ "unexpected manner!"), error=True)
+ else:
+ abnormal = False
+ if exitCode == 0:
+ # XXX remove this warning after I fix cocoasudo.
+ logger.warning("The above exit code MIGHT BE WRONG.")
+ self._stop_eip(abnormal)
def _on_raise_window_event(self, req):
"""
diff --git a/src/leap/gui/statuspanel.py b/src/leap/gui/statuspanel.py
index de913f09..3e5a5093 100644
--- a/src/leap/gui/statuspanel.py
+++ b/src/leap/gui/statuspanel.py
@@ -171,7 +171,6 @@ class StatusPanelWidget(QtGui.QWidget):
"""
self.hide_status_box()
self.set_startstop_enabled(False)
- logger.debug('disabling buton.....................')
def eip_started(self):
"""
diff --git a/src/leap/gui/ui/statuspanel.ui b/src/leap/gui/ui/statuspanel.ui
index 502ba78a..1a2c77ad 100644
--- a/src/leap/gui/ui/statuspanel.ui
+++ b/src/leap/gui/ui/statuspanel.ui
@@ -208,6 +208,9 @@
<property name="text">
<string>...</string>
</property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
</widget>
</item>
</layout>
diff --git a/src/leap/services/eip/vpnprocess.py b/src/leap/services/eip/vpnprocess.py
index d9fa85a6..0ec56ae7 100644
--- a/src/leap/services/eip/vpnprocess.py
+++ b/src/leap/services/eip/vpnprocess.py
@@ -142,6 +142,14 @@ class VPN(object):
# after running out of patience, we try a killProcess
logger.debug("Process did not died. Sending a SIGKILL.")
+ self.killit()
+
+ def killit(self):
+ """
+ Sends a kill signal to the process.
+ """
+ self._stop_pollers()
+ self._vpnproc.aborted = True
self._vpnproc.killProcess()
def terminate(self, shutdown=False):
@@ -225,11 +233,20 @@ class VPNManager(object):
self._reactor = reactor
self._tn = None
self._qtsigs = qtsigs
+ self._aborted = False
@property
def qtsigs(self):
return self._qtsigs
+ @property
+ def aborted(self):
+ return self._aborted
+
+ @aborted.setter
+ def aborted(self, value):
+ self._aborted = value
+
def _seek_to_eof(self):
"""
Read as much as available. Position seek pointer to end of stream
@@ -378,7 +395,7 @@ class VPNManager(object):
"""
# TODO decide about putting a max_lim to retries and signaling
# an error.
- if not self.is_connected():
+ if not self.aborted and not self.is_connected():
self.connect_to_management(self._socket_host, self._socket_port)
self._reactor.callLater(
self.CONNECTION_RETRY_TIME,
@@ -611,6 +628,7 @@ class VPNProcess(protocol.ProcessProtocol, VPNManager):
self._last_state = None
self._last_status = None
+ self._alive = False
# processProtocol methods
@@ -620,6 +638,8 @@ class VPNProcess(protocol.ProcessProtocol, VPNManager):
.. seeAlso: `http://twistedmatrix.com/documents/13.0.0/api/twisted.internet.protocol.ProcessProtocol.html` # noqa
"""
+ self._alive = True
+ self.aborted = False
self.try_to_connect_to_management()
def outReceived(self, data):
@@ -643,6 +663,8 @@ class VPNProcess(protocol.ProcessProtocol, VPNManager):
exit_code = reason.value.exitCode
if isinstance(exit_code, int):
logger.debug("processExited, status %d" % (exit_code,))
+ self.qtsigs.process_finished.emit(exit_code)
+ self._alive = False
def processEnded(self, reason):
"""
@@ -661,13 +683,15 @@ class VPNProcess(protocol.ProcessProtocol, VPNManager):
"""
Polls connection status.
"""
- self.get_status()
+ if self._alive:
+ self.get_status()
def pollState(self):
"""
Polls connection state.
"""
- self.get_state()
+ if self._alive:
+ self.get_state()
# launcher