From ce4b5c36f0e3288d047e406830125a00bb387e3d Mon Sep 17 00:00:00 2001 From: Anthony Dong Date: Mon, 25 Mar 2019 18:18:43 +0100 Subject: ui: bind all new components together Signed-off-by: Anthony Dong Signed-off-by: Jason A. Donenfeld --- ui/ui.go | 265 +++++++++------------------------------------------------------ 1 file changed, 35 insertions(+), 230 deletions(-) (limited to 'ui') diff --git a/ui/ui.go b/ui/ui.go index 2cd558b7..4acd4a76 100644 --- a/ui/ui.go +++ b/ui/ui.go @@ -12,26 +12,9 @@ import ( "time" "github.com/lxn/walk" - "github.com/lxn/win" - "golang.zx2c4.com/wireguard/windows/conf" - "golang.zx2c4.com/wireguard/windows/ringlogger" "golang.zx2c4.com/wireguard/windows/service" - "golang.zx2c4.com/wireguard/windows/ui/syntax" ) -const testInterfaceName = "test" - -const demoConfig = `[Interface] -PrivateKey = 6KpcbNFK4tKBciKBT2Rj6Z/sHBqxdV+p+nuNA5AlWGI= -Address = 192.168.4.84/24 -DNS = 8.8.8.8, 8.8.4.4, 1.1.1.1, 1.0.0.1 - -[Peer] -PublicKey = JRI8Xc0zKP9kXk8qP84NdUQA04h6DLfFbwJn4g+/PFs= -Endpoint = demo.wireguard.com:12912 -AllowedIPs = 0.0.0.0/0 -` - const nagMessage = `It looks like you're still using this WireGuard pre-alpha build. Great! We're glad you like it, and we'd appreciate you sharing both your successes and your tribulations with us via team@wireguard.com or #wireguard on Freenode. @@ -40,11 +23,9 @@ But because this is pre-release software, we're not confident it's something you Would you like to quit WireGuard now? If not, you'll be nagged again in two minutes about the same thing.` -var quit func() - func nag() { if walk.MsgBox(nil, "THANKS FOR REPORTING BUGS COME AGAIN ANOTHER DAY", nagMessage, walk.MsgBoxIconError|walk.MsgBoxYesNo|0x00001000) != walk.DlgCmdNo { - quit() + onQuit() } time.AfterFunc(time.Minute*2, nag) } @@ -52,223 +33,48 @@ func nag() { func RunUI() { runtime.LockOSThread() - icon, _ := walk.NewIconFromResourceId(1) - - mw, _ := walk.NewMainWindowWithName("WireGuard") - tray, _ := walk.NewNotifyIcon(mw) - defer tray.Dispose() - tray.SetIcon(icon) - tray.SetToolTip("WireGuard: Deactivated") - tray.SetVisible(true) - - mw.SetSize(walk.Size{900, 1400}) - mw.SetLayout(walk.NewVBoxLayout()) - mw.SetIcon(icon) - mw.Closing().Attach(func(canceled *bool, reason walk.CloseReason) { - *canceled = true - mw.Hide() - }) - - tl, _ := walk.NewTextLabel(mw) - tl.SetText("Public key: (unknown)") - - se, _ := syntax.NewSyntaxEdit(mw) - lastPrivate := "" - se.PrivateKeyChanged().Attach(func(privateKey string) { - if privateKey == lastPrivate { - return - } - lastPrivate = privateKey - key, err := conf.NewPrivateKeyFromString(privateKey) - if err == nil { - tl.SetText("Public key: " + key.Public().String()) - } else { - tl.SetText("Public key: (unknown)") - } - }) - - tunnels, err := service.IPCClientTunnels() - didFind := false - if err == nil { - for _, tunnel := range tunnels { - if tunnel.Name == testInterfaceName { - storedConfig, err := tunnel.StoredConfig() - if err == nil { - se.SetText(storedConfig.ToWgQuick()) - didFind = true - } - } - } - } - if !didFind { - se.SetText(demoConfig) - } - - cv, _ := NewConfView(mw) - cv.SetVisible(false) - cv.SetEnabled(false) - - var runningTunnel *service.Tunnel - updateConfView := func() { - tun := runningTunnel - if tun == nil || !mw.Visible() || !cv.Visible() { - return - } - conf, err := tun.RuntimeConfig() - if err != nil { - return - } - cv.SetConfiguration(&conf) - } - go func() { - t := time.NewTicker(time.Second) - for { - updateConfView() - <-t.C - } - }() - showRunningView := func(on bool) { - cv.SetVisible(on) - cv.SetEnabled(on) - se.SetVisible(!on) - tl.SetVisible(!on) - if on { - updateConfView() - } + icon, err := walk.NewIconFromResourceId(1) + if err != nil { + panic(err) } + defer icon.Dispose() - pb, _ := walk.NewPushButton(mw) - pb.SetText("Start") - pb.Clicked().Attach(func() { - restoreState := true - pbE := pb.Enabled() - seE := se.Enabled() - pbT := pb.Text() - defer func() { - if restoreState { - pb.SetEnabled(pbE) - se.SetEnabled(seE) - pb.SetText(pbT) - } - }() - - mw.SetSuspended(true) - pb.SetEnabled(false) - se.SetEnabled(false) - pb.SetText("Requesting..") - mw.SetSuspended(false) - if runningTunnel != nil { - err := runningTunnel.Stop() - if err != nil { - walk.MsgBox(mw, "Unable to stop tunnel", err.Error(), walk.MsgBoxIconError) - return - } - restoreState = false - return - } - c, err := conf.FromWgQuick(se.Text(), testInterfaceName) - if err != nil { - walk.MsgBox(mw, "Invalid configuration", err.Error(), walk.MsgBoxIconError) - return - } - cv.SetConfiguration(c) - tunnel, err := service.IPCClientNewTunnel(c) - if err != nil { - walk.MsgBox(mw, "Unable to create tunnel", err.Error(), walk.MsgBoxIconError) - return - } - err = tunnel.Start() - if err != nil { - walk.MsgBox(mw, "Unable to start tunnel", err.Error(), walk.MsgBoxIconError) - return - } - restoreState = false - }) - - logger, err := ringlogger.NewRingloggerFromInheritedMappingHandle(os.Args[5], "GUI") + mtw, err := NewManageTunnelsWindow(icon) if err != nil { - walk.MsgBox(nil, "Unable to initialize logging", fmt.Sprint(err), walk.MsgBoxIconError) - return + panic(err) } - NewLogView(mw, logger) + defer mtw.Dispose() - quitAction := walk.NewAction() - quitAction.SetText("Exit") - quit = func() { - tray.Dispose() - onQuit() + tray, err := NewTray(mtw, icon) + if err != nil { + panic(err) } - quitAction.Triggered().Attach(quit) - tray.ContextMenu().Actions().Add(quitAction) - tray.MouseDown().Attach(func(x, y int, button walk.MouseButton) { - if button == walk.LeftButton { - mw.Show() - win.SetForegroundWindow(mw.Handle()) - win.BringWindowToTop(mw.Handle()) - updateConfView() - } - }) + defer tray.Dispose() - setServiceState := func(tunnel *service.Tunnel, state service.TunnelState, showNotifications bool) { - if tunnel.Name != testInterfaceName { + // Bind to updates + service.IPCClientRegisterTunnelChange(func(tunnel *service.Tunnel, state service.TunnelState, err error) { + if err == nil { return } - mw.SetSuspended(true) - //TODO: also set tray icon to reflect state - switch state { - case service.TunnelStarting: - runningTunnel = tunnel - showRunningView(false) - se.SetEnabled(false) - pb.SetText("Starting...") - pb.SetEnabled(false) - tray.SetToolTip("WireGuard: Activating...") - case service.TunnelStarted: - runningTunnel = tunnel - showRunningView(true) - se.SetEnabled(false) - pb.SetText("Stop") - pb.SetEnabled(true) - tray.SetToolTip("WireGuard: Activated") - if showNotifications { - //TODO: ShowCustom with right icon - tray.ShowInfo("WireGuard Activated", fmt.Sprintf("The %s tunnel has been activated.", tunnel.Name)) - } - case service.TunnelStopping: - runningTunnel = tunnel - showRunningView(false) - se.SetEnabled(false) - pb.SetText("Stopping...") - pb.SetEnabled(false) - tray.SetToolTip("WireGuard: Deactivating...") - case service.TunnelStopped: - showRunningView(false) - se.SetEnabled(true) - pb.SetText("Start") - pb.SetEnabled(true) - tray.SetToolTip("WireGuard: Deactivated") - if showNotifications && runningTunnel != nil { - //TODO: ShowCustom with right icon - tray.ShowInfo("WireGuard Deactivated", fmt.Sprintf("The %s tunnel has been deactivated.", tunnel.Name)) + + if mtw.Visible() { + errMsg := err.Error() + if len(errMsg) > 0 && errMsg[len(errMsg)-1] != '.' { + errMsg += "." } - runningTunnel = nil + walk.MsgBox(mtw, "Tunnel Error", errMsg+"\n\nPlease consult the Windows Event Log for more information.", walk.MsgBoxIconWarning) + } else { + tray.ShowError("WireGuard Tunnel Error", err.Error()) } - mw.SetSuspended(false) - } + }) service.IPCClientRegisterTunnelChange(func(tunnel *service.Tunnel, state service.TunnelState, err error) { - setServiceState(tunnel, state, err == nil) - if err != nil { - if mw.Visible() { - errMsg := err.Error() - if len(errMsg) > 0 && errMsg[len(errMsg)-1] != '.' { - errMsg += "." - } - walk.MsgBox(mw, "Tunnel Error", errMsg+"\n\nPlease consult the log for more information.", walk.MsgBoxIconWarning) - } else { - tray.ShowError("WireGuard Tunnel Error", err.Error()) - } - } + tray.SetTunnelStateWithNotification(tunnel, state, err == nil) + }) + service.IPCClientRegisterTunnelChange(func(tunnel *service.Tunnel, state service.TunnelState, err error) { + mtw.SetTunnelState(tunnel, state) }) + + // Fetch current state go func() { tunnels, err := service.IPCClientTunnels() if err != nil { @@ -279,16 +85,13 @@ func RunUI() { if err != nil { continue } - if tunnel.Name == testInterfaceName && state != service.TunnelStopped { - runningTunnel = &tunnel - setServiceState(&tunnel, state, false) - } + tray.SetTunnelStateWithNotification(&tunnel, state, false) + mtw.SetTunnelState(&tunnel, state) } }() time.AfterFunc(time.Minute*15, nag) - - mw.Run() + mtw.Run() } func onQuit() { @@ -297,6 +100,8 @@ func onQuit() { walk.MsgBox(nil, "Error Exiting WireGuard", fmt.Sprintf("Unable to exit service due to: %s. You may want to stop WireGuard from the service manager.", err), walk.MsgBoxIconError) os.Exit(1) } + + walk.App().Exit(0) } const aboutText = ` -- cgit v1.2.3-59-g8ed1b