magicpacket/magicpacket.go
Rama main · réplica de lectura del repositorio original.
package magicpacket
import (
"fmt"
"io"
"net"
)
const (
// A magic packet is a 6-byte 0xFF sync stream followed by the MAC repeated 16 times.
packetSize = 102
syncStreamSize = 6
macRepeatCount = 16
)
// MagicPacket represents a wake-on-LAN packet
type MagicPacket struct {
// The MAC address of the machine to wake up
MacAddress net.HardwareAddr
}
// NewMagicPacket creates a new MagicPacket for the given MAC address
func NewMagicPacket(macAddress net.HardwareAddr) *MagicPacket {
return &MagicPacket{MacAddress: macAddress}
}
// Bytes returns the raw magic packet payload.
func (p *MagicPacket) Bytes() []byte {
packet := make([]byte, packetSize)
for i := 0; i < syncStreamSize; i++ {
packet[i] = 0xFF
}
for i := 1; i <= macRepeatCount; i++ {
copy(packet[i*6:], p.MacAddress)
}
return packet
}
// WriteTo writes the packet to w. It implements io.WriterTo so the send path can
// be tested against an in-memory writer instead of the network.
func (p *MagicPacket) WriteTo(w io.Writer) (int64, error) {
n, err := w.Write(p.Bytes())
return int64(n), err
}
// Broadcast sends the magic packet to addr, a "host:port" broadcast target such
// as "255.255.255.255:9" or a subnet-directed broadcast like "192.168.1.255:9".
// A subnet-directed broadcast is routed out the interface owning that subnet,
// which is what makes waking devices reliable on multi-homed hosts.
func (p *MagicPacket) Broadcast(addr string) (err error) {
udpAddr, err := net.ResolveUDPAddr("udp", addr)
if err != nil {
return fmt.Errorf("invalid broadcast address %q: %w", addr, err)
}
conn, err := net.DialUDP("udp", nil, udpAddr)
if err != nil {
return err
}
// Surface a close error, but don't let it mask a write error.
defer func() {
if cerr := conn.Close(); cerr != nil && err == nil {
err = cerr
}
}()
_, err = p.WriteTo(conn)
return err
}