aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/ui
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2019-03-20 02:18:05 -0600
committerJason A. Donenfeld <Jason@zx2c4.com>2019-03-21 03:24:11 -0600
commit4e58a239c084d673b1376167318ede11eded15c2 (patch)
tree036751633485acaa313a5b4c758d06f276202e7f /ui
parentconf: expose configuration root directory (diff)
downloadwireguard-windows-4e58a239c084d673b1376167318ede11eded15c2.tar.xz
wireguard-windows-4e58a239c084d673b1376167318ede11eded15c2.zip
ringlogger: introduce basic file ring logging
Diffstat (limited to 'ui')
-rw-r--r--ui/logview.go128
-rw-r--r--ui/ui.go16
2 files changed, 142 insertions, 2 deletions
diff --git a/ui/logview.go b/ui/logview.go
new file mode 100644
index 00000000..e7a8a237
--- /dev/null
+++ b/ui/logview.go
@@ -0,0 +1,128 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
+ */
+
+package ui
+
+import (
+ "errors"
+ "fmt"
+ "github.com/lxn/walk"
+ "github.com/lxn/win"
+ "golang.zx2c4.com/wireguard/windows/ringlogger"
+ "strings"
+ "syscall"
+ "time"
+ "unsafe"
+)
+
+type LogView struct {
+ walk.WidgetBase
+ logChan chan string
+}
+
+const (
+ TEM_APPENDTEXT = win.WM_USER + 6
+)
+
+func NewLogView(parent walk.Container, rl *ringlogger.Ringlogger) (*LogView, error) {
+ lc := make(chan string, 1024)
+ lv := &LogView{logChan: lc}
+
+ if err := walk.InitWidget(
+ lv,
+ parent,
+ "EDIT",
+ win.WS_TABSTOP|win.WS_VISIBLE|win.WS_VSCROLL|win.ES_MULTILINE|win.ES_WANTRETURN,
+ win.WS_EX_CLIENTEDGE); err != nil {
+ return nil, err
+ }
+ lv.setReadOnly(true)
+ lv.SendMessage(win.EM_SETLIMITTEXT, 4294967295, 0)
+
+ go func() {
+ var lines []ringlogger.FollowLine
+ cursor := ringlogger.CursorAll
+ for {
+ if lv.IsDisposed() {
+ return
+ }
+ lines, cursor = rl.FollowFromCursor(cursor)
+ sb := strings.Builder{}
+ for _, line := range lines {
+ sb.WriteString(fmt.Sprintf("%s: %s\r\n", line.Stamp.Format("2006-01-02 15:04:05.000000"), strings.ReplaceAll(line.Line, "\n", "\r\n")))
+ }
+ newLines := sb.String()
+ if len(newLines) > 0 {
+ lv.AppendText(newLines)
+ }
+ time.Sleep(300 * time.Millisecond)
+ }
+ }()
+ return lv, nil
+}
+
+func (*LogView) LayoutFlags() walk.LayoutFlags {
+ return walk.ShrinkableHorz | walk.ShrinkableVert | walk.GrowableHorz | walk.GrowableVert | walk.GreedyHorz | walk.GreedyVert
+}
+
+func (*LogView) MinSizeHint() walk.Size {
+ return walk.Size{20, 12}
+}
+
+func (*LogView) SizeHint() walk.Size {
+ return walk.Size{100, 100}
+}
+
+func (lv *LogView) setTextSelection(start, end int) {
+ lv.SendMessage(win.EM_SETSEL, uintptr(start), uintptr(end))
+}
+
+func (lv *LogView) textLength() int {
+ return int(lv.SendMessage(0x000E, uintptr(0), uintptr(0)))
+}
+
+func (lv *LogView) AppendText(value string) {
+ textLength := lv.textLength()
+ lv.setTextSelection(textLength, textLength)
+ lv.SendMessage(win.EM_REPLACESEL, 0, uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(value))))
+}
+
+func (lv *LogView) setReadOnly(readOnly bool) error {
+ if 0 == lv.SendMessage(win.EM_SETREADONLY, uintptr(win.BoolToBOOL(readOnly)), 0) {
+ return errors.New("fail to call EM_SETREADONLY")
+ }
+
+ return nil
+}
+
+func (lv *LogView) PostAppendText(value string) {
+ lv.logChan <- value
+ win.PostMessage(lv.Handle(), TEM_APPENDTEXT, 0, 0)
+}
+
+func (lv *LogView) Write(p []byte) (int, error) {
+ lv.PostAppendText(string(p) + "\r\n")
+ return len(p), nil
+}
+
+func (lv *LogView) WndProc(hwnd win.HWND, msg uint32, wParam, lParam uintptr) uintptr {
+ switch msg {
+ case win.WM_GETDLGCODE:
+ if wParam == win.VK_RETURN {
+ return win.DLGC_WANTALLKEYS
+ }
+
+ return win.DLGC_HASSETSEL | win.DLGC_WANTARROWS | win.DLGC_WANTCHARS
+ case TEM_APPENDTEXT:
+ select {
+ case value := <-lv.logChan:
+ lv.AppendText(value)
+ default:
+ return 0
+ }
+ }
+
+ return lv.WidgetBase.WndProc(hwnd, msg, wParam, lParam)
+}
diff --git a/ui/ui.go b/ui/ui.go
index 7bc49489..bbae9980 100644
--- a/ui/ui.go
+++ b/ui/ui.go
@@ -10,6 +10,7 @@ import (
"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"
"os"
@@ -54,7 +55,7 @@ func RunUI() {
tray.SetToolTip("WireGuard: Deactivated")
tray.SetVisible(true)
- mw.SetSize(walk.Size{900, 800})
+ mw.SetSize(walk.Size{900, 1400})
mw.SetLayout(walk.NewVBoxLayout())
mw.SetIcon(icon)
mw.Closing().Attach(func(canceled *bool, reason walk.CloseReason) {
@@ -178,6 +179,17 @@ func RunUI() {
restoreState = false
})
+ logfile, err := service.IPCClientLogFilePath()
+ var logger *ringlogger.Ringlogger
+ if err == nil {
+ logger, err = ringlogger.NewRinglogger(logfile, "GUI")
+ }
+ if err != nil {
+ walk.MsgBox(nil, "Unable to initialize logging", fmt.Sprintf("%v\n\nFile: %s", err, logfile), walk.MsgBoxIconError)
+ return
+ }
+ NewLogView(mw, logger)
+
quitAction := walk.NewAction()
quitAction.SetText("Exit")
quit = func() {
@@ -249,7 +261,7 @@ func RunUI() {
setServiceState(tunnel, state, err == nil)
if err != nil {
if mw.Visible() {
- walk.MsgBox(mw, "Tunnel Error", err.Error()+"\n\nPlease consult the Windows Event Log for more information.", walk.MsgBoxIconWarning)
+ walk.MsgBox(mw, "Tunnel Error", err.Error()+"\n\nPlease consult the log for more information.", walk.MsgBoxIconWarning)
} else {
tray.ShowError("WireGuard Tunnel Error", err.Error())
}