feat(protocol): freeze M4 native session RC6 contract
This commit is contained in:
@@ -8,13 +8,18 @@ import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
import os
|
||||
|
||||
|
||||
ROOT = pathlib.Path(__file__).resolve().parents[1]
|
||||
|
||||
|
||||
def run(command: list[str], directory: pathlib.Path) -> None:
|
||||
result = subprocess.run(command, cwd=directory, text=True, capture_output=True, check=False)
|
||||
environment = os.environ.copy()
|
||||
cache_root = pathlib.Path(tempfile.gettempdir()) / "versevdi-protocol-module-cache"
|
||||
environment.setdefault("CLANG_MODULE_CACHE_PATH", str(cache_root / "clang"))
|
||||
environment.setdefault("SWIFT_MODULECACHE_PATH", str(cache_root / "swift"))
|
||||
result = subprocess.run(command, cwd=directory, env=environment, text=True, capture_output=True, check=False)
|
||||
if result.returncode != 0:
|
||||
raise RuntimeError("%s\n%s%s" % (" ".join(command), result.stdout, result.stderr))
|
||||
|
||||
@@ -58,21 +63,27 @@ def main() -> int:
|
||||
swift.write_text(
|
||||
"""import Foundation
|
||||
|
||||
let video = try VideoProfile(codec: "h264", bitDepth: 8, chromaSubsampling: "4:2:0", colorSpace: "bt709-limited", transferFunction: "sdr")
|
||||
let hevc = try VideoProfile(codec: "hevc", bitDepth: 8, chromaSubsampling: "4:2:0", colorSpace: "bt709-limited", transferFunction: "sdr")
|
||||
let audio = try AudioProfile(codec: "opus", sampleRateHz: 48000, channels: 2, channelLayout: "stereo", packetDurationMs: 5)
|
||||
let display = try DisplayMode(resolutionWidth: 2560, resolutionHeight: 1440, fps: 120)
|
||||
let adjustment = try SessionAdjustment(displayReason: "none", bitrateReason: "none")
|
||||
let descriptor = try SelectedSessionDescriptor(videoProfile: video, audioProfile: audio, displayMode: display, bitrateTargetKbps: 40000, bitrateMaximumKbps: 50000, adjustment: adjustment, mediaTimestampBasis: "gateway-send-wall-clock-ms")
|
||||
let capability = try CapabilityProfile(
|
||||
transport: "quic-tls13", framing: "datagram-v1", media: "encoded",
|
||||
audio: "encoded", sourceRateControl: "server", clientDecode: ["h264-opus"]
|
||||
sourceRateControl: "server", videoProfiles: [video], audioProfiles: [audio]
|
||||
)
|
||||
guard currentWireVersion == "2", nMinus1WireVersion == "1", nMinus2WireVersion == "0" else {
|
||||
fatalError("unexpected control wire compatibility declaration")
|
||||
}
|
||||
_ = try CapabilityProfile(
|
||||
transport: "quic-tls13", framing: "datagram-v2", media: "encoded",
|
||||
audio: "encoded", sourceRateControl: "server", clientDecode: ["h264-opus"]
|
||||
sourceRateControl: "server", videoProfiles: [video], audioProfiles: [audio]
|
||||
)
|
||||
do {
|
||||
_ = try CapabilityProfile(
|
||||
transport: "quic-tls13", framing: "datagram-v3", media: "encoded",
|
||||
audio: "encoded", sourceRateControl: "server", clientDecode: ["h264-opus"]
|
||||
sourceRateControl: "server", videoProfiles: [video], audioProfiles: [audio]
|
||||
)
|
||||
fatalError("unregistered framing was accepted")
|
||||
} catch { }
|
||||
@@ -82,7 +93,7 @@ let request = try TunnelAdmissionRequest(
|
||||
clientNonce: String(repeating: "n", count: 16), deviceSignature: String(repeating: "s", count: 86), capabilities: capability
|
||||
)
|
||||
_ = request
|
||||
let transcript = "versevdi/tunnel-admission/v17:session7:gateway8:audience43:" + String(repeating: "g", count: 43) + "1:016:" + String(repeating: "n", count: 16) + "10:quic-tls1311:datagram-v17:encoded7:encoded6:server1:19:h264-opus"
|
||||
let transcript = "versevdi/tunnel-admission/v17:session7:gateway8:audience43:" + String(repeating: "g", count: 43) + "1:016:" + String(repeating: "n", count: 16) + "10:quic-tls1311:datagram-v17:encoded6:server1:11:14:h2641:85:4:2:013:bt709-limited3:sdr4:opus5:480001:26:stereo1:5"
|
||||
guard String(data: request.deviceAdmissionTranscript(), encoding: .utf8) == transcript else {
|
||||
fatalError("unexpected device admission transcript")
|
||||
}
|
||||
@@ -126,18 +137,18 @@ for (name, field, serverID, principalID, deviceID, challenge, expiry) in invalid
|
||||
}
|
||||
let incompatible = try CapabilityProfile(
|
||||
transport: "quic-tls13", framing: "datagram-v1", media: "encoded",
|
||||
audio: "encoded", sourceRateControl: "server", clientDecode: ["hevc-opus"]
|
||||
sourceRateControl: "server", videoProfiles: [hevc], audioProfiles: [audio]
|
||||
)
|
||||
let gatewayCapability = try CapabilityProfile(
|
||||
transport: "quic-tls13", framing: "datagram-v1", media: "encoded",
|
||||
audio: "encoded", sourceRateControl: "server", clientDecode: ["hevc-opus", "h264-opus"]
|
||||
sourceRateControl: "server", videoProfiles: [hevc, video], audioProfiles: [audio]
|
||||
)
|
||||
do {
|
||||
guard try CapabilityProfile.intersection([capability, capability]) == capability else {
|
||||
fatalError("matching capability profiles did not intersect")
|
||||
}
|
||||
} catch { fatalError("matching capability profiles did not intersect") }
|
||||
guard try CapabilityProfile.intersection([gatewayCapability, capability]).clientDecode == ["h264-opus"] else {
|
||||
guard try CapabilityProfile.intersection([gatewayCapability, capability]).videoProfiles == [video] else {
|
||||
fatalError("ordered registered profile intersection changed")
|
||||
}
|
||||
do {
|
||||
@@ -165,17 +176,22 @@ for invalid in [
|
||||
}
|
||||
let clientAuthority = try ClientSessionAuthority(
|
||||
version: "1", sessionId: "session", gatewayId: "gateway", audience: "audience",
|
||||
reconnectSequence: 2, expiresAt: "2099-01-01T00:00:00Z", capabilities: capability
|
||||
reconnectSequence: 2, expiresAt: "2099-01-01T00:00:00Z", capabilities: capability, selectedDescriptor: descriptor
|
||||
)
|
||||
let clientAuthorityJSON = try clientAuthority.encodeJSON()
|
||||
let clientAuthorityObject = try JSONSerialization.jsonObject(with: clientAuthorityJSON) as! [String: Any]
|
||||
guard Set(clientAuthorityObject.keys) == Set([
|
||||
"version", "session_id", "gateway_id", "audience", "reconnect_sequence", "expires_at", "capabilities"
|
||||
"version", "session_id", "gateway_id", "audience", "reconnect_sequence", "expires_at", "capabilities", "selected_descriptor"
|
||||
]), !String(data: clientAuthorityJSON, encoding: .utf8)!.contains("provider_") else {
|
||||
fatalError("client authority was not exactly provider-free")
|
||||
}
|
||||
_ = try ClientSessionAuthority.decodeJSON(clientAuthorityJSON)
|
||||
for field in ["version", "session_id", "gateway_id", "audience", "reconnect_sequence", "expires_at", "capabilities"] {
|
||||
let duplicateCapability = Data(#"{"transport":"quic-tls13","transport":"quic-tls13","framing":"datagram-v1","media":"encoded","source_rate_control":"server","video_profiles":[{"codec":"h264","bit_depth":8,"chroma_subsampling":"4:2:0","color_space":"bt709-limited","transfer_function":"sdr"}],"audio_profiles":[{"codec":"opus","sample_rate_hz":48000,"channels":2,"channel_layout":"stereo","packet_duration_ms":5}]}"#.utf8)
|
||||
do {
|
||||
_ = try CapabilityProfile.decodeJSON(duplicateCapability)
|
||||
fatalError("capability accepted duplicate JSON keys")
|
||||
} catch { }
|
||||
for field in ["version", "session_id", "gateway_id", "audience", "reconnect_sequence", "expires_at", "capabilities", "selected_descriptor"] {
|
||||
var missing = clientAuthorityObject
|
||||
missing.removeValue(forKey: field)
|
||||
do {
|
||||
@@ -217,7 +233,7 @@ do {
|
||||
)
|
||||
fatalError("invalid allocation bounds were accepted")
|
||||
} catch { }
|
||||
let displayMode = try DisplayMode(resolutionWidth: 2560, resolutionHeight: 1440, fps: 120)
|
||||
let displayMode = display
|
||||
for invalid in [
|
||||
{ try DisplayMode(resolutionWidth: 319, resolutionHeight: 1440, fps: 120) },
|
||||
{ try DisplayMode(resolutionWidth: 2560, resolutionHeight: 199, fps: 120) },
|
||||
@@ -230,14 +246,14 @@ for invalid in [
|
||||
}
|
||||
let policyFreeV2Request = try SessionRequest(
|
||||
clientDeviceId: "device-1", deviceKeyId: "key-1", poolId: "pool-1",
|
||||
idempotencyKey: "request-1", requestedDisplayMode: nil
|
||||
idempotencyKey: "request-1", videoProfiles: [video], bitratePreference: try BitratePreference(mode: "auto", targetKbps: nil), requestedDisplayMode: nil
|
||||
).encodeJSON()
|
||||
guard !String(data: policyFreeV2Request, encoding: .utf8)!.contains("requested_display_mode") else {
|
||||
fatalError("wire-v2 request encoded an absent display mode")
|
||||
}
|
||||
let displayRequest = try SessionRequest(
|
||||
clientDeviceId: "device-1", deviceKeyId: "key-1", poolId: "pool-1",
|
||||
idempotencyKey: "request-1", requestedDisplayMode: displayMode
|
||||
idempotencyKey: "request-1", videoProfiles: [video], bitratePreference: try BitratePreference(mode: "explicit", targetKbps: 40000), requestedDisplayMode: displayMode
|
||||
)
|
||||
guard try SessionRequest.decodeJSON(displayRequest.encodeJSON()).requestedDisplayMode == displayMode else {
|
||||
fatalError("display mode did not round-trip")
|
||||
@@ -295,14 +311,14 @@ for expiresAt in ["2099-01-01T00:00:00+00:00", "2099-01-01T00:00:00.100Z"] {
|
||||
} catch { }
|
||||
}
|
||||
let streamPolicy = try ProviderStreamPolicy(
|
||||
resolutionWidth: 2560, resolutionHeight: 1440, fps: 120,
|
||||
codec: "HEVC", bitrateKbps: 40000, audioEnabled: true
|
||||
videoProfile: hevc, audioProfile: audio, displayMode: displayMode,
|
||||
bitrateTargetKbps: 40000, bitrateMaximumKbps: 50000
|
||||
)
|
||||
guard streamPolicy.codec == "HEVC" else { fatalError("stream policy changed") }
|
||||
guard streamPolicy.videoProfile == hevc else { fatalError("stream policy changed") }
|
||||
for invalid in [
|
||||
{ try ProviderStreamPolicy(resolutionWidth: 319, resolutionHeight: 1440, fps: 120, codec: "HEVC", bitrateKbps: 40000, audioEnabled: true) },
|
||||
{ try ProviderStreamPolicy(resolutionWidth: 2560, resolutionHeight: 1440, fps: 241, codec: "HEVC", bitrateKbps: 40000, audioEnabled: true) },
|
||||
{ try ProviderStreamPolicy(resolutionWidth: 2560, resolutionHeight: 1440, fps: 120, codec: "VP9", bitrateKbps: 40000, audioEnabled: true) },
|
||||
{ try ProviderStreamPolicy(videoProfile: video, audioProfile: audio, displayMode: try DisplayMode(resolutionWidth: 319, resolutionHeight: 1440, fps: 120), bitrateTargetKbps: 40000, bitrateMaximumKbps: 50000) },
|
||||
{ try ProviderStreamPolicy(videoProfile: video, audioProfile: audio, displayMode: displayMode, bitrateTargetKbps: 50001, bitrateMaximumKbps: 50000) },
|
||||
{ try ProviderStreamPolicy(videoProfile: try VideoProfile(codec: "vp9", bitDepth: 8, chromaSubsampling: "4:2:0", colorSpace: "bt709-limited", transferFunction: "sdr"), audioProfile: audio, displayMode: displayMode, bitrateTargetKbps: 40000, bitrateMaximumKbps: 50000) },
|
||||
] {
|
||||
do {
|
||||
_ = try invalid()
|
||||
@@ -363,17 +379,23 @@ fn main() {
|
||||
assert_eq!(CURRENT_WIRE_VERSION, "2");
|
||||
assert_eq!(N_MINUS_1_WIRE_VERSION, "1");
|
||||
assert_eq!(N_MINUS_2_WIRE_VERSION, "0");
|
||||
let video = VideoProfile::new("h264".into(), 8, "4:2:0".into(), "bt709-limited".into(), "sdr".into()).unwrap();
|
||||
let hevc = VideoProfile::new("hevc".into(), 8, "4:2:0".into(), "bt709-limited".into(), "sdr".into()).unwrap();
|
||||
let audio = AudioProfile::new("opus".into(), 48000, 2, "stereo".into(), 5).unwrap();
|
||||
let display = DisplayMode::new(2560, 1440, 120).unwrap();
|
||||
let adjustment = SessionAdjustment::new("none".into(), "none".into()).unwrap();
|
||||
let descriptor = SelectedSessionDescriptor::new(video.clone(), audio.clone(), display.clone(), 40000, 50000, adjustment, "gateway-send-wall-clock-ms".into()).unwrap();
|
||||
let capabilities = CapabilityProfile::new(
|
||||
"quic-tls13".into(), "datagram-v1".into(), "encoded".into(),
|
||||
"encoded".into(), "server".into(), vec!["h264-opus".into()],
|
||||
"server".into(), vec![video.clone()], vec![audio.clone()],
|
||||
).unwrap();
|
||||
assert!(CapabilityProfile::new(
|
||||
"quic-tls13".into(), "datagram-v2".into(), "encoded".into(),
|
||||
"encoded".into(), "server".into(), vec!["h264-opus".into()],
|
||||
"server".into(), vec![video.clone()], vec![audio.clone()],
|
||||
).is_ok());
|
||||
assert!(CapabilityProfile::new(
|
||||
"quic-tls13".into(), "datagram-v3".into(), "encoded".into(),
|
||||
"encoded".into(), "server".into(), vec!["h264-opus".into()],
|
||||
"server".into(), vec![video.clone()], vec![audio.clone()],
|
||||
).is_err());
|
||||
let request = TunnelAdmissionRequest::new(
|
||||
"1".into(), "session".into(), "gateway".into(), "audience".into(),
|
||||
@@ -381,7 +403,7 @@ fn main() {
|
||||
).unwrap();
|
||||
let transcript = "versevdi/tunnel-admission/v17:session7:gateway8:audience43:".to_string()
|
||||
+ &"g".repeat(43) + "1:016:" + &"n".repeat(16)
|
||||
+ "10:quic-tls1311:datagram-v17:encoded7:encoded6:server1:19:h264-opus";
|
||||
+ "10:quic-tls1311:datagram-v17:encoded6:server1:11:14:h2641:85:4:2:013:bt709-limited3:sdr4:opus5:480001:26:stereo1:5";
|
||||
assert_eq!(request.device_admission_transcript(), transcript.into_bytes());
|
||||
let proof_server_id = vec![1u8; 16];
|
||||
let proof_principal_id = vec![2u8; 16];
|
||||
@@ -423,26 +445,26 @@ fn main() {
|
||||
).is_err());
|
||||
let client_authority = ClientSessionAuthority::new(
|
||||
"1".into(), "session".into(), "gateway".into(), "audience".into(), 2,
|
||||
"2099-01-01T00:00:00Z".into(), capabilities.clone(),
|
||||
"2099-01-01T00:00:00Z".into(), capabilities.clone(), descriptor.clone(),
|
||||
).unwrap();
|
||||
assert_eq!(client_authority.sessionId(), "session");
|
||||
assert_eq!(client_authority.capabilities(), &capabilities);
|
||||
assert!(ClientSessionAuthority::new(
|
||||
"1".into(), "session".into(), "gateway".into(), "audience".into(), 2,
|
||||
"not-a-time".into(), capabilities.clone(),
|
||||
"not-a-time".into(), capabilities.clone(), descriptor.clone(),
|
||||
).is_err());
|
||||
assert!(intersect_capability_profiles(&[capabilities.clone(), capabilities.clone()]).is_ok());
|
||||
let incompatible = CapabilityProfile::new(
|
||||
"quic-tls13".into(), "datagram-v1".into(), "encoded".into(),
|
||||
"encoded".into(), "server".into(), vec!["hevc-opus".into()],
|
||||
"server".into(), vec![hevc.clone()], vec![audio.clone()],
|
||||
).unwrap();
|
||||
let gateway_capability = CapabilityProfile::new(
|
||||
"quic-tls13".into(), "datagram-v1".into(), "encoded".into(),
|
||||
"encoded".into(), "server".into(), vec!["hevc-opus".into(), "h264-opus".into()],
|
||||
"server".into(), vec![hevc.clone(), video.clone()], vec![audio.clone()],
|
||||
).unwrap();
|
||||
assert_eq!(
|
||||
intersect_capability_profiles(&[gateway_capability, capabilities.clone()]).unwrap().clientDecode(),
|
||||
&vec!["h264-opus".to_string()],
|
||||
intersect_capability_profiles(&[gateway_capability, capabilities.clone()]).unwrap().videoProfiles(),
|
||||
&vec![video.clone()],
|
||||
);
|
||||
assert!(intersect_capability_profiles(&[capabilities, incompatible]).is_err());
|
||||
assert!(AllocationPolicy::new(
|
||||
@@ -454,11 +476,13 @@ fn main() {
|
||||
assert!(DisplayMode::new(2560, 1440, 241).is_err());
|
||||
let policy_free_v2_request = SessionRequest::new(
|
||||
"device-1".into(), "key-1".into(), "pool-1".into(), "request-1".into(),
|
||||
vec![video.clone()], BitratePreference::new("auto".into(), None).unwrap(),
|
||||
None,
|
||||
).unwrap();
|
||||
assert!(policy_free_v2_request.requestedDisplayMode().is_none());
|
||||
let display_request = SessionRequest::new(
|
||||
"device-1".into(), "key-1".into(), "pool-1".into(), "request-1".into(),
|
||||
vec![video.clone()], BitratePreference::new("explicit".into(), Some(40000)).unwrap(),
|
||||
Some(display_mode.clone()),
|
||||
).unwrap();
|
||||
assert_eq!(display_request.requestedDisplayMode(), &Some(display_mode));
|
||||
@@ -486,17 +510,13 @@ fn main() {
|
||||
).is_err());
|
||||
}
|
||||
assert!(ProviderStreamPolicy::new(
|
||||
2560, 1440, 120, "HEVC".into(), 40000, true,
|
||||
hevc.clone(), audio.clone(), display.clone(), 40000, 50000,
|
||||
).is_ok());
|
||||
assert!(DisplayMode::new(319, 1440, 120).is_err());
|
||||
assert!(ProviderStreamPolicy::new(
|
||||
319, 1440, 120, "HEVC".into(), 40000, true,
|
||||
).is_err());
|
||||
assert!(ProviderStreamPolicy::new(
|
||||
2560, 1440, 241, "HEVC".into(), 40000, true,
|
||||
).is_err());
|
||||
assert!(ProviderStreamPolicy::new(
|
||||
2560, 1440, 120, "VP9".into(), 40000, true,
|
||||
video.clone(), audio.clone(), display.clone(), 50001, 50000,
|
||||
).is_err());
|
||||
assert!(VideoProfile::new("vp9".into(), 8, "4:2:0".into(), "bt709-limited".into(), "sdr".into()).is_err());
|
||||
assert!(GatewayTelemetry::new(
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, "ready".into(),
|
||||
).is_ok());
|
||||
@@ -532,6 +552,7 @@ fn main() {
|
||||
("reconnect_sequence", 5),
|
||||
("expires_at", 6),
|
||||
("capabilities", 7),
|
||||
("selected_descriptor", 8),
|
||||
]
|
||||
actual_protobuf_fields = protobuf_message_fields("ClientSessionAuthority")
|
||||
if actual_protobuf_fields != expected_protobuf_fields:
|
||||
|
||||
Reference in New Issue
Block a user