summaryrefslogtreecommitdiff
path: root/src/leap/bitmask/vpn/_observer.py
diff options
context:
space:
mode:
authorKali Kaneko (leap communications) <kali@leap.se>2017-02-01 00:00:20 +0100
committerKali Kaneko (leap communications) <kali@leap.se>2017-02-23 00:37:29 +0100
commit6d1d18faec5caa60c26b8245f0ab17c63d0b80d8 (patch)
tree08dbfd0e257bea0434543df6505bcc9e12acbf97 /src/leap/bitmask/vpn/_observer.py
parent8fb76310e14a5893397894c6155ac7aa4f28e483 (diff)
[refactor] split vpn control into some modules
Diffstat (limited to 'src/leap/bitmask/vpn/_observer.py')
-rw-r--r--src/leap/bitmask/vpn/_observer.py73
1 files changed, 73 insertions, 0 deletions
diff --git a/src/leap/bitmask/vpn/_observer.py b/src/leap/bitmask/vpn/_observer.py
new file mode 100644
index 0000000..1bb363d
--- /dev/null
+++ b/src/leap/bitmask/vpn/_observer.py
@@ -0,0 +1,73 @@
+from twisted.logger import Logger
+
+logger = Logger()
+
+
+class VPNObserver(object):
+ """
+ A class containing different patterns in the openvpn output that
+ we can react upon.
+ """
+
+ _events = {
+ 'NETWORK_UNREACHABLE': (
+ 'Network is unreachable (code=101)',),
+ 'PROCESS_RESTART_TLS': (
+ "SIGTERM[soft,tls-error]",),
+ 'PROCESS_RESTART_PING': (
+ "SIGTERM[soft,ping-restart]",),
+ 'INITIALIZATION_COMPLETED': (
+ "Initialization Sequence Completed",),
+ }
+
+ def __init__(self, signaler=None):
+ self._signaler = signaler
+
+ def watch(self, line):
+ """
+ Inspects line searching for the different patterns. If a match
+ is found, try to emit the corresponding signal.
+
+ :param line: a line of openvpn output
+ :type line: str
+ """
+ chained_iter = chain(*[
+ zip(repeat(key, len(l)), l)
+ for key, l in self._events.iteritems()])
+ for event, pattern in chained_iter:
+ if pattern in line:
+ logger.debug('pattern matched! %s' % pattern)
+ break
+ else:
+ return
+
+ sig = self._get_signal(event)
+ if sig is not None:
+ if self._signaler is not None:
+ self._signaler.signal(sig)
+ return
+ else:
+ logger.debug('We got %s event from openvpn output but we could '
+ 'not find a matching signal for it.' % event)
+
+ def _get_signal(self, event):
+ """
+ Tries to get the matching signal from the eip signals
+ objects based on the name of the passed event (in lowercase)
+
+ :param event: the name of the event that we want to get a signal for
+ :type event: str
+ :returns: a Signaler signal or None
+ :rtype: str or None
+ """
+ if self._signaler is None:
+ return
+ sig = self._signaler
+ signals = {
+ "network_unreachable": sig.eip_network_unreachable,
+ "process_restart_tls": sig.eip_process_restart_tls,
+ "process_restart_ping": sig.eip_process_restart_ping,
+ "initialization_completed": sig.eip_connected
+ }
+ return signals.get(event.lower())
+