Wake: a target may list several broadcast addresses
Config keeps broadcast (one) and adds broadcasts (a list); exactly one must be present. Wake.Addresses() returns Broadcast then Broadcasts; checkWake errors on both-set, neither-or-empty, and non-host:port entries. Waker sends to every address in order, logging/past a failure so one dead address does not stop the others, and returns false only when none could be sent. Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
This commit is contained in:
@@ -7,11 +7,24 @@ import (
|
||||
)
|
||||
|
||||
// Wake is the magic-wake pattern sent to a host to rouse it: its MAC, the
|
||||
// broadcast address to aim at, and how long to wait for the answer.
|
||||
// broadcast address(s) to aim at, and how long to wait for the answer. A host
|
||||
// that roams between networks names several, so Broadcast (one) and Broadcasts
|
||||
// (a list) are alternatives: exactly one must be set.
|
||||
type Wake struct {
|
||||
MAC string `toml:"mac"`
|
||||
Broadcast string `toml:"broadcast"`
|
||||
Wait Duration `toml:"wait"`
|
||||
MAC string `toml:"mac"`
|
||||
Broadcast string `toml:"broadcast"`
|
||||
Broadcasts []string `toml:"broadcasts"`
|
||||
Wait Duration `toml:"wait"`
|
||||
}
|
||||
|
||||
// Addresses is Broadcast (when set) followed by Broadcasts: the ordered list to
|
||||
// send wake packets to, never empty for a parsed config.
|
||||
func (w *Wake) Addresses() []string {
|
||||
addrs := make([]string, 0, 1+len(w.Broadcasts))
|
||||
if w.Broadcast != "" {
|
||||
addrs = append(addrs, w.Broadcast)
|
||||
}
|
||||
return append(addrs, w.Broadcasts...)
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -40,8 +53,19 @@ func (c *Config) checkWake() *Error {
|
||||
return &Error{Field: wakeField + ".mac", Msg: "must be a MAC address"}
|
||||
}
|
||||
|
||||
if _, _, err := net.SplitHostPort(w.Broadcast); err != nil || w.Broadcast == "" {
|
||||
broadcastSet := w.Broadcast != ""
|
||||
broadcastsSet := len(w.Broadcasts) > 0
|
||||
switch {
|
||||
case broadcastSet && broadcastsSet:
|
||||
return &Error{Field: wakeField + ".broadcasts", Msg: "choose broadcast or broadcasts, not both"}
|
||||
case !broadcastSet && !broadcastsSet:
|
||||
return &Error{Field: wakeField + ".broadcast", Msg: "must be a non-empty host:port"}
|
||||
default:
|
||||
for _, a := range w.Broadcasts {
|
||||
if _, _, err := net.SplitHostPort(a); err != nil || a == "" {
|
||||
return &Error{Field: wakeField + ".broadcasts", Msg: "must be a non-empty host:port"}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if w.Wait.Duration == 0 {
|
||||
|
||||
Reference in New Issue
Block a user