diff options
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | bitmask/events.go | 40 | ||||
-rw-r--r-- | bitmask/main.go | 77 | ||||
-rw-r--r-- | bitmask/vpn.go | 27 | ||||
-rw-r--r-- | main.go | 41 | ||||
-rw-r--r-- | systray.go | 48 |
6 files changed, 188 insertions, 49 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..f4255bb --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +Dependencies +------------ + + # apt install libzmq3-dev libgtk-3-dev libappindicator3-dev diff --git a/bitmask/events.go b/bitmask/events.go new file mode 100644 index 0000000..3fed26a --- /dev/null +++ b/bitmask/events.go @@ -0,0 +1,40 @@ +package bitmask + +import ( + "github.com/pebbe/zmq4" +) + +const ( + eventsEndpoint = "tcp://127.0.0.1:9001" + //serverKeyPath = "/home/user/.config/leap/events/zmq_certificates/public_keys/server.key" // FIXME +) + +func initEvents() (*zmq4.Socket, error) { + socket, err := zmq4.NewSocket(zmq4.SUB) + if err != nil { + return nil, err + } + + if zmq4.HasCurve() { + // TODO + } + + err = socket.Connect(eventsEndpoint) + if err != nil { + return nil, err + } + return socket, nil +} + +func (b *Bitmask) fetchStatus() { + // TODO: this should be a subscription to the event + for { + time.Sleep(time.Second) + status, err := b.GetStatus() + if err != nil { + log.Printf("Error receiving status: %v", err) + continue + } + b.statusCh <- status + } +} diff --git a/bitmask/main.go b/bitmask/main.go new file mode 100644 index 0000000..b4607b3 --- /dev/null +++ b/bitmask/main.go @@ -0,0 +1,77 @@ +package bitmask + +import ( + "encoding/json" + "errors" + + "github.com/pebbe/zmq4" +) + +const ( + // On win should be: tcp://127.0.0.1:5001 + coreEndpoint = "ipc:///tmp/bitmask.core.sock" +) + +// Bitmask holds the bitmask client data +type Bitmask struct { + //eventsoc *zmq4.Socket + coresoc *zmq4.Socket + statusCh chan string +} + +// Init the connection to bitmask +func Init() (*Bitmask, error) { + statusCh := make(chan string) + socket, err := initCore() + if err != nil { + return nil, err + } + + b := Bitmask{socket, statusCh} + go b.fetchStatus() + return &b, nil +} + +// GetStatusCh returns a channel that will recieve VPN status changes +func (b *Bitmask) GetStatusCh() chan string { + return b.statusCh +} + +// Close the connection to bitmask +func (b *Bitmask) Close() { + b.coresoc.Close() +} + +func (b *Bitmask) send(parts ...interface{}) (map[string]interface{}, error) { + _, err := b.coresoc.SendMessage(parts...) + if err != nil { + return nil, err + } + resJSON, err := b.coresoc.RecvBytes(0) + if err != nil { + return nil, err + } + return parseResponse(resJSON) +} + +func parseResponse(resJSON []byte) (map[string]interface{}, error) { + var response struct { + Result map[string]interface{} + Error string + } + err := json.Unmarshal(resJSON, &response) + if response.Error != "" { + return nil, errors.New(response.Error) + } + return response.Result, err +} + +func initCore() (*zmq4.Socket, error) { + socket, err := zmq4.NewSocket(zmq4.REQ) + if err != nil { + return nil, err + } + + err = socket.Connect(coreEndpoint) + return socket, err +} diff --git a/bitmask/vpn.go b/bitmask/vpn.go new file mode 100644 index 0000000..025e2e3 --- /dev/null +++ b/bitmask/vpn.go @@ -0,0 +1,27 @@ +package bitmask + +import ( + "log" + "time" +) + +// StartVPN for provider +func (b *Bitmask) StartVPN(provider string) error { + _, err := b.send("vpn", "start", provider) + return err +} + +// StopVPN or cancel +func (b *Bitmask) StopVPN() error { + _, err := b.send("vpn", "stop") + return err +} + +// GetStatus returns the VPN status +func (b *Bitmask) GetStatus() (string, error) { + res, err := b.send("vpn", "status") + if err != nil { + return "", err + } + return res["status"].(string), nil +} @@ -1,40 +1,21 @@ package main import ( - "time" + "log" + + "0xacab.org/meskio/bitmask-systray/bitmask" ) -var ch chan string +const ( + provider = "demo.bitmask.net" +) func main() { go notificate() - ch = make(chan string) - run(ch) -} - -func startVPN() { - go func() { - ch <- "starting" - time.Sleep(time.Second * 5) - ch <- "on" - }() -} - -func cancelVPN() { - go func() { - ch <- "stopping" - time.Sleep(time.Second * 5) - ch <- "off" - }() -} - -func stopVPN() { - go func() { - ch <- "failed" - }() -} - -func getVPNStatus() string { - return "off" + b, err := bitmask.Init() + if err != nil { + log.Fatal(err) + } + run(b) } @@ -1,17 +1,18 @@ package main import ( - "fmt" + "log" "os" "time" + "0xacab.org/meskio/bitmask-systray/bitmask" "0xacab.org/meskio/bitmask-systray/icon" "github.com/getlantern/systray" "github.com/skratchdot/open-golang/open" ) type bmTray struct { - ch chan string + bm *bitmask.Bitmask waitCh chan bool mStatus *systray.MenuItem mTurnOn *systray.MenuItem @@ -20,14 +21,14 @@ type bmTray struct { mGateways []*systray.MenuItem } -func run(ch chan string) { - bt := bmTray{ch: ch} +func run(bm *bitmask.Bitmask) { + bt := bmTray{bm: bm} systray.Run(bt.onReady, bt.onExit) } func (bt bmTray) onExit() { // TODO: this doesn't get executed :( - fmt.Println("Finished onExit") + log.Println("Finished onExit") } func (bt *bmTray) onReady() { @@ -51,31 +52,37 @@ func (bt *bmTray) onReady() { bt.mGateways[2].Uncheck() systray.AddSeparator() - mHelp := systray.AddMenuItem("Help", "") - mDonate := systray.AddMenuItem("Donate", "") - mAbout := systray.AddMenuItem("About", "") + mHelp := systray.AddMenuItem("Help ...", "") + mDonate := systray.AddMenuItem("Donate ...)", "") + mAbout := systray.AddMenuItem("About ...", "") systray.AddSeparator() mQuit := systray.AddMenuItem("Quit", "Quit BitmaskVPN") go func() { - bt.changeStatus(getVPNStatus()) + ch := bt.bm.GetStatusCh() + status, err := bt.bm.GetStatus() + if err != nil { + log.Printf("Error getting status: %v", err) + } else { + bt.changeStatus(status) + } for { select { case status := <-ch: - fmt.Println("status: " + status) + log.Println("status: " + status) bt.changeStatus(status) case <-bt.mTurnOn.ClickedCh: - fmt.Println("on") - startVPN() + log.Println("on") + bt.bm.StartVPN(provider) case <-bt.mTurnOff.ClickedCh: - fmt.Println("off") - stopVPN() + log.Println("off") + bt.bm.StopVPN() case <-bt.mCancel.ClickedCh: - fmt.Println("cancel") - cancelVPN() + log.Println("cancel") + bt.bm.StopVPN() case <-mHelp.ClickedCh: open.Run("https://riseup.net/en/vpn/vpn-black") @@ -86,7 +93,8 @@ func (bt *bmTray) onReady() { case <-mQuit.ClickedCh: systray.Quit() - fmt.Println("Quit now...") + bt.bm.Close() + log.Println("Quit now...") os.Exit(0) } } @@ -95,6 +103,7 @@ func (bt *bmTray) onReady() { func (bt *bmTray) changeStatus(status string) { statusStr := status + bt.mTurnOn.SetTitle("Turn on") if bt.waitCh != nil { bt.waitCh <- true bt.waitCh = nil @@ -129,9 +138,10 @@ func (bt *bmTray) changeStatus(status string) { case "failed": systray.SetIcon(icon.Error) + bt.mTurnOn.SetTitle("Retry") go bt.mTurnOn.Show() - go bt.mTurnOff.Hide() - go bt.mCancel.Show() + go bt.mTurnOff.Show() + go bt.mCancel.Hide() statusStr = "blocking internet" } |