Skip to content
Snippets Groups Projects
Verified Commit 96a892f8 authored by meskio's avatar meskio :tent:
Browse files

[feat] implement bitmask.core zmq comunication

parent 56b9c951
No related branches found
No related tags found
No related merge requests found
Dependencies
------------
# apt install libzmq3-dev libgtk-3-dev libappindicator3-dev
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
}
}
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
}
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
}
package main package main
import ( import (
"time" "log"
"0xacab.org/meskio/bitmask-systray/bitmask"
) )
var ch chan string const (
provider = "demo.bitmask.net"
)
func main() { func main() {
go notificate() go notificate()
ch = make(chan string) b, err := bitmask.Init()
run(ch) if err != nil {
} log.Fatal(err)
}
func startVPN() { run(b)
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"
} }
package main package main
import ( import (
"fmt" "log"
"os" "os"
"time" "time"
"0xacab.org/meskio/bitmask-systray/bitmask"
"0xacab.org/meskio/bitmask-systray/icon" "0xacab.org/meskio/bitmask-systray/icon"
"github.com/getlantern/systray" "github.com/getlantern/systray"
"github.com/skratchdot/open-golang/open" "github.com/skratchdot/open-golang/open"
) )
type bmTray struct { type bmTray struct {
ch chan string bm *bitmask.Bitmask
waitCh chan bool waitCh chan bool
mStatus *systray.MenuItem mStatus *systray.MenuItem
mTurnOn *systray.MenuItem mTurnOn *systray.MenuItem
...@@ -20,14 +21,14 @@ type bmTray struct { ...@@ -20,14 +21,14 @@ type bmTray struct {
mGateways []*systray.MenuItem mGateways []*systray.MenuItem
} }
func run(ch chan string) { func run(bm *bitmask.Bitmask) {
bt := bmTray{ch: ch} bt := bmTray{bm: bm}
systray.Run(bt.onReady, bt.onExit) systray.Run(bt.onReady, bt.onExit)
} }
func (bt bmTray) onExit() { func (bt bmTray) onExit() {
// TODO: this doesn't get executed :( // TODO: this doesn't get executed :(
fmt.Println("Finished onExit") log.Println("Finished onExit")
} }
func (bt *bmTray) onReady() { func (bt *bmTray) onReady() {
...@@ -51,31 +52,37 @@ func (bt *bmTray) onReady() { ...@@ -51,31 +52,37 @@ func (bt *bmTray) onReady() {
bt.mGateways[2].Uncheck() bt.mGateways[2].Uncheck()
systray.AddSeparator() systray.AddSeparator()
mHelp := systray.AddMenuItem("Help", "") mHelp := systray.AddMenuItem("Help ...", "")
mDonate := systray.AddMenuItem("Donate", "") mDonate := systray.AddMenuItem("Donate ...)", "")
mAbout := systray.AddMenuItem("About", "") mAbout := systray.AddMenuItem("About ...", "")
systray.AddSeparator() systray.AddSeparator()
mQuit := systray.AddMenuItem("Quit", "Quit BitmaskVPN") mQuit := systray.AddMenuItem("Quit", "Quit BitmaskVPN")
go func() { 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 { for {
select { select {
case status := <-ch: case status := <-ch:
fmt.Println("status: " + status) log.Println("status: " + status)
bt.changeStatus(status) bt.changeStatus(status)
case <-bt.mTurnOn.ClickedCh: case <-bt.mTurnOn.ClickedCh:
fmt.Println("on") log.Println("on")
startVPN() bt.bm.StartVPN(provider)
case <-bt.mTurnOff.ClickedCh: case <-bt.mTurnOff.ClickedCh:
fmt.Println("off") log.Println("off")
stopVPN() bt.bm.StopVPN()
case <-bt.mCancel.ClickedCh: case <-bt.mCancel.ClickedCh:
fmt.Println("cancel") log.Println("cancel")
cancelVPN() bt.bm.StopVPN()
case <-mHelp.ClickedCh: case <-mHelp.ClickedCh:
open.Run("https://riseup.net/en/vpn/vpn-black") open.Run("https://riseup.net/en/vpn/vpn-black")
...@@ -86,7 +93,8 @@ func (bt *bmTray) onReady() { ...@@ -86,7 +93,8 @@ func (bt *bmTray) onReady() {
case <-mQuit.ClickedCh: case <-mQuit.ClickedCh:
systray.Quit() systray.Quit()
fmt.Println("Quit now...") bt.bm.Close()
log.Println("Quit now...")
os.Exit(0) os.Exit(0)
} }
} }
...@@ -95,6 +103,7 @@ func (bt *bmTray) onReady() { ...@@ -95,6 +103,7 @@ func (bt *bmTray) onReady() {
func (bt *bmTray) changeStatus(status string) { func (bt *bmTray) changeStatus(status string) {
statusStr := status statusStr := status
bt.mTurnOn.SetTitle("Turn on")
if bt.waitCh != nil { if bt.waitCh != nil {
bt.waitCh <- true bt.waitCh <- true
bt.waitCh = nil bt.waitCh = nil
...@@ -129,9 +138,10 @@ func (bt *bmTray) changeStatus(status string) { ...@@ -129,9 +138,10 @@ func (bt *bmTray) changeStatus(status string) {
case "failed": case "failed":
systray.SetIcon(icon.Error) systray.SetIcon(icon.Error)
bt.mTurnOn.SetTitle("Retry")
go bt.mTurnOn.Show() go bt.mTurnOn.Show()
go bt.mTurnOff.Hide() go bt.mTurnOff.Show()
go bt.mCancel.Show() go bt.mCancel.Hide()
statusStr = "blocking internet" statusStr = "blocking internet"
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment