121 lines
1.9 KiB
Go
121 lines
1.9 KiB
Go
package properties
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"errors"
|
|
"io"
|
|
|
|
"badat.dev/maeqtt/v2/mqtt/types"
|
|
)
|
|
|
|
type Property interface {
|
|
id() int
|
|
parse(r *bufio.Reader) error
|
|
write(w io.Writer) error
|
|
hasValue() bool
|
|
}
|
|
|
|
func findMatchingProp(props []Property, id int) *Property {
|
|
for _, prop := range props {
|
|
if prop.id() == id {
|
|
return (&prop)
|
|
}
|
|
}
|
|
return nil
|
|
|
|
}
|
|
|
|
func ParseProperties(r *bufio.Reader, props []Property) error {
|
|
propLen, err := types.DecodeVariableByteInt(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
limitReader := io.LimitReader(r, int64(propLen))
|
|
r = bufio.NewReader(limitReader)
|
|
|
|
for {
|
|
propId, err := r.ReadByte()
|
|
if err != nil {
|
|
if err == io.EOF {
|
|
break
|
|
} else {
|
|
return err
|
|
}
|
|
}
|
|
prop := findMatchingProp(props, int(propId))
|
|
if prop == nil {
|
|
return errors.New("Malformed packet invalid propid")
|
|
}
|
|
err = (*prop).parse(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func WriteProps(w io.Writer, props []Property) error {
|
|
buf := bytes.NewBuffer([]byte{})
|
|
for _, p := range props {
|
|
if p.hasValue() {
|
|
buf.Write([]byte{byte(p.id())})
|
|
err := p.write(buf)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
return types.WriteDataWithVarIntLen(w, buf.Bytes())
|
|
}
|
|
|
|
type KVPair struct {
|
|
key string
|
|
value string
|
|
}
|
|
|
|
type UserProperty struct {
|
|
values []KVPair
|
|
}
|
|
|
|
func (*UserProperty) id() int {
|
|
return 38
|
|
}
|
|
|
|
func (u *UserProperty) parse(r *bufio.Reader) error {
|
|
key, err := types.DecodeUTF8String(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
value, err := types.DecodeUTF8String(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
u.values = append(u.values, KVPair{
|
|
key: key,
|
|
value: value,
|
|
})
|
|
return nil
|
|
}
|
|
|
|
func (u *UserProperty) write(w io.Writer) error {
|
|
for _, k := range u.values {
|
|
err := types.WriteUTF8String(w, k.key)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = types.WriteUTF8String(w, k.value)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (u *UserProperty) hasValue() bool {
|
|
return len(u.values) > 0
|
|
}
|