summaryrefslogtreecommitdiff
path: root/src/leap
diff options
context:
space:
mode:
authorKali Kaneko (leap communications) <kali@leap.se>2017-06-15 14:55:56 +0200
committerKali Kaneko (leap communications) <kali@leap.se>2017-06-16 19:21:05 +0200
commit3eedb42c4bf8b362b4a123154f50a5911de1a08f (patch)
tree1f9d5a1e658ad950445240c2d5c5f21a0787bbbe /src/leap
parent478d294e4a7809639123806cbe9e43fdc8e55a1a (diff)
[feat] process logs through management interface
Diffstat (limited to 'src/leap')
-rw-r--r--src/leap/bitmask/vpn/_management.py30
-rw-r--r--src/leap/bitmask/vpn/_status.py2
-rw-r--r--src/leap/bitmask/vpn/process.py33
3 files changed, 41 insertions, 24 deletions
diff --git a/src/leap/bitmask/vpn/_management.py b/src/leap/bitmask/vpn/_management.py
index 16bb86f..26050be 100644
--- a/src/leap/bitmask/vpn/_management.py
+++ b/src/leap/bitmask/vpn/_management.py
@@ -2,7 +2,7 @@ import os
import shutil
import socket
-from twisted.internet import defer, reactor
+from twisted.internet import reactor
from twisted.logger import Logger
import psutil
@@ -56,6 +56,7 @@ class VPNManagement(object):
self._last_state = None
self._last_status = None
self._status = None
+ self._logs = {}
def set_connection(self, host, port):
"""
@@ -68,6 +69,9 @@ class VPNManagement(object):
self._host = host
self._port = port
+ def set_watcher(self, watcher):
+ self._watcher = watcher
+
def is_connected(self):
return bool(self._tn)
@@ -112,6 +116,23 @@ class VPNManagement(object):
self.CONNECTION_RETRY_TIME,
self.connect_retry, retry + 1)
+ def process_log(self):
+ if not self._watcher:
+ return
+
+ lines = self._send_command('log 20')
+ for line in lines:
+ try:
+ splitted = line.split(',')
+ ts = splitted[0]
+ msg = ','.join(splitted[2:])
+ if ts not in self._logs:
+ self._watcher.watch(msg)
+ self.log.info('VPN: %s' % msg)
+ self._logs[ts] = msg
+ except Exception:
+ pass
+
def _seek_to_eof(self):
"""
Read as much as available. Position seek pointer to end of stream
@@ -172,7 +193,6 @@ class VPNManagement(object):
self._tn.get_socket().close()
self._tn = None
-
def _parse_state_and_notify(self, output):
"""
Parses the output of the state command, and trigger a state transition
@@ -183,7 +203,6 @@ class VPNManagement(object):
:type output: list
"""
for line in output:
- print "PARSING", line
stripped = line.strip()
if stripped == "END":
continue
@@ -199,8 +218,6 @@ class VPNManagement(object):
if state != self._last_state:
# XXX this status object is the vpn status observer
if self._status:
- # XXX DEBUG -----------------------
- print "SETTING STATUS", state
self._status.set_status(state, None)
self._last_state = state
@@ -213,13 +230,11 @@ class VPNManagement(object):
as its output
:type output: list
"""
- print "PARSING STATUS", output
tun_tap_read = ""
tun_tap_write = ""
for line in output:
stripped = line.strip()
- print "LINE", stripped
if stripped.endswith("STATISTICS") or stripped == "END":
continue
parts = stripped.split(",")
@@ -245,7 +260,6 @@ class VPNManagement(object):
traffic_status = (tun_tap_read, tun_tap_write)
if traffic_status != self._last_status:
- # XXX this status object is the vpn status observer
if self._status:
self._status.set_traffic_status(traffic_status)
self._last_status = traffic_status
diff --git a/src/leap/bitmask/vpn/_status.py b/src/leap/bitmask/vpn/_status.py
index 7cd4896..6bd9c7c 100644
--- a/src/leap/bitmask/vpn/_status.py
+++ b/src/leap/bitmask/vpn/_status.py
@@ -1,8 +1,8 @@
from itertools import chain, repeat
-from ._human import bytes2human
from leap.common.events import catalog, emit_async
+from leap.bitmask.vpn._human import bytes2human
# TODO implement a more explicit state machine
# TODO check good transitions
diff --git a/src/leap/bitmask/vpn/process.py b/src/leap/bitmask/vpn/process.py
index 34548bf..9b23526 100644
--- a/src/leap/bitmask/vpn/process.py
+++ b/src/leap/bitmask/vpn/process.py
@@ -94,8 +94,9 @@ class _VPNProcess(protocol.ProcessProtocol, _management.VPNManagement):
self._restartfun = restartfun
self._status = _status.VPNStatus()
- self.restarting = False
+ self.set_watcher(self._status)
+ self.restarting = False
self._remotes = remotes
@property
@@ -115,8 +116,6 @@ class _VPNProcess(protocol.ProcessProtocol, _management.VPNManagement):
def connectionMade(self):
"""
Called when the connection is made.
-
- .. seeAlso: `http://twistedmatrix.com/documents/13.0.0/api/twisted.internet.protocol.ProcessProtocol.html` # noqa
"""
self._alive = True
self.aborted = False
@@ -125,23 +124,25 @@ class _VPNProcess(protocol.ProcessProtocol, _management.VPNManagement):
def outReceived(self, data):
"""
Called when new data is available on stdout.
+ We only use this to drive the status state machine in linux, OSX uses
+ the management interface.
:param data: the data read on stdout
-
- .. seeAlso: `http://twistedmatrix.com/documents/13.0.0/api/twisted.internet.protocol.ProcessProtocol.html` # noqa
"""
- # truncate the newline
- line = data[:-1]
- if 'SIGTERM[soft,ping-restart]' in line:
- self.restarting = True
- self.log.info(line)
- self._status.watch(line)
+ # TODO deprecate, use log through management interface too.
+
+ if IS_LINUX:
+ # truncate the newline
+ line = data[:-1]
+ # TODO -- internalize this into _status!!! so that it can be shared
+ if 'SIGTERM[soft,ping-restart]' in line:
+ self.restarting = True
+ self.log.info(line)
+ # self._status.watch(line)
def processExited(self, failure):
"""
Called when the child process exits.
-
- .. seeAlso: `http://twistedmatrix.com/documents/13.0.0/api/twisted.internet.protocol.ProcessProtocol.html` # noqa
"""
err = failure.trap(
internet_error.ProcessDone, internet_error.ProcessTerminated)
@@ -162,8 +163,6 @@ class _VPNProcess(protocol.ProcessProtocol, _management.VPNManagement):
"""
Called when the child process exits and all file descriptors associated
with it have been closed.
-
- .. seeAlso: `http://twistedmatrix.com/documents/13.0.0/api/twisted.internet.protocol.ProcessProtocol.html` # noqa
"""
exit_code = reason.value.exitCode
if isinstance(exit_code, int):
@@ -188,6 +187,10 @@ class _VPNProcess(protocol.ProcessProtocol, _management.VPNManagement):
if self._alive:
self.get_state()
+ def pollLog(self):
+ if self._alive:
+ self.process_log()
+
# launcher
def preUp(self):