diff options
author | kali kaneko (leap communications) <kali@leap.se> | 2020-05-29 22:09:15 +0200 |
---|---|---|
committer | kali kaneko (leap communications) <kali@leap.se> | 2020-06-12 20:02:30 +0200 |
commit | 719413cad922e1d34f2ea495bae0165cae53b22f (patch) | |
tree | 2018091e2263b4bd69611a4f284e4d2febf36ec9 /pkg/systray2 | |
parent | 42593eb08464ace7be4d5dd088a48720591575c3 (diff) |
[refactor] copy over systray to new package
- delete gtk systray module
Diffstat (limited to 'pkg/systray2')
-rw-r--r-- | pkg/systray2/config.go | 108 | ||||
-rw-r--r-- | pkg/systray2/pid.go | 99 | ||||
-rw-r--r-- | pkg/systray2/pid_test.go | 21 | ||||
-rw-r--r-- | pkg/systray2/run.go | 104 |
4 files changed, 332 insertions, 0 deletions
diff --git a/pkg/systray2/config.go b/pkg/systray2/config.go new file mode 100644 index 0000000..75a4a98 --- /dev/null +++ b/pkg/systray2/config.go @@ -0,0 +1,108 @@ +// Copyright (C) 2018 LEAP +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +package systray + +import ( + "encoding/json" + "os" + "path" + "time" + + "0xacab.org/leap/bitmask-vpn/pkg/config" + "golang.org/x/text/message" +) + +const ( + oneDay = time.Hour * 24 + oneMonth = oneDay * 30 +) + +var ( + configPath = path.Join(config.Path, "systray.json") +) + +// Config holds the configuration of the systray +type Config struct { + file struct { + LastNotification time.Time + Donated time.Time + SelectGateway bool + Obfs4 bool + UserStoppedVPN bool + DisableAustostart bool + } + SelectGateway bool + Obfs4 bool + DisableAustostart bool + StartVPN bool + Version string + Printer *message.Printer +} + +// ParseConfig reads the configuration from the configuration file +func ParseConfig() *Config { + var conf Config + + f, err := os.Open(configPath) + if err != nil { + conf.save() + } else { + defer f.Close() + dec := json.NewDecoder(f) + err = dec.Decode(&conf.file) + } + + conf.SelectGateway = conf.file.SelectGateway + conf.Obfs4 = conf.file.Obfs4 + conf.DisableAustostart = conf.file.DisableAustostart + conf.StartVPN = !conf.file.UserStoppedVPN + return &conf +} + +func (c *Config) setUserStoppedVPN(vpnStopped bool) error { + c.file.UserStoppedVPN = vpnStopped + return c.save() +} + +func (c *Config) hasDonated() bool { + return c.file.Donated.Add(oneMonth).After(time.Now()) +} + +func (c *Config) needsNotification() bool { + return !c.hasDonated() && c.file.LastNotification.Add(oneDay).Before(time.Now()) +} + +func (c *Config) setNotification() error { + c.file.LastNotification = time.Now() + return c.save() +} + +func (c *Config) setDonated() error { + c.file.Donated = time.Now() + return c.save() +} + +func (c *Config) save() error { + f, err := os.Create(configPath) + if err != nil { + return err + } + defer f.Close() + + enc := json.NewEncoder(f) + enc.SetIndent("", " ") + return enc.Encode(c.file) +} diff --git a/pkg/systray2/pid.go b/pkg/systray2/pid.go new file mode 100644 index 0000000..b898d4e --- /dev/null +++ b/pkg/systray2/pid.go @@ -0,0 +1,99 @@ +package systray + +import ( + "fmt" + "io/ioutil" + "log" + "os" + "path/filepath" + "strconv" + "strings" + "syscall" + + "0xacab.org/leap/bitmask-vpn/pkg/config" + "github.com/keybase/go-ps" +) + +var pidFile = filepath.Join(config.Path, "systray.pid") + +func acquirePID() error { + pid := syscall.Getpid() + current, err := getPID() + if err != nil { + return err + } + + if current != pid && pidRunning(current) { + return fmt.Errorf("Another systray is running with pid: %d", current) + } + + return setPID(pid) +} + +func releasePID() error { + pid := syscall.Getpid() + current, err := getPID() + if err != nil { + return err + } + if current != 0 && current != pid { + return fmt.Errorf("Can't release pid file, is not own by this process") + } + + if current == pid { + return os.Remove(pidFile) + } + return nil +} + +func getPID() (int, error) { + _, err := os.Stat(pidFile) + if os.IsNotExist(err) { + return 0, nil + } + if err != nil { + return 0, err + } + + file, err := os.Open(pidFile) + if err != nil { + return 0, err + } + defer file.Close() + + b, err := ioutil.ReadAll(file) + if err != nil { + return 0, err + } + if len(b) == 0 { + return 0, nil + } + return strconv.Atoi(string(b)) +} + +func setPID(pid int) error { + file, err := os.Create(pidFile) + if err != nil { + return err + } + defer file.Close() + + _, err = file.WriteString(fmt.Sprintf("%d", pid)) + return err +} + +func pidRunning(pid int) bool { + if pid == 0 { + return false + } + proc, err := ps.FindProcess(pid) + if err != nil { + log.Printf("An error ocurred finding process: %v", err) + return false + } + if proc == nil { + return false + } + log.Printf("There is a running process with the pid %d and executable: %s", pid, proc.Executable()) + return strings.Contains(os.Args[0], proc.Executable()) +} diff --git a/pkg/systray2/pid_test.go b/pkg/systray2/pid_test.go new file mode 100644 index 0000000..dda8384 --- /dev/null +++ b/pkg/systray2/pid_test.go @@ -0,0 +1,21 @@ +package systray + +import ( + "syscall" + "testing" +) + +const ( + invalidPid = 345678 +) + +func TestPidRunning(t *testing.T) { + pid := syscall.Getpid() + if !pidRunning(pid) { + t.Errorf("pid %v is not running", pid) + } + + if pidRunning(invalidPid) { + t.Errorf("pid %v is running", invalidPid) + } +} diff --git a/pkg/systray2/run.go b/pkg/systray2/run.go new file mode 100644 index 0000000..937fb58 --- /dev/null +++ b/pkg/systray2/run.go @@ -0,0 +1,104 @@ +// Copyright (C) 2018 LEAP +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +package systray + +import ( + "log" + "os" + + "0xacab.org/leap/bitmask-vpn/pkg/bitmask" + "0xacab.org/leap/bitmask-vpn/pkg/config" +) + +func initialize(conf *Config, bt *bmTray, finishedCh chan bool) { + defer func() { finishedCh <- true }() + if _, err := os.Stat(config.Path); os.IsNotExist(err) { + os.MkdirAll(config.Path, os.ModePerm) + } + + err := acquirePID() + if err != nil { + log.Fatal(err) + } + defer releasePID() + + b, err := bitmask.Init(conf.Printer) + if err != nil { + // TODO notify failure + return + } + defer b.Close() + go checkAndStartBitmask(b, conf) + go listenSignals(b) + + var as bitmask.Autostart + if conf.DisableAustostart { + as = &bitmask.DummyAutostart{} + } else { + as = bitmask.NewAutostart(config.ApplicationName, "") + } + err = as.Enable() + if err != nil { + log.Printf("Error enabling autostart: %v", err) + } +} + +func checkAndStartBitmask(b bitmask.Bitmask, conf *Config) { + if conf.Obfs4 { + err := b.UseTransport("obfs4") + if err != nil { + log.Printf("Error setting transport: %v", err) + } + } + err := checkAndInstallHelpers(b) + if err != nil { + log.Printf("Is bitmask running? %v", err) + os.Exit(1) + } + err = maybeStartVPN(b, conf) + if err != nil { + log.Println("Error starting VPN: ", err) + } +} + +func checkAndInstallHelpers(b bitmask.Bitmask) error { + helpers, priviledge, err := b.VPNCheck() + if (err != nil && err.Error() == "nopolkit") || (err == nil && !priviledge) { + log.Printf("No polkit found") + os.Exit(1) + } else if err != nil { + log.Printf("Error checking vpn: %v", err) + return err + } + + if !helpers { + err = b.InstallHelpers() + if err != nil { + log.Println("Error installing helpers: ", err) + } + } + return nil +} + +func maybeStartVPN(b bitmask.Bitmask, conf *Config) error { + if !conf.StartVPN { + return nil + } + + err := b.StartVPN(config.Provider) + conf.setUserStoppedVPN(false) + return err +} |