Skip to content

Commit

Permalink
Merge pull request #1183 from mrpalide/fix/update-systray
Browse files Browse the repository at this point in the history
Fix Systray on Linux
  • Loading branch information
0pcom authored May 9, 2022
2 parents 196209e + 1152acd commit 600a671
Show file tree
Hide file tree
Showing 9 changed files with 265 additions and 219 deletions.
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,12 @@ mac-installer-help: ## Show installer creation help
win-installer:
@powershell '.\scripts\win_installer\script.ps1'

set-cap-vpn-client:
sudo setcap 'cap_net_admin+p' ./apps/vpn-client

set-cap-vpn-server:
sudo setcap 'cap_net_admin+p' ./apps/vpn-server

help:
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ require (
github.com/ivanpirog/coloredcobra v1.0.0
github.com/james-barrow/golang-ipc v0.0.0-20210227130457-95e7cc81f5e2
github.com/skycoin/skywire-utilities v0.0.0-20220331141811-c29ff9ab891e
github.com/skycoin/systray v1.10.0
github.com/skycoin/systray v1.10.1-0.20220509091536-c90eecafd3fd
)

require (
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -484,8 +484,8 @@ github.com/skycoin/skycoin v0.27.1 h1:HatxsRwVSPaV4qxH6290xPBmkH/HgiuAoY2qC+e8C9
github.com/skycoin/skycoin v0.27.1/go.mod h1:78nHjQzd8KG0jJJVL/j0xMmrihXi70ti63fh8vXScJw=
github.com/skycoin/skywire-utilities v0.0.0-20220331141811-c29ff9ab891e h1:2LOmMQqYEk2XX4H8A/MXQmYIIl7opIVYmY3k76D1+Oc=
github.com/skycoin/skywire-utilities v0.0.0-20220331141811-c29ff9ab891e/go.mod h1:9fOsut+rqCBd33NPF3cuolXrw8uQESYshSvdYMaZNEo=
github.com/skycoin/systray v1.10.0 h1:fQZJHMylpVvfmOOTLvUssfyHVDoC8Idx6Ba2BlLEuGg=
github.com/skycoin/systray v1.10.0/go.mod h1:/i17Eni5GxFiboIZceeamY5LktDSFFRCvd3fBMerQ+4=
github.com/skycoin/systray v1.10.1-0.20220509091536-c90eecafd3fd h1:z2aytJ9vsBpsBrC6nfHuOTS+AUoEbaKs257+AiigUjk=
github.com/skycoin/systray v1.10.1-0.20220509091536-c90eecafd3fd/go.mod h1:LvRiIPZbFo8Qqp7Q9C9LXK02CqoVmc9EUGihU6kTRWc=
github.com/skycoin/yamux v0.0.0-20200803175205-571ceb89da9f h1:A5dEM1OE9YhN3LciZU9qPjo7fJ46JeHNi3JCroDkK0Y=
github.com/skycoin/yamux v0.0.0-20200803175205-571ceb89da9f/go.mod h1:48cleOxgkiLbgv322LOg2Vrxtu180Mb8GG1HbuhmFYM=
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 h1:TG/diQgUe0pntT/2D9tmUCz4VNwm9MfrtPr0SU2qSX8=
Expand Down
169 changes: 65 additions & 104 deletions internal/gui/gui.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,14 @@ var (
stopVisorFn func()
closeDmsgDC func()
rpcC visor.API
vpnLastStatus int
)

var (
guiStopped int32
)

var (
mAdvancedButton *systray.MenuItem
mOpenHypervisor *systray.MenuItem
mVPNClient *systray.MenuItem
mVPNStatus *systray.MenuItem
Expand All @@ -69,24 +69,28 @@ func GetOnGUIReady(icon []byte, conf *visorconfig.V1) func() {
logger := logging.NewMasterLogger()
logger.SetLevel(logrus.InfoLevel)

go func() {

}()

httpC := getHTTPClient(conf, context.Background(), logger)
if isRoot() {
return func() {
systray.SetTemplateIcon(icon, icon)
systray.SetTooltip("Skywire")
initOpenVPNLinkBtn(conf)
initAdvancedButton(conf)
initUIBtns(conf)
initVpnClientBtn(conf, httpC, logger)
initAdvancedButton(conf)
initQuitBtn()
go handleRootInteraction(conf, doneCh)
}
} else {
return func() {
systray.SetTemplateIcon(icon, icon)
systray.SetTooltip("Skywire")
initOpenVPNLinkBtn(conf)
initAdvancedButton(conf)
initUIBtns(conf)
initVpnClientBtn(conf, httpC, logger)
initAdvancedButton(conf)
initQuitBtn()
go handleUserInteraction(conf, doneCh)
}
Expand Down Expand Up @@ -121,65 +125,37 @@ func Stop() {
return
}
stopVisor()

systray.Quit()
}

func initAdvancedButton(conf *visorconfig.V1) {

hvAddr := getHVAddr(conf)

mAdvancedButton = systray.AddMenuItem("Advanced", "Advanced Menu")
mOpenHypervisor = mAdvancedButton.AddSubMenuItem("Open Hypervisor", "Open Hypervisor")
mAdvancedButton := systray.AddMenuItem("Advanced", "Advanced Menu")
mUninstall = mAdvancedButton.AddSubMenuItem("Uninstall", "Uninstall Application")

// if it's not installed via package, hide the uninstall button
initUninstallBtn()
//hide the buttons which could launch the browser if the process is run as root
if isRoot() {
if !checkIsPackage() {
mAdvancedButton.Hide()
mOpenHypervisor.Hide()
return
}
// if visor's not running or hypervisor config is absent,
// there won't be any way to open the hypervisor, so disable button
if hvAddr == "" {
mOpenHypervisor.Disable()
return
}

// if hypervisor is already running, just leave the button enabled
// as a default
if isHypervisorRunning(hvAddr) {
return
mUninstall.Hide()
}

// visor is running, but hypervisor is not yet, so disable the button
mOpenHypervisor.Disable()

// wait for the hypervisor to start in the background
go func() {
t := time.NewTicker(1 * time.Second)
defer t.Stop()

// we simply wait till the hypervisor is up
for {
<-t.C

if isHypervisorRunning(hvAddr) {
mOpenHypervisor.Enable()
break
}
}
}()
}

func initOpenVPNLinkBtn(vc *visorconfig.V1) {
func initUIBtns(vc *visorconfig.V1) {
mOpenHypervisor = systray.AddMenuItem("Open Hypervisor UI", "Open Hypervisor")
mVPNLink = systray.AddMenuItem("Open VPN UI", "Open VPN UI in browser")
hvAddr := getHVAddr(vc)
if isRoot() {
mVPNLink.Hide()
mOpenHypervisor.Hide()
return
}
mVPNLink.Disable()
mOpenHypervisor.Disable()

// if not hypervisor, both buttons no need to start
if hvAddr == "" {
return
}

// wait for the vpn client to start in the background
// if it's not started or if it isn't alive just disable the link.
Expand All @@ -190,29 +166,27 @@ func initOpenVPNLinkBtn(vc *visorconfig.V1) {
// we simply wait till the hypervisor is up
for {
<-t.C
if isVPNExists(vc) {
mVPNLink.Enable()
break
if mOpenHypervisor.Disabled() {
if isHypervisorRunning(hvAddr) {
mOpenHypervisor.Enable()
}
} else {
mVPNLink.Disable()
if isVPNExists(vc) {
mVPNLink.Enable()
return
}
}
}
}()
}

func initVpnClientBtn(conf *visorconfig.V1, httpClient *http.Client, logger *logging.MasterLogger) {

rpc_logger := logger.PackageLogger("systray:rpc_client")
hvAddr := getHVAddr(conf)
for !isHypervisorRunning(hvAddr) {
rpc_logger.Info("Waiting for RPC to get ready...")
time.Sleep(2 * time.Second)
}
rpcC = rpcClient(conf, rpc_logger)

mVPNClient := systray.AddMenuItem("VPN", "VPN Client Submenu")
mVPNClient = systray.AddMenuItem("VPN", "VPN Client Submenu")
// VPN Status
mVPNStatus = mVPNClient.AddSubMenuItem("Status: Disconnect", "VPN Client Status")
mVPNStatus = mVPNClient.AddSubMenuItem("Status: Disconnected", "VPN Client Status")
mVPNStatus.Disable()
go vpnStatusBtn(conf, rpcC)
// VPN Connect/Disconnect Button
Expand All @@ -227,42 +201,41 @@ func initVpnClientBtn(conf *visorconfig.V1, httpClient *http.Client, logger *log
}

func vpnStatusBtn(conf *visorconfig.V1, rpcClient visor.API) {
lastStatus := 0
for {
stats, _ := rpcClient.GetAppConnectionsSummary(skyenv.VPNClientName)
if len(stats) == 1 {
if stats[0].IsAlive {
if lastStatus != 1 {
if vpnLastStatus != 1 {
mVPNStatus.SetTitle("Status: Connected")
mVPNButton.SetTitle("Disconnect")
mVPNButton.Enable()
lastStatus = 1
vpnLastStatus = 1
}
} else {
if lastStatus != 2 {
mVPNStatus.SetTitle("Status: Connecting...")
if vpnLastStatus != 2 {
mVPNStatus.SetTitle("Status: Connecting")
mVPNButton.SetTitle("Disconnect")
mVPNButton.Disable()
lastStatus = 2
vpnLastStatus = 2
}
}
} else {
if lastStatus != 0 {
mVPNStatus.SetTitle("Status: Disconnected")
if vpnLastStatus != 0 {
if vpnLastStatus == 2 || vpnLastStatus == 3 {
mVPNStatus.SetTitle("Status: Errored")
} else {
mVPNStatus.SetTitle("Status: Disconnected")
}
mVPNButton.SetTitle("Connect")
mVPNButton.Enable()
lastStatus = 0
vpnLastStatus = 0
}
}
time.Sleep(3 * time.Second)
time.Sleep(2 * time.Second)
}
}

func serversBtn(conf *visorconfig.V1, servers []*systray.MenuItem, rpcClient visor.API) {
btnChannel := make(chan int)
for index, server := range servers {
go func(chn chan int, server *systray.MenuItem, index int) {

select {
case <-server.ClickedCh:
chn <- index
Expand All @@ -273,7 +246,7 @@ func serversBtn(conf *visorconfig.V1, servers []*systray.MenuItem, rpcClient vis
for {
selectedServer := servers[<-btnChannel]
serverTempValue := strings.Split(selectedServer.String(), ",")[2]
serverPK := serverTempValue[2 : len(serverTempValue)-5]
serverPK := serverTempValue[2 : len(serverTempValue)-7]
for _, server := range servers {
server.Uncheck()
server.Enable()
Expand All @@ -287,32 +260,18 @@ func serversBtn(conf *visorconfig.V1, servers []*systray.MenuItem, rpcClient vis

rpcClient.StopApp(skyenv.VPNClientName)
rpcClient.SetAppPK(skyenv.VPNClientName, pk)
vpnLastStatus = 3
rpcClient.StartApp(skyenv.VPNClientName)
}
}

func handleVPNButton(conf *visorconfig.V1, rpcClient visor.API) {
stats, _ := rpcClient.GetAppConnectionsSummary(skyenv.VPNClientName)
if len(stats) == 1 {
if stats[0].IsAlive {
mVPNStatus.SetTitle("Status: Disconnecting...")
mVPNButton.Disable()
mVPNButton.SetTitle("Connect")
if err := rpcClient.StopApp(skyenv.VPNClientName); err != nil {
mVPNStatus.SetTitle("Status: Connected")
mVPNButton.Enable()
mVPNButton.SetTitle("Disconnect")
}
}
rpcClient.StopApp(skyenv.VPNClientName)
} else {
mVPNStatus.SetTitle("Status: Connecting...")
mVPNButton.Disable()
mVPNButton.SetTitle("Disconnect")
if err := rpcClient.StartApp(skyenv.VPNClientName); err != nil {
mVPNStatus.SetTitle("Status: Disconnected")
mVPNButton.Enable()
mVPNButton.SetTitle("Connect")
}
vpnLastStatus = 3
rpcClient.StartApp(skyenv.VPNClientName)
}
}

Expand All @@ -332,7 +291,6 @@ func handleVPNLinkButton(conf *visorconfig.V1) {

// getAvailPublicVPNServers gets all available public VPN server from service discovery URL
func getAvailPublicVPNServers(conf *visorconfig.V1, httpC *http.Client, logger *logging.Logger) []string {

svrConfig := servicedisc.Config{
Type: servicedisc.ServiceTypeVPN,
PK: conf.PK,
Expand All @@ -350,7 +308,7 @@ func getAvailPublicVPNServers(conf *visorconfig.V1, httpC *http.Client, logger *
if server.Geo != nil {
serverAddrs[idx] = server.Addr.PubKey().String() + " | " + server.Geo.Country
} else {
serverAddrs[idx] = server.Addr.PubKey().String() + " | N/A"
serverAddrs[idx] = server.Addr.PubKey().String() + " | NA"
}
}
return serverAddrs
Expand Down Expand Up @@ -421,12 +379,6 @@ func isSetVPNClientPKExist(conf *visorconfig.V1) bool {
return false
}

func initUninstallBtn() {
if !checkIsPackage() {
mUninstall.Hide()
}
}

func initQuitBtn() {
mQuit = systray.AddMenuItem("Quit", "")
}
Expand Down Expand Up @@ -573,10 +525,19 @@ func getVPNAddr(conf *visorconfig.V1) string {
}

func rpcClient(conf *visorconfig.V1, logger *logging.Logger) visor.API {
const rpcDialTimeout = time.Second * 5
conn, err := net.DialTimeout("tcp", conf.CLIAddr, rpcDialTimeout)
if err != nil {
logger.Fatal("RPC connection failed:", err)
var conn net.Conn
var err error
var rpcConnected bool
logger.Info("Connecting to RPC")
for !rpcConnected {
conn, err = net.Dial("tcp", conf.CLIAddr)
if err != nil {
logger.Warn("RPC connection failed. Try again in 2 seconds.")
} else {
rpcConnected = true
}
time.Sleep(2 * time.Second)
}
logger.Info("RPC Connection established")
return visor.NewRPCClient(logger, conn, visor.RPCPrefix, 0)
}
5 changes: 3 additions & 2 deletions vendor/github.com/skycoin/systray/systray.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 600a671

Please sign in to comment.