summaryrefslogtreecommitdiff
path: root/src/leap/bitmask/vpn/_status.py
blob: 11d564fa48a935fa5e0b2ae631632ca5d65b1fd8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
from itertools import chain, repeat
from twisted.logger import Logger

logger = Logger()


# TODO implement a state machine in this class


class VPNStatus(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):
        self.status = 'OFFLINE'
        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(*[
            zip(repeat(key, len(l)), l)
            for key, l in self._events.iteritems()])
        for event, pattern in chained_iter:
            if pattern in line:
                break
        else:
            return

        status, errcode = self._status_codes(event)
        self.set_status(status, errcode)


    def set_status(self, status, errcode):
        self.status = status
        self.errcode = errcode

    def set_traffic_status(self, status):
        down, up = status
        self._traffic_up = up
        self._traffic_down = down

    def get_traffic_status(self):
        # XXX return Human readable too
        return {'down': self._traffic_down,
                'up': self._traffic_up}

    def _status_codes(self, event):
        # TODO check good transitions
        # TODO check valid states

        _table = {
            "network_unreachable": ('OFFLINE', 'network unreachable'),
            "process_restart_tls": ('RESTARTING', 'restart tls'),
            "process_restart_ping": ('CONNECTING', None),
            "initialization_completed": ('ONLINE', None)
        }
        return _table.get(event.lower())