summaryrefslogtreecommitdiff
path: root/src/leap/bitmask/vpn/_control.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/leap/bitmask/vpn/_control.py')
-rw-r--r--src/leap/bitmask/vpn/_control.py185
1 files changed, 0 insertions, 185 deletions
diff --git a/src/leap/bitmask/vpn/_control.py b/src/leap/bitmask/vpn/_control.py
deleted file mode 100644
index ff39db8d..00000000
--- a/src/leap/bitmask/vpn/_control.py
+++ /dev/null
@@ -1,185 +0,0 @@
-import os
-
-from twisted.internet import reactor, defer
-from twisted.logger import Logger
-
-from .process import VPNProcess
-from .constants import IS_LINUX
-
-
-# TODO
-# TODO merge these classes with service.
-# [ ] register change state listener
-# emit_async(catalog.VPN_STATUS_CHANGED)
-# [ ] catch ping-restart
-# 'NETWORK_UNREACHABLE': (
-# 'Network is unreachable (code=101)',),
-# 'PROCESS_RESTART_TLS': (
-# "SIGTERM[soft,tls-error]",),
-
-
-class VPNControl(object):
-
- """
- This is the high-level object that the service knows about.
- It exposes the start and terminate methods.
-
- On start, it spawns a VPNProcess instance that will use a vpnlauncher
- suited for the running platform and connect to the management interface
- opened by the openvpn process, executing commands over that interface on
- demand.
- """
-
- TERMINATE_MAXTRIES = 10
- TERMINATE_WAIT = 1 # secs
- RESTART_WAIT = 2 # secs
-
- log = Logger()
-
- def __init__(self, remotes, vpnconfig,
- providerconfig, socket_host, socket_port):
- self._vpnproc = None
- self._user_stopped = False
-
- self._remotes = remotes
- self._vpnconfig = vpnconfig
- self._providerconfig = providerconfig
- self._host = socket_host
- self._port = socket_port
-
- def start(self):
- self.log.debug('VPN: start')
-
- self._user_stopped = False
-
- args = [self._vpnconfig, self._providerconfig, self._host,
- self._port]
- kwargs = {'openvpn_verb': 4, 'remotes': self._remotes,
- 'restartfun': self.restart}
-
- vpnproc = VPNProcess(*args, **kwargs)
-
- # TODO -- restore
- # if get_openvpn_process():
- # self.log.info(
- # 'Another vpn process is running. Will try to stop it.')
- # vpnproc.stop_if_already_running()
-
- try:
- vpnproc.preUp()
- except Exception as e:
- self.log.error('Error on vpn pre-up {0!r}'.format(e))
- raise
- try:
- cmd = vpnproc.getCommand()
- except Exception as e:
- self.log.error(
- 'Error while getting vpn command... {0!r}'.format(e))
- raise
-
- env = os.environ
-
- try:
- runningproc = reactor.spawnProcess(vpnproc, cmd[0], cmd, env)
- except Exception as e:
- self.log.error(
- 'Error while spawning vpn process... {0!r}'.format(e))
- return False
-
- # TODO get pid from management instead
- vpnproc.pid = runningproc.pid
- self._vpnproc = vpnproc
-
- return True
-
- @defer.inlineCallbacks
- def restart(self):
- yield self.stop(shutdown=False, restart=True)
- reactor.callLater(
- self.RESTART_WAIT, self.start)
-
- def stop(self, shutdown=False, restart=False):
- """
- Stops the openvpn subprocess.
-
- Attempts to send a SIGTERM first, and after a timeout
- it sends a SIGKILL.
-
- :param shutdown: whether this is the final shutdown
- :type shutdown: bool
- :param restart: whether this stop is part of a hard restart.
- :type restart: bool
- """
- # We assume that the only valid stops are initiated
- # by an user action, not hard restarts
- self._user_stopped = not restart
- if self._vpnproc is not None:
- self._vpnproc.restarting = restart
-
- try:
- if self._vpnproc is not None:
- self._vpnproc.preDown()
- except Exception as e:
- self.log.error('Error on vpn pre-down {0!r}'.format(e))
- raise
-
- d = defer.succeed(True)
- if IS_LINUX:
- # TODO factor this out to a linux-only launcher mechanism.
- # First we try to be polite and send a SIGTERM...
- if self._vpnproc is not None:
- self._sentterm = True
- self._vpnproc.terminate()
-
- # we trigger a countdown to be unpolite
- # if strictly needed.
- d = defer.Deferred()
- reactor.callLater(
- self.TERMINATE_WAIT, self._kill_if_left_alive, d)
- return d
-
- # TODO -- remove indirection
- @property
- def status(self):
- if not self._vpnproc:
- return {'status': 'off', 'error': None}
- return self._vpnproc.status
-
- @property
- def traffic_status(self):
- return self._vpnproc.traffic_status
-
- def _killit(self):
- if self._vpnproc is None:
- self.log.debug("There's no vpn process running to kill.")
- else:
- self._vpnproc.aborted = True
- self._vpnproc.kill()
-
- def _kill_if_left_alive(self, deferred, tries=0):
- """
- Check if the process is still alive, and send a
- SIGKILL after a timeout period.
-
- :param tries: counter of tries, used in recursion
- :type tries: int
- """
- if tries < self.TERMINATE_MAXTRIES:
- if self._vpnproc.transport.pid is None:
- deferred.callback(True)
- return
- else:
- self.log.debug('Process did not die, waiting...')
-
- tries += 1
- reactor.callLater(self.TERMINATE_WAIT,
- self._kill_if_left_alive, deferred, tries)
- return
-
- # after running out of patience, we try a killProcess
- self.log.debug('Process did not die. Sending a SIGKILL.')
- try:
- self._killit()
- except OSError:
- self.log.error('Could not kill process!')
- deferred.callback(True)