diff options
| -rw-r--r-- | src/leap/bitmask/vpn/_status.py | 79 | 
1 files changed, 38 insertions, 41 deletions
| diff --git a/src/leap/bitmask/vpn/_status.py b/src/leap/bitmask/vpn/_status.py index c408883d..7cd48968 100644 --- a/src/leap/bitmask/vpn/_status.py +++ b/src/leap/bitmask/vpn/_status.py @@ -4,13 +4,16 @@ from ._human import bytes2human  from leap.common.events import catalog, emit_async -# TODO implement a state machine in this class +# TODO implement a more explicit state machine +# TODO check good transitions +# TODO check valid states  class VPNStatus(object):      """      A class containing different patterns in the openvpn output that -    we can react upon. +    we can react upon. The patterns drive an internal state machine that can be +    queried through the ``status`` property.      """      _events = { @@ -21,25 +24,31 @@ class VPNStatus(object):          'INITIALIZATION_COMPLETED': (              "Initialization Sequence Completed",),      } +    _STARTING = ('AUTH', 'WAIT', 'CONNECTING', 'GET_CONFIG', +                 'ASSIGN_IP', 'ADD_ROUTES', 'RECONNECTING') +    _STOPPING = ("EXITING",) +    _CONNECTED = ("CONNECTED",)      def __init__(self):          self._status = 'off'          self.errcode = None          self._traffic_down = None          self._traffic_up = None - -    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(*[ +        self._chained_iter = chain(*[              zip(repeat(key, len(l)), l)              for key, l in self._events.iteritems()]) -        for event, pattern in chained_iter: + +    def _status_codes(self, event): + +        _table = { +            "network_unreachable": ('off', 'network unreachable'), +            "process_restart_tls": ('starting', 'restart tls'), +            "initialization_completed": ('on', None) +        } +        return _table.get(event.lower()) + +    def watch(self, line): +        for event, pattern in self._chained_iter:              if pattern in line:                  break          else: @@ -48,24 +57,27 @@ class VPNStatus(object):          status, errcode = self._status_codes(event)          self.set_status(status, errcode) +    @property +    def status(self): +        status = self.get_traffic_status() +        status.update({ +            'status': self._status, +            'error': self.errcode +        }) +        return status +      def set_status(self, status, errcode): -        if status in ("AUTH", "WAIT", "CONNECTING", "GET_CONFIG", -                      "ASSIGN_IP", "ADD_ROUTES", "RECONNECTING"): +        if status in self._STARTING:              status = "starting" -        elif status == "EXITING": +        elif status in self._STOPPING:              status = "stopping" -        elif status == "CONNECTED": +        elif status in self._CONNECTED:              status = "on"          self._status = status          self.errcode = errcode          emit_async(catalog.VPN_STATUS_CHANGED) -    def set_traffic_status(self, status): -        up, down = status -        self._traffic_up = up -        self._traffic_down = down -      def get_traffic_status(self):          down = None          up = None @@ -75,22 +87,7 @@ class VPNStatus(object):              up = bytes2human(self._traffic_up)          return {'down': down, 'up': up} -    @property -    def status(self): -        status = self.get_traffic_status() -        status.update({ -            'status': self._status, -            'error': self.errcode -        }) -        return status - -    def _status_codes(self, event): -        # TODO check good transitions -        # TODO check valid states - -        _table = { -            "network_unreachable": ('off', 'network unreachable'), -            "process_restart_tls": ('starting', 'restart tls'), -            "initialization_completed": ('on', None) -        } -        return _table.get(event.lower()) +    def set_traffic_status(self, status): +        up, down = status +        self._traffic_up = up +        self._traffic_down = down | 
