feat(protocol): freeze M4 native session RC6 contract

This commit is contained in:
sechmachine
2026-08-13 07:18:03 +07:00
parent 4693102b3c
commit 8eacc4fda9
35 changed files with 5334 additions and 473 deletions
+51 -31
View File
@@ -11,6 +11,24 @@ import (
protocol "git.sechmachine.io.vn/sechmachine/VerseVDI-Protocol/gen/go/protocol"
)
func rc6Video(codec string) protocol.VideoProfile {
return protocol.VideoProfile{Codec: codec, BitDepth: 8, ChromaSubsampling: "4:2:0", ColorSpace: "bt709-limited", TransferFunction: "sdr"}
}
func rc6Audio() protocol.AudioProfile {
return protocol.AudioProfile{Codec: "opus", SampleRateHz: 48000, Channels: 2, ChannelLayout: "stereo", PacketDurationMs: 5}
}
func rc6Capability(codecs ...string) protocol.CapabilityProfile {
videos := make([]protocol.VideoProfile, len(codecs))
for index, codec := range codecs { videos[index] = rc6Video(codec) }
return protocol.CapabilityProfile{Transport: "quic-tls13", Framing: "datagram-v1", Media: "encoded", SourceRateControl: "server", VideoProfiles: videos, AudioProfiles: []protocol.AudioProfile{rc6Audio()}}
}
func rc6Descriptor(codec string) protocol.SelectedSessionDescriptor {
return protocol.SelectedSessionDescriptor{VideoProfile: rc6Video(codec), AudioProfile: rc6Audio(), DisplayMode: protocol.DisplayMode{ResolutionWidth: 1920, ResolutionHeight: 1080, Fps: 60}, BitrateTargetKbps: 20000, BitrateMaximumKbps: 40000, Adjustment: protocol.SessionAdjustment{DisplayReason: "none", BitrateReason: "none"}, MediaTimestampBasis: "gateway-send-wall-clock-ms"}
}
func TestDeviceRegistrationProofTranscriptIsCanonicalAndStrict(t *testing.T) {
serverID, _ := hex.DecodeString("00112233445566778899aabbccddeeff")
principalID, _ := hex.DecodeString("102132435465768798a9bacbdcedfe0f")
@@ -51,7 +69,7 @@ func TestDeviceRegistrationProofTranscriptIsCanonicalAndStrict(t *testing.T) {
}
func TestManifestRejectsForbiddenAndUnknownFields(t *testing.T) {
valid := `{"version":"1","purpose":"launch","session_id":"session-1","reconnect_sequence":0,"gateway":{"id":"gateway-1","addresses":["gateway.control.test:443"],"public_identity":"gateway.control.test"},"tunnel":{"versions":["verse-gateway-v1/1"],"features":["control.v1"]},"profile":{"id":"standard","bounds":{"minimum_kbps":1,"target_kbps":2,"maximum_kbps":3}},"grant":{"opaque_value":"opaque-one-time-grant-value-with-at-least-43-bytes","expires_at":"2099-01-01T00:00:00Z","audience":"versevdi-gateway"},"correlation_id":"correlation-1"}`
valid := `{"version":"1","purpose":"launch","session_id":"session-1","reconnect_sequence":0,"gateway":{"id":"gateway-1","addresses":["gateway.control.test:443"],"public_identity":"gateway.control.test"},"tunnel":{"versions":["verse-gateway-v1/1"],"features":["control.v1"]},"profile":{"id":"standard","bounds":{"minimum_kbps":1,"target_kbps":2,"maximum_kbps":3}},"grant":{"opaque_value":"opaque-one-time-grant-value-with-at-least-43-bytes","expires_at":"2099-01-01T00:00:00Z","audience":"versevdi-gateway"},"correlation_id":"correlation-1","selected_descriptor":{"video_profile":{"codec":"h264","bit_depth":8,"chroma_subsampling":"4:2:0","color_space":"bt709-limited","transfer_function":"sdr"},"audio_profile":{"codec":"opus","sample_rate_hz":48000,"channels":2,"channel_layout":"stereo","packet_duration_ms":5},"display_mode":{"resolution_width":1920,"resolution_height":1080,"fps":60},"bitrate_target_kbps":20000,"bitrate_maximum_kbps":40000,"adjustment":{"display_reason":"none","bitrate_reason":"none"},"media_timestamp_basis":"gateway-send-wall-clock-ms"}}`
manifest, err := protocol.DecodeConnectionManifest([]byte(valid))
if err != nil || manifest.Gateway.ID != "gateway-1" {
t.Fatalf("valid manifest = %+v, err = %v", manifest, err)
@@ -83,6 +101,7 @@ func TestDisplayModeIsOptionalStrictAndBounded(t *testing.T) {
request := protocol.SessionRequest{
ClientDeviceID: "device-1", DeviceKeyID: "key-1", PoolID: "pool-1", IdempotencyKey: "request-1",
VideoProfiles: []protocol.VideoProfile{rc6Video("h264")}, BitratePreference: protocol.BitratePreference{Mode: "auto"},
}
legacy, err := protocol.EncodeSessionRequest(request)
if err != nil {
@@ -140,7 +159,7 @@ func TestSessionRequestRejectsClientPolicySnapshot(t *testing.T) {
if protocol.CurrentWireVersion != "2" || protocol.NMinus1WireVersion != "1" || protocol.NMinus2WireVersion != "0" {
t.Fatalf("wire compatibility = current %q, n-1 %q, n-2 %q", protocol.CurrentWireVersion, protocol.NMinus1WireVersion, protocol.NMinus2WireVersion)
}
request := `{"client_device_id":"device-1","device_key_id":"key-1","pool_id":"pool-1","idempotency_key":"request-1"}`
request := `{"client_device_id":"device-1","device_key_id":"key-1","pool_id":"pool-1","idempotency_key":"request-1","video_profiles":[{"codec":"h264","bit_depth":8,"chroma_subsampling":"4:2:0","color_space":"bt709-limited","transfer_function":"sdr"}],"bitrate_preference":{"mode":"auto"}}`
if _, err := protocol.DecodeSessionRequest([]byte(request)); err != nil {
t.Fatalf("policy-free SessionRequest rejected: %v", err)
}
@@ -225,7 +244,7 @@ func TestGeneratedDecodersRejectMissingRequiredFieldsAndTrailingValues(t *testin
}
func TestGatewayContractsRejectUnknownVersionsAndFields(t *testing.T) {
registration := `{"version":"1","gateway_id":"gateway-1","instance_identity":"instance-1","certificate_identity":"cert-1","public_identity":"public-1","address":"gateway.test:443","provider_identity":"apollo-provider-1","protocol_min_version":1,"protocol_max_version":1,"connection_capacity":8,"bandwidth_capacity_kbps":100000,"features":["datagram.media"],"capabilities":{"transport":"quic","framing":"datagram-v1","media":"encoded","audio":"encoded","source_rate_control":"server","client_decode":["h264-opus"]}}`
registration := `{"version":"1","gateway_id":"gateway-1","instance_identity":"instance-1","certificate_identity":"cert-1","public_identity":"public-1","address":"gateway.test:443","provider_identity":"apollo-provider-1","protocol_min_version":1,"protocol_max_version":1,"connection_capacity":8,"bandwidth_capacity_kbps":100000,"features":["datagram.media"],"capabilities":{"transport":"quic","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}]}}`
if _, err := protocol.DecodeGatewayRegistration([]byte(registration)); err != nil {
t.Fatalf("valid gateway registration rejected: %v", err)
}
@@ -244,7 +263,7 @@ func TestGatewayContractsRejectUnknownVersionsAndFields(t *testing.T) {
}
func TestGatewayRegistrationRejectsInvertedProtocolBounds(t *testing.T) {
registration := `{"version":"1","gateway_id":"gateway-1","instance_identity":"instance-1","certificate_identity":"cert-1","public_identity":"public-1","address":"gateway.test:443","provider_identity":"apollo-provider-1","protocol_min_version":2,"protocol_max_version":1,"connection_capacity":8,"bandwidth_capacity_kbps":100000,"features":["datagram.media"],"capabilities":{"transport":"quic","framing":"datagram-v1","media":"encoded","audio":"encoded","source_rate_control":"server","client_decode":["h264-opus"]}}`
registration := `{"version":"1","gateway_id":"gateway-1","instance_identity":"instance-1","certificate_identity":"cert-1","public_identity":"public-1","address":"gateway.test:443","provider_identity":"apollo-provider-1","protocol_min_version":2,"protocol_max_version":1,"connection_capacity":8,"bandwidth_capacity_kbps":100000,"features":["datagram.media"],"capabilities":{"transport":"quic","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}]}}`
if _, err := protocol.DecodeGatewayRegistration([]byte(registration)); err == nil {
t.Fatal("DecodeGatewayRegistration accepted inverted protocol bounds")
}
@@ -267,12 +286,12 @@ func TestGatewayHeartbeatCarriesBoundedObservedTelemetry(t *testing.T) {
}
func TestCapabilityIntersectionRejectsNoOverlap(t *testing.T) {
first := protocol.CapabilityProfile{Transport: "quic-tls13", Framing: "datagram-v1", Media: "encoded", Audio: "encoded", SourceRateControl: "server", ClientDecode: []string{"h264-opus"}}
first := rc6Capability("h264")
if got, err := protocol.IntersectCapabilityProfiles(first, first); err != nil || !reflect.DeepEqual(got, first) {
t.Fatalf("IntersectCapabilityProfiles matching profiles = %+v, %v", got, err)
}
second := first
second.ClientDecode = []string{"hevc-opus"}
second.VideoProfiles = []protocol.VideoProfile{rc6Video("hevc")}
if _, err := protocol.IntersectCapabilityProfiles(first, second); err == nil {
t.Fatal("IntersectCapabilityProfiles accepted profiles without a common codec profile")
}
@@ -280,31 +299,31 @@ func TestCapabilityIntersectionRejectsNoOverlap(t *testing.T) {
func TestCapabilityIntersectionSelectsRegisteredOrderedProfiles(t *testing.T) {
gateway := protocol.CapabilityProfile{
Transport: "quic-tls13", Framing: "datagram-v1", Media: "encoded", Audio: "encoded",
SourceRateControl: "server", ClientDecode: []string{"hevc-opus", "h264-opus"},
Transport: "quic-tls13", Framing: "datagram-v1", Media: "encoded",
SourceRateControl: "server", VideoProfiles: []protocol.VideoProfile{rc6Video("hevc"), rc6Video("h264")}, AudioProfiles: []protocol.AudioProfile{rc6Audio()},
}
h264Client := gateway
h264Client.ClientDecode = []string{"h264-opus"}
h264Client.VideoProfiles = []protocol.VideoProfile{rc6Video("h264")}
selected, err := protocol.IntersectCapabilityProfiles(gateway, h264Client)
if err != nil || !reflect.DeepEqual(selected.ClientDecode, []string{"h264-opus"}) {
if err != nil || !reflect.DeepEqual(selected.VideoProfiles, []protocol.VideoProfile{rc6Video("h264")}) {
t.Fatalf("H.264 profile intersection = %+v, %v", selected, err)
}
hevcClient := gateway
hevcClient.ClientDecode = []string{"hevc-opus"}
hevcClient.VideoProfiles = []protocol.VideoProfile{rc6Video("hevc")}
selected, err = protocol.IntersectCapabilityProfiles(gateway, hevcClient)
if err != nil || !reflect.DeepEqual(selected.ClientDecode, []string{"hevc-opus"}) {
if err != nil || !reflect.DeepEqual(selected.VideoProfiles, []protocol.VideoProfile{rc6Video("hevc")}) {
t.Fatalf("HEVC profile intersection = %+v, %v", selected, err)
}
noOverlap := gateway
noOverlap.ClientDecode = []string{"h264-opus"}
noOverlap.VideoProfiles = []protocol.VideoProfile{rc6Video("h264")}
if _, err := protocol.IntersectCapabilityProfiles(noOverlap, hevcClient); err == nil {
t.Fatal("intersection accepted registered profiles without overlap")
}
for _, invalid := range [][]string{{"h264-hevc-opus"}, {"h264-opus", "h264-opus"}} {
for _, invalid := range [][]protocol.VideoProfile{{{Codec: "vp9", BitDepth: 8, ChromaSubsampling: "4:2:0", ColorSpace: "bt709-limited", TransferFunction: "sdr"}}, {rc6Video("h264"), rc6Video("h264")}} {
profile := gateway
profile.ClientDecode = invalid
profile.VideoProfiles = invalid
if err := profile.Validate(); err == nil {
t.Fatalf("CapabilityProfile accepted invalid registered profile set %q", invalid)
t.Fatalf("CapabilityProfile accepted invalid registered profile set %+v", invalid)
}
}
}
@@ -312,7 +331,7 @@ func TestCapabilityIntersectionSelectsRegisteredOrderedProfiles(t *testing.T) {
func TestCapabilityProfileRequiresRegisteredFraming(t *testing.T) {
valid := protocol.CapabilityProfile{
Transport: "quic-tls13", Framing: "datagram-v2", Media: "encoded",
Audio: "encoded", SourceRateControl: "server", ClientDecode: []string{"h264-opus"},
SourceRateControl: "server", VideoProfiles: []protocol.VideoProfile{rc6Video("h264")}, AudioProfiles: []protocol.AudioProfile{rc6Audio()},
}
if err := valid.Validate(); err != nil {
t.Fatalf("registered datagram-v2 rejected: %v", err)
@@ -329,8 +348,8 @@ func TestTunnelAdmissionRequiresDeviceSignature(t *testing.T) {
Version: "1", SessionID: "session-1", GatewayID: "gateway-1", Audience: "versevdi-gateway",
Grant: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_", ReconnectSequence: 0,
ClientNonce: "0123456789abcdef", Capabilities: protocol.CapabilityProfile{
Transport: "quic-tls13", Framing: "datagram-v1", Media: "encoded", Audio: "encoded",
SourceRateControl: "server", ClientDecode: []string{"h264-opus"},
Transport: "quic-tls13", Framing: "datagram-v1", Media: "encoded",
SourceRateControl: "server", VideoProfiles: []protocol.VideoProfile{rc6Video("h264")}, AudioProfiles: []protocol.AudioProfile{rc6Audio()},
},
}
if _, err := protocol.EncodeTunnelAdmissionRequest(request); err == nil {
@@ -343,18 +362,18 @@ func TestTunnelAdmissionTranscriptIsDomainSeparatedAndLengthDelimited(t *testing
Version: "1", SessionID: "session", GatewayID: "gateway", Audience: "audience",
Grant: strings.Repeat("g", 43), ReconnectSequence: 0, ClientNonce: strings.Repeat("n", 16),
DeviceSignature: strings.Repeat("s", 86), Capabilities: protocol.CapabilityProfile{
Transport: "quic-tls13", Framing: "datagram-v1", Media: "encoded", Audio: "encoded",
SourceRateControl: "server", ClientDecode: []string{"h264-opus"},
Transport: "quic-tls13", Framing: "datagram-v1", Media: "encoded",
SourceRateControl: "server", VideoProfiles: []protocol.VideoProfile{rc6Video("h264")}, AudioProfiles: []protocol.AudioProfile{rc6Audio()},
},
}
want := "versevdi/tunnel-admission/v17:session7:gateway8:audience43:" + strings.Repeat("g", 43) + "1:016:" + strings.Repeat("n", 16) + "10:quic-tls1311:datagram-v17:encoded7:encoded6:server1:19:h264-opus"
want := "versevdi/tunnel-admission/v17:session7:gateway8:audience43:" + strings.Repeat("g", 43) + "1:016:" + strings.Repeat("n", 16) + "10:quic-tls1311:datagram-v17:encoded6:server1:11:14:h2641:85:4:2:013:bt709-limited3:sdr4:opus5:480001:26:stereo1:5"
if got := string(request.DeviceAdmissionTranscript()); got != want {
t.Fatalf("DeviceAdmissionTranscript() = %q, want %q", got, want)
}
}
func TestSessionAuthorityRejectsProviderRoute(t *testing.T) {
valid := `{"version":"1","session_id":"session-1","gateway_id":"gateway-1","audience":"versevdi-gateway","reconnect_sequence":0,"expires_at":"2099-01-01T00:00:00Z","capabilities":{"transport":"quic","framing":"datagram-v1","media":"encoded","audio":"encoded","source_rate_control":"server","client_decode":["h264-opus"]},"provider_profile":"apollo","provider_identity":"provider-1"}`
valid := `{"version":"1","session_id":"session-1","gateway_id":"gateway-1","audience":"versevdi-gateway","reconnect_sequence":0,"expires_at":"2099-01-01T00:00:00Z","capabilities":{"transport":"quic","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}]},"provider_profile":"apollo","provider_identity":"provider-1","selected_descriptor":{"video_profile":{"codec":"h264","bit_depth":8,"chroma_subsampling":"4:2:0","color_space":"bt709-limited","transfer_function":"sdr"},"audio_profile":{"codec":"opus","sample_rate_hz":48000,"channels":2,"channel_layout":"stereo","packet_duration_ms":5},"display_mode":{"resolution_width":1920,"resolution_height":1080,"fps":60},"bitrate_target_kbps":20000,"bitrate_maximum_kbps":40000,"adjustment":{"display_reason":"none","bitrate_reason":"none"},"media_timestamp_basis":"gateway-send-wall-clock-ms"}}`
if _, err := protocol.DecodeSessionAuthority([]byte(valid)); err != nil {
t.Fatalf("valid session authority rejected: %v", err)
}
@@ -367,9 +386,10 @@ func TestClientSessionAuthorityIsStrictAndProviderFree(t *testing.T) {
authority := protocol.ClientSessionAuthority{
Version: "1", SessionID: "session-1", GatewayID: "gateway-1", Audience: "versevdi-gateway",
ReconnectSequence: 2, ExpiresAt: "2099-01-01T00:00:00Z", Capabilities: protocol.CapabilityProfile{
Transport: "quic-tls13", Framing: "datagram-v1", Media: "encoded", Audio: "encoded",
SourceRateControl: "server", ClientDecode: []string{"h264-opus"},
Transport: "quic-tls13", Framing: "datagram-v1", Media: "encoded",
SourceRateControl: "server", VideoProfiles: []protocol.VideoProfile{rc6Video("h264")}, AudioProfiles: []protocol.AudioProfile{rc6Audio()},
},
SelectedDescriptor: rc6Descriptor("h264"),
}
encoded, err := protocol.EncodeClientSessionAuthority(authority)
if err != nil {
@@ -381,7 +401,7 @@ func TestClientSessionAuthorityIsStrictAndProviderFree(t *testing.T) {
}
wantFields := map[string]bool{
"version": true, "session_id": true, "gateway_id": true, "audience": true,
"reconnect_sequence": true, "expires_at": true, "capabilities": true,
"reconnect_sequence": true, "expires_at": true, "capabilities": true, "selected_descriptor": true,
}
if len(fields) != len(wantFields) {
t.Fatalf("encoded client authority fields = %v; want exactly %v", fields, wantFields)
@@ -399,7 +419,7 @@ func TestClientSessionAuthorityIsStrictAndProviderFree(t *testing.T) {
t.Fatalf("DecodeClientSessionAuthority() = %+v, %v; want %+v", decoded, err, authority)
}
for _, field := range []string{"version", "session_id", "gateway_id", "audience", "reconnect_sequence", "expires_at", "capabilities"} {
for _, field := range []string{"version", "session_id", "gateway_id", "audience", "reconnect_sequence", "expires_at", "capabilities", "selected_descriptor"} {
missing := make(map[string]json.RawMessage, len(fields)-1)
for key, value := range fields {
if key != field {
@@ -439,7 +459,7 @@ func TestClientSessionAuthorityIsStrictAndProviderFree(t *testing.T) {
}
func TestProviderSessionWorkIsStrictAndSessionBound(t *testing.T) {
valid := `{"version":"1","session_id":"session-1","gateway_id":"gateway-1","reconnect_sequence":0,"expires_at":"2099-01-01T00:00:00Z","provider_profile":"apollo","provider_identity":"provider-1","policy_version_id":"policy-1","stream_policy":{"resolution_width":2560,"resolution_height":1440,"fps":120,"codec":"HEVC","bitrate_kbps":40000,"audio_enabled":true},"application_id":"42","client_id":"paired-client-1","management_host":"apollo.test","management_port":47990,"stream_host":"apollo.test","stream_port":47984,"client_certificate_pem":"certificate","client_private_key_pem":"private-key","server_certificate_pem":"server-certificate","clipboard_policy":{"client_to_provider_enabled":false,"provider_to_client_enabled":false,"max_text_bytes":65536,"max_updates_per_minute":30},"provider_application_termination_allowed":false}`
valid := `{"version":"1","session_id":"session-1","gateway_id":"gateway-1","reconnect_sequence":0,"expires_at":"2099-01-01T00:00:00Z","provider_profile":"apollo","provider_identity":"provider-1","policy_version_id":"policy-1","stream_policy":{"video_profile":{"codec":"hevc","bit_depth":8,"chroma_subsampling":"4:2:0","color_space":"bt709-limited","transfer_function":"sdr"},"audio_profile":{"codec":"opus","sample_rate_hz":48000,"channels":2,"channel_layout":"stereo","packet_duration_ms":5},"display_mode":{"resolution_width":2560,"resolution_height":1440,"fps":120},"bitrate_target_kbps":40000,"bitrate_maximum_kbps":50000},"application_id":"42","client_id":"paired-client-1","management_host":"apollo.test","management_port":47990,"stream_host":"apollo.test","stream_port":47984,"client_certificate_pem":"certificate","client_private_key_pem":"private-key","server_certificate_pem":"server-certificate","clipboard_policy":{"client_to_provider_enabled":false,"provider_to_client_enabled":false,"max_text_bytes":65536,"max_updates_per_minute":30},"provider_application_termination_allowed":false}`
if _, err := protocol.DecodeProviderSessionWork([]byte(valid)); err != nil {
t.Fatalf("valid provider work rejected: %v", err)
}
@@ -450,10 +470,10 @@ func TestProviderSessionWorkIsStrictAndSessionBound(t *testing.T) {
t.Fatal("provider work accepted missing clipboard policy")
}
for _, invalid := range []string{
strings.Replace(valid, `,"stream_policy":{"resolution_width":2560,"resolution_height":1440,"fps":120,"codec":"HEVC","bitrate_kbps":40000,"audio_enabled":true}`, "", 1),
strings.Replace(valid, `,"stream_policy":{"video_profile":{"codec":"hevc","bit_depth":8,"chroma_subsampling":"4:2:0","color_space":"bt709-limited","transfer_function":"sdr"},"audio_profile":{"codec":"opus","sample_rate_hz":48000,"channels":2,"channel_layout":"stereo","packet_duration_ms":5},"display_mode":{"resolution_width":2560,"resolution_height":1440,"fps":120},"bitrate_target_kbps":40000,"bitrate_maximum_kbps":50000}`, "", 1),
strings.Replace(valid, `"fps":120`, `"fps":241`, 1),
strings.Replace(valid, `"codec":"HEVC"`, `"codec":"VP9"`, 1),
strings.Replace(valid, `"audio_enabled":true`, `"audio_enabled":true,"unknown":false`, 1),
strings.Replace(valid, `"codec":"hevc"`, `"codec":"vp9"`, 1),
strings.Replace(valid, `"packet_duration_ms":5`, `"packet_duration_ms":5,"unknown":false`, 1),
} {
if _, err := protocol.DecodeProviderSessionWork([]byte(invalid)); err == nil {
t.Fatalf("provider work accepted invalid stream policy: %s", invalid)