mirror of
https://github.com/zgwit/beeq.git
synced 2025-09-26 19:51:13 +08:00
175 lines
2.9 KiB
Go
175 lines
2.9 KiB
Go
package packet
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"fmt"
|
|
)
|
|
|
|
type SubTopic struct {
|
|
topic []byte
|
|
flag byte
|
|
}
|
|
|
|
func (msg *SubTopic) Topic() []byte {
|
|
return msg.topic
|
|
}
|
|
|
|
func (msg *SubTopic) SetTopic(b []byte) {
|
|
msg.topic = b
|
|
}
|
|
|
|
func (msg *SubTopic) Qos() MsgQos {
|
|
return MsgQos(msg.flag & 0x03) //0000 0011
|
|
}
|
|
|
|
func (msg *SubTopic) SetQos(qos MsgQos) {
|
|
msg.flag &= 0xFC
|
|
msg.flag |= byte(qos)
|
|
}
|
|
|
|
type Subscribe struct {
|
|
Header
|
|
|
|
packetId uint16
|
|
|
|
topics []*SubTopic
|
|
}
|
|
|
|
func (msg *Subscribe) PacketId() uint16 {
|
|
return msg.packetId
|
|
}
|
|
|
|
func (msg *Subscribe) SetPacketId(p uint16) {
|
|
msg.dirty = true
|
|
msg.packetId = p
|
|
}
|
|
|
|
func (msg *Subscribe) Topics() []*SubTopic {
|
|
return msg.topics
|
|
}
|
|
|
|
func (msg *Subscribe) AddTopic(topic []byte, qos MsgQos) {
|
|
msg.dirty = true
|
|
st := &SubTopic{}
|
|
st.SetTopic(topic)
|
|
st.SetQos(qos)
|
|
msg.topics = append(msg.topics, st)
|
|
}
|
|
|
|
func (msg *Subscribe) ClearTopic() {
|
|
msg.dirty = true
|
|
msg.topics = msg.topics[0:0]
|
|
}
|
|
|
|
func (msg *Subscribe) Decode(buf []byte) (int, error) {
|
|
msg.dirty = false
|
|
|
|
//total := len(buf)
|
|
offset := 0
|
|
|
|
//Header
|
|
msg.header = buf[0]
|
|
offset++
|
|
|
|
//Remain Length
|
|
if l, n, err := ReadRemainLength(buf[offset:]); err != nil {
|
|
return offset, err
|
|
} else {
|
|
msg.remainLength = l
|
|
offset += n
|
|
}
|
|
headerLen := offset
|
|
|
|
// PacketId
|
|
msg.packetId = binary.BigEndian.Uint16(buf[offset:])
|
|
offset += 2
|
|
|
|
// FixHead & VarHead
|
|
msg.head = buf[0:offset]
|
|
plo := offset
|
|
|
|
// Parse Topics
|
|
for offset-headerLen < msg.remainLength {
|
|
st := &SubTopic{}
|
|
//Topic
|
|
if b, n, err := ReadBytes(buf[offset:]); err != nil {
|
|
return offset, err
|
|
} else {
|
|
st.SetTopic(b)
|
|
offset += n
|
|
}
|
|
//Qos
|
|
qos := buf[offset]
|
|
if (qos & 0x03) != qos {
|
|
return offset, fmt.Errorf("Topic Qos %x", qos)
|
|
}
|
|
st.SetQos(MsgQos(qos))
|
|
offset++
|
|
msg.topics = append(msg.topics, st)
|
|
}
|
|
|
|
//Payload
|
|
msg.payload = buf[plo:offset]
|
|
|
|
return offset, nil
|
|
}
|
|
|
|
func (msg *Subscribe) Encode() ([]byte, []byte, error) {
|
|
if !msg.dirty {
|
|
return msg.head, msg.payload, nil
|
|
}
|
|
|
|
//Remain Length
|
|
msg.remainLength = 0
|
|
//Packet Id
|
|
msg.remainLength += 2
|
|
|
|
//FixHead & VarHead
|
|
hl := msg.remainLength
|
|
|
|
//Topics
|
|
for _, t := range msg.topics {
|
|
msg.remainLength += 2 + len(t.Topic())
|
|
msg.remainLength += 1
|
|
}
|
|
|
|
pl := msg.remainLength - hl
|
|
hl += 1 + LenLen(msg.remainLength)
|
|
|
|
//Alloc buffer
|
|
msg.head = make([]byte, hl)
|
|
msg.payload = make([]byte, pl)
|
|
|
|
//Header
|
|
ho := 0
|
|
msg.head[ho] = msg.header
|
|
ho++
|
|
|
|
//Remain Length
|
|
if n, err := WriteRemainLength(msg.head[ho:], msg.remainLength); err != nil {
|
|
return nil, nil, err
|
|
} else {
|
|
ho += n
|
|
}
|
|
|
|
//Packet Id
|
|
binary.BigEndian.PutUint16(msg.head[ho:], msg.packetId)
|
|
ho += 2
|
|
|
|
plo := 0
|
|
//Topics
|
|
for _, t := range msg.topics {
|
|
//Topic
|
|
if n, err := WriteBytes(msg.payload[plo:], t.topic); err != nil {
|
|
return msg.head, nil, err
|
|
} else {
|
|
plo += n
|
|
}
|
|
//Qos
|
|
msg.payload[plo] = t.flag
|
|
plo++
|
|
}
|
|
|
|
return msg.head, msg.payload, nil
|
|
}
|