/
pack_tlv.go
113 lines (88 loc) · 2.36 KB
/
pack_tlv.go
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
package packer_type_length_value
import (
"encoding/binary"
"github.com/pkg/errors"
"io"
"github.com/MaxnSter/gnet/packer"
"github.com/MaxnSter/gnet/util"
)
var (
_ packer.Packer = (*tlvPacker)(nil)
)
const (
Name = "tlv"
LengthBytes = 4
TypeBytes = 4
MaxLength = 1 << 23
)
// ------------|---------------|-------------
// | Length | Type(msgId) | value |
// | 4 | 4 | msg |
// ------------------------------------------
// | |--------------body----------|
type tlvPacker struct {
}
func UnpackMsgId(body []byte) (msgId uint32, value []byte) {
msgId = binary.BigEndian.Uint32(body)
value = body[TypeBytes:]
return
}
func PackMsgId(msgId uint32, value []byte) (body []byte) {
body = make([]byte, len(value)+TypeBytes)
binary.BigEndian.PutUint32(body, msgId)
copy(body[TypeBytes:], value)
return
}
func (p *tlvPacker) Unpack(reader io.Reader) (body []byte, err error) {
//读取长度段
header := make([]byte, LengthBytes)
_, err = io.ReadFull(reader, header)
if err != nil {
if err == io.ErrUnexpectedEOF {
err = io.EOF
}
return
}
//解析长度段
length := binary.BigEndian.Uint32(header)
if length > MaxLength {
err = errors.Errorf("msg too long, max:%d, actual:%d", MaxLength, length)
}
if length <= TypeBytes {
err = errors.Errorf("msg too short, min:%d, actual:%d", TypeBytes, length)
}
if err != nil {
return
}
//根据length,读取对应字节数
body = make([]byte, length)
//从body中解析messageId,根据messageId,我们可以获取该messageId对应的meta信息
_, err = io.ReadFull(reader, body)
return
}
func (p *tlvPacker) Pack(writer io.Writer, body []byte) error {
if len(body) <= TypeBytes {
return errors.Errorf("msg too short, min:%d, actual:%d", TypeBytes, len(body))
}
//对应上图, Length + Type + Value 总的长度
totalLen := LengthBytes + len(body)
//对应上图 Type + Value总的长度,
bodyLen := len(body)
pack := make([]byte, totalLen)
// put length
// Length的值 = Type + Value总的长度
binary.BigEndian.PutUint32(pack, uint32(bodyLen))
// put value([]byte after encode)
copy(pack[LengthBytes:], body)
return util.WriteFull(writer, pack)
}
// TypeName返回tlvPacker的名称
func (p *tlvPacker) String() string {
return Name
}
func init() {
packer.RegisterPacker(Name, &tlvPacker{})
}
func New() packer.Packer {
return &tlvPacker{}
}