forked from brutella/hc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
tlv8.go
124 lines (104 loc) · 2.58 KB
/
tlv8.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
114
115
116
117
118
119
120
121
122
123
124
package util
import (
"bytes"
"encoding/binary"
"io"
)
type tlv8Container struct {
Container
Items []tlv8
}
// NewTLV8Container returns a type-length-value container which implements the Container interface.
// Packets which value exceed a length of 8 bit (255) will be split up in multiple packets.
//
// Learn more https://en.wikipedia.org/wiki/Type-length-value
func NewTLV8Container() Container {
return &tlv8Container{
Items: make([]tlv8, 0, 1),
}
}
// NewTLV8ContainerFromReader returns a tlv8 container from a bytes buffer.
func NewTLV8ContainerFromReader(r io.Reader) (Container, error) {
var items = make([]tlv8, 0, 1)
for r != nil {
var item tlv8
if err := binary.Read(r, binary.LittleEndian, &item.tag); err != nil {
if err == io.EOF {
break
}
return nil, err
}
if err := binary.Read(r, binary.LittleEndian, &item.length); err != nil {
return nil, err
}
item.value = make([]byte, item.length)
if err := binary.Read(r, binary.LittleEndian, &item.value); err != nil {
return nil, err
}
items = append(items, item)
}
return &tlv8Container{
Items: items,
}, nil
}
func (t *tlv8Container) GetBuffer(tag uint8) *bytes.Buffer {
var b bytes.Buffer
for _, item := range t.Items {
if item.tag == tag {
b.Write(item.value)
}
}
return &b
}
func (t *tlv8Container) GetString(tag uint8) string {
return string(t.GetBytes(tag))
}
func (t *tlv8Container) GetBytes(tag uint8) []byte {
return t.GetBuffer(tag).Bytes()
}
func (t *tlv8Container) GetByte(tag uint8) byte {
buffer := t.GetBuffer(tag)
b, _ := buffer.ReadByte()
return b
}
func (t *tlv8Container) SetString(tag uint8, value string) {
t.SetBytes(tag, []byte(value))
}
func (t *tlv8Container) SetBytes(tag uint8, value []byte) {
r := bytes.NewBuffer(value)
for {
var item = tlv8{}
item.tag = tag
var bytes = make([]byte, 255)
n, err := io.ReadFull(r, bytes)
if err == nil || err == io.ErrUnexpectedEOF {
item.length = uint8(n)
item.value = bytes[:item.length]
t.Items = append(t.Items, item)
if err == io.ErrUnexpectedEOF { // Fewer than 255 bytes read
break
}
} else {
break
}
}
}
func (t *tlv8Container) SetByte(tag uint8, b byte) {
t.SetBytes(tag, []byte{b})
}
func (t *tlv8Container) BytesBuffer() *bytes.Buffer {
var b bytes.Buffer
for _, item := range t.Items {
// Since we are using just 1 byte for tag and length, the byte order does not matter
b.Write([]byte{item.tag})
b.Write([]byte{item.length})
b.Write(item.value)
}
return &b
}
// Encodes data into by tag, length and value
type tlv8 struct {
tag uint8
length uint8
value []byte
}