lucky/thirdlib/go-wol/magic_packet.go

75 lines
1.8 KiB
Go

package wol
////////////////////////////////////////////////////////////////////////////////
import (
"bytes"
"encoding/binary"
"fmt"
"net"
"regexp"
)
////////////////////////////////////////////////////////////////////////////////
var (
delims = ":-"
reMAC = regexp.MustCompile(`^([0-9a-fA-F]{2}[` + delims + `]){5}([0-9a-fA-F]{2})$`)
)
////////////////////////////////////////////////////////////////////////////////
// MACAddress represents a 6 byte network mac address.
type MACAddress [6]byte
// MagicPacket is constituted of 6 bytes of 0xFF followed by 16-groups of the
// destination MAC address.
type MagicPacket struct {
header [6]byte
payload [16]MACAddress
}
// New returns a magic packet based on a mac address string.
func New(mac string) (*MagicPacket, error) {
var packet MagicPacket
var macAddr MACAddress
hwAddr, err := net.ParseMAC(mac)
if err != nil {
return nil, err
}
// We only support 6 byte MAC addresses since it is much harder to use the
// binary.Write(...) interface when the size of the MagicPacket is dynamic.
if !reMAC.MatchString(mac) {
return nil, fmt.Errorf("%s is not a IEEE 802 MAC-48 address", mac)
}
// Copy bytes from the returned HardwareAddr -> a fixed size MACAddress.
for idx := range macAddr {
macAddr[idx] = hwAddr[idx]
}
// Setup the header which is 6 repetitions of 0xFF.
for idx := range packet.header {
packet.header[idx] = 0xFF
}
// Setup the payload which is 16 repetitions of the MAC addr.
for idx := range packet.payload {
packet.payload[idx] = macAddr
}
return &packet, nil
}
// Marshal serializes the magic packet structure into a 102 byte slice.
func (mp *MagicPacket) Marshal() ([]byte, error) {
var buf bytes.Buffer
if err := binary.Write(&buf, binary.BigEndian, mp); err != nil {
return nil, err
}
return buf.Bytes(), nil
}