fix(gateway): close Phase 3C audit gaps
This commit is contained in:
+37
-21
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user