aboutsummaryrefslogtreecommitdiff
path: root/network/protocol/pktline/header.go
diff options
context:
space:
mode:
Diffstat (limited to 'network/protocol/pktline/header.go')
-rw-r--r--network/protocol/pktline/header.go57
1 files changed, 57 insertions, 0 deletions
diff --git a/network/protocol/pktline/header.go b/network/protocol/pktline/header.go
new file mode 100644
index 00000000..41e50e04
--- /dev/null
+++ b/network/protocol/pktline/header.go
@@ -0,0 +1,57 @@
+package pktline
+
+import "fmt"
+
+func hexval(b byte) int {
+ switch {
+ case b >= '0' && b <= '9':
+ return int(b - '0')
+ case b >= 'a' && b <= 'f':
+ return int(b-'a') + 10
+ case b >= 'A' && b <= 'F':
+ return int(b-'A') + 10
+ default:
+ return -1
+ }
+}
+
+// ParseLengthHeader parses a 4-byte hexadecimal pkt-line length header.
+//
+// The returned value is the full on-wire packet size, including the 4-byte
+// header. Semantic interpretation (data/control/error) is done by Decoder.
+//
+// The 4-byte header is only an actual length when above or equal to 4.
+// Otherwise, it indicates some control packet.
+func ParseLengthHeader(h [4]byte) (int, error) {
+ a := hexval(h[0])
+ b := hexval(h[1])
+ c := hexval(h[2])
+ d := hexval(h[3])
+
+ if a < 0 || b < 0 || c < 0 || d < 0 {
+ return 0, fmt.Errorf("%w: %q", ErrInvalidLength, string(h[:]))
+ }
+
+ return (a << 12) | (b << 8) | (c << 4) | d, nil
+}
+
+// EncodeLengthHeader encodes n as a 4-byte hexadecimal pkt-line header.
+//
+// n is the full on-wire packet size including the 4-byte header.
+//
+// The 4-byte header is only an actual length when above or equal to 4.
+// Otherwise, it indicates some control packet.
+func EncodeLengthHeader(dst *[4]byte, n int) error {
+ if n < 0 || n > LargePacketMax {
+ return fmt.Errorf("%w: %d", ErrInvalidLength, n)
+ }
+
+ const hex = "0123456789abcdef"
+
+ dst[0] = hex[(n>>12)&0xf]
+ dst[1] = hex[(n>>8)&0xf]
+ dst[2] = hex[(n>>4)&0xf]
+ dst[3] = hex[n&0xf]
+
+ return nil
+}