fix(gateway): close Phase 3C audit gaps
This commit is contained in:
+44
-9
@@ -19,13 +19,14 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
defaultHelloLimit = 16 * 1024
|
||||
defaultControlLimit = 128 * 1024
|
||||
clientControlBacklog = 64
|
||||
applicationError = quic.ApplicationErrorCode(0x100)
|
||||
controlFlowID = "control.ack.v1"
|
||||
inputFlowID = "input.sequenced.v1"
|
||||
clipboardFlowID = "clipboard.text.v1"
|
||||
defaultHelloLimit = 16 * 1024
|
||||
defaultControlLimit = 128 * 1024
|
||||
clientControlBacklog = 64
|
||||
applicationError = quic.ApplicationErrorCode(0x100)
|
||||
terminalFeedbackDrain = 100 * time.Millisecond
|
||||
controlFlowID = "control.ack.v1"
|
||||
inputFlowID = "input.sequenced.v1"
|
||||
clipboardFlowID = "clipboard.text.v1"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -324,12 +325,26 @@ func (s *Server) validateProviderWork(work protocol.ProviderSessionWork, authori
|
||||
}
|
||||
if work.SessionID != authority.SessionID || work.GatewayID != authority.GatewayID ||
|
||||
work.ReconnectSequence != authority.ReconnectSequence || work.ExpiresAt != authority.ExpiresAt ||
|
||||
work.ProviderProfile != authority.ProviderProfile {
|
||||
work.ProviderProfile != authority.ProviderProfile || !apolloPolicyMatchesCapabilities(work.StreamPolicy, authority.Capabilities) {
|
||||
return ErrAdmissionRejected
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func apolloPolicyMatchesCapabilities(policy protocol.ProviderStreamPolicy, capabilities protocol.CapabilityProfile) bool {
|
||||
if validateApolloStreamPolicy(policy) != nil || capabilities.Audio != "encoded" {
|
||||
return false
|
||||
}
|
||||
switch policy.Codec {
|
||||
case "H264":
|
||||
return capabilities.ClientDecode == "h264-opus" || capabilities.ClientDecode == defaultClientDecode
|
||||
case "HEVC":
|
||||
return capabilities.ClientDecode == "hevc-opus" || capabilities.ClientDecode == defaultClientDecode
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) addSession(session *gatewaySession) {
|
||||
s.mu.Lock()
|
||||
s.sessions[session] = struct{}{}
|
||||
@@ -358,6 +373,7 @@ type gatewaySession struct {
|
||||
pressed map[string]struct{}
|
||||
sequence atomic.Uint32
|
||||
mediaDrops uint64
|
||||
endReason error
|
||||
result chan error
|
||||
}
|
||||
|
||||
@@ -389,7 +405,7 @@ func (s *gatewaySession) run() {
|
||||
case <-timer.C:
|
||||
s.server.metrics.InputRejected.Add(1)
|
||||
case <-s.ctx.Done():
|
||||
case <-s.result:
|
||||
case s.endReason = <-s.result:
|
||||
}
|
||||
s.cancel()
|
||||
}
|
||||
@@ -404,6 +420,10 @@ func (s *gatewaySession) providerEventLoop() {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if event.Kind == ProviderEventDisconnected {
|
||||
s.result <- ErrProviderDisconnected
|
||||
return
|
||||
}
|
||||
payload, err := EncodeProviderEvent(event)
|
||||
if err == nil {
|
||||
err = s.sendControl(s.sequence.Add(1), payload)
|
||||
@@ -412,6 +432,17 @@ func (s *gatewaySession) providerEventLoop() {
|
||||
s.result <- err
|
||||
return
|
||||
}
|
||||
if event.Kind == ProviderEventTerminated {
|
||||
timer := time.NewTimer(terminalFeedbackDrain)
|
||||
select {
|
||||
case <-s.ctx.Done():
|
||||
timer.Stop()
|
||||
return
|
||||
case <-timer.C:
|
||||
}
|
||||
s.result <- ErrProviderTerminated
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -771,6 +802,10 @@ func (s *gatewaySession) cleanup() {
|
||||
_ = s.connection.CloseWithError(applicationError, "session closed")
|
||||
return
|
||||
}
|
||||
if errors.Is(s.endReason, ErrProviderDisconnected) {
|
||||
state.State = ProviderStateDisconnected
|
||||
state.CleanupPending = false
|
||||
}
|
||||
if err := s.server.config.Admission.Release(cleanupCtx, s.authority); err != nil {
|
||||
s.server.metrics.ProviderErrors.Add(1)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user