1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
package inform
import (
"bytes"
"encoding/json"
"fmt"
)
const (
PROTOCOL_MAGIC int32 = 1414414933 // UBNT
INFORM_VERSION int32 = 0
DATA_VERSION int32 = 1
ENCRYPTED_FLAG = 1
COMPRESSED_FLAG = 2
)
// Wrapper around an inform message, serializes directly into the wire
// protocol
type InformWrapper struct {
Version int32
MacAddr []byte
Flags int16
DataVersion int32
Payload []byte
}
// Create InformWrapper with sane defaults
func NewInformWrapper() *InformWrapper {
w := &InformWrapper{
Version: INFORM_VERSION,
MacAddr: make([]byte, 6),
Flags: 0,
DataVersion: DATA_VERSION,
}
// Almost all messages are encrypted outside of provisioning so default
// this and make users explicitly disable it.
w.SetEncrypted(true)
return w
}
// Create an InformWrapper that is a response to an incoming wrapper. Copies
// all necessary data for a response so callers can just set a payload
func NewInformWrapperResponse(msg *InformWrapper) *InformWrapper {
w := NewInformWrapper()
copy(w.MacAddr, msg.MacAddr)
return w
}
// Update the payload data with JSON value
func (i *InformWrapper) UpdatePayload(v interface{}) error {
if d, err := json.Marshal(v); err != nil {
return err
} else {
i.Payload = d
return nil
}
}
// Unmarshal a payload body that we received from a device. Does not work for
// user-set messages
func (i *InformWrapper) UnmarshalPayload() (*DeviceMessage, error) {
var m DeviceMessage
err := json.Unmarshal(i.Payload, &m)
if err != nil {
return nil, err
}
return &m, nil
}
// Format Mac address bytes as lowercase string with colons
func (i *InformWrapper) FormattedMac() string {
return fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x",
i.MacAddr[0], i.MacAddr[1], i.MacAddr[2],
i.MacAddr[3], i.MacAddr[4], i.MacAddr[5])
}
func (i *InformWrapper) String() string {
b := &bytes.Buffer{}
fmt.Fprintf(b, "Version: \t%d\n", i.Version)
fmt.Fprintf(b, "Mac Addr: \t%s\n", i.FormattedMac())
fmt.Fprintf(b, "Flags: \t%d\n", i.Flags)
fmt.Fprintf(b, " Encrypted: \t%t\n", i.IsEncrypted())
fmt.Fprintf(b, " Compressed: \t%t\n", i.IsCompressed())
fmt.Fprintf(b, "Data Version: \t%d\n", i.DataVersion)
fmt.Fprintf(b, "Payload: \t%q\n", i.Payload)
return b.String()
}
func (i *InformWrapper) IsEncrypted() bool {
return i.Flags&ENCRYPTED_FLAG != 0
}
func (i *InformWrapper) SetEncrypted(e bool) {
if e {
i.Flags |= ENCRYPTED_FLAG
} else {
i.Flags &= ENCRYPTED_FLAG
}
}
func (i *InformWrapper) IsCompressed() bool {
return i.Flags&COMPRESSED_FLAG != 0
}
func (i *InformWrapper) SetCompressed(c bool) {
if c {
i.Flags |= COMPRESSED_FLAG
} else {
i.Flags &= COMPRESSED_FLAG
}
}
|