#!/usr/bin/env python3 """Compile and exercise strict generated Swift and Rust gateway contracts.""" from __future__ import annotations import pathlib 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: 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)) def run_failure(command: list[str], directory: pathlib.Path, expected: str) -> None: result = subprocess.run(command, cwd=directory, text=True, capture_output=True, check=False) if result.returncode == 0 or expected not in result.stdout + result.stderr: raise RuntimeError("expected failure: %s\n%s%s" % (" ".join(command), result.stdout, result.stderr)) def protobuf_message_fields(name: str) -> list[tuple[str, int]]: result = subprocess.run( ["protoc", "--decode=google.protobuf.FileDescriptorSet", "google/protobuf/descriptor.proto"], input=(ROOT / "gen/protobuf/tunnel-v1.pb").read_bytes(), capture_output=True, check=False, ) if result.returncode != 0: raise RuntimeError(result.stderr.decode()) lines = result.stdout.decode().splitlines() marker = f' name: "{name}"' try: name_index = lines.index(marker) start = max(index for index in range(name_index) if lines[index] == " message_type {") except (ValueError, StopIteration) as exc: raise RuntimeError(f"protobuf descriptor missing message {name}") from exc depth = 0 block: list[str] = [] for line in lines[start:]: depth += line.count("{") - line.count("}") block.append(line) if depth == 0: break return [(field, int(number)) for field, number in re.findall(r' field \{\n name: "([^"]+)"\n number: (\d+)', "\n".join(block))] def main() -> int: with tempfile.TemporaryDirectory(prefix="versevdi-generated-contracts-") as temporary: workspace = pathlib.Path(temporary) swift = workspace / "main.swift" 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 operationId = "12345678-1234-1234-1234-123456789abc" _ = try GatewayQualityWorkRequest(version: "1", sessionId: "session", gatewayId: "gateway", reconnectSequence: 2, acquisition: "poll", operationId: nil, revision: nil, leaseGeneration: nil, currentAppliedRevision: nil) _ = try GatewayQualityWorkRequest(version: "1", sessionId: "session", gatewayId: "gateway", reconnectSequence: 2, acquisition: "prompt", operationId: operationId, revision: 7, leaseGeneration: nil, currentAppliedRevision: nil) _ = try GatewayQualityWorkRequest(version: "1", sessionId: "session", gatewayId: "gateway", reconnectSequence: 2, acquisition: "observation", operationId: operationId, revision: 7, leaseGeneration: 3, currentAppliedRevision: 6) do { _ = try GatewayQualityWorkRequest(version: "1", sessionId: "session", gatewayId: "gateway", reconnectSequence: 2, acquisition: "poll", operationId: operationId, revision: 7, leaseGeneration: nil, currentAppliedRevision: nil) fatalError("poll accepted unknown operation coordinates") } catch { } _ = try GatewayQualityAck(version: "1", sessionId: "session", gatewayId: "gateway", reconnectSequence: 2, operationId: operationId, revision: 7, leaseGeneration: 3, outcome: "applied", currentAppliedRevision: 7, failureCode: nil) _ = try GatewayQualityAck(version: "1", sessionId: "session", gatewayId: "gateway", reconnectSequence: 2, operationId: operationId, revision: 7, leaseGeneration: 3, outcome: "proven_prior", currentAppliedRevision: 6, failureCode: nil) _ = try GatewayQualityAck(version: "1", sessionId: "session", gatewayId: "gateway", reconnectSequence: 2, operationId: operationId, revision: 7, leaseGeneration: 3, outcome: "unknown", currentAppliedRevision: nil, failureCode: nil) do { _ = try GatewayQualityAck(version: "1", sessionId: "session", gatewayId: "gateway", reconnectSequence: 2, operationId: operationId, revision: 7, leaseGeneration: 3, outcome: "applied", currentAppliedRevision: 6, failureCode: nil) fatalError("applied ack accepted a contradictory revision") } catch { } let capability = try CapabilityProfile( transport: "quic-tls13", framing: "datagram-v1", media: "encoded", 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", sourceRateControl: "server", videoProfiles: [video], audioProfiles: [audio] ) do { _ = try CapabilityProfile( transport: "quic-tls13", framing: "datagram-v3", media: "encoded", sourceRateControl: "server", videoProfiles: [video], audioProfiles: [audio] ) fatalError("unregistered framing was accepted") } catch { } let request = try TunnelAdmissionRequest( version: "1", sessionId: "session", gatewayId: "gateway", audience: "audience", grant: String(repeating: "g", count: 43), reconnectSequence: 0, 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: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") } let proofServerID = Data(repeating: 1, count: 16) let proofPrincipalID = Data(repeating: 2, count: 16) let proofDeviceID = Data(repeating: 3, count: 16) let proofChallenge = Data(repeating: 4, count: 32) let proofTranscript = try deviceRegistrationProofTranscript( serverID: proofServerID, principalID: proofPrincipalID, deviceID: proofDeviceID, challenge: proofChallenge, expiryUnixMilliseconds: 1 ) guard proofTranscript.count == 112, String(data: proofTranscript.prefix(24), encoding: .utf8) == "versevdi-device-proof-v1", Array(proofTranscript.suffix(8)) == [0, 0, 0, 0, 0, 0, 0, 1] else { fatalError("unexpected device registration proof transcript") } let invalidProofInputs: [(String, String, Data, Data, Data, Data, Int64)] = [ ("server-short", "server_id", Data(repeating: 0, count: 15), proofPrincipalID, proofDeviceID, proofChallenge, 0), ("server-long", "server_id", Data(repeating: 0, count: 17), proofPrincipalID, proofDeviceID, proofChallenge, 0), ("principal-short", "principal_id", proofServerID, Data(repeating: 0, count: 15), proofDeviceID, proofChallenge, 0), ("principal-long", "principal_id", proofServerID, Data(repeating: 0, count: 17), proofDeviceID, proofChallenge, 0), ("device-short", "device_id", proofServerID, proofPrincipalID, Data(repeating: 0, count: 15), proofChallenge, 0), ("device-long", "device_id", proofServerID, proofPrincipalID, Data(repeating: 0, count: 17), proofChallenge, 0), ("challenge-short", "challenge", proofServerID, proofPrincipalID, proofDeviceID, Data(repeating: 0, count: 31), 0), ("challenge-long", "challenge", proofServerID, proofPrincipalID, proofDeviceID, Data(repeating: 0, count: 33), 0), ("negative-expiry", "expiry_unix_milliseconds", proofServerID, proofPrincipalID, proofDeviceID, proofChallenge, -1), ] for (name, field, serverID, principalID, deviceID, challenge, expiry) in invalidProofInputs { do { _ = try deviceRegistrationProofTranscript( serverID: serverID, principalID: principalID, deviceID: deviceID, challenge: challenge, expiryUnixMilliseconds: expiry ) fatalError("\(name) was accepted") } catch let error as ContractValidationError { guard error.field == field, error.code == (field == "expiry_unix_milliseconds" ? "minimum" : "invalid_length") else { fatalError("\(name) returned the wrong validation error") } } } let incompatible = try CapabilityProfile( transport: "quic-tls13", framing: "datagram-v1", media: "encoded", sourceRateControl: "server", videoProfiles: [hevc], audioProfiles: [audio] ) let gatewayCapability = try CapabilityProfile( transport: "quic-tls13", framing: "datagram-v1", media: "encoded", 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]).videoProfiles == [video] else { fatalError("ordered registered profile intersection changed") } do { _ = try CapabilityProfile.intersection([capability, incompatible]) fatalError("profiles without overlap were accepted") } catch { } let valid = try request.encodeJSON() var unsupported = try JSONSerialization.jsonObject(with: valid) as! [String: Any] unsupported["version"] = "2" var downgrade = try JSONSerialization.jsonObject(with: valid) as! [String: Any] downgrade["version"] = "0" var unknown = try JSONSerialization.jsonObject(with: valid) as! [String: Any] unknown["unknown"] = true for invalid in [ try JSONSerialization.data(withJSONObject: unsupported), try JSONSerialization.data(withJSONObject: downgrade), try JSONSerialization.data(withJSONObject: unknown), Data("{".utf8), valid + Data(" {}".utf8), ] { do { _ = try TunnelAdmissionRequest.decodeJSON(invalid) fatalError("invalid tunnel admission request was accepted") } catch { } } let clientAuthority = try ClientSessionAuthority( version: "1", sessionId: "session", gatewayId: "gateway", audience: "audience", 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", "selected_descriptor" ]), !String(data: clientAuthorityJSON, encoding: .utf8)!.contains("provider_") else { fatalError("client authority was not exactly provider-free") } _ = try ClientSessionAuthority.decodeJSON(clientAuthorityJSON) 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 { } do { _ = try CapabilityProfile.decodeJSON(Data(repeating: 32, count: 1_048_577)) fatalError("capability accepted oversized JSON") } catch let error as ContractValidationError { guard error.code == "payload_too_large" else { fatalError("oversized JSON was not rejected before parsing") } } let deeplyNested = Data((String(repeating: "[", count: 65) + "null" + String(repeating: "]", count: 65)).utf8) do { _ = try CapabilityProfile.decodeJSON(deeplyNested) fatalError("capability accepted over-deep JSON") } catch let error as ContractValidationError { guard error.code == "nesting_too_deep" else { fatalError("over-deep JSON was not rejected before decoding") } } for field in ["version", "session_id", "gateway_id", "audience", "reconnect_sequence", "expires_at", "capabilities", "selected_descriptor"] { var missing = clientAuthorityObject missing.removeValue(forKey: field) do { _ = try ClientSessionAuthority.decodeJSON(try JSONSerialization.data(withJSONObject: missing)) fatalError("client authority accepted missing \(field)") } catch { } } for (field, value) in [ ("provider_profile", "apollo"), ("provider_identity", "provider-1"), ("provider_url", "https://provider.invalid"), ("management_host", "provider.invalid"), ("unknown", "true"), ] { var injected = clientAuthorityObject injected[field] = value do { _ = try ClientSessionAuthority.decodeJSON(try JSONSerialization.data(withJSONObject: injected)) fatalError("client authority accepted injected \(field)") } catch { } } for expiresAt in ["not-a-time", "2099-01-01T00:00:00+00:00", "2099-01-01T00:00:00.100Z"] { var invalidExpiry = clientAuthorityObject invalidExpiry["expires_at"] = expiresAt do { _ = try ClientSessionAuthority.decodeJSON(try JSONSerialization.data(withJSONObject: invalidExpiry)) fatalError("client authority accepted invalid expiry") } catch { } } do { _ = try ClientSessionAuthority.decodeJSON(clientAuthorityJSON + Data(" {}".utf8)) fatalError("client authority accepted trailing JSON") } catch { } do { _ = try AllocationPolicy( minimumKbps: 100, targetKbps: 50, maximumKbps: 25, tier: "standard", audience: "audience", protocolValue: "verse", protocolVersion: 1, grantTtlSeconds: 60, reservationLeaseSeconds: 300 ) fatalError("invalid allocation bounds were accepted") } catch { } let displayMode = display for invalid in [ { try DisplayMode(resolutionWidth: 319, resolutionHeight: 1440, fps: 120) }, { try DisplayMode(resolutionWidth: 2560, resolutionHeight: 199, fps: 120) }, { try DisplayMode(resolutionWidth: 2560, resolutionHeight: 1440, fps: 241) }, ] { do { _ = try invalid() fatalError("invalid display mode was accepted") } catch { } } let policyFreeV2Request = try SessionRequest( clientDeviceId: "device-1", deviceKeyId: "key-1", poolId: "pool-1", 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", 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") } var nullDisplayRequest = try JSONSerialization.jsonObject(with: displayRequest.encodeJSON()) as! [String: Any] nullDisplayRequest["requested_display_mode"] = NSNull() do { _ = try SessionRequest.decodeJSON(try JSONSerialization.data(withJSONObject: nullDisplayRequest)) fatalError("explicit null display mode was accepted") } catch { } let nativeIdentity = try NativeSessionIdentity(clientDeviceId: "device-1", deviceKeyId: "key-1") let browserSession = try BrowserAuthenticatedSession( username: "alice", provider: "local", roles: ["user"], role: "user" ) guard !String(data: try browserSession.encodeJSON(), encoding: .utf8)!.contains("native_identity") else { fatalError("browser session encoded native identity") } let nativeSession = try NativeAuthenticatedSession( username: "alice", provider: "local", roles: ["user"], role: "user", nativeIdentity: nativeIdentity ) guard try NativeAuthenticatedSession.decodeJSON(nativeSession.encodeJSON()).nativeIdentity == nativeIdentity else { fatalError("native session identity did not round-trip") } do { _ = try BrowserAuthenticatedSession.decodeJSON(nativeSession.encodeJSON()) fatalError("browser session accepted native identity") } catch { } do { _ = try NativeAuthenticatedSession.decodeJSON(browserSession.encodeJSON()) fatalError("native session accepted missing identity") } catch { } var partialNativeSession = try JSONSerialization.jsonObject(with: nativeSession.encodeJSON()) as! [String: Any] partialNativeSession["native_identity"] = ["client_device_id": "device-1"] do { _ = try NativeAuthenticatedSession.decodeJSON(try JSONSerialization.data(withJSONObject: partialNativeSession)) fatalError("partial native identity was accepted") } catch { } for roles in [[""], [String(repeating: "r", count: 65)]] { do { _ = try BrowserAuthenticatedSession(username: "alice", provider: "local", roles: roles, role: "user") fatalError("invalid role item length was accepted") } catch { } } _ = try NativeTunnelCredential( clientDeviceId: "device-1", deviceKeyId: "key-1", certificateChainPem: "certificate", trustBundlePem: "trust", expiresAt: "2099-01-01T00:00:00Z" ) for expiresAt in ["2099-01-01T00:00:00+00:00", "2099-01-01T00:00:00.100Z"] { do { _ = try NativeTunnelCredential( clientDeviceId: "device-1", deviceKeyId: "key-1", certificateChainPem: "certificate", trustBundlePem: "trust", expiresAt: expiresAt ) fatalError("noncanonical RFC3339 UTC timestamp was accepted") } catch { } } let streamPolicy = try ProviderStreamPolicy( videoProfile: hevc, audioProfile: audio, displayMode: displayMode, bitrateTargetKbps: 40000, bitrateMaximumKbps: 50000 ) guard streamPolicy.videoProfile == hevc else { fatalError("stream policy changed") } for invalid in [ { 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() fatalError("invalid stream policy was accepted") } catch { } } let telemetry = try GatewayTelemetry( admittedSessions: 1, admissionRejects: 2, reconnects: 3, drainTransitions: 4, mediaDrops: 5, mediaPackets: 6, mediaBytes: 7, queueDelayMicros: 8, processingDelayMicros: 9, processingSamples: 10, pacingDelayMicros: 11, providerErrors: 12, inputRejected: 13, controlRttMicros: 14, controlJitterMicros: 15, controlLossPpm: 16, pendingReliable: 17, providerState: "ready" ) guard telemetry.mediaBytes == 7 else { fatalError("gateway telemetry changed") } do { _ = try GatewayTelemetry( admittedSessions: 1, admissionRejects: 2, reconnects: 3, drainTransitions: 4, mediaDrops: 5, mediaPackets: 6, mediaBytes: 7, queueDelayMicros: 8, processingDelayMicros: 9, processingSamples: 10, pacingDelayMicros: 11, providerErrors: 12, inputRejected: 13, controlRttMicros: 14, controlJitterMicros: 15, controlLossPpm: 1000001, pendingReliable: 17, providerState: "ready" ) fatalError("invalid gateway telemetry was accepted") } catch { } for text in [ String(repeating: "a", count: 65536), String(repeating: "é", count: 32768), String(repeating: "\\\"", count: 32768), ] { let clipboard = try GatewayClipboardText( direction: "client_to_provider", text: text, encoding: "utf-8", loopToken: "abcdefghijklmnop" ) let decoded = try GatewayClipboardText.decodeJSON(clipboard.encodeJSON()) guard decoded.text == text else { fatalError("clipboard text changed during round-trip") } } do { _ = try GatewayClipboardText( direction: "client_to_provider", text: String(repeating: "a", count: 65537), encoding: "utf-8", loopToken: "abcdefghijklmnop" ) fatalError("oversized clipboard text was accepted") } catch { } """, encoding="utf-8", ) run(["swiftc", str(ROOT / "gen/swift/Protocol.swift"), str(swift), "-o", str(workspace / "swift-contracts")], ROOT) run([str(workspace / "swift-contracts")], ROOT) rust = workspace / "protocol.rs" shutil.copyfile(ROOT / "gen/rust/protocol.rs", rust) with rust.open("a", encoding="utf-8") as output: output.write( """ 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 operation_id = "12345678-1234-1234-1234-123456789abc".to_string(); assert!(GatewayQualityWorkRequest::new("1".into(), "session".into(), "gateway".into(), 2, "poll".into(), None, None, None, None).is_ok()); assert!(GatewayQualityWorkRequest::new("1".into(), "session".into(), "gateway".into(), 2, "prompt".into(), Some(operation_id.clone()), Some(7), None, None).is_ok()); assert!(GatewayQualityWorkRequest::new("1".into(), "session".into(), "gateway".into(), 2, "observation".into(), Some(operation_id.clone()), Some(7), Some(3), Some(6)).is_ok()); assert!(GatewayQualityWorkRequest::new("1".into(), "session".into(), "gateway".into(), 2, "poll".into(), Some(operation_id.clone()), Some(7), None, None).is_err()); assert!(GatewayQualityAck::new("1".into(), "session".into(), "gateway".into(), 2, operation_id.clone(), 7, 3, "applied".into(), Some(7), None).is_ok()); assert!(GatewayQualityAck::new("1".into(), "session".into(), "gateway".into(), 2, operation_id.clone(), 7, 3, "proven_prior".into(), Some(6), None).is_ok()); assert!(GatewayQualityAck::new("1".into(), "session".into(), "gateway".into(), 2, operation_id.clone(), 7, 3, "unknown".into(), None, None).is_ok()); assert!(GatewayQualityAck::new("1".into(), "session".into(), "gateway".into(), 2, operation_id, 7, 3, "applied".into(), Some(6), None).is_err()); let capabilities = CapabilityProfile::new( "quic-tls13".into(), "datagram-v1".into(), "encoded".into(), "server".into(), vec![video.clone()], vec![audio.clone()], ).unwrap(); assert!(CapabilityProfile::new( "quic-tls13".into(), "datagram-v2".into(), "encoded".into(), "server".into(), vec![video.clone()], vec![audio.clone()], ).is_ok()); assert!(CapabilityProfile::new( "quic-tls13".into(), "datagram-v3".into(), "encoded".into(), "server".into(), vec![video.clone()], vec![audio.clone()], ).is_err()); let request = TunnelAdmissionRequest::new( "1".into(), "session".into(), "gateway".into(), "audience".into(), "g".repeat(43), 0, "n".repeat(16), "s".repeat(86), capabilities.clone(), ).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: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]; let proof_device_id = vec![3u8; 16]; let proof_challenge = vec![4u8; 32]; let proof = device_registration_proof_transcript( &proof_server_id, &proof_principal_id, &proof_device_id, &proof_challenge, 1, ).unwrap(); assert_eq!(proof.len(), 112); assert_eq!(&proof[..24], b"versevdi-device-proof-v1"); assert_eq!(&proof[104..], &[0, 0, 0, 0, 0, 0, 0, 1]); for (server_id, principal_id, device_id, challenge, expiry, field, code) in [ (vec![0; 15], proof_principal_id.clone(), proof_device_id.clone(), proof_challenge.clone(), 0, "server_id", "invalid_length"), (vec![0; 17], proof_principal_id.clone(), proof_device_id.clone(), proof_challenge.clone(), 0, "server_id", "invalid_length"), (proof_server_id.clone(), vec![0; 15], proof_device_id.clone(), proof_challenge.clone(), 0, "principal_id", "invalid_length"), (proof_server_id.clone(), vec![0; 17], proof_device_id.clone(), proof_challenge.clone(), 0, "principal_id", "invalid_length"), (proof_server_id.clone(), proof_principal_id.clone(), vec![0; 15], proof_challenge.clone(), 0, "device_id", "invalid_length"), (proof_server_id.clone(), proof_principal_id.clone(), vec![0; 17], proof_challenge.clone(), 0, "device_id", "invalid_length"), (proof_server_id.clone(), proof_principal_id.clone(), proof_device_id.clone(), vec![0; 31], 0, "challenge", "invalid_length"), (proof_server_id.clone(), proof_principal_id.clone(), proof_device_id.clone(), vec![0; 33], 0, "challenge", "invalid_length"), (proof_server_id.clone(), proof_principal_id.clone(), proof_device_id.clone(), proof_challenge.clone(), -1, "expiry_unix_milliseconds", "minimum"), ] { assert_eq!( device_registration_proof_transcript(&server_id, &principal_id, &device_id, &challenge, expiry), Err(ValidationError::new(field, code)), ); } assert!(TunnelAdmissionRequest::new( "2".into(), "session".into(), "gateway".into(), "audience".into(), "g".repeat(43), 0, "n".repeat(16), "s".repeat(86), capabilities.clone(), ).is_err()); assert!(TunnelAdmissionRequest::new( "0".into(), "session".into(), "gateway".into(), "audience".into(), "g".repeat(43), 0, "n".repeat(16), "s".repeat(86), capabilities.clone(), ).is_err()); assert!(TunnelAdmissionRequest::new( "1".into(), "session".into(), "gateway".into(), "audience".into(), "g".repeat(43), 0, "short".into(), "s".repeat(86), capabilities.clone(), ).is_err()); let client_authority = ClientSessionAuthority::new( "1".into(), "session".into(), "gateway".into(), "audience".into(), 2, "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(), 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(), "server".into(), vec![hevc.clone()], vec![audio.clone()], ).unwrap(); let gateway_capability = CapabilityProfile::new( "quic-tls13".into(), "datagram-v1".into(), "encoded".into(), "server".into(), vec![hevc.clone(), video.clone()], vec![audio.clone()], ).unwrap(); assert_eq!( intersect_capability_profiles(&[gateway_capability, capabilities.clone()]).unwrap().videoProfiles(), &vec![video.clone()], ); assert!(intersect_capability_profiles(&[capabilities, incompatible]).is_err()); assert!(AllocationPolicy::new( 100, 50, 25, "standard".into(), "audience".into(), "verse".into(), 1, 60, 300, ).is_err()); let display_mode = DisplayMode::new(2560, 1440, 120).unwrap(); assert!(DisplayMode::new(319, 1440, 120).is_err()); assert!(DisplayMode::new(2560, 199, 120).is_err()); 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)); let native_identity = NativeSessionIdentity::new("device-1".into(), "key-1".into()).unwrap(); assert!(BrowserAuthenticatedSession::new( "alice".into(), "local".into(), vec!["user".into()], "user".into(), ).is_ok()); assert!(NativeAuthenticatedSession::new( "alice".into(), "local".into(), vec!["user".into()], "user".into(), native_identity, ).is_ok()); assert!(BrowserAuthenticatedSession::new( "alice".into(), "local".into(), vec![String::new()], "user".into(), ).is_err()); assert!(BrowserAuthenticatedSession::new( "alice".into(), "local".into(), vec!["r".repeat(65)], "user".into(), ).is_err()); assert!(NativeTunnelCredential::new( "device-1".into(), "key-1".into(), "certificate".into(), "trust".into(), "2099-01-01T00:00:00Z".into(), ).is_ok()); for expires_at in ["2099-01-01T00:00:00+00:00", "2099-01-01T00:00:00.100Z"] { assert!(NativeTunnelCredential::new( "device-1".into(), "key-1".into(), "certificate".into(), "trust".into(), expires_at.into(), ).is_err()); } assert!(ProviderStreamPolicy::new( hevc.clone(), audio.clone(), display.clone(), 40000, 50000, ).is_ok()); assert!(DisplayMode::new(319, 1440, 120).is_err()); assert!(ProviderStreamPolicy::new( 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()); assert!(GatewayTelemetry::new( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1000001, 17, "ready".into(), ).is_err()); assert!(GatewayTelemetry::new( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, "provider.example:47984".into(), ).is_err()); for text in [ "a".repeat(65536), "é".repeat(32768), "\\\"".repeat(32768), ] { assert!(GatewayClipboardText::new( "client_to_provider".into(), text, "utf-8".into(), "abcdefghijklmnop".into(), ).is_ok()); } assert!(GatewayClipboardText::new( "client_to_provider".into(), "a".repeat(65537), "utf-8".into(), "abcdefghijklmnop".into(), ).is_err()); } """ ) run(["rustc", str(rust), "-o", str(workspace / "rust-contracts")], ROOT) run([str(workspace / "rust-contracts")], ROOT) expected_protobuf_messages = { "ClientSessionAuthority": [ ("version", 1), ("session_id", 2), ("gateway_id", 3), ("audience", 4), ("reconnect_sequence", 5), ("expires_at", 6), ("capabilities", 7), ("selected_descriptor", 8), ], "GatewayQualityWorkRequest": [ ("version", 1), ("session_id", 2), ("gateway_id", 3), ("reconnect_sequence", 4), ("operation_id", 5), ("revision", 6), ("current_applied_revision", 7), ("acquisition", 8), ("lease_generation", 9), ], "GatewayQualityWork": [ ("version", 1), ("session_id", 2), ("gateway_id", 3), ("reconnect_sequence", 4), ("operation_id", 5), ("revision", 6), ("lease_expires_at", 7), ("selected_descriptor", 8), ("current_applied_revision", 9), ("lease_generation", 10), ], "GatewayQualityAck": [ ("version", 1), ("session_id", 2), ("gateway_id", 3), ("reconnect_sequence", 4), ("operation_id", 5), ("revision", 6), ("outcome", 7), ("current_applied_revision", 8), ("failure_code", 9), ("lease_generation", 10), ], "GatewayStopWorkRequest": [ ("version", 1), ("session_id", 2), ("gateway_id", 3), ("reconnect_sequence", 4), ("operation_id", 5), ("acquisition", 6), ], } for message, expected_protobuf_fields in expected_protobuf_messages.items(): actual_protobuf_fields = protobuf_message_fields(message) if actual_protobuf_fields != expected_protobuf_fields: raise RuntimeError( f"{message} protobuf fields = {actual_protobuf_fields}; " f"want {expected_protobuf_fields}" ) rust_unknown = workspace / "unknown.rs" shutil.copyfile(ROOT / "gen/rust/protocol.rs", rust_unknown) with rust_unknown.open("a", encoding="utf-8") as output: output.write("\nfn main() { let _ = CapabilityProfile { unknown: String::new() }; }\n") run_failure(["rustc", str(rust_unknown), "-o", str(workspace / "rust-unknown")], ROOT, "no field named `unknown`") print("Generated strict contract checks passed") return 0 if __name__ == "__main__": raise SystemExit(main())