Files
Sanaei f727d04f65
CI / go-test (push) Canceled after 0s
CI / postgres-durable-first (push) Canceled after 0s
CI / codegen (push) Canceled after 0s
CI / govulncheck (push) Canceled after 0s
CI / race (push) Canceled after 0s
CI / fuzz-smoke (push) Canceled after 0s
CI / golangci (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CodeQL Advanced / Analyze (go) (push) Canceled after 0s
CodeQL Advanced / Analyze (actions) (push) Canceled after 0s
CodeQL Advanced / Analyze (javascript-typescript) (push) Canceled after 0s
Docs CI / build (push) Canceled after 0s
Docs Deploy (GitHub Pages) / build (push) Canceled after 0s
Release 3X-UI / build (386) (push) Canceled after 0s
Release 3X-UI / build (amd64) (push) Canceled after 0s
Release 3X-UI / build (arm64) (push) Canceled after 0s
Release 3X-UI / build (armv5) (push) Canceled after 0s
Release 3X-UI / build (armv6) (push) Canceled after 0s
Release 3X-UI / build (armv7) (push) Canceled after 0s
Release 3X-UI / build (s390x) (push) Canceled after 0s
Release 3X-UI / Build for Windows (amd64) (push) Canceled after 0s
Deploy Smoke Tests / noninteractive-install (ubuntu-24.04-arm) (push) Canceled after 0s
Deploy Smoke Tests / noninteractive-install (ubuntu-latest) (push) Canceled after 0s
Deploy Smoke Tests / release-tag-install (ubuntu-24.04-arm) (push) Canceled after 0s
Deploy Smoke Tests / release-tag-install (ubuntu-latest) (push) Canceled after 0s
Docs Deploy (GitHub Pages) / deploy (push) Canceled after 0s
Release 3X-UI / Publish rolling dev release (push) Canceled after 0s
v3.7.0
2026-08-24 15:07:15 +02:00

58 lines
1.7 KiB
Go

// Package wirecodec holds the shared envelope codec for node-to-node config
// transport: zstd (de)compression, SHA-256 integrity hashing, and the header /
// capability constants both the panel (sender) and node (receiver) agree on.
package wirecodec
import (
"crypto/sha256"
"encoding/hex"
"errors"
"github.com/klauspost/compress/zstd"
)
const (
// HashHeader carries the lowercase-hex SHA-256 of the (uncompressed) body.
HashHeader = "X-Config-Sha256"
// CapsHeader is set by a node on its API responses to advertise support.
CapsHeader = "X-3x-Node-Caps"
// EncodingZstd is the Content-Encoding value for a zstd-compressed body.
EncodingZstd = "zstd"
// CapZstd is the capability token advertised in CapsHeader.
CapZstd = "zstd"
// maxDecodeBytes bounds in-memory decompression to defuse a zstd bomb from
// an (authenticated) node-API caller.
maxDecodeBytes = 16 << 20
)
// EncodeAll/DecodeAll on these shared instances are safe for concurrent use.
var (
zstdEncoder, _ = zstd.NewWriter(nil)
zstdDecoder, _ = zstd.NewReader(nil, zstd.WithDecoderMaxMemory(maxDecodeBytes))
)
// Compress zstd-compresses b.
func Compress(b []byte) []byte {
return zstdEncoder.EncodeAll(b, nil)
}
// Decompress zstd-decompresses src, rejecting output larger than maxOut (and any
// input that would blow the in-memory bomb ceiling).
func Decompress(src []byte, maxOut int) ([]byte, error) {
out, err := zstdDecoder.DecodeAll(src, nil)
if err != nil {
return nil, err
}
if maxOut > 0 && len(out) > maxOut {
return nil, errors.New("wirecodec: decompressed body exceeds limit")
}
return out, nil
}
// Sha256Hex returns the lowercase-hex SHA-256 of b.
func Sha256Hex(b []byte) string {
sum := sha256.Sum256(b)
return hex.EncodeToString(sum[:])
}