///|
pub const TLV_ALPN : Byte = b'\x01'
///|
pub const TLV_AUTHORITY : Byte = b'\x02'
///|
pub const TLV_CRC32C : Byte = b'\x03'
///|
pub const TLV_NOOP : Byte = b'\x04'
///|
pub const TLV_UNIQUE_ID : Byte = b'\x05'
///|
pub const TLV_SSL : Byte = b'\x20'
///|
pub const TLV_SSL_VERSION : Byte = b'\x21'
///|
pub const TLV_SSL_CN : Byte = b'\x22'
///|
pub const TLV_SSL_CIPHER : Byte = b'\x23'
///|
pub const TLV_SSL_SIG_ALG : Byte = b'\x24'
///|
pub const TLV_SSL_KEY_ALG : Byte = b'\x25'
///|
pub const TLV_SSL_GROUP : Byte = b'\x26'
///|
pub const TLV_SSL_SIG_SCHEME : Byte = b'\x27'
///|
pub const TLV_SSL_CLIENT_CERT : Byte = b'\x28'
///|
pub const TLV_NETNS : Byte = b'\x30'
///|
fn is_registered_tlv(kind : Byte) -> Bool {
let n = kind.to_int()
n == 1 ||
n == 2 ||
n == 3 ||
n == 4 ||
n == 5 ||
(n >= 0x20 && n <= 0x28) ||
n == 0x30
}
///|
pub fn parse_tlvs(
input : Bytes,
offset? : Int = 0,
preserve_unknown? : Bool = true,
) -> Result[Array[RawTlv], ProxyError] {
let result = Array::make(0, { type_code: b'\x00', value: Bytes::new(0) })
let mut at = 0
let mut saw_crc = false
while at < input.length() {
if input.length() - at < 3 {
return Err(
proxy_error(TruncatedTlv, offset + at, "incomplete TLV header"),
)
}
let kind = input[at]
let length = (input[at + 1].to_int() << 8) | input[at + 2].to_int()
if length > input.length() - at - 3 {
return Err(
proxy_error(
TruncatedTlv,
offset + at,
"declared TLV value exceeds header",
),
)
}
let value = Bytes::from_array(input.to_array()[at + 3:at + 3 + length])
if kind == TLV_CRC32C {
if length != 4 {
return Err(
proxy_error(InvalidTlv, offset + at, "CRC32C TLV must be four bytes"),
)
}
if saw_crc {
return Err(
proxy_error(DuplicateCrc32c, offset + at, "more than one CRC32C TLV"),
)
}
saw_crc = true
}
if is_registered_tlv(kind) || preserve_unknown {
result.push({ type_code: kind, value })
}
at = at + 3 + length
}
Ok(result)
}
///|
pub fn encode_tlvs(tlvs : Array[RawTlv]) -> Result[Bytes, ProxyError] {
let buffer = @buffer.Buffer(size_hint=32)
let mut saw_crc = false
for tlv in tlvs {
if tlv.value.length() > 65535 {
return Err(
proxy_error(InvalidLength, 0, "TLV value is longer than 65535 bytes"),
)
}
if tlv.type_code == TLV_CRC32C {
if saw_crc {
return Err(proxy_error(DuplicateCrc32c, 0, "more than one CRC32C TLV"))
}
if tlv.value.length() != 4 {
return Err(proxy_error(InvalidTlv, 0, "CRC32C TLV must be four bytes"))
}
saw_crc = true
}
buffer.write_byte(tlv.type_code)
buffer.write_bytes(write_u16_be(tlv.value.length()))
buffer.write_bytes(tlv.value)
}
Ok(buffer.to_bytes())
}
///|
pub fn find_tlv(tlvs : Array[RawTlv], type_code : Byte) -> RawTlv? {
for tlv in tlvs {
if tlv.type_code == type_code {
return Some(tlv)
}
}
None
}
///|
pub fn find_all_tlvs(tlvs : Array[RawTlv], type_code : Byte) -> Array[RawTlv] {
let result = Array::make(0, { type_code: b'\x00', value: Bytes::new(0) })
for tlv in tlvs {
if tlv.type_code == type_code {
result.push(tlv)
}
}
result
}