vail/cmd/vail/message.go

105 lines
2.2 KiB
Go
Raw Permalink Normal View History

package main
import (
"bytes"
"encoding/binary"
2020-05-30 22:23:53 -06:00
"time"
)
2022-05-15 21:12:36 -06:00
// MessageSender can send Messages
type MessageSender interface {
Send(m Message) error
}
// MessageReceiver can receive Messages
type MessageReceiver interface {
Receive() (Message, error)
}
// MessageSocket can send and receive Messages
type MessageSocket interface {
MessageSender
MessageReceiver
}
2022-06-06 15:28:17 -06:00
// Message is a single Vail message.
type Message struct {
2022-05-15 15:57:12 -06:00
// Timestamp of this message. Milliseconds since epoch.
2020-05-30 22:23:53 -06:00
Timestamp int64
2022-05-15 15:57:12 -06:00
2022-06-06 15:28:17 -06:00
// Number of connected clients.
2022-05-15 15:57:12 -06:00
Clients uint16
2022-06-06 15:28:17 -06:00
// Message timing in milliseconds.
// Timings alternate between tone and silence.
// For example, `A` could be sent as [80, 80, 240]
2022-06-06 09:54:55 -06:00
Duration []uint16
}
2022-05-15 17:38:57 -06:00
func NewMessage(ts time.Time, durations ...time.Duration) Message {
2020-05-30 22:23:53 -06:00
msg := Message{
Timestamp: ts.UnixNano() / time.Millisecond.Nanoseconds(),
2022-06-06 09:54:55 -06:00
Duration: make([]uint16, len(durations)),
2020-05-30 22:23:53 -06:00
}
for i, dns := range durations {
ms := dns.Milliseconds()
2022-05-15 15:57:12 -06:00
if ms > 255 {
2020-05-30 22:23:53 -06:00
ms = 255
2022-05-15 15:57:12 -06:00
} else if ms < 0 {
2020-05-30 22:23:53 -06:00
ms = 0
}
2022-06-06 09:54:55 -06:00
msg.Duration[i] = uint16(ms)
2020-05-30 22:23:53 -06:00
}
return msg
}
2020-04-12 20:55:17 -06:00
// Marshaling presumes something else is keeping track of lengths
func (m Message) MarshalBinary() ([]byte, error) {
var w bytes.Buffer
if err := binary.Write(&w, binary.BigEndian, m.Timestamp); err != nil {
return nil, err
}
2022-05-15 15:57:12 -06:00
if err := binary.Write(&w, binary.BigEndian, m.Clients); err != nil {
return nil, err
}
if err := binary.Write(&w, binary.BigEndian, m.Duration); err != nil {
return nil, err
}
return w.Bytes(), nil
}
2022-06-06 09:54:55 -06:00
// UnmarshalBinary unpacks a binary buffer into a Message.
func (m *Message) UnmarshalBinary(data []byte) error {
r := bytes.NewReader(data)
if err := binary.Read(r, binary.BigEndian, &m.Timestamp); err != nil {
return err
}
2022-05-15 15:57:12 -06:00
if err := binary.Read(r, binary.BigEndian, &m.Clients); err != nil {
return err
}
2022-06-06 09:54:55 -06:00
dlen := r.Len() / 2
m.Duration = make([]uint16, dlen)
if err := binary.Read(r, binary.BigEndian, &m.Duration); err != nil {
return err
}
return nil
}
func (m Message) Equal(m2 Message) bool {
if m.Timestamp != m2.Timestamp {
return false
}
2022-05-15 15:57:12 -06:00
if len(m.Duration) != len(m2.Duration) {
return false
}
2022-05-15 15:57:12 -06:00
for i := range m.Duration {
if m.Duration[i] != m2.Duration[i] {
return false
}
}
2022-05-15 15:57:12 -06:00
return true
}