mirror of https://github.com/edouardparis/lntop
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
118 lines
2.8 KiB
Go
118 lines
2.8 KiB
Go
package macaroon
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"fmt"
|
|
)
|
|
|
|
type fieldType int
|
|
|
|
// Field constants as used in the binary encoding.
|
|
const (
|
|
fieldEOS fieldType = 0
|
|
fieldLocation fieldType = 1
|
|
fieldIdentifier fieldType = 2
|
|
fieldVerificationId fieldType = 4
|
|
fieldSignature fieldType = 6
|
|
)
|
|
|
|
type packetV2 struct {
|
|
// fieldType holds the type of the field.
|
|
fieldType fieldType
|
|
|
|
// data holds the packet's data.
|
|
data []byte
|
|
}
|
|
|
|
// parseSectionV2 parses a sequence of packets
|
|
// in data. The sequence is terminated by a packet
|
|
// with a field type of fieldEOS.
|
|
func parseSectionV2(data []byte) ([]byte, []packetV2, error) {
|
|
prevFieldType := fieldType(-1)
|
|
var packets []packetV2
|
|
for {
|
|
if len(data) == 0 {
|
|
return nil, nil, fmt.Errorf("section extends past end of buffer")
|
|
}
|
|
rest, p, err := parsePacketV2(data)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
if p.fieldType == fieldEOS {
|
|
return rest, packets, nil
|
|
}
|
|
if p.fieldType <= prevFieldType {
|
|
return nil, nil, fmt.Errorf("fields out of order")
|
|
}
|
|
packets = append(packets, p)
|
|
prevFieldType = p.fieldType
|
|
data = rest
|
|
}
|
|
}
|
|
|
|
// parsePacketV2 parses a V2 data package at the start
|
|
// of the given data.
|
|
// The format of a packet is as follows:
|
|
//
|
|
// fieldType(varint) payloadLen(varint) data[payloadLen bytes]
|
|
//
|
|
// apart from fieldEOS which has no payloadLen or data (it's
|
|
// a single zero byte).
|
|
func parsePacketV2(data []byte) ([]byte, packetV2, error) {
|
|
data, ft, err := parseVarint(data)
|
|
if err != nil {
|
|
return nil, packetV2{}, err
|
|
}
|
|
p := packetV2{
|
|
fieldType: fieldType(ft),
|
|
}
|
|
if p.fieldType == fieldEOS {
|
|
return data, p, nil
|
|
}
|
|
data, payloadLen, err := parseVarint(data)
|
|
if err != nil {
|
|
return nil, packetV2{}, err
|
|
}
|
|
if payloadLen > len(data) {
|
|
return nil, packetV2{}, fmt.Errorf("field data extends past end of buffer")
|
|
}
|
|
p.data = data[0:payloadLen]
|
|
return data[payloadLen:], p, nil
|
|
}
|
|
|
|
// parseVarint parses the variable-length integer
|
|
// at the start of the given data and returns rest
|
|
// of the buffer and the number.
|
|
func parseVarint(data []byte) ([]byte, int, error) {
|
|
val, n := binary.Uvarint(data)
|
|
if n > 0 {
|
|
if val > 0x7fffffff {
|
|
return nil, 0, fmt.Errorf("varint value out of range")
|
|
}
|
|
return data[n:], int(val), nil
|
|
}
|
|
if n == 0 {
|
|
return nil, 0, fmt.Errorf("varint value extends past end of buffer")
|
|
}
|
|
return nil, 0, fmt.Errorf("varint value out of range")
|
|
}
|
|
|
|
func appendPacketV2(data []byte, p packetV2) []byte {
|
|
data = appendVarint(data, int(p.fieldType))
|
|
if p.fieldType != fieldEOS {
|
|
data = appendVarint(data, len(p.data))
|
|
data = append(data, p.data...)
|
|
}
|
|
return data
|
|
}
|
|
|
|
func appendEOSV2(data []byte) []byte {
|
|
return append(data, 0)
|
|
}
|
|
|
|
func appendVarint(data []byte, x int) []byte {
|
|
var buf [binary.MaxVarintLen32]byte
|
|
n := binary.PutUvarint(buf[:], uint64(x))
|
|
return append(data, buf[:n]...)
|
|
}
|