2024-10-16 19:05:55 +00:00
|
|
|
package v3
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/binary"
|
|
|
|
"errors"
|
2024-10-31 21:05:15 +00:00
|
|
|
"fmt"
|
2024-10-16 19:05:55 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
datagramRequestIdLen = 16
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
// ErrInvalidRequestIDLen is returned when the provided request id can not be parsed from the provided byte slice.
|
|
|
|
ErrInvalidRequestIDLen error = errors.New("invalid request id length provided")
|
|
|
|
// ErrInvalidPayloadDestLen is returned when the provided destination byte slice cannot fit the whole request id.
|
|
|
|
ErrInvalidPayloadDestLen error = errors.New("invalid payload size provided")
|
|
|
|
)
|
|
|
|
|
|
|
|
// RequestID is the request-id-v2 identifier, it is used to distinguish between specific flows or sessions proxied
|
|
|
|
// from the edge to cloudflared.
|
|
|
|
type RequestID uint128
|
|
|
|
|
|
|
|
type uint128 struct {
|
|
|
|
hi uint64
|
|
|
|
lo uint64
|
|
|
|
}
|
|
|
|
|
|
|
|
// RequestIDFromSlice reads a request ID from a byte slice.
|
|
|
|
func RequestIDFromSlice(data []byte) (RequestID, error) {
|
|
|
|
if len(data) != datagramRequestIdLen {
|
|
|
|
return RequestID{}, ErrInvalidRequestIDLen
|
|
|
|
}
|
|
|
|
|
|
|
|
return RequestID{
|
|
|
|
hi: binary.BigEndian.Uint64(data[:8]),
|
|
|
|
lo: binary.BigEndian.Uint64(data[8:]),
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2024-10-31 21:05:15 +00:00
|
|
|
func (id RequestID) String() string {
|
|
|
|
return fmt.Sprintf("%016x%016x", id.hi, id.lo)
|
|
|
|
}
|
|
|
|
|
2024-10-16 19:05:55 +00:00
|
|
|
// Compare returns an integer comparing two IPs.
|
|
|
|
// The result will be 0 if id == id2, -1 if id < id2, and +1 if id > id2.
|
|
|
|
// The definition of "less than" is the same as the [RequestID.Less] method.
|
|
|
|
func (id RequestID) Compare(id2 RequestID) int {
|
|
|
|
hi1, hi2 := id.hi, id2.hi
|
|
|
|
if hi1 < hi2 {
|
|
|
|
return -1
|
|
|
|
}
|
|
|
|
if hi1 > hi2 {
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
lo1, lo2 := id.lo, id2.lo
|
|
|
|
if lo1 < lo2 {
|
|
|
|
return -1
|
|
|
|
}
|
|
|
|
if lo1 > lo2 {
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
// Less reports whether id sorts before id2.
|
|
|
|
func (id RequestID) Less(id2 RequestID) bool { return id.Compare(id2) == -1 }
|
|
|
|
|
|
|
|
// MarshalBinaryTo writes the id to the provided destination byte slice; the byte slice must be of at least size 16.
|
|
|
|
func (id RequestID) MarshalBinaryTo(data []byte) error {
|
|
|
|
if len(data) < datagramRequestIdLen {
|
|
|
|
return ErrInvalidPayloadDestLen
|
|
|
|
}
|
|
|
|
binary.BigEndian.PutUint64(data[:8], id.hi)
|
|
|
|
binary.BigEndian.PutUint64(data[8:], id.lo)
|
|
|
|
return nil
|
|
|
|
}
|