fix(gateway): close Phase 3C audit gaps

This commit is contained in:
sechmachine
2026-07-30 01:46:00 +07:00
parent 040ca73ce9
commit d3852d15f3
23 changed files with 1619 additions and 219 deletions
+37 -21
View File
@@ -22,21 +22,46 @@ type apolloAudioAssembler struct {
blocks map[uint16]*apolloAudioFECBlock
}
func (a *apolloAudioAssembler) Add(codec *apolloMediaCodec, shard apolloAudioShard) ([][]byte, error) {
func (a *apolloAudioAssembler) Add(codec *apolloMediaCodec, shard apolloAudioShard) ([][]byte, bool, error) {
if codec == nil || len(shard.payload) == 0 || len(shard.payload) > 1408 || len(shard.payload)%16 != 0 {
return nil, errApolloMedia
return nil, false, errApolloMedia
}
if a.blocks == nil {
a.blocks = make(map[uint16]*apolloAudioFECBlock)
}
base := shard.base
if base&3 != 0 {
return nil, errApolloMedia
return nil, false, errApolloMedia
}
index := 0
if shard.parity {
if shard.parityIndex >= apolloAudioParityShards {
return nil, false, errApolloMedia
}
index = apolloAudioDataShards + int(shard.parityIndex)
} else {
index = int(uint16(shard.sequence - base))
if index >= apolloAudioDataShards {
return nil, false, errApolloMedia
}
}
evicted := false
block := a.blocks[base]
if block == nil {
if len(a.blocks) >= apolloAudioMaximumBlocks {
return nil, errApolloMedia
var oldest uint16
var maximumAge uint16
for candidate := range a.blocks {
age := base - candidate
if age > maximumAge && age < 1<<15 {
oldest, maximumAge = candidate, age
}
}
if maximumAge == 0 {
return nil, false, errApolloMedia
}
delete(a.blocks, oldest)
evicted = true
}
block = &apolloAudioFECBlock{base: base}
a.blocks[base] = block
@@ -44,49 +69,40 @@ func (a *apolloAudioAssembler) Add(codec *apolloMediaCodec, shard apolloAudioSha
if block.size == 0 {
block.size = len(shard.payload)
} else if block.size != len(shard.payload) {
return nil, errApolloMedia
return nil, evicted, errApolloMedia
}
index := 0
if shard.parity {
if shard.parityIndex >= apolloAudioParityShards {
return nil, errApolloMedia
}
index = apolloAudioDataShards + int(shard.parityIndex)
if block.haveFEC && (block.timestamp != shard.timestamp || block.ssrc != shard.ssrc) {
return nil, errApolloMedia
return nil, evicted, errApolloMedia
}
block.timestamp, block.ssrc, block.haveFEC = shard.timestamp, shard.ssrc, true
} else {
index = int(uint16(shard.sequence - base))
if index >= apolloAudioDataShards {
return nil, errApolloMedia
}
if block.haveFEC && (shard.timestamp != block.timestamp+uint32(index*5) || shard.ssrc != block.ssrc) {
return nil, errApolloMedia
return nil, evicted, errApolloMedia
}
}
if block.received[index] {
return nil, errApolloMedia
return nil, evicted, errApolloMedia
}
block.shards[index] = append([]byte(nil), shard.payload...)
block.received[index] = true
block.count++
if block.count < apolloAudioDataShards {
return nil, nil
return nil, evicted, nil
}
if err := reconstructApolloAudioBlock(block); err != nil {
return nil, err
return nil, evicted, err
}
output := make([][]byte, apolloAudioDataShards)
for index := range output {
payload, err := codec.openApolloAudioCipher(base+uint16(index), block.shards[index])
if err != nil {
return nil, err
return nil, evicted, err
}
output[index] = payload
}
delete(a.blocks, base)
return output, nil
return output, evicted, nil
}
func reconstructApolloAudioBlock(block *apolloAudioFECBlock) error {