fix(gateway): close Phase 3C audit gaps
This commit is contained in:
@@ -55,6 +55,7 @@ func TestNativeApolloManagementUsesSessionScopedMTLS(t *testing.T) {
|
||||
Version: "1", SessionID: "session-1", GatewayID: "gateway-1", ReconnectSequence: 0,
|
||||
ExpiresAt: "2099-01-01T00:00:00Z", ProviderProfile: ProviderProfileApollo,
|
||||
ProviderIdentity: "apollo-server#sha256:" + hex.EncodeToString(pinned[:]), PolicyVersionID: "policy-1", ApplicationID: "1", ClientID: "paired-client",
|
||||
StreamPolicy: protocol.ProviderStreamPolicy{ResolutionWidth: 1920, ResolutionHeight: 1080, Fps: 60, Codec: "H264", BitrateKbps: 8000, AudioEnabled: true},
|
||||
ManagementHost: host, ManagementPort: port, StreamHost: host, StreamPort: 47984,
|
||||
ClientCertificatePem: certificatePEM(t, clientTLS.Certificates[0]),
|
||||
ClientPrivateKeyPem: privateKeyPEM(t, clientTLS.Certificates[0]),
|
||||
@@ -70,6 +71,32 @@ func TestNativeApolloManagementUsesSessionScopedMTLS(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestNativeApolloSetupRejectsUnsupportedStreamPolicyBeforeProviderReadiness(t *testing.T) {
|
||||
work := protocol.ProviderSessionWork{
|
||||
Version: "1", SessionID: "session-1", GatewayID: "gateway-1",
|
||||
ExpiresAt: "2099-01-01T00:00:00Z", ProviderProfile: ProviderProfileApollo,
|
||||
ProviderIdentity: "provider#sha256:00", PolicyVersionID: "policy-1",
|
||||
ApplicationID: "1", ClientID: "client-1", ManagementHost: "127.0.0.1", ManagementPort: 1,
|
||||
StreamHost: "127.0.0.1", StreamPort: 1, ClientCertificatePem: "invalid",
|
||||
ClientPrivateKeyPem: "invalid", ServerCertificatePem: "invalid",
|
||||
ClipboardPolicy: protocol.ClipboardPolicy{MaxTextBytes: 65536, MaxUpdatesPerMinute: 30},
|
||||
}
|
||||
for name, policy := range map[string]protocol.ProviderStreamPolicy{
|
||||
"audio-disabled": {ResolutionWidth: 1920, ResolutionHeight: 1080, Fps: 60, Codec: "H264", BitrateKbps: 8000, AudioEnabled: false},
|
||||
"av1": {ResolutionWidth: 3840, ResolutionHeight: 2160, Fps: 60, Codec: "AV1", BitrateKbps: 50000, AudioEnabled: true},
|
||||
} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
work.StreamPolicy = policy
|
||||
_, err := NewNativeApolloBackend().Setup(context.Background(), LaunchRequest{
|
||||
SessionID: "session-1", ProviderProfile: ProviderProfileApollo, ProviderWork: work,
|
||||
})
|
||||
if !errors.Is(err, ErrProviderMalformed) {
|
||||
t.Fatalf("Setup() error = %v, want ErrProviderMalformed before provider readiness", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNativeApolloSetupRequiresModernEncryptedRTSPOrder(t *testing.T) {
|
||||
serverTLS, clientTLS := testTLS(t)
|
||||
streamListener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
@@ -158,8 +185,9 @@ func TestNativeApolloSetupRequiresModernEncryptedRTSPOrder(t *testing.T) {
|
||||
}
|
||||
if method == "ANNOUNCE" {
|
||||
for _, required := range []string{
|
||||
"a=x-nv-video[0].clientViewportWd:1920", "a=x-nv-video[0].clientViewportHt:1080", "a=x-nv-video[0].maxFPS:60",
|
||||
"a=x-nv-video[0].packetSize:1024", "a=x-nv-vqos[0].bw.maximumBitrateKbps:8000", "a=x-nv-audio.surround.numChannels:2",
|
||||
"a=x-nv-video[0].clientViewportWd:2560", "a=x-nv-video[0].clientViewportHt:1440", "a=x-nv-video[0].maxFPS:120",
|
||||
"a=x-nv-video[0].packetSize:1024", "a=x-nv-clientSupportHevc:1", "a=x-nv-vqos[0].bitStreamFormat:1",
|
||||
"a=x-nv-vqos[0].bw.maximumBitrateKbps:32000", "a=x-ml-video.configuredBitrateKbps:40000", "a=x-nv-audio.surround.numChannels:2",
|
||||
"a=x-nv-general.useReliableUdp:13", "a=x-ss-general.encryptionEnabled:7",
|
||||
} {
|
||||
if !strings.Contains(string(plaintext), required+"\r\n") {
|
||||
@@ -255,6 +283,7 @@ func TestNativeApolloSetupRequiresModernEncryptedRTSPOrder(t *testing.T) {
|
||||
Version: "1", SessionID: "session-1", GatewayID: "gateway-1", ReconnectSequence: 0,
|
||||
ExpiresAt: "2099-01-01T00:00:00Z", ProviderProfile: ProviderProfileApollo,
|
||||
ProviderIdentity: "apollo-server#sha256:" + hex.EncodeToString(pinned[:]), PolicyVersionID: "policy-1", ApplicationID: "42", ClientID: "paired-client",
|
||||
StreamPolicy: protocol.ProviderStreamPolicy{ResolutionWidth: 2560, ResolutionHeight: 1440, Fps: 120, Codec: "HEVC", BitrateKbps: 40000, AudioEnabled: true},
|
||||
ManagementHost: managementHost, ManagementPort: managementPort, StreamHost: streamHost, StreamPort: streamPort,
|
||||
ClientCertificatePem: certificatePEM(t, clientTLS.Certificates[0]), ClientPrivateKeyPem: privateKeyPEM(t, clientTLS.Certificates[0]),
|
||||
ServerCertificatePem: certificatePEM(t, tls.Certificate{Certificate: [][]byte{serverTLS.Certificates[0].Certificate[1]}}),
|
||||
@@ -625,6 +654,33 @@ func TestNativeApolloSessionRelaysOnlyAuthenticatedEncodedUDPMedia(t *testing.T)
|
||||
t.Fatal("encrypted FEC audio was not recovered")
|
||||
}
|
||||
}
|
||||
for block := 0; block < apolloAudioMaximumBlocks+1; block++ {
|
||||
sequence := uint16(100 + block*apolloAudioDataShards)
|
||||
packet := sourceShapedEncryptedAudioPacketWithHeaders(t, key, keyID, sequence, uint32(sequence)*5, 1, []byte{byte(block)})
|
||||
if _, err := audioServer.WriteToUDP(packet, audioClient.LocalAddr().(*net.UDPAddr)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
for index, want := range [][]byte{{0xa0}, {0xa1}, {0xa2}, {0xa3}} {
|
||||
sequence := uint16(124 + index)
|
||||
packet := sourceShapedEncryptedAudioPacketWithHeaders(t, key, keyID, sequence, uint32(sequence)*5, 1, want)
|
||||
if _, err := audioServer.WriteToUDP(packet, audioClient.LocalAddr().(*net.UDPAddr)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
for _, want := range [][]byte{{0xa0}, {0xa1}, {0xa2}, {0xa3}} {
|
||||
select {
|
||||
case payload := <-session.Audio():
|
||||
if string(payload) != string(want) {
|
||||
t.Fatalf("post-loss audio relay = %x, want %x", payload, want)
|
||||
}
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("sustained loss permanently stalled newer audio")
|
||||
}
|
||||
}
|
||||
if drops := session.Telemetry().MediaDrops; drops < 2 {
|
||||
t.Fatalf("stale FEC eviction drops = %d, want at least 2", drops)
|
||||
}
|
||||
terminateCtx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||
defer cancel()
|
||||
if err := session.Terminate(terminateCtx); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user