Adding upstream version 1.34.4.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
e393c3af3f
commit
4978089aab
4963 changed files with 677545 additions and 0 deletions
167
plugins/common/socket/splitters.go
Normal file
167
plugins/common/socket/splitters.go
Normal file
|
@ -0,0 +1,167 @@
|
|||
package socket
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type lengthFieldSpec struct {
|
||||
Offset int64 `toml:"offset"`
|
||||
Bytes int64 `toml:"bytes"`
|
||||
Endianness string `toml:"endianness"`
|
||||
HeaderLength int64 `toml:"header_length"`
|
||||
converter func([]byte) int
|
||||
}
|
||||
|
||||
type SplitConfig struct {
|
||||
SplittingStrategy string `toml:"splitting_strategy"`
|
||||
SplittingDelimiter string `toml:"splitting_delimiter"`
|
||||
SplittingLength int `toml:"splitting_length"`
|
||||
SplittingLengthField lengthFieldSpec `toml:"splitting_length_field"`
|
||||
}
|
||||
|
||||
func (cfg *SplitConfig) NewSplitter() (bufio.SplitFunc, error) {
|
||||
switch cfg.SplittingStrategy {
|
||||
case "", "newline":
|
||||
return bufio.ScanLines, nil
|
||||
case "null":
|
||||
return scanNull, nil
|
||||
case "delimiter":
|
||||
re := regexp.MustCompile(`(\s*0?x)`)
|
||||
d := re.ReplaceAllString(strings.ToLower(cfg.SplittingDelimiter), "")
|
||||
delimiter, err := hex.DecodeString(d)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("decoding delimiter failed: %w", err)
|
||||
}
|
||||
return createScanDelimiter(delimiter), nil
|
||||
case "fixed length":
|
||||
return createScanFixedLength(cfg.SplittingLength), nil
|
||||
case "variable length":
|
||||
// Create the converter function
|
||||
var order binary.ByteOrder
|
||||
switch strings.ToLower(cfg.SplittingLengthField.Endianness) {
|
||||
case "", "be":
|
||||
order = binary.BigEndian
|
||||
case "le":
|
||||
order = binary.LittleEndian
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid 'endianness' %q", cfg.SplittingLengthField.Endianness)
|
||||
}
|
||||
|
||||
switch cfg.SplittingLengthField.Bytes {
|
||||
case 1:
|
||||
cfg.SplittingLengthField.converter = func(b []byte) int {
|
||||
return int(b[0])
|
||||
}
|
||||
case 2:
|
||||
cfg.SplittingLengthField.converter = func(b []byte) int {
|
||||
return int(order.Uint16(b))
|
||||
}
|
||||
case 4:
|
||||
cfg.SplittingLengthField.converter = func(b []byte) int {
|
||||
return int(order.Uint32(b))
|
||||
}
|
||||
case 8:
|
||||
cfg.SplittingLengthField.converter = func(b []byte) int {
|
||||
return int(order.Uint64(b))
|
||||
}
|
||||
default:
|
||||
cfg.SplittingLengthField.converter = func(b []byte) int {
|
||||
buf := make([]byte, 8)
|
||||
start := 0
|
||||
if order == binary.BigEndian {
|
||||
start = 8 - len(b)
|
||||
}
|
||||
for i := 0; i < len(b); i++ {
|
||||
buf[start+i] = b[i]
|
||||
}
|
||||
return int(order.Uint64(buf))
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we have enough bytes in the header
|
||||
return createScanVariableLength(cfg.SplittingLengthField), nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("unknown 'splitting_strategy' %q", cfg.SplittingStrategy)
|
||||
}
|
||||
|
||||
func scanNull(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
||||
if atEOF && len(data) == 0 {
|
||||
return 0, nil, nil
|
||||
}
|
||||
if i := bytes.IndexByte(data, 0); i >= 0 {
|
||||
return i + 1, data[:i], nil
|
||||
}
|
||||
if atEOF {
|
||||
return len(data), data, nil
|
||||
}
|
||||
// Request more data.
|
||||
return 0, nil, nil
|
||||
}
|
||||
|
||||
func createScanDelimiter(delimiter []byte) bufio.SplitFunc {
|
||||
return func(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
||||
if atEOF && len(data) == 0 {
|
||||
return 0, nil, nil
|
||||
}
|
||||
if i := bytes.Index(data, delimiter); i >= 0 {
|
||||
return i + len(delimiter), data[:i], nil
|
||||
}
|
||||
if atEOF {
|
||||
return len(data), data, nil
|
||||
}
|
||||
// Request more data.
|
||||
return 0, nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
func createScanFixedLength(length int) bufio.SplitFunc {
|
||||
return func(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
||||
if atEOF && len(data) == 0 {
|
||||
return 0, nil, nil
|
||||
}
|
||||
if len(data) >= length {
|
||||
return length, data[:length], nil
|
||||
}
|
||||
if atEOF {
|
||||
return len(data), data, nil
|
||||
}
|
||||
// Request more data.
|
||||
return 0, nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
func createScanVariableLength(spec lengthFieldSpec) bufio.SplitFunc {
|
||||
minlen := int(spec.Offset)
|
||||
minlen += int(spec.Bytes)
|
||||
headerLen := int(spec.HeaderLength)
|
||||
|
||||
return func(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
||||
if atEOF && len(data) == 0 {
|
||||
return 0, nil, nil
|
||||
}
|
||||
dataLen := len(data)
|
||||
if dataLen >= minlen {
|
||||
// Extract the length field and convert it to a number
|
||||
lf := data[spec.Offset : spec.Offset+spec.Bytes]
|
||||
length := spec.converter(lf)
|
||||
start := headerLen
|
||||
end := length + headerLen
|
||||
// If we have enough data return it without the header
|
||||
if end <= dataLen {
|
||||
return end, data[start:end], nil
|
||||
}
|
||||
}
|
||||
if atEOF {
|
||||
return len(data), data, nil
|
||||
}
|
||||
// Request more data.
|
||||
return 0, nil, nil
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue