67 lines
2.4 KiB
Python
67 lines
2.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Validate the bounded Phase 3A datagram header and fixture corpus."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import binascii
|
|
import pathlib
|
|
|
|
ROOT = pathlib.Path(__file__).resolve().parents[1]
|
|
V1_CHANNEL_LIMITS = {1: 1024, 2: 2048, 3: 65515, 10: 1179, 11: 1179, 12: 1179}
|
|
V2_CHANNEL_LIMITS = {10: 1177, 11: 1177}
|
|
|
|
|
|
def classify(raw: bytes) -> str:
|
|
if len(raw) < 3:
|
|
return "invalid:truncated"
|
|
if raw[:2] != b"VD":
|
|
return "invalid:magic"
|
|
if raw[2] not in (1, 2):
|
|
return "invalid:unsupported_version"
|
|
header_bytes = 21 if raw[2] == 1 else 23
|
|
if len(raw) < header_bytes:
|
|
return "invalid:truncated"
|
|
limits = V1_CHANNEL_LIMITS if raw[2] == 1 else V2_CHANNEL_LIMITS
|
|
if raw[3] not in limits:
|
|
return "invalid:unknown_channel"
|
|
if raw[4] != 0:
|
|
return "invalid:flags"
|
|
if raw[2] == 1:
|
|
fragment_index, fragment_count = raw[17], raw[18]
|
|
payload_length = int.from_bytes(raw[19:21], "big")
|
|
else:
|
|
fragment_index = int.from_bytes(raw[17:19], "big")
|
|
fragment_count = int.from_bytes(raw[19:21], "big")
|
|
payload_length = int.from_bytes(raw[21:23], "big")
|
|
if fragment_count > 891:
|
|
return "invalid:fragment_limit"
|
|
if fragment_count == 0 or fragment_index >= fragment_count:
|
|
return "invalid:fragment"
|
|
if payload_length > limits[raw[3]]:
|
|
return "invalid:payload_limit"
|
|
if len(raw) != header_bytes + payload_length:
|
|
return "invalid:length_mismatch"
|
|
if raw[2] == 1 and len(raw) > 65536 or raw[2] == 2 and len(raw) > 1200:
|
|
return "invalid:frame_limit"
|
|
return "valid"
|
|
|
|
|
|
def main() -> None:
|
|
for fixture in ("datagram-v1.tsv", "datagram-v2.tsv"):
|
|
lines = (ROOT / "fixtures/conformance" / fixture).read_text(encoding="utf-8").splitlines()
|
|
assert lines[0] == "id\tversion\tkind\tinput\texpected"
|
|
for line in lines[1:]:
|
|
identifier, version, kind, input_value, expected = line.split("\t")
|
|
assert kind == "datagram" and version in ("1", "2")
|
|
encoded = input_value.removeprefix("hex=")
|
|
try:
|
|
actual = classify(binascii.unhexlify(encoded))
|
|
except binascii.Error:
|
|
actual = "invalid:hex"
|
|
assert actual == expected, f"{fixture}:{identifier}: {actual} != {expected}"
|
|
print("Datagram frame validation passed")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|