package main import ( "fmt" "net" "regexp" "github.com/lxn/walk" "github.com/lxn/walk/declarative" "github.com/mdlayher/wol" ) // WakeOnLAN struct type for wake on lan type WakeOnLAN struct { SleepHost, SleepPass, SleepMac string SleepPort int } func runWakeOnLanDg(owner walk.Form, dfgAddr, mactgadd string) (int, error) { const regexSingle = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$" var wakeClientguiwindow struct { dlgWakeOnLan *walk.Dialog dbindersshx *walk.DataBinder acceptPB, cancelPB *walk.PushButton macLine, addrLine *walk.LineEdit } wakestatset := &WakeOnLAN{ SleepHost: dfgAddr, SleepMac: mactgadd, SleepPort: 7, } return declarative.Dialog{ AssignTo: &wakeClientguiwindow.dlgWakeOnLan, FixedSize: true, Title: "Wake On LAN Client", DefaultButton: &wakeClientguiwindow.acceptPB, CancelButton: &wakeClientguiwindow.cancelPB, DataBinder: declarative.DataBinder{ AssignTo: &wakeClientguiwindow.dbindersshx, Name: "wakeClient", DataSource: wakestatset, ErrorPresenter: declarative.ToolTipErrorPresenter{}, }, MinSize: declarative.Size{Width: 320, Height: 300}, Layout: declarative.VBox{}, Children: []declarative.Widget{ declarative.GroupBox{ Title: "Wake On Lan Options", Layout: declarative.HBox{}, Children: []declarative.Widget{ declarative.Composite{ Layout: declarative.Grid{Columns: 1}, Children: []declarative.Widget{ declarative.GroupBox{ Title: "Host Address To Wake", Layout: declarative.Grid{Columns: 3}, Children: []declarative.Widget{ declarative.LineEdit{ AssignTo: &wakeClientguiwindow.addrLine, ToolTipText: "format: IP Address", CueBanner: "IPv4 Address...", Text: declarative.Bind("SleepHost"), }, declarative.NumberEdit{ ToolTipText: "port number", MaxSize: declarative.Size{Width: 40}, MinSize: declarative.Size{Width: 40}, Value: declarative.Bind("SleepPort"), MinValue: 1, MaxValue: 65535, }, }, }, declarative.GroupBox{ Title: "Host MAC Address", Layout: declarative.Grid{Columns: 1}, Children: []declarative.Widget{ declarative.LineEdit{ AssignTo: &wakeClientguiwindow.macLine, CueBanner: "Mac Address...", Text: declarative.Bind("SleepMac"), }, }, }, declarative.GroupBox{ Title: "Optional Wake Up Password", Layout: declarative.VBox{}, Children: []declarative.Widget{ declarative.LineEdit{ CueBanner: "Optional Password...", PasswordMode: true, Text: declarative.Bind("SleepPass"), }, }, }, }, }, }, }, declarative.Composite{ Layout: declarative.HBox{}, Children: []declarative.Widget{ declarative.HSpacer{}, declarative.PushButton{ AssignTo: &wakeClientguiwindow.acceptPB, Text: "Wake Up", OnClicked: func() { if err := wakeClientguiwindow.dbindersshx.Submit(); err != nil { return } if wakestatset.SleepHost == "" { wakeClientguiwindow.addrLine.Focused() return } if wakestatset.SleepMac == "" { wakeClientguiwindow.macLine.Focused() return } if match, _ := regexp.MatchString(regexSingle, wakestatset.SleepHost); !match { walk.MsgBox(wakeClientguiwindow.dlgWakeOnLan, "Host syntax error", "Invalid IPv4 address, Example: 192.168.1.1", walk.MsgBoxIconError) return } digMacAddr, err := net.ParseMAC(wakestatset.SleepMac) if err != nil { walk.MsgBox(wakeClientguiwindow.dlgWakeOnLan, "Mac syntax error", fmt.Sprint(err), walk.MsgBoxIconError) return } if err := wakeMachineUp(fmt.Sprintf("%v:%v", wakestatset.SleepHost, wakestatset.SleepPort), digMacAddr, []byte(wakestatset.SleepPass)); err != nil { walk.MsgBox(wakeClientguiwindow.dlgWakeOnLan, "Wake on error", fmt.Sprint(err), walk.MsgBoxIconError) return } walk.MsgBox(wakeClientguiwindow.dlgWakeOnLan, "Wake on lan", fmt.Sprintf("sent UDP Wake-on-LAN magic packet using \n%s to %s", wakestatset.SleepHost, wakestatset.SleepMac), walk.MsgBoxIconInformation) }, }, declarative.PushButton{ AssignTo: &wakeClientguiwindow.cancelPB, Text: "Cancel", OnClicked: func() { wakeClientguiwindow.dlgWakeOnLan.Cancel() }, }, }, }, }, }.Run(owner) } func wakeMachineUp(ipaddr string, macaddr net.HardwareAddr, password []byte) error { machine, err := wol.NewClient() if err != nil { return err } defer machine.Close() return machine.WakePassword(ipaddr, macaddr, password) }