-
Notifications
You must be signed in to change notification settings - Fork 3
/
pobasic.go
197 lines (183 loc) · 5.68 KB
/
pobasic.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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
package bw2bind
import (
"encoding/hex"
"encoding/json"
"fmt"
"strconv"
"strings"
_ "github.com/ugorji/go/codec"
"gopkg.in/vmihailenco/msgpack.v2"
"gopkg.in/yaml.v2"
)
type POConstructor struct {
PONum string
Mask int
Constructor func(int, []byte) (PayloadObject, error)
}
//Most specialised must be first
var PayloadObjectConstructors = []POConstructor{
{"2.0.3.1", 32, LoadMetadataPayloadObjectPO},
{"67.0.0.0", 8, LoadYAMLPayloadObjectPO},
{"2.0.0.0", 8, LoadMsgPackPayloadObjectPO},
{"64.0.0.0", 4, LoadTextPayloadObjectPO},
{"0.0.0.0", 0, LoadBasePayloadObjectPO},
}
func LoadPayloadObject(ponum int, contents []byte) (PayloadObject, error) {
for _, c := range PayloadObjectConstructors {
cponum, _ := PONumFromDotForm(c.PONum)
cponum = cponum >> uint(32-c.Mask)
if (ponum >> uint(32-c.Mask)) == cponum {
return c.Constructor(ponum, contents)
}
}
panic("Could not load PO")
}
//PayloadObject implements 0.0.0.0/0 : base
type PayloadObject interface {
GetPONum() int
GetPODotNum() string
TextRepresentation() string
GetContents() []byte
IsTypeDF(df string) bool
IsType(ponum, mask int) bool
}
type PayloadObjectImpl struct {
ponum int
contents []byte
}
func LoadBasePayloadObject(ponum int, contents []byte) (*PayloadObjectImpl, error) {
return &PayloadObjectImpl{ponum: ponum, contents: contents}, nil
}
func LoadBasePayloadObjectPO(ponum int, contents []byte) (PayloadObject, error) {
return LoadBasePayloadObject(ponum, contents)
}
func CreateBasePayloadObject(ponum int, contents []byte) *PayloadObjectImpl {
rv, _ := LoadBasePayloadObject(ponum, contents)
return rv
}
func (po *PayloadObjectImpl) GetPONum() int {
return po.ponum
}
func (po *PayloadObjectImpl) SetPONum(ponum int) {
po.ponum = ponum
}
func (po *PayloadObjectImpl) GetContents() []byte {
return po.contents
}
func (po *PayloadObjectImpl) SetContents(v []byte) {
po.contents = v
}
func (po *PayloadObjectImpl) GetPODotNum() string {
return fmt.Sprintf("%d.%d.%d.%d", po.ponum>>24, (po.ponum>>16)&0xFF, (po.ponum>>8)&0xFF, po.ponum&0xFF)
}
func (po *PayloadObjectImpl) TextRepresentation() string {
return fmt.Sprintf("PO %s len %d (generic) hexdump:\n%s", PONumDotForm(po.ponum), len(po.contents), hex.Dump(po.contents))
}
func (po *PayloadObjectImpl) IsType(ponum, mask int) bool {
return (ponum >> uint(32-mask)) == (po.ponum >> uint(32-mask))
}
func (po *PayloadObjectImpl) IsTypeDF(df string) bool {
parts := strings.SplitN(df, "/", 2)
var mask int
var err error
if len(parts) != 2 {
mask = 32
} else {
mask, err = strconv.Atoi(parts[1])
if err != nil {
panic("malformed masked dot form")
}
}
ponum := FromDotForm(parts[0])
return po.IsType(ponum, mask)
}
//TextPayloadObject implements 64.0.0.0/4 : Human readable
type TextPayloadObject interface {
PayloadObject
Value() string
}
type TextPayloadObjectImpl struct {
PayloadObjectImpl
}
func LoadTextPayloadObject(ponum int, contents []byte) (*TextPayloadObjectImpl, error) {
bpl, _ := LoadBasePayloadObject(ponum, contents)
return &TextPayloadObjectImpl{*bpl}, nil
}
func LoadTextPayloadObjectPO(ponum int, contents []byte) (PayloadObject, error) {
return LoadTextPayloadObject(ponum, contents)
}
func CreateTextPayloadObject(ponum int, contents string) *TextPayloadObjectImpl {
rv, _ := LoadTextPayloadObject(ponum, []byte(contents))
return rv
}
func (po *TextPayloadObjectImpl) TextRepresentation() string {
return fmt.Sprintf("PO %s len %d (human readable) contents:\n%s", PONumDotForm(po.ponum), len(po.contents), string(po.contents))
}
func (po *TextPayloadObjectImpl) Value() string {
return string(po.contents)
}
type YAMLPayloadObject interface {
PayloadObject
ValueInto(v interface{}) error
}
type YAMLPayloadObjectImpl struct {
TextPayloadObjectImpl
}
func LoadYAMLPayloadObject(ponum int, contents []byte) (*YAMLPayloadObjectImpl, error) {
tpl, _ := LoadTextPayloadObject(ponum, contents)
rv := YAMLPayloadObjectImpl{*tpl}
return &rv, nil
}
func LoadYAMLPayloadObjectPO(ponum int, contents []byte) (PayloadObject, error) {
return LoadYAMLPayloadObject(ponum, contents)
}
func CreateYAMLPayloadObject(ponum int, value interface{}) (*YAMLPayloadObjectImpl, error) {
contents, err := yaml.Marshal(value)
if err != nil {
return nil, err
}
tpl, _ := LoadTextPayloadObject(ponum, contents)
rv := YAMLPayloadObjectImpl{*tpl}
return &rv, nil
}
func (po *YAMLPayloadObjectImpl) ValueInto(v interface{}) error {
err := yaml.Unmarshal(po.contents, v)
return err
}
type MsgPackPayloadObject interface {
PayloadObject
ValueInto(v interface{}) error
}
type MsgPackPayloadObjectImpl struct {
PayloadObjectImpl
}
func LoadMsgPackPayloadObject(ponum int, contents []byte) (*MsgPackPayloadObjectImpl, error) {
bpl, _ := LoadBasePayloadObject(ponum, contents)
rv := MsgPackPayloadObjectImpl{*bpl}
return &rv, nil
}
func LoadMsgPackPayloadObjectPO(ponum int, contents []byte) (PayloadObject, error) {
return LoadMsgPackPayloadObject(ponum, contents)
}
func CreateMsgPackPayloadObject(ponum int, value interface{}) (*MsgPackPayloadObjectImpl, error) {
buf, err := msgpack.Marshal(value)
if err != nil {
return nil, err
}
return LoadMsgPackPayloadObject(ponum, buf)
}
func (po *MsgPackPayloadObjectImpl) ValueInto(v interface{}) error {
err := msgpack.Unmarshal(po.contents, &v)
return err
}
func (po *MsgPackPayloadObjectImpl) TextRepresentation() string {
var x map[string]interface{}
e := po.ValueInto(&x)
if e == nil {
b, err := json.MarshalIndent(x, "", " ")
if err == nil {
return fmt.Sprintf("PO %s len %d (msgpack) contents:\n%+v", PONumDotForm(po.ponum), len(po.contents), string(b))
}
}
return fmt.Sprintf("PO %s len %d (msgpack) contents undecodable, hexdump:\n%s", PONumDotForm(po.ponum), len(po.contents), hex.Dump(po.contents))
}