From d4f013fee611299aea7f8cfff0377ba8646ba17d Mon Sep 17 00:00:00 2001
From: Ruben Pollan <meskio@sindominio.net>
Date: Wed, 13 Jun 2018 15:02:23 +0200
Subject: [PATCH] [feat] do a proper openvpn process management

---
 bitmask_go/launcher_linux.go | 43 +++++++++++++++++++++++++++++++-----
 bitmask_go/main.go           |  4 +++-
 bitmask_go/vpn.go            |  8 +++----
 3 files changed, 44 insertions(+), 11 deletions(-)

diff --git a/bitmask_go/launcher_linux.go b/bitmask_go/launcher_linux.go
index 05398a68..6a1407cc 100644
--- a/bitmask_go/launcher_linux.go
+++ b/bitmask_go/launcher_linux.go
@@ -34,32 +34,63 @@ var bitmaskRootPaths = []string{
 	"/snap/bin/riseup-vpn.bitmask-root",
 }
 
-func openvpnStart(flags ...string) error {
+type launcher struct {
+	openvpnCh chan []string
+}
+
+func newLauncher() *launcher {
+	l := launcher{make(chan []string, 1)}
+	go l.openvpnRunner()
+	return &l
+}
+
+func (l *launcher) openvpnStart(flags ...string) error {
 	log.Println("openvpn start: ", flags)
 	arg := []string{"openvpn", "start", getOpenvpnPath()}
 	arg = append(arg, flags...)
-	// TODO: check errors somehow instead of fire and forget
-	go runBitmaskRoot(arg...)
+	l.openvpnCh <- arg
 	return nil
 }
 
-func openvpnStop() error {
+func (l *launcher) openvpnStop() error {
+	l.openvpnCh <- nil
 	log.Println("openvpn stop")
 	return runBitmaskRoot("openvpn", "stop")
 }
 
-func firewallStart(gateways []string) error {
+func (l *launcher) firewallStart(gateways []string) error {
 	log.Println("firewall start")
 	arg := []string{"firewall", "start"}
 	arg = append(arg, gateways...)
 	return runBitmaskRoot(arg...)
 }
 
-func firewallStop() error {
+func (l *launcher) firewallStop() error {
 	log.Println("firewall stop")
 	return runBitmaskRoot("firewall", "stop")
 }
 
+func (l *launcher) openvpnRunner(arg ...string) {
+	running := false
+	runOpenvpn := func(arg []string) {
+		for running {
+			err := runBitmaskRoot(arg...)
+			if err != nil {
+				log.Printf("An error ocurred running openvpn: %v", err)
+			}
+		}
+	}
+
+	for arg := range l.openvpnCh {
+		if arg == nil {
+			running = false
+		} else {
+			running = true
+			go runOpenvpn(arg)
+		}
+	}
+}
+
 func runBitmaskRoot(arg ...string) error {
 	bitmaskRoot, err := bitmaskRootPath()
 	if err != nil {
diff --git a/bitmask_go/main.go b/bitmask_go/main.go
index 49f803a6..6b60d43c 100644
--- a/bitmask_go/main.go
+++ b/bitmask_go/main.go
@@ -28,6 +28,7 @@ type Bitmask struct {
 	tempdir          string
 	statusCh         chan string
 	managementClient *openvpn.MgmtClient
+	launch           *launcher
 }
 
 // Init the connection to bitmask
@@ -37,7 +38,8 @@ func Init() (*Bitmask, error) {
 	if err != nil {
 		return nil, err
 	}
-	b := Bitmask{tempdir, statusCh, nil}
+	launch := newLauncher()
+	b := Bitmask{tempdir, statusCh, nil, launch}
 
 	err = b.StopVPN()
 	if err != nil {
diff --git a/bitmask_go/vpn.go b/bitmask_go/vpn.go
index 09adcf08..2e693682 100644
--- a/bitmask_go/vpn.go
+++ b/bitmask_go/vpn.go
@@ -33,7 +33,7 @@ var gateways = []string{
 // StartVPN for provider
 func (b *Bitmask) StartVPN(provider string) error {
 	// TODO: openvpn args are hardcoded
-	err := firewallStart(gateways)
+	err := b.launch.firewallStart(gateways)
 	if err != nil {
 		return err
 	}
@@ -44,16 +44,16 @@ func (b *Bitmask) StartVPN(provider string) error {
 	}
 	certPemPath := b.getCertPemPath()
 	arg = append(arg, "--client", "--tls-client", "--remote-cert-tls", "server", "--tls-cipher", "DHE-RSA-AES128-SHA", "--cipher", "AES-128-CBC", "--tun-ipv6", "--auth", "SHA1", "--keepalive", "10 30", "--management-client", "--management", openvpnManagementAddr+" "+openvpnManagementPort, "--ca", b.getCaCertPath(), "--cert", certPemPath, "--key", certPemPath)
-	return openvpnStart(arg...)
+	return b.launch.openvpnStart(arg...)
 }
 
 // StopVPN or cancel
 func (b *Bitmask) StopVPN() error {
-	err := firewallStop()
+	err := b.launch.firewallStop()
 	if err != nil {
 		return err
 	}
-	return openvpnStop()
+	return b.launch.openvpnStop()
 }
 
 // GetStatus returns the VPN status
-- 
GitLab