You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
81 lines
2.1 KiB
81 lines
2.1 KiB
package appkit
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"errors"
|
|
"math"
|
|
)
|
|
|
|
// 数据协议如下:
|
|
//
|
|
// +-----------+--------+--------------+-------+------+
|
|
// | 0x01,0x02 | length | topic-length | topic | data |
|
|
// +-----------+--------+--------------+-------+------+
|
|
// 2 2 2 n n
|
|
//
|
|
// * 头部有两个模数 0x01、0x02;
|
|
// * length 表示消息的总长度;
|
|
// * 然后分别是 topic、data,包含其长度和数据;
|
|
// * 长度使用 uint16 类型,所以占用 2 个字节;
|
|
//
|
|
// todo 实现数据校验码,防止篡改
|
|
|
|
// Encode 数据编码
|
|
func Encode(topic, data []byte) ([]byte, error) {
|
|
topicLen := len(topic)
|
|
dataLen := len(data)
|
|
size := 2 + topicLen + dataLen // 不包括模数和数据长度
|
|
if topicLen == 0 {
|
|
return nil, errors.New("topic too small")
|
|
}
|
|
if size+4 > math.MaxUint16 {
|
|
return nil, errors.New("data too big")
|
|
}
|
|
buf := &bytes.Buffer{}
|
|
// 由于 模数、topic 和 data 都是基本类型,所以当
|
|
// 执行 binary.Write() 时是不会出错的
|
|
_ = binary.Write(buf, binary.BigEndian, []byte{0x01, 0x02})
|
|
_ = binary.Write(buf, binary.BigEndian, uint16(size))
|
|
_ = binary.Write(buf, binary.BigEndian, uint16(topicLen))
|
|
_ = binary.Write(buf, binary.BigEndian, topic)
|
|
_ = binary.Write(buf, binary.BigEndian, data) // 如果没有数据会不会报错
|
|
return buf.Bytes(), nil
|
|
}
|
|
|
|
// Decode 数据解码
|
|
func Decode(buf []byte) (topic, data []byte, err error) {
|
|
r := bytes.NewReader(buf)
|
|
// 读取模数
|
|
var v [2]byte
|
|
err = binary.Read(r, binary.BigEndian, &v)
|
|
if err != nil {
|
|
return
|
|
}
|
|
if v[0] != 0x01 || v[1] != 0x02 {
|
|
err = errors.New("protocol error")
|
|
return
|
|
}
|
|
// 读取数据长度
|
|
var size uint16
|
|
err = binary.Read(r, binary.BigEndian, &size)
|
|
if err != nil {
|
|
return
|
|
}
|
|
// 读取主题长度
|
|
var topicLen uint16
|
|
err = binary.Read(r, binary.BigEndian, &topicLen)
|
|
if err != nil {
|
|
return
|
|
}
|
|
// 读取主题
|
|
topic = make([]byte, topicLen)
|
|
err = binary.Read(r, binary.BigEndian, &topic)
|
|
if err != nil {
|
|
return
|
|
}
|
|
// 读取数据
|
|
data = make([]byte, size-2-topicLen)
|
|
err = binary.Read(r, binary.BigEndian, &data)
|
|
return
|
|
}
|
|
|