-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpacket_auth.go
More file actions
107 lines (90 loc) · 2.29 KB
/
packet_auth.go
File metadata and controls
107 lines (90 loc) · 2.29 KB
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
//nolint:dupl // MQTT v5.0 requires separate packet types with same structure
package mqttv5
import (
"bytes"
"io"
)
// AuthPacket represents an MQTT AUTH packet.
// MQTT v5.0 spec: Section 3.15
type AuthPacket struct {
ReasonCode ReasonCode
Props Properties
}
// Type returns the packet type.
func (p *AuthPacket) Type() PacketType { return PacketAUTH }
// Properties returns a pointer to the packet's properties.
func (p *AuthPacket) Properties() *Properties { return &p.Props }
// Encode writes the packet to the writer.
func (p *AuthPacket) Encode(w io.Writer) (int, error) {
if err := p.Validate(); err != nil {
return 0, err
}
if err := p.Props.ValidateFor(PropCtxAUTH); err != nil {
return 0, err
}
var buf bytes.Buffer
// Reason Code and Properties (optional if success with no properties)
if p.ReasonCode != ReasonSuccess || p.Props.Len() > 0 {
if err := buf.WriteByte(byte(p.ReasonCode)); err != nil {
return 0, err
}
if p.Props.Len() > 0 {
if _, err := p.Props.Encode(&buf); err != nil {
return 0, err
}
}
}
// Write fixed header
header := FixedHeader{
PacketType: PacketAUTH,
Flags: 0x00,
RemainingLength: uint32(buf.Len()),
}
total, err := header.Encode(w)
if err != nil {
return total, err
}
n, err := w.Write(buf.Bytes())
return total + n, err
}
// Decode reads the packet from the reader.
func (p *AuthPacket) Decode(r io.Reader, header FixedHeader) (int, error) {
if header.PacketType != PacketAUTH {
return 0, ErrInvalidPacketType
}
if header.Flags != 0x00 {
return 0, ErrInvalidPacketFlags
}
var totalRead int
// Reason Code (optional)
if header.RemainingLength > 0 {
var reasonBuf [1]byte
n, err := io.ReadFull(r, reasonBuf[:])
totalRead += n
if err != nil {
return totalRead, err
}
p.ReasonCode = ReasonCode(reasonBuf[0])
// Properties (optional)
if header.RemainingLength > 1 {
n, err = p.Props.Decode(r)
totalRead += n
if err != nil {
return totalRead, err
}
if err := p.Props.ValidateFor(PropCtxAUTH); err != nil {
return totalRead, err
}
}
} else {
p.ReasonCode = ReasonSuccess
}
return totalRead, nil
}
// Validate validates the packet contents.
func (p *AuthPacket) Validate() error {
if !p.ReasonCode.ValidForAUTH() {
return ErrInvalidReasonCode
}
return nil
}